openldap-2.4.42+dfsg/0000755000175000017500000000000012563404150013030 5ustar ryanryanopenldap-2.4.42+dfsg/README0000644000175000017500000000664612563404150013724 0ustar ryanryanOpenLDAP 2.4 README For a description of what this distribution contains, see the ANNOUNCEMENT file in this directory. For a description of changes from previous releases, see the CHANGES file in this directory. This is 2.4 release, it includes significant changes from prior releases. REQUIRED SOFTWARE Building OpenLDAP Software requires a number of software packages to be preinstalled. Additional information regarding prerequisite software can be found in the OpenLDAP Administrator's Guide. Base system (libraries and tools): Standard C compiler (required) Cyrus SASL 2.1.21+ (recommended) OpenSSL 0.9.7+ (recommended) Reentrant POSIX REGEX software (required) SLAPD: BDB and HDB backends require Oracle Berkeley DB 4.4 - 4.8, or 5.0 - 5.1. It is highly recommended to apply the patches from Oracle for a given release. CLIENTS/CONTRIB ware: Depends on package. See per package README. MAKING AND INSTALLING THE DISTRIBUTION Please see the INSTALL file for basic instructions. More detailed instructions can be found in the OpenLDAP Admnistrator's Guide (see DOCUMENTATION section). DOCUMENTATION The OpenLDAP Administrator's Guide is available in the guide.html file in the doc/guide/admin directory. The guide and a number of other documents are available at . The distribution also includes manual pages for most programs and library APIs. See ldap(3) for details. The OpenLDAP website is available and contains the latest LDAP news, releases announcements, pointers to other LDAP resources, etc.. It is located at . The OpenLDAP Software FAQ is available at . SUPPORT / FEEDBACK / PROBLEM REPORTS / DISCUSSIONS OpenLDAP Software is user supported. If you have problems, please review the OpenLDAP FAQ and archives of the OpenLDAP-software and OpenLDAP-bugs mailing lists . If you cannot find the answer, please enquire on the OpenLDAP-software list. Issues, such as bug reports, should be reported using our Issue Tracking System . Do not use this system for software enquiries. Please direct these to an appropriate mailing list. CONTRIBUTING See for information regarding how to contribute code or documentation to the OpenLDAP Project for inclusion in OpenLDAP Software. While you are encouraged to coordinate and discuss the development activities on the mailing list prior to submission, it is noted that contributions must be submitted using the Issue Tracking System to be considered. --- $OpenLDAP$ This work is part of OpenLDAP Software . Copyright 1998-2015 The OpenLDAP Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted only as authorized by the OpenLDAP Public License. A copy of this license is available in the file LICENSE in the top-level directory of the distribution or, alternatively, at . OpenLDAP is a registered trademark of the OpenLDAP Foundation. openldap-2.4.42+dfsg/Makefile.in0000644000175000017500000000171712563404150015103 0ustar ryanryan# Master Makefile for OpenLDAP # $OpenLDAP$ ## This work is part of OpenLDAP Software . ## ## Copyright 1998-2015 The OpenLDAP Foundation. ## All rights reserved. ## ## Redistribution and use in source and binary forms, with or without ## modification, are permitted only as authorized by the OpenLDAP ## Public License. ## ## A copy of this license is available in the file LICENSE in the ## top-level directory of the distribution or, alternatively, at ## . SUBDIRS= include libraries clients servers tests doc CLEANDIRS= INSTALLDIRS= makefiles: FORCE ./config.status # force a make all before make install # only done at the top-level install-common: all FORCE clean-local: FORCE $(RM) config.cache config.log configure.lineno $(RM) -r autom4te.cache veryclean-local: FORCE $(RM) config.status libtool stamp-h stamp-h.in distclean: veryclean FORCE check: test test: FORCE cd tests; $(MAKE) test openldap-2.4.42+dfsg/LICENSE0000644000175000017500000000424612563404150014043 0ustar ryanryanThe OpenLDAP Public License Version 2.8, 17 August 2003 Redistribution and use of this software and associated documentation ("Software"), with or without modification, are permitted provided that the following conditions are met: 1. Redistributions in source form must retain copyright statements and notices, 2. Redistributions in binary form must reproduce applicable copyright statements and notices, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution, and 3. Redistributions must contain a verbatim copy of this document. The OpenLDAP Foundation may revise this license from time to time. Each revision is distinguished by a version number. You may use this Software under terms of this license revision or under the terms of any subsequent revision of the license. THIS SOFTWARE IS PROVIDED BY THE OPENLDAP FOUNDATION AND ITS CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED 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 OPENLDAP FOUNDATION, ITS CONTRIBUTORS, OR THE AUTHOR(S) OR OWNER(S) OF THE SOFTWARE 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. The names of the authors and copyright holders must not be used in advertising or otherwise to promote the sale, use or other dealing in this Software without specific, written prior permission. Title to copyright in this Software shall at all times remain with copyright holders. OpenLDAP is a registered trademark of the OpenLDAP Foundation. Copyright 1999-2003 The OpenLDAP Foundation, Redwood City, California, USA. All Rights Reserved. Permission to copy and distribute verbatim copies of this document is granted. openldap-2.4.42+dfsg/COPYRIGHT0000644000175000017500000000445112563404150014327 0ustar ryanryanCopyright 1998-2015 The OpenLDAP Foundation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted only as authorized by the OpenLDAP Public License. A copy of this license is available in the file LICENSE in the top-level directory of the distribution or, alternatively, at . OpenLDAP is a registered trademark of the OpenLDAP Foundation. Individual files and/or contributed packages may be copyright by other parties and/or subject to additional restrictions. This work is derived from the University of Michigan LDAP v3.3 distribution. Information concerning this software is available at . This work also contains materials derived from public sources. Additional information about OpenLDAP can be obtained at . --- Portions Copyright 1998-2012 Kurt D. Zeilenga. Portions Copyright 1998-2006 Net Boolean Incorporated. Portions Copyright 2001-2006 IBM Corporation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted only as authorized by the OpenLDAP Public License. --- Portions Copyright 1999-2008 Howard Y.H. Chu. Portions Copyright 1999-2008 Symas Corporation. Portions Copyright 1998-2003 Hallvard B. Furuseth. Portions Copyright 2007-2011 Gavin Henry. Portions Copyright 2007-2011 Suretec Systems Ltd. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that this notice is preserved. The names of the copyright holders may not be used to endorse or promote products derived from this software without their specific prior written permission. This software is provided ``as is'' without express or implied warranty. --- Portions Copyright (c) 1992-1996 Regents of the University of Michigan. All rights reserved. Redistribution and use in source and binary forms are permitted provided that this notice is preserved and that due credit is given to the University of Michigan at Ann Arbor. The name of the University may not be used to endorse or promote products derived from this software without specific prior written permission. This software is provided ``as is'' without express or implied warranty. openldap-2.4.42+dfsg/libraries/0000755000175000017500000000000012563404150015004 5ustar ryanryanopenldap-2.4.42+dfsg/libraries/Makefile.in0000644000175000017500000000114312563404150017050 0ustar ryanryan# Libraries Makefile for OpenLDAP # $OpenLDAP$ ## This work is part of OpenLDAP Software . ## ## Copyright 1998-2015 The OpenLDAP Foundation. ## All rights reserved. ## ## Redistribution and use in source and binary forms, with or without ## modification, are permitted only as authorized by the OpenLDAP ## Public License. ## ## A copy of this license is available in the file LICENSE in the ## top-level directory of the distribution or, alternatively, at ## . SUBDIRS= \ liblutil \ liblber \ liblunicode \ libldap libldap_r \ librewrite openldap-2.4.42+dfsg/libraries/liblmdb/0000755000175000017500000000000012563404150016411 5ustar ryanryanopenldap-2.4.42+dfsg/libraries/liblmdb/mdb_stat.c0000644000175000017500000001440112563404150020352 0ustar ryanryan/* mdb_stat.c - memory-mapped database status tool */ /* * Copyright 2011-2015 Howard Chu, Symas Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #include #include #include #include #include "lmdb.h" #ifdef _WIN32 #define Z "I" #else #define Z "z" #endif static void prstat(MDB_stat *ms) { #if 0 printf(" Page size: %u\n", ms->ms_psize); #endif printf(" Tree depth: %u\n", ms->ms_depth); printf(" Branch pages: %"Z"u\n", ms->ms_branch_pages); printf(" Leaf pages: %"Z"u\n", ms->ms_leaf_pages); printf(" Overflow pages: %"Z"u\n", ms->ms_overflow_pages); printf(" Entries: %"Z"u\n", ms->ms_entries); } static void usage(char *prog) { fprintf(stderr, "usage: %s dbpath [-V] [-n] [-e] [-r[r]] [-f[f[f]]] [-a|-s subdb]\n", prog); exit(EXIT_FAILURE); } int main(int argc, char *argv[]) { int i, rc; MDB_env *env; MDB_txn *txn; MDB_dbi dbi; MDB_stat mst; MDB_envinfo mei; char *prog = argv[0]; char *envname; char *subname = NULL; int alldbs = 0, envinfo = 0, envflags = 0, freinfo = 0, rdrinfo = 0; if (argc < 2) { usage(prog); } /* -a: print stat of main DB and all subDBs * -s: print stat of only the named subDB * -e: print env info * -f: print freelist info * -r: print reader info * -n: use NOSUBDIR flag on env_open * -V: print version and exit * (default) print stat of only the main DB */ while ((i = getopt(argc, argv, "Vaefnrs:")) != EOF) { switch(i) { case 'V': printf("%s\n", MDB_VERSION_STRING); exit(0); break; case 'a': if (subname) usage(prog); alldbs++; break; case 'e': envinfo++; break; case 'f': freinfo++; break; case 'n': envflags |= MDB_NOSUBDIR; break; case 'r': rdrinfo++; break; case 's': if (alldbs) usage(prog); subname = optarg; break; default: usage(prog); } } if (optind != argc - 1) usage(prog); envname = argv[optind]; rc = mdb_env_create(&env); if (rc) { fprintf(stderr, "mdb_env_create failed, error %d %s\n", rc, mdb_strerror(rc)); return EXIT_FAILURE; } if (alldbs || subname) { mdb_env_set_maxdbs(env, 4); } rc = mdb_env_open(env, envname, envflags | MDB_RDONLY, 0664); if (rc) { fprintf(stderr, "mdb_env_open failed, error %d %s\n", rc, mdb_strerror(rc)); goto env_close; } if (envinfo) { (void)mdb_env_stat(env, &mst); (void)mdb_env_info(env, &mei); printf("Environment Info\n"); printf(" Map address: %p\n", mei.me_mapaddr); printf(" Map size: %"Z"u\n", mei.me_mapsize); printf(" Page size: %u\n", mst.ms_psize); printf(" Max pages: %"Z"u\n", mei.me_mapsize / mst.ms_psize); printf(" Number of pages used: %"Z"u\n", mei.me_last_pgno+1); printf(" Last transaction ID: %"Z"u\n", mei.me_last_txnid); printf(" Max readers: %u\n", mei.me_maxreaders); printf(" Number of readers used: %u\n", mei.me_numreaders); } if (rdrinfo) { printf("Reader Table Status\n"); rc = mdb_reader_list(env, (MDB_msg_func *)fputs, stdout); if (rdrinfo > 1) { int dead; mdb_reader_check(env, &dead); printf(" %d stale readers cleared.\n", dead); rc = mdb_reader_list(env, (MDB_msg_func *)fputs, stdout); } if (!(subname || alldbs || freinfo)) goto env_close; } rc = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn); if (rc) { fprintf(stderr, "mdb_txn_begin failed, error %d %s\n", rc, mdb_strerror(rc)); goto env_close; } if (freinfo) { MDB_cursor *cursor; MDB_val key, data; size_t pages = 0, *iptr; printf("Freelist Status\n"); dbi = 0; rc = mdb_cursor_open(txn, dbi, &cursor); if (rc) { fprintf(stderr, "mdb_cursor_open failed, error %d %s\n", rc, mdb_strerror(rc)); goto txn_abort; } rc = mdb_stat(txn, dbi, &mst); if (rc) { fprintf(stderr, "mdb_stat failed, error %d %s\n", rc, mdb_strerror(rc)); goto txn_abort; } prstat(&mst); while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) { iptr = data.mv_data; pages += *iptr; if (freinfo > 1) { char *bad = ""; size_t pg, prev; ssize_t i, j, span = 0; j = *iptr++; for (i = j, prev = 1; --i >= 0; ) { pg = iptr[i]; if (pg <= prev) bad = " [bad sequence]"; prev = pg; pg += span; for (; i >= span && iptr[i-span] == pg; span++, pg++) ; } printf(" Transaction %"Z"u, %"Z"d pages, maxspan %"Z"d%s\n", *(size_t *)key.mv_data, j, span, bad); if (freinfo > 2) { for (--j; j >= 0; ) { pg = iptr[j]; for (span=1; --j >= 0 && iptr[j] == pg+span; span++) ; printf(span>1 ? " %9"Z"u[%"Z"d]\n" : " %9"Z"u\n", pg, span); } } } } mdb_cursor_close(cursor); printf(" Free pages: %"Z"u\n", pages); } rc = mdb_open(txn, subname, 0, &dbi); if (rc) { fprintf(stderr, "mdb_open failed, error %d %s\n", rc, mdb_strerror(rc)); goto txn_abort; } rc = mdb_stat(txn, dbi, &mst); if (rc) { fprintf(stderr, "mdb_stat failed, error %d %s\n", rc, mdb_strerror(rc)); goto txn_abort; } printf("Status of %s\n", subname ? subname : "Main DB"); prstat(&mst); if (alldbs) { MDB_cursor *cursor; MDB_val key; rc = mdb_cursor_open(txn, dbi, &cursor); if (rc) { fprintf(stderr, "mdb_cursor_open failed, error %d %s\n", rc, mdb_strerror(rc)); goto txn_abort; } while ((rc = mdb_cursor_get(cursor, &key, NULL, MDB_NEXT_NODUP)) == 0) { char *str; MDB_dbi db2; if (memchr(key.mv_data, '\0', key.mv_size)) continue; str = malloc(key.mv_size+1); memcpy(str, key.mv_data, key.mv_size); str[key.mv_size] = '\0'; rc = mdb_open(txn, str, 0, &db2); if (rc == MDB_SUCCESS) printf("Status of %s\n", str); free(str); if (rc) continue; rc = mdb_stat(txn, db2, &mst); if (rc) { fprintf(stderr, "mdb_stat failed, error %d %s\n", rc, mdb_strerror(rc)); goto txn_abort; } prstat(&mst); mdb_close(env, db2); } mdb_cursor_close(cursor); } if (rc == MDB_NOTFOUND) rc = MDB_SUCCESS; mdb_close(env, dbi); txn_abort: mdb_txn_abort(txn); env_close: mdb_env_close(env); return rc ? EXIT_FAILURE : EXIT_SUCCESS; } openldap-2.4.42+dfsg/libraries/liblmdb/mdb_dump.10000644000175000017500000000422512563404150020265 0ustar ryanryan.TH MDB_DUMP 1 "2014/06/20" "LMDB 0.9.14" .\" Copyright 2014-2015 Howard Chu, Symas Corp. All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME mdb_dump \- LMDB environment export tool .SH SYNOPSIS .B mdb_dump .BR \ envpath [\c .BR \-V ] [\c .BI \-f \ file\fR] [\c .BR \-l ] [\c .BR \-n ] [\c .BR \-p ] [\c .BR \-a \ | .BI \-s \ subdb\fR] .SH DESCRIPTION The .B mdb_dump utility reads a database and writes its contents to the standard output using a portable flat-text format understood by the .BR mdb_load (1) utility. .SH OPTIONS .TP .BR \-V Write the library version number to the standard output, and exit. .TP .BR \-f \ file Write to the specified file instead of to the standard output. .TP .BR \-l List the databases stored in the environment. Just the names will be listed, no data will be output. .TP .BR \-n Dump an LMDB database which does not use subdirectories. .TP .BR \-p If characters in either the key or data items are printing characters (as defined by isprint(3)), output them directly. This option permits users to use standard text editors and tools to modify the contents of databases. Note: different systems may have different notions about what characters are considered printing characters, and databases dumped in this manner may be less portable to external systems. .TP .BR \-a Dump all of the subdatabases in the environment. .TP .BR \-s \ subdb Dump a specific subdatabase. If no database is specified, only the main database is dumped. .SH DIAGNOSTICS Exit status is zero if no errors occur. Errors result in a non-zero exit status and a diagnostic message being written to standard error. Dumping and reloading databases that use user-defined comparison functions will result in new databases that use the default comparison functions. \fBIn this case it is quite likely that the reloaded database will be damaged beyond repair permitting neither record storage nor retrieval.\fP The only available workaround is to modify the source for the .BR mdb_load (1) utility to load the database using the correct comparison functions. .SH "SEE ALSO" .BR mdb_load (1) .SH AUTHOR Howard Chu of Symas Corporation openldap-2.4.42+dfsg/libraries/liblmdb/mtest2.c0000644000175000017500000000663612563404150020006 0ustar ryanryan/* mtest2.c - memory-mapped database tester/toy */ /* * Copyright 2011-2015 Howard Chu, Symas Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Just like mtest.c, but using a subDB instead of the main DB */ #include #include #include #include "lmdb.h" #define E(expr) CHECK((rc = (expr)) == MDB_SUCCESS, #expr) #define RES(err, expr) ((rc = expr) == (err) || (CHECK(!rc, #expr), 0)) #define CHECK(test, msg) ((test) ? (void)0 : ((void)fprintf(stderr, \ "%s:%d: %s: %s\n", __FILE__, __LINE__, msg, mdb_strerror(rc)), abort())) int main(int argc,char * argv[]) { int i = 0, j = 0, rc; MDB_env *env; MDB_dbi dbi; MDB_val key, data; MDB_txn *txn; MDB_stat mst; MDB_cursor *cursor; int count; int *values; char sval[32] = ""; srand(time(NULL)); count = (rand()%384) + 64; values = (int *)malloc(count*sizeof(int)); for(i = 0;i -1; i-= (rand()%5)) { j++; txn=NULL; E(mdb_txn_begin(env, NULL, 0, &txn)); sprintf(sval, "%03x ", values[i]); if (RES(MDB_NOTFOUND, mdb_del(txn, dbi, &key, NULL))) { j--; mdb_txn_abort(txn); } else { E(mdb_txn_commit(txn)); } } free(values); printf("Deleted %d values\n", j); E(mdb_env_stat(env, &mst)); E(mdb_txn_begin(env, NULL, MDB_RDONLY, &txn)); E(mdb_cursor_open(txn, dbi, &cursor)); printf("Cursor next\n"); while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) { printf("key: %.*s, data: %.*s\n", (int) key.mv_size, (char *) key.mv_data, (int) data.mv_size, (char *) data.mv_data); } CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get"); printf("Cursor prev\n"); while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_PREV)) == 0) { printf("key: %.*s, data: %.*s\n", (int) key.mv_size, (char *) key.mv_data, (int) data.mv_size, (char *) data.mv_data); } CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get"); mdb_cursor_close(cursor); mdb_txn_abort(txn); mdb_dbi_close(env, dbi); mdb_env_close(env); return 0; } openldap-2.4.42+dfsg/libraries/liblmdb/mtest4.c0000644000175000017500000001126712563404150020004 0ustar ryanryan/* mtest4.c - memory-mapped database tester/toy */ /* * Copyright 2011-2015 Howard Chu, Symas Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Tests for sorted duplicate DBs with fixed-size keys */ #include #include #include #include #include "lmdb.h" #define E(expr) CHECK((rc = (expr)) == MDB_SUCCESS, #expr) #define RES(err, expr) ((rc = expr) == (err) || (CHECK(!rc, #expr), 0)) #define CHECK(test, msg) ((test) ? (void)0 : ((void)fprintf(stderr, \ "%s:%d: %s: %s\n", __FILE__, __LINE__, msg, mdb_strerror(rc)), abort())) int main(int argc,char * argv[]) { int i = 0, j = 0, rc; MDB_env *env; MDB_dbi dbi; MDB_val key, data; MDB_txn *txn; MDB_stat mst; MDB_cursor *cursor; int count; int *values; char sval[8]; char kval[sizeof(int)]; memset(sval, 0, sizeof(sval)); count = 510; values = (int *)malloc(count*sizeof(int)); for(i = 0;i -1; i-= (rand()%3)) { j++; txn=NULL; E(mdb_txn_begin(env, NULL, 0, &txn)); sprintf(sval, "%07x", values[i]); key.mv_size = sizeof(int); key.mv_data = kval; data.mv_size = sizeof(sval); data.mv_data = sval; if (RES(MDB_NOTFOUND, mdb_del(txn, dbi, &key, &data))) { j--; mdb_txn_abort(txn); } else { E(mdb_txn_commit(txn)); } } free(values); printf("Deleted %d values\n", j); E(mdb_env_stat(env, &mst)); E(mdb_txn_begin(env, NULL, MDB_RDONLY, &txn)); E(mdb_cursor_open(txn, dbi, &cursor)); printf("Cursor next\n"); while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) { printf("key: %.*s, data: %.*s\n", (int) key.mv_size, (char *) key.mv_data, (int) data.mv_size, (char *) data.mv_data); } CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get"); printf("Cursor prev\n"); while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_PREV)) == 0) { printf("key: %.*s, data: %.*s\n", (int) key.mv_size, (char *) key.mv_data, (int) data.mv_size, (char *) data.mv_data); } CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get"); mdb_cursor_close(cursor); mdb_txn_abort(txn); mdb_dbi_close(env, dbi); mdb_env_close(env); return 0; } openldap-2.4.42+dfsg/libraries/liblmdb/LICENSE0000644000175000017500000000424612563404150017424 0ustar ryanryanThe OpenLDAP Public License Version 2.8, 17 August 2003 Redistribution and use of this software and associated documentation ("Software"), with or without modification, are permitted provided that the following conditions are met: 1. Redistributions in source form must retain copyright statements and notices, 2. Redistributions in binary form must reproduce applicable copyright statements and notices, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution, and 3. Redistributions must contain a verbatim copy of this document. The OpenLDAP Foundation may revise this license from time to time. Each revision is distinguished by a version number. You may use this Software under terms of this license revision or under the terms of any subsequent revision of the license. THIS SOFTWARE IS PROVIDED BY THE OPENLDAP FOUNDATION AND ITS CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED 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 OPENLDAP FOUNDATION, ITS CONTRIBUTORS, OR THE AUTHOR(S) OR OWNER(S) OF THE SOFTWARE 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. The names of the authors and copyright holders must not be used in advertising or otherwise to promote the sale, use or other dealing in this Software without specific, written prior permission. Title to copyright in this Software shall at all times remain with copyright holders. OpenLDAP is a registered trademark of the OpenLDAP Foundation. Copyright 1999-2003 The OpenLDAP Foundation, Redwood City, California, USA. All Rights Reserved. Permission to copy and distribute verbatim copies of this document is granted. openldap-2.4.42+dfsg/libraries/liblmdb/COPYRIGHT0000644000175000017500000000131312563404150017702 0ustar ryanryanCopyright 2011-2015 Howard Chu, Symas Corp. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted only as authorized by the OpenLDAP Public License. A copy of this license is available in the file LICENSE in the top-level directory of the distribution or, alternatively, at . OpenLDAP is a registered trademark of the OpenLDAP Foundation. Individual files and/or contributed packages may be copyright by other parties and/or subject to additional restrictions. This work also contains materials derived from public sources. Additional information about OpenLDAP can be obtained at . openldap-2.4.42+dfsg/libraries/liblmdb/midl.c0000644000175000017500000001460412563404150017507 0ustar ryanryan/** @file midl.c * @brief ldap bdb back-end ID List functions */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 2000-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #include #include #include #include #include #include "midl.h" /** @defgroup internal LMDB Internals * @{ */ /** @defgroup idls ID List Management * @{ */ #define CMP(x,y) ( (x) < (y) ? -1 : (x) > (y) ) unsigned mdb_midl_search( MDB_IDL ids, MDB_ID id ) { /* * binary search of id in ids * if found, returns position of id * if not found, returns first position greater than id */ unsigned base = 0; unsigned cursor = 1; int val = 0; unsigned n = ids[0]; while( 0 < n ) { unsigned pivot = n >> 1; cursor = base + pivot + 1; val = CMP( ids[cursor], id ); if( val < 0 ) { n = pivot; } else if ( val > 0 ) { base = cursor; n -= pivot + 1; } else { return cursor; } } if( val > 0 ) { ++cursor; } return cursor; } #if 0 /* superseded by append/sort */ int mdb_midl_insert( MDB_IDL ids, MDB_ID id ) { unsigned x, i; x = mdb_midl_search( ids, id ); assert( x > 0 ); if( x < 1 ) { /* internal error */ return -2; } if ( x <= ids[0] && ids[x] == id ) { /* duplicate */ assert(0); return -1; } if ( ++ids[0] >= MDB_IDL_DB_MAX ) { /* no room */ --ids[0]; return -2; } else { /* insert id */ for (i=ids[0]; i>x; i--) ids[i] = ids[i-1]; ids[x] = id; } return 0; } #endif MDB_IDL mdb_midl_alloc(int num) { MDB_IDL ids = malloc((num+2) * sizeof(MDB_ID)); if (ids) { *ids++ = num; *ids = 0; } return ids; } void mdb_midl_free(MDB_IDL ids) { if (ids) free(ids-1); } void mdb_midl_shrink( MDB_IDL *idp ) { MDB_IDL ids = *idp; if (*(--ids) > MDB_IDL_UM_MAX && (ids = realloc(ids, (MDB_IDL_UM_MAX+1) * sizeof(MDB_ID)))) { *ids++ = MDB_IDL_UM_MAX; *idp = ids; } } static int mdb_midl_grow( MDB_IDL *idp, int num ) { MDB_IDL idn = *idp-1; /* grow it */ idn = realloc(idn, (*idn + num + 2) * sizeof(MDB_ID)); if (!idn) return ENOMEM; *idn++ += num; *idp = idn; return 0; } int mdb_midl_need( MDB_IDL *idp, unsigned num ) { MDB_IDL ids = *idp; num += ids[0]; if (num > ids[-1]) { num = (num + num/4 + (256 + 2)) & -256; if (!(ids = realloc(ids-1, num * sizeof(MDB_ID)))) return ENOMEM; *ids++ = num - 2; *idp = ids; } return 0; } int mdb_midl_append( MDB_IDL *idp, MDB_ID id ) { MDB_IDL ids = *idp; /* Too big? */ if (ids[0] >= ids[-1]) { if (mdb_midl_grow(idp, MDB_IDL_UM_MAX)) return ENOMEM; ids = *idp; } ids[0]++; ids[ids[0]] = id; return 0; } int mdb_midl_append_list( MDB_IDL *idp, MDB_IDL app ) { MDB_IDL ids = *idp; /* Too big? */ if (ids[0] + app[0] >= ids[-1]) { if (mdb_midl_grow(idp, app[0])) return ENOMEM; ids = *idp; } memcpy(&ids[ids[0]+1], &app[1], app[0] * sizeof(MDB_ID)); ids[0] += app[0]; return 0; } int mdb_midl_append_range( MDB_IDL *idp, MDB_ID id, unsigned n ) { MDB_ID *ids = *idp, len = ids[0]; /* Too big? */ if (len + n > ids[-1]) { if (mdb_midl_grow(idp, n | MDB_IDL_UM_MAX)) return ENOMEM; ids = *idp; } ids[0] = len + n; ids += len; while (n) ids[n--] = id++; return 0; } void mdb_midl_xmerge( MDB_IDL idl, MDB_IDL merge ) { MDB_ID old_id, merge_id, i = merge[0], j = idl[0], k = i+j, total = k; idl[0] = (MDB_ID)-1; /* delimiter for idl scan below */ old_id = idl[j]; while (i) { merge_id = merge[i--]; for (; old_id < merge_id; old_id = idl[--j]) idl[k--] = old_id; idl[k--] = merge_id; } idl[0] = total; } /* Quicksort + Insertion sort for small arrays */ #define SMALL 8 #define MIDL_SWAP(a,b) { itmp=(a); (a)=(b); (b)=itmp; } void mdb_midl_sort( MDB_IDL ids ) { /* Max possible depth of int-indexed tree * 2 items/level */ int istack[sizeof(int)*CHAR_BIT * 2]; int i,j,k,l,ir,jstack; MDB_ID a, itmp; ir = (int)ids[0]; l = 1; jstack = 0; for(;;) { if (ir - l < SMALL) { /* Insertion sort */ for (j=l+1;j<=ir;j++) { a = ids[j]; for (i=j-1;i>=1;i--) { if (ids[i] >= a) break; ids[i+1] = ids[i]; } ids[i+1] = a; } if (jstack == 0) break; ir = istack[jstack--]; l = istack[jstack--]; } else { k = (l + ir) >> 1; /* Choose median of left, center, right */ MIDL_SWAP(ids[k], ids[l+1]); if (ids[l] < ids[ir]) { MIDL_SWAP(ids[l], ids[ir]); } if (ids[l+1] < ids[ir]) { MIDL_SWAP(ids[l+1], ids[ir]); } if (ids[l] < ids[l+1]) { MIDL_SWAP(ids[l], ids[l+1]); } i = l+1; j = ir; a = ids[l+1]; for(;;) { do i++; while(ids[i] > a); do j--; while(ids[j] < a); if (j < i) break; MIDL_SWAP(ids[i],ids[j]); } ids[l+1] = ids[j]; ids[j] = a; jstack += 2; if (ir-i+1 >= j-l) { istack[jstack] = ir; istack[jstack-1] = i; ir = j-1; } else { istack[jstack] = j-1; istack[jstack-1] = l; l = i; } } } } unsigned mdb_mid2l_search( MDB_ID2L ids, MDB_ID id ) { /* * binary search of id in ids * if found, returns position of id * if not found, returns first position greater than id */ unsigned base = 0; unsigned cursor = 1; int val = 0; unsigned n = (unsigned)ids[0].mid; while( 0 < n ) { unsigned pivot = n >> 1; cursor = base + pivot + 1; val = CMP( id, ids[cursor].mid ); if( val < 0 ) { n = pivot; } else if ( val > 0 ) { base = cursor; n -= pivot + 1; } else { return cursor; } } if( val > 0 ) { ++cursor; } return cursor; } int mdb_mid2l_insert( MDB_ID2L ids, MDB_ID2 *id ) { unsigned x, i; x = mdb_mid2l_search( ids, id->mid ); if( x < 1 ) { /* internal error */ return -2; } if ( x <= ids[0].mid && ids[x].mid == id->mid ) { /* duplicate */ return -1; } if ( ids[0].mid >= MDB_IDL_UM_MAX ) { /* too big */ return -2; } else { /* insert id */ ids[0].mid++; for (i=(unsigned)ids[0].mid; i>x; i--) ids[i] = ids[i-1]; ids[x] = *id; } return 0; } int mdb_mid2l_append( MDB_ID2L ids, MDB_ID2 *id ) { /* Too big? */ if (ids[0].mid >= MDB_IDL_UM_MAX) { return -2; } ids[0].mid++; ids[ids[0].mid] = *id; return 0; } /** @} */ /** @} */ openldap-2.4.42+dfsg/libraries/liblmdb/sample-bdb.txt0000644000175000017500000000374412563404150021170 0ustar ryanryan/* sample-bdb.txt - BerkeleyDB toy/sample * * Do a line-by-line comparison of this and sample-mdb.txt */ /* * Copyright 2012-2015 Howard Chu, Symas Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #include #include #include int main(int argc,char * argv[]) { int rc; DB_ENV *env; DB *dbi; DBT key, data; DB_TXN *txn; DBC *cursor; char sval[32], kval[32]; /* Note: Most error checking omitted for simplicity */ #define FLAGS (DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_TXN|DB_INIT_MPOOL|DB_CREATE|DB_THREAD) rc = db_env_create(&env, 0); rc = env->open(env, "./testdb", FLAGS, 0664); rc = db_create(&dbi, env, 0); rc = env->txn_begin(env, NULL, &txn, 0); rc = dbi->open(dbi, txn, "test.bdb", NULL, DB_BTREE, DB_CREATE, 0664); memset(&key, 0, sizeof(DBT)); memset(&data, 0, sizeof(DBT)); key.size = sizeof(int); key.data = sval; data.size = sizeof(sval); data.data = sval; sprintf(sval, "%03x %d foo bar", 32, 3141592); rc = dbi->put(dbi, txn, &key, &data, 0); rc = txn->commit(txn, 0); if (rc) { fprintf(stderr, "txn->commit: (%d) %s\n", rc, db_strerror(rc)); goto leave; } rc = env->txn_begin(env, NULL, &txn, 0); rc = dbi->cursor(dbi, txn, &cursor, 0); key.flags = DB_DBT_USERMEM; key.data = kval; key.ulen = sizeof(kval); data.flags = DB_DBT_USERMEM; data.data = sval; data.ulen = sizeof(sval); while ((rc = cursor->c_get(cursor, &key, &data, DB_NEXT)) == 0) { printf("key: %p %.*s, data: %p %.*s\n", key.data, (int) key.size, (char *) key.data, data.data, (int) data.size, (char *) data.data); } rc = cursor->c_close(cursor); rc = txn->abort(txn); leave: rc = dbi->close(dbi, 0); rc = env->close(env, 0); return rc; } openldap-2.4.42+dfsg/libraries/liblmdb/mdb_load.c0000644000175000017500000002424212563404150020322 0ustar ryanryan/* mdb_load.c - memory-mapped database load tool */ /* * Copyright 2011-2015 Howard Chu, Symas Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #include #include #include #include #include #include #include "lmdb.h" #define PRINT 1 #define NOHDR 2 static int mode; static char *subname = NULL; static size_t lineno; static int version; static int flags; static char *prog; static int Eof; static MDB_envinfo info; static MDB_val kbuf, dbuf; #ifdef _WIN32 #define Z "I" #else #define Z "z" #endif #define STRLENOF(s) (sizeof(s)-1) typedef struct flagbit { int bit; char *name; int len; } flagbit; #define S(s) s, STRLENOF(s) flagbit dbflags[] = { { MDB_REVERSEKEY, S("reversekey") }, { MDB_DUPSORT, S("dupsort") }, { MDB_INTEGERKEY, S("integerkey") }, { MDB_DUPFIXED, S("dupfixed") }, { MDB_INTEGERDUP, S("integerdup") }, { MDB_REVERSEDUP, S("reversedup") }, { 0, NULL, 0 } }; static void readhdr(void) { char *ptr; while (fgets(dbuf.mv_data, dbuf.mv_size, stdin) != NULL) { lineno++; if (!strncmp(dbuf.mv_data, "VERSION=", STRLENOF("VERSION="))) { version=atoi((char *)dbuf.mv_data+STRLENOF("VERSION=")); if (version > 3) { fprintf(stderr, "%s: line %" Z "d: unsupported VERSION %d\n", prog, lineno, version); exit(EXIT_FAILURE); } } else if (!strncmp(dbuf.mv_data, "HEADER=END", STRLENOF("HEADER=END"))) { break; } else if (!strncmp(dbuf.mv_data, "format=", STRLENOF("format="))) { if (!strncmp((char *)dbuf.mv_data+STRLENOF("FORMAT="), "print", STRLENOF("print"))) mode |= PRINT; else if (strncmp((char *)dbuf.mv_data+STRLENOF("FORMAT="), "bytevalue", STRLENOF("bytevalue"))) { fprintf(stderr, "%s: line %" Z "d: unsupported FORMAT %s\n", prog, lineno, (char *)dbuf.mv_data+STRLENOF("FORMAT=")); exit(EXIT_FAILURE); } } else if (!strncmp(dbuf.mv_data, "database=", STRLENOF("database="))) { ptr = memchr(dbuf.mv_data, '\n', dbuf.mv_size); if (ptr) *ptr = '\0'; if (subname) free(subname); subname = strdup((char *)dbuf.mv_data+STRLENOF("database=")); } else if (!strncmp(dbuf.mv_data, "type=", STRLENOF("type="))) { if (strncmp((char *)dbuf.mv_data+STRLENOF("type="), "btree", STRLENOF("btree"))) { fprintf(stderr, "%s: line %" Z "d: unsupported type %s\n", prog, lineno, (char *)dbuf.mv_data+STRLENOF("type=")); exit(EXIT_FAILURE); } } else if (!strncmp(dbuf.mv_data, "mapaddr=", STRLENOF("mapaddr="))) { int i; ptr = memchr(dbuf.mv_data, '\n', dbuf.mv_size); if (ptr) *ptr = '\0'; i = sscanf((char *)dbuf.mv_data+STRLENOF("mapaddr="), "%p", &info.me_mapaddr); if (i != 1) { fprintf(stderr, "%s: line %" Z "d: invalid mapaddr %s\n", prog, lineno, (char *)dbuf.mv_data+STRLENOF("mapaddr=")); exit(EXIT_FAILURE); } } else if (!strncmp(dbuf.mv_data, "mapsize=", STRLENOF("mapsize="))) { int i; ptr = memchr(dbuf.mv_data, '\n', dbuf.mv_size); if (ptr) *ptr = '\0'; i = sscanf((char *)dbuf.mv_data+STRLENOF("mapsize="), "%" Z "u", &info.me_mapsize); if (i != 1) { fprintf(stderr, "%s: line %" Z "d: invalid mapsize %s\n", prog, lineno, (char *)dbuf.mv_data+STRLENOF("mapsize=")); exit(EXIT_FAILURE); } } else if (!strncmp(dbuf.mv_data, "maxreaders=", STRLENOF("maxreaders="))) { int i; ptr = memchr(dbuf.mv_data, '\n', dbuf.mv_size); if (ptr) *ptr = '\0'; i = sscanf((char *)dbuf.mv_data+STRLENOF("maxreaders="), "%u", &info.me_maxreaders); if (i != 1) { fprintf(stderr, "%s: line %" Z "d: invalid maxreaders %s\n", prog, lineno, (char *)dbuf.mv_data+STRLENOF("maxreaders=")); exit(EXIT_FAILURE); } } else { int i; for (i=0; dbflags[i].bit; i++) { if (!strncmp(dbuf.mv_data, dbflags[i].name, dbflags[i].len) && ((char *)dbuf.mv_data)[dbflags[i].len] == '=') { flags |= dbflags[i].bit; break; } } if (!dbflags[i].bit) { ptr = memchr(dbuf.mv_data, '=', dbuf.mv_size); if (!ptr) { fprintf(stderr, "%s: line %" Z "d: unexpected format\n", prog, lineno); exit(EXIT_FAILURE); } else { *ptr = '\0'; fprintf(stderr, "%s: line %" Z "d: unrecognized keyword ignored: %s\n", prog, lineno, (char *)dbuf.mv_data); } } } } } static void badend(void) { fprintf(stderr, "%s: line %" Z "d: unexpected end of input\n", prog, lineno); } static int unhex(unsigned char *c2) { int x, c; x = *c2++ & 0x4f; if (x & 0x40) x -= 55; c = x << 4; x = *c2 & 0x4f; if (x & 0x40) x -= 55; c |= x; return c; } static int readline(MDB_val *out, MDB_val *buf) { unsigned char *c1, *c2, *end; size_t len, l2; int c; if (!(mode & NOHDR)) { c = fgetc(stdin); if (c == EOF) { Eof = 1; return EOF; } if (c != ' ') { lineno++; if (fgets(buf->mv_data, buf->mv_size, stdin) == NULL) { badend: Eof = 1; badend(); return EOF; } if (c == 'D' && !strncmp(buf->mv_data, "ATA=END", STRLENOF("ATA=END"))) return EOF; goto badend; } } if (fgets(buf->mv_data, buf->mv_size, stdin) == NULL) { Eof = 1; return EOF; } lineno++; c1 = buf->mv_data; len = strlen((char *)c1); l2 = len; /* Is buffer too short? */ while (c1[len-1] != '\n') { buf->mv_data = realloc(buf->mv_data, buf->mv_size*2); if (!buf->mv_data) { Eof = 1; fprintf(stderr, "%s: line %" Z "d: out of memory, line too long\n", prog, lineno); return EOF; } c1 = buf->mv_data; c1 += l2; if (fgets((char *)c1, buf->mv_size+1, stdin) == NULL) { Eof = 1; badend(); return EOF; } buf->mv_size *= 2; len = strlen((char *)c1); l2 += len; } c1 = c2 = buf->mv_data; len = l2; c1[--len] = '\0'; end = c1 + len; if (mode & PRINT) { while (c2 < end) { if (*c2 == '\\') { if (c2[1] == '\\') { c1++; c2 += 2; } else { if (c2+3 > end || !isxdigit(c2[1]) || !isxdigit(c2[2])) { Eof = 1; badend(); return EOF; } *c1++ = unhex(++c2); c2 += 2; } } else { c1++; c2++; } } } else { /* odd length not allowed */ if (len & 1) { Eof = 1; badend(); return EOF; } while (c2 < end) { if (!isxdigit(*c2) || !isxdigit(c2[1])) { Eof = 1; badend(); return EOF; } *c1++ = unhex(c2); c2 += 2; } } c2 = out->mv_data = buf->mv_data; out->mv_size = c1 - c2; return 0; } static void usage(void) { fprintf(stderr, "usage: %s dbpath [-V] [-f input] [-n] [-s name] [-N] [-T]\n", prog); exit(EXIT_FAILURE); } int main(int argc, char *argv[]) { int i, rc; MDB_env *env; MDB_txn *txn; MDB_cursor *mc; MDB_dbi dbi; char *envname; int envflags = 0, putflags = 0; int dohdr = 0; prog = argv[0]; if (argc < 2) { usage(); } /* -f: load file instead of stdin * -n: use NOSUBDIR flag on env_open * -s: load into named subDB * -N: use NOOVERWRITE on puts * -T: read plaintext * -V: print version and exit */ while ((i = getopt(argc, argv, "f:ns:NTV")) != EOF) { switch(i) { case 'V': printf("%s\n", MDB_VERSION_STRING); exit(0); break; case 'f': if (freopen(optarg, "r", stdin) == NULL) { fprintf(stderr, "%s: %s: reopen: %s\n", prog, optarg, strerror(errno)); exit(EXIT_FAILURE); } break; case 'n': envflags |= MDB_NOSUBDIR; break; case 's': subname = strdup(optarg); break; case 'N': putflags = MDB_NOOVERWRITE|MDB_NODUPDATA; break; case 'T': mode |= NOHDR; break; default: usage(); } } if (optind != argc - 1) usage(); dbuf.mv_size = 4096; dbuf.mv_data = malloc(dbuf.mv_size); if (!(mode & NOHDR)) readhdr(); envname = argv[optind]; rc = mdb_env_create(&env); if (rc) { fprintf(stderr, "mdb_env_create failed, error %d %s\n", rc, mdb_strerror(rc)); return EXIT_FAILURE; } mdb_env_set_maxdbs(env, 2); if (info.me_maxreaders) mdb_env_set_maxreaders(env, info.me_maxreaders); if (info.me_mapsize) mdb_env_set_mapsize(env, info.me_mapsize); if (info.me_mapaddr) envflags |= MDB_FIXEDMAP; rc = mdb_env_open(env, envname, envflags, 0664); if (rc) { fprintf(stderr, "mdb_env_open failed, error %d %s\n", rc, mdb_strerror(rc)); goto env_close; } kbuf.mv_size = mdb_env_get_maxkeysize(env) * 2 + 2; kbuf.mv_data = malloc(kbuf.mv_size); while(!Eof) { MDB_val key, data; int batch = 0; flags = 0; if (!dohdr) { dohdr = 1; } else if (!(mode & NOHDR)) readhdr(); rc = mdb_txn_begin(env, NULL, 0, &txn); if (rc) { fprintf(stderr, "mdb_txn_begin failed, error %d %s\n", rc, mdb_strerror(rc)); goto env_close; } rc = mdb_open(txn, subname, flags|MDB_CREATE, &dbi); if (rc) { fprintf(stderr, "mdb_open failed, error %d %s\n", rc, mdb_strerror(rc)); goto txn_abort; } rc = mdb_cursor_open(txn, dbi, &mc); if (rc) { fprintf(stderr, "mdb_cursor_open failed, error %d %s\n", rc, mdb_strerror(rc)); goto txn_abort; } while(1) { rc = readline(&key, &kbuf); if (rc == EOF) break; if (rc) goto txn_abort; rc = readline(&data, &dbuf); if (rc) goto txn_abort; rc = mdb_cursor_put(mc, &key, &data, putflags); if (rc == MDB_KEYEXIST && putflags) continue; if (rc) goto txn_abort; batch++; if (batch == 100) { rc = mdb_txn_commit(txn); if (rc) { fprintf(stderr, "%s: line %" Z "d: txn_commit: %s\n", prog, lineno, mdb_strerror(rc)); goto env_close; } rc = mdb_txn_begin(env, NULL, 0, &txn); if (rc) { fprintf(stderr, "mdb_txn_begin failed, error %d %s\n", rc, mdb_strerror(rc)); goto env_close; } rc = mdb_cursor_open(txn, dbi, &mc); if (rc) { fprintf(stderr, "mdb_cursor_open failed, error %d %s\n", rc, mdb_strerror(rc)); goto txn_abort; } batch = 0; } } rc = mdb_txn_commit(txn); txn = NULL; if (rc) { fprintf(stderr, "%s: line %" Z "d: txn_commit: %s\n", prog, lineno, mdb_strerror(rc)); goto env_close; } mdb_dbi_close(env, dbi); } txn_abort: mdb_txn_abort(txn); env_close: mdb_env_close(env); return rc ? EXIT_FAILURE : EXIT_SUCCESS; } openldap-2.4.42+dfsg/libraries/liblmdb/mdb_load.10000644000175000017500000000440312563404150020235 0ustar ryanryan.TH MDB_LOAD 1 "2014/06/20" "LMDB 0.9.14" .\" Copyright 2014-2015 Howard Chu, Symas Corp. All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME mdb_load \- LMDB environment import tool .SH SYNOPSIS .B mdb_load .BR \ envpath [\c .BR \-V ] [\c .BI \-f \ file\fR] [\c .BR \-n ] [\c .BI \-s \ subdb\fR] [\c .BR \-N ] [\c .BR \-T ] .SH DESCRIPTION The .B mdb_load utility reads from the standard input and loads it into the LMDB environment .BR envpath . The input to .B mdb_load must be in the output format specified by the .BR mdb_dump (1) utility or as specified by the .B -T option below. .SH OPTIONS .TP .BR \-V Write the library version number to the standard output, and exit. .TP .BR \-f \ file Read from the specified file instead of from the standard input. .TP .BR \-n Load an LMDB database which does not use subdirectories. .TP .BR \-s \ subdb Load a specific subdatabase. If no database is specified, data is loaded into the main database. .TP .BR \-N Don't overwrite existing records when loading into an already existing database; just skip them. .TP .BR \-T Load data from simple text files. The input must be paired lines of text, where the first line of the pair is the key item, and the second line of the pair is its corresponding data item. A simple escape mechanism, where newline and backslash (\\) characters are special, is applied to the text input. Newline characters are interpreted as record separators. Backslash characters in the text will be interpreted in one of two ways: If the backslash character precedes another backslash character, the pair will be interpreted as a literal backslash. If the backslash character precedes any other character, the two characters following the backslash will be interpreted as a hexadecimal specification of a single character; for example, \\0a is a newline character in the ASCII character set. For this reason, any backslash or newline characters that naturally occur in the text input must be escaped to avoid misinterpretation by .BR mdb_load . .SH DIAGNOSTICS Exit status is zero if no errors occur. Errors result in a non-zero exit status and a diagnostic message being written to standard error. .SH "SEE ALSO" .BR mdb_dump (1) .SH AUTHOR Howard Chu of Symas Corporation openldap-2.4.42+dfsg/libraries/liblmdb/mdb.c0000644000175000017500000100666712563404150017337 0ustar ryanryan/** @file mdb.c * @brief Lightning memory-mapped database library * * A Btree-based database management library modeled loosely on the * BerkeleyDB API, but much simplified. */ /* * Copyright 2011-2015 Howard Chu, Symas Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . * * This code is derived from btree.c written by Martin Hedenfalk. * * Copyright (c) 2009, 2010 Martin Hedenfalk * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef _GNU_SOURCE #define _GNU_SOURCE 1 #endif #ifdef _WIN32 #include #include /** getpid() returns int; MinGW defines pid_t but MinGW64 typedefs it * as int64 which is wrong. MSVC doesn't define it at all, so just * don't use it. */ #define MDB_PID_T int #define MDB_THR_T DWORD #include #include #ifdef __GNUC__ # include #else # define LITTLE_ENDIAN 1234 # define BIG_ENDIAN 4321 # define BYTE_ORDER LITTLE_ENDIAN # ifndef SSIZE_MAX # define SSIZE_MAX INT_MAX # endif #endif #else #include #include #define MDB_PID_T pid_t #define MDB_THR_T pthread_t #include #include #include #ifdef HAVE_SYS_FILE_H #include #endif #include #endif #if defined(__mips) && defined(__linux) /* MIPS has cache coherency issues, requires explicit cache control */ #include extern int cacheflush(char *addr, int nbytes, int cache); #define CACHEFLUSH(addr, bytes, cache) cacheflush(addr, bytes, cache) #else #define CACHEFLUSH(addr, bytes, cache) #endif #if defined(__linux) && !defined(MDB_FDATASYNC_WORKS) /** fdatasync is broken on ext3/ext4fs on older kernels, see * description in #mdb_env_open2 comments. You can safely * define MDB_FDATASYNC_WORKS if this code will only be run * on kernels 3.6 and newer. */ #define BROKEN_FDATASYNC #endif #include #include #include #include #include #include #include #include #include #if defined(__sun) || defined(ANDROID) /* Most platforms have posix_memalign, older may only have memalign */ #define HAVE_MEMALIGN 1 #include #endif #if !(defined(BYTE_ORDER) || defined(__BYTE_ORDER)) #include #include /* defines BYTE_ORDER on HPUX and Solaris */ #endif #if defined(__APPLE__) || defined (BSD) # define MDB_USE_POSIX_SEM 1 # define MDB_FDATASYNC fsync #elif defined(ANDROID) # define MDB_FDATASYNC fsync #endif #ifndef _WIN32 #include #ifdef MDB_USE_POSIX_SEM # define MDB_USE_HASH 1 #include #endif #endif #ifdef USE_VALGRIND #include #define VGMEMP_CREATE(h,r,z) VALGRIND_CREATE_MEMPOOL(h,r,z) #define VGMEMP_ALLOC(h,a,s) VALGRIND_MEMPOOL_ALLOC(h,a,s) #define VGMEMP_FREE(h,a) VALGRIND_MEMPOOL_FREE(h,a) #define VGMEMP_DESTROY(h) VALGRIND_DESTROY_MEMPOOL(h) #define VGMEMP_DEFINED(a,s) VALGRIND_MAKE_MEM_DEFINED(a,s) #else #define VGMEMP_CREATE(h,r,z) #define VGMEMP_ALLOC(h,a,s) #define VGMEMP_FREE(h,a) #define VGMEMP_DESTROY(h) #define VGMEMP_DEFINED(a,s) #endif #ifndef BYTE_ORDER # if (defined(_LITTLE_ENDIAN) || defined(_BIG_ENDIAN)) && !(defined(_LITTLE_ENDIAN) && defined(_BIG_ENDIAN)) /* Solaris just defines one or the other */ # define LITTLE_ENDIAN 1234 # define BIG_ENDIAN 4321 # ifdef _LITTLE_ENDIAN # define BYTE_ORDER LITTLE_ENDIAN # else # define BYTE_ORDER BIG_ENDIAN # endif # else # define BYTE_ORDER __BYTE_ORDER # endif #endif #ifndef LITTLE_ENDIAN #define LITTLE_ENDIAN __LITTLE_ENDIAN #endif #ifndef BIG_ENDIAN #define BIG_ENDIAN __BIG_ENDIAN #endif #if defined(__i386) || defined(__x86_64) || defined(_M_IX86) #define MISALIGNED_OK 1 #endif #include "lmdb.h" #include "midl.h" #if (BYTE_ORDER == LITTLE_ENDIAN) == (BYTE_ORDER == BIG_ENDIAN) # error "Unknown or unsupported endianness (BYTE_ORDER)" #elif (-6 & 5) || CHAR_BIT != 8 || UINT_MAX < 0xffffffff || ULONG_MAX % 0xFFFF # error "Two's complement, reasonably sized integer types, please" #endif #ifdef __GNUC__ /** Put infrequently used env functions in separate section */ # ifdef __APPLE__ # define ESECT __attribute__ ((section("__TEXT,text_env"))) # else # define ESECT __attribute__ ((section("text_env"))) # endif #else #define ESECT #endif /** @defgroup internal LMDB Internals * @{ */ /** @defgroup compat Compatibility Macros * A bunch of macros to minimize the amount of platform-specific ifdefs * needed throughout the rest of the code. When the features this library * needs are similar enough to POSIX to be hidden in a one-or-two line * replacement, this macro approach is used. * @{ */ /** Features under development */ #ifndef MDB_DEVEL #define MDB_DEVEL 0 #endif /** Wrapper around __func__, which is a C99 feature */ #if __STDC_VERSION__ >= 199901L # define mdb_func_ __func__ #elif __GNUC__ >= 2 || _MSC_VER >= 1300 # define mdb_func_ __FUNCTION__ #else /* If a debug message says (), update the #if statements above */ # define mdb_func_ "" #endif #ifdef _WIN32 #define MDB_USE_HASH 1 #define MDB_PIDLOCK 0 #define THREAD_RET DWORD #define pthread_t HANDLE #define pthread_mutex_t HANDLE #define pthread_cond_t HANDLE #define pthread_key_t DWORD #define pthread_self() GetCurrentThreadId() #define pthread_key_create(x,y) \ ((*(x) = TlsAlloc()) == TLS_OUT_OF_INDEXES ? ErrCode() : 0) #define pthread_key_delete(x) TlsFree(x) #define pthread_getspecific(x) TlsGetValue(x) #define pthread_setspecific(x,y) (TlsSetValue(x,y) ? 0 : ErrCode()) #define pthread_mutex_unlock(x) ReleaseMutex(*x) #define pthread_mutex_lock(x) WaitForSingleObject(*x, INFINITE) #define pthread_cond_signal(x) SetEvent(*x) #define pthread_cond_wait(cond,mutex) do{SignalObjectAndWait(*mutex, *cond, INFINITE, FALSE); WaitForSingleObject(*mutex, INFINITE);}while(0) #define THREAD_CREATE(thr,start,arg) thr=CreateThread(NULL,0,start,arg,0,NULL) #define THREAD_FINISH(thr) WaitForSingleObject(thr, INFINITE) #define LOCK_MUTEX_R(env) pthread_mutex_lock(&(env)->me_rmutex) #define UNLOCK_MUTEX_R(env) pthread_mutex_unlock(&(env)->me_rmutex) #define LOCK_MUTEX_W(env) pthread_mutex_lock(&(env)->me_wmutex) #define UNLOCK_MUTEX_W(env) pthread_mutex_unlock(&(env)->me_wmutex) #define getpid() GetCurrentProcessId() #define MDB_FDATASYNC(fd) (!FlushFileBuffers(fd)) #define MDB_MSYNC(addr,len,flags) (!FlushViewOfFile(addr,len)) #define ErrCode() GetLastError() #define GET_PAGESIZE(x) {SYSTEM_INFO si; GetSystemInfo(&si); (x) = si.dwPageSize;} #define close(fd) (CloseHandle(fd) ? 0 : -1) #define munmap(ptr,len) UnmapViewOfFile(ptr) #ifdef PROCESS_QUERY_LIMITED_INFORMATION #define MDB_PROCESS_QUERY_LIMITED_INFORMATION PROCESS_QUERY_LIMITED_INFORMATION #else #define MDB_PROCESS_QUERY_LIMITED_INFORMATION 0x1000 #endif #define Z "I" #else #define THREAD_RET void * #define THREAD_CREATE(thr,start,arg) pthread_create(&thr,NULL,start,arg) #define THREAD_FINISH(thr) pthread_join(thr,NULL) #define Z "z" /**< printf format modifier for size_t */ /** For MDB_LOCK_FORMAT: True if readers take a pid lock in the lockfile */ #define MDB_PIDLOCK 1 #ifdef MDB_USE_POSIX_SEM #define LOCK_MUTEX_R(env) mdb_sem_wait((env)->me_rmutex) #define UNLOCK_MUTEX_R(env) sem_post((env)->me_rmutex) #define LOCK_MUTEX_W(env) mdb_sem_wait((env)->me_wmutex) #define UNLOCK_MUTEX_W(env) sem_post((env)->me_wmutex) static int mdb_sem_wait(sem_t *sem) { int rc; while ((rc = sem_wait(sem)) && (rc = errno) == EINTR) ; return rc; } #else /** Lock the reader mutex. */ #define LOCK_MUTEX_R(env) pthread_mutex_lock(&(env)->me_txns->mti_mutex) /** Unlock the reader mutex. */ #define UNLOCK_MUTEX_R(env) pthread_mutex_unlock(&(env)->me_txns->mti_mutex) /** Lock the writer mutex. * Only a single write transaction is allowed at a time. Other writers * will block waiting for this mutex. */ #define LOCK_MUTEX_W(env) pthread_mutex_lock(&(env)->me_txns->mti_wmutex) /** Unlock the writer mutex. */ #define UNLOCK_MUTEX_W(env) pthread_mutex_unlock(&(env)->me_txns->mti_wmutex) #endif /* MDB_USE_POSIX_SEM */ /** Get the error code for the last failed system function. */ #define ErrCode() errno /** An abstraction for a file handle. * On POSIX systems file handles are small integers. On Windows * they're opaque pointers. */ #define HANDLE int /** A value for an invalid file handle. * Mainly used to initialize file variables and signify that they are * unused. */ #define INVALID_HANDLE_VALUE (-1) /** Get the size of a memory page for the system. * This is the basic size that the platform's memory manager uses, and is * fundamental to the use of memory-mapped files. */ #define GET_PAGESIZE(x) ((x) = sysconf(_SC_PAGE_SIZE)) #endif #if defined(_WIN32) || defined(MDB_USE_POSIX_SEM) #define MNAME_LEN 32 #else #define MNAME_LEN (sizeof(pthread_mutex_t)) #endif /** @} */ #ifndef _WIN32 /** A flag for opening a file and requesting synchronous data writes. * This is only used when writing a meta page. It's not strictly needed; * we could just do a normal write and then immediately perform a flush. * But if this flag is available it saves us an extra system call. * * @note If O_DSYNC is undefined but exists in /usr/include, * preferably set some compiler flag to get the definition. * Otherwise compile with the less efficient -DMDB_DSYNC=O_SYNC. */ #ifndef MDB_DSYNC # define MDB_DSYNC O_DSYNC #endif #endif /** Function for flushing the data of a file. Define this to fsync * if fdatasync() is not supported. */ #ifndef MDB_FDATASYNC # define MDB_FDATASYNC fdatasync #endif #ifndef MDB_MSYNC # define MDB_MSYNC(addr,len,flags) msync(addr,len,flags) #endif #ifndef MS_SYNC #define MS_SYNC 1 #endif #ifndef MS_ASYNC #define MS_ASYNC 0 #endif /** A page number in the database. * Note that 64 bit page numbers are overkill, since pages themselves * already represent 12-13 bits of addressable memory, and the OS will * always limit applications to a maximum of 63 bits of address space. * * @note In the #MDB_node structure, we only store 48 bits of this value, * which thus limits us to only 60 bits of addressable data. */ typedef MDB_ID pgno_t; /** A transaction ID. * See struct MDB_txn.mt_txnid for details. */ typedef MDB_ID txnid_t; /** @defgroup debug Debug Macros * @{ */ #ifndef MDB_DEBUG /** Enable debug output. Needs variable argument macros (a C99 feature). * Set this to 1 for copious tracing. Set to 2 to add dumps of all IDLs * read from and written to the database (used for free space management). */ #define MDB_DEBUG 0 #endif #if MDB_DEBUG static int mdb_debug; static txnid_t mdb_debug_start; /** Print a debug message with printf formatting. * Requires double parenthesis around 2 or more args. */ # define DPRINTF(args) ((void) ((mdb_debug) && DPRINTF0 args)) # define DPRINTF0(fmt, ...) \ fprintf(stderr, "%s:%d " fmt "\n", mdb_func_, __LINE__, __VA_ARGS__) #else # define DPRINTF(args) ((void) 0) #endif /** Print a debug string. * The string is printed literally, with no format processing. */ #define DPUTS(arg) DPRINTF(("%s", arg)) /** Debuging output value of a cursor DBI: Negative in a sub-cursor. */ #define DDBI(mc) \ (((mc)->mc_flags & C_SUB) ? -(int)(mc)->mc_dbi : (int)(mc)->mc_dbi) /** @} */ /** @brief The maximum size of a database page. * * It is 32k or 64k, since value-PAGEBASE must fit in * #MDB_page.%mp_upper. * * LMDB will use database pages < OS pages if needed. * That causes more I/O in write transactions: The OS must * know (read) the whole page before writing a partial page. * * Note that we don't currently support Huge pages. On Linux, * regular data files cannot use Huge pages, and in general * Huge pages aren't actually pageable. We rely on the OS * demand-pager to read our data and page it out when memory * pressure from other processes is high. So until OSs have * actual paging support for Huge pages, they're not viable. */ #define MAX_PAGESIZE (PAGEBASE ? 0x10000 : 0x8000) /** The minimum number of keys required in a database page. * Setting this to a larger value will place a smaller bound on the * maximum size of a data item. Data items larger than this size will * be pushed into overflow pages instead of being stored directly in * the B-tree node. This value used to default to 4. With a page size * of 4096 bytes that meant that any item larger than 1024 bytes would * go into an overflow page. That also meant that on average 2-3KB of * each overflow page was wasted space. The value cannot be lower than * 2 because then there would no longer be a tree structure. With this * value, items larger than 2KB will go into overflow pages, and on * average only 1KB will be wasted. */ #define MDB_MINKEYS 2 /** A stamp that identifies a file as an LMDB file. * There's nothing special about this value other than that it is easily * recognizable, and it will reflect any byte order mismatches. */ #define MDB_MAGIC 0xBEEFC0DE /** The version number for a database's datafile format. */ #define MDB_DATA_VERSION ((MDB_DEVEL) ? 999 : 1) /** The version number for a database's lockfile format. */ #define MDB_LOCK_VERSION 1 /** @brief The max size of a key we can write, or 0 for computed max. * * This macro should normally be left alone or set to 0. * Note that a database with big keys or dupsort data cannot be * reliably modified by a liblmdb which uses a smaller max. * The default is 511 for backwards compat, or 0 when #MDB_DEVEL. * * Other values are allowed, for backwards compat. However: * A value bigger than the computed max can break if you do not * know what you are doing, and liblmdb <= 0.9.10 can break when * modifying a DB with keys/dupsort data bigger than its max. * * Data items in an #MDB_DUPSORT database are also limited to * this size, since they're actually keys of a sub-DB. Keys and * #MDB_DUPSORT data items must fit on a node in a regular page. */ #ifndef MDB_MAXKEYSIZE #define MDB_MAXKEYSIZE ((MDB_DEVEL) ? 0 : 511) #endif /** The maximum size of a key we can write to the environment. */ #if MDB_MAXKEYSIZE #define ENV_MAXKEY(env) (MDB_MAXKEYSIZE) #else #define ENV_MAXKEY(env) ((env)->me_maxkey) #endif /** @brief The maximum size of a data item. * * We only store a 32 bit value for node sizes. */ #define MAXDATASIZE 0xffffffffUL #if MDB_DEBUG /** Key size which fits in a #DKBUF. * @ingroup debug */ #define DKBUF_MAXKEYSIZE ((MDB_MAXKEYSIZE) > 0 ? (MDB_MAXKEYSIZE) : 511) /** A key buffer. * @ingroup debug * This is used for printing a hex dump of a key's contents. */ #define DKBUF char kbuf[DKBUF_MAXKEYSIZE*2+1] /** Display a key in hex. * @ingroup debug * Invoke a function to display a key in hex. */ #define DKEY(x) mdb_dkey(x, kbuf) #else #define DKBUF #define DKEY(x) 0 #endif /** An invalid page number. * Mainly used to denote an empty tree. */ #define P_INVALID (~(pgno_t)0) /** Test if the flags \b f are set in a flag word \b w. */ #define F_ISSET(w, f) (((w) & (f)) == (f)) /** Round \b n up to an even number. */ #define EVEN(n) (((n) + 1U) & -2) /* sign-extending -2 to match n+1U */ /** Used for offsets within a single page. * Since memory pages are typically 4 or 8KB in size, 12-13 bits, * this is plenty. */ typedef uint16_t indx_t; /** Default size of memory map. * This is certainly too small for any actual applications. Apps should always set * the size explicitly using #mdb_env_set_mapsize(). */ #define DEFAULT_MAPSIZE 1048576 /** @defgroup readers Reader Lock Table * Readers don't acquire any locks for their data access. Instead, they * simply record their transaction ID in the reader table. The reader * mutex is needed just to find an empty slot in the reader table. The * slot's address is saved in thread-specific data so that subsequent read * transactions started by the same thread need no further locking to proceed. * * If #MDB_NOTLS is set, the slot address is not saved in thread-specific data. * * No reader table is used if the database is on a read-only filesystem, or * if #MDB_NOLOCK is set. * * Since the database uses multi-version concurrency control, readers don't * actually need any locking. This table is used to keep track of which * readers are using data from which old transactions, so that we'll know * when a particular old transaction is no longer in use. Old transactions * that have discarded any data pages can then have those pages reclaimed * for use by a later write transaction. * * The lock table is constructed such that reader slots are aligned with the * processor's cache line size. Any slot is only ever used by one thread. * This alignment guarantees that there will be no contention or cache * thrashing as threads update their own slot info, and also eliminates * any need for locking when accessing a slot. * * A writer thread will scan every slot in the table to determine the oldest * outstanding reader transaction. Any freed pages older than this will be * reclaimed by the writer. The writer doesn't use any locks when scanning * this table. This means that there's no guarantee that the writer will * see the most up-to-date reader info, but that's not required for correct * operation - all we need is to know the upper bound on the oldest reader, * we don't care at all about the newest reader. So the only consequence of * reading stale information here is that old pages might hang around a * while longer before being reclaimed. That's actually good anyway, because * the longer we delay reclaiming old pages, the more likely it is that a * string of contiguous pages can be found after coalescing old pages from * many old transactions together. * @{ */ /** Number of slots in the reader table. * This value was chosen somewhat arbitrarily. 126 readers plus a * couple mutexes fit exactly into 8KB on my development machine. * Applications should set the table size using #mdb_env_set_maxreaders(). */ #define DEFAULT_READERS 126 /** The size of a CPU cache line in bytes. We want our lock structures * aligned to this size to avoid false cache line sharing in the * lock table. * This value works for most CPUs. For Itanium this should be 128. */ #ifndef CACHELINE #define CACHELINE 64 #endif /** The information we store in a single slot of the reader table. * In addition to a transaction ID, we also record the process and * thread ID that owns a slot, so that we can detect stale information, * e.g. threads or processes that went away without cleaning up. * @note We currently don't check for stale records. We simply re-init * the table when we know that we're the only process opening the * lock file. */ typedef struct MDB_rxbody { /** Current Transaction ID when this transaction began, or (txnid_t)-1. * Multiple readers that start at the same time will probably have the * same ID here. Again, it's not important to exclude them from * anything; all we need to know is which version of the DB they * started from so we can avoid overwriting any data used in that * particular version. */ volatile txnid_t mrb_txnid; /** The process ID of the process owning this reader txn. */ volatile MDB_PID_T mrb_pid; /** The thread ID of the thread owning this txn. */ volatile MDB_THR_T mrb_tid; } MDB_rxbody; /** The actual reader record, with cacheline padding. */ typedef struct MDB_reader { union { MDB_rxbody mrx; /** shorthand for mrb_txnid */ #define mr_txnid mru.mrx.mrb_txnid #define mr_pid mru.mrx.mrb_pid #define mr_tid mru.mrx.mrb_tid /** cache line alignment */ char pad[(sizeof(MDB_rxbody)+CACHELINE-1) & ~(CACHELINE-1)]; } mru; } MDB_reader; /** The header for the reader table. * The table resides in a memory-mapped file. (This is a different file * than is used for the main database.) * * For POSIX the actual mutexes reside in the shared memory of this * mapped file. On Windows, mutexes are named objects allocated by the * kernel; we store the mutex names in this mapped file so that other * processes can grab them. This same approach is also used on * MacOSX/Darwin (using named semaphores) since MacOSX doesn't support * process-shared POSIX mutexes. For these cases where a named object * is used, the object name is derived from a 64 bit FNV hash of the * environment pathname. As such, naming collisions are extremely * unlikely. If a collision occurs, the results are unpredictable. */ typedef struct MDB_txbody { /** Stamp identifying this as an LMDB file. It must be set * to #MDB_MAGIC. */ uint32_t mtb_magic; /** Format of this lock file. Must be set to #MDB_LOCK_FORMAT. */ uint32_t mtb_format; #if defined(_WIN32) || defined(MDB_USE_POSIX_SEM) char mtb_rmname[MNAME_LEN]; #else /** Mutex protecting access to this table. * This is the reader lock that #LOCK_MUTEX_R acquires. */ pthread_mutex_t mtb_mutex; #endif /** The ID of the last transaction committed to the database. * This is recorded here only for convenience; the value can always * be determined by reading the main database meta pages. */ volatile txnid_t mtb_txnid; /** The number of slots that have been used in the reader table. * This always records the maximum count, it is not decremented * when readers release their slots. */ volatile unsigned mtb_numreaders; } MDB_txbody; /** The actual reader table definition. */ typedef struct MDB_txninfo { union { MDB_txbody mtb; #define mti_magic mt1.mtb.mtb_magic #define mti_format mt1.mtb.mtb_format #define mti_mutex mt1.mtb.mtb_mutex #define mti_rmname mt1.mtb.mtb_rmname #define mti_txnid mt1.mtb.mtb_txnid #define mti_numreaders mt1.mtb.mtb_numreaders char pad[(sizeof(MDB_txbody)+CACHELINE-1) & ~(CACHELINE-1)]; } mt1; union { #if defined(_WIN32) || defined(MDB_USE_POSIX_SEM) char mt2_wmname[MNAME_LEN]; #define mti_wmname mt2.mt2_wmname #else pthread_mutex_t mt2_wmutex; #define mti_wmutex mt2.mt2_wmutex #endif char pad[(MNAME_LEN+CACHELINE-1) & ~(CACHELINE-1)]; } mt2; MDB_reader mti_readers[1]; } MDB_txninfo; /** Lockfile format signature: version, features and field layout */ #define MDB_LOCK_FORMAT \ ((uint32_t) \ ((MDB_LOCK_VERSION) \ /* Flags which describe functionality */ \ + (((MDB_PIDLOCK) != 0) << 16))) /** @} */ /** Common header for all page types. * Overflow records occupy a number of contiguous pages with no * headers on any page after the first. */ typedef struct MDB_page { #define mp_pgno mp_p.p_pgno #define mp_next mp_p.p_next union { pgno_t p_pgno; /**< page number */ struct MDB_page *p_next; /**< for in-memory list of freed pages */ } mp_p; uint16_t mp_pad; /** @defgroup mdb_page Page Flags * @ingroup internal * Flags for the page headers. * @{ */ #define P_BRANCH 0x01 /**< branch page */ #define P_LEAF 0x02 /**< leaf page */ #define P_OVERFLOW 0x04 /**< overflow page */ #define P_META 0x08 /**< meta page */ #define P_DIRTY 0x10 /**< dirty page, also set for #P_SUBP pages */ #define P_LEAF2 0x20 /**< for #MDB_DUPFIXED records */ #define P_SUBP 0x40 /**< for #MDB_DUPSORT sub-pages */ #define P_LOOSE 0x4000 /**< page was dirtied then freed, can be reused */ #define P_KEEP 0x8000 /**< leave this page alone during spill */ /** @} */ uint16_t mp_flags; /**< @ref mdb_page */ #define mp_lower mp_pb.pb.pb_lower #define mp_upper mp_pb.pb.pb_upper #define mp_pages mp_pb.pb_pages union { struct { indx_t pb_lower; /**< lower bound of free space */ indx_t pb_upper; /**< upper bound of free space */ } pb; uint32_t pb_pages; /**< number of overflow pages */ } mp_pb; indx_t mp_ptrs[1]; /**< dynamic size */ } MDB_page; /** Size of the page header, excluding dynamic data at the end */ #define PAGEHDRSZ ((unsigned) offsetof(MDB_page, mp_ptrs)) /** Address of first usable data byte in a page, after the header */ #define METADATA(p) ((void *)((char *)(p) + PAGEHDRSZ)) /** ITS#7713, change PAGEBASE to handle 65536 byte pages */ #define PAGEBASE ((MDB_DEVEL) ? PAGEHDRSZ : 0) /** Number of nodes on a page */ #define NUMKEYS(p) (((p)->mp_lower - (PAGEHDRSZ-PAGEBASE)) >> 1) /** The amount of space remaining in the page */ #define SIZELEFT(p) (indx_t)((p)->mp_upper - (p)->mp_lower) /** The percentage of space used in the page, in tenths of a percent. */ #define PAGEFILL(env, p) (1000L * ((env)->me_psize - PAGEHDRSZ - SIZELEFT(p)) / \ ((env)->me_psize - PAGEHDRSZ)) /** The minimum page fill factor, in tenths of a percent. * Pages emptier than this are candidates for merging. */ #define FILL_THRESHOLD 250 /** Test if a page is a leaf page */ #define IS_LEAF(p) F_ISSET((p)->mp_flags, P_LEAF) /** Test if a page is a LEAF2 page */ #define IS_LEAF2(p) F_ISSET((p)->mp_flags, P_LEAF2) /** Test if a page is a branch page */ #define IS_BRANCH(p) F_ISSET((p)->mp_flags, P_BRANCH) /** Test if a page is an overflow page */ #define IS_OVERFLOW(p) F_ISSET((p)->mp_flags, P_OVERFLOW) /** Test if a page is a sub page */ #define IS_SUBP(p) F_ISSET((p)->mp_flags, P_SUBP) /** The number of overflow pages needed to store the given size. */ #define OVPAGES(size, psize) ((PAGEHDRSZ-1 + (size)) / (psize) + 1) /** Link in #MDB_txn.%mt_loose_pgs list */ #define NEXT_LOOSE_PAGE(p) (*(MDB_page **)((p) + 2)) /** Header for a single key/data pair within a page. * Used in pages of type #P_BRANCH and #P_LEAF without #P_LEAF2. * We guarantee 2-byte alignment for 'MDB_node's. */ typedef struct MDB_node { /** lo and hi are used for data size on leaf nodes and for * child pgno on branch nodes. On 64 bit platforms, flags * is also used for pgno. (Branch nodes have no flags). * They are in host byte order in case that lets some * accesses be optimized into a 32-bit word access. */ #if BYTE_ORDER == LITTLE_ENDIAN unsigned short mn_lo, mn_hi; /**< part of data size or pgno */ #else unsigned short mn_hi, mn_lo; #endif /** @defgroup mdb_node Node Flags * @ingroup internal * Flags for node headers. * @{ */ #define F_BIGDATA 0x01 /**< data put on overflow page */ #define F_SUBDATA 0x02 /**< data is a sub-database */ #define F_DUPDATA 0x04 /**< data has duplicates */ /** valid flags for #mdb_node_add() */ #define NODE_ADD_FLAGS (F_DUPDATA|F_SUBDATA|MDB_RESERVE|MDB_APPEND) /** @} */ unsigned short mn_flags; /**< @ref mdb_node */ unsigned short mn_ksize; /**< key size */ char mn_data[1]; /**< key and data are appended here */ } MDB_node; /** Size of the node header, excluding dynamic data at the end */ #define NODESIZE offsetof(MDB_node, mn_data) /** Bit position of top word in page number, for shifting mn_flags */ #define PGNO_TOPWORD ((pgno_t)-1 > 0xffffffffu ? 32 : 0) /** Size of a node in a branch page with a given key. * This is just the node header plus the key, there is no data. */ #define INDXSIZE(k) (NODESIZE + ((k) == NULL ? 0 : (k)->mv_size)) /** Size of a node in a leaf page with a given key and data. * This is node header plus key plus data size. */ #define LEAFSIZE(k, d) (NODESIZE + (k)->mv_size + (d)->mv_size) /** Address of node \b i in page \b p */ #define NODEPTR(p, i) ((MDB_node *)((char *)(p) + (p)->mp_ptrs[i] + PAGEBASE)) /** Address of the key for the node */ #define NODEKEY(node) (void *)((node)->mn_data) /** Address of the data for a node */ #define NODEDATA(node) (void *)((char *)(node)->mn_data + (node)->mn_ksize) /** Get the page number pointed to by a branch node */ #define NODEPGNO(node) \ ((node)->mn_lo | ((pgno_t) (node)->mn_hi << 16) | \ (PGNO_TOPWORD ? ((pgno_t) (node)->mn_flags << PGNO_TOPWORD) : 0)) /** Set the page number in a branch node */ #define SETPGNO(node,pgno) do { \ (node)->mn_lo = (pgno) & 0xffff; (node)->mn_hi = (pgno) >> 16; \ if (PGNO_TOPWORD) (node)->mn_flags = (pgno) >> PGNO_TOPWORD; } while(0) /** Get the size of the data in a leaf node */ #define NODEDSZ(node) ((node)->mn_lo | ((unsigned)(node)->mn_hi << 16)) /** Set the size of the data for a leaf node */ #define SETDSZ(node,size) do { \ (node)->mn_lo = (size) & 0xffff; (node)->mn_hi = (size) >> 16;} while(0) /** The size of a key in a node */ #define NODEKSZ(node) ((node)->mn_ksize) /** Copy a page number from src to dst */ #ifdef MISALIGNED_OK #define COPY_PGNO(dst,src) dst = src #else #if SIZE_MAX > 4294967295UL #define COPY_PGNO(dst,src) do { \ unsigned short *s, *d; \ s = (unsigned short *)&(src); \ d = (unsigned short *)&(dst); \ *d++ = *s++; \ *d++ = *s++; \ *d++ = *s++; \ *d = *s; \ } while (0) #else #define COPY_PGNO(dst,src) do { \ unsigned short *s, *d; \ s = (unsigned short *)&(src); \ d = (unsigned short *)&(dst); \ *d++ = *s++; \ *d = *s; \ } while (0) #endif #endif /** The address of a key in a LEAF2 page. * LEAF2 pages are used for #MDB_DUPFIXED sorted-duplicate sub-DBs. * There are no node headers, keys are stored contiguously. */ #define LEAF2KEY(p, i, ks) ((char *)(p) + PAGEHDRSZ + ((i)*(ks))) /** Set the \b node's key into \b keyptr, if requested. */ #define MDB_GET_KEY(node, keyptr) { if ((keyptr) != NULL) { \ (keyptr)->mv_size = NODEKSZ(node); (keyptr)->mv_data = NODEKEY(node); } } /** Set the \b node's key into \b key. */ #define MDB_GET_KEY2(node, key) { key.mv_size = NODEKSZ(node); key.mv_data = NODEKEY(node); } /** Information about a single database in the environment. */ typedef struct MDB_db { uint32_t md_pad; /**< also ksize for LEAF2 pages */ uint16_t md_flags; /**< @ref mdb_dbi_open */ uint16_t md_depth; /**< depth of this tree */ pgno_t md_branch_pages; /**< number of internal pages */ pgno_t md_leaf_pages; /**< number of leaf pages */ pgno_t md_overflow_pages; /**< number of overflow pages */ size_t md_entries; /**< number of data items */ pgno_t md_root; /**< the root page of this tree */ } MDB_db; /** mdb_dbi_open flags */ #define MDB_VALID 0x8000 /**< DB handle is valid, for me_dbflags */ #define PERSISTENT_FLAGS (0xffff & ~(MDB_VALID)) #define VALID_FLAGS (MDB_REVERSEKEY|MDB_DUPSORT|MDB_INTEGERKEY|MDB_DUPFIXED|\ MDB_INTEGERDUP|MDB_REVERSEDUP|MDB_CREATE) /** Handle for the DB used to track free pages. */ #define FREE_DBI 0 /** Handle for the default DB. */ #define MAIN_DBI 1 /** Meta page content. * A meta page is the start point for accessing a database snapshot. * Pages 0-1 are meta pages. Transaction N writes meta page #(N % 2). */ typedef struct MDB_meta { /** Stamp identifying this as an LMDB file. It must be set * to #MDB_MAGIC. */ uint32_t mm_magic; /** Version number of this file. Must be set to #MDB_DATA_VERSION. */ uint32_t mm_version; void *mm_address; /**< address for fixed mapping */ size_t mm_mapsize; /**< size of mmap region */ MDB_db mm_dbs[2]; /**< first is free space, 2nd is main db */ /** The size of pages used in this DB */ #define mm_psize mm_dbs[0].md_pad /** Any persistent environment flags. @ref mdb_env */ #define mm_flags mm_dbs[0].md_flags pgno_t mm_last_pg; /**< last used page in file */ volatile txnid_t mm_txnid; /**< txnid that committed this page */ } MDB_meta; /** Buffer for a stack-allocated meta page. * The members define size and alignment, and silence type * aliasing warnings. They are not used directly; that could * mean incorrectly using several union members in parallel. */ typedef union MDB_metabuf { MDB_page mb_page; struct { char mm_pad[PAGEHDRSZ]; MDB_meta mm_meta; } mb_metabuf; } MDB_metabuf; /** Auxiliary DB info. * The information here is mostly static/read-only. There is * only a single copy of this record in the environment. */ typedef struct MDB_dbx { MDB_val md_name; /**< name of the database */ MDB_cmp_func *md_cmp; /**< function for comparing keys */ MDB_cmp_func *md_dcmp; /**< function for comparing data items */ MDB_rel_func *md_rel; /**< user relocate function */ void *md_relctx; /**< user-provided context for md_rel */ } MDB_dbx; /** A database transaction. * Every operation requires a transaction handle. */ struct MDB_txn { MDB_txn *mt_parent; /**< parent of a nested txn */ MDB_txn *mt_child; /**< nested txn under this txn */ pgno_t mt_next_pgno; /**< next unallocated page */ /** The ID of this transaction. IDs are integers incrementing from 1. * Only committed write transactions increment the ID. If a transaction * aborts, the ID may be re-used by the next writer. */ txnid_t mt_txnid; MDB_env *mt_env; /**< the DB environment */ /** The list of pages that became unused during this transaction. */ MDB_IDL mt_free_pgs; /** The list of loose pages that became unused and may be reused * in this transaction, linked through #NEXT_LOOSE_PAGE(page). */ MDB_page *mt_loose_pgs; /* #Number of loose pages (#mt_loose_pgs) */ int mt_loose_count; /** The sorted list of dirty pages we temporarily wrote to disk * because the dirty list was full. page numbers in here are * shifted left by 1, deleted slots have the LSB set. */ MDB_IDL mt_spill_pgs; union { /** For write txns: Modified pages. Sorted when not MDB_WRITEMAP. */ MDB_ID2L dirty_list; /** For read txns: This thread/txn's reader table slot, or NULL. */ MDB_reader *reader; } mt_u; /** Array of records for each DB known in the environment. */ MDB_dbx *mt_dbxs; /** Array of MDB_db records for each known DB */ MDB_db *mt_dbs; /** Array of sequence numbers for each DB handle */ unsigned int *mt_dbiseqs; /** @defgroup mt_dbflag Transaction DB Flags * @ingroup internal * @{ */ #define DB_DIRTY 0x01 /**< DB was modified or is DUPSORT data */ #define DB_STALE 0x02 /**< Named-DB record is older than txnID */ #define DB_NEW 0x04 /**< Named-DB handle opened in this txn */ #define DB_VALID 0x08 /**< DB handle is valid, see also #MDB_VALID */ /** @} */ /** In write txns, array of cursors for each DB */ MDB_cursor **mt_cursors; /** Array of flags for each DB */ unsigned char *mt_dbflags; /** Number of DB records in use. This number only ever increments; * we don't decrement it when individual DB handles are closed. */ MDB_dbi mt_numdbs; /** @defgroup mdb_txn Transaction Flags * @ingroup internal * @{ */ #define MDB_TXN_RDONLY 0x01 /**< read-only transaction */ #define MDB_TXN_ERROR 0x02 /**< txn is unusable after an error */ #define MDB_TXN_DIRTY 0x04 /**< must write, even if dirty list is empty */ #define MDB_TXN_SPILLS 0x08 /**< txn or a parent has spilled pages */ /** @} */ unsigned int mt_flags; /**< @ref mdb_txn */ /** #dirty_list room: Array size - \#dirty pages visible to this txn. * Includes ancestor txns' dirty pages not hidden by other txns' * dirty/spilled pages. Thus commit(nested txn) has room to merge * dirty_list into mt_parent after freeing hidden mt_parent pages. */ unsigned int mt_dirty_room; }; /** Enough space for 2^32 nodes with minimum of 2 keys per node. I.e., plenty. * At 4 keys per node, enough for 2^64 nodes, so there's probably no need to * raise this on a 64 bit machine. */ #define CURSOR_STACK 32 struct MDB_xcursor; /** Cursors are used for all DB operations. * A cursor holds a path of (page pointer, key index) from the DB * root to a position in the DB, plus other state. #MDB_DUPSORT * cursors include an xcursor to the current data item. Write txns * track their cursors and keep them up to date when data moves. * Exception: An xcursor's pointer to a #P_SUBP page can be stale. * (A node with #F_DUPDATA but no #F_SUBDATA contains a subpage). */ struct MDB_cursor { /** Next cursor on this DB in this txn */ MDB_cursor *mc_next; /** Backup of the original cursor if this cursor is a shadow */ MDB_cursor *mc_backup; /** Context used for databases with #MDB_DUPSORT, otherwise NULL */ struct MDB_xcursor *mc_xcursor; /** The transaction that owns this cursor */ MDB_txn *mc_txn; /** The database handle this cursor operates on */ MDB_dbi mc_dbi; /** The database record for this cursor */ MDB_db *mc_db; /** The database auxiliary record for this cursor */ MDB_dbx *mc_dbx; /** The @ref mt_dbflag for this database */ unsigned char *mc_dbflag; unsigned short mc_snum; /**< number of pushed pages */ unsigned short mc_top; /**< index of top page, normally mc_snum-1 */ /** @defgroup mdb_cursor Cursor Flags * @ingroup internal * Cursor state flags. * @{ */ #define C_INITIALIZED 0x01 /**< cursor has been initialized and is valid */ #define C_EOF 0x02 /**< No more data */ #define C_SUB 0x04 /**< Cursor is a sub-cursor */ #define C_DEL 0x08 /**< last op was a cursor_del */ #define C_SPLITTING 0x20 /**< Cursor is in page_split */ #define C_UNTRACK 0x40 /**< Un-track cursor when closing */ /** @} */ unsigned int mc_flags; /**< @ref mdb_cursor */ MDB_page *mc_pg[CURSOR_STACK]; /**< stack of pushed pages */ indx_t mc_ki[CURSOR_STACK]; /**< stack of page indices */ }; /** Context for sorted-dup records. * We could have gone to a fully recursive design, with arbitrarily * deep nesting of sub-databases. But for now we only handle these * levels - main DB, optional sub-DB, sorted-duplicate DB. */ typedef struct MDB_xcursor { /** A sub-cursor for traversing the Dup DB */ MDB_cursor mx_cursor; /** The database record for this Dup DB */ MDB_db mx_db; /** The auxiliary DB record for this Dup DB */ MDB_dbx mx_dbx; /** The @ref mt_dbflag for this Dup DB */ unsigned char mx_dbflag; } MDB_xcursor; /** State of FreeDB old pages, stored in the MDB_env */ typedef struct MDB_pgstate { pgno_t *mf_pghead; /**< Reclaimed freeDB pages, or NULL before use */ txnid_t mf_pglast; /**< ID of last used record, or 0 if !mf_pghead */ } MDB_pgstate; /** The database environment. */ struct MDB_env { HANDLE me_fd; /**< The main data file */ HANDLE me_lfd; /**< The lock file */ HANDLE me_mfd; /**< just for writing the meta pages */ /** Failed to update the meta page. Probably an I/O error. */ #define MDB_FATAL_ERROR 0x80000000U /** Some fields are initialized. */ #define MDB_ENV_ACTIVE 0x20000000U /** me_txkey is set */ #define MDB_ENV_TXKEY 0x10000000U /** fdatasync is unreliable */ #define MDB_FSYNCONLY 0x08000000U uint32_t me_flags; /**< @ref mdb_env */ unsigned int me_psize; /**< DB page size, inited from me_os_psize */ unsigned int me_os_psize; /**< OS page size, from #GET_PAGESIZE */ unsigned int me_maxreaders; /**< size of the reader table */ unsigned int me_numreaders; /**< max numreaders set by this env */ MDB_dbi me_numdbs; /**< number of DBs opened */ MDB_dbi me_maxdbs; /**< size of the DB table */ MDB_PID_T me_pid; /**< process ID of this env */ char *me_path; /**< path to the DB files */ char *me_map; /**< the memory map of the data file */ MDB_txninfo *me_txns; /**< the memory map of the lock file or NULL */ MDB_meta *me_metas[2]; /**< pointers to the two meta pages */ void *me_pbuf; /**< scratch area for DUPSORT put() */ MDB_txn *me_txn; /**< current write transaction */ MDB_txn *me_txn0; /**< prealloc'd write transaction */ size_t me_mapsize; /**< size of the data memory map */ off_t me_size; /**< current file size */ pgno_t me_maxpg; /**< me_mapsize / me_psize */ MDB_dbx *me_dbxs; /**< array of static DB info */ uint16_t *me_dbflags; /**< array of flags from MDB_db.md_flags */ unsigned int *me_dbiseqs; /**< array of dbi sequence numbers */ pthread_key_t me_txkey; /**< thread-key for readers */ txnid_t me_pgoldest; /**< ID of oldest reader last time we looked */ MDB_pgstate me_pgstate; /**< state of old pages from freeDB */ # define me_pglast me_pgstate.mf_pglast # define me_pghead me_pgstate.mf_pghead MDB_page *me_dpages; /**< list of malloc'd blocks for re-use */ /** IDL of pages that became unused in a write txn */ MDB_IDL me_free_pgs; /** ID2L of pages written during a write txn. Length MDB_IDL_UM_SIZE. */ MDB_ID2L me_dirty_list; /** Max number of freelist items that can fit in a single overflow page */ int me_maxfree_1pg; /** Max size of a node on a page */ unsigned int me_nodemax; #if !(MDB_MAXKEYSIZE) unsigned int me_maxkey; /**< max size of a key */ #endif int me_live_reader; /**< have liveness lock in reader table */ #ifdef _WIN32 int me_pidquery; /**< Used in OpenProcess */ HANDLE me_rmutex; /* Windows mutexes don't reside in shared mem */ HANDLE me_wmutex; #elif defined(MDB_USE_POSIX_SEM) sem_t *me_rmutex; /* Shared mutexes are not supported */ sem_t *me_wmutex; #endif void *me_userctx; /**< User-settable context */ MDB_assert_func *me_assert_func; /**< Callback for assertion failures */ }; /** Nested transaction */ typedef struct MDB_ntxn { MDB_txn mnt_txn; /**< the transaction */ MDB_pgstate mnt_pgstate; /**< parent transaction's saved freestate */ } MDB_ntxn; /** max number of pages to commit in one writev() call */ #define MDB_COMMIT_PAGES 64 #if defined(IOV_MAX) && IOV_MAX < MDB_COMMIT_PAGES #undef MDB_COMMIT_PAGES #define MDB_COMMIT_PAGES IOV_MAX #endif /** max bytes to write in one call */ #define MAX_WRITE (0x80000000U >> (sizeof(ssize_t) == 4)) /** Check \b txn and \b dbi arguments to a function */ #define TXN_DBI_EXIST(txn, dbi) \ ((txn) && (dbi) < (txn)->mt_numdbs && ((txn)->mt_dbflags[dbi] & DB_VALID)) /** Check for misused \b dbi handles */ #define TXN_DBI_CHANGED(txn, dbi) \ ((txn)->mt_dbiseqs[dbi] != (txn)->mt_env->me_dbiseqs[dbi]) static int mdb_page_alloc(MDB_cursor *mc, int num, MDB_page **mp); static int mdb_page_new(MDB_cursor *mc, uint32_t flags, int num, MDB_page **mp); static int mdb_page_touch(MDB_cursor *mc); static int mdb_page_get(MDB_txn *txn, pgno_t pgno, MDB_page **mp, int *lvl); static int mdb_page_search_root(MDB_cursor *mc, MDB_val *key, int modify); #define MDB_PS_MODIFY 1 #define MDB_PS_ROOTONLY 2 #define MDB_PS_FIRST 4 #define MDB_PS_LAST 8 static int mdb_page_search(MDB_cursor *mc, MDB_val *key, int flags); static int mdb_page_merge(MDB_cursor *csrc, MDB_cursor *cdst); #define MDB_SPLIT_REPLACE MDB_APPENDDUP /**< newkey is not new */ static int mdb_page_split(MDB_cursor *mc, MDB_val *newkey, MDB_val *newdata, pgno_t newpgno, unsigned int nflags); static int mdb_env_read_header(MDB_env *env, MDB_meta *meta); static int mdb_env_pick_meta(const MDB_env *env); static int mdb_env_write_meta(MDB_txn *txn); #if !(defined(_WIN32) || defined(MDB_USE_POSIX_SEM)) /* Drop unused excl arg */ # define mdb_env_close0(env, excl) mdb_env_close1(env) #endif static void mdb_env_close0(MDB_env *env, int excl); static MDB_node *mdb_node_search(MDB_cursor *mc, MDB_val *key, int *exactp); static int mdb_node_add(MDB_cursor *mc, indx_t indx, MDB_val *key, MDB_val *data, pgno_t pgno, unsigned int flags); static void mdb_node_del(MDB_cursor *mc, int ksize); static void mdb_node_shrink(MDB_page *mp, indx_t indx); static int mdb_node_move(MDB_cursor *csrc, MDB_cursor *cdst); static int mdb_node_read(MDB_txn *txn, MDB_node *leaf, MDB_val *data); static size_t mdb_leaf_size(MDB_env *env, MDB_val *key, MDB_val *data); static size_t mdb_branch_size(MDB_env *env, MDB_val *key); static int mdb_rebalance(MDB_cursor *mc); static int mdb_update_key(MDB_cursor *mc, MDB_val *key); static void mdb_cursor_pop(MDB_cursor *mc); static int mdb_cursor_push(MDB_cursor *mc, MDB_page *mp); static int mdb_cursor_del0(MDB_cursor *mc); static int mdb_del0(MDB_txn *txn, MDB_dbi dbi, MDB_val *key, MDB_val *data, unsigned flags); static int mdb_cursor_sibling(MDB_cursor *mc, int move_right); static int mdb_cursor_next(MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_cursor_op op); static int mdb_cursor_prev(MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_cursor_op op); static int mdb_cursor_set(MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_cursor_op op, int *exactp); static int mdb_cursor_first(MDB_cursor *mc, MDB_val *key, MDB_val *data); static int mdb_cursor_last(MDB_cursor *mc, MDB_val *key, MDB_val *data); static void mdb_cursor_init(MDB_cursor *mc, MDB_txn *txn, MDB_dbi dbi, MDB_xcursor *mx); static void mdb_xcursor_init0(MDB_cursor *mc); static void mdb_xcursor_init1(MDB_cursor *mc, MDB_node *node); static int mdb_drop0(MDB_cursor *mc, int subs); static void mdb_default_cmp(MDB_txn *txn, MDB_dbi dbi); /** @cond */ static MDB_cmp_func mdb_cmp_memn, mdb_cmp_memnr, mdb_cmp_int, mdb_cmp_cint, mdb_cmp_long; /** @endcond */ /** Compare two items pointing at size_t's of unknown alignment. */ #ifdef MISALIGNED_OK # define mdb_cmp_clong mdb_cmp_long #else # define mdb_cmp_clong mdb_cmp_cint #endif #ifdef _WIN32 static SECURITY_DESCRIPTOR mdb_null_sd; static SECURITY_ATTRIBUTES mdb_all_sa; static int mdb_sec_inited; #endif /** Return the library version info. */ char * mdb_version(int *major, int *minor, int *patch) { if (major) *major = MDB_VERSION_MAJOR; if (minor) *minor = MDB_VERSION_MINOR; if (patch) *patch = MDB_VERSION_PATCH; return MDB_VERSION_STRING; } /** Table of descriptions for LMDB @ref errors */ static char *const mdb_errstr[] = { "MDB_KEYEXIST: Key/data pair already exists", "MDB_NOTFOUND: No matching key/data pair found", "MDB_PAGE_NOTFOUND: Requested page not found", "MDB_CORRUPTED: Located page was wrong type", "MDB_PANIC: Update of meta page failed", "MDB_VERSION_MISMATCH: Database environment version mismatch", "MDB_INVALID: File is not an LMDB file", "MDB_MAP_FULL: Environment mapsize limit reached", "MDB_DBS_FULL: Environment maxdbs limit reached", "MDB_READERS_FULL: Environment maxreaders limit reached", "MDB_TLS_FULL: Thread-local storage keys full - too many environments open", "MDB_TXN_FULL: Transaction has too many dirty pages - transaction too big", "MDB_CURSOR_FULL: Internal error - cursor stack limit reached", "MDB_PAGE_FULL: Internal error - page has no more space", "MDB_MAP_RESIZED: Database contents grew beyond environment mapsize", "MDB_INCOMPATIBLE: Operation and DB incompatible, or DB flags changed", "MDB_BAD_RSLOT: Invalid reuse of reader locktable slot", "MDB_BAD_TXN: Transaction cannot recover - it must be aborted", "MDB_BAD_VALSIZE: Unsupported size of key/DB name/data, or wrong DUPFIXED size", "MDB_BAD_DBI: The specified DBI handle was closed/changed unexpectedly", }; char * mdb_strerror(int err) { #ifdef _WIN32 /** HACK: pad 4KB on stack over the buf. Return system msgs in buf. * This works as long as no function between the call to mdb_strerror * and the actual use of the message uses more than 4K of stack. */ char pad[4096]; char buf[1024], *ptr = buf; #endif int i; if (!err) return ("Successful return: 0"); if (err >= MDB_KEYEXIST && err <= MDB_LAST_ERRCODE) { i = err - MDB_KEYEXIST; return mdb_errstr[i]; } #ifdef _WIN32 /* These are the C-runtime error codes we use. The comment indicates * their numeric value, and the Win32 error they would correspond to * if the error actually came from a Win32 API. A major mess, we should * have used LMDB-specific error codes for everything. */ switch(err) { case ENOENT: /* 2, FILE_NOT_FOUND */ case EIO: /* 5, ACCESS_DENIED */ case ENOMEM: /* 12, INVALID_ACCESS */ case EACCES: /* 13, INVALID_DATA */ case EBUSY: /* 16, CURRENT_DIRECTORY */ case EINVAL: /* 22, BAD_COMMAND */ case ENOSPC: /* 28, OUT_OF_PAPER */ return strerror(err); default: ; } buf[0] = 0; FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, 0, ptr, sizeof(buf), (va_list *)pad); return ptr; #else return strerror(err); #endif } /** assert(3) variant in cursor context */ #define mdb_cassert(mc, expr) mdb_assert0((mc)->mc_txn->mt_env, expr, #expr) /** assert(3) variant in transaction context */ #define mdb_tassert(mc, expr) mdb_assert0((txn)->mt_env, expr, #expr) /** assert(3) variant in environment context */ #define mdb_eassert(env, expr) mdb_assert0(env, expr, #expr) #ifndef NDEBUG # define mdb_assert0(env, expr, expr_txt) ((expr) ? (void)0 : \ mdb_assert_fail(env, expr_txt, mdb_func_, __FILE__, __LINE__)) static void mdb_assert_fail(MDB_env *env, const char *expr_txt, const char *func, const char *file, int line) { char buf[400]; sprintf(buf, "%.100s:%d: Assertion '%.200s' failed in %.40s()", file, line, expr_txt, func); if (env->me_assert_func) env->me_assert_func(env, buf); fprintf(stderr, "%s\n", buf); abort(); } #else # define mdb_assert0(env, expr, expr_txt) ((void) 0) #endif /* NDEBUG */ #if MDB_DEBUG /** Return the page number of \b mp which may be sub-page, for debug output */ static pgno_t mdb_dbg_pgno(MDB_page *mp) { pgno_t ret; COPY_PGNO(ret, mp->mp_pgno); return ret; } /** Display a key in hexadecimal and return the address of the result. * @param[in] key the key to display * @param[in] buf the buffer to write into. Should always be #DKBUF. * @return The key in hexadecimal form. */ char * mdb_dkey(MDB_val *key, char *buf) { char *ptr = buf; unsigned char *c = key->mv_data; unsigned int i; if (!key) return ""; if (key->mv_size > DKBUF_MAXKEYSIZE) return "MDB_MAXKEYSIZE"; /* may want to make this a dynamic check: if the key is mostly * printable characters, print it as-is instead of converting to hex. */ #if 1 buf[0] = '\0'; for (i=0; imv_size; i++) ptr += sprintf(ptr, "%02x", *c++); #else sprintf(buf, "%.*s", key->mv_size, key->mv_data); #endif return buf; } static const char * mdb_leafnode_type(MDB_node *n) { static char *const tp[2][2] = {{"", ": DB"}, {": sub-page", ": sub-DB"}}; return F_ISSET(n->mn_flags, F_BIGDATA) ? ": overflow page" : tp[F_ISSET(n->mn_flags, F_DUPDATA)][F_ISSET(n->mn_flags, F_SUBDATA)]; } /** Display all the keys in the page. */ void mdb_page_list(MDB_page *mp) { pgno_t pgno = mdb_dbg_pgno(mp); const char *type, *state = (mp->mp_flags & P_DIRTY) ? ", dirty" : ""; MDB_node *node; unsigned int i, nkeys, nsize, total = 0; MDB_val key; DKBUF; switch (mp->mp_flags & (P_BRANCH|P_LEAF|P_LEAF2|P_META|P_OVERFLOW|P_SUBP)) { case P_BRANCH: type = "Branch page"; break; case P_LEAF: type = "Leaf page"; break; case P_LEAF|P_SUBP: type = "Sub-page"; break; case P_LEAF|P_LEAF2: type = "LEAF2 page"; break; case P_LEAF|P_LEAF2|P_SUBP: type = "LEAF2 sub-page"; break; case P_OVERFLOW: fprintf(stderr, "Overflow page %"Z"u pages %u%s\n", pgno, mp->mp_pages, state); return; case P_META: fprintf(stderr, "Meta-page %"Z"u txnid %"Z"u\n", pgno, ((MDB_meta *)METADATA(mp))->mm_txnid); return; default: fprintf(stderr, "Bad page %"Z"u flags 0x%u\n", pgno, mp->mp_flags); return; } nkeys = NUMKEYS(mp); fprintf(stderr, "%s %"Z"u numkeys %d%s\n", type, pgno, nkeys, state); for (i=0; imp_pad; key.mv_data = LEAF2KEY(mp, i, nsize); total += nsize; fprintf(stderr, "key %d: nsize %d, %s\n", i, nsize, DKEY(&key)); continue; } node = NODEPTR(mp, i); key.mv_size = node->mn_ksize; key.mv_data = node->mn_data; nsize = NODESIZE + key.mv_size; if (IS_BRANCH(mp)) { fprintf(stderr, "key %d: page %"Z"u, %s\n", i, NODEPGNO(node), DKEY(&key)); total += nsize; } else { if (F_ISSET(node->mn_flags, F_BIGDATA)) nsize += sizeof(pgno_t); else nsize += NODEDSZ(node); total += nsize; nsize += sizeof(indx_t); fprintf(stderr, "key %d: nsize %d, %s%s\n", i, nsize, DKEY(&key), mdb_leafnode_type(node)); } total = EVEN(total); } fprintf(stderr, "Total: header %d + contents %d + unused %d\n", IS_LEAF2(mp) ? PAGEHDRSZ : PAGEBASE + mp->mp_lower, total, SIZELEFT(mp)); } void mdb_cursor_chk(MDB_cursor *mc) { unsigned int i; MDB_node *node; MDB_page *mp; if (!mc->mc_snum && !(mc->mc_flags & C_INITIALIZED)) return; for (i=0; imc_top; i++) { mp = mc->mc_pg[i]; node = NODEPTR(mp, mc->mc_ki[i]); if (NODEPGNO(node) != mc->mc_pg[i+1]->mp_pgno) printf("oops!\n"); } if (mc->mc_ki[i] >= NUMKEYS(mc->mc_pg[i])) printf("ack!\n"); } #endif #if (MDB_DEBUG) > 2 /** Count all the pages in each DB and in the freelist * and make sure it matches the actual number of pages * being used. * All named DBs must be open for a correct count. */ static void mdb_audit(MDB_txn *txn) { MDB_cursor mc; MDB_val key, data; MDB_ID freecount, count; MDB_dbi i; int rc; freecount = 0; mdb_cursor_init(&mc, txn, FREE_DBI, NULL); while ((rc = mdb_cursor_get(&mc, &key, &data, MDB_NEXT)) == 0) freecount += *(MDB_ID *)data.mv_data; mdb_tassert(txn, rc == MDB_NOTFOUND); count = 0; for (i = 0; imt_numdbs; i++) { MDB_xcursor mx; if (!(txn->mt_dbflags[i] & DB_VALID)) continue; mdb_cursor_init(&mc, txn, i, &mx); if (txn->mt_dbs[i].md_root == P_INVALID) continue; count += txn->mt_dbs[i].md_branch_pages + txn->mt_dbs[i].md_leaf_pages + txn->mt_dbs[i].md_overflow_pages; if (txn->mt_dbs[i].md_flags & MDB_DUPSORT) { rc = mdb_page_search(&mc, NULL, MDB_PS_FIRST); for (; rc == MDB_SUCCESS; rc = mdb_cursor_sibling(&mc, 1)) { unsigned j; MDB_page *mp; mp = mc.mc_pg[mc.mc_top]; for (j=0; jmn_flags & F_SUBDATA) { MDB_db db; memcpy(&db, NODEDATA(leaf), sizeof(db)); count += db.md_branch_pages + db.md_leaf_pages + db.md_overflow_pages; } } } mdb_tassert(txn, rc == MDB_NOTFOUND); } } if (freecount + count + 2 /* metapages */ != txn->mt_next_pgno) { fprintf(stderr, "audit: %lu freecount: %lu count: %lu total: %lu next_pgno: %lu\n", txn->mt_txnid, freecount, count+2, freecount+count+2, txn->mt_next_pgno); } } #endif int mdb_cmp(MDB_txn *txn, MDB_dbi dbi, const MDB_val *a, const MDB_val *b) { return txn->mt_dbxs[dbi].md_cmp(a, b); } int mdb_dcmp(MDB_txn *txn, MDB_dbi dbi, const MDB_val *a, const MDB_val *b) { MDB_cmp_func *dcmp = txn->mt_dbxs[dbi].md_dcmp; #if UINT_MAX < SIZE_MAX if (dcmp == mdb_cmp_int && a->mv_size == sizeof(size_t)) dcmp = mdb_cmp_clong; #endif return dcmp(a, b); } /** Allocate memory for a page. * Re-use old malloc'd pages first for singletons, otherwise just malloc. */ static MDB_page * mdb_page_malloc(MDB_txn *txn, unsigned num) { MDB_env *env = txn->mt_env; MDB_page *ret = env->me_dpages; size_t psize = env->me_psize, sz = psize, off; /* For ! #MDB_NOMEMINIT, psize counts how much to init. * For a single page alloc, we init everything after the page header. * For multi-page, we init the final page; if the caller needed that * many pages they will be filling in at least up to the last page. */ if (num == 1) { if (ret) { VGMEMP_ALLOC(env, ret, sz); VGMEMP_DEFINED(ret, sizeof(ret->mp_next)); env->me_dpages = ret->mp_next; return ret; } psize -= off = PAGEHDRSZ; } else { sz *= num; off = sz - psize; } if ((ret = malloc(sz)) != NULL) { VGMEMP_ALLOC(env, ret, sz); if (!(env->me_flags & MDB_NOMEMINIT)) { memset((char *)ret + off, 0, psize); ret->mp_pad = 0; } } else { txn->mt_flags |= MDB_TXN_ERROR; } return ret; } /** Free a single page. * Saves single pages to a list, for future reuse. * (This is not used for multi-page overflow pages.) */ static void mdb_page_free(MDB_env *env, MDB_page *mp) { mp->mp_next = env->me_dpages; VGMEMP_FREE(env, mp); env->me_dpages = mp; } /** Free a dirty page */ static void mdb_dpage_free(MDB_env *env, MDB_page *dp) { if (!IS_OVERFLOW(dp) || dp->mp_pages == 1) { mdb_page_free(env, dp); } else { /* large pages just get freed directly */ VGMEMP_FREE(env, dp); free(dp); } } /** Return all dirty pages to dpage list */ static void mdb_dlist_free(MDB_txn *txn) { MDB_env *env = txn->mt_env; MDB_ID2L dl = txn->mt_u.dirty_list; unsigned i, n = dl[0].mid; for (i = 1; i <= n; i++) { mdb_dpage_free(env, dl[i].mptr); } dl[0].mid = 0; } /** Loosen or free a single page. * Saves single pages to a list for future reuse * in this same txn. It has been pulled from the freeDB * and already resides on the dirty list, but has been * deleted. Use these pages first before pulling again * from the freeDB. * * If the page wasn't dirtied in this txn, just add it * to this txn's free list. */ static int mdb_page_loose(MDB_cursor *mc, MDB_page *mp) { int loose = 0; pgno_t pgno = mp->mp_pgno; MDB_txn *txn = mc->mc_txn; if ((mp->mp_flags & P_DIRTY) && mc->mc_dbi != FREE_DBI) { if (txn->mt_parent) { MDB_ID2 *dl = txn->mt_u.dirty_list; /* If txn has a parent, make sure the page is in our * dirty list. */ if (dl[0].mid) { unsigned x = mdb_mid2l_search(dl, pgno); if (x <= dl[0].mid && dl[x].mid == pgno) { if (mp != dl[x].mptr) { /* bad cursor? */ mc->mc_flags &= ~(C_INITIALIZED|C_EOF); txn->mt_flags |= MDB_TXN_ERROR; return MDB_CORRUPTED; } /* ok, it's ours */ loose = 1; } } } else { /* no parent txn, so it's just ours */ loose = 1; } } if (loose) { DPRINTF(("loosen db %d page %"Z"u", DDBI(mc), mp->mp_pgno)); NEXT_LOOSE_PAGE(mp) = txn->mt_loose_pgs; txn->mt_loose_pgs = mp; txn->mt_loose_count++; mp->mp_flags |= P_LOOSE; } else { int rc = mdb_midl_append(&txn->mt_free_pgs, pgno); if (rc) return rc; } return MDB_SUCCESS; } /** Set or clear P_KEEP in dirty, non-overflow, non-sub pages watched by txn. * @param[in] mc A cursor handle for the current operation. * @param[in] pflags Flags of the pages to update: * P_DIRTY to set P_KEEP, P_DIRTY|P_KEEP to clear it. * @param[in] all No shortcuts. Needed except after a full #mdb_page_flush(). * @return 0 on success, non-zero on failure. */ static int mdb_pages_xkeep(MDB_cursor *mc, unsigned pflags, int all) { enum { Mask = P_SUBP|P_DIRTY|P_LOOSE|P_KEEP }; MDB_txn *txn = mc->mc_txn; MDB_cursor *m3; MDB_xcursor *mx; MDB_page *dp, *mp; MDB_node *leaf; unsigned i, j; int rc = MDB_SUCCESS, level; /* Mark pages seen by cursors */ if (mc->mc_flags & C_UNTRACK) mc = NULL; /* will find mc in mt_cursors */ for (i = txn->mt_numdbs;; mc = txn->mt_cursors[--i]) { for (; mc; mc=mc->mc_next) { if (!(mc->mc_flags & C_INITIALIZED)) continue; for (m3 = mc;; m3 = &mx->mx_cursor) { mp = NULL; for (j=0; jmc_snum; j++) { mp = m3->mc_pg[j]; if ((mp->mp_flags & Mask) == pflags) mp->mp_flags ^= P_KEEP; } mx = m3->mc_xcursor; /* Proceed to mx if it is at a sub-database */ if (! (mx && (mx->mx_cursor.mc_flags & C_INITIALIZED))) break; if (! (mp && (mp->mp_flags & P_LEAF))) break; leaf = NODEPTR(mp, m3->mc_ki[j-1]); if (!(leaf->mn_flags & F_SUBDATA)) break; } } if (i == 0) break; } if (all) { /* Mark dirty root pages */ for (i=0; imt_numdbs; i++) { if (txn->mt_dbflags[i] & DB_DIRTY) { pgno_t pgno = txn->mt_dbs[i].md_root; if (pgno == P_INVALID) continue; if ((rc = mdb_page_get(txn, pgno, &dp, &level)) != MDB_SUCCESS) break; if ((dp->mp_flags & Mask) == pflags && level <= 1) dp->mp_flags ^= P_KEEP; } } } return rc; } static int mdb_page_flush(MDB_txn *txn, int keep); /** Spill pages from the dirty list back to disk. * This is intended to prevent running into #MDB_TXN_FULL situations, * but note that they may still occur in a few cases: * 1) our estimate of the txn size could be too small. Currently this * seems unlikely, except with a large number of #MDB_MULTIPLE items. * 2) child txns may run out of space if their parents dirtied a * lot of pages and never spilled them. TODO: we probably should do * a preemptive spill during #mdb_txn_begin() of a child txn, if * the parent's dirty_room is below a given threshold. * * Otherwise, if not using nested txns, it is expected that apps will * not run into #MDB_TXN_FULL any more. The pages are flushed to disk * the same way as for a txn commit, e.g. their P_DIRTY flag is cleared. * If the txn never references them again, they can be left alone. * If the txn only reads them, they can be used without any fuss. * If the txn writes them again, they can be dirtied immediately without * going thru all of the work of #mdb_page_touch(). Such references are * handled by #mdb_page_unspill(). * * Also note, we never spill DB root pages, nor pages of active cursors, * because we'll need these back again soon anyway. And in nested txns, * we can't spill a page in a child txn if it was already spilled in a * parent txn. That would alter the parent txns' data even though * the child hasn't committed yet, and we'd have no way to undo it if * the child aborted. * * @param[in] m0 cursor A cursor handle identifying the transaction and * database for which we are checking space. * @param[in] key For a put operation, the key being stored. * @param[in] data For a put operation, the data being stored. * @return 0 on success, non-zero on failure. */ static int mdb_page_spill(MDB_cursor *m0, MDB_val *key, MDB_val *data) { MDB_txn *txn = m0->mc_txn; MDB_page *dp; MDB_ID2L dl = txn->mt_u.dirty_list; unsigned int i, j, need; int rc; if (m0->mc_flags & C_SUB) return MDB_SUCCESS; /* Estimate how much space this op will take */ i = m0->mc_db->md_depth; /* Named DBs also dirty the main DB */ if (m0->mc_dbi > MAIN_DBI) i += txn->mt_dbs[MAIN_DBI].md_depth; /* For puts, roughly factor in the key+data size */ if (key) i += (LEAFSIZE(key, data) + txn->mt_env->me_psize) / txn->mt_env->me_psize; i += i; /* double it for good measure */ need = i; if (txn->mt_dirty_room > i) return MDB_SUCCESS; if (!txn->mt_spill_pgs) { txn->mt_spill_pgs = mdb_midl_alloc(MDB_IDL_UM_MAX); if (!txn->mt_spill_pgs) return ENOMEM; } else { /* purge deleted slots */ MDB_IDL sl = txn->mt_spill_pgs; unsigned int num = sl[0]; j=0; for (i=1; i<=num; i++) { if (!(sl[i] & 1)) sl[++j] = sl[i]; } sl[0] = j; } /* Preserve pages which may soon be dirtied again */ if ((rc = mdb_pages_xkeep(m0, P_DIRTY, 1)) != MDB_SUCCESS) goto done; /* Less aggressive spill - we originally spilled the entire dirty list, * with a few exceptions for cursor pages and DB root pages. But this * turns out to be a lot of wasted effort because in a large txn many * of those pages will need to be used again. So now we spill only 1/8th * of the dirty pages. Testing revealed this to be a good tradeoff, * better than 1/2, 1/4, or 1/10. */ if (need < MDB_IDL_UM_MAX / 8) need = MDB_IDL_UM_MAX / 8; /* Save the page IDs of all the pages we're flushing */ /* flush from the tail forward, this saves a lot of shifting later on. */ for (i=dl[0].mid; i && need; i--) { MDB_ID pn = dl[i].mid << 1; dp = dl[i].mptr; if (dp->mp_flags & (P_LOOSE|P_KEEP)) continue; /* Can't spill twice, make sure it's not already in a parent's * spill list. */ if (txn->mt_parent) { MDB_txn *tx2; for (tx2 = txn->mt_parent; tx2; tx2 = tx2->mt_parent) { if (tx2->mt_spill_pgs) { j = mdb_midl_search(tx2->mt_spill_pgs, pn); if (j <= tx2->mt_spill_pgs[0] && tx2->mt_spill_pgs[j] == pn) { dp->mp_flags |= P_KEEP; break; } } } if (tx2) continue; } if ((rc = mdb_midl_append(&txn->mt_spill_pgs, pn))) goto done; need--; } mdb_midl_sort(txn->mt_spill_pgs); /* Flush the spilled part of dirty list */ if ((rc = mdb_page_flush(txn, i)) != MDB_SUCCESS) goto done; /* Reset any dirty pages we kept that page_flush didn't see */ rc = mdb_pages_xkeep(m0, P_DIRTY|P_KEEP, i); done: txn->mt_flags |= rc ? MDB_TXN_ERROR : MDB_TXN_SPILLS; return rc; } /** Find oldest txnid still referenced. Expects txn->mt_txnid > 0. */ static txnid_t mdb_find_oldest(MDB_txn *txn) { int i; txnid_t mr, oldest = txn->mt_txnid - 1; if (txn->mt_env->me_txns) { MDB_reader *r = txn->mt_env->me_txns->mti_readers; for (i = txn->mt_env->me_txns->mti_numreaders; --i >= 0; ) { if (r[i].mr_pid) { mr = r[i].mr_txnid; if (oldest > mr) oldest = mr; } } } return oldest; } /** Add a page to the txn's dirty list */ static void mdb_page_dirty(MDB_txn *txn, MDB_page *mp) { MDB_ID2 mid; int rc, (*insert)(MDB_ID2L, MDB_ID2 *); if (txn->mt_env->me_flags & MDB_WRITEMAP) { insert = mdb_mid2l_append; } else { insert = mdb_mid2l_insert; } mid.mid = mp->mp_pgno; mid.mptr = mp; rc = insert(txn->mt_u.dirty_list, &mid); mdb_tassert(txn, rc == 0); txn->mt_dirty_room--; } /** Allocate page numbers and memory for writing. Maintain me_pglast, * me_pghead and mt_next_pgno. * * If there are free pages available from older transactions, they * are re-used first. Otherwise allocate a new page at mt_next_pgno. * Do not modify the freedB, just merge freeDB records into me_pghead[] * and move me_pglast to say which records were consumed. Only this * function can create me_pghead and move me_pglast/mt_next_pgno. * @param[in] mc cursor A cursor handle identifying the transaction and * database for which we are allocating. * @param[in] num the number of pages to allocate. * @param[out] mp Address of the allocated page(s). Requests for multiple pages * will always be satisfied by a single contiguous chunk of memory. * @return 0 on success, non-zero on failure. */ static int mdb_page_alloc(MDB_cursor *mc, int num, MDB_page **mp) { #ifdef MDB_PARANOID /* Seems like we can ignore this now */ /* Get at most more freeDB records once me_pghead * has enough pages. If not enough, use new pages from the map. * If and mc is updating the freeDB, only get new * records if me_pghead is empty. Then the freelist cannot play * catch-up with itself by growing while trying to save it. */ enum { Paranoid = 1, Max_retries = 500 }; #else enum { Paranoid = 0, Max_retries = INT_MAX /*infinite*/ }; #endif int rc, retry = num * 60; MDB_txn *txn = mc->mc_txn; MDB_env *env = txn->mt_env; pgno_t pgno, *mop = env->me_pghead; unsigned i, j, mop_len = mop ? mop[0] : 0, n2 = num-1; MDB_page *np; txnid_t oldest = 0, last; MDB_cursor_op op; MDB_cursor m2; int found_old = 0; /* If there are any loose pages, just use them */ if (num == 1 && txn->mt_loose_pgs) { np = txn->mt_loose_pgs; txn->mt_loose_pgs = NEXT_LOOSE_PAGE(np); txn->mt_loose_count--; DPRINTF(("db %d use loose page %"Z"u", DDBI(mc), np->mp_pgno)); *mp = np; return MDB_SUCCESS; } *mp = NULL; /* If our dirty list is already full, we can't do anything */ if (txn->mt_dirty_room == 0) { rc = MDB_TXN_FULL; goto fail; } for (op = MDB_FIRST;; op = MDB_NEXT) { MDB_val key, data; MDB_node *leaf; pgno_t *idl; /* Seek a big enough contiguous page range. Prefer * pages at the tail, just truncating the list. */ if (mop_len > n2) { i = mop_len; do { pgno = mop[i]; if (mop[i-n2] == pgno+n2) goto search_done; } while (--i > n2); if (--retry < 0) break; } if (op == MDB_FIRST) { /* 1st iteration */ /* Prepare to fetch more and coalesce */ last = env->me_pglast; oldest = env->me_pgoldest; mdb_cursor_init(&m2, txn, FREE_DBI, NULL); if (last) { op = MDB_SET_RANGE; key.mv_data = &last; /* will look up last+1 */ key.mv_size = sizeof(last); } if (Paranoid && mc->mc_dbi == FREE_DBI) retry = -1; } if (Paranoid && retry < 0 && mop_len) break; last++; /* Do not fetch more if the record will be too recent */ if (oldest <= last) { if (!found_old) { oldest = mdb_find_oldest(txn); env->me_pgoldest = oldest; found_old = 1; } if (oldest <= last) break; } rc = mdb_cursor_get(&m2, &key, NULL, op); if (rc) { if (rc == MDB_NOTFOUND) break; goto fail; } last = *(txnid_t*)key.mv_data; if (oldest <= last) { if (!found_old) { oldest = mdb_find_oldest(txn); env->me_pgoldest = oldest; found_old = 1; } if (oldest <= last) break; } np = m2.mc_pg[m2.mc_top]; leaf = NODEPTR(np, m2.mc_ki[m2.mc_top]); if ((rc = mdb_node_read(txn, leaf, &data)) != MDB_SUCCESS) return rc; idl = (MDB_ID *) data.mv_data; i = idl[0]; if (!mop) { if (!(env->me_pghead = mop = mdb_midl_alloc(i))) { rc = ENOMEM; goto fail; } } else { if ((rc = mdb_midl_need(&env->me_pghead, i)) != 0) goto fail; mop = env->me_pghead; } env->me_pglast = last; #if (MDB_DEBUG) > 1 DPRINTF(("IDL read txn %"Z"u root %"Z"u num %u", last, txn->mt_dbs[FREE_DBI].md_root, i)); for (j = i; j; j--) DPRINTF(("IDL %"Z"u", idl[j])); #endif /* Merge in descending sorted order */ mdb_midl_xmerge(mop, idl); mop_len = mop[0]; } /* Use new pages from the map when nothing suitable in the freeDB */ i = 0; pgno = txn->mt_next_pgno; if (pgno + num >= env->me_maxpg) { DPUTS("DB size maxed out"); rc = MDB_MAP_FULL; goto fail; } search_done: if (env->me_flags & MDB_WRITEMAP) { np = (MDB_page *)(env->me_map + env->me_psize * pgno); } else { if (!(np = mdb_page_malloc(txn, num))) { rc = ENOMEM; goto fail; } } if (i) { mop[0] = mop_len -= num; /* Move any stragglers down */ for (j = i-num; j < mop_len; ) mop[++j] = mop[++i]; } else { txn->mt_next_pgno = pgno + num; } np->mp_pgno = pgno; mdb_page_dirty(txn, np); *mp = np; return MDB_SUCCESS; fail: txn->mt_flags |= MDB_TXN_ERROR; return rc; } /** Copy the used portions of a non-overflow page. * @param[in] dst page to copy into * @param[in] src page to copy from * @param[in] psize size of a page */ static void mdb_page_copy(MDB_page *dst, MDB_page *src, unsigned int psize) { enum { Align = sizeof(pgno_t) }; indx_t upper = src->mp_upper, lower = src->mp_lower, unused = upper-lower; /* If page isn't full, just copy the used portion. Adjust * alignment so memcpy may copy words instead of bytes. */ if ((unused &= -Align) && !IS_LEAF2(src)) { upper = (upper + PAGEBASE) & -Align; memcpy(dst, src, (lower + PAGEBASE + (Align-1)) & -Align); memcpy((pgno_t *)((char *)dst+upper), (pgno_t *)((char *)src+upper), psize - upper); } else { memcpy(dst, src, psize - unused); } } /** Pull a page off the txn's spill list, if present. * If a page being referenced was spilled to disk in this txn, bring * it back and make it dirty/writable again. * @param[in] txn the transaction handle. * @param[in] mp the page being referenced. It must not be dirty. * @param[out] ret the writable page, if any. ret is unchanged if * mp wasn't spilled. */ static int mdb_page_unspill(MDB_txn *txn, MDB_page *mp, MDB_page **ret) { MDB_env *env = txn->mt_env; const MDB_txn *tx2; unsigned x; pgno_t pgno = mp->mp_pgno, pn = pgno << 1; for (tx2 = txn; tx2; tx2=tx2->mt_parent) { if (!tx2->mt_spill_pgs) continue; x = mdb_midl_search(tx2->mt_spill_pgs, pn); if (x <= tx2->mt_spill_pgs[0] && tx2->mt_spill_pgs[x] == pn) { MDB_page *np; int num; if (txn->mt_dirty_room == 0) return MDB_TXN_FULL; if (IS_OVERFLOW(mp)) num = mp->mp_pages; else num = 1; if (env->me_flags & MDB_WRITEMAP) { np = mp; } else { np = mdb_page_malloc(txn, num); if (!np) return ENOMEM; if (num > 1) memcpy(np, mp, num * env->me_psize); else mdb_page_copy(np, mp, env->me_psize); } if (tx2 == txn) { /* If in current txn, this page is no longer spilled. * If it happens to be the last page, truncate the spill list. * Otherwise mark it as deleted by setting the LSB. */ if (x == txn->mt_spill_pgs[0]) txn->mt_spill_pgs[0]--; else txn->mt_spill_pgs[x] |= 1; } /* otherwise, if belonging to a parent txn, the * page remains spilled until child commits */ mdb_page_dirty(txn, np); np->mp_flags |= P_DIRTY; *ret = np; break; } } return MDB_SUCCESS; } /** Touch a page: make it dirty and re-insert into tree with updated pgno. * @param[in] mc cursor pointing to the page to be touched * @return 0 on success, non-zero on failure. */ static int mdb_page_touch(MDB_cursor *mc) { MDB_page *mp = mc->mc_pg[mc->mc_top], *np; MDB_txn *txn = mc->mc_txn; MDB_cursor *m2, *m3; pgno_t pgno; int rc; if (!F_ISSET(mp->mp_flags, P_DIRTY)) { if (txn->mt_flags & MDB_TXN_SPILLS) { np = NULL; rc = mdb_page_unspill(txn, mp, &np); if (rc) goto fail; if (np) goto done; } if ((rc = mdb_midl_need(&txn->mt_free_pgs, 1)) || (rc = mdb_page_alloc(mc, 1, &np))) goto fail; pgno = np->mp_pgno; DPRINTF(("touched db %d page %"Z"u -> %"Z"u", DDBI(mc), mp->mp_pgno, pgno)); mdb_cassert(mc, mp->mp_pgno != pgno); mdb_midl_xappend(txn->mt_free_pgs, mp->mp_pgno); /* Update the parent page, if any, to point to the new page */ if (mc->mc_top) { MDB_page *parent = mc->mc_pg[mc->mc_top-1]; MDB_node *node = NODEPTR(parent, mc->mc_ki[mc->mc_top-1]); SETPGNO(node, pgno); } else { mc->mc_db->md_root = pgno; } } else if (txn->mt_parent && !IS_SUBP(mp)) { MDB_ID2 mid, *dl = txn->mt_u.dirty_list; pgno = mp->mp_pgno; /* If txn has a parent, make sure the page is in our * dirty list. */ if (dl[0].mid) { unsigned x = mdb_mid2l_search(dl, pgno); if (x <= dl[0].mid && dl[x].mid == pgno) { if (mp != dl[x].mptr) { /* bad cursor? */ mc->mc_flags &= ~(C_INITIALIZED|C_EOF); txn->mt_flags |= MDB_TXN_ERROR; return MDB_CORRUPTED; } return 0; } } mdb_cassert(mc, dl[0].mid < MDB_IDL_UM_MAX); /* No - copy it */ np = mdb_page_malloc(txn, 1); if (!np) return ENOMEM; mid.mid = pgno; mid.mptr = np; rc = mdb_mid2l_insert(dl, &mid); mdb_cassert(mc, rc == 0); } else { return 0; } mdb_page_copy(np, mp, txn->mt_env->me_psize); np->mp_pgno = pgno; np->mp_flags |= P_DIRTY; done: /* Adjust cursors pointing to mp */ mc->mc_pg[mc->mc_top] = np; m2 = txn->mt_cursors[mc->mc_dbi]; if (mc->mc_flags & C_SUB) { for (; m2; m2=m2->mc_next) { m3 = &m2->mc_xcursor->mx_cursor; if (m3->mc_snum < mc->mc_snum) continue; if (m3->mc_pg[mc->mc_top] == mp) m3->mc_pg[mc->mc_top] = np; } } else { for (; m2; m2=m2->mc_next) { if (m2->mc_snum < mc->mc_snum) continue; if (m2->mc_pg[mc->mc_top] == mp) { m2->mc_pg[mc->mc_top] = np; if ((mc->mc_db->md_flags & MDB_DUPSORT) && IS_LEAF(np) && m2->mc_ki[mc->mc_top] == mc->mc_ki[mc->mc_top]) { MDB_node *leaf = NODEPTR(np, mc->mc_ki[mc->mc_top]); if (!(leaf->mn_flags & F_SUBDATA)) m2->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(leaf); } } } } return 0; fail: txn->mt_flags |= MDB_TXN_ERROR; return rc; } int mdb_env_sync(MDB_env *env, int force) { int rc = 0; if (env->me_flags & MDB_RDONLY) return EACCES; if (force || !F_ISSET(env->me_flags, MDB_NOSYNC)) { if (env->me_flags & MDB_WRITEMAP) { int flags = ((env->me_flags & MDB_MAPASYNC) && !force) ? MS_ASYNC : MS_SYNC; if (MDB_MSYNC(env->me_map, env->me_mapsize, flags)) rc = ErrCode(); #ifdef _WIN32 else if (flags == MS_SYNC && MDB_FDATASYNC(env->me_fd)) rc = ErrCode(); #endif } else { #ifdef BROKEN_FDATASYNC if (env->me_flags & MDB_FSYNCONLY) { if (fsync(env->me_fd)) rc = ErrCode(); } else #endif if (MDB_FDATASYNC(env->me_fd)) rc = ErrCode(); } } return rc; } /** Back up parent txn's cursors, then grab the originals for tracking */ static int mdb_cursor_shadow(MDB_txn *src, MDB_txn *dst) { MDB_cursor *mc, *bk; MDB_xcursor *mx; size_t size; int i; for (i = src->mt_numdbs; --i >= 0; ) { if ((mc = src->mt_cursors[i]) != NULL) { size = sizeof(MDB_cursor); if (mc->mc_xcursor) size += sizeof(MDB_xcursor); for (; mc; mc = bk->mc_next) { bk = malloc(size); if (!bk) return ENOMEM; *bk = *mc; mc->mc_backup = bk; mc->mc_db = &dst->mt_dbs[i]; /* Kill pointers into src - and dst to reduce abuse: The * user may not use mc until dst ends. Otherwise we'd... */ mc->mc_txn = NULL; /* ...set this to dst */ mc->mc_dbflag = NULL; /* ...and &dst->mt_dbflags[i] */ if ((mx = mc->mc_xcursor) != NULL) { *(MDB_xcursor *)(bk+1) = *mx; mx->mx_cursor.mc_txn = NULL; /* ...and dst. */ } mc->mc_next = dst->mt_cursors[i]; dst->mt_cursors[i] = mc; } } } return MDB_SUCCESS; } /** Close this write txn's cursors, give parent txn's cursors back to parent. * @param[in] txn the transaction handle. * @param[in] merge true to keep changes to parent cursors, false to revert. * @return 0 on success, non-zero on failure. */ static void mdb_cursors_close(MDB_txn *txn, unsigned merge) { MDB_cursor **cursors = txn->mt_cursors, *mc, *next, *bk; MDB_xcursor *mx; int i; for (i = txn->mt_numdbs; --i >= 0; ) { for (mc = cursors[i]; mc; mc = next) { next = mc->mc_next; if ((bk = mc->mc_backup) != NULL) { if (merge) { /* Commit changes to parent txn */ mc->mc_next = bk->mc_next; mc->mc_backup = bk->mc_backup; mc->mc_txn = bk->mc_txn; mc->mc_db = bk->mc_db; mc->mc_dbflag = bk->mc_dbflag; if ((mx = mc->mc_xcursor) != NULL) mx->mx_cursor.mc_txn = bk->mc_txn; } else { /* Abort nested txn */ *mc = *bk; if ((mx = mc->mc_xcursor) != NULL) *mx = *(MDB_xcursor *)(bk+1); } mc = bk; } /* Only malloced cursors are permanently tracked. */ free(mc); } cursors[i] = NULL; } } #if !(MDB_DEBUG) #define mdb_txn_reset0(txn, act) mdb_txn_reset0(txn) #endif static void mdb_txn_reset0(MDB_txn *txn, const char *act); #if !(MDB_PIDLOCK) /* Currently the same as defined(_WIN32) */ enum Pidlock_op { Pidset, Pidcheck }; #else enum Pidlock_op { Pidset = F_SETLK, Pidcheck = F_GETLK }; #endif /** Set or check a pid lock. Set returns 0 on success. * Check returns 0 if the process is certainly dead, nonzero if it may * be alive (the lock exists or an error happened so we do not know). * * On Windows Pidset is a no-op, we merely check for the existence * of the process with the given pid. On POSIX we use a single byte * lock on the lockfile, set at an offset equal to the pid. */ static int mdb_reader_pid(MDB_env *env, enum Pidlock_op op, MDB_PID_T pid) { #if !(MDB_PIDLOCK) /* Currently the same as defined(_WIN32) */ int ret = 0; HANDLE h; if (op == Pidcheck) { h = OpenProcess(env->me_pidquery, FALSE, pid); /* No documented "no such process" code, but other program use this: */ if (!h) return ErrCode() != ERROR_INVALID_PARAMETER; /* A process exists until all handles to it close. Has it exited? */ ret = WaitForSingleObject(h, 0) != 0; CloseHandle(h); } return ret; #else for (;;) { int rc; struct flock lock_info; memset(&lock_info, 0, sizeof(lock_info)); lock_info.l_type = F_WRLCK; lock_info.l_whence = SEEK_SET; lock_info.l_start = pid; lock_info.l_len = 1; if ((rc = fcntl(env->me_lfd, op, &lock_info)) == 0) { if (op == F_GETLK && lock_info.l_type != F_UNLCK) rc = -1; } else if ((rc = ErrCode()) == EINTR) { continue; } return rc; } #endif } /** Common code for #mdb_txn_begin() and #mdb_txn_renew(). * @param[in] txn the transaction handle to initialize * @return 0 on success, non-zero on failure. */ static int mdb_txn_renew0(MDB_txn *txn) { MDB_env *env = txn->mt_env; MDB_txninfo *ti = env->me_txns; MDB_meta *meta; unsigned int i, nr, flags = txn->mt_flags; uint16_t x; int rc, new_notls = 0; if ((flags &= MDB_TXN_RDONLY) != 0) { if (!ti) { meta = env->me_metas[ mdb_env_pick_meta(env) ]; txn->mt_txnid = meta->mm_txnid; txn->mt_u.reader = NULL; } else { MDB_reader *r = (env->me_flags & MDB_NOTLS) ? txn->mt_u.reader : pthread_getspecific(env->me_txkey); if (r) { if (r->mr_pid != env->me_pid || r->mr_txnid != (txnid_t)-1) return MDB_BAD_RSLOT; } else { MDB_PID_T pid = env->me_pid; MDB_THR_T tid = pthread_self(); if (!env->me_live_reader) { rc = mdb_reader_pid(env, Pidset, pid); if (rc) return rc; env->me_live_reader = 1; } LOCK_MUTEX_R(env); nr = ti->mti_numreaders; for (i=0; imti_readers[i].mr_pid == 0) break; if (i == env->me_maxreaders) { UNLOCK_MUTEX_R(env); return MDB_READERS_FULL; } ti->mti_readers[i].mr_pid = pid; ti->mti_readers[i].mr_tid = tid; if (i == nr) ti->mti_numreaders = ++nr; /* Save numreaders for un-mutexed mdb_env_close() */ env->me_numreaders = nr; UNLOCK_MUTEX_R(env); r = &ti->mti_readers[i]; new_notls = (env->me_flags & MDB_NOTLS); if (!new_notls && (rc=pthread_setspecific(env->me_txkey, r))) { r->mr_pid = 0; return rc; } } do /* LY: Retry on a race, ITS#7970. */ r->mr_txnid = ti->mti_txnid; while(r->mr_txnid != ti->mti_txnid); txn->mt_txnid = r->mr_txnid; txn->mt_u.reader = r; meta = env->me_metas[txn->mt_txnid & 1]; } txn->mt_dbxs = env->me_dbxs; /* mostly static anyway */ } else { if (ti) { LOCK_MUTEX_W(env); txn->mt_txnid = ti->mti_txnid; meta = env->me_metas[txn->mt_txnid & 1]; } else { meta = env->me_metas[ mdb_env_pick_meta(env) ]; txn->mt_txnid = meta->mm_txnid; } txn->mt_txnid++; #if MDB_DEBUG if (txn->mt_txnid == mdb_debug_start) mdb_debug = 1; #endif txn->mt_child = NULL; txn->mt_loose_pgs = NULL; txn->mt_loose_count = 0; txn->mt_dirty_room = MDB_IDL_UM_MAX; txn->mt_u.dirty_list = env->me_dirty_list; txn->mt_u.dirty_list[0].mid = 0; txn->mt_free_pgs = env->me_free_pgs; txn->mt_free_pgs[0] = 0; txn->mt_spill_pgs = NULL; env->me_txn = txn; memcpy(txn->mt_dbiseqs, env->me_dbiseqs, env->me_maxdbs * sizeof(unsigned int)); } /* Copy the DB info and flags */ memcpy(txn->mt_dbs, meta->mm_dbs, 2 * sizeof(MDB_db)); /* Moved to here to avoid a data race in read TXNs */ txn->mt_next_pgno = meta->mm_last_pg+1; txn->mt_flags = flags; /* Setup db info */ txn->mt_numdbs = env->me_numdbs; for (i=2; imt_numdbs; i++) { x = env->me_dbflags[i]; txn->mt_dbs[i].md_flags = x & PERSISTENT_FLAGS; txn->mt_dbflags[i] = (x & MDB_VALID) ? DB_VALID|DB_STALE : 0; } txn->mt_dbflags[0] = txn->mt_dbflags[1] = DB_VALID; if (env->me_maxpg < txn->mt_next_pgno) { mdb_txn_reset0(txn, "renew0-mapfail"); if (new_notls) { txn->mt_u.reader->mr_pid = 0; txn->mt_u.reader = NULL; } return MDB_MAP_RESIZED; } return MDB_SUCCESS; } int mdb_txn_renew(MDB_txn *txn) { int rc; if (!txn || txn->mt_dbxs) /* A reset txn has mt_dbxs==NULL */ return EINVAL; if (txn->mt_env->me_flags & MDB_FATAL_ERROR) { DPUTS("environment had fatal error, must shutdown!"); return MDB_PANIC; } rc = mdb_txn_renew0(txn); if (rc == MDB_SUCCESS) { DPRINTF(("renew txn %"Z"u%c %p on mdbenv %p, root page %"Z"u", txn->mt_txnid, (txn->mt_flags & MDB_TXN_RDONLY) ? 'r' : 'w', (void *)txn, (void *)txn->mt_env, txn->mt_dbs[MAIN_DBI].md_root)); } return rc; } int mdb_txn_begin(MDB_env *env, MDB_txn *parent, unsigned int flags, MDB_txn **ret) { MDB_txn *txn; MDB_ntxn *ntxn; int rc, size, tsize = sizeof(MDB_txn); if (env->me_flags & MDB_FATAL_ERROR) { DPUTS("environment had fatal error, must shutdown!"); return MDB_PANIC; } if ((env->me_flags & MDB_RDONLY) && !(flags & MDB_RDONLY)) return EACCES; if (parent) { /* Nested transactions: Max 1 child, write txns only, no writemap */ if (parent->mt_child || (flags & MDB_RDONLY) || (parent->mt_flags & (MDB_TXN_RDONLY|MDB_TXN_ERROR)) || (env->me_flags & MDB_WRITEMAP)) { return (parent->mt_flags & MDB_TXN_RDONLY) ? EINVAL : MDB_BAD_TXN; } tsize = sizeof(MDB_ntxn); } size = tsize; if (!(flags & MDB_RDONLY)) { if (!parent) { txn = env->me_txn0; /* just reuse preallocated write txn */ goto ok; } /* child txns use own copy of cursors */ size += env->me_maxdbs * sizeof(MDB_cursor *); } size += env->me_maxdbs * (sizeof(MDB_db)+1); if ((txn = calloc(1, size)) == NULL) { DPRINTF(("calloc: %s", strerror(errno))); return ENOMEM; } txn->mt_dbs = (MDB_db *) ((char *)txn + tsize); if (flags & MDB_RDONLY) { txn->mt_flags |= MDB_TXN_RDONLY; txn->mt_dbflags = (unsigned char *)(txn->mt_dbs + env->me_maxdbs); txn->mt_dbiseqs = env->me_dbiseqs; } else { txn->mt_cursors = (MDB_cursor **)(txn->mt_dbs + env->me_maxdbs); if (parent) { txn->mt_dbiseqs = parent->mt_dbiseqs; txn->mt_dbflags = (unsigned char *)(txn->mt_cursors + env->me_maxdbs); } else { txn->mt_dbiseqs = (unsigned int *)(txn->mt_cursors + env->me_maxdbs); txn->mt_dbflags = (unsigned char *)(txn->mt_dbiseqs + env->me_maxdbs); } } txn->mt_env = env; ok: if (parent) { unsigned int i; txn->mt_u.dirty_list = malloc(sizeof(MDB_ID2)*MDB_IDL_UM_SIZE); if (!txn->mt_u.dirty_list || !(txn->mt_free_pgs = mdb_midl_alloc(MDB_IDL_UM_MAX))) { free(txn->mt_u.dirty_list); free(txn); return ENOMEM; } txn->mt_txnid = parent->mt_txnid; txn->mt_dirty_room = parent->mt_dirty_room; txn->mt_u.dirty_list[0].mid = 0; txn->mt_spill_pgs = NULL; txn->mt_next_pgno = parent->mt_next_pgno; parent->mt_child = txn; txn->mt_parent = parent; txn->mt_numdbs = parent->mt_numdbs; txn->mt_flags = parent->mt_flags; txn->mt_dbxs = parent->mt_dbxs; memcpy(txn->mt_dbs, parent->mt_dbs, txn->mt_numdbs * sizeof(MDB_db)); /* Copy parent's mt_dbflags, but clear DB_NEW */ for (i=0; imt_numdbs; i++) txn->mt_dbflags[i] = parent->mt_dbflags[i] & ~DB_NEW; rc = 0; ntxn = (MDB_ntxn *)txn; ntxn->mnt_pgstate = env->me_pgstate; /* save parent me_pghead & co */ if (env->me_pghead) { size = MDB_IDL_SIZEOF(env->me_pghead); env->me_pghead = mdb_midl_alloc(env->me_pghead[0]); if (env->me_pghead) memcpy(env->me_pghead, ntxn->mnt_pgstate.mf_pghead, size); else rc = ENOMEM; } if (!rc) rc = mdb_cursor_shadow(parent, txn); if (rc) mdb_txn_reset0(txn, "beginchild-fail"); } else { rc = mdb_txn_renew0(txn); } if (rc) { if (txn != env->me_txn0) free(txn); } else { *ret = txn; DPRINTF(("begin txn %"Z"u%c %p on mdbenv %p, root page %"Z"u", txn->mt_txnid, (txn->mt_flags & MDB_TXN_RDONLY) ? 'r' : 'w', (void *) txn, (void *) env, txn->mt_dbs[MAIN_DBI].md_root)); } return rc; } MDB_env * mdb_txn_env(MDB_txn *txn) { if(!txn) return NULL; return txn->mt_env; } /** Export or close DBI handles opened in this txn. */ static void mdb_dbis_update(MDB_txn *txn, int keep) { int i; MDB_dbi n = txn->mt_numdbs; MDB_env *env = txn->mt_env; unsigned char *tdbflags = txn->mt_dbflags; for (i = n; --i >= 2;) { if (tdbflags[i] & DB_NEW) { if (keep) { env->me_dbflags[i] = txn->mt_dbs[i].md_flags | MDB_VALID; } else { char *ptr = env->me_dbxs[i].md_name.mv_data; if (ptr) { env->me_dbxs[i].md_name.mv_data = NULL; env->me_dbxs[i].md_name.mv_size = 0; env->me_dbflags[i] = 0; env->me_dbiseqs[i]++; free(ptr); } } } } if (keep && env->me_numdbs < n) env->me_numdbs = n; } /** Common code for #mdb_txn_reset() and #mdb_txn_abort(). * May be called twice for readonly txns: First reset it, then abort. * @param[in] txn the transaction handle to reset * @param[in] act why the transaction is being reset */ static void mdb_txn_reset0(MDB_txn *txn, const char *act) { MDB_env *env = txn->mt_env; /* Close any DBI handles opened in this txn */ mdb_dbis_update(txn, 0); DPRINTF(("%s txn %"Z"u%c %p on mdbenv %p, root page %"Z"u", act, txn->mt_txnid, (txn->mt_flags & MDB_TXN_RDONLY) ? 'r' : 'w', (void *) txn, (void *)env, txn->mt_dbs[MAIN_DBI].md_root)); if (F_ISSET(txn->mt_flags, MDB_TXN_RDONLY)) { if (txn->mt_u.reader) { txn->mt_u.reader->mr_txnid = (txnid_t)-1; if (!(env->me_flags & MDB_NOTLS)) txn->mt_u.reader = NULL; /* txn does not own reader */ } txn->mt_numdbs = 0; /* close nothing if called again */ txn->mt_dbxs = NULL; /* mark txn as reset */ } else { pgno_t *pghead = env->me_pghead; mdb_cursors_close(txn, 0); if (!(env->me_flags & MDB_WRITEMAP)) { mdb_dlist_free(txn); } if (!txn->mt_parent) { mdb_midl_shrink(&txn->mt_free_pgs); env->me_free_pgs = txn->mt_free_pgs; /* me_pgstate: */ env->me_pghead = NULL; env->me_pglast = 0; env->me_txn = NULL; /* The writer mutex was locked in mdb_txn_begin. */ if (env->me_txns) UNLOCK_MUTEX_W(env); } else { txn->mt_parent->mt_child = NULL; env->me_pgstate = ((MDB_ntxn *)txn)->mnt_pgstate; mdb_midl_free(txn->mt_free_pgs); mdb_midl_free(txn->mt_spill_pgs); free(txn->mt_u.dirty_list); } mdb_midl_free(pghead); } } void mdb_txn_reset(MDB_txn *txn) { if (txn == NULL) return; /* This call is only valid for read-only txns */ if (!(txn->mt_flags & MDB_TXN_RDONLY)) return; mdb_txn_reset0(txn, "reset"); } void mdb_txn_abort(MDB_txn *txn) { if (txn == NULL) return; if (txn->mt_child) mdb_txn_abort(txn->mt_child); mdb_txn_reset0(txn, "abort"); /* Free reader slot tied to this txn (if MDB_NOTLS && writable FS) */ if ((txn->mt_flags & MDB_TXN_RDONLY) && txn->mt_u.reader) txn->mt_u.reader->mr_pid = 0; if (txn != txn->mt_env->me_txn0) free(txn); } /** Save the freelist as of this transaction to the freeDB. * This changes the freelist. Keep trying until it stabilizes. */ static int mdb_freelist_save(MDB_txn *txn) { /* env->me_pghead[] can grow and shrink during this call. * env->me_pglast and txn->mt_free_pgs[] can only grow. * Page numbers cannot disappear from txn->mt_free_pgs[]. */ MDB_cursor mc; MDB_env *env = txn->mt_env; int rc, maxfree_1pg = env->me_maxfree_1pg, more = 1; txnid_t pglast = 0, head_id = 0; pgno_t freecnt = 0, *free_pgs, *mop; ssize_t head_room = 0, total_room = 0, mop_len, clean_limit; mdb_cursor_init(&mc, txn, FREE_DBI, NULL); if (env->me_pghead) { /* Make sure first page of freeDB is touched and on freelist */ rc = mdb_page_search(&mc, NULL, MDB_PS_FIRST|MDB_PS_MODIFY); if (rc && rc != MDB_NOTFOUND) return rc; } if (!env->me_pghead && txn->mt_loose_pgs) { /* Put loose page numbers in mt_free_pgs, since * we may be unable to return them to me_pghead. */ MDB_page *mp = txn->mt_loose_pgs; if ((rc = mdb_midl_need(&txn->mt_free_pgs, txn->mt_loose_count)) != 0) return rc; for (; mp; mp = NEXT_LOOSE_PAGE(mp)) mdb_midl_xappend(txn->mt_free_pgs, mp->mp_pgno); txn->mt_loose_pgs = NULL; txn->mt_loose_count = 0; } /* MDB_RESERVE cancels meminit in ovpage malloc (when no WRITEMAP) */ clean_limit = (env->me_flags & (MDB_NOMEMINIT|MDB_WRITEMAP)) ? SSIZE_MAX : maxfree_1pg; for (;;) { /* Come back here after each Put() in case freelist changed */ MDB_val key, data; pgno_t *pgs; ssize_t j; /* If using records from freeDB which we have not yet * deleted, delete them and any we reserved for me_pghead. */ while (pglast < env->me_pglast) { rc = mdb_cursor_first(&mc, &key, NULL); if (rc) return rc; pglast = head_id = *(txnid_t *)key.mv_data; total_room = head_room = 0; mdb_tassert(txn, pglast <= env->me_pglast); rc = mdb_cursor_del(&mc, 0); if (rc) return rc; } /* Save the IDL of pages freed by this txn, to a single record */ if (freecnt < txn->mt_free_pgs[0]) { if (!freecnt) { /* Make sure last page of freeDB is touched and on freelist */ rc = mdb_page_search(&mc, NULL, MDB_PS_LAST|MDB_PS_MODIFY); if (rc && rc != MDB_NOTFOUND) return rc; } free_pgs = txn->mt_free_pgs; /* Write to last page of freeDB */ key.mv_size = sizeof(txn->mt_txnid); key.mv_data = &txn->mt_txnid; do { freecnt = free_pgs[0]; data.mv_size = MDB_IDL_SIZEOF(free_pgs); rc = mdb_cursor_put(&mc, &key, &data, MDB_RESERVE); if (rc) return rc; /* Retry if mt_free_pgs[] grew during the Put() */ free_pgs = txn->mt_free_pgs; } while (freecnt < free_pgs[0]); mdb_midl_sort(free_pgs); memcpy(data.mv_data, free_pgs, data.mv_size); #if (MDB_DEBUG) > 1 { unsigned int i = free_pgs[0]; DPRINTF(("IDL write txn %"Z"u root %"Z"u num %u", txn->mt_txnid, txn->mt_dbs[FREE_DBI].md_root, i)); for (; i; i--) DPRINTF(("IDL %"Z"u", free_pgs[i])); } #endif continue; } mop = env->me_pghead; mop_len = (mop ? mop[0] : 0) + txn->mt_loose_count; /* Reserve records for me_pghead[]. Split it if multi-page, * to avoid searching freeDB for a page range. Use keys in * range [1,me_pglast]: Smaller than txnid of oldest reader. */ if (total_room >= mop_len) { if (total_room == mop_len || --more < 0) break; } else if (head_room >= maxfree_1pg && head_id > 1) { /* Keep current record (overflow page), add a new one */ head_id--; head_room = 0; } /* (Re)write {key = head_id, IDL length = head_room} */ total_room -= head_room; head_room = mop_len - total_room; if (head_room > maxfree_1pg && head_id > 1) { /* Overflow multi-page for part of me_pghead */ head_room /= head_id; /* amortize page sizes */ head_room += maxfree_1pg - head_room % (maxfree_1pg + 1); } else if (head_room < 0) { /* Rare case, not bothering to delete this record */ head_room = 0; } key.mv_size = sizeof(head_id); key.mv_data = &head_id; data.mv_size = (head_room + 1) * sizeof(pgno_t); rc = mdb_cursor_put(&mc, &key, &data, MDB_RESERVE); if (rc) return rc; /* IDL is initially empty, zero out at least the length */ pgs = (pgno_t *)data.mv_data; j = head_room > clean_limit ? head_room : 0; do { pgs[j] = 0; } while (--j >= 0); total_room += head_room; } /* Return loose page numbers to me_pghead, though usually none are * left at this point. The pages themselves remain in dirty_list. */ if (txn->mt_loose_pgs) { MDB_page *mp = txn->mt_loose_pgs; unsigned count = txn->mt_loose_count; MDB_IDL loose; /* Room for loose pages + temp IDL with same */ if ((rc = mdb_midl_need(&env->me_pghead, 2*count+1)) != 0) return rc; mop = env->me_pghead; loose = mop + MDB_IDL_ALLOCLEN(mop) - count; for (count = 0; mp; mp = NEXT_LOOSE_PAGE(mp)) loose[ ++count ] = mp->mp_pgno; loose[0] = count; mdb_midl_sort(loose); mdb_midl_xmerge(mop, loose); txn->mt_loose_pgs = NULL; txn->mt_loose_count = 0; mop_len = mop[0]; } /* Fill in the reserved me_pghead records */ rc = MDB_SUCCESS; if (mop_len) { MDB_val key, data; mop += mop_len; rc = mdb_cursor_first(&mc, &key, &data); for (; !rc; rc = mdb_cursor_next(&mc, &key, &data, MDB_NEXT)) { txnid_t id = *(txnid_t *)key.mv_data; ssize_t len = (ssize_t)(data.mv_size / sizeof(MDB_ID)) - 1; MDB_ID save; mdb_tassert(txn, len >= 0 && id <= env->me_pglast); key.mv_data = &id; if (len > mop_len) { len = mop_len; data.mv_size = (len + 1) * sizeof(MDB_ID); } data.mv_data = mop -= len; save = mop[0]; mop[0] = len; rc = mdb_cursor_put(&mc, &key, &data, MDB_CURRENT); mop[0] = save; if (rc || !(mop_len -= len)) break; } } return rc; } /** Flush (some) dirty pages to the map, after clearing their dirty flag. * @param[in] txn the transaction that's being committed * @param[in] keep number of initial pages in dirty_list to keep dirty. * @return 0 on success, non-zero on failure. */ static int mdb_page_flush(MDB_txn *txn, int keep) { MDB_env *env = txn->mt_env; MDB_ID2L dl = txn->mt_u.dirty_list; unsigned psize = env->me_psize, j; int i, pagecount = dl[0].mid, rc; size_t size = 0, pos = 0; pgno_t pgno = 0; MDB_page *dp = NULL; #ifdef _WIN32 OVERLAPPED ov; #else struct iovec iov[MDB_COMMIT_PAGES]; ssize_t wpos = 0, wsize = 0, wres; size_t next_pos = 1; /* impossible pos, so pos != next_pos */ int n = 0; #endif j = i = keep; if (env->me_flags & MDB_WRITEMAP) { /* Clear dirty flags */ while (++i <= pagecount) { dp = dl[i].mptr; /* Don't flush this page yet */ if (dp->mp_flags & (P_LOOSE|P_KEEP)) { dp->mp_flags &= ~P_KEEP; dl[++j] = dl[i]; continue; } dp->mp_flags &= ~P_DIRTY; } goto done; } /* Write the pages */ for (;;) { if (++i <= pagecount) { dp = dl[i].mptr; /* Don't flush this page yet */ if (dp->mp_flags & (P_LOOSE|P_KEEP)) { dp->mp_flags &= ~P_KEEP; dl[i].mid = 0; continue; } pgno = dl[i].mid; /* clear dirty flag */ dp->mp_flags &= ~P_DIRTY; pos = pgno * psize; size = psize; if (IS_OVERFLOW(dp)) size *= dp->mp_pages; } #ifdef _WIN32 else break; /* Windows actually supports scatter/gather I/O, but only on * unbuffered file handles. Since we're relying on the OS page * cache for all our data, that's self-defeating. So we just * write pages one at a time. We use the ov structure to set * the write offset, to at least save the overhead of a Seek * system call. */ DPRINTF(("committing page %"Z"u", pgno)); memset(&ov, 0, sizeof(ov)); ov.Offset = pos & 0xffffffff; ov.OffsetHigh = pos >> 16 >> 16; if (!WriteFile(env->me_fd, dp, size, NULL, &ov)) { rc = ErrCode(); DPRINTF(("WriteFile: %d", rc)); return rc; } #else /* Write up to MDB_COMMIT_PAGES dirty pages at a time. */ if (pos!=next_pos || n==MDB_COMMIT_PAGES || wsize+size>MAX_WRITE) { if (n) { retry_write: /* Write previous page(s) */ #ifdef MDB_USE_PWRITEV wres = pwritev(env->me_fd, iov, n, wpos); #else if (n == 1) { wres = pwrite(env->me_fd, iov[0].iov_base, wsize, wpos); } else { retry_seek: if (lseek(env->me_fd, wpos, SEEK_SET) == -1) { rc = ErrCode(); if (rc == EINTR) goto retry_seek; DPRINTF(("lseek: %s", strerror(rc))); return rc; } wres = writev(env->me_fd, iov, n); } #endif if (wres != wsize) { if (wres < 0) { rc = ErrCode(); if (rc == EINTR) goto retry_write; DPRINTF(("Write error: %s", strerror(rc))); } else { rc = EIO; /* TODO: Use which error code? */ DPUTS("short write, filesystem full?"); } return rc; } n = 0; } if (i > pagecount) break; wpos = pos; wsize = 0; } DPRINTF(("committing page %"Z"u", pgno)); next_pos = pos + size; iov[n].iov_len = size; iov[n].iov_base = (char *)dp; wsize += size; n++; #endif /* _WIN32 */ } /* MIPS has cache coherency issues, this is a no-op everywhere else * Note: for any size >= on-chip cache size, entire on-chip cache is * flushed. */ CACHEFLUSH(env->me_map, txn->mt_next_pgno * env->me_psize, DCACHE); for (i = keep; ++i <= pagecount; ) { dp = dl[i].mptr; /* This is a page we skipped above */ if (!dl[i].mid) { dl[++j] = dl[i]; dl[j].mid = dp->mp_pgno; continue; } mdb_dpage_free(env, dp); } done: i--; txn->mt_dirty_room += i - j; dl[0].mid = j; return MDB_SUCCESS; } int mdb_txn_commit(MDB_txn *txn) { int rc; unsigned int i; MDB_env *env; if (txn == NULL || txn->mt_env == NULL) return EINVAL; if (txn->mt_child) { rc = mdb_txn_commit(txn->mt_child); txn->mt_child = NULL; if (rc) goto fail; } env = txn->mt_env; if (F_ISSET(txn->mt_flags, MDB_TXN_RDONLY)) { mdb_dbis_update(txn, 1); txn->mt_numdbs = 2; /* so txn_abort() doesn't close any new handles */ mdb_txn_abort(txn); return MDB_SUCCESS; } if (F_ISSET(txn->mt_flags, MDB_TXN_ERROR)) { DPUTS("error flag is set, can't commit"); if (txn->mt_parent) txn->mt_parent->mt_flags |= MDB_TXN_ERROR; rc = MDB_BAD_TXN; goto fail; } if (txn->mt_parent) { MDB_txn *parent = txn->mt_parent; MDB_page **lp; MDB_ID2L dst, src; MDB_IDL pspill; unsigned x, y, len, ps_len; /* Append our free list to parent's */ rc = mdb_midl_append_list(&parent->mt_free_pgs, txn->mt_free_pgs); if (rc) goto fail; mdb_midl_free(txn->mt_free_pgs); /* Failures after this must either undo the changes * to the parent or set MDB_TXN_ERROR in the parent. */ parent->mt_next_pgno = txn->mt_next_pgno; parent->mt_flags = txn->mt_flags; /* Merge our cursors into parent's and close them */ mdb_cursors_close(txn, 1); /* Update parent's DB table. */ memcpy(parent->mt_dbs, txn->mt_dbs, txn->mt_numdbs * sizeof(MDB_db)); parent->mt_numdbs = txn->mt_numdbs; parent->mt_dbflags[0] = txn->mt_dbflags[0]; parent->mt_dbflags[1] = txn->mt_dbflags[1]; for (i=2; imt_numdbs; i++) { /* preserve parent's DB_NEW status */ x = parent->mt_dbflags[i] & DB_NEW; parent->mt_dbflags[i] = txn->mt_dbflags[i] | x; } dst = parent->mt_u.dirty_list; src = txn->mt_u.dirty_list; /* Remove anything in our dirty list from parent's spill list */ if ((pspill = parent->mt_spill_pgs) && (ps_len = pspill[0])) { x = y = ps_len; pspill[0] = (pgno_t)-1; /* Mark our dirty pages as deleted in parent spill list */ for (i=0, len=src[0].mid; ++i <= len; ) { MDB_ID pn = src[i].mid << 1; while (pn > pspill[x]) x--; if (pn == pspill[x]) { pspill[x] = 1; y = --x; } } /* Squash deleted pagenums if we deleted any */ for (x=y; ++x <= ps_len; ) if (!(pspill[x] & 1)) pspill[++y] = pspill[x]; pspill[0] = y; } /* Find len = length of merging our dirty list with parent's */ x = dst[0].mid; dst[0].mid = 0; /* simplify loops */ if (parent->mt_parent) { len = x + src[0].mid; y = mdb_mid2l_search(src, dst[x].mid + 1) - 1; for (i = x; y && i; y--) { pgno_t yp = src[y].mid; while (yp < dst[i].mid) i--; if (yp == dst[i].mid) { i--; len--; } } } else { /* Simplify the above for single-ancestor case */ len = MDB_IDL_UM_MAX - txn->mt_dirty_room; } /* Merge our dirty list with parent's */ y = src[0].mid; for (i = len; y; dst[i--] = src[y--]) { pgno_t yp = src[y].mid; while (yp < dst[x].mid) dst[i--] = dst[x--]; if (yp == dst[x].mid) free(dst[x--].mptr); } mdb_tassert(txn, i == x); dst[0].mid = len; free(txn->mt_u.dirty_list); parent->mt_dirty_room = txn->mt_dirty_room; if (txn->mt_spill_pgs) { if (parent->mt_spill_pgs) { /* TODO: Prevent failure here, so parent does not fail */ rc = mdb_midl_append_list(&parent->mt_spill_pgs, txn->mt_spill_pgs); if (rc) parent->mt_flags |= MDB_TXN_ERROR; mdb_midl_free(txn->mt_spill_pgs); mdb_midl_sort(parent->mt_spill_pgs); } else { parent->mt_spill_pgs = txn->mt_spill_pgs; } } /* Append our loose page list to parent's */ for (lp = &parent->mt_loose_pgs; *lp; lp = &NEXT_LOOSE_PAGE(lp)) ; *lp = txn->mt_loose_pgs; parent->mt_loose_count += txn->mt_loose_count; parent->mt_child = NULL; mdb_midl_free(((MDB_ntxn *)txn)->mnt_pgstate.mf_pghead); free(txn); return rc; } if (txn != env->me_txn) { DPUTS("attempt to commit unknown transaction"); rc = EINVAL; goto fail; } mdb_cursors_close(txn, 0); if (!txn->mt_u.dirty_list[0].mid && !(txn->mt_flags & (MDB_TXN_DIRTY|MDB_TXN_SPILLS))) goto done; DPRINTF(("committing txn %"Z"u %p on mdbenv %p, root page %"Z"u", txn->mt_txnid, (void*)txn, (void*)env, txn->mt_dbs[MAIN_DBI].md_root)); /* Update DB root pointers */ if (txn->mt_numdbs > 2) { MDB_cursor mc; MDB_dbi i; MDB_val data; data.mv_size = sizeof(MDB_db); mdb_cursor_init(&mc, txn, MAIN_DBI, NULL); for (i = 2; i < txn->mt_numdbs; i++) { if (txn->mt_dbflags[i] & DB_DIRTY) { if (TXN_DBI_CHANGED(txn, i)) { rc = MDB_BAD_DBI; goto fail; } data.mv_data = &txn->mt_dbs[i]; rc = mdb_cursor_put(&mc, &txn->mt_dbxs[i].md_name, &data, F_SUBDATA); if (rc) goto fail; } } } rc = mdb_freelist_save(txn); if (rc) goto fail; mdb_midl_free(env->me_pghead); env->me_pghead = NULL; mdb_midl_shrink(&txn->mt_free_pgs); env->me_free_pgs = txn->mt_free_pgs; #if (MDB_DEBUG) > 2 mdb_audit(txn); #endif if ((rc = mdb_page_flush(txn, 0)) || (rc = mdb_env_sync(env, 0)) || (rc = mdb_env_write_meta(txn))) goto fail; /* Free P_LOOSE pages left behind in dirty_list */ if (!(env->me_flags & MDB_WRITEMAP)) mdb_dlist_free(txn); done: env->me_pglast = 0; env->me_txn = NULL; mdb_dbis_update(txn, 1); if (env->me_txns) UNLOCK_MUTEX_W(env); if (txn != env->me_txn0) free(txn); return MDB_SUCCESS; fail: mdb_txn_abort(txn); return rc; } /** Read the environment parameters of a DB environment before * mapping it into memory. * @param[in] env the environment handle * @param[out] meta address of where to store the meta information * @return 0 on success, non-zero on failure. */ static int ESECT mdb_env_read_header(MDB_env *env, MDB_meta *meta) { MDB_metabuf pbuf; MDB_page *p; MDB_meta *m; int i, rc, off; enum { Size = sizeof(pbuf) }; /* We don't know the page size yet, so use a minimum value. * Read both meta pages so we can use the latest one. */ for (i=off=0; i<2; i++, off = meta->mm_psize) { #ifdef _WIN32 DWORD len; OVERLAPPED ov; memset(&ov, 0, sizeof(ov)); ov.Offset = off; rc = ReadFile(env->me_fd, &pbuf, Size, &len, &ov) ? (int)len : -1; if (rc == -1 && ErrCode() == ERROR_HANDLE_EOF) rc = 0; #else rc = pread(env->me_fd, &pbuf, Size, off); #endif if (rc != Size) { if (rc == 0 && off == 0) return ENOENT; rc = rc < 0 ? (int) ErrCode() : MDB_INVALID; DPRINTF(("read: %s", mdb_strerror(rc))); return rc; } p = (MDB_page *)&pbuf; if (!F_ISSET(p->mp_flags, P_META)) { DPRINTF(("page %"Z"u not a meta page", p->mp_pgno)); return MDB_INVALID; } m = METADATA(p); if (m->mm_magic != MDB_MAGIC) { DPUTS("meta has invalid magic"); return MDB_INVALID; } if (m->mm_version != MDB_DATA_VERSION) { DPRINTF(("database is version %u, expected version %u", m->mm_version, MDB_DATA_VERSION)); return MDB_VERSION_MISMATCH; } if (off == 0 || m->mm_txnid > meta->mm_txnid) *meta = *m; } return 0; } static void ESECT mdb_env_init_meta0(MDB_env *env, MDB_meta *meta) { meta->mm_magic = MDB_MAGIC; meta->mm_version = MDB_DATA_VERSION; meta->mm_mapsize = env->me_mapsize; meta->mm_psize = env->me_psize; meta->mm_last_pg = 1; meta->mm_flags = env->me_flags & 0xffff; meta->mm_flags |= MDB_INTEGERKEY; meta->mm_dbs[0].md_root = P_INVALID; meta->mm_dbs[1].md_root = P_INVALID; } /** Write the environment parameters of a freshly created DB environment. * @param[in] env the environment handle * @param[out] meta address of where to store the meta information * @return 0 on success, non-zero on failure. */ static int ESECT mdb_env_init_meta(MDB_env *env, MDB_meta *meta) { MDB_page *p, *q; int rc; unsigned int psize; #ifdef _WIN32 DWORD len; OVERLAPPED ov; memset(&ov, 0, sizeof(ov)); #define DO_PWRITE(rc, fd, ptr, size, len, pos) do { \ ov.Offset = pos; \ rc = WriteFile(fd, ptr, size, &len, &ov); } while(0) #else int len; #define DO_PWRITE(rc, fd, ptr, size, len, pos) do { \ len = pwrite(fd, ptr, size, pos); \ if (len == -1 && ErrCode() == EINTR) continue; \ rc = (len >= 0); break; } while(1) #endif DPUTS("writing new meta page"); psize = env->me_psize; mdb_env_init_meta0(env, meta); p = calloc(2, psize); p->mp_pgno = 0; p->mp_flags = P_META; *(MDB_meta *)METADATA(p) = *meta; q = (MDB_page *)((char *)p + psize); q->mp_pgno = 1; q->mp_flags = P_META; *(MDB_meta *)METADATA(q) = *meta; DO_PWRITE(rc, env->me_fd, p, psize * 2, len, 0); if (!rc) rc = ErrCode(); else if ((unsigned) len == psize * 2) rc = MDB_SUCCESS; else rc = ENOSPC; free(p); return rc; } /** Update the environment info to commit a transaction. * @param[in] txn the transaction that's being committed * @return 0 on success, non-zero on failure. */ static int mdb_env_write_meta(MDB_txn *txn) { MDB_env *env; MDB_meta meta, metab, *mp; size_t mapsize; off_t off; int rc, len, toggle; char *ptr; HANDLE mfd; #ifdef _WIN32 OVERLAPPED ov; #else int r2; #endif toggle = txn->mt_txnid & 1; DPRINTF(("writing meta page %d for root page %"Z"u", toggle, txn->mt_dbs[MAIN_DBI].md_root)); env = txn->mt_env; mp = env->me_metas[toggle]; mapsize = env->me_metas[toggle ^ 1]->mm_mapsize; /* Persist any increases of mapsize config */ if (mapsize < env->me_mapsize) mapsize = env->me_mapsize; if (env->me_flags & MDB_WRITEMAP) { mp->mm_mapsize = mapsize; mp->mm_dbs[0] = txn->mt_dbs[0]; mp->mm_dbs[1] = txn->mt_dbs[1]; mp->mm_last_pg = txn->mt_next_pgno - 1; mp->mm_txnid = txn->mt_txnid; if (!(env->me_flags & (MDB_NOMETASYNC|MDB_NOSYNC))) { unsigned meta_size = env->me_psize; rc = (env->me_flags & MDB_MAPASYNC) ? MS_ASYNC : MS_SYNC; ptr = env->me_map; if (toggle) { #ifndef _WIN32 /* POSIX msync() requires ptr = start of OS page */ if (meta_size < env->me_os_psize) meta_size += meta_size; else #endif ptr += meta_size; } if (MDB_MSYNC(ptr, meta_size, rc)) { rc = ErrCode(); goto fail; } } goto done; } metab.mm_txnid = env->me_metas[toggle]->mm_txnid; metab.mm_last_pg = env->me_metas[toggle]->mm_last_pg; meta.mm_mapsize = mapsize; meta.mm_dbs[0] = txn->mt_dbs[0]; meta.mm_dbs[1] = txn->mt_dbs[1]; meta.mm_last_pg = txn->mt_next_pgno - 1; meta.mm_txnid = txn->mt_txnid; off = offsetof(MDB_meta, mm_mapsize); ptr = (char *)&meta + off; len = sizeof(MDB_meta) - off; if (toggle) off += env->me_psize; off += PAGEHDRSZ; /* Write to the SYNC fd */ mfd = env->me_flags & (MDB_NOSYNC|MDB_NOMETASYNC) ? env->me_fd : env->me_mfd; #ifdef _WIN32 { memset(&ov, 0, sizeof(ov)); ov.Offset = off; if (!WriteFile(mfd, ptr, len, (DWORD *)&rc, &ov)) rc = -1; } #else retry_write: rc = pwrite(mfd, ptr, len, off); #endif if (rc != len) { rc = rc < 0 ? ErrCode() : EIO; #ifndef _WIN32 if (rc == EINTR) goto retry_write; #endif DPUTS("write failed, disk error?"); /* On a failure, the pagecache still contains the new data. * Write some old data back, to prevent it from being used. * Use the non-SYNC fd; we know it will fail anyway. */ meta.mm_last_pg = metab.mm_last_pg; meta.mm_txnid = metab.mm_txnid; #ifdef _WIN32 memset(&ov, 0, sizeof(ov)); ov.Offset = off; WriteFile(env->me_fd, ptr, len, NULL, &ov); #else r2 = pwrite(env->me_fd, ptr, len, off); (void)r2; /* Silence warnings. We don't care about pwrite's return value */ #endif fail: env->me_flags |= MDB_FATAL_ERROR; return rc; } /* MIPS has cache coherency issues, this is a no-op everywhere else */ CACHEFLUSH(env->me_map + off, len, DCACHE); done: /* Memory ordering issues are irrelevant; since the entire writer * is wrapped by wmutex, all of these changes will become visible * after the wmutex is unlocked. Since the DB is multi-version, * readers will get consistent data regardless of how fresh or * how stale their view of these values is. */ if (env->me_txns) env->me_txns->mti_txnid = txn->mt_txnid; return MDB_SUCCESS; } /** Check both meta pages to see which one is newer. * @param[in] env the environment handle * @return meta toggle (0 or 1). */ static int mdb_env_pick_meta(const MDB_env *env) { return (env->me_metas[0]->mm_txnid < env->me_metas[1]->mm_txnid); } int ESECT mdb_env_create(MDB_env **env) { MDB_env *e; e = calloc(1, sizeof(MDB_env)); if (!e) return ENOMEM; e->me_maxreaders = DEFAULT_READERS; e->me_maxdbs = e->me_numdbs = 2; e->me_fd = INVALID_HANDLE_VALUE; e->me_lfd = INVALID_HANDLE_VALUE; e->me_mfd = INVALID_HANDLE_VALUE; #ifdef MDB_USE_POSIX_SEM e->me_rmutex = SEM_FAILED; e->me_wmutex = SEM_FAILED; #endif e->me_pid = getpid(); GET_PAGESIZE(e->me_os_psize); VGMEMP_CREATE(e,0,0); *env = e; return MDB_SUCCESS; } static int ESECT mdb_env_map(MDB_env *env, void *addr) { MDB_page *p; unsigned int flags = env->me_flags; #ifdef _WIN32 int rc; HANDLE mh; LONG sizelo, sizehi; size_t msize; if (flags & MDB_RDONLY) { /* Don't set explicit map size, use whatever exists */ msize = 0; sizelo = 0; sizehi = 0; } else { msize = env->me_mapsize; sizelo = msize & 0xffffffff; sizehi = msize >> 16 >> 16; /* only needed on Win64 */ /* Windows won't create mappings for zero length files. * and won't map more than the file size. * Just set the maxsize right now. */ if (SetFilePointer(env->me_fd, sizelo, &sizehi, 0) != (DWORD)sizelo || !SetEndOfFile(env->me_fd) || SetFilePointer(env->me_fd, 0, NULL, 0) != 0) return ErrCode(); } mh = CreateFileMapping(env->me_fd, NULL, flags & MDB_WRITEMAP ? PAGE_READWRITE : PAGE_READONLY, sizehi, sizelo, NULL); if (!mh) return ErrCode(); env->me_map = MapViewOfFileEx(mh, flags & MDB_WRITEMAP ? FILE_MAP_WRITE : FILE_MAP_READ, 0, 0, msize, addr); rc = env->me_map ? 0 : ErrCode(); CloseHandle(mh); if (rc) return rc; #else int prot = PROT_READ; if (flags & MDB_WRITEMAP) { prot |= PROT_WRITE; if (ftruncate(env->me_fd, env->me_mapsize) < 0) return ErrCode(); } env->me_map = mmap(addr, env->me_mapsize, prot, MAP_SHARED, env->me_fd, 0); if (env->me_map == MAP_FAILED) { env->me_map = NULL; return ErrCode(); } if (flags & MDB_NORDAHEAD) { /* Turn off readahead. It's harmful when the DB is larger than RAM. */ #ifdef MADV_RANDOM madvise(env->me_map, env->me_mapsize, MADV_RANDOM); #else #ifdef POSIX_MADV_RANDOM posix_madvise(env->me_map, env->me_mapsize, POSIX_MADV_RANDOM); #endif /* POSIX_MADV_RANDOM */ #endif /* MADV_RANDOM */ } #endif /* _WIN32 */ /* Can happen because the address argument to mmap() is just a * hint. mmap() can pick another, e.g. if the range is in use. * The MAP_FIXED flag would prevent that, but then mmap could * instead unmap existing pages to make room for the new map. */ if (addr && env->me_map != addr) return EBUSY; /* TODO: Make a new MDB_* error code? */ p = (MDB_page *)env->me_map; env->me_metas[0] = METADATA(p); env->me_metas[1] = (MDB_meta *)((char *)env->me_metas[0] + env->me_psize); return MDB_SUCCESS; } int ESECT mdb_env_set_mapsize(MDB_env *env, size_t size) { /* If env is already open, caller is responsible for making * sure there are no active txns. */ if (env->me_map) { int rc; void *old; if (env->me_txn) return EINVAL; if (!size) size = env->me_metas[mdb_env_pick_meta(env)]->mm_mapsize; else if (size < env->me_mapsize) { /* If the configured size is smaller, make sure it's * still big enough. Silently round up to minimum if not. */ size_t minsize = (env->me_metas[mdb_env_pick_meta(env)]->mm_last_pg + 1) * env->me_psize; if (size < minsize) size = minsize; } munmap(env->me_map, env->me_mapsize); env->me_mapsize = size; old = (env->me_flags & MDB_FIXEDMAP) ? env->me_map : NULL; rc = mdb_env_map(env, old); if (rc) return rc; } env->me_mapsize = size; if (env->me_psize) env->me_maxpg = env->me_mapsize / env->me_psize; return MDB_SUCCESS; } int ESECT mdb_env_set_maxdbs(MDB_env *env, MDB_dbi dbs) { if (env->me_map) return EINVAL; env->me_maxdbs = dbs + 2; /* Named databases + main and free DB */ return MDB_SUCCESS; } int ESECT mdb_env_set_maxreaders(MDB_env *env, unsigned int readers) { if (env->me_map || readers < 1) return EINVAL; env->me_maxreaders = readers; return MDB_SUCCESS; } int ESECT mdb_env_get_maxreaders(MDB_env *env, unsigned int *readers) { if (!env || !readers) return EINVAL; *readers = env->me_maxreaders; return MDB_SUCCESS; } static int ESECT mdb_fsize(HANDLE fd, size_t *size) { #ifdef _WIN32 LARGE_INTEGER fsize; if (!GetFileSizeEx(fd, &fsize)) return ErrCode(); *size = fsize.QuadPart; #else struct stat st; if (fstat(fd, &st)) return ErrCode(); *size = st.st_size; #endif return MDB_SUCCESS; } #ifdef BROKEN_FDATASYNC #include #include #endif /** Further setup required for opening an LMDB environment */ static int ESECT mdb_env_open2(MDB_env *env) { unsigned int flags = env->me_flags; int i, newenv = 0, rc; MDB_meta meta; #ifdef _WIN32 /* See if we should use QueryLimited */ rc = GetVersion(); if ((rc & 0xff) > 5) env->me_pidquery = MDB_PROCESS_QUERY_LIMITED_INFORMATION; else env->me_pidquery = PROCESS_QUERY_INFORMATION; #endif /* _WIN32 */ #ifdef BROKEN_FDATASYNC /* ext3/ext4 fdatasync is broken on some older Linux kernels. * https://lkml.org/lkml/2012/9/3/83 * Kernels after 3.6-rc6 are known good. * https://lkml.org/lkml/2012/9/10/556 * See if the DB is on ext3/ext4, then check for new enough kernel * Kernels 2.6.32.60, 2.6.34.15, 3.2.30, and 3.5.4 are also known * to be patched. */ { struct statfs st; fstatfs(env->me_fd, &st); while (st.f_type == 0xEF53) { struct utsname uts; int i; uname(&uts); if (uts.release[0] < '3') { if (!strncmp(uts.release, "2.6.32.", 7)) { i = atoi(uts.release+7); if (i >= 60) break; /* 2.6.32.60 and newer is OK */ } else if (!strncmp(uts.release, "2.6.34.", 7)) { i = atoi(uts.release+7); if (i >= 15) break; /* 2.6.34.15 and newer is OK */ } } else if (uts.release[0] == '3') { i = atoi(uts.release+2); if (i > 5) break; /* 3.6 and newer is OK */ if (i == 5) { i = atoi(uts.release+4); if (i >= 4) break; /* 3.5.4 and newer is OK */ } else if (i == 2) { i = atoi(uts.release+4); if (i >= 30) break; /* 3.2.30 and newer is OK */ } } else { /* 4.x and newer is OK */ break; } env->me_flags |= MDB_FSYNCONLY; break; } } #endif memset(&meta, 0, sizeof(meta)); if ((i = mdb_env_read_header(env, &meta)) != 0) { if (i != ENOENT) return i; DPUTS("new mdbenv"); newenv = 1; env->me_psize = env->me_os_psize; if (env->me_psize > MAX_PAGESIZE) env->me_psize = MAX_PAGESIZE; } else { env->me_psize = meta.mm_psize; } /* Was a mapsize configured? */ if (!env->me_mapsize) { /* If this is a new environment, take the default, * else use the size recorded in the existing env. */ env->me_mapsize = newenv ? DEFAULT_MAPSIZE : meta.mm_mapsize; } else if (env->me_mapsize < meta.mm_mapsize) { /* If the configured size is smaller, make sure it's * still big enough. Silently round up to minimum if not. */ size_t minsize = (meta.mm_last_pg + 1) * meta.mm_psize; if (env->me_mapsize < minsize) env->me_mapsize = minsize; } rc = mdb_env_map(env, (flags & MDB_FIXEDMAP) ? meta.mm_address : NULL); if (rc) return rc; if (newenv) { if (flags & MDB_FIXEDMAP) meta.mm_address = env->me_map; i = mdb_env_init_meta(env, &meta); if (i != MDB_SUCCESS) { return i; } } env->me_maxfree_1pg = (env->me_psize - PAGEHDRSZ) / sizeof(pgno_t) - 1; env->me_nodemax = (((env->me_psize - PAGEHDRSZ) / MDB_MINKEYS) & -2) - sizeof(indx_t); #if !(MDB_MAXKEYSIZE) env->me_maxkey = env->me_nodemax - (NODESIZE + sizeof(MDB_db)); #endif env->me_maxpg = env->me_mapsize / env->me_psize; #if MDB_DEBUG { int toggle = mdb_env_pick_meta(env); MDB_db *db = &env->me_metas[toggle]->mm_dbs[MAIN_DBI]; DPRINTF(("opened database version %u, pagesize %u", env->me_metas[0]->mm_version, env->me_psize)); DPRINTF(("using meta page %d", toggle)); DPRINTF(("depth: %u", db->md_depth)); DPRINTF(("entries: %"Z"u", db->md_entries)); DPRINTF(("branch pages: %"Z"u", db->md_branch_pages)); DPRINTF(("leaf pages: %"Z"u", db->md_leaf_pages)); DPRINTF(("overflow pages: %"Z"u", db->md_overflow_pages)); DPRINTF(("root: %"Z"u", db->md_root)); } #endif return MDB_SUCCESS; } /** Release a reader thread's slot in the reader lock table. * This function is called automatically when a thread exits. * @param[in] ptr This points to the slot in the reader lock table. */ static void mdb_env_reader_dest(void *ptr) { MDB_reader *reader = ptr; reader->mr_pid = 0; } #ifdef _WIN32 /** Junk for arranging thread-specific callbacks on Windows. This is * necessarily platform and compiler-specific. Windows supports up * to 1088 keys. Let's assume nobody opens more than 64 environments * in a single process, for now. They can override this if needed. */ #ifndef MAX_TLS_KEYS #define MAX_TLS_KEYS 64 #endif static pthread_key_t mdb_tls_keys[MAX_TLS_KEYS]; static int mdb_tls_nkeys; static void NTAPI mdb_tls_callback(PVOID module, DWORD reason, PVOID ptr) { int i; switch(reason) { case DLL_PROCESS_ATTACH: break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: for (i=0; ime_txns->mti_txnid = env->me_metas[toggle]->mm_txnid; #ifdef _WIN32 { OVERLAPPED ov; /* First acquire a shared lock. The Unlock will * then release the existing exclusive lock. */ memset(&ov, 0, sizeof(ov)); if (!LockFileEx(env->me_lfd, 0, 0, 1, 0, &ov)) { rc = ErrCode(); } else { UnlockFile(env->me_lfd, 0, 0, 1, 0); *excl = 0; } } #else { struct flock lock_info; /* The shared lock replaces the existing lock */ memset((void *)&lock_info, 0, sizeof(lock_info)); lock_info.l_type = F_RDLCK; lock_info.l_whence = SEEK_SET; lock_info.l_start = 0; lock_info.l_len = 1; while ((rc = fcntl(env->me_lfd, F_SETLK, &lock_info)) && (rc = ErrCode()) == EINTR) ; *excl = rc ? -1 : 0; /* error may mean we lost the lock */ } #endif return rc; } /** Try to get exclusive lock, otherwise shared. * Maintain *excl = -1: no/unknown lock, 0: shared, 1: exclusive. */ static int ESECT mdb_env_excl_lock(MDB_env *env, int *excl) { int rc = 0; #ifdef _WIN32 if (LockFile(env->me_lfd, 0, 0, 1, 0)) { *excl = 1; } else { OVERLAPPED ov; memset(&ov, 0, sizeof(ov)); if (LockFileEx(env->me_lfd, 0, 0, 1, 0, &ov)) { *excl = 0; } else { rc = ErrCode(); } } #else struct flock lock_info; memset((void *)&lock_info, 0, sizeof(lock_info)); lock_info.l_type = F_WRLCK; lock_info.l_whence = SEEK_SET; lock_info.l_start = 0; lock_info.l_len = 1; while ((rc = fcntl(env->me_lfd, F_SETLK, &lock_info)) && (rc = ErrCode()) == EINTR) ; if (!rc) { *excl = 1; } else # ifdef MDB_USE_POSIX_SEM if (*excl < 0) /* always true when !MDB_USE_POSIX_SEM */ # endif { lock_info.l_type = F_RDLCK; while ((rc = fcntl(env->me_lfd, F_SETLKW, &lock_info)) && (rc = ErrCode()) == EINTR) ; if (rc == 0) *excl = 0; } #endif return rc; } #ifdef MDB_USE_HASH /* * hash_64 - 64 bit Fowler/Noll/Vo-0 FNV-1a hash code * * @(#) $Revision: 5.1 $ * @(#) $Id: hash_64a.c,v 5.1 2009/06/30 09:01:38 chongo Exp $ * @(#) $Source: /usr/local/src/cmd/fnv/RCS/hash_64a.c,v $ * * http://www.isthe.com/chongo/tech/comp/fnv/index.html * *** * * Please do not copyright this code. This code is in the public domain. * * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO * EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * By: * chongo /\oo/\ * http://www.isthe.com/chongo/ * * Share and Enjoy! :-) */ typedef unsigned long long mdb_hash_t; #define MDB_HASH_INIT ((mdb_hash_t)0xcbf29ce484222325ULL) /** perform a 64 bit Fowler/Noll/Vo FNV-1a hash on a buffer * @param[in] val value to hash * @param[in] hval initial value for hash * @return 64 bit hash * * NOTE: To use the recommended 64 bit FNV-1a hash, use MDB_HASH_INIT as the * hval arg on the first call. */ static mdb_hash_t mdb_hash_val(MDB_val *val, mdb_hash_t hval) { unsigned char *s = (unsigned char *)val->mv_data; /* unsigned string */ unsigned char *end = s + val->mv_size; /* * FNV-1a hash each octet of the string */ while (s < end) { /* xor the bottom with the current octet */ hval ^= (mdb_hash_t)*s++; /* multiply by the 64 bit FNV magic prime mod 2^64 */ hval += (hval << 1) + (hval << 4) + (hval << 5) + (hval << 7) + (hval << 8) + (hval << 40); } /* return our new hash value */ return hval; } /** Hash the string and output the encoded hash. * This uses modified RFC1924 Ascii85 encoding to accommodate systems with * very short name limits. We don't care about the encoding being reversible, * we just want to preserve as many bits of the input as possible in a * small printable string. * @param[in] str string to hash * @param[out] encbuf an array of 11 chars to hold the hash */ static const char mdb_a85[]= "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~"; static void mdb_pack85(unsigned long l, char *out) { int i; for (i=0; i<5; i++) { *out++ = mdb_a85[l % 85]; l /= 85; } } static void mdb_hash_enc(MDB_val *val, char *encbuf) { mdb_hash_t h = mdb_hash_val(val, MDB_HASH_INIT); mdb_pack85(h, encbuf); mdb_pack85(h>>32, encbuf+5); encbuf[10] = '\0'; } #endif /** Open and/or initialize the lock region for the environment. * @param[in] env The LMDB environment. * @param[in] lpath The pathname of the file used for the lock region. * @param[in] mode The Unix permissions for the file, if we create it. * @param[in,out] excl In -1, out lock type: -1 none, 0 shared, 1 exclusive * @return 0 on success, non-zero on failure. */ static int ESECT mdb_env_setup_locks(MDB_env *env, char *lpath, int mode, int *excl) { #ifdef _WIN32 # define MDB_ERRCODE_ROFS ERROR_WRITE_PROTECT #else # define MDB_ERRCODE_ROFS EROFS #ifdef O_CLOEXEC /* Linux: Open file and set FD_CLOEXEC atomically */ # define MDB_CLOEXEC O_CLOEXEC #else int fdflags; # define MDB_CLOEXEC 0 #endif #endif int rc; off_t size, rsize; #ifdef _WIN32 env->me_lfd = CreateFile(lpath, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); #else env->me_lfd = open(lpath, O_RDWR|O_CREAT|MDB_CLOEXEC, mode); #endif if (env->me_lfd == INVALID_HANDLE_VALUE) { rc = ErrCode(); if (rc == MDB_ERRCODE_ROFS && (env->me_flags & MDB_RDONLY)) { return MDB_SUCCESS; } goto fail_errno; } #if ! ((MDB_CLOEXEC) || defined(_WIN32)) /* Lose record locks when exec*() */ if ((fdflags = fcntl(env->me_lfd, F_GETFD) | FD_CLOEXEC) >= 0) fcntl(env->me_lfd, F_SETFD, fdflags); #endif if (!(env->me_flags & MDB_NOTLS)) { rc = pthread_key_create(&env->me_txkey, mdb_env_reader_dest); if (rc) goto fail; env->me_flags |= MDB_ENV_TXKEY; #ifdef _WIN32 /* Windows TLS callbacks need help finding their TLS info. */ if (mdb_tls_nkeys >= MAX_TLS_KEYS) { rc = MDB_TLS_FULL; goto fail; } mdb_tls_keys[mdb_tls_nkeys++] = env->me_txkey; #endif } /* Try to get exclusive lock. If we succeed, then * nobody is using the lock region and we should initialize it. */ if ((rc = mdb_env_excl_lock(env, excl))) goto fail; #ifdef _WIN32 size = GetFileSize(env->me_lfd, NULL); #else size = lseek(env->me_lfd, 0, SEEK_END); if (size == -1) goto fail_errno; #endif rsize = (env->me_maxreaders-1) * sizeof(MDB_reader) + sizeof(MDB_txninfo); if (size < rsize && *excl > 0) { #ifdef _WIN32 if (SetFilePointer(env->me_lfd, rsize, NULL, FILE_BEGIN) != (DWORD)rsize || !SetEndOfFile(env->me_lfd)) goto fail_errno; #else if (ftruncate(env->me_lfd, rsize) != 0) goto fail_errno; #endif } else { rsize = size; size = rsize - sizeof(MDB_txninfo); env->me_maxreaders = size/sizeof(MDB_reader) + 1; } { #ifdef _WIN32 HANDLE mh; mh = CreateFileMapping(env->me_lfd, NULL, PAGE_READWRITE, 0, 0, NULL); if (!mh) goto fail_errno; env->me_txns = MapViewOfFileEx(mh, FILE_MAP_WRITE, 0, 0, rsize, NULL); CloseHandle(mh); if (!env->me_txns) goto fail_errno; #else void *m = mmap(NULL, rsize, PROT_READ|PROT_WRITE, MAP_SHARED, env->me_lfd, 0); if (m == MAP_FAILED) goto fail_errno; env->me_txns = m; #endif } if (*excl > 0) { #ifdef _WIN32 BY_HANDLE_FILE_INFORMATION stbuf; struct { DWORD volume; DWORD nhigh; DWORD nlow; } idbuf; MDB_val val; char encbuf[11]; if (!mdb_sec_inited) { InitializeSecurityDescriptor(&mdb_null_sd, SECURITY_DESCRIPTOR_REVISION); SetSecurityDescriptorDacl(&mdb_null_sd, TRUE, 0, FALSE); mdb_all_sa.nLength = sizeof(SECURITY_ATTRIBUTES); mdb_all_sa.bInheritHandle = FALSE; mdb_all_sa.lpSecurityDescriptor = &mdb_null_sd; mdb_sec_inited = 1; } if (!GetFileInformationByHandle(env->me_lfd, &stbuf)) goto fail_errno; idbuf.volume = stbuf.dwVolumeSerialNumber; idbuf.nhigh = stbuf.nFileIndexHigh; idbuf.nlow = stbuf.nFileIndexLow; val.mv_data = &idbuf; val.mv_size = sizeof(idbuf); mdb_hash_enc(&val, encbuf); sprintf(env->me_txns->mti_rmname, "Global\\MDBr%s", encbuf); sprintf(env->me_txns->mti_wmname, "Global\\MDBw%s", encbuf); env->me_rmutex = CreateMutex(&mdb_all_sa, FALSE, env->me_txns->mti_rmname); if (!env->me_rmutex) goto fail_errno; env->me_wmutex = CreateMutex(&mdb_all_sa, FALSE, env->me_txns->mti_wmname); if (!env->me_wmutex) goto fail_errno; #elif defined(MDB_USE_POSIX_SEM) struct stat stbuf; struct { dev_t dev; ino_t ino; } idbuf; MDB_val val; char encbuf[11]; #if defined(__NetBSD__) #define MDB_SHORT_SEMNAMES 1 /* limited to 14 chars */ #endif if (fstat(env->me_lfd, &stbuf)) goto fail_errno; idbuf.dev = stbuf.st_dev; idbuf.ino = stbuf.st_ino; val.mv_data = &idbuf; val.mv_size = sizeof(idbuf); mdb_hash_enc(&val, encbuf); #ifdef MDB_SHORT_SEMNAMES encbuf[9] = '\0'; /* drop name from 15 chars to 14 chars */ #endif sprintf(env->me_txns->mti_rmname, "/MDBr%s", encbuf); sprintf(env->me_txns->mti_wmname, "/MDBw%s", encbuf); /* Clean up after a previous run, if needed: Try to * remove both semaphores before doing anything else. */ sem_unlink(env->me_txns->mti_rmname); sem_unlink(env->me_txns->mti_wmname); env->me_rmutex = sem_open(env->me_txns->mti_rmname, O_CREAT|O_EXCL, mode, 1); if (env->me_rmutex == SEM_FAILED) goto fail_errno; env->me_wmutex = sem_open(env->me_txns->mti_wmname, O_CREAT|O_EXCL, mode, 1); if (env->me_wmutex == SEM_FAILED) goto fail_errno; #else /* MDB_USE_POSIX_SEM */ pthread_mutexattr_t mattr; if ((rc = pthread_mutexattr_init(&mattr)) || (rc = pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED)) || (rc = pthread_mutex_init(&env->me_txns->mti_mutex, &mattr)) || (rc = pthread_mutex_init(&env->me_txns->mti_wmutex, &mattr))) goto fail; pthread_mutexattr_destroy(&mattr); #endif /* _WIN32 || MDB_USE_POSIX_SEM */ env->me_txns->mti_magic = MDB_MAGIC; env->me_txns->mti_format = MDB_LOCK_FORMAT; env->me_txns->mti_txnid = 0; env->me_txns->mti_numreaders = 0; } else { if (env->me_txns->mti_magic != MDB_MAGIC) { DPUTS("lock region has invalid magic"); rc = MDB_INVALID; goto fail; } if (env->me_txns->mti_format != MDB_LOCK_FORMAT) { DPRINTF(("lock region has format+version 0x%x, expected 0x%x", env->me_txns->mti_format, MDB_LOCK_FORMAT)); rc = MDB_VERSION_MISMATCH; goto fail; } rc = ErrCode(); if (rc && rc != EACCES && rc != EAGAIN) { goto fail; } #ifdef _WIN32 env->me_rmutex = OpenMutex(SYNCHRONIZE, FALSE, env->me_txns->mti_rmname); if (!env->me_rmutex) goto fail_errno; env->me_wmutex = OpenMutex(SYNCHRONIZE, FALSE, env->me_txns->mti_wmname); if (!env->me_wmutex) goto fail_errno; #elif defined(MDB_USE_POSIX_SEM) env->me_rmutex = sem_open(env->me_txns->mti_rmname, 0); if (env->me_rmutex == SEM_FAILED) goto fail_errno; env->me_wmutex = sem_open(env->me_txns->mti_wmname, 0); if (env->me_wmutex == SEM_FAILED) goto fail_errno; #endif } return MDB_SUCCESS; fail_errno: rc = ErrCode(); fail: return rc; } /** The name of the lock file in the DB environment */ #define LOCKNAME "/lock.mdb" /** The name of the data file in the DB environment */ #define DATANAME "/data.mdb" /** The suffix of the lock file when no subdir is used */ #define LOCKSUFF "-lock" /** Only a subset of the @ref mdb_env flags can be changed * at runtime. Changing other flags requires closing the * environment and re-opening it with the new flags. */ #define CHANGEABLE (MDB_NOSYNC|MDB_NOMETASYNC|MDB_MAPASYNC|MDB_NOMEMINIT) #define CHANGELESS (MDB_FIXEDMAP|MDB_NOSUBDIR|MDB_RDONLY|MDB_WRITEMAP| \ MDB_NOTLS|MDB_NOLOCK|MDB_NORDAHEAD) #if VALID_FLAGS & PERSISTENT_FLAGS & (CHANGEABLE|CHANGELESS) # error "Persistent DB flags & env flags overlap, but both go in mm_flags" #endif int ESECT mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mdb_mode_t mode) { int oflags, rc, len, excl = -1; char *lpath, *dpath; if (env->me_fd!=INVALID_HANDLE_VALUE || (flags & ~(CHANGEABLE|CHANGELESS))) return EINVAL; len = strlen(path); if (flags & MDB_NOSUBDIR) { rc = len + sizeof(LOCKSUFF) + len + 1; } else { rc = len + sizeof(LOCKNAME) + len + sizeof(DATANAME); } lpath = malloc(rc); if (!lpath) return ENOMEM; if (flags & MDB_NOSUBDIR) { dpath = lpath + len + sizeof(LOCKSUFF); sprintf(lpath, "%s" LOCKSUFF, path); strcpy(dpath, path); } else { dpath = lpath + len + sizeof(LOCKNAME); sprintf(lpath, "%s" LOCKNAME, path); sprintf(dpath, "%s" DATANAME, path); } rc = MDB_SUCCESS; flags |= env->me_flags; if (flags & MDB_RDONLY) { /* silently ignore WRITEMAP when we're only getting read access */ flags &= ~MDB_WRITEMAP; } else { if (!((env->me_free_pgs = mdb_midl_alloc(MDB_IDL_UM_MAX)) && (env->me_dirty_list = calloc(MDB_IDL_UM_SIZE, sizeof(MDB_ID2))))) rc = ENOMEM; } env->me_flags = flags |= MDB_ENV_ACTIVE; if (rc) goto leave; env->me_path = strdup(path); env->me_dbxs = calloc(env->me_maxdbs, sizeof(MDB_dbx)); env->me_dbflags = calloc(env->me_maxdbs, sizeof(uint16_t)); env->me_dbiseqs = calloc(env->me_maxdbs, sizeof(unsigned int)); if (!(env->me_dbxs && env->me_path && env->me_dbflags && env->me_dbiseqs)) { rc = ENOMEM; goto leave; } /* For RDONLY, get lockfile after we know datafile exists */ if (!(flags & (MDB_RDONLY|MDB_NOLOCK))) { rc = mdb_env_setup_locks(env, lpath, mode, &excl); if (rc) goto leave; } #ifdef _WIN32 if (F_ISSET(flags, MDB_RDONLY)) { oflags = GENERIC_READ; len = OPEN_EXISTING; } else { oflags = GENERIC_READ|GENERIC_WRITE; len = OPEN_ALWAYS; } mode = FILE_ATTRIBUTE_NORMAL; env->me_fd = CreateFile(dpath, oflags, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, len, mode, NULL); #else if (F_ISSET(flags, MDB_RDONLY)) oflags = O_RDONLY; else oflags = O_RDWR | O_CREAT; env->me_fd = open(dpath, oflags, mode); #endif if (env->me_fd == INVALID_HANDLE_VALUE) { rc = ErrCode(); goto leave; } if ((flags & (MDB_RDONLY|MDB_NOLOCK)) == MDB_RDONLY) { rc = mdb_env_setup_locks(env, lpath, mode, &excl); if (rc) goto leave; } if ((rc = mdb_env_open2(env)) == MDB_SUCCESS) { if (flags & (MDB_RDONLY|MDB_WRITEMAP)) { env->me_mfd = env->me_fd; } else { /* Synchronous fd for meta writes. Needed even with * MDB_NOSYNC/MDB_NOMETASYNC, in case these get reset. */ #ifdef _WIN32 len = OPEN_EXISTING; env->me_mfd = CreateFile(dpath, oflags, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, len, mode | FILE_FLAG_WRITE_THROUGH, NULL); #else oflags &= ~O_CREAT; env->me_mfd = open(dpath, oflags | MDB_DSYNC, mode); #endif if (env->me_mfd == INVALID_HANDLE_VALUE) { rc = ErrCode(); goto leave; } } DPRINTF(("opened dbenv %p", (void *) env)); if (excl > 0) { rc = mdb_env_share_locks(env, &excl); if (rc) goto leave; } if (!((flags & MDB_RDONLY) || (env->me_pbuf = calloc(1, env->me_psize)))) rc = ENOMEM; if (!(flags & MDB_RDONLY)) { MDB_txn *txn; int tsize = sizeof(MDB_txn), size = tsize + env->me_maxdbs * (sizeof(MDB_db)+sizeof(MDB_cursor *)+sizeof(unsigned int)+1); txn = calloc(1, size); if (txn) { txn->mt_dbs = (MDB_db *)((char *)txn + tsize); txn->mt_cursors = (MDB_cursor **)(txn->mt_dbs + env->me_maxdbs); txn->mt_dbiseqs = (unsigned int *)(txn->mt_cursors + env->me_maxdbs); txn->mt_dbflags = (unsigned char *)(txn->mt_dbiseqs + env->me_maxdbs); txn->mt_env = env; txn->mt_dbxs = env->me_dbxs; env->me_txn0 = txn; } else { rc = ENOMEM; } } } leave: if (rc) { mdb_env_close0(env, excl); } free(lpath); return rc; } /** Destroy resources from mdb_env_open(), clear our readers & DBIs */ static void ESECT mdb_env_close0(MDB_env *env, int excl) { int i; if (!(env->me_flags & MDB_ENV_ACTIVE)) return; /* Doing this here since me_dbxs may not exist during mdb_env_close */ if (env->me_dbxs) { for (i = env->me_maxdbs; --i > MAIN_DBI; ) free(env->me_dbxs[i].md_name.mv_data); free(env->me_dbxs); } free(env->me_pbuf); free(env->me_dbiseqs); free(env->me_dbflags); free(env->me_path); free(env->me_dirty_list); free(env->me_txn0); mdb_midl_free(env->me_free_pgs); if (env->me_flags & MDB_ENV_TXKEY) { pthread_key_delete(env->me_txkey); #ifdef _WIN32 /* Delete our key from the global list */ for (i=0; ime_txkey) { mdb_tls_keys[i] = mdb_tls_keys[mdb_tls_nkeys-1]; mdb_tls_nkeys--; break; } #endif } if (env->me_map) { munmap(env->me_map, env->me_mapsize); } if (env->me_mfd != env->me_fd && env->me_mfd != INVALID_HANDLE_VALUE) (void) close(env->me_mfd); if (env->me_fd != INVALID_HANDLE_VALUE) (void) close(env->me_fd); if (env->me_txns) { MDB_PID_T pid = env->me_pid; /* Clearing readers is done in this function because * me_txkey with its destructor must be disabled first. */ for (i = env->me_numreaders; --i >= 0; ) if (env->me_txns->mti_readers[i].mr_pid == pid) env->me_txns->mti_readers[i].mr_pid = 0; #ifdef _WIN32 if (env->me_rmutex) { CloseHandle(env->me_rmutex); if (env->me_wmutex) CloseHandle(env->me_wmutex); } /* Windows automatically destroys the mutexes when * the last handle closes. */ #elif defined(MDB_USE_POSIX_SEM) if (env->me_rmutex != SEM_FAILED) { sem_close(env->me_rmutex); if (env->me_wmutex != SEM_FAILED) sem_close(env->me_wmutex); /* If we have the filelock: If we are the * only remaining user, clean up semaphores. */ if (excl == 0) mdb_env_excl_lock(env, &excl); if (excl > 0) { sem_unlink(env->me_txns->mti_rmname); sem_unlink(env->me_txns->mti_wmname); } } #endif munmap((void *)env->me_txns, (env->me_maxreaders-1)*sizeof(MDB_reader)+sizeof(MDB_txninfo)); } if (env->me_lfd != INVALID_HANDLE_VALUE) { #ifdef _WIN32 if (excl >= 0) { /* Unlock the lockfile. Windows would have unlocked it * after closing anyway, but not necessarily at once. */ UnlockFile(env->me_lfd, 0, 0, 1, 0); } #endif (void) close(env->me_lfd); } env->me_flags &= ~(MDB_ENV_ACTIVE|MDB_ENV_TXKEY); } void ESECT mdb_env_close(MDB_env *env) { MDB_page *dp; if (env == NULL) return; VGMEMP_DESTROY(env); while ((dp = env->me_dpages) != NULL) { VGMEMP_DEFINED(&dp->mp_next, sizeof(dp->mp_next)); env->me_dpages = dp->mp_next; free(dp); } mdb_env_close0(env, 0); free(env); } /** Compare two items pointing at aligned size_t's */ static int mdb_cmp_long(const MDB_val *a, const MDB_val *b) { return (*(size_t *)a->mv_data < *(size_t *)b->mv_data) ? -1 : *(size_t *)a->mv_data > *(size_t *)b->mv_data; } /** Compare two items pointing at aligned unsigned int's. * * This is also set as #MDB_INTEGERDUP|#MDB_DUPFIXED's #MDB_dbx.%md_dcmp, * but #mdb_cmp_clong() is called instead if the data type is size_t. */ static int mdb_cmp_int(const MDB_val *a, const MDB_val *b) { return (*(unsigned int *)a->mv_data < *(unsigned int *)b->mv_data) ? -1 : *(unsigned int *)a->mv_data > *(unsigned int *)b->mv_data; } /** Compare two items pointing at unsigned ints of unknown alignment. * Nodes and keys are guaranteed to be 2-byte aligned. */ static int mdb_cmp_cint(const MDB_val *a, const MDB_val *b) { #if BYTE_ORDER == LITTLE_ENDIAN unsigned short *u, *c; int x; u = (unsigned short *) ((char *) a->mv_data + a->mv_size); c = (unsigned short *) ((char *) b->mv_data + a->mv_size); do { x = *--u - *--c; } while(!x && u > (unsigned short *)a->mv_data); return x; #else unsigned short *u, *c, *end; int x; end = (unsigned short *) ((char *) a->mv_data + a->mv_size); u = (unsigned short *)a->mv_data; c = (unsigned short *)b->mv_data; do { x = *u++ - *c++; } while(!x && u < end); return x; #endif } /** Compare two items lexically */ static int mdb_cmp_memn(const MDB_val *a, const MDB_val *b) { int diff; ssize_t len_diff; unsigned int len; len = a->mv_size; len_diff = (ssize_t) a->mv_size - (ssize_t) b->mv_size; if (len_diff > 0) { len = b->mv_size; len_diff = 1; } diff = memcmp(a->mv_data, b->mv_data, len); return diff ? diff : len_diff<0 ? -1 : len_diff; } /** Compare two items in reverse byte order */ static int mdb_cmp_memnr(const MDB_val *a, const MDB_val *b) { const unsigned char *p1, *p2, *p1_lim; ssize_t len_diff; int diff; p1_lim = (const unsigned char *)a->mv_data; p1 = (const unsigned char *)a->mv_data + a->mv_size; p2 = (const unsigned char *)b->mv_data + b->mv_size; len_diff = (ssize_t) a->mv_size - (ssize_t) b->mv_size; if (len_diff > 0) { p1_lim += len_diff; len_diff = 1; } while (p1 > p1_lim) { diff = *--p1 - *--p2; if (diff) return diff; } return len_diff<0 ? -1 : len_diff; } /** Search for key within a page, using binary search. * Returns the smallest entry larger or equal to the key. * If exactp is non-null, stores whether the found entry was an exact match * in *exactp (1 or 0). * Updates the cursor index with the index of the found entry. * If no entry larger or equal to the key is found, returns NULL. */ static MDB_node * mdb_node_search(MDB_cursor *mc, MDB_val *key, int *exactp) { unsigned int i = 0, nkeys; int low, high; int rc = 0; MDB_page *mp = mc->mc_pg[mc->mc_top]; MDB_node *node = NULL; MDB_val nodekey; MDB_cmp_func *cmp; DKBUF; nkeys = NUMKEYS(mp); DPRINTF(("searching %u keys in %s %spage %"Z"u", nkeys, IS_LEAF(mp) ? "leaf" : "branch", IS_SUBP(mp) ? "sub-" : "", mdb_dbg_pgno(mp))); low = IS_LEAF(mp) ? 0 : 1; high = nkeys - 1; cmp = mc->mc_dbx->md_cmp; /* Branch pages have no data, so if using integer keys, * alignment is guaranteed. Use faster mdb_cmp_int. */ if (cmp == mdb_cmp_cint && IS_BRANCH(mp)) { if (NODEPTR(mp, 1)->mn_ksize == sizeof(size_t)) cmp = mdb_cmp_long; else cmp = mdb_cmp_int; } if (IS_LEAF2(mp)) { nodekey.mv_size = mc->mc_db->md_pad; node = NODEPTR(mp, 0); /* fake */ while (low <= high) { i = (low + high) >> 1; nodekey.mv_data = LEAF2KEY(mp, i, nodekey.mv_size); rc = cmp(key, &nodekey); DPRINTF(("found leaf index %u [%s], rc = %i", i, DKEY(&nodekey), rc)); if (rc == 0) break; if (rc > 0) low = i + 1; else high = i - 1; } } else { while (low <= high) { i = (low + high) >> 1; node = NODEPTR(mp, i); nodekey.mv_size = NODEKSZ(node); nodekey.mv_data = NODEKEY(node); rc = cmp(key, &nodekey); #if MDB_DEBUG if (IS_LEAF(mp)) DPRINTF(("found leaf index %u [%s], rc = %i", i, DKEY(&nodekey), rc)); else DPRINTF(("found branch index %u [%s -> %"Z"u], rc = %i", i, DKEY(&nodekey), NODEPGNO(node), rc)); #endif if (rc == 0) break; if (rc > 0) low = i + 1; else high = i - 1; } } if (rc > 0) { /* Found entry is less than the key. */ i++; /* Skip to get the smallest entry larger than key. */ if (!IS_LEAF2(mp)) node = NODEPTR(mp, i); } if (exactp) *exactp = (rc == 0 && nkeys > 0); /* store the key index */ mc->mc_ki[mc->mc_top] = i; if (i >= nkeys) /* There is no entry larger or equal to the key. */ return NULL; /* nodeptr is fake for LEAF2 */ return node; } #if 0 static void mdb_cursor_adjust(MDB_cursor *mc, func) { MDB_cursor *m2; for (m2 = mc->mc_txn->mt_cursors[mc->mc_dbi]; m2; m2=m2->mc_next) { if (m2->mc_pg[m2->mc_top] == mc->mc_pg[mc->mc_top]) { func(mc, m2); } } } #endif /** Pop a page off the top of the cursor's stack. */ static void mdb_cursor_pop(MDB_cursor *mc) { if (mc->mc_snum) { #if MDB_DEBUG MDB_page *top = mc->mc_pg[mc->mc_top]; #endif mc->mc_snum--; if (mc->mc_snum) mc->mc_top--; DPRINTF(("popped page %"Z"u off db %d cursor %p", top->mp_pgno, DDBI(mc), (void *) mc)); } } /** Push a page onto the top of the cursor's stack. */ static int mdb_cursor_push(MDB_cursor *mc, MDB_page *mp) { DPRINTF(("pushing page %"Z"u on db %d cursor %p", mp->mp_pgno, DDBI(mc), (void *) mc)); if (mc->mc_snum >= CURSOR_STACK) { mc->mc_txn->mt_flags |= MDB_TXN_ERROR; return MDB_CURSOR_FULL; } mc->mc_top = mc->mc_snum++; mc->mc_pg[mc->mc_top] = mp; mc->mc_ki[mc->mc_top] = 0; return MDB_SUCCESS; } /** Find the address of the page corresponding to a given page number. * @param[in] txn the transaction for this access. * @param[in] pgno the page number for the page to retrieve. * @param[out] ret address of a pointer where the page's address will be stored. * @param[out] lvl dirty_list inheritance level of found page. 1=current txn, 0=mapped page. * @return 0 on success, non-zero on failure. */ static int mdb_page_get(MDB_txn *txn, pgno_t pgno, MDB_page **ret, int *lvl) { MDB_env *env = txn->mt_env; MDB_page *p = NULL; int level; if (!((txn->mt_flags & MDB_TXN_RDONLY) | (env->me_flags & MDB_WRITEMAP))) { MDB_txn *tx2 = txn; level = 1; do { MDB_ID2L dl = tx2->mt_u.dirty_list; unsigned x; /* Spilled pages were dirtied in this txn and flushed * because the dirty list got full. Bring this page * back in from the map (but don't unspill it here, * leave that unless page_touch happens again). */ if (tx2->mt_spill_pgs) { MDB_ID pn = pgno << 1; x = mdb_midl_search(tx2->mt_spill_pgs, pn); if (x <= tx2->mt_spill_pgs[0] && tx2->mt_spill_pgs[x] == pn) { p = (MDB_page *)(env->me_map + env->me_psize * pgno); goto done; } } if (dl[0].mid) { unsigned x = mdb_mid2l_search(dl, pgno); if (x <= dl[0].mid && dl[x].mid == pgno) { p = dl[x].mptr; goto done; } } level++; } while ((tx2 = tx2->mt_parent) != NULL); } if (pgno < txn->mt_next_pgno) { level = 0; p = (MDB_page *)(env->me_map + env->me_psize * pgno); } else { DPRINTF(("page %"Z"u not found", pgno)); txn->mt_flags |= MDB_TXN_ERROR; return MDB_PAGE_NOTFOUND; } done: *ret = p; if (lvl) *lvl = level; return MDB_SUCCESS; } /** Finish #mdb_page_search() / #mdb_page_search_lowest(). * The cursor is at the root page, set up the rest of it. */ static int mdb_page_search_root(MDB_cursor *mc, MDB_val *key, int flags) { MDB_page *mp = mc->mc_pg[mc->mc_top]; int rc; DKBUF; while (IS_BRANCH(mp)) { MDB_node *node; indx_t i; DPRINTF(("branch page %"Z"u has %u keys", mp->mp_pgno, NUMKEYS(mp))); mdb_cassert(mc, NUMKEYS(mp) > 1); DPRINTF(("found index 0 to page %"Z"u", NODEPGNO(NODEPTR(mp, 0)))); if (flags & (MDB_PS_FIRST|MDB_PS_LAST)) { i = 0; if (flags & MDB_PS_LAST) i = NUMKEYS(mp) - 1; } else { int exact; node = mdb_node_search(mc, key, &exact); if (node == NULL) i = NUMKEYS(mp) - 1; else { i = mc->mc_ki[mc->mc_top]; if (!exact) { mdb_cassert(mc, i > 0); i--; } } DPRINTF(("following index %u for key [%s]", i, DKEY(key))); } mdb_cassert(mc, i < NUMKEYS(mp)); node = NODEPTR(mp, i); if ((rc = mdb_page_get(mc->mc_txn, NODEPGNO(node), &mp, NULL)) != 0) return rc; mc->mc_ki[mc->mc_top] = i; if ((rc = mdb_cursor_push(mc, mp))) return rc; if (flags & MDB_PS_MODIFY) { if ((rc = mdb_page_touch(mc)) != 0) return rc; mp = mc->mc_pg[mc->mc_top]; } } if (!IS_LEAF(mp)) { DPRINTF(("internal error, index points to a %02X page!?", mp->mp_flags)); mc->mc_txn->mt_flags |= MDB_TXN_ERROR; return MDB_CORRUPTED; } DPRINTF(("found leaf page %"Z"u for key [%s]", mp->mp_pgno, key ? DKEY(key) : "null")); mc->mc_flags |= C_INITIALIZED; mc->mc_flags &= ~C_EOF; return MDB_SUCCESS; } /** Search for the lowest key under the current branch page. * This just bypasses a NUMKEYS check in the current page * before calling mdb_page_search_root(), because the callers * are all in situations where the current page is known to * be underfilled. */ static int mdb_page_search_lowest(MDB_cursor *mc) { MDB_page *mp = mc->mc_pg[mc->mc_top]; MDB_node *node = NODEPTR(mp, 0); int rc; if ((rc = mdb_page_get(mc->mc_txn, NODEPGNO(node), &mp, NULL)) != 0) return rc; mc->mc_ki[mc->mc_top] = 0; if ((rc = mdb_cursor_push(mc, mp))) return rc; return mdb_page_search_root(mc, NULL, MDB_PS_FIRST); } /** Search for the page a given key should be in. * Push it and its parent pages on the cursor stack. * @param[in,out] mc the cursor for this operation. * @param[in] key the key to search for, or NULL for first/last page. * @param[in] flags If MDB_PS_MODIFY is set, visited pages in the DB * are touched (updated with new page numbers). * If MDB_PS_FIRST or MDB_PS_LAST is set, find first or last leaf. * This is used by #mdb_cursor_first() and #mdb_cursor_last(). * If MDB_PS_ROOTONLY set, just fetch root node, no further lookups. * @return 0 on success, non-zero on failure. */ static int mdb_page_search(MDB_cursor *mc, MDB_val *key, int flags) { int rc; pgno_t root; /* Make sure the txn is still viable, then find the root from * the txn's db table and set it as the root of the cursor's stack. */ if (F_ISSET(mc->mc_txn->mt_flags, MDB_TXN_ERROR)) { DPUTS("transaction has failed, must abort"); return MDB_BAD_TXN; } else { /* Make sure we're using an up-to-date root */ if (*mc->mc_dbflag & DB_STALE) { MDB_cursor mc2; if (TXN_DBI_CHANGED(mc->mc_txn, mc->mc_dbi)) return MDB_BAD_DBI; mdb_cursor_init(&mc2, mc->mc_txn, MAIN_DBI, NULL); rc = mdb_page_search(&mc2, &mc->mc_dbx->md_name, 0); if (rc) return rc; { MDB_val data; int exact = 0; uint16_t flags; MDB_node *leaf = mdb_node_search(&mc2, &mc->mc_dbx->md_name, &exact); if (!exact) return MDB_NOTFOUND; if ((leaf->mn_flags & (F_DUPDATA|F_SUBDATA)) != F_SUBDATA) return MDB_INCOMPATIBLE; /* not a named DB */ rc = mdb_node_read(mc->mc_txn, leaf, &data); if (rc) return rc; memcpy(&flags, ((char *) data.mv_data + offsetof(MDB_db, md_flags)), sizeof(uint16_t)); /* The txn may not know this DBI, or another process may * have dropped and recreated the DB with other flags. */ if ((mc->mc_db->md_flags & PERSISTENT_FLAGS) != flags) return MDB_INCOMPATIBLE; memcpy(mc->mc_db, data.mv_data, sizeof(MDB_db)); } *mc->mc_dbflag &= ~DB_STALE; } root = mc->mc_db->md_root; if (root == P_INVALID) { /* Tree is empty. */ DPUTS("tree is empty"); return MDB_NOTFOUND; } } mdb_cassert(mc, root > 1); if (!mc->mc_pg[0] || mc->mc_pg[0]->mp_pgno != root) if ((rc = mdb_page_get(mc->mc_txn, root, &mc->mc_pg[0], NULL)) != 0) return rc; mc->mc_snum = 1; mc->mc_top = 0; DPRINTF(("db %d root page %"Z"u has flags 0x%X", DDBI(mc), root, mc->mc_pg[0]->mp_flags)); if (flags & MDB_PS_MODIFY) { if ((rc = mdb_page_touch(mc))) return rc; } if (flags & MDB_PS_ROOTONLY) return MDB_SUCCESS; return mdb_page_search_root(mc, key, flags); } static int mdb_ovpage_free(MDB_cursor *mc, MDB_page *mp) { MDB_txn *txn = mc->mc_txn; pgno_t pg = mp->mp_pgno; unsigned x = 0, ovpages = mp->mp_pages; MDB_env *env = txn->mt_env; MDB_IDL sl = txn->mt_spill_pgs; MDB_ID pn = pg << 1; int rc; DPRINTF(("free ov page %"Z"u (%d)", pg, ovpages)); /* If the page is dirty or on the spill list we just acquired it, * so we should give it back to our current free list, if any. * Otherwise put it onto the list of pages we freed in this txn. * * Won't create me_pghead: me_pglast must be inited along with it. * Unsupported in nested txns: They would need to hide the page * range in ancestor txns' dirty and spilled lists. */ if (env->me_pghead && !txn->mt_parent && ((mp->mp_flags & P_DIRTY) || (sl && (x = mdb_midl_search(sl, pn)) <= sl[0] && sl[x] == pn))) { unsigned i, j; pgno_t *mop; MDB_ID2 *dl, ix, iy; rc = mdb_midl_need(&env->me_pghead, ovpages); if (rc) return rc; if (!(mp->mp_flags & P_DIRTY)) { /* This page is no longer spilled */ if (x == sl[0]) sl[0]--; else sl[x] |= 1; goto release; } /* Remove from dirty list */ dl = txn->mt_u.dirty_list; x = dl[0].mid--; for (ix = dl[x]; ix.mptr != mp; ix = iy) { if (x > 1) { x--; iy = dl[x]; dl[x] = ix; } else { mdb_cassert(mc, x > 1); j = ++(dl[0].mid); dl[j] = ix; /* Unsorted. OK when MDB_TXN_ERROR. */ txn->mt_flags |= MDB_TXN_ERROR; return MDB_CORRUPTED; } } if (!(env->me_flags & MDB_WRITEMAP)) mdb_dpage_free(env, mp); release: /* Insert in me_pghead */ mop = env->me_pghead; j = mop[0] + ovpages; for (i = mop[0]; i && mop[i] < pg; i--) mop[j--] = mop[i]; while (j>i) mop[j--] = pg++; mop[0] += ovpages; } else { rc = mdb_midl_append_range(&txn->mt_free_pgs, pg, ovpages); if (rc) return rc; } mc->mc_db->md_overflow_pages -= ovpages; return 0; } /** Return the data associated with a given node. * @param[in] txn The transaction for this operation. * @param[in] leaf The node being read. * @param[out] data Updated to point to the node's data. * @return 0 on success, non-zero on failure. */ static int mdb_node_read(MDB_txn *txn, MDB_node *leaf, MDB_val *data) { MDB_page *omp; /* overflow page */ pgno_t pgno; int rc; if (!F_ISSET(leaf->mn_flags, F_BIGDATA)) { data->mv_size = NODEDSZ(leaf); data->mv_data = NODEDATA(leaf); return MDB_SUCCESS; } /* Read overflow data. */ data->mv_size = NODEDSZ(leaf); memcpy(&pgno, NODEDATA(leaf), sizeof(pgno)); if ((rc = mdb_page_get(txn, pgno, &omp, NULL)) != 0) { DPRINTF(("read overflow page %"Z"u failed", pgno)); return rc; } data->mv_data = METADATA(omp); return MDB_SUCCESS; } int mdb_get(MDB_txn *txn, MDB_dbi dbi, MDB_val *key, MDB_val *data) { MDB_cursor mc; MDB_xcursor mx; int exact = 0; DKBUF; DPRINTF(("===> get db %u key [%s]", dbi, DKEY(key))); if (!key || !data || dbi == FREE_DBI || !TXN_DBI_EXIST(txn, dbi)) return EINVAL; if (txn->mt_flags & MDB_TXN_ERROR) return MDB_BAD_TXN; mdb_cursor_init(&mc, txn, dbi, &mx); return mdb_cursor_set(&mc, key, data, MDB_SET, &exact); } /** Find a sibling for a page. * Replaces the page at the top of the cursor's stack with the * specified sibling, if one exists. * @param[in] mc The cursor for this operation. * @param[in] move_right Non-zero if the right sibling is requested, * otherwise the left sibling. * @return 0 on success, non-zero on failure. */ static int mdb_cursor_sibling(MDB_cursor *mc, int move_right) { int rc; MDB_node *indx; MDB_page *mp; if (mc->mc_snum < 2) { return MDB_NOTFOUND; /* root has no siblings */ } mdb_cursor_pop(mc); DPRINTF(("parent page is page %"Z"u, index %u", mc->mc_pg[mc->mc_top]->mp_pgno, mc->mc_ki[mc->mc_top])); if (move_right ? (mc->mc_ki[mc->mc_top] + 1u >= NUMKEYS(mc->mc_pg[mc->mc_top])) : (mc->mc_ki[mc->mc_top] == 0)) { DPRINTF(("no more keys left, moving to %s sibling", move_right ? "right" : "left")); if ((rc = mdb_cursor_sibling(mc, move_right)) != MDB_SUCCESS) { /* undo cursor_pop before returning */ mc->mc_top++; mc->mc_snum++; return rc; } } else { if (move_right) mc->mc_ki[mc->mc_top]++; else mc->mc_ki[mc->mc_top]--; DPRINTF(("just moving to %s index key %u", move_right ? "right" : "left", mc->mc_ki[mc->mc_top])); } mdb_cassert(mc, IS_BRANCH(mc->mc_pg[mc->mc_top])); indx = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]); if ((rc = mdb_page_get(mc->mc_txn, NODEPGNO(indx), &mp, NULL)) != 0) { /* mc will be inconsistent if caller does mc_snum++ as above */ mc->mc_flags &= ~(C_INITIALIZED|C_EOF); return rc; } mdb_cursor_push(mc, mp); if (!move_right) mc->mc_ki[mc->mc_top] = NUMKEYS(mp)-1; return MDB_SUCCESS; } /** Move the cursor to the next data item. */ static int mdb_cursor_next(MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_cursor_op op) { MDB_page *mp; MDB_node *leaf; int rc; if (mc->mc_flags & C_EOF) { return MDB_NOTFOUND; } mdb_cassert(mc, mc->mc_flags & C_INITIALIZED); mp = mc->mc_pg[mc->mc_top]; if (mc->mc_db->md_flags & MDB_DUPSORT) { leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]); if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { if (op == MDB_NEXT || op == MDB_NEXT_DUP) { rc = mdb_cursor_next(&mc->mc_xcursor->mx_cursor, data, NULL, MDB_NEXT); if (op != MDB_NEXT || rc != MDB_NOTFOUND) { if (rc == MDB_SUCCESS) MDB_GET_KEY(leaf, key); return rc; } } } else { mc->mc_xcursor->mx_cursor.mc_flags &= ~(C_INITIALIZED|C_EOF); if (op == MDB_NEXT_DUP) return MDB_NOTFOUND; } } DPRINTF(("cursor_next: top page is %"Z"u in cursor %p", mdb_dbg_pgno(mp), (void *) mc)); if (mc->mc_flags & C_DEL) goto skip; if (mc->mc_ki[mc->mc_top] + 1u >= NUMKEYS(mp)) { DPUTS("=====> move to next sibling page"); if ((rc = mdb_cursor_sibling(mc, 1)) != MDB_SUCCESS) { mc->mc_flags |= C_EOF; return rc; } mp = mc->mc_pg[mc->mc_top]; DPRINTF(("next page is %"Z"u, key index %u", mp->mp_pgno, mc->mc_ki[mc->mc_top])); } else mc->mc_ki[mc->mc_top]++; skip: DPRINTF(("==> cursor points to page %"Z"u with %u keys, key index %u", mdb_dbg_pgno(mp), NUMKEYS(mp), mc->mc_ki[mc->mc_top])); if (IS_LEAF2(mp)) { key->mv_size = mc->mc_db->md_pad; key->mv_data = LEAF2KEY(mp, mc->mc_ki[mc->mc_top], key->mv_size); return MDB_SUCCESS; } mdb_cassert(mc, IS_LEAF(mp)); leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]); if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { mdb_xcursor_init1(mc, leaf); } if (data) { if ((rc = mdb_node_read(mc->mc_txn, leaf, data)) != MDB_SUCCESS) return rc; if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { rc = mdb_cursor_first(&mc->mc_xcursor->mx_cursor, data, NULL); if (rc != MDB_SUCCESS) return rc; } } MDB_GET_KEY(leaf, key); return MDB_SUCCESS; } /** Move the cursor to the previous data item. */ static int mdb_cursor_prev(MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_cursor_op op) { MDB_page *mp; MDB_node *leaf; int rc; mdb_cassert(mc, mc->mc_flags & C_INITIALIZED); mp = mc->mc_pg[mc->mc_top]; if (mc->mc_db->md_flags & MDB_DUPSORT) { leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]); if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { if (op == MDB_PREV || op == MDB_PREV_DUP) { rc = mdb_cursor_prev(&mc->mc_xcursor->mx_cursor, data, NULL, MDB_PREV); if (op != MDB_PREV || rc != MDB_NOTFOUND) { if (rc == MDB_SUCCESS) { MDB_GET_KEY(leaf, key); mc->mc_flags &= ~C_EOF; } return rc; } } } else { mc->mc_xcursor->mx_cursor.mc_flags &= ~(C_INITIALIZED|C_EOF); if (op == MDB_PREV_DUP) return MDB_NOTFOUND; } } DPRINTF(("cursor_prev: top page is %"Z"u in cursor %p", mdb_dbg_pgno(mp), (void *) mc)); if (mc->mc_ki[mc->mc_top] == 0) { DPUTS("=====> move to prev sibling page"); if ((rc = mdb_cursor_sibling(mc, 0)) != MDB_SUCCESS) { return rc; } mp = mc->mc_pg[mc->mc_top]; mc->mc_ki[mc->mc_top] = NUMKEYS(mp) - 1; DPRINTF(("prev page is %"Z"u, key index %u", mp->mp_pgno, mc->mc_ki[mc->mc_top])); } else mc->mc_ki[mc->mc_top]--; mc->mc_flags &= ~C_EOF; DPRINTF(("==> cursor points to page %"Z"u with %u keys, key index %u", mdb_dbg_pgno(mp), NUMKEYS(mp), mc->mc_ki[mc->mc_top])); if (IS_LEAF2(mp)) { key->mv_size = mc->mc_db->md_pad; key->mv_data = LEAF2KEY(mp, mc->mc_ki[mc->mc_top], key->mv_size); return MDB_SUCCESS; } mdb_cassert(mc, IS_LEAF(mp)); leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]); if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { mdb_xcursor_init1(mc, leaf); } if (data) { if ((rc = mdb_node_read(mc->mc_txn, leaf, data)) != MDB_SUCCESS) return rc; if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { rc = mdb_cursor_last(&mc->mc_xcursor->mx_cursor, data, NULL); if (rc != MDB_SUCCESS) return rc; } } MDB_GET_KEY(leaf, key); return MDB_SUCCESS; } /** Set the cursor on a specific data item. */ static int mdb_cursor_set(MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_cursor_op op, int *exactp) { int rc; MDB_page *mp; MDB_node *leaf = NULL; DKBUF; if (key->mv_size == 0) return MDB_BAD_VALSIZE; if (mc->mc_xcursor) mc->mc_xcursor->mx_cursor.mc_flags &= ~(C_INITIALIZED|C_EOF); /* See if we're already on the right page */ if (mc->mc_flags & C_INITIALIZED) { MDB_val nodekey; mp = mc->mc_pg[mc->mc_top]; if (!NUMKEYS(mp)) { mc->mc_ki[mc->mc_top] = 0; return MDB_NOTFOUND; } if (mp->mp_flags & P_LEAF2) { nodekey.mv_size = mc->mc_db->md_pad; nodekey.mv_data = LEAF2KEY(mp, 0, nodekey.mv_size); } else { leaf = NODEPTR(mp, 0); MDB_GET_KEY2(leaf, nodekey); } rc = mc->mc_dbx->md_cmp(key, &nodekey); if (rc == 0) { /* Probably happens rarely, but first node on the page * was the one we wanted. */ mc->mc_ki[mc->mc_top] = 0; if (exactp) *exactp = 1; goto set1; } if (rc > 0) { unsigned int i; unsigned int nkeys = NUMKEYS(mp); if (nkeys > 1) { if (mp->mp_flags & P_LEAF2) { nodekey.mv_data = LEAF2KEY(mp, nkeys-1, nodekey.mv_size); } else { leaf = NODEPTR(mp, nkeys-1); MDB_GET_KEY2(leaf, nodekey); } rc = mc->mc_dbx->md_cmp(key, &nodekey); if (rc == 0) { /* last node was the one we wanted */ mc->mc_ki[mc->mc_top] = nkeys-1; if (exactp) *exactp = 1; goto set1; } if (rc < 0) { if (mc->mc_ki[mc->mc_top] < NUMKEYS(mp)) { /* This is definitely the right page, skip search_page */ if (mp->mp_flags & P_LEAF2) { nodekey.mv_data = LEAF2KEY(mp, mc->mc_ki[mc->mc_top], nodekey.mv_size); } else { leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]); MDB_GET_KEY2(leaf, nodekey); } rc = mc->mc_dbx->md_cmp(key, &nodekey); if (rc == 0) { /* current node was the one we wanted */ if (exactp) *exactp = 1; goto set1; } } rc = 0; goto set2; } } /* If any parents have right-sibs, search. * Otherwise, there's nothing further. */ for (i=0; imc_top; i++) if (mc->mc_ki[i] < NUMKEYS(mc->mc_pg[i])-1) break; if (i == mc->mc_top) { /* There are no other pages */ mc->mc_ki[mc->mc_top] = nkeys; return MDB_NOTFOUND; } } if (!mc->mc_top) { /* There are no other pages */ mc->mc_ki[mc->mc_top] = 0; if (op == MDB_SET_RANGE && !exactp) { rc = 0; goto set1; } else return MDB_NOTFOUND; } } rc = mdb_page_search(mc, key, 0); if (rc != MDB_SUCCESS) return rc; mp = mc->mc_pg[mc->mc_top]; mdb_cassert(mc, IS_LEAF(mp)); set2: leaf = mdb_node_search(mc, key, exactp); if (exactp != NULL && !*exactp) { /* MDB_SET specified and not an exact match. */ return MDB_NOTFOUND; } if (leaf == NULL) { DPUTS("===> inexact leaf not found, goto sibling"); if ((rc = mdb_cursor_sibling(mc, 1)) != MDB_SUCCESS) { mc->mc_flags |= C_EOF; return rc; /* no entries matched */ } mp = mc->mc_pg[mc->mc_top]; mdb_cassert(mc, IS_LEAF(mp)); leaf = NODEPTR(mp, 0); } set1: mc->mc_flags |= C_INITIALIZED; mc->mc_flags &= ~C_EOF; if (IS_LEAF2(mp)) { if (op == MDB_SET_RANGE || op == MDB_SET_KEY) { key->mv_size = mc->mc_db->md_pad; key->mv_data = LEAF2KEY(mp, mc->mc_ki[mc->mc_top], key->mv_size); } return MDB_SUCCESS; } if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { mdb_xcursor_init1(mc, leaf); } if (data) { if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { if (op == MDB_SET || op == MDB_SET_KEY || op == MDB_SET_RANGE) { rc = mdb_cursor_first(&mc->mc_xcursor->mx_cursor, data, NULL); } else { int ex2, *ex2p; if (op == MDB_GET_BOTH) { ex2p = &ex2; ex2 = 0; } else { ex2p = NULL; } rc = mdb_cursor_set(&mc->mc_xcursor->mx_cursor, data, NULL, MDB_SET_RANGE, ex2p); if (rc != MDB_SUCCESS) return rc; } } else if (op == MDB_GET_BOTH || op == MDB_GET_BOTH_RANGE) { MDB_val olddata; MDB_cmp_func *dcmp; if ((rc = mdb_node_read(mc->mc_txn, leaf, &olddata)) != MDB_SUCCESS) return rc; dcmp = mc->mc_dbx->md_dcmp; #if UINT_MAX < SIZE_MAX if (dcmp == mdb_cmp_int && olddata.mv_size == sizeof(size_t)) dcmp = mdb_cmp_clong; #endif rc = dcmp(data, &olddata); if (rc) { if (op == MDB_GET_BOTH || rc > 0) return MDB_NOTFOUND; rc = 0; *data = olddata; } } else { if (mc->mc_xcursor) mc->mc_xcursor->mx_cursor.mc_flags &= ~(C_INITIALIZED|C_EOF); if ((rc = mdb_node_read(mc->mc_txn, leaf, data)) != MDB_SUCCESS) return rc; } } /* The key already matches in all other cases */ if (op == MDB_SET_RANGE || op == MDB_SET_KEY) MDB_GET_KEY(leaf, key); DPRINTF(("==> cursor placed on key [%s]", DKEY(key))); return rc; } /** Move the cursor to the first item in the database. */ static int mdb_cursor_first(MDB_cursor *mc, MDB_val *key, MDB_val *data) { int rc; MDB_node *leaf; if (mc->mc_xcursor) mc->mc_xcursor->mx_cursor.mc_flags &= ~(C_INITIALIZED|C_EOF); if (!(mc->mc_flags & C_INITIALIZED) || mc->mc_top) { rc = mdb_page_search(mc, NULL, MDB_PS_FIRST); if (rc != MDB_SUCCESS) return rc; } mdb_cassert(mc, IS_LEAF(mc->mc_pg[mc->mc_top])); leaf = NODEPTR(mc->mc_pg[mc->mc_top], 0); mc->mc_flags |= C_INITIALIZED; mc->mc_flags &= ~C_EOF; mc->mc_ki[mc->mc_top] = 0; if (IS_LEAF2(mc->mc_pg[mc->mc_top])) { key->mv_size = mc->mc_db->md_pad; key->mv_data = LEAF2KEY(mc->mc_pg[mc->mc_top], 0, key->mv_size); return MDB_SUCCESS; } if (data) { if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { mdb_xcursor_init1(mc, leaf); rc = mdb_cursor_first(&mc->mc_xcursor->mx_cursor, data, NULL); if (rc) return rc; } else { if ((rc = mdb_node_read(mc->mc_txn, leaf, data)) != MDB_SUCCESS) return rc; } } MDB_GET_KEY(leaf, key); return MDB_SUCCESS; } /** Move the cursor to the last item in the database. */ static int mdb_cursor_last(MDB_cursor *mc, MDB_val *key, MDB_val *data) { int rc; MDB_node *leaf; if (mc->mc_xcursor) mc->mc_xcursor->mx_cursor.mc_flags &= ~(C_INITIALIZED|C_EOF); if (!(mc->mc_flags & C_EOF)) { if (!(mc->mc_flags & C_INITIALIZED) || mc->mc_top) { rc = mdb_page_search(mc, NULL, MDB_PS_LAST); if (rc != MDB_SUCCESS) return rc; } mdb_cassert(mc, IS_LEAF(mc->mc_pg[mc->mc_top])); } mc->mc_ki[mc->mc_top] = NUMKEYS(mc->mc_pg[mc->mc_top]) - 1; mc->mc_flags |= C_INITIALIZED|C_EOF; leaf = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]); if (IS_LEAF2(mc->mc_pg[mc->mc_top])) { key->mv_size = mc->mc_db->md_pad; key->mv_data = LEAF2KEY(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top], key->mv_size); return MDB_SUCCESS; } if (data) { if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { mdb_xcursor_init1(mc, leaf); rc = mdb_cursor_last(&mc->mc_xcursor->mx_cursor, data, NULL); if (rc) return rc; } else { if ((rc = mdb_node_read(mc->mc_txn, leaf, data)) != MDB_SUCCESS) return rc; } } MDB_GET_KEY(leaf, key); return MDB_SUCCESS; } int mdb_cursor_get(MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_cursor_op op) { int rc; int exact = 0; int (*mfunc)(MDB_cursor *mc, MDB_val *key, MDB_val *data); if (mc == NULL) return EINVAL; if (mc->mc_txn->mt_flags & MDB_TXN_ERROR) return MDB_BAD_TXN; switch (op) { case MDB_GET_CURRENT: if (!(mc->mc_flags & C_INITIALIZED)) { rc = EINVAL; } else { MDB_page *mp = mc->mc_pg[mc->mc_top]; int nkeys = NUMKEYS(mp); if (!nkeys || mc->mc_ki[mc->mc_top] >= nkeys) { mc->mc_ki[mc->mc_top] = nkeys; rc = MDB_NOTFOUND; break; } rc = MDB_SUCCESS; if (IS_LEAF2(mp)) { key->mv_size = mc->mc_db->md_pad; key->mv_data = LEAF2KEY(mp, mc->mc_ki[mc->mc_top], key->mv_size); } else { MDB_node *leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]); MDB_GET_KEY(leaf, key); if (data) { if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { if (mc->mc_flags & C_DEL) mdb_xcursor_init1(mc, leaf); rc = mdb_cursor_get(&mc->mc_xcursor->mx_cursor, data, NULL, MDB_GET_CURRENT); } else { rc = mdb_node_read(mc->mc_txn, leaf, data); } } } } break; case MDB_GET_BOTH: case MDB_GET_BOTH_RANGE: if (data == NULL) { rc = EINVAL; break; } if (mc->mc_xcursor == NULL) { rc = MDB_INCOMPATIBLE; break; } /* FALLTHRU */ case MDB_SET: case MDB_SET_KEY: case MDB_SET_RANGE: if (key == NULL) { rc = EINVAL; } else { rc = mdb_cursor_set(mc, key, data, op, op == MDB_SET_RANGE ? NULL : &exact); } break; case MDB_GET_MULTIPLE: if (data == NULL || !(mc->mc_flags & C_INITIALIZED)) { rc = EINVAL; break; } if (!(mc->mc_db->md_flags & MDB_DUPFIXED)) { rc = MDB_INCOMPATIBLE; break; } rc = MDB_SUCCESS; if (!(mc->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED) || (mc->mc_xcursor->mx_cursor.mc_flags & C_EOF)) break; goto fetchm; case MDB_NEXT_MULTIPLE: if (data == NULL) { rc = EINVAL; break; } if (!(mc->mc_db->md_flags & MDB_DUPFIXED)) { rc = MDB_INCOMPATIBLE; break; } if (!(mc->mc_flags & C_INITIALIZED)) rc = mdb_cursor_first(mc, key, data); else rc = mdb_cursor_next(mc, key, data, MDB_NEXT_DUP); if (rc == MDB_SUCCESS) { if (mc->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED) { MDB_cursor *mx; fetchm: mx = &mc->mc_xcursor->mx_cursor; data->mv_size = NUMKEYS(mx->mc_pg[mx->mc_top]) * mx->mc_db->md_pad; data->mv_data = METADATA(mx->mc_pg[mx->mc_top]); mx->mc_ki[mx->mc_top] = NUMKEYS(mx->mc_pg[mx->mc_top])-1; } else { rc = MDB_NOTFOUND; } } break; case MDB_NEXT: case MDB_NEXT_DUP: case MDB_NEXT_NODUP: if (!(mc->mc_flags & C_INITIALIZED)) rc = mdb_cursor_first(mc, key, data); else rc = mdb_cursor_next(mc, key, data, op); break; case MDB_PREV: case MDB_PREV_DUP: case MDB_PREV_NODUP: if (!(mc->mc_flags & C_INITIALIZED)) { rc = mdb_cursor_last(mc, key, data); if (rc) break; mc->mc_flags |= C_INITIALIZED; mc->mc_ki[mc->mc_top]++; } rc = mdb_cursor_prev(mc, key, data, op); break; case MDB_FIRST: rc = mdb_cursor_first(mc, key, data); break; case MDB_FIRST_DUP: mfunc = mdb_cursor_first; mmove: if (data == NULL || !(mc->mc_flags & C_INITIALIZED)) { rc = EINVAL; break; } if (mc->mc_xcursor == NULL) { rc = MDB_INCOMPATIBLE; break; } { MDB_node *leaf = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]); if (!F_ISSET(leaf->mn_flags, F_DUPDATA)) { MDB_GET_KEY(leaf, key); rc = mdb_node_read(mc->mc_txn, leaf, data); break; } } if (!(mc->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED)) { rc = EINVAL; break; } rc = mfunc(&mc->mc_xcursor->mx_cursor, data, NULL); break; case MDB_LAST: rc = mdb_cursor_last(mc, key, data); break; case MDB_LAST_DUP: mfunc = mdb_cursor_last; goto mmove; default: DPRINTF(("unhandled/unimplemented cursor operation %u", op)); rc = EINVAL; break; } if (mc->mc_flags & C_DEL) mc->mc_flags ^= C_DEL; return rc; } /** Touch all the pages in the cursor stack. Set mc_top. * Makes sure all the pages are writable, before attempting a write operation. * @param[in] mc The cursor to operate on. */ static int mdb_cursor_touch(MDB_cursor *mc) { int rc = MDB_SUCCESS; if (mc->mc_dbi > MAIN_DBI && !(*mc->mc_dbflag & DB_DIRTY)) { MDB_cursor mc2; MDB_xcursor mcx; if (TXN_DBI_CHANGED(mc->mc_txn, mc->mc_dbi)) return MDB_BAD_DBI; mdb_cursor_init(&mc2, mc->mc_txn, MAIN_DBI, &mcx); rc = mdb_page_search(&mc2, &mc->mc_dbx->md_name, MDB_PS_MODIFY); if (rc) return rc; *mc->mc_dbflag |= DB_DIRTY; } mc->mc_top = 0; if (mc->mc_snum) { do { rc = mdb_page_touch(mc); } while (!rc && ++(mc->mc_top) < mc->mc_snum); mc->mc_top = mc->mc_snum-1; } return rc; } /** Do not spill pages to disk if txn is getting full, may fail instead */ #define MDB_NOSPILL 0x8000 int mdb_cursor_put(MDB_cursor *mc, MDB_val *key, MDB_val *data, unsigned int flags) { enum { MDB_NO_ROOT = MDB_LAST_ERRCODE+10 }; /* internal code */ MDB_env *env; MDB_node *leaf = NULL; MDB_page *fp, *mp; uint16_t fp_flags; MDB_val xdata, *rdata, dkey, olddata; MDB_db dummy; int do_sub = 0, insert_key, insert_data; unsigned int mcount = 0, dcount = 0, nospill; size_t nsize; int rc, rc2; unsigned int nflags; DKBUF; if (mc == NULL || key == NULL) return EINVAL; env = mc->mc_txn->mt_env; /* Check this first so counter will always be zero on any * early failures. */ if (flags & MDB_MULTIPLE) { dcount = data[1].mv_size; data[1].mv_size = 0; if (!F_ISSET(mc->mc_db->md_flags, MDB_DUPFIXED)) return MDB_INCOMPATIBLE; } nospill = flags & MDB_NOSPILL; flags &= ~MDB_NOSPILL; if (mc->mc_txn->mt_flags & (MDB_TXN_RDONLY|MDB_TXN_ERROR)) return (mc->mc_txn->mt_flags & MDB_TXN_RDONLY) ? EACCES : MDB_BAD_TXN; if (key->mv_size-1 >= ENV_MAXKEY(env)) return MDB_BAD_VALSIZE; #if SIZE_MAX > MAXDATASIZE if (data->mv_size > ((mc->mc_db->md_flags & MDB_DUPSORT) ? ENV_MAXKEY(env) : MAXDATASIZE)) return MDB_BAD_VALSIZE; #else if ((mc->mc_db->md_flags & MDB_DUPSORT) && data->mv_size > ENV_MAXKEY(env)) return MDB_BAD_VALSIZE; #endif DPRINTF(("==> put db %d key [%s], size %"Z"u, data size %"Z"u", DDBI(mc), DKEY(key), key ? key->mv_size : 0, data->mv_size)); dkey.mv_size = 0; if (flags == MDB_CURRENT) { if (!(mc->mc_flags & C_INITIALIZED)) return EINVAL; rc = MDB_SUCCESS; } else if (mc->mc_db->md_root == P_INVALID) { /* new database, cursor has nothing to point to */ mc->mc_snum = 0; mc->mc_top = 0; mc->mc_flags &= ~C_INITIALIZED; rc = MDB_NO_ROOT; } else { int exact = 0; MDB_val d2; if (flags & MDB_APPEND) { MDB_val k2; rc = mdb_cursor_last(mc, &k2, &d2); if (rc == 0) { rc = mc->mc_dbx->md_cmp(key, &k2); if (rc > 0) { rc = MDB_NOTFOUND; mc->mc_ki[mc->mc_top]++; } else { /* new key is <= last key */ rc = MDB_KEYEXIST; } } } else { rc = mdb_cursor_set(mc, key, &d2, MDB_SET, &exact); } if ((flags & MDB_NOOVERWRITE) && rc == 0) { DPRINTF(("duplicate key [%s]", DKEY(key))); *data = d2; return MDB_KEYEXIST; } if (rc && rc != MDB_NOTFOUND) return rc; } if (mc->mc_flags & C_DEL) mc->mc_flags ^= C_DEL; /* Cursor is positioned, check for room in the dirty list */ if (!nospill) { if (flags & MDB_MULTIPLE) { rdata = &xdata; xdata.mv_size = data->mv_size * dcount; } else { rdata = data; } if ((rc2 = mdb_page_spill(mc, key, rdata))) return rc2; } if (rc == MDB_NO_ROOT) { MDB_page *np; /* new database, write a root leaf page */ DPUTS("allocating new root leaf page"); if ((rc2 = mdb_page_new(mc, P_LEAF, 1, &np))) { return rc2; } mdb_cursor_push(mc, np); mc->mc_db->md_root = np->mp_pgno; mc->mc_db->md_depth++; *mc->mc_dbflag |= DB_DIRTY; if ((mc->mc_db->md_flags & (MDB_DUPSORT|MDB_DUPFIXED)) == MDB_DUPFIXED) np->mp_flags |= P_LEAF2; mc->mc_flags |= C_INITIALIZED; } else { /* make sure all cursor pages are writable */ rc2 = mdb_cursor_touch(mc); if (rc2) return rc2; } insert_key = insert_data = rc; if (insert_key) { /* The key does not exist */ DPRINTF(("inserting key at index %i", mc->mc_ki[mc->mc_top])); if ((mc->mc_db->md_flags & MDB_DUPSORT) && LEAFSIZE(key, data) > env->me_nodemax) { /* Too big for a node, insert in sub-DB. Set up an empty * "old sub-page" for prep_subDB to expand to a full page. */ fp_flags = P_LEAF|P_DIRTY; fp = env->me_pbuf; fp->mp_pad = data->mv_size; /* used if MDB_DUPFIXED */ fp->mp_lower = fp->mp_upper = (PAGEHDRSZ-PAGEBASE); olddata.mv_size = PAGEHDRSZ; goto prep_subDB; } } else { /* there's only a key anyway, so this is a no-op */ if (IS_LEAF2(mc->mc_pg[mc->mc_top])) { char *ptr; unsigned int ksize = mc->mc_db->md_pad; if (key->mv_size != ksize) return MDB_BAD_VALSIZE; ptr = LEAF2KEY(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top], ksize); memcpy(ptr, key->mv_data, ksize); fix_parent: /* if overwriting slot 0 of leaf, need to * update branch key if there is a parent page */ if (mc->mc_top && !mc->mc_ki[mc->mc_top]) { unsigned short top = mc->mc_top; mc->mc_top--; /* slot 0 is always an empty key, find real slot */ while (mc->mc_top && !mc->mc_ki[mc->mc_top]) mc->mc_top--; if (mc->mc_ki[mc->mc_top]) rc2 = mdb_update_key(mc, key); else rc2 = MDB_SUCCESS; mc->mc_top = top; if (rc2) return rc2; } return MDB_SUCCESS; } more: leaf = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]); olddata.mv_size = NODEDSZ(leaf); olddata.mv_data = NODEDATA(leaf); /* DB has dups? */ if (F_ISSET(mc->mc_db->md_flags, MDB_DUPSORT)) { /* Prepare (sub-)page/sub-DB to accept the new item, * if needed. fp: old sub-page or a header faking * it. mp: new (sub-)page. offset: growth in page * size. xdata: node data with new page or DB. */ unsigned i, offset = 0; mp = fp = xdata.mv_data = env->me_pbuf; mp->mp_pgno = mc->mc_pg[mc->mc_top]->mp_pgno; /* Was a single item before, must convert now */ if (!F_ISSET(leaf->mn_flags, F_DUPDATA)) { MDB_cmp_func *dcmp; /* Just overwrite the current item */ if (flags == MDB_CURRENT) goto current; dcmp = mc->mc_dbx->md_dcmp; #if UINT_MAX < SIZE_MAX if (dcmp == mdb_cmp_int && olddata.mv_size == sizeof(size_t)) dcmp = mdb_cmp_clong; #endif /* does data match? */ if (!dcmp(data, &olddata)) { if (flags & MDB_NODUPDATA) return MDB_KEYEXIST; /* overwrite it */ goto current; } /* Back up original data item */ dkey.mv_size = olddata.mv_size; dkey.mv_data = memcpy(fp+1, olddata.mv_data, olddata.mv_size); /* Make sub-page header for the dup items, with dummy body */ fp->mp_flags = P_LEAF|P_DIRTY|P_SUBP; fp->mp_lower = (PAGEHDRSZ-PAGEBASE); xdata.mv_size = PAGEHDRSZ + dkey.mv_size + data->mv_size; if (mc->mc_db->md_flags & MDB_DUPFIXED) { fp->mp_flags |= P_LEAF2; fp->mp_pad = data->mv_size; xdata.mv_size += 2 * data->mv_size; /* leave space for 2 more */ } else { xdata.mv_size += 2 * (sizeof(indx_t) + NODESIZE) + (dkey.mv_size & 1) + (data->mv_size & 1); } fp->mp_upper = xdata.mv_size - PAGEBASE; olddata.mv_size = xdata.mv_size; /* pretend olddata is fp */ } else if (leaf->mn_flags & F_SUBDATA) { /* Data is on sub-DB, just store it */ flags |= F_DUPDATA|F_SUBDATA; goto put_sub; } else { /* Data is on sub-page */ fp = olddata.mv_data; switch (flags) { default: if (!(mc->mc_db->md_flags & MDB_DUPFIXED)) { offset = EVEN(NODESIZE + sizeof(indx_t) + data->mv_size); break; } offset = fp->mp_pad; if (SIZELEFT(fp) < offset) { offset *= 4; /* space for 4 more */ break; } /* FALLTHRU: Big enough MDB_DUPFIXED sub-page */ case MDB_CURRENT: fp->mp_flags |= P_DIRTY; COPY_PGNO(fp->mp_pgno, mp->mp_pgno); mc->mc_xcursor->mx_cursor.mc_pg[0] = fp; flags |= F_DUPDATA; goto put_sub; } xdata.mv_size = olddata.mv_size + offset; } fp_flags = fp->mp_flags; if (NODESIZE + NODEKSZ(leaf) + xdata.mv_size > env->me_nodemax) { /* Too big for a sub-page, convert to sub-DB */ fp_flags &= ~P_SUBP; prep_subDB: if (mc->mc_db->md_flags & MDB_DUPFIXED) { fp_flags |= P_LEAF2; dummy.md_pad = fp->mp_pad; dummy.md_flags = MDB_DUPFIXED; if (mc->mc_db->md_flags & MDB_INTEGERDUP) dummy.md_flags |= MDB_INTEGERKEY; } else { dummy.md_pad = 0; dummy.md_flags = 0; } dummy.md_depth = 1; dummy.md_branch_pages = 0; dummy.md_leaf_pages = 1; dummy.md_overflow_pages = 0; dummy.md_entries = NUMKEYS(fp); xdata.mv_size = sizeof(MDB_db); xdata.mv_data = &dummy; if ((rc = mdb_page_alloc(mc, 1, &mp))) return rc; offset = env->me_psize - olddata.mv_size; flags |= F_DUPDATA|F_SUBDATA; dummy.md_root = mp->mp_pgno; } if (mp != fp) { mp->mp_flags = fp_flags | P_DIRTY; mp->mp_pad = fp->mp_pad; mp->mp_lower = fp->mp_lower; mp->mp_upper = fp->mp_upper + offset; if (fp_flags & P_LEAF2) { memcpy(METADATA(mp), METADATA(fp), NUMKEYS(fp) * fp->mp_pad); } else { memcpy((char *)mp + mp->mp_upper + PAGEBASE, (char *)fp + fp->mp_upper + PAGEBASE, olddata.mv_size - fp->mp_upper - PAGEBASE); for (i=0; imp_ptrs[i] = fp->mp_ptrs[i] + offset; } } rdata = &xdata; flags |= F_DUPDATA; do_sub = 1; if (!insert_key) mdb_node_del(mc, 0); goto new_sub; } current: /* LMDB passes F_SUBDATA in 'flags' to write a DB record */ if ((leaf->mn_flags ^ flags) & F_SUBDATA) return MDB_INCOMPATIBLE; /* overflow page overwrites need special handling */ if (F_ISSET(leaf->mn_flags, F_BIGDATA)) { MDB_page *omp; pgno_t pg; int level, ovpages, dpages = OVPAGES(data->mv_size, env->me_psize); memcpy(&pg, olddata.mv_data, sizeof(pg)); if ((rc2 = mdb_page_get(mc->mc_txn, pg, &omp, &level)) != 0) return rc2; ovpages = omp->mp_pages; /* Is the ov page large enough? */ if (ovpages >= dpages) { if (!(omp->mp_flags & P_DIRTY) && (level || (env->me_flags & MDB_WRITEMAP))) { rc = mdb_page_unspill(mc->mc_txn, omp, &omp); if (rc) return rc; level = 0; /* dirty in this txn or clean */ } /* Is it dirty? */ if (omp->mp_flags & P_DIRTY) { /* yes, overwrite it. Note in this case we don't * bother to try shrinking the page if the new data * is smaller than the overflow threshold. */ if (level > 1) { /* It is writable only in a parent txn */ size_t sz = (size_t) env->me_psize * ovpages, off; MDB_page *np = mdb_page_malloc(mc->mc_txn, ovpages); MDB_ID2 id2; if (!np) return ENOMEM; id2.mid = pg; id2.mptr = np; rc2 = mdb_mid2l_insert(mc->mc_txn->mt_u.dirty_list, &id2); mdb_cassert(mc, rc2 == 0); if (!(flags & MDB_RESERVE)) { /* Copy end of page, adjusting alignment so * compiler may copy words instead of bytes. */ off = (PAGEHDRSZ + data->mv_size) & -sizeof(size_t); memcpy((size_t *)((char *)np + off), (size_t *)((char *)omp + off), sz - off); sz = PAGEHDRSZ; } memcpy(np, omp, sz); /* Copy beginning of page */ omp = np; } SETDSZ(leaf, data->mv_size); if (F_ISSET(flags, MDB_RESERVE)) data->mv_data = METADATA(omp); else memcpy(METADATA(omp), data->mv_data, data->mv_size); return MDB_SUCCESS; } } if ((rc2 = mdb_ovpage_free(mc, omp)) != MDB_SUCCESS) return rc2; } else if (data->mv_size == olddata.mv_size) { /* same size, just replace it. Note that we could * also reuse this node if the new data is smaller, * but instead we opt to shrink the node in that case. */ if (F_ISSET(flags, MDB_RESERVE)) data->mv_data = olddata.mv_data; else if (!(mc->mc_flags & C_SUB)) memcpy(olddata.mv_data, data->mv_data, data->mv_size); else { memcpy(NODEKEY(leaf), key->mv_data, key->mv_size); goto fix_parent; } return MDB_SUCCESS; } mdb_node_del(mc, 0); } rdata = data; new_sub: nflags = flags & NODE_ADD_FLAGS; nsize = IS_LEAF2(mc->mc_pg[mc->mc_top]) ? key->mv_size : mdb_leaf_size(env, key, rdata); if (SIZELEFT(mc->mc_pg[mc->mc_top]) < nsize) { if (( flags & (F_DUPDATA|F_SUBDATA)) == F_DUPDATA ) nflags &= ~MDB_APPEND; /* sub-page may need room to grow */ if (!insert_key) nflags |= MDB_SPLIT_REPLACE; rc = mdb_page_split(mc, key, rdata, P_INVALID, nflags); } else { /* There is room already in this leaf page. */ rc = mdb_node_add(mc, mc->mc_ki[mc->mc_top], key, rdata, 0, nflags); if (rc == 0 && insert_key) { /* Adjust other cursors pointing to mp */ MDB_cursor *m2, *m3; MDB_dbi dbi = mc->mc_dbi; unsigned i = mc->mc_top; MDB_page *mp = mc->mc_pg[i]; for (m2 = mc->mc_txn->mt_cursors[dbi]; m2; m2=m2->mc_next) { if (mc->mc_flags & C_SUB) m3 = &m2->mc_xcursor->mx_cursor; else m3 = m2; if (m3 == mc || m3->mc_snum < mc->mc_snum) continue; if (m3->mc_pg[i] == mp && m3->mc_ki[i] >= mc->mc_ki[i]) { m3->mc_ki[i]++; } } } } if (rc == MDB_SUCCESS) { /* Now store the actual data in the child DB. Note that we're * storing the user data in the keys field, so there are strict * size limits on dupdata. The actual data fields of the child * DB are all zero size. */ if (do_sub) { int xflags; size_t ecount; put_sub: xdata.mv_size = 0; xdata.mv_data = ""; leaf = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]); if (flags & MDB_CURRENT) { xflags = MDB_CURRENT|MDB_NOSPILL; } else { mdb_xcursor_init1(mc, leaf); xflags = (flags & MDB_NODUPDATA) ? MDB_NOOVERWRITE|MDB_NOSPILL : MDB_NOSPILL; } /* converted, write the original data first */ if (dkey.mv_size) { rc = mdb_cursor_put(&mc->mc_xcursor->mx_cursor, &dkey, &xdata, xflags); if (rc) goto bad_sub; { /* Adjust other cursors pointing to mp */ MDB_cursor *m2; unsigned i = mc->mc_top; MDB_page *mp = mc->mc_pg[i]; for (m2 = mc->mc_txn->mt_cursors[mc->mc_dbi]; m2; m2=m2->mc_next) { if (m2 == mc || m2->mc_snum < mc->mc_snum) continue; if (!(m2->mc_flags & C_INITIALIZED)) continue; if (m2->mc_pg[i] == mp && m2->mc_ki[i] == mc->mc_ki[i]) { mdb_xcursor_init1(m2, leaf); } } } /* we've done our job */ dkey.mv_size = 0; } ecount = mc->mc_xcursor->mx_db.md_entries; if (flags & MDB_APPENDDUP) xflags |= MDB_APPEND; rc = mdb_cursor_put(&mc->mc_xcursor->mx_cursor, data, &xdata, xflags); if (flags & F_SUBDATA) { void *db = NODEDATA(leaf); memcpy(db, &mc->mc_xcursor->mx_db, sizeof(MDB_db)); } insert_data = mc->mc_xcursor->mx_db.md_entries - ecount; } /* Increment count unless we just replaced an existing item. */ if (insert_data) mc->mc_db->md_entries++; if (insert_key) { /* Invalidate txn if we created an empty sub-DB */ if (rc) goto bad_sub; /* If we succeeded and the key didn't exist before, * make sure the cursor is marked valid. */ mc->mc_flags |= C_INITIALIZED; } if (flags & MDB_MULTIPLE) { if (!rc) { mcount++; /* let caller know how many succeeded, if any */ data[1].mv_size = mcount; if (mcount < dcount) { data[0].mv_data = (char *)data[0].mv_data + data[0].mv_size; insert_key = insert_data = 0; goto more; } } } return rc; bad_sub: if (rc == MDB_KEYEXIST) /* should not happen, we deleted that item */ rc = MDB_CORRUPTED; } mc->mc_txn->mt_flags |= MDB_TXN_ERROR; return rc; } int mdb_cursor_del(MDB_cursor *mc, unsigned int flags) { MDB_node *leaf; MDB_page *mp; int rc; if (mc->mc_txn->mt_flags & (MDB_TXN_RDONLY|MDB_TXN_ERROR)) return (mc->mc_txn->mt_flags & MDB_TXN_RDONLY) ? EACCES : MDB_BAD_TXN; if (!(mc->mc_flags & C_INITIALIZED)) return EINVAL; if (mc->mc_ki[mc->mc_top] >= NUMKEYS(mc->mc_pg[mc->mc_top])) return MDB_NOTFOUND; if (!(flags & MDB_NOSPILL) && (rc = mdb_page_spill(mc, NULL, NULL))) return rc; rc = mdb_cursor_touch(mc); if (rc) return rc; mp = mc->mc_pg[mc->mc_top]; if (IS_LEAF2(mp)) goto del_key; leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]); if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { if (flags & MDB_NODUPDATA) { /* mdb_cursor_del0() will subtract the final entry */ mc->mc_db->md_entries -= mc->mc_xcursor->mx_db.md_entries - 1; } else { if (!F_ISSET(leaf->mn_flags, F_SUBDATA)) { mc->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(leaf); } rc = mdb_cursor_del(&mc->mc_xcursor->mx_cursor, MDB_NOSPILL); if (rc) return rc; /* If sub-DB still has entries, we're done */ if (mc->mc_xcursor->mx_db.md_entries) { if (leaf->mn_flags & F_SUBDATA) { /* update subDB info */ void *db = NODEDATA(leaf); memcpy(db, &mc->mc_xcursor->mx_db, sizeof(MDB_db)); } else { MDB_cursor *m2; /* shrink fake page */ mdb_node_shrink(mp, mc->mc_ki[mc->mc_top]); leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]); mc->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(leaf); /* fix other sub-DB cursors pointed at this fake page */ for (m2 = mc->mc_txn->mt_cursors[mc->mc_dbi]; m2; m2=m2->mc_next) { if (m2 == mc || m2->mc_snum < mc->mc_snum) continue; if (m2->mc_pg[mc->mc_top] == mp && m2->mc_ki[mc->mc_top] == mc->mc_ki[mc->mc_top]) m2->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(leaf); } } mc->mc_db->md_entries--; mc->mc_flags |= C_DEL; return rc; } /* otherwise fall thru and delete the sub-DB */ } if (leaf->mn_flags & F_SUBDATA) { /* add all the child DB's pages to the free list */ rc = mdb_drop0(&mc->mc_xcursor->mx_cursor, 0); if (rc) goto fail; } } /* LMDB passes F_SUBDATA in 'flags' to delete a DB record */ else if ((leaf->mn_flags ^ flags) & F_SUBDATA) { rc = MDB_INCOMPATIBLE; goto fail; } /* add overflow pages to free list */ if (F_ISSET(leaf->mn_flags, F_BIGDATA)) { MDB_page *omp; pgno_t pg; memcpy(&pg, NODEDATA(leaf), sizeof(pg)); if ((rc = mdb_page_get(mc->mc_txn, pg, &omp, NULL)) || (rc = mdb_ovpage_free(mc, omp))) goto fail; } del_key: return mdb_cursor_del0(mc); fail: mc->mc_txn->mt_flags |= MDB_TXN_ERROR; return rc; } /** Allocate and initialize new pages for a database. * @param[in] mc a cursor on the database being added to. * @param[in] flags flags defining what type of page is being allocated. * @param[in] num the number of pages to allocate. This is usually 1, * unless allocating overflow pages for a large record. * @param[out] mp Address of a page, or NULL on failure. * @return 0 on success, non-zero on failure. */ static int mdb_page_new(MDB_cursor *mc, uint32_t flags, int num, MDB_page **mp) { MDB_page *np; int rc; if ((rc = mdb_page_alloc(mc, num, &np))) return rc; DPRINTF(("allocated new mpage %"Z"u, page size %u", np->mp_pgno, mc->mc_txn->mt_env->me_psize)); np->mp_flags = flags | P_DIRTY; np->mp_lower = (PAGEHDRSZ-PAGEBASE); np->mp_upper = mc->mc_txn->mt_env->me_psize - PAGEBASE; if (IS_BRANCH(np)) mc->mc_db->md_branch_pages++; else if (IS_LEAF(np)) mc->mc_db->md_leaf_pages++; else if (IS_OVERFLOW(np)) { mc->mc_db->md_overflow_pages += num; np->mp_pages = num; } *mp = np; return 0; } /** Calculate the size of a leaf node. * The size depends on the environment's page size; if a data item * is too large it will be put onto an overflow page and the node * size will only include the key and not the data. Sizes are always * rounded up to an even number of bytes, to guarantee 2-byte alignment * of the #MDB_node headers. * @param[in] env The environment handle. * @param[in] key The key for the node. * @param[in] data The data for the node. * @return The number of bytes needed to store the node. */ static size_t mdb_leaf_size(MDB_env *env, MDB_val *key, MDB_val *data) { size_t sz; sz = LEAFSIZE(key, data); if (sz > env->me_nodemax) { /* put on overflow page */ sz -= data->mv_size - sizeof(pgno_t); } return EVEN(sz + sizeof(indx_t)); } /** Calculate the size of a branch node. * The size should depend on the environment's page size but since * we currently don't support spilling large keys onto overflow * pages, it's simply the size of the #MDB_node header plus the * size of the key. Sizes are always rounded up to an even number * of bytes, to guarantee 2-byte alignment of the #MDB_node headers. * @param[in] env The environment handle. * @param[in] key The key for the node. * @return The number of bytes needed to store the node. */ static size_t mdb_branch_size(MDB_env *env, MDB_val *key) { size_t sz; sz = INDXSIZE(key); if (sz > env->me_nodemax) { /* put on overflow page */ /* not implemented */ /* sz -= key->size - sizeof(pgno_t); */ } return sz + sizeof(indx_t); } /** Add a node to the page pointed to by the cursor. * @param[in] mc The cursor for this operation. * @param[in] indx The index on the page where the new node should be added. * @param[in] key The key for the new node. * @param[in] data The data for the new node, if any. * @param[in] pgno The page number, if adding a branch node. * @param[in] flags Flags for the node. * @return 0 on success, non-zero on failure. Possible errors are: *
    *
  • ENOMEM - failed to allocate overflow pages for the node. *
  • MDB_PAGE_FULL - there is insufficient room in the page. This error * should never happen since all callers already calculate the * page's free space before calling this function. *
*/ static int mdb_node_add(MDB_cursor *mc, indx_t indx, MDB_val *key, MDB_val *data, pgno_t pgno, unsigned int flags) { unsigned int i; size_t node_size = NODESIZE; ssize_t room; indx_t ofs; MDB_node *node; MDB_page *mp = mc->mc_pg[mc->mc_top]; MDB_page *ofp = NULL; /* overflow page */ DKBUF; mdb_cassert(mc, mp->mp_upper >= mp->mp_lower); DPRINTF(("add to %s %spage %"Z"u index %i, data size %"Z"u key size %"Z"u [%s]", IS_LEAF(mp) ? "leaf" : "branch", IS_SUBP(mp) ? "sub-" : "", mdb_dbg_pgno(mp), indx, data ? data->mv_size : 0, key ? key->mv_size : 0, key ? DKEY(key) : "null")); if (IS_LEAF2(mp)) { /* Move higher keys up one slot. */ int ksize = mc->mc_db->md_pad, dif; char *ptr = LEAF2KEY(mp, indx, ksize); dif = NUMKEYS(mp) - indx; if (dif > 0) memmove(ptr+ksize, ptr, dif*ksize); /* insert new key */ memcpy(ptr, key->mv_data, ksize); /* Just using these for counting */ mp->mp_lower += sizeof(indx_t); mp->mp_upper -= ksize - sizeof(indx_t); return MDB_SUCCESS; } room = (ssize_t)SIZELEFT(mp) - (ssize_t)sizeof(indx_t); if (key != NULL) node_size += key->mv_size; if (IS_LEAF(mp)) { mdb_cassert(mc, data); if (F_ISSET(flags, F_BIGDATA)) { /* Data already on overflow page. */ node_size += sizeof(pgno_t); } else if (node_size + data->mv_size > mc->mc_txn->mt_env->me_nodemax) { int ovpages = OVPAGES(data->mv_size, mc->mc_txn->mt_env->me_psize); int rc; /* Put data on overflow page. */ DPRINTF(("data size is %"Z"u, node would be %"Z"u, put data on overflow page", data->mv_size, node_size+data->mv_size)); node_size = EVEN(node_size + sizeof(pgno_t)); if ((ssize_t)node_size > room) goto full; if ((rc = mdb_page_new(mc, P_OVERFLOW, ovpages, &ofp))) return rc; DPRINTF(("allocated overflow page %"Z"u", ofp->mp_pgno)); flags |= F_BIGDATA; goto update; } else { node_size += data->mv_size; } } node_size = EVEN(node_size); if ((ssize_t)node_size > room) goto full; update: /* Move higher pointers up one slot. */ for (i = NUMKEYS(mp); i > indx; i--) mp->mp_ptrs[i] = mp->mp_ptrs[i - 1]; /* Adjust free space offsets. */ ofs = mp->mp_upper - node_size; mdb_cassert(mc, ofs >= mp->mp_lower + sizeof(indx_t)); mp->mp_ptrs[indx] = ofs; mp->mp_upper = ofs; mp->mp_lower += sizeof(indx_t); /* Write the node data. */ node = NODEPTR(mp, indx); node->mn_ksize = (key == NULL) ? 0 : key->mv_size; node->mn_flags = flags; if (IS_LEAF(mp)) SETDSZ(node,data->mv_size); else SETPGNO(node,pgno); if (key) memcpy(NODEKEY(node), key->mv_data, key->mv_size); if (IS_LEAF(mp)) { mdb_cassert(mc, key); if (ofp == NULL) { if (F_ISSET(flags, F_BIGDATA)) memcpy(node->mn_data + key->mv_size, data->mv_data, sizeof(pgno_t)); else if (F_ISSET(flags, MDB_RESERVE)) data->mv_data = node->mn_data + key->mv_size; else memcpy(node->mn_data + key->mv_size, data->mv_data, data->mv_size); } else { memcpy(node->mn_data + key->mv_size, &ofp->mp_pgno, sizeof(pgno_t)); if (F_ISSET(flags, MDB_RESERVE)) data->mv_data = METADATA(ofp); else memcpy(METADATA(ofp), data->mv_data, data->mv_size); } } return MDB_SUCCESS; full: DPRINTF(("not enough room in page %"Z"u, got %u ptrs", mdb_dbg_pgno(mp), NUMKEYS(mp))); DPRINTF(("upper-lower = %u - %u = %"Z"d", mp->mp_upper,mp->mp_lower,room)); DPRINTF(("node size = %"Z"u", node_size)); mc->mc_txn->mt_flags |= MDB_TXN_ERROR; return MDB_PAGE_FULL; } /** Delete the specified node from a page. * @param[in] mc Cursor pointing to the node to delete. * @param[in] ksize The size of a node. Only used if the page is * part of a #MDB_DUPFIXED database. */ static void mdb_node_del(MDB_cursor *mc, int ksize) { MDB_page *mp = mc->mc_pg[mc->mc_top]; indx_t indx = mc->mc_ki[mc->mc_top]; unsigned int sz; indx_t i, j, numkeys, ptr; MDB_node *node; char *base; DPRINTF(("delete node %u on %s page %"Z"u", indx, IS_LEAF(mp) ? "leaf" : "branch", mdb_dbg_pgno(mp))); numkeys = NUMKEYS(mp); mdb_cassert(mc, indx < numkeys); if (IS_LEAF2(mp)) { int x = numkeys - 1 - indx; base = LEAF2KEY(mp, indx, ksize); if (x) memmove(base, base + ksize, x * ksize); mp->mp_lower -= sizeof(indx_t); mp->mp_upper += ksize - sizeof(indx_t); return; } node = NODEPTR(mp, indx); sz = NODESIZE + node->mn_ksize; if (IS_LEAF(mp)) { if (F_ISSET(node->mn_flags, F_BIGDATA)) sz += sizeof(pgno_t); else sz += NODEDSZ(node); } sz = EVEN(sz); ptr = mp->mp_ptrs[indx]; for (i = j = 0; i < numkeys; i++) { if (i != indx) { mp->mp_ptrs[j] = mp->mp_ptrs[i]; if (mp->mp_ptrs[i] < ptr) mp->mp_ptrs[j] += sz; j++; } } base = (char *)mp + mp->mp_upper + PAGEBASE; memmove(base + sz, base, ptr - mp->mp_upper); mp->mp_lower -= sizeof(indx_t); mp->mp_upper += sz; } /** Compact the main page after deleting a node on a subpage. * @param[in] mp The main page to operate on. * @param[in] indx The index of the subpage on the main page. */ static void mdb_node_shrink(MDB_page *mp, indx_t indx) { MDB_node *node; MDB_page *sp, *xp; char *base; int nsize, delta; indx_t i, numkeys, ptr; node = NODEPTR(mp, indx); sp = (MDB_page *)NODEDATA(node); delta = SIZELEFT(sp); xp = (MDB_page *)((char *)sp + delta); /* shift subpage upward */ if (IS_LEAF2(sp)) { nsize = NUMKEYS(sp) * sp->mp_pad; if (nsize & 1) return; /* do not make the node uneven-sized */ memmove(METADATA(xp), METADATA(sp), nsize); } else { int i; numkeys = NUMKEYS(sp); for (i=numkeys-1; i>=0; i--) xp->mp_ptrs[i] = sp->mp_ptrs[i] - delta; } xp->mp_upper = sp->mp_lower; xp->mp_lower = sp->mp_lower; xp->mp_flags = sp->mp_flags; xp->mp_pad = sp->mp_pad; COPY_PGNO(xp->mp_pgno, mp->mp_pgno); nsize = NODEDSZ(node) - delta; SETDSZ(node, nsize); /* shift lower nodes upward */ ptr = mp->mp_ptrs[indx]; numkeys = NUMKEYS(mp); for (i = 0; i < numkeys; i++) { if (mp->mp_ptrs[i] <= ptr) mp->mp_ptrs[i] += delta; } base = (char *)mp + mp->mp_upper + PAGEBASE; memmove(base + delta, base, ptr - mp->mp_upper + NODESIZE + NODEKSZ(node)); mp->mp_upper += delta; } /** Initial setup of a sorted-dups cursor. * Sorted duplicates are implemented as a sub-database for the given key. * The duplicate data items are actually keys of the sub-database. * Operations on the duplicate data items are performed using a sub-cursor * initialized when the sub-database is first accessed. This function does * the preliminary setup of the sub-cursor, filling in the fields that * depend only on the parent DB. * @param[in] mc The main cursor whose sorted-dups cursor is to be initialized. */ static void mdb_xcursor_init0(MDB_cursor *mc) { MDB_xcursor *mx = mc->mc_xcursor; mx->mx_cursor.mc_xcursor = NULL; mx->mx_cursor.mc_txn = mc->mc_txn; mx->mx_cursor.mc_db = &mx->mx_db; mx->mx_cursor.mc_dbx = &mx->mx_dbx; mx->mx_cursor.mc_dbi = mc->mc_dbi; mx->mx_cursor.mc_dbflag = &mx->mx_dbflag; mx->mx_cursor.mc_snum = 0; mx->mx_cursor.mc_top = 0; mx->mx_cursor.mc_flags = C_SUB; mx->mx_dbx.md_name.mv_size = 0; mx->mx_dbx.md_name.mv_data = NULL; mx->mx_dbx.md_cmp = mc->mc_dbx->md_dcmp; mx->mx_dbx.md_dcmp = NULL; mx->mx_dbx.md_rel = mc->mc_dbx->md_rel; } /** Final setup of a sorted-dups cursor. * Sets up the fields that depend on the data from the main cursor. * @param[in] mc The main cursor whose sorted-dups cursor is to be initialized. * @param[in] node The data containing the #MDB_db record for the * sorted-dup database. */ static void mdb_xcursor_init1(MDB_cursor *mc, MDB_node *node) { MDB_xcursor *mx = mc->mc_xcursor; if (node->mn_flags & F_SUBDATA) { memcpy(&mx->mx_db, NODEDATA(node), sizeof(MDB_db)); mx->mx_cursor.mc_pg[0] = 0; mx->mx_cursor.mc_snum = 0; mx->mx_cursor.mc_top = 0; mx->mx_cursor.mc_flags = C_SUB; } else { MDB_page *fp = NODEDATA(node); mx->mx_db.md_pad = mc->mc_pg[mc->mc_top]->mp_pad; mx->mx_db.md_flags = 0; mx->mx_db.md_depth = 1; mx->mx_db.md_branch_pages = 0; mx->mx_db.md_leaf_pages = 1; mx->mx_db.md_overflow_pages = 0; mx->mx_db.md_entries = NUMKEYS(fp); COPY_PGNO(mx->mx_db.md_root, fp->mp_pgno); mx->mx_cursor.mc_snum = 1; mx->mx_cursor.mc_top = 0; mx->mx_cursor.mc_flags = C_INITIALIZED|C_SUB; mx->mx_cursor.mc_pg[0] = fp; mx->mx_cursor.mc_ki[0] = 0; if (mc->mc_db->md_flags & MDB_DUPFIXED) { mx->mx_db.md_flags = MDB_DUPFIXED; mx->mx_db.md_pad = fp->mp_pad; if (mc->mc_db->md_flags & MDB_INTEGERDUP) mx->mx_db.md_flags |= MDB_INTEGERKEY; } } DPRINTF(("Sub-db -%u root page %"Z"u", mx->mx_cursor.mc_dbi, mx->mx_db.md_root)); mx->mx_dbflag = DB_VALID|DB_DIRTY; /* DB_DIRTY guides mdb_cursor_touch */ #if UINT_MAX < SIZE_MAX if (mx->mx_dbx.md_cmp == mdb_cmp_int && mx->mx_db.md_pad == sizeof(size_t)) mx->mx_dbx.md_cmp = mdb_cmp_clong; #endif } /** Initialize a cursor for a given transaction and database. */ static void mdb_cursor_init(MDB_cursor *mc, MDB_txn *txn, MDB_dbi dbi, MDB_xcursor *mx) { mc->mc_next = NULL; mc->mc_backup = NULL; mc->mc_dbi = dbi; mc->mc_txn = txn; mc->mc_db = &txn->mt_dbs[dbi]; mc->mc_dbx = &txn->mt_dbxs[dbi]; mc->mc_dbflag = &txn->mt_dbflags[dbi]; mc->mc_snum = 0; mc->mc_top = 0; mc->mc_pg[0] = 0; mc->mc_ki[0] = 0; mc->mc_flags = 0; if (txn->mt_dbs[dbi].md_flags & MDB_DUPSORT) { mdb_tassert(txn, mx != NULL); mc->mc_xcursor = mx; mdb_xcursor_init0(mc); } else { mc->mc_xcursor = NULL; } if (*mc->mc_dbflag & DB_STALE) { mdb_page_search(mc, NULL, MDB_PS_ROOTONLY); } } int mdb_cursor_open(MDB_txn *txn, MDB_dbi dbi, MDB_cursor **ret) { MDB_cursor *mc; size_t size = sizeof(MDB_cursor); if (!ret || !TXN_DBI_EXIST(txn, dbi)) return EINVAL; if (txn->mt_flags & MDB_TXN_ERROR) return MDB_BAD_TXN; /* Allow read access to the freelist */ if (!dbi && !F_ISSET(txn->mt_flags, MDB_TXN_RDONLY)) return EINVAL; if (txn->mt_dbs[dbi].md_flags & MDB_DUPSORT) size += sizeof(MDB_xcursor); if ((mc = malloc(size)) != NULL) { mdb_cursor_init(mc, txn, dbi, (MDB_xcursor *)(mc + 1)); if (txn->mt_cursors) { mc->mc_next = txn->mt_cursors[dbi]; txn->mt_cursors[dbi] = mc; mc->mc_flags |= C_UNTRACK; } } else { return ENOMEM; } *ret = mc; return MDB_SUCCESS; } int mdb_cursor_renew(MDB_txn *txn, MDB_cursor *mc) { if (!mc || !TXN_DBI_EXIST(txn, mc->mc_dbi)) return EINVAL; if ((mc->mc_flags & C_UNTRACK) || txn->mt_cursors) return EINVAL; if (txn->mt_flags & MDB_TXN_ERROR) return MDB_BAD_TXN; mdb_cursor_init(mc, txn, mc->mc_dbi, mc->mc_xcursor); return MDB_SUCCESS; } /* Return the count of duplicate data items for the current key */ int mdb_cursor_count(MDB_cursor *mc, size_t *countp) { MDB_node *leaf; if (mc == NULL || countp == NULL) return EINVAL; if (mc->mc_xcursor == NULL) return MDB_INCOMPATIBLE; if (mc->mc_txn->mt_flags & MDB_TXN_ERROR) return MDB_BAD_TXN; if (!(mc->mc_flags & C_INITIALIZED)) return EINVAL; if (!mc->mc_snum || (mc->mc_flags & C_EOF)) return MDB_NOTFOUND; leaf = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]); if (!F_ISSET(leaf->mn_flags, F_DUPDATA)) { *countp = 1; } else { if (!(mc->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED)) return EINVAL; *countp = mc->mc_xcursor->mx_db.md_entries; } return MDB_SUCCESS; } void mdb_cursor_close(MDB_cursor *mc) { if (mc && !mc->mc_backup) { /* remove from txn, if tracked */ if ((mc->mc_flags & C_UNTRACK) && mc->mc_txn->mt_cursors) { MDB_cursor **prev = &mc->mc_txn->mt_cursors[mc->mc_dbi]; while (*prev && *prev != mc) prev = &(*prev)->mc_next; if (*prev == mc) *prev = mc->mc_next; } free(mc); } } MDB_txn * mdb_cursor_txn(MDB_cursor *mc) { if (!mc) return NULL; return mc->mc_txn; } MDB_dbi mdb_cursor_dbi(MDB_cursor *mc) { return mc->mc_dbi; } /** Replace the key for a branch node with a new key. * @param[in] mc Cursor pointing to the node to operate on. * @param[in] key The new key to use. * @return 0 on success, non-zero on failure. */ static int mdb_update_key(MDB_cursor *mc, MDB_val *key) { MDB_page *mp; MDB_node *node; char *base; size_t len; int delta, ksize, oksize; indx_t ptr, i, numkeys, indx; DKBUF; indx = mc->mc_ki[mc->mc_top]; mp = mc->mc_pg[mc->mc_top]; node = NODEPTR(mp, indx); ptr = mp->mp_ptrs[indx]; #if MDB_DEBUG { MDB_val k2; char kbuf2[DKBUF_MAXKEYSIZE*2+1]; k2.mv_data = NODEKEY(node); k2.mv_size = node->mn_ksize; DPRINTF(("update key %u (ofs %u) [%s] to [%s] on page %"Z"u", indx, ptr, mdb_dkey(&k2, kbuf2), DKEY(key), mp->mp_pgno)); } #endif /* Sizes must be 2-byte aligned. */ ksize = EVEN(key->mv_size); oksize = EVEN(node->mn_ksize); delta = ksize - oksize; /* Shift node contents if EVEN(key length) changed. */ if (delta) { if (delta > 0 && SIZELEFT(mp) < delta) { pgno_t pgno; /* not enough space left, do a delete and split */ DPRINTF(("Not enough room, delta = %d, splitting...", delta)); pgno = NODEPGNO(node); mdb_node_del(mc, 0); return mdb_page_split(mc, key, NULL, pgno, MDB_SPLIT_REPLACE); } numkeys = NUMKEYS(mp); for (i = 0; i < numkeys; i++) { if (mp->mp_ptrs[i] <= ptr) mp->mp_ptrs[i] -= delta; } base = (char *)mp + mp->mp_upper + PAGEBASE; len = ptr - mp->mp_upper + NODESIZE; memmove(base - delta, base, len); mp->mp_upper -= delta; node = NODEPTR(mp, indx); } /* But even if no shift was needed, update ksize */ if (node->mn_ksize != key->mv_size) node->mn_ksize = key->mv_size; if (key->mv_size) memcpy(NODEKEY(node), key->mv_data, key->mv_size); return MDB_SUCCESS; } static void mdb_cursor_copy(const MDB_cursor *csrc, MDB_cursor *cdst); /** Move a node from csrc to cdst. */ static int mdb_node_move(MDB_cursor *csrc, MDB_cursor *cdst) { MDB_node *srcnode; MDB_val key, data; pgno_t srcpg; MDB_cursor mn; int rc; unsigned short flags; DKBUF; /* Mark src and dst as dirty. */ if ((rc = mdb_page_touch(csrc)) || (rc = mdb_page_touch(cdst))) return rc; if (IS_LEAF2(csrc->mc_pg[csrc->mc_top])) { key.mv_size = csrc->mc_db->md_pad; key.mv_data = LEAF2KEY(csrc->mc_pg[csrc->mc_top], csrc->mc_ki[csrc->mc_top], key.mv_size); data.mv_size = 0; data.mv_data = NULL; srcpg = 0; flags = 0; } else { srcnode = NODEPTR(csrc->mc_pg[csrc->mc_top], csrc->mc_ki[csrc->mc_top]); mdb_cassert(csrc, !((size_t)srcnode & 1)); srcpg = NODEPGNO(srcnode); flags = srcnode->mn_flags; if (csrc->mc_ki[csrc->mc_top] == 0 && IS_BRANCH(csrc->mc_pg[csrc->mc_top])) { unsigned int snum = csrc->mc_snum; MDB_node *s2; /* must find the lowest key below src */ rc = mdb_page_search_lowest(csrc); if (rc) return rc; if (IS_LEAF2(csrc->mc_pg[csrc->mc_top])) { key.mv_size = csrc->mc_db->md_pad; key.mv_data = LEAF2KEY(csrc->mc_pg[csrc->mc_top], 0, key.mv_size); } else { s2 = NODEPTR(csrc->mc_pg[csrc->mc_top], 0); key.mv_size = NODEKSZ(s2); key.mv_data = NODEKEY(s2); } csrc->mc_snum = snum--; csrc->mc_top = snum; } else { key.mv_size = NODEKSZ(srcnode); key.mv_data = NODEKEY(srcnode); } data.mv_size = NODEDSZ(srcnode); data.mv_data = NODEDATA(srcnode); } if (IS_BRANCH(cdst->mc_pg[cdst->mc_top]) && cdst->mc_ki[cdst->mc_top] == 0) { unsigned int snum = cdst->mc_snum; MDB_node *s2; MDB_val bkey; /* must find the lowest key below dst */ mdb_cursor_copy(cdst, &mn); rc = mdb_page_search_lowest(&mn); if (rc) return rc; if (IS_LEAF2(mn.mc_pg[mn.mc_top])) { bkey.mv_size = mn.mc_db->md_pad; bkey.mv_data = LEAF2KEY(mn.mc_pg[mn.mc_top], 0, bkey.mv_size); } else { s2 = NODEPTR(mn.mc_pg[mn.mc_top], 0); bkey.mv_size = NODEKSZ(s2); bkey.mv_data = NODEKEY(s2); } mn.mc_snum = snum--; mn.mc_top = snum; mn.mc_ki[snum] = 0; rc = mdb_update_key(&mn, &bkey); if (rc) return rc; } DPRINTF(("moving %s node %u [%s] on page %"Z"u to node %u on page %"Z"u", IS_LEAF(csrc->mc_pg[csrc->mc_top]) ? "leaf" : "branch", csrc->mc_ki[csrc->mc_top], DKEY(&key), csrc->mc_pg[csrc->mc_top]->mp_pgno, cdst->mc_ki[cdst->mc_top], cdst->mc_pg[cdst->mc_top]->mp_pgno)); /* Add the node to the destination page. */ rc = mdb_node_add(cdst, cdst->mc_ki[cdst->mc_top], &key, &data, srcpg, flags); if (rc != MDB_SUCCESS) return rc; /* Delete the node from the source page. */ mdb_node_del(csrc, key.mv_size); { /* Adjust other cursors pointing to mp */ MDB_cursor *m2, *m3; MDB_dbi dbi = csrc->mc_dbi; MDB_page *mp = csrc->mc_pg[csrc->mc_top]; for (m2 = csrc->mc_txn->mt_cursors[dbi]; m2; m2=m2->mc_next) { if (csrc->mc_flags & C_SUB) m3 = &m2->mc_xcursor->mx_cursor; else m3 = m2; if (m3 == csrc) continue; if (m3->mc_pg[csrc->mc_top] == mp && m3->mc_ki[csrc->mc_top] == csrc->mc_ki[csrc->mc_top]) { m3->mc_pg[csrc->mc_top] = cdst->mc_pg[cdst->mc_top]; m3->mc_ki[csrc->mc_top] = cdst->mc_ki[cdst->mc_top]; } } } /* Update the parent separators. */ if (csrc->mc_ki[csrc->mc_top] == 0) { if (csrc->mc_ki[csrc->mc_top-1] != 0) { if (IS_LEAF2(csrc->mc_pg[csrc->mc_top])) { key.mv_data = LEAF2KEY(csrc->mc_pg[csrc->mc_top], 0, key.mv_size); } else { srcnode = NODEPTR(csrc->mc_pg[csrc->mc_top], 0); key.mv_size = NODEKSZ(srcnode); key.mv_data = NODEKEY(srcnode); } DPRINTF(("update separator for source page %"Z"u to [%s]", csrc->mc_pg[csrc->mc_top]->mp_pgno, DKEY(&key))); mdb_cursor_copy(csrc, &mn); mn.mc_snum--; mn.mc_top--; if ((rc = mdb_update_key(&mn, &key)) != MDB_SUCCESS) return rc; } if (IS_BRANCH(csrc->mc_pg[csrc->mc_top])) { MDB_val nullkey; indx_t ix = csrc->mc_ki[csrc->mc_top]; nullkey.mv_size = 0; csrc->mc_ki[csrc->mc_top] = 0; rc = mdb_update_key(csrc, &nullkey); csrc->mc_ki[csrc->mc_top] = ix; mdb_cassert(csrc, rc == MDB_SUCCESS); } } if (cdst->mc_ki[cdst->mc_top] == 0) { if (cdst->mc_ki[cdst->mc_top-1] != 0) { if (IS_LEAF2(csrc->mc_pg[csrc->mc_top])) { key.mv_data = LEAF2KEY(cdst->mc_pg[cdst->mc_top], 0, key.mv_size); } else { srcnode = NODEPTR(cdst->mc_pg[cdst->mc_top], 0); key.mv_size = NODEKSZ(srcnode); key.mv_data = NODEKEY(srcnode); } DPRINTF(("update separator for destination page %"Z"u to [%s]", cdst->mc_pg[cdst->mc_top]->mp_pgno, DKEY(&key))); mdb_cursor_copy(cdst, &mn); mn.mc_snum--; mn.mc_top--; if ((rc = mdb_update_key(&mn, &key)) != MDB_SUCCESS) return rc; } if (IS_BRANCH(cdst->mc_pg[cdst->mc_top])) { MDB_val nullkey; indx_t ix = cdst->mc_ki[cdst->mc_top]; nullkey.mv_size = 0; cdst->mc_ki[cdst->mc_top] = 0; rc = mdb_update_key(cdst, &nullkey); cdst->mc_ki[cdst->mc_top] = ix; mdb_cassert(cdst, rc == MDB_SUCCESS); } } return MDB_SUCCESS; } /** Merge one page into another. * The nodes from the page pointed to by \b csrc will * be copied to the page pointed to by \b cdst and then * the \b csrc page will be freed. * @param[in] csrc Cursor pointing to the source page. * @param[in] cdst Cursor pointing to the destination page. * @return 0 on success, non-zero on failure. */ static int mdb_page_merge(MDB_cursor *csrc, MDB_cursor *cdst) { MDB_page *psrc, *pdst; MDB_node *srcnode; MDB_val key, data; unsigned nkeys; int rc; indx_t i, j; psrc = csrc->mc_pg[csrc->mc_top]; pdst = cdst->mc_pg[cdst->mc_top]; DPRINTF(("merging page %"Z"u into %"Z"u", psrc->mp_pgno, pdst->mp_pgno)); mdb_cassert(csrc, csrc->mc_snum > 1); /* can't merge root page */ mdb_cassert(csrc, cdst->mc_snum > 1); /* Mark dst as dirty. */ if ((rc = mdb_page_touch(cdst))) return rc; /* Move all nodes from src to dst. */ j = nkeys = NUMKEYS(pdst); if (IS_LEAF2(psrc)) { key.mv_size = csrc->mc_db->md_pad; key.mv_data = METADATA(psrc); for (i = 0; i < NUMKEYS(psrc); i++, j++) { rc = mdb_node_add(cdst, j, &key, NULL, 0, 0); if (rc != MDB_SUCCESS) return rc; key.mv_data = (char *)key.mv_data + key.mv_size; } } else { for (i = 0; i < NUMKEYS(psrc); i++, j++) { srcnode = NODEPTR(psrc, i); if (i == 0 && IS_BRANCH(psrc)) { MDB_cursor mn; MDB_node *s2; mdb_cursor_copy(csrc, &mn); /* must find the lowest key below src */ rc = mdb_page_search_lowest(&mn); if (rc) return rc; if (IS_LEAF2(mn.mc_pg[mn.mc_top])) { key.mv_size = mn.mc_db->md_pad; key.mv_data = LEAF2KEY(mn.mc_pg[mn.mc_top], 0, key.mv_size); } else { s2 = NODEPTR(mn.mc_pg[mn.mc_top], 0); key.mv_size = NODEKSZ(s2); key.mv_data = NODEKEY(s2); } } else { key.mv_size = srcnode->mn_ksize; key.mv_data = NODEKEY(srcnode); } data.mv_size = NODEDSZ(srcnode); data.mv_data = NODEDATA(srcnode); rc = mdb_node_add(cdst, j, &key, &data, NODEPGNO(srcnode), srcnode->mn_flags); if (rc != MDB_SUCCESS) return rc; } } DPRINTF(("dst page %"Z"u now has %u keys (%.1f%% filled)", pdst->mp_pgno, NUMKEYS(pdst), (float)PAGEFILL(cdst->mc_txn->mt_env, pdst) / 10)); /* Unlink the src page from parent and add to free list. */ csrc->mc_top--; mdb_node_del(csrc, 0); if (csrc->mc_ki[csrc->mc_top] == 0) { key.mv_size = 0; rc = mdb_update_key(csrc, &key); if (rc) { csrc->mc_top++; return rc; } } csrc->mc_top++; psrc = csrc->mc_pg[csrc->mc_top]; /* If not operating on FreeDB, allow this page to be reused * in this txn. Otherwise just add to free list. */ rc = mdb_page_loose(csrc, psrc); if (rc) return rc; if (IS_LEAF(psrc)) csrc->mc_db->md_leaf_pages--; else csrc->mc_db->md_branch_pages--; { /* Adjust other cursors pointing to mp */ MDB_cursor *m2, *m3; MDB_dbi dbi = csrc->mc_dbi; for (m2 = csrc->mc_txn->mt_cursors[dbi]; m2; m2=m2->mc_next) { if (csrc->mc_flags & C_SUB) m3 = &m2->mc_xcursor->mx_cursor; else m3 = m2; if (m3 == csrc) continue; if (m3->mc_snum < csrc->mc_snum) continue; if (m3->mc_pg[csrc->mc_top] == psrc) { m3->mc_pg[csrc->mc_top] = pdst; m3->mc_ki[csrc->mc_top] += nkeys; } } } { unsigned int snum = cdst->mc_snum; uint16_t depth = cdst->mc_db->md_depth; mdb_cursor_pop(cdst); rc = mdb_rebalance(cdst); /* Did the tree shrink? */ if (depth > cdst->mc_db->md_depth) snum--; cdst->mc_snum = snum; cdst->mc_top = snum-1; } return rc; } /** Copy the contents of a cursor. * @param[in] csrc The cursor to copy from. * @param[out] cdst The cursor to copy to. */ static void mdb_cursor_copy(const MDB_cursor *csrc, MDB_cursor *cdst) { unsigned int i; cdst->mc_txn = csrc->mc_txn; cdst->mc_dbi = csrc->mc_dbi; cdst->mc_db = csrc->mc_db; cdst->mc_dbx = csrc->mc_dbx; cdst->mc_snum = csrc->mc_snum; cdst->mc_top = csrc->mc_top; cdst->mc_flags = csrc->mc_flags; for (i=0; imc_snum; i++) { cdst->mc_pg[i] = csrc->mc_pg[i]; cdst->mc_ki[i] = csrc->mc_ki[i]; } } /** Rebalance the tree after a delete operation. * @param[in] mc Cursor pointing to the page where rebalancing * should begin. * @return 0 on success, non-zero on failure. */ static int mdb_rebalance(MDB_cursor *mc) { MDB_node *node; int rc; unsigned int ptop, minkeys; MDB_cursor mn; indx_t oldki; minkeys = 1 + (IS_BRANCH(mc->mc_pg[mc->mc_top])); DPRINTF(("rebalancing %s page %"Z"u (has %u keys, %.1f%% full)", IS_LEAF(mc->mc_pg[mc->mc_top]) ? "leaf" : "branch", mdb_dbg_pgno(mc->mc_pg[mc->mc_top]), NUMKEYS(mc->mc_pg[mc->mc_top]), (float)PAGEFILL(mc->mc_txn->mt_env, mc->mc_pg[mc->mc_top]) / 10)); if (PAGEFILL(mc->mc_txn->mt_env, mc->mc_pg[mc->mc_top]) >= FILL_THRESHOLD && NUMKEYS(mc->mc_pg[mc->mc_top]) >= minkeys) { DPRINTF(("no need to rebalance page %"Z"u, above fill threshold", mdb_dbg_pgno(mc->mc_pg[mc->mc_top]))); return MDB_SUCCESS; } if (mc->mc_snum < 2) { MDB_page *mp = mc->mc_pg[0]; if (IS_SUBP(mp)) { DPUTS("Can't rebalance a subpage, ignoring"); return MDB_SUCCESS; } if (NUMKEYS(mp) == 0) { DPUTS("tree is completely empty"); mc->mc_db->md_root = P_INVALID; mc->mc_db->md_depth = 0; mc->mc_db->md_leaf_pages = 0; rc = mdb_midl_append(&mc->mc_txn->mt_free_pgs, mp->mp_pgno); if (rc) return rc; /* Adjust cursors pointing to mp */ mc->mc_snum = 0; mc->mc_top = 0; mc->mc_flags &= ~C_INITIALIZED; { MDB_cursor *m2, *m3; MDB_dbi dbi = mc->mc_dbi; for (m2 = mc->mc_txn->mt_cursors[dbi]; m2; m2=m2->mc_next) { if (mc->mc_flags & C_SUB) m3 = &m2->mc_xcursor->mx_cursor; else m3 = m2; if (m3->mc_snum < mc->mc_snum) continue; if (m3->mc_pg[0] == mp) { m3->mc_snum = 0; m3->mc_top = 0; m3->mc_flags &= ~C_INITIALIZED; } } } } else if (IS_BRANCH(mp) && NUMKEYS(mp) == 1) { int i; DPUTS("collapsing root page!"); rc = mdb_midl_append(&mc->mc_txn->mt_free_pgs, mp->mp_pgno); if (rc) return rc; mc->mc_db->md_root = NODEPGNO(NODEPTR(mp, 0)); rc = mdb_page_get(mc->mc_txn,mc->mc_db->md_root,&mc->mc_pg[0],NULL); if (rc) return rc; mc->mc_db->md_depth--; mc->mc_db->md_branch_pages--; mc->mc_ki[0] = mc->mc_ki[1]; for (i = 1; imc_db->md_depth; i++) { mc->mc_pg[i] = mc->mc_pg[i+1]; mc->mc_ki[i] = mc->mc_ki[i+1]; } { /* Adjust other cursors pointing to mp */ MDB_cursor *m2, *m3; MDB_dbi dbi = mc->mc_dbi; for (m2 = mc->mc_txn->mt_cursors[dbi]; m2; m2=m2->mc_next) { if (mc->mc_flags & C_SUB) m3 = &m2->mc_xcursor->mx_cursor; else m3 = m2; if (m3 == mc || m3->mc_snum < mc->mc_snum) continue; if (m3->mc_pg[0] == mp) { for (i=0; imc_snum; i++) { m3->mc_pg[i] = m3->mc_pg[i+1]; m3->mc_ki[i] = m3->mc_ki[i+1]; } m3->mc_snum--; m3->mc_top--; } } } } else DPUTS("root page doesn't need rebalancing"); return MDB_SUCCESS; } /* The parent (branch page) must have at least 2 pointers, * otherwise the tree is invalid. */ ptop = mc->mc_top-1; mdb_cassert(mc, NUMKEYS(mc->mc_pg[ptop]) > 1); /* Leaf page fill factor is below the threshold. * Try to move keys from left or right neighbor, or * merge with a neighbor page. */ /* Find neighbors. */ mdb_cursor_copy(mc, &mn); mn.mc_xcursor = NULL; oldki = mc->mc_ki[mc->mc_top]; if (mc->mc_ki[ptop] == 0) { /* We're the leftmost leaf in our parent. */ DPUTS("reading right neighbor"); mn.mc_ki[ptop]++; node = NODEPTR(mc->mc_pg[ptop], mn.mc_ki[ptop]); rc = mdb_page_get(mc->mc_txn,NODEPGNO(node),&mn.mc_pg[mn.mc_top],NULL); if (rc) return rc; mn.mc_ki[mn.mc_top] = 0; mc->mc_ki[mc->mc_top] = NUMKEYS(mc->mc_pg[mc->mc_top]); } else { /* There is at least one neighbor to the left. */ DPUTS("reading left neighbor"); mn.mc_ki[ptop]--; node = NODEPTR(mc->mc_pg[ptop], mn.mc_ki[ptop]); rc = mdb_page_get(mc->mc_txn,NODEPGNO(node),&mn.mc_pg[mn.mc_top],NULL); if (rc) return rc; mn.mc_ki[mn.mc_top] = NUMKEYS(mn.mc_pg[mn.mc_top]) - 1; mc->mc_ki[mc->mc_top] = 0; } DPRINTF(("found neighbor page %"Z"u (%u keys, %.1f%% full)", mn.mc_pg[mn.mc_top]->mp_pgno, NUMKEYS(mn.mc_pg[mn.mc_top]), (float)PAGEFILL(mc->mc_txn->mt_env, mn.mc_pg[mn.mc_top]) / 10)); /* If the neighbor page is above threshold and has enough keys, * move one key from it. Otherwise we should try to merge them. * (A branch page must never have less than 2 keys.) */ minkeys = 1 + (IS_BRANCH(mn.mc_pg[mn.mc_top])); if (PAGEFILL(mc->mc_txn->mt_env, mn.mc_pg[mn.mc_top]) >= FILL_THRESHOLD && NUMKEYS(mn.mc_pg[mn.mc_top]) > minkeys) { rc = mdb_node_move(&mn, mc); if (mc->mc_ki[ptop]) { oldki++; } } else { if (mc->mc_ki[ptop] == 0) { rc = mdb_page_merge(&mn, mc); } else { MDB_cursor dummy; oldki += NUMKEYS(mn.mc_pg[mn.mc_top]); mn.mc_ki[mn.mc_top] += mc->mc_ki[mn.mc_top] + 1; /* We want mdb_rebalance to find mn when doing fixups */ if (mc->mc_flags & C_SUB) { dummy.mc_next = mc->mc_txn->mt_cursors[mc->mc_dbi]; mc->mc_txn->mt_cursors[mc->mc_dbi] = &dummy; dummy.mc_xcursor = (MDB_xcursor *)&mn; } else { mn.mc_next = mc->mc_txn->mt_cursors[mc->mc_dbi]; mc->mc_txn->mt_cursors[mc->mc_dbi] = &mn; } rc = mdb_page_merge(mc, &mn); if (mc->mc_flags & C_SUB) mc->mc_txn->mt_cursors[mc->mc_dbi] = dummy.mc_next; else mc->mc_txn->mt_cursors[mc->mc_dbi] = mn.mc_next; mdb_cursor_copy(&mn, mc); } mc->mc_flags &= ~C_EOF; } mc->mc_ki[mc->mc_top] = oldki; return rc; } /** Complete a delete operation started by #mdb_cursor_del(). */ static int mdb_cursor_del0(MDB_cursor *mc) { int rc; MDB_page *mp; indx_t ki; unsigned int nkeys; ki = mc->mc_ki[mc->mc_top]; mdb_node_del(mc, mc->mc_db->md_pad); mc->mc_db->md_entries--; rc = mdb_rebalance(mc); if (rc == MDB_SUCCESS) { MDB_cursor *m2, *m3; MDB_dbi dbi = mc->mc_dbi; /* DB is totally empty now, just bail out. * Other cursors adjustments were already done * by mdb_rebalance and aren't needed here. */ if (!mc->mc_snum) return rc; mp = mc->mc_pg[mc->mc_top]; nkeys = NUMKEYS(mp); /* if mc points past last node in page, find next sibling */ if (mc->mc_ki[mc->mc_top] >= nkeys) { rc = mdb_cursor_sibling(mc, 1); if (rc == MDB_NOTFOUND) { mc->mc_flags |= C_EOF; rc = MDB_SUCCESS; } } /* Adjust other cursors pointing to mp */ for (m2 = mc->mc_txn->mt_cursors[dbi]; !rc && m2; m2=m2->mc_next) { m3 = (mc->mc_flags & C_SUB) ? &m2->mc_xcursor->mx_cursor : m2; if (! (m2->mc_flags & m3->mc_flags & C_INITIALIZED)) continue; if (m3 == mc || m3->mc_snum < mc->mc_snum) continue; if (m3->mc_pg[mc->mc_top] == mp) { if (m3->mc_ki[mc->mc_top] >= ki) { m3->mc_flags |= C_DEL; if (m3->mc_ki[mc->mc_top] > ki) m3->mc_ki[mc->mc_top]--; else if (mc->mc_db->md_flags & MDB_DUPSORT) m3->mc_xcursor->mx_cursor.mc_flags |= C_EOF; } if (m3->mc_ki[mc->mc_top] >= nkeys) { rc = mdb_cursor_sibling(m3, 1); if (rc == MDB_NOTFOUND) { m3->mc_flags |= C_EOF; rc = MDB_SUCCESS; } } } } mc->mc_flags |= C_DEL; } if (rc) mc->mc_txn->mt_flags |= MDB_TXN_ERROR; return rc; } int mdb_del(MDB_txn *txn, MDB_dbi dbi, MDB_val *key, MDB_val *data) { if (!key || dbi == FREE_DBI || !TXN_DBI_EXIST(txn, dbi)) return EINVAL; if (txn->mt_flags & (MDB_TXN_RDONLY|MDB_TXN_ERROR)) return (txn->mt_flags & MDB_TXN_RDONLY) ? EACCES : MDB_BAD_TXN; if (!F_ISSET(txn->mt_dbs[dbi].md_flags, MDB_DUPSORT)) { /* must ignore any data */ data = NULL; } return mdb_del0(txn, dbi, key, data, 0); } static int mdb_del0(MDB_txn *txn, MDB_dbi dbi, MDB_val *key, MDB_val *data, unsigned flags) { MDB_cursor mc; MDB_xcursor mx; MDB_cursor_op op; MDB_val rdata, *xdata; int rc, exact = 0; DKBUF; DPRINTF(("====> delete db %u key [%s]", dbi, DKEY(key))); mdb_cursor_init(&mc, txn, dbi, &mx); if (data) { op = MDB_GET_BOTH; rdata = *data; xdata = &rdata; } else { op = MDB_SET; xdata = NULL; flags |= MDB_NODUPDATA; } rc = mdb_cursor_set(&mc, key, xdata, op, &exact); if (rc == 0) { /* let mdb_page_split know about this cursor if needed: * delete will trigger a rebalance; if it needs to move * a node from one page to another, it will have to * update the parent's separator key(s). If the new sepkey * is larger than the current one, the parent page may * run out of space, triggering a split. We need this * cursor to be consistent until the end of the rebalance. */ mc.mc_flags |= C_UNTRACK; mc.mc_next = txn->mt_cursors[dbi]; txn->mt_cursors[dbi] = &mc; rc = mdb_cursor_del(&mc, flags); txn->mt_cursors[dbi] = mc.mc_next; } return rc; } /** Split a page and insert a new node. * @param[in,out] mc Cursor pointing to the page and desired insertion index. * The cursor will be updated to point to the actual page and index where * the node got inserted after the split. * @param[in] newkey The key for the newly inserted node. * @param[in] newdata The data for the newly inserted node. * @param[in] newpgno The page number, if the new node is a branch node. * @param[in] nflags The #NODE_ADD_FLAGS for the new node. * @return 0 on success, non-zero on failure. */ static int mdb_page_split(MDB_cursor *mc, MDB_val *newkey, MDB_val *newdata, pgno_t newpgno, unsigned int nflags) { unsigned int flags; int rc = MDB_SUCCESS, new_root = 0, did_split = 0; indx_t newindx; pgno_t pgno = 0; int i, j, split_indx, nkeys, pmax; MDB_env *env = mc->mc_txn->mt_env; MDB_node *node; MDB_val sepkey, rkey, xdata, *rdata = &xdata; MDB_page *copy = NULL; MDB_page *mp, *rp, *pp; int ptop; MDB_cursor mn; DKBUF; mp = mc->mc_pg[mc->mc_top]; newindx = mc->mc_ki[mc->mc_top]; nkeys = NUMKEYS(mp); DPRINTF(("-----> splitting %s page %"Z"u and adding [%s] at index %i/%i", IS_LEAF(mp) ? "leaf" : "branch", mp->mp_pgno, DKEY(newkey), mc->mc_ki[mc->mc_top], nkeys)); /* Create a right sibling. */ if ((rc = mdb_page_new(mc, mp->mp_flags, 1, &rp))) return rc; DPRINTF(("new right sibling: page %"Z"u", rp->mp_pgno)); if (mc->mc_snum < 2) { if ((rc = mdb_page_new(mc, P_BRANCH, 1, &pp))) goto done; /* shift current top to make room for new parent */ mc->mc_pg[1] = mc->mc_pg[0]; mc->mc_ki[1] = mc->mc_ki[0]; mc->mc_pg[0] = pp; mc->mc_ki[0] = 0; mc->mc_db->md_root = pp->mp_pgno; DPRINTF(("root split! new root = %"Z"u", pp->mp_pgno)); mc->mc_db->md_depth++; new_root = 1; /* Add left (implicit) pointer. */ if ((rc = mdb_node_add(mc, 0, NULL, NULL, mp->mp_pgno, 0)) != MDB_SUCCESS) { /* undo the pre-push */ mc->mc_pg[0] = mc->mc_pg[1]; mc->mc_ki[0] = mc->mc_ki[1]; mc->mc_db->md_root = mp->mp_pgno; mc->mc_db->md_depth--; goto done; } mc->mc_snum = 2; mc->mc_top = 1; ptop = 0; } else { ptop = mc->mc_top-1; DPRINTF(("parent branch page is %"Z"u", mc->mc_pg[ptop]->mp_pgno)); } mc->mc_flags |= C_SPLITTING; mdb_cursor_copy(mc, &mn); mn.mc_pg[mn.mc_top] = rp; mn.mc_ki[ptop] = mc->mc_ki[ptop]+1; if (nflags & MDB_APPEND) { mn.mc_ki[mn.mc_top] = 0; sepkey = *newkey; split_indx = newindx; nkeys = 0; } else { split_indx = (nkeys+1) / 2; if (IS_LEAF2(rp)) { char *split, *ins; int x; unsigned int lsize, rsize, ksize; /* Move half of the keys to the right sibling */ x = mc->mc_ki[mc->mc_top] - split_indx; ksize = mc->mc_db->md_pad; split = LEAF2KEY(mp, split_indx, ksize); rsize = (nkeys - split_indx) * ksize; lsize = (nkeys - split_indx) * sizeof(indx_t); mp->mp_lower -= lsize; rp->mp_lower += lsize; mp->mp_upper += rsize - lsize; rp->mp_upper -= rsize - lsize; sepkey.mv_size = ksize; if (newindx == split_indx) { sepkey.mv_data = newkey->mv_data; } else { sepkey.mv_data = split; } if (x<0) { ins = LEAF2KEY(mp, mc->mc_ki[mc->mc_top], ksize); memcpy(rp->mp_ptrs, split, rsize); sepkey.mv_data = rp->mp_ptrs; memmove(ins+ksize, ins, (split_indx - mc->mc_ki[mc->mc_top]) * ksize); memcpy(ins, newkey->mv_data, ksize); mp->mp_lower += sizeof(indx_t); mp->mp_upper -= ksize - sizeof(indx_t); } else { if (x) memcpy(rp->mp_ptrs, split, x * ksize); ins = LEAF2KEY(rp, x, ksize); memcpy(ins, newkey->mv_data, ksize); memcpy(ins+ksize, split + x * ksize, rsize - x * ksize); rp->mp_lower += sizeof(indx_t); rp->mp_upper -= ksize - sizeof(indx_t); mc->mc_ki[mc->mc_top] = x; mc->mc_pg[mc->mc_top] = rp; } } else { int psize, nsize, k; /* Maximum free space in an empty page */ pmax = env->me_psize - PAGEHDRSZ; if (IS_LEAF(mp)) nsize = mdb_leaf_size(env, newkey, newdata); else nsize = mdb_branch_size(env, newkey); nsize = EVEN(nsize); /* grab a page to hold a temporary copy */ copy = mdb_page_malloc(mc->mc_txn, 1); if (copy == NULL) { rc = ENOMEM; goto done; } copy->mp_pgno = mp->mp_pgno; copy->mp_flags = mp->mp_flags; copy->mp_lower = (PAGEHDRSZ-PAGEBASE); copy->mp_upper = env->me_psize - PAGEBASE; /* prepare to insert */ for (i=0, j=0; imp_ptrs[j++] = 0; } copy->mp_ptrs[j++] = mp->mp_ptrs[i]; } /* When items are relatively large the split point needs * to be checked, because being off-by-one will make the * difference between success or failure in mdb_node_add. * * It's also relevant if a page happens to be laid out * such that one half of its nodes are all "small" and * the other half of its nodes are "large." If the new * item is also "large" and falls on the half with * "large" nodes, it also may not fit. * * As a final tweak, if the new item goes on the last * spot on the page (and thus, onto the new page), bias * the split so the new page is emptier than the old page. * This yields better packing during sequential inserts. */ if (nkeys < 20 || nsize > pmax/16 || newindx >= nkeys) { /* Find split point */ psize = 0; if (newindx <= split_indx || newindx >= nkeys) { i = 0; j = 1; k = newindx >= nkeys ? nkeys : split_indx+2; } else { i = nkeys; j = -1; k = split_indx-1; } for (; i!=k; i+=j) { if (i == newindx) { psize += nsize; node = NULL; } else { node = (MDB_node *)((char *)mp + copy->mp_ptrs[i] + PAGEBASE); psize += NODESIZE + NODEKSZ(node) + sizeof(indx_t); if (IS_LEAF(mp)) { if (F_ISSET(node->mn_flags, F_BIGDATA)) psize += sizeof(pgno_t); else psize += NODEDSZ(node); } psize = EVEN(psize); } if (psize > pmax || i == k-j) { split_indx = i + (j<0); break; } } } if (split_indx == newindx) { sepkey.mv_size = newkey->mv_size; sepkey.mv_data = newkey->mv_data; } else { node = (MDB_node *)((char *)mp + copy->mp_ptrs[split_indx] + PAGEBASE); sepkey.mv_size = node->mn_ksize; sepkey.mv_data = NODEKEY(node); } } } DPRINTF(("separator is %d [%s]", split_indx, DKEY(&sepkey))); /* Copy separator key to the parent. */ if (SIZELEFT(mn.mc_pg[ptop]) < mdb_branch_size(env, &sepkey)) { mn.mc_snum--; mn.mc_top--; did_split = 1; rc = mdb_page_split(&mn, &sepkey, NULL, rp->mp_pgno, 0); if (rc) goto done; /* root split? */ if (mn.mc_snum == mc->mc_snum) { mc->mc_pg[mc->mc_snum] = mc->mc_pg[mc->mc_top]; mc->mc_ki[mc->mc_snum] = mc->mc_ki[mc->mc_top]; mc->mc_pg[mc->mc_top] = mc->mc_pg[ptop]; mc->mc_ki[mc->mc_top] = mc->mc_ki[ptop]; mc->mc_snum++; mc->mc_top++; ptop++; } /* Right page might now have changed parent. * Check if left page also changed parent. */ if (mn.mc_pg[ptop] != mc->mc_pg[ptop] && mc->mc_ki[ptop] >= NUMKEYS(mc->mc_pg[ptop])) { for (i=0; imc_pg[i] = mn.mc_pg[i]; mc->mc_ki[i] = mn.mc_ki[i]; } mc->mc_pg[ptop] = mn.mc_pg[ptop]; if (mn.mc_ki[ptop]) { mc->mc_ki[ptop] = mn.mc_ki[ptop] - 1; } else { /* find right page's left sibling */ mc->mc_ki[ptop] = mn.mc_ki[ptop]; mdb_cursor_sibling(mc, 0); } } } else { mn.mc_top--; rc = mdb_node_add(&mn, mn.mc_ki[ptop], &sepkey, NULL, rp->mp_pgno, 0); mn.mc_top++; } mc->mc_flags ^= C_SPLITTING; if (rc != MDB_SUCCESS) { goto done; } if (nflags & MDB_APPEND) { mc->mc_pg[mc->mc_top] = rp; mc->mc_ki[mc->mc_top] = 0; rc = mdb_node_add(mc, 0, newkey, newdata, newpgno, nflags); if (rc) goto done; for (i=0; imc_top; i++) mc->mc_ki[i] = mn.mc_ki[i]; } else if (!IS_LEAF2(mp)) { /* Move nodes */ mc->mc_pg[mc->mc_top] = rp; i = split_indx; j = 0; do { if (i == newindx) { rkey.mv_data = newkey->mv_data; rkey.mv_size = newkey->mv_size; if (IS_LEAF(mp)) { rdata = newdata; } else pgno = newpgno; flags = nflags; /* Update index for the new key. */ mc->mc_ki[mc->mc_top] = j; } else { node = (MDB_node *)((char *)mp + copy->mp_ptrs[i] + PAGEBASE); rkey.mv_data = NODEKEY(node); rkey.mv_size = node->mn_ksize; if (IS_LEAF(mp)) { xdata.mv_data = NODEDATA(node); xdata.mv_size = NODEDSZ(node); rdata = &xdata; } else pgno = NODEPGNO(node); flags = node->mn_flags; } if (!IS_LEAF(mp) && j == 0) { /* First branch index doesn't need key data. */ rkey.mv_size = 0; } rc = mdb_node_add(mc, j, &rkey, rdata, pgno, flags); if (rc) goto done; if (i == nkeys) { i = 0; j = 0; mc->mc_pg[mc->mc_top] = copy; } else { i++; j++; } } while (i != split_indx); nkeys = NUMKEYS(copy); for (i=0; imp_ptrs[i] = copy->mp_ptrs[i]; mp->mp_lower = copy->mp_lower; mp->mp_upper = copy->mp_upper; memcpy(NODEPTR(mp, nkeys-1), NODEPTR(copy, nkeys-1), env->me_psize - copy->mp_upper - PAGEBASE); /* reset back to original page */ if (newindx < split_indx) { mc->mc_pg[mc->mc_top] = mp; if (nflags & MDB_RESERVE) { node = NODEPTR(mp, mc->mc_ki[mc->mc_top]); if (!(node->mn_flags & F_BIGDATA)) newdata->mv_data = NODEDATA(node); } } else { mc->mc_pg[mc->mc_top] = rp; mc->mc_ki[ptop]++; /* Make sure mc_ki is still valid. */ if (mn.mc_pg[ptop] != mc->mc_pg[ptop] && mc->mc_ki[ptop] >= NUMKEYS(mc->mc_pg[ptop])) { for (i=0; i<=ptop; i++) { mc->mc_pg[i] = mn.mc_pg[i]; mc->mc_ki[i] = mn.mc_ki[i]; } } } } { /* Adjust other cursors pointing to mp */ MDB_cursor *m2, *m3; MDB_dbi dbi = mc->mc_dbi; int fixup = NUMKEYS(mp); for (m2 = mc->mc_txn->mt_cursors[dbi]; m2; m2=m2->mc_next) { if (mc->mc_flags & C_SUB) m3 = &m2->mc_xcursor->mx_cursor; else m3 = m2; if (m3 == mc) continue; if (!(m2->mc_flags & m3->mc_flags & C_INITIALIZED)) continue; if (m3->mc_flags & C_SPLITTING) continue; if (new_root) { int k; /* root split */ for (k=m3->mc_top; k>=0; k--) { m3->mc_ki[k+1] = m3->mc_ki[k]; m3->mc_pg[k+1] = m3->mc_pg[k]; } if (m3->mc_ki[0] >= split_indx) { m3->mc_ki[0] = 1; } else { m3->mc_ki[0] = 0; } m3->mc_pg[0] = mc->mc_pg[0]; m3->mc_snum++; m3->mc_top++; } if (m3->mc_top >= mc->mc_top && m3->mc_pg[mc->mc_top] == mp) { if (m3->mc_ki[mc->mc_top] >= newindx && !(nflags & MDB_SPLIT_REPLACE)) m3->mc_ki[mc->mc_top]++; if (m3->mc_ki[mc->mc_top] >= fixup) { m3->mc_pg[mc->mc_top] = rp; m3->mc_ki[mc->mc_top] -= fixup; m3->mc_ki[ptop] = mn.mc_ki[ptop]; } } else if (!did_split && m3->mc_top >= ptop && m3->mc_pg[ptop] == mc->mc_pg[ptop] && m3->mc_ki[ptop] >= mc->mc_ki[ptop]) { m3->mc_ki[ptop]++; } } } DPRINTF(("mp left: %d, rp left: %d", SIZELEFT(mp), SIZELEFT(rp))); done: if (copy) /* tmp page */ mdb_page_free(env, copy); if (rc) mc->mc_txn->mt_flags |= MDB_TXN_ERROR; return rc; } int mdb_put(MDB_txn *txn, MDB_dbi dbi, MDB_val *key, MDB_val *data, unsigned int flags) { MDB_cursor mc; MDB_xcursor mx; if (!key || !data || dbi == FREE_DBI || !TXN_DBI_EXIST(txn, dbi)) return EINVAL; if ((flags & (MDB_NOOVERWRITE|MDB_NODUPDATA|MDB_RESERVE|MDB_APPEND|MDB_APPENDDUP)) != flags) return EINVAL; mdb_cursor_init(&mc, txn, dbi, &mx); return mdb_cursor_put(&mc, key, data, flags); } #ifndef MDB_WBUF #define MDB_WBUF (1024*1024) #endif /** State needed for a compacting copy. */ typedef struct mdb_copy { pthread_mutex_t mc_mutex; pthread_cond_t mc_cond; char *mc_wbuf[2]; char *mc_over[2]; MDB_env *mc_env; MDB_txn *mc_txn; int mc_wlen[2]; int mc_olen[2]; pgno_t mc_next_pgno; HANDLE mc_fd; int mc_status; volatile int mc_new; int mc_toggle; } mdb_copy; /** Dedicated writer thread for compacting copy. */ static THREAD_RET ESECT mdb_env_copythr(void *arg) { mdb_copy *my = arg; char *ptr; int toggle = 0, wsize, rc; #ifdef _WIN32 DWORD len; #define DO_WRITE(rc, fd, ptr, w2, len) rc = WriteFile(fd, ptr, w2, &len, NULL) #else int len; #define DO_WRITE(rc, fd, ptr, w2, len) len = write(fd, ptr, w2); rc = (len >= 0) #endif pthread_mutex_lock(&my->mc_mutex); my->mc_new = 0; pthread_cond_signal(&my->mc_cond); for(;;) { while (!my->mc_new) pthread_cond_wait(&my->mc_cond, &my->mc_mutex); if (my->mc_new < 0) { my->mc_new = 0; break; } my->mc_new = 0; wsize = my->mc_wlen[toggle]; ptr = my->mc_wbuf[toggle]; again: while (wsize > 0) { DO_WRITE(rc, my->mc_fd, ptr, wsize, len); if (!rc) { rc = ErrCode(); break; } else if (len > 0) { rc = MDB_SUCCESS; ptr += len; wsize -= len; continue; } else { rc = EIO; break; } } if (rc) { my->mc_status = rc; break; } /* If there's an overflow page tail, write it too */ if (my->mc_olen[toggle]) { wsize = my->mc_olen[toggle]; ptr = my->mc_over[toggle]; my->mc_olen[toggle] = 0; goto again; } my->mc_wlen[toggle] = 0; toggle ^= 1; pthread_cond_signal(&my->mc_cond); } pthread_cond_signal(&my->mc_cond); pthread_mutex_unlock(&my->mc_mutex); return (THREAD_RET)0; #undef DO_WRITE } /** Tell the writer thread there's a buffer ready to write */ static int ESECT mdb_env_cthr_toggle(mdb_copy *my, int st) { int toggle = my->mc_toggle ^ 1; pthread_mutex_lock(&my->mc_mutex); if (my->mc_status) { pthread_mutex_unlock(&my->mc_mutex); return my->mc_status; } while (my->mc_new == 1) pthread_cond_wait(&my->mc_cond, &my->mc_mutex); my->mc_new = st; my->mc_toggle = toggle; pthread_cond_signal(&my->mc_cond); pthread_mutex_unlock(&my->mc_mutex); return 0; } /** Depth-first tree traversal for compacting copy. */ static int ESECT mdb_env_cwalk(mdb_copy *my, pgno_t *pg, int flags) { MDB_cursor mc; MDB_txn *txn = my->mc_txn; MDB_node *ni; MDB_page *mo, *mp, *leaf; char *buf, *ptr; int rc, toggle; unsigned int i; /* Empty DB, nothing to do */ if (*pg == P_INVALID) return MDB_SUCCESS; mc.mc_snum = 1; mc.mc_top = 0; mc.mc_txn = txn; rc = mdb_page_get(my->mc_txn, *pg, &mc.mc_pg[0], NULL); if (rc) return rc; rc = mdb_page_search_root(&mc, NULL, MDB_PS_FIRST); if (rc) return rc; /* Make cursor pages writable */ buf = ptr = malloc(my->mc_env->me_psize * mc.mc_snum); if (buf == NULL) return ENOMEM; for (i=0; imc_env->me_psize); mc.mc_pg[i] = (MDB_page *)ptr; ptr += my->mc_env->me_psize; } /* This is writable space for a leaf page. Usually not needed. */ leaf = (MDB_page *)ptr; toggle = my->mc_toggle; while (mc.mc_snum > 0) { unsigned n; mp = mc.mc_pg[mc.mc_top]; n = NUMKEYS(mp); if (IS_LEAF(mp)) { if (!IS_LEAF2(mp) && !(flags & F_DUPDATA)) { for (i=0; imn_flags & F_BIGDATA) { MDB_page *omp; pgno_t pg; /* Need writable leaf */ if (mp != leaf) { mc.mc_pg[mc.mc_top] = leaf; mdb_page_copy(leaf, mp, my->mc_env->me_psize); mp = leaf; ni = NODEPTR(mp, i); } memcpy(&pg, NODEDATA(ni), sizeof(pg)); rc = mdb_page_get(txn, pg, &omp, NULL); if (rc) goto done; if (my->mc_wlen[toggle] >= MDB_WBUF) { rc = mdb_env_cthr_toggle(my, 1); if (rc) goto done; toggle = my->mc_toggle; } mo = (MDB_page *)(my->mc_wbuf[toggle] + my->mc_wlen[toggle]); memcpy(mo, omp, my->mc_env->me_psize); mo->mp_pgno = my->mc_next_pgno; my->mc_next_pgno += omp->mp_pages; my->mc_wlen[toggle] += my->mc_env->me_psize; if (omp->mp_pages > 1) { my->mc_olen[toggle] = my->mc_env->me_psize * (omp->mp_pages - 1); my->mc_over[toggle] = (char *)omp + my->mc_env->me_psize; rc = mdb_env_cthr_toggle(my, 1); if (rc) goto done; toggle = my->mc_toggle; } memcpy(NODEDATA(ni), &mo->mp_pgno, sizeof(pgno_t)); } else if (ni->mn_flags & F_SUBDATA) { MDB_db db; /* Need writable leaf */ if (mp != leaf) { mc.mc_pg[mc.mc_top] = leaf; mdb_page_copy(leaf, mp, my->mc_env->me_psize); mp = leaf; ni = NODEPTR(mp, i); } memcpy(&db, NODEDATA(ni), sizeof(db)); my->mc_toggle = toggle; rc = mdb_env_cwalk(my, &db.md_root, ni->mn_flags & F_DUPDATA); if (rc) goto done; toggle = my->mc_toggle; memcpy(NODEDATA(ni), &db, sizeof(db)); } } } } else { mc.mc_ki[mc.mc_top]++; if (mc.mc_ki[mc.mc_top] < n) { pgno_t pg; again: ni = NODEPTR(mp, mc.mc_ki[mc.mc_top]); pg = NODEPGNO(ni); rc = mdb_page_get(txn, pg, &mp, NULL); if (rc) goto done; mc.mc_top++; mc.mc_snum++; mc.mc_ki[mc.mc_top] = 0; if (IS_BRANCH(mp)) { /* Whenever we advance to a sibling branch page, * we must proceed all the way down to its first leaf. */ mdb_page_copy(mc.mc_pg[mc.mc_top], mp, my->mc_env->me_psize); goto again; } else mc.mc_pg[mc.mc_top] = mp; continue; } } if (my->mc_wlen[toggle] >= MDB_WBUF) { rc = mdb_env_cthr_toggle(my, 1); if (rc) goto done; toggle = my->mc_toggle; } mo = (MDB_page *)(my->mc_wbuf[toggle] + my->mc_wlen[toggle]); mdb_page_copy(mo, mp, my->mc_env->me_psize); mo->mp_pgno = my->mc_next_pgno++; my->mc_wlen[toggle] += my->mc_env->me_psize; if (mc.mc_top) { /* Update parent if there is one */ ni = NODEPTR(mc.mc_pg[mc.mc_top-1], mc.mc_ki[mc.mc_top-1]); SETPGNO(ni, mo->mp_pgno); mdb_cursor_pop(&mc); } else { /* Otherwise we're done */ *pg = mo->mp_pgno; break; } } done: free(buf); return rc; } /** Copy environment with compaction. */ static int ESECT mdb_env_copyfd1(MDB_env *env, HANDLE fd) { MDB_meta *mm; MDB_page *mp; mdb_copy my; MDB_txn *txn = NULL; pthread_t thr; int rc; #ifdef _WIN32 my.mc_mutex = CreateMutex(NULL, FALSE, NULL); my.mc_cond = CreateEvent(NULL, FALSE, FALSE, NULL); my.mc_wbuf[0] = _aligned_malloc(MDB_WBUF*2, env->me_os_psize); if (my.mc_wbuf[0] == NULL) return errno; #else pthread_mutex_init(&my.mc_mutex, NULL); pthread_cond_init(&my.mc_cond, NULL); #ifdef HAVE_MEMALIGN my.mc_wbuf[0] = memalign(env->me_os_psize, MDB_WBUF*2); if (my.mc_wbuf[0] == NULL) return errno; #else rc = posix_memalign((void **)&my.mc_wbuf[0], env->me_os_psize, MDB_WBUF*2); if (rc) return rc; #endif #endif memset(my.mc_wbuf[0], 0, MDB_WBUF*2); my.mc_wbuf[1] = my.mc_wbuf[0] + MDB_WBUF; my.mc_wlen[0] = 0; my.mc_wlen[1] = 0; my.mc_olen[0] = 0; my.mc_olen[1] = 0; my.mc_next_pgno = 2; my.mc_status = 0; my.mc_new = 1; my.mc_toggle = 0; my.mc_env = env; my.mc_fd = fd; THREAD_CREATE(thr, mdb_env_copythr, &my); rc = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn); if (rc) return rc; mp = (MDB_page *)my.mc_wbuf[0]; memset(mp, 0, 2*env->me_psize); mp->mp_pgno = 0; mp->mp_flags = P_META; mm = (MDB_meta *)METADATA(mp); mdb_env_init_meta0(env, mm); mm->mm_address = env->me_metas[0]->mm_address; mp = (MDB_page *)(my.mc_wbuf[0] + env->me_psize); mp->mp_pgno = 1; mp->mp_flags = P_META; *(MDB_meta *)METADATA(mp) = *mm; mm = (MDB_meta *)METADATA(mp); /* Count the number of free pages, subtract from lastpg to find * number of active pages */ { MDB_ID freecount = 0; MDB_cursor mc; MDB_val key, data; mdb_cursor_init(&mc, txn, FREE_DBI, NULL); while ((rc = mdb_cursor_get(&mc, &key, &data, MDB_NEXT)) == 0) freecount += *(MDB_ID *)data.mv_data; freecount += txn->mt_dbs[0].md_branch_pages + txn->mt_dbs[0].md_leaf_pages + txn->mt_dbs[0].md_overflow_pages; /* Set metapage 1 */ mm->mm_last_pg = txn->mt_next_pgno - freecount - 1; mm->mm_dbs[1] = txn->mt_dbs[1]; if (mm->mm_last_pg > 1) { mm->mm_dbs[1].md_root = mm->mm_last_pg; mm->mm_txnid = 1; } else { mm->mm_dbs[1].md_root = P_INVALID; } } my.mc_wlen[0] = env->me_psize * 2; my.mc_txn = txn; pthread_mutex_lock(&my.mc_mutex); while(my.mc_new) pthread_cond_wait(&my.mc_cond, &my.mc_mutex); pthread_mutex_unlock(&my.mc_mutex); rc = mdb_env_cwalk(&my, &txn->mt_dbs[1].md_root, 0); if (rc == MDB_SUCCESS && my.mc_wlen[my.mc_toggle]) rc = mdb_env_cthr_toggle(&my, 1); mdb_env_cthr_toggle(&my, -1); pthread_mutex_lock(&my.mc_mutex); while(my.mc_new) pthread_cond_wait(&my.mc_cond, &my.mc_mutex); pthread_mutex_unlock(&my.mc_mutex); THREAD_FINISH(thr); mdb_txn_abort(txn); #ifdef _WIN32 CloseHandle(my.mc_cond); CloseHandle(my.mc_mutex); _aligned_free(my.mc_wbuf[0]); #else pthread_cond_destroy(&my.mc_cond); pthread_mutex_destroy(&my.mc_mutex); free(my.mc_wbuf[0]); #endif return rc; } /** Copy environment as-is. */ static int ESECT mdb_env_copyfd0(MDB_env *env, HANDLE fd) { MDB_txn *txn = NULL; int rc; size_t wsize; char *ptr; #ifdef _WIN32 DWORD len, w2; #define DO_WRITE(rc, fd, ptr, w2, len) rc = WriteFile(fd, ptr, w2, &len, NULL) #else ssize_t len; size_t w2; #define DO_WRITE(rc, fd, ptr, w2, len) len = write(fd, ptr, w2); rc = (len >= 0) #endif /* Do the lock/unlock of the reader mutex before starting the * write txn. Otherwise other read txns could block writers. */ rc = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn); if (rc) return rc; if (env->me_txns) { /* We must start the actual read txn after blocking writers */ mdb_txn_reset0(txn, "reset-stage1"); /* Temporarily block writers until we snapshot the meta pages */ LOCK_MUTEX_W(env); rc = mdb_txn_renew0(txn); if (rc) { UNLOCK_MUTEX_W(env); goto leave; } } wsize = env->me_psize * 2; ptr = env->me_map; w2 = wsize; while (w2 > 0) { DO_WRITE(rc, fd, ptr, w2, len); if (!rc) { rc = ErrCode(); break; } else if (len > 0) { rc = MDB_SUCCESS; ptr += len; w2 -= len; continue; } else { /* Non-blocking or async handles are not supported */ rc = EIO; break; } } if (env->me_txns) UNLOCK_MUTEX_W(env); if (rc) goto leave; w2 = txn->mt_next_pgno * env->me_psize; { size_t fsize = 0; if ((rc = mdb_fsize(env->me_fd, &fsize))) goto leave; if (w2 > fsize) w2 = fsize; } wsize = w2 - wsize; while (wsize > 0) { if (wsize > MAX_WRITE) w2 = MAX_WRITE; else w2 = wsize; DO_WRITE(rc, fd, ptr, w2, len); if (!rc) { rc = ErrCode(); break; } else if (len > 0) { rc = MDB_SUCCESS; ptr += len; wsize -= len; continue; } else { rc = EIO; break; } } leave: mdb_txn_abort(txn); return rc; } int ESECT mdb_env_copyfd2(MDB_env *env, HANDLE fd, unsigned int flags) { if (flags & MDB_CP_COMPACT) return mdb_env_copyfd1(env, fd); else return mdb_env_copyfd0(env, fd); } int ESECT mdb_env_copyfd(MDB_env *env, HANDLE fd) { return mdb_env_copyfd2(env, fd, 0); } int ESECT mdb_env_copy2(MDB_env *env, const char *path, unsigned int flags) { int rc, len; char *lpath; HANDLE newfd = INVALID_HANDLE_VALUE; if (env->me_flags & MDB_NOSUBDIR) { lpath = (char *)path; } else { len = strlen(path); len += sizeof(DATANAME); lpath = malloc(len); if (!lpath) return ENOMEM; sprintf(lpath, "%s" DATANAME, path); } /* The destination path must exist, but the destination file must not. * We don't want the OS to cache the writes, since the source data is * already in the OS cache. */ #ifdef _WIN32 newfd = CreateFile(lpath, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_FLAG_NO_BUFFERING|FILE_FLAG_WRITE_THROUGH, NULL); #else newfd = open(lpath, O_WRONLY|O_CREAT|O_EXCL, 0666); #endif if (newfd == INVALID_HANDLE_VALUE) { rc = ErrCode(); goto leave; } if (env->me_psize >= env->me_os_psize) { #ifdef O_DIRECT /* Set O_DIRECT if the file system supports it */ if ((rc = fcntl(newfd, F_GETFL)) != -1) (void) fcntl(newfd, F_SETFL, rc | O_DIRECT); #endif #ifdef F_NOCACHE /* __APPLE__ */ rc = fcntl(newfd, F_NOCACHE, 1); if (rc) { rc = ErrCode(); goto leave; } #endif } rc = mdb_env_copyfd2(env, newfd, flags); leave: if (!(env->me_flags & MDB_NOSUBDIR)) free(lpath); if (newfd != INVALID_HANDLE_VALUE) if (close(newfd) < 0 && rc == MDB_SUCCESS) rc = ErrCode(); return rc; } int ESECT mdb_env_copy(MDB_env *env, const char *path) { return mdb_env_copy2(env, path, 0); } int ESECT mdb_env_set_flags(MDB_env *env, unsigned int flag, int onoff) { if ((flag & CHANGEABLE) != flag) return EINVAL; if (onoff) env->me_flags |= flag; else env->me_flags &= ~flag; return MDB_SUCCESS; } int ESECT mdb_env_get_flags(MDB_env *env, unsigned int *arg) { if (!env || !arg) return EINVAL; *arg = env->me_flags; return MDB_SUCCESS; } int ESECT mdb_env_set_userctx(MDB_env *env, void *ctx) { if (!env) return EINVAL; env->me_userctx = ctx; return MDB_SUCCESS; } void * ESECT mdb_env_get_userctx(MDB_env *env) { return env ? env->me_userctx : NULL; } int ESECT mdb_env_set_assert(MDB_env *env, MDB_assert_func *func) { if (!env) return EINVAL; #ifndef NDEBUG env->me_assert_func = func; #endif return MDB_SUCCESS; } int ESECT mdb_env_get_path(MDB_env *env, const char **arg) { if (!env || !arg) return EINVAL; *arg = env->me_path; return MDB_SUCCESS; } int ESECT mdb_env_get_fd(MDB_env *env, mdb_filehandle_t *arg) { if (!env || !arg) return EINVAL; *arg = env->me_fd; return MDB_SUCCESS; } /** Common code for #mdb_stat() and #mdb_env_stat(). * @param[in] env the environment to operate in. * @param[in] db the #MDB_db record containing the stats to return. * @param[out] arg the address of an #MDB_stat structure to receive the stats. * @return 0, this function always succeeds. */ static int ESECT mdb_stat0(MDB_env *env, MDB_db *db, MDB_stat *arg) { arg->ms_psize = env->me_psize; arg->ms_depth = db->md_depth; arg->ms_branch_pages = db->md_branch_pages; arg->ms_leaf_pages = db->md_leaf_pages; arg->ms_overflow_pages = db->md_overflow_pages; arg->ms_entries = db->md_entries; return MDB_SUCCESS; } int ESECT mdb_env_stat(MDB_env *env, MDB_stat *arg) { int toggle; if (env == NULL || arg == NULL) return EINVAL; toggle = mdb_env_pick_meta(env); return mdb_stat0(env, &env->me_metas[toggle]->mm_dbs[MAIN_DBI], arg); } int ESECT mdb_env_info(MDB_env *env, MDB_envinfo *arg) { int toggle; if (env == NULL || arg == NULL) return EINVAL; toggle = mdb_env_pick_meta(env); arg->me_mapaddr = env->me_metas[toggle]->mm_address; arg->me_mapsize = env->me_mapsize; arg->me_maxreaders = env->me_maxreaders; /* me_numreaders may be zero if this process never used any readers. Use * the shared numreader count if it exists. */ arg->me_numreaders = env->me_txns ? env->me_txns->mti_numreaders : env->me_numreaders; arg->me_last_pgno = env->me_metas[toggle]->mm_last_pg; arg->me_last_txnid = env->me_metas[toggle]->mm_txnid; return MDB_SUCCESS; } /** Set the default comparison functions for a database. * Called immediately after a database is opened to set the defaults. * The user can then override them with #mdb_set_compare() or * #mdb_set_dupsort(). * @param[in] txn A transaction handle returned by #mdb_txn_begin() * @param[in] dbi A database handle returned by #mdb_dbi_open() */ static void mdb_default_cmp(MDB_txn *txn, MDB_dbi dbi) { uint16_t f = txn->mt_dbs[dbi].md_flags; txn->mt_dbxs[dbi].md_cmp = (f & MDB_REVERSEKEY) ? mdb_cmp_memnr : (f & MDB_INTEGERKEY) ? mdb_cmp_cint : mdb_cmp_memn; txn->mt_dbxs[dbi].md_dcmp = !(f & MDB_DUPSORT) ? 0 : ((f & MDB_INTEGERDUP) ? ((f & MDB_DUPFIXED) ? mdb_cmp_int : mdb_cmp_cint) : ((f & MDB_REVERSEDUP) ? mdb_cmp_memnr : mdb_cmp_memn)); } int mdb_dbi_open(MDB_txn *txn, const char *name, unsigned int flags, MDB_dbi *dbi) { MDB_val key, data; MDB_dbi i; MDB_cursor mc; MDB_db dummy; int rc, dbflag, exact; unsigned int unused = 0, seq; size_t len; if (txn->mt_dbxs[FREE_DBI].md_cmp == NULL) { mdb_default_cmp(txn, FREE_DBI); } if ((flags & VALID_FLAGS) != flags) return EINVAL; if (txn->mt_flags & MDB_TXN_ERROR) return MDB_BAD_TXN; /* main DB? */ if (!name) { *dbi = MAIN_DBI; if (flags & PERSISTENT_FLAGS) { uint16_t f2 = flags & PERSISTENT_FLAGS; /* make sure flag changes get committed */ if ((txn->mt_dbs[MAIN_DBI].md_flags | f2) != txn->mt_dbs[MAIN_DBI].md_flags) { txn->mt_dbs[MAIN_DBI].md_flags |= f2; txn->mt_flags |= MDB_TXN_DIRTY; } } mdb_default_cmp(txn, MAIN_DBI); return MDB_SUCCESS; } if (txn->mt_dbxs[MAIN_DBI].md_cmp == NULL) { mdb_default_cmp(txn, MAIN_DBI); } /* Is the DB already open? */ len = strlen(name); for (i=2; imt_numdbs; i++) { if (!txn->mt_dbxs[i].md_name.mv_size) { /* Remember this free slot */ if (!unused) unused = i; continue; } if (len == txn->mt_dbxs[i].md_name.mv_size && !strncmp(name, txn->mt_dbxs[i].md_name.mv_data, len)) { *dbi = i; return MDB_SUCCESS; } } /* If no free slot and max hit, fail */ if (!unused && txn->mt_numdbs >= txn->mt_env->me_maxdbs) return MDB_DBS_FULL; /* Cannot mix named databases with some mainDB flags */ if (txn->mt_dbs[MAIN_DBI].md_flags & (MDB_DUPSORT|MDB_INTEGERKEY)) return (flags & MDB_CREATE) ? MDB_INCOMPATIBLE : MDB_NOTFOUND; /* Find the DB info */ dbflag = DB_NEW|DB_VALID; exact = 0; key.mv_size = len; key.mv_data = (void *)name; mdb_cursor_init(&mc, txn, MAIN_DBI, NULL); rc = mdb_cursor_set(&mc, &key, &data, MDB_SET, &exact); if (rc == MDB_SUCCESS) { /* make sure this is actually a DB */ MDB_node *node = NODEPTR(mc.mc_pg[mc.mc_top], mc.mc_ki[mc.mc_top]); if ((node->mn_flags & (F_DUPDATA|F_SUBDATA)) != F_SUBDATA) return MDB_INCOMPATIBLE; } else if (rc == MDB_NOTFOUND && (flags & MDB_CREATE)) { /* Create if requested */ data.mv_size = sizeof(MDB_db); data.mv_data = &dummy; memset(&dummy, 0, sizeof(dummy)); dummy.md_root = P_INVALID; dummy.md_flags = flags & PERSISTENT_FLAGS; rc = mdb_cursor_put(&mc, &key, &data, F_SUBDATA); dbflag |= DB_DIRTY; } /* OK, got info, add to table */ if (rc == MDB_SUCCESS) { unsigned int slot = unused ? unused : txn->mt_numdbs; txn->mt_dbxs[slot].md_name.mv_data = strdup(name); txn->mt_dbxs[slot].md_name.mv_size = len; txn->mt_dbxs[slot].md_rel = NULL; txn->mt_dbflags[slot] = dbflag; /* txn-> and env-> are the same in read txns, use * tmp variable to avoid undefined assignment */ seq = ++txn->mt_env->me_dbiseqs[slot]; txn->mt_dbiseqs[slot] = seq; memcpy(&txn->mt_dbs[slot], data.mv_data, sizeof(MDB_db)); *dbi = slot; mdb_default_cmp(txn, slot); if (!unused) { txn->mt_numdbs++; } } return rc; } int mdb_stat(MDB_txn *txn, MDB_dbi dbi, MDB_stat *arg) { if (!arg || !TXN_DBI_EXIST(txn, dbi)) return EINVAL; if (txn->mt_flags & MDB_TXN_ERROR) return MDB_BAD_TXN; if (txn->mt_dbflags[dbi] & DB_STALE) { MDB_cursor mc; MDB_xcursor mx; /* Stale, must read the DB's root. cursor_init does it for us. */ mdb_cursor_init(&mc, txn, dbi, &mx); } return mdb_stat0(txn->mt_env, &txn->mt_dbs[dbi], arg); } void mdb_dbi_close(MDB_env *env, MDB_dbi dbi) { char *ptr; if (dbi <= MAIN_DBI || dbi >= env->me_maxdbs) return; ptr = env->me_dbxs[dbi].md_name.mv_data; /* If there was no name, this was already closed */ if (ptr) { env->me_dbxs[dbi].md_name.mv_data = NULL; env->me_dbxs[dbi].md_name.mv_size = 0; env->me_dbflags[dbi] = 0; env->me_dbiseqs[dbi]++; free(ptr); } } int mdb_dbi_flags(MDB_txn *txn, MDB_dbi dbi, unsigned int *flags) { /* We could return the flags for the FREE_DBI too but what's the point? */ if (dbi == FREE_DBI || !TXN_DBI_EXIST(txn, dbi)) return EINVAL; *flags = txn->mt_dbs[dbi].md_flags & PERSISTENT_FLAGS; return MDB_SUCCESS; } /** Add all the DB's pages to the free list. * @param[in] mc Cursor on the DB to free. * @param[in] subs non-Zero to check for sub-DBs in this DB. * @return 0 on success, non-zero on failure. */ static int mdb_drop0(MDB_cursor *mc, int subs) { int rc; rc = mdb_page_search(mc, NULL, MDB_PS_FIRST); if (rc == MDB_SUCCESS) { MDB_txn *txn = mc->mc_txn; MDB_node *ni; MDB_cursor mx; unsigned int i; /* LEAF2 pages have no nodes, cannot have sub-DBs */ if (IS_LEAF2(mc->mc_pg[mc->mc_top])) mdb_cursor_pop(mc); mdb_cursor_copy(mc, &mx); while (mc->mc_snum > 0) { MDB_page *mp = mc->mc_pg[mc->mc_top]; unsigned n = NUMKEYS(mp); if (IS_LEAF(mp)) { for (i=0; imn_flags & F_BIGDATA) { MDB_page *omp; pgno_t pg; memcpy(&pg, NODEDATA(ni), sizeof(pg)); rc = mdb_page_get(txn, pg, &omp, NULL); if (rc != 0) goto done; mdb_cassert(mc, IS_OVERFLOW(omp)); rc = mdb_midl_append_range(&txn->mt_free_pgs, pg, omp->mp_pages); if (rc) goto done; } else if (subs && (ni->mn_flags & F_SUBDATA)) { mdb_xcursor_init1(mc, ni); rc = mdb_drop0(&mc->mc_xcursor->mx_cursor, 0); if (rc) goto done; } } } else { if ((rc = mdb_midl_need(&txn->mt_free_pgs, n)) != 0) goto done; for (i=0; imt_free_pgs, pg); } } if (!mc->mc_top) break; mc->mc_ki[mc->mc_top] = i; rc = mdb_cursor_sibling(mc, 1); if (rc) { if (rc != MDB_NOTFOUND) goto done; /* no more siblings, go back to beginning * of previous level. */ mdb_cursor_pop(mc); mc->mc_ki[0] = 0; for (i=1; imc_snum; i++) { mc->mc_ki[i] = 0; mc->mc_pg[i] = mx.mc_pg[i]; } } } /* free it */ rc = mdb_midl_append(&txn->mt_free_pgs, mc->mc_db->md_root); done: if (rc) txn->mt_flags |= MDB_TXN_ERROR; } else if (rc == MDB_NOTFOUND) { rc = MDB_SUCCESS; } return rc; } int mdb_drop(MDB_txn *txn, MDB_dbi dbi, int del) { MDB_cursor *mc, *m2; int rc; if ((unsigned)del > 1 || dbi == FREE_DBI || !TXN_DBI_EXIST(txn, dbi)) return EINVAL; if (F_ISSET(txn->mt_flags, MDB_TXN_RDONLY)) return EACCES; if (dbi > MAIN_DBI && TXN_DBI_CHANGED(txn, dbi)) return MDB_BAD_DBI; rc = mdb_cursor_open(txn, dbi, &mc); if (rc) return rc; rc = mdb_drop0(mc, mc->mc_db->md_flags & MDB_DUPSORT); /* Invalidate the dropped DB's cursors */ for (m2 = txn->mt_cursors[dbi]; m2; m2 = m2->mc_next) m2->mc_flags &= ~(C_INITIALIZED|C_EOF); if (rc) goto leave; /* Can't delete the main DB */ if (del && dbi > MAIN_DBI) { rc = mdb_del0(txn, MAIN_DBI, &mc->mc_dbx->md_name, NULL, F_SUBDATA); if (!rc) { txn->mt_dbflags[dbi] = DB_STALE; mdb_dbi_close(txn->mt_env, dbi); } else { txn->mt_flags |= MDB_TXN_ERROR; } } else { /* reset the DB record, mark it dirty */ txn->mt_dbflags[dbi] |= DB_DIRTY; txn->mt_dbs[dbi].md_depth = 0; txn->mt_dbs[dbi].md_branch_pages = 0; txn->mt_dbs[dbi].md_leaf_pages = 0; txn->mt_dbs[dbi].md_overflow_pages = 0; txn->mt_dbs[dbi].md_entries = 0; txn->mt_dbs[dbi].md_root = P_INVALID; txn->mt_flags |= MDB_TXN_DIRTY; } leave: mdb_cursor_close(mc); return rc; } int mdb_set_compare(MDB_txn *txn, MDB_dbi dbi, MDB_cmp_func *cmp) { if (dbi == FREE_DBI || !TXN_DBI_EXIST(txn, dbi)) return EINVAL; txn->mt_dbxs[dbi].md_cmp = cmp; return MDB_SUCCESS; } int mdb_set_dupsort(MDB_txn *txn, MDB_dbi dbi, MDB_cmp_func *cmp) { if (dbi == FREE_DBI || !TXN_DBI_EXIST(txn, dbi)) return EINVAL; txn->mt_dbxs[dbi].md_dcmp = cmp; return MDB_SUCCESS; } int mdb_set_relfunc(MDB_txn *txn, MDB_dbi dbi, MDB_rel_func *rel) { if (dbi == FREE_DBI || !TXN_DBI_EXIST(txn, dbi)) return EINVAL; txn->mt_dbxs[dbi].md_rel = rel; return MDB_SUCCESS; } int mdb_set_relctx(MDB_txn *txn, MDB_dbi dbi, void *ctx) { if (dbi == FREE_DBI || !TXN_DBI_EXIST(txn, dbi)) return EINVAL; txn->mt_dbxs[dbi].md_relctx = ctx; return MDB_SUCCESS; } int ESECT mdb_env_get_maxkeysize(MDB_env *env) { return ENV_MAXKEY(env); } int ESECT mdb_reader_list(MDB_env *env, MDB_msg_func *func, void *ctx) { unsigned int i, rdrs; MDB_reader *mr; char buf[64]; int rc = 0, first = 1; if (!env || !func) return -1; if (!env->me_txns) { return func("(no reader locks)\n", ctx); } rdrs = env->me_txns->mti_numreaders; mr = env->me_txns->mti_readers; for (i=0; i> 1; cursor = base + pivot + 1; val = pid - ids[cursor]; if( val < 0 ) { n = pivot; } else if ( val > 0 ) { base = cursor; n -= pivot + 1; } else { /* found, so it's a duplicate */ return -1; } } if( val > 0 ) { ++cursor; } ids[0]++; for (n = ids[0]; n > cursor; n--) ids[n] = ids[n-1]; ids[n] = pid; return 0; } int ESECT mdb_reader_check(MDB_env *env, int *dead) { unsigned int i, j, rdrs; MDB_reader *mr; MDB_PID_T *pids, pid; int count = 0; if (!env) return EINVAL; if (dead) *dead = 0; if (!env->me_txns) return MDB_SUCCESS; rdrs = env->me_txns->mti_numreaders; pids = malloc((rdrs+1) * sizeof(MDB_PID_T)); if (!pids) return ENOMEM; pids[0] = 0; mr = env->me_txns->mti_readers; for (i=0; ime_pid) { pid = mr[i].mr_pid; if (mdb_pid_insert(pids, pid) == 0) { if (!mdb_reader_pid(env, Pidcheck, pid)) { LOCK_MUTEX_R(env); /* Recheck, a new process may have reused pid */ if (!mdb_reader_pid(env, Pidcheck, pid)) { for (j=i; j. */ #include #include #include #include #include #include #include #include "lmdb.h" #ifdef _WIN32 #define Z "I" #else #define Z "z" #endif #define PRINT 1 static int mode; typedef struct flagbit { int bit; char *name; } flagbit; flagbit dbflags[] = { { MDB_REVERSEKEY, "reversekey" }, { MDB_DUPSORT, "dupsort" }, { MDB_INTEGERKEY, "integerkey" }, { MDB_DUPFIXED, "dupfixed" }, { MDB_INTEGERDUP, "integerdup" }, { MDB_REVERSEDUP, "reversedup" }, { 0, NULL } }; static volatile sig_atomic_t gotsig; static void dumpsig( int sig ) { gotsig=1; } static const char hexc[] = "0123456789abcdef"; static void hex(unsigned char c) { putchar(hexc[c >> 4]); putchar(hexc[c & 0xf]); } static void text(MDB_val *v) { unsigned char *c, *end; putchar(' '); c = v->mv_data; end = c + v->mv_size; while (c < end) { if (isprint(*c)) { putchar(*c); } else { putchar('\\'); hex(*c); } c++; } putchar('\n'); } static void byte(MDB_val *v) { unsigned char *c, *end; putchar(' '); c = v->mv_data; end = c + v->mv_size; while (c < end) { hex(*c++); } putchar('\n'); } /* Dump in BDB-compatible format */ static int dumpit(MDB_txn *txn, MDB_dbi dbi, char *name) { MDB_cursor *mc; MDB_stat ms; MDB_val key, data; MDB_envinfo info; unsigned int flags; int rc, i; rc = mdb_dbi_flags(txn, dbi, &flags); if (rc) return rc; rc = mdb_stat(txn, dbi, &ms); if (rc) return rc; rc = mdb_env_info(mdb_txn_env(txn), &info); if (rc) return rc; printf("VERSION=3\n"); printf("format=%s\n", mode & PRINT ? "print" : "bytevalue"); if (name) printf("database=%s\n", name); printf("type=btree\n"); printf("mapsize=%" Z "u\n", info.me_mapsize); if (info.me_mapaddr) printf("mapaddr=%p\n", info.me_mapaddr); printf("maxreaders=%u\n", info.me_maxreaders); if (flags & MDB_DUPSORT) printf("duplicates=1\n"); for (i=0; dbflags[i].bit; i++) if (flags & dbflags[i].bit) printf("%s=1\n", dbflags[i].name); printf("db_pagesize=%d\n", ms.ms_psize); printf("HEADER=END\n"); rc = mdb_cursor_open(txn, dbi, &mc); if (rc) return rc; while ((rc = mdb_cursor_get(mc, &key, &data, MDB_NEXT) == MDB_SUCCESS)) { if (gotsig) { rc = EINTR; break; } if (mode & PRINT) { text(&key); text(&data); } else { byte(&key); byte(&data); } } printf("DATA=END\n"); if (rc == MDB_NOTFOUND) rc = MDB_SUCCESS; return rc; } static void usage(char *prog) { fprintf(stderr, "usage: %s dbpath [-V] [-f output] [-l] [-n] [-p] [-a|-s subdb]\n", prog); exit(EXIT_FAILURE); } int main(int argc, char *argv[]) { int i, rc; MDB_env *env; MDB_txn *txn; MDB_dbi dbi; char *prog = argv[0]; char *envname; char *subname = NULL; int alldbs = 0, envflags = 0, list = 0; if (argc < 2) { usage(prog); } /* -a: dump main DB and all subDBs * -s: dump only the named subDB * -n: use NOSUBDIR flag on env_open * -p: use printable characters * -f: write to file instead of stdout * -V: print version and exit * (default) dump only the main DB */ while ((i = getopt(argc, argv, "af:lnps:V")) != EOF) { switch(i) { case 'V': printf("%s\n", MDB_VERSION_STRING); exit(0); break; case 'l': list = 1; /*FALLTHROUGH*/; case 'a': if (subname) usage(prog); alldbs++; break; case 'f': if (freopen(optarg, "w", stdout) == NULL) { fprintf(stderr, "%s: %s: reopen: %s\n", prog, optarg, strerror(errno)); exit(EXIT_FAILURE); } break; case 'n': envflags |= MDB_NOSUBDIR; break; case 'p': mode |= PRINT; break; case 's': if (alldbs) usage(prog); subname = optarg; break; default: usage(prog); } } if (optind != argc - 1) usage(prog); #ifdef SIGPIPE signal(SIGPIPE, dumpsig); #endif #ifdef SIGHUP signal(SIGHUP, dumpsig); #endif signal(SIGINT, dumpsig); signal(SIGTERM, dumpsig); envname = argv[optind]; rc = mdb_env_create(&env); if (rc) { fprintf(stderr, "mdb_env_create failed, error %d %s\n", rc, mdb_strerror(rc)); return EXIT_FAILURE; } if (alldbs || subname) { mdb_env_set_maxdbs(env, 2); } rc = mdb_env_open(env, envname, envflags | MDB_RDONLY, 0664); if (rc) { fprintf(stderr, "mdb_env_open failed, error %d %s\n", rc, mdb_strerror(rc)); goto env_close; } rc = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn); if (rc) { fprintf(stderr, "mdb_txn_begin failed, error %d %s\n", rc, mdb_strerror(rc)); goto env_close; } rc = mdb_open(txn, subname, 0, &dbi); if (rc) { fprintf(stderr, "mdb_open failed, error %d %s\n", rc, mdb_strerror(rc)); goto txn_abort; } if (alldbs) { MDB_cursor *cursor; MDB_val key; int count = 0; rc = mdb_cursor_open(txn, dbi, &cursor); if (rc) { fprintf(stderr, "mdb_cursor_open failed, error %d %s\n", rc, mdb_strerror(rc)); goto txn_abort; } while ((rc = mdb_cursor_get(cursor, &key, NULL, MDB_NEXT_NODUP)) == 0) { char *str; MDB_dbi db2; if (memchr(key.mv_data, '\0', key.mv_size)) continue; count++; str = malloc(key.mv_size+1); memcpy(str, key.mv_data, key.mv_size); str[key.mv_size] = '\0'; rc = mdb_open(txn, str, 0, &db2); if (rc == MDB_SUCCESS) { if (list) { printf("%s\n", str); list++; } else { rc = dumpit(txn, db2, str); if (rc) break; } mdb_close(env, db2); } free(str); if (rc) continue; } mdb_cursor_close(cursor); if (!count) { fprintf(stderr, "%s: %s does not contain multiple databases\n", prog, envname); rc = MDB_NOTFOUND; } else if (rc == MDB_NOTFOUND) { rc = MDB_SUCCESS; } } else { rc = dumpit(txn, dbi, subname); } if (rc && rc != MDB_NOTFOUND) fprintf(stderr, "%s: %s: %s\n", prog, envname, mdb_strerror(rc)); mdb_close(env, dbi); txn_abort: mdb_txn_abort(txn); env_close: mdb_env_close(env); return rc ? EXIT_FAILURE : EXIT_SUCCESS; } openldap-2.4.42+dfsg/libraries/liblmdb/mdb_copy.10000644000175000017500000000267512563404150020301 0ustar ryanryan.TH MDB_COPY 1 "2014/06/20" "LMDB 0.9.14" .\" Copyright 2012-2015 Howard Chu, Symas Corp. All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME mdb_copy \- LMDB environment copy tool .SH SYNOPSIS .B mdb_copy [\c .BR \-V ] [\c .BR \-c ] [\c .BR \-n ] .B srcpath [\c .BR dstpath ] .SH DESCRIPTION The .B mdb_copy utility copies an LMDB environment. The environment can be copied regardless of whether it is currently in use. No lockfile is created, since it gets recreated at need. If .I dstpath is specified it must be the path of an empty directory for storing the backup. Otherwise, the backup will be written to stdout. .SH OPTIONS .TP .BR \-V Write the library version number to the standard output, and exit. .TP .BR \-c Compact while copying. Only current data pages will be copied; freed or unused pages will be omitted from the copy. This option will slow down the backup process as it is more CPU-intensive. .TP .BR \-n Open LDMB environment(s) which do not use subdirectories. .SH DIAGNOSTICS Exit status is zero if no errors occur. Errors result in a non-zero exit status and a diagnostic message being written to standard error. .SH CAVEATS This utility can trigger significant file size growth if run in parallel with write transactions, because pages which they free during copying cannot be reused until the copy is done. .SH "SEE ALSO" .BR mdb_stat (1) .SH AUTHOR Howard Chu of Symas Corporation openldap-2.4.42+dfsg/libraries/liblmdb/mtest.c0000644000175000017500000001266012563404150017716 0ustar ryanryan/* mtest.c - memory-mapped database tester/toy */ /* * Copyright 2011-2015 Howard Chu, Symas Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #include #include #include #include "lmdb.h" #define E(expr) CHECK((rc = (expr)) == MDB_SUCCESS, #expr) #define RES(err, expr) ((rc = expr) == (err) || (CHECK(!rc, #expr), 0)) #define CHECK(test, msg) ((test) ? (void)0 : ((void)fprintf(stderr, \ "%s:%d: %s: %s\n", __FILE__, __LINE__, msg, mdb_strerror(rc)), abort())) int main(int argc,char * argv[]) { int i = 0, j = 0, rc; MDB_env *env; MDB_dbi dbi; MDB_val key, data; MDB_txn *txn; MDB_stat mst; MDB_cursor *cursor, *cur2; MDB_cursor_op op; int count; int *values; char sval[32] = ""; srand(time(NULL)); count = (rand()%384) + 64; values = (int *)malloc(count*sizeof(int)); for(i = 0;i in each iteration, since MDB_NOOVERWRITE may modify it */ data.mv_size = sizeof(sval); data.mv_data = sval; if (RES(MDB_KEYEXIST, mdb_put(txn, dbi, &key, &data, MDB_NOOVERWRITE))) { j++; data.mv_size = sizeof(sval); data.mv_data = sval; } } if (j) printf("%d duplicates skipped\n", j); E(mdb_txn_commit(txn)); E(mdb_env_stat(env, &mst)); E(mdb_txn_begin(env, NULL, MDB_RDONLY, &txn)); E(mdb_cursor_open(txn, dbi, &cursor)); while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) { printf("key: %p %.*s, data: %p %.*s\n", key.mv_data, (int) key.mv_size, (char *) key.mv_data, data.mv_data, (int) data.mv_size, (char *) data.mv_data); } CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get"); mdb_cursor_close(cursor); mdb_txn_abort(txn); j=0; key.mv_data = sval; for (i= count - 1; i > -1; i-= (rand()%5)) { j++; txn=NULL; E(mdb_txn_begin(env, NULL, 0, &txn)); sprintf(sval, "%03x ", values[i]); if (RES(MDB_NOTFOUND, mdb_del(txn, dbi, &key, NULL))) { j--; mdb_txn_abort(txn); } else { E(mdb_txn_commit(txn)); } } free(values); printf("Deleted %d values\n", j); E(mdb_env_stat(env, &mst)); E(mdb_txn_begin(env, NULL, MDB_RDONLY, &txn)); E(mdb_cursor_open(txn, dbi, &cursor)); printf("Cursor next\n"); while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) { printf("key: %.*s, data: %.*s\n", (int) key.mv_size, (char *) key.mv_data, (int) data.mv_size, (char *) data.mv_data); } CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get"); printf("Cursor last\n"); E(mdb_cursor_get(cursor, &key, &data, MDB_LAST)); printf("key: %.*s, data: %.*s\n", (int) key.mv_size, (char *) key.mv_data, (int) data.mv_size, (char *) data.mv_data); printf("Cursor prev\n"); while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_PREV)) == 0) { printf("key: %.*s, data: %.*s\n", (int) key.mv_size, (char *) key.mv_data, (int) data.mv_size, (char *) data.mv_data); } CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get"); printf("Cursor last/prev\n"); E(mdb_cursor_get(cursor, &key, &data, MDB_LAST)); printf("key: %.*s, data: %.*s\n", (int) key.mv_size, (char *) key.mv_data, (int) data.mv_size, (char *) data.mv_data); E(mdb_cursor_get(cursor, &key, &data, MDB_PREV)); printf("key: %.*s, data: %.*s\n", (int) key.mv_size, (char *) key.mv_data, (int) data.mv_size, (char *) data.mv_data); mdb_cursor_close(cursor); mdb_txn_abort(txn); printf("Deleting with cursor\n"); E(mdb_txn_begin(env, NULL, 0, &txn)); E(mdb_cursor_open(txn, dbi, &cur2)); for (i=0; i<50; i++) { if (RES(MDB_NOTFOUND, mdb_cursor_get(cur2, &key, &data, MDB_NEXT))) break; printf("key: %p %.*s, data: %p %.*s\n", key.mv_data, (int) key.mv_size, (char *) key.mv_data, data.mv_data, (int) data.mv_size, (char *) data.mv_data); E(mdb_del(txn, dbi, &key, NULL)); } printf("Restarting cursor in txn\n"); for (op=MDB_FIRST, i=0; i<=32; op=MDB_NEXT, i++) { if (RES(MDB_NOTFOUND, mdb_cursor_get(cur2, &key, &data, op))) break; printf("key: %p %.*s, data: %p %.*s\n", key.mv_data, (int) key.mv_size, (char *) key.mv_data, data.mv_data, (int) data.mv_size, (char *) data.mv_data); } mdb_cursor_close(cur2); E(mdb_txn_commit(txn)); printf("Restarting cursor outside txn\n"); E(mdb_txn_begin(env, NULL, 0, &txn)); E(mdb_cursor_open(txn, dbi, &cursor)); for (op=MDB_FIRST, i=0; i<=32; op=MDB_NEXT, i++) { if (RES(MDB_NOTFOUND, mdb_cursor_get(cursor, &key, &data, op))) break; printf("key: %p %.*s, data: %p %.*s\n", key.mv_data, (int) key.mv_size, (char *) key.mv_data, data.mv_data, (int) data.mv_size, (char *) data.mv_data); } mdb_cursor_close(cursor); mdb_txn_abort(txn); mdb_dbi_close(env, dbi); mdb_env_close(env); return 0; } openldap-2.4.42+dfsg/libraries/liblmdb/sample-mdb.txt0000644000175000017500000000320412563404150021172 0ustar ryanryan/* sample-mdb.txt - MDB toy/sample * * Do a line-by-line comparison of this and sample-bdb.txt */ /* * Copyright 2012-2015 Howard Chu, Symas Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #include #include "lmdb.h" int main(int argc,char * argv[]) { int rc; MDB_env *env; MDB_dbi dbi; MDB_val key, data; MDB_txn *txn; MDB_cursor *cursor; char sval[32]; /* Note: Most error checking omitted for simplicity */ rc = mdb_env_create(&env); rc = mdb_env_open(env, "./testdb", 0, 0664); rc = mdb_txn_begin(env, NULL, 0, &txn); rc = mdb_dbi_open(txn, NULL, 0, &dbi); key.mv_size = sizeof(int); key.mv_data = sval; data.mv_size = sizeof(sval); data.mv_data = sval; sprintf(sval, "%03x %d foo bar", 32, 3141592); rc = mdb_put(txn, dbi, &key, &data, 0); rc = mdb_txn_commit(txn); if (rc) { fprintf(stderr, "mdb_txn_commit: (%d) %s\n", rc, mdb_strerror(rc)); goto leave; } rc = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn); rc = mdb_cursor_open(txn, dbi, &cursor); while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) { printf("key: %p %.*s, data: %p %.*s\n", key.mv_data, (int) key.mv_size, (char *) key.mv_data, data.mv_data, (int) data.mv_size, (char *) data.mv_data); } mdb_cursor_close(cursor); mdb_txn_abort(txn); leave: mdb_dbi_close(env, dbi); mdb_env_close(env); return 0; } openldap-2.4.42+dfsg/libraries/liblmdb/Doxyfile0000644000175000017500000020461412563404150020126 0ustar ryanryan# Doxyfile 1.7.1 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # http://www.gnu.org/software/libiconv for the list of possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = LMDB # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, # Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English # messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, # Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, # Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = YES # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) JAVADOC_AUTOBRIEF = NO # If the QT_AUTOBRIEF tag is set to YES then Doxygen will # interpret the first line (until the first dot) of a Qt-style # comment as the brief description. If set to NO, the comments # will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 4 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = YES # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for # Java. For instance, namespaces will be presented as packages, qualified # scopes will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources only. Doxygen will then generate output that is more tailored for # Fortran. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for # VHDL. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given extension. # Doxygen has a built-in mapping, but you can override or extend it using this # tag. The format is ext=language, where ext is a file extension, and language # is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, # C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make # doxygen treat .inc files as Fortran files (default is PHP), and .f files as C # (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions # you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. EXTENSION_MAPPING = # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. # Doxygen will parse them like normal C++ but will assume all classes use public # instead of private inheritance when no explicit protection keyword is present. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate getter # and setter methods for a property. Setting this option to YES (the default) # will make doxygen to replace the get and set methods by a property in the # documentation. This will only work if the methods are indeed getting or # setting a simple type. If this is not the case, or you want to show the # methods anyway, you should set this option to NO. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES INLINE_GROUPED_CLASSES = YES # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum # is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically # be useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. TYPEDEF_HIDES_STRUCT = YES # The SYMBOL_CACHE_SIZE determines the size of the internal cache use to # determine which symbols to keep in memory and which to flush to disk. # When the cache is full, less often used symbols will be written to disk. # For small to medium size projects (<1000 input files) the default value is # probably good enough. For larger projects a too small cache size can cause # doxygen to be busy swapping symbols to and from disk most of the time # causing a significant performance penality. # If the system has enough physical memory increasing the cache will improve the # performance by keeping more symbols in memory. Note that the value works on # a logarithmic scale so increasing the size by one will rougly double the # memory usage. The cache size is given by this formula: # 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols SYMBOL_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base # name of the file that contains the anonymous namespace. By default # anonymous namespace are hidden. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen # will list include files with double quotes in the documentation # rather than with sharp brackets. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = NO # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen # will sort the (brief and detailed) documentation of class members so that # constructors and destructors are listed first. If set to NO (the default) # the constructors will appear in the respective orders defined by # SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. # This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO # and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the # hierarchy of group names into alphabetical order. If set to NO (the default) # the group names will appear in their defined order. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # If the sources in your project are distributed over multiple directories # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. The default is NO. SHOW_DIRECTORIES = NO # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the # Folder Tree View (if specified). The default is YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the # Namespaces page. # This will remove the Namespaces entry from the Quick Index # and from the Folder Tree View (if specified). The default is YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. The create the layout file # that represents doxygen's defaults, run doxygen with the -l option. # You can optionally specify a file name after the option, if omitted # DoxygenLayout.xml will be used as the name of the layout file. LAYOUT_FILE = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be abled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = lmdb.h midl.h mdb.c midl.c # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # also the default input encoding. Doxygen uses libiconv (or the iconv built # into libc) for the transcoding. See http://www.gnu.org/software/libiconv for # the list of possible encodings. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx # *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 FILE_PATTERNS = # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used select whether or not files or # directories that are symbolic links (a Unix filesystem feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. # If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. # Doxygen will compare the file name with each pattern and apply the # filter if there is a match. # The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER # is applied to all files. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = NO # If the REFERENCES_RELATION tag is set to YES # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = NO # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will # link to the source code. # Otherwise they will link to the documentation. REFERENCES_LINK_SOURCE = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = YES # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. # Doxygen will adjust the colors in the stylesheet and background images # according to this color. Hue is specified as an angle on a colorwheel, # see http://en.wikipedia.org/wiki/Hue for more information. # For instance the value 0 represents red, 60 is yellow, 120 is green, # 180 is cyan, 240 is blue, 300 purple, and 360 is red again. # The allowed range is 0 to 359. HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of # the colors in the HTML output. For a value of 0 the output will use # grayscales only. A value of 255 will produce the most vivid colors. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to # the luminance component of the colors in the HTML output. Values below # 100 gradually make the output lighter, whereas values above 100 make # the output darker. The value divided by 100 is the actual gamma applied, # so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, # and 100 does not change the gamma. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting # this to NO can help when comparing the output of multiple runs. HTML_TIMESTAMP = YES # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. For this to work a browser that supports # JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox # Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). HTML_DYNAMIC_SECTIONS = NO # If the GENERATE_DOCSET tag is set to YES, additional index files # will be generated that can be used as input for Apple's Xcode 3 # integrated development environment, introduced with OSX 10.5 (Leopard). # To create a documentation set, doxygen will generate a Makefile in the # HTML output directory. Running make will produce the docset in that # directory and running "make install" will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find # it at startup. # See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. GENERATE_DOCSET = NO # When GENERATE_DOCSET tag is set to YES, this tag determines the name of the # feed. A documentation feed provides an umbrella under which multiple # documentation sets from a single provider (such as a company or product suite) # can be grouped. DOCSET_FEEDNAME = "Doxygen generated docs" # When GENERATE_DOCSET tag is set to YES, this tag specifies a string that # should uniquely identify the documentation set bundle. This should be a # reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen # will append .docset to the name. DOCSET_BUNDLE_ID = org.doxygen.Project # When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compiled HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING # is used to encode HtmlHelp index (hhk), content (hhc) and project file # content. CHM_INDEX_ENCODING = # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated # that can be used as input for Qt's qhelpgenerator to generate a # Qt Compressed Help (.qch) of the generated HTML documentation. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can # be used to specify the file name of the resulting .qch file. # The path specified is relative to the HTML output folder. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#namespace QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#virtual-folders QHP_VIRTUAL_FOLDER = doc # If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to # add. For more information please see # http://doc.trolltech.com/qthelpproject.html#custom-filters QHP_CUST_FILTER_NAME = # The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see # # Qt Help Project / Custom Filters. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's # filter section matches. # # Qt Help Project / Filter Attributes. QHP_SECT_FILTER_ATTRS = # If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can # be used to specify the location of Qt's qhelpgenerator. # If non-empty doxygen will try to run qhelpgenerator on the generated # .qhp file. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files # will be generated, which together with the HTML files, form an Eclipse help # plugin. To install this plugin and make it available under the help contents # menu in Eclipse, the contents of the directory containing the HTML and XML # files needs to be copied into the plugins directory of eclipse. The name of # the directory within the plugins directory should be the same as # the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before # the help appears. GENERATE_ECLIPSEHELP = NO # A unique identifier for the eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have # this name. ECLIPSE_DOC_ID = org.doxygen.Project # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. # If the tag value is set to YES, a side panel will be generated # containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). # Windows users are probably better off using the HTML help feature. GENERATE_TREEVIEW = NO # By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, # and Class Hierarchy pages using a tree view instead of an ordered list. USE_INLINE_TREES = NO # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 # When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open # links to external symbols imported via tag files in a separate window. EXT_LINKS_IN_WINDOW = NO # Use this tag to change the font size of Latex formulas included # as images in the HTML documentation. The default is 10. Note that # when you change the font size after a successful doxygen run you need # to manually remove any form_*.png images from the HTML output directory # to force them to be regenerated. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are # not supported properly for IE 6.0, but are supported on all modern browsers. # Note that when changing this option you need to delete any form_*.png files # in the HTML output before the changes have effect. FORMULA_TRANSPARENT = YES # When the SEARCHENGINE tag is enabled doxygen will generate a search box # for the HTML output. The underlying search engine uses javascript # and DHTML and should work on any modern browser. Note that when using # HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets # (GENERATE_DOCSET) there is already a search function so this one should # typically be disabled. For large projects the javascript based search engine # can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. SEARCHENGINE = YES # When the SERVER_BASED_SEARCH tag is enabled the search engine will be # implemented using a PHP enabled web server instead of at the web client # using Javascript. Doxygen will generate the search PHP script and index # file to put on the web server. The advantage of the server # based approach is that it scales better to large projects and allows # full text search. The disadvances is that it is more difficult to setup # and does not have live searching capabilities. SERVER_BASED_SEARCH = NO #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. # Note that when enabling USE_PDFLATEX this option is only used for # generating bitmaps for formulas in the HTML output, but not in the # Makefile that is written to the output directory. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = YES # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = YES # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO # If LATEX_SOURCE_CODE is set to YES then doxygen will include # source code with syntax highlighting in the LaTeX output. # Note that which sources are shown also depends on other settings # such as SOURCE_BROWSER. LATEX_SOURCE_CODE = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = YES # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. # This is useful # if you want to understand what is going on. # On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = DEBUG=2 __GNUC__=1 # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse # the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = tooltag=./man1 # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option is superseded by the HAVE_DOT option below. This is only a # fallback. It is recommended to install and use dot, since it yields more # powerful graphs. CLASS_DIAGRAMS = YES # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see # http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the # documentation. The MSCGEN_PATH tag allows you to specify the directory where # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. MSCGEN_PATH = # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = NO # The DOT_NUM_THREADS specifies the number of dot invocations doxygen is # allowed to run in parallel. When set to 0 (the default) doxygen will # base this on the number of processors available in the system. You can set it # explicitly to a value larger than 0 to get control over the balance # between CPU load and processing speed. DOT_NUM_THREADS = 0 # By default doxygen will write a font called FreeSans.ttf to the output # directory and reference it in all dot files that doxygen generates. This # font does not include all possible unicode characters however, so when you need # these (or just want a differently looking font) you can specify the font name # using DOT_FONTNAME. You need need to make sure dot is able to find the font, # which can be done by putting it in a standard location or by setting the # DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory # containing the font. DOT_FONTNAME = FreeSans.ttf # The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. # The default size is 10pt. DOT_FONTSIZE = 10 # By default doxygen will tell dot to use the output directory to look for the # FreeSans.ttf font (which doxygen will put there itself). If you specify a # different font using DOT_FONTNAME you can set the path where dot # can find it using this tag. DOT_FONTPATH = # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT options are set to YES then # doxygen will generate a call dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable call graphs # for selected functions only using the \callgraph command. CALL_GRAPH = NO # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then # doxygen will generate a caller dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable caller # graphs for selected functions only using the \callergraph command. CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen if the # number of direct children of the root node in a graph is already larger than # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 50 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, because dot on Windows does not # seem to support this out of the box. Warning: Depending on the platform used, # enabling this option may lead to badly anti-aliased labels on the edges of # a graph (i.e. they become hard to read). DOT_TRANSPARENT = NO # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = YES # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES openldap-2.4.42+dfsg/libraries/liblmdb/CHANGES0000644000175000017500000001165012563404150017407 0ustar ryanryanLMDB 0.9 Change Log LMDB 0.9.16 Release (2015/08/14) Fix cursor EOF bug (ITS#8190) Fix handling of subDB records (ITS#8181) Fix mdb_midl_shrink() usage (ITS#8200) LMDB 0.9.15 Release (2015/06/19) Fix txn init (ITS#7961,#7987) Fix MDB_PREV_DUP (ITS#7955,#7671) Fix compact of empty env (ITS#7956) Fix mdb_copy file mode Fix mdb_env_close() after failed mdb_env_open() Fix mdb_rebalance collapsing root (ITS#8062) Fix mdb_load with large values (ITS#8066) Fix to retry writes on EINTR (ITS#8106) Fix mdb_cursor_del on empty DB (ITS#8109) Fix MDB_INTEGERDUP key compare (ITS#8117) Fix error handling (ITS#7959,#8157,etc.) Fix race conditions (ITS#7969,7970) Added workaround for fdatasync bug in ext3fs Build Don't use -fPIC for static lib Update .gitignore (ITS#7952,#7953) Cleanup for "make test" (ITS#7841), "make clean", mtest*.c Misc. Android/Windows cleanup Documentation Fix MDB_APPEND doc Fix MDB_MAXKEYSIZE doc (ITS#8156) Fix mdb_cursor_put,mdb_cursor_del EACCES description Fix mdb_env_sync(MDB_RDONLY env) doc (ITS#8021) Clarify MDB_WRITEMAP doc (ITS#8021) Clarify mdb_env_open doc Clarify mdb_dbi_open doc LMDB 0.9.14 Release (2014/09/20) Fix to support 64K page size (ITS#7713) Fix to persist decreased as well as increased mapsizes (ITS#7789) Fix cursor bug when deleting last node of a DUPSORT key Fix mdb_env_info to return FIXEDMAP address Fix ambiguous error code from writing to closed DBI (ITS#7825) Fix mdb_copy copying past end of file (ITS#7886) Fix cursor bugs from page_merge/rebalance Fix to dirty fewer pages in deletes (mdb_page_loose()) Fix mdb_dbi_open creating subDBs (ITS#7917) Fix mdb_cursor_get(_DUP) with single value (ITS#7913) Fix Windows compat issues in mtests (ITS#7879) Add compacting variant of mdb_copy Add BigEndian integer key compare code Add mdb_dump/mdb_load utilities LMDB 0.9.13 Release (2014/06/18) Fix mdb_page_alloc unlimited overflow page search Documentation Re-fix MDB_CURRENT doc (ITS#7793) Fix MDB_GET_MULTIPLE/MDB_NEXT_MULTIPLE doc LMDB 0.9.12 Release (2014/06/13) Fix MDB_GET_BOTH regression (ITS#7875,#7681) Fix MDB_MULTIPLE writing multiple keys (ITS#7834) Fix mdb_rebalance (ITS#7829) Fix mdb_page_split (ITS#7815) Fix md_entries count (ITS#7861,#7828,#7793) Fix MDB_CURRENT (ITS#7793) Fix possible crash on Windows DLL detach Misc code cleanup Documentation mdb_cursor_put: cursor moves on error (ITS#7771) LMDB 0.9.11 Release (2014/01/15) Add mdb_env_set_assert() (ITS#7775) Fix: invalidate txn on page allocation errors (ITS#7377) Fix xcursor tracking in mdb_cursor_del0() (ITS#7771) Fix corruption from deletes (ITS#7756) Fix Windows/MSVC build issues Raise safe limit of max MDB_MAXKEYSIZE Misc code cleanup Documentation Remove spurious note about non-overlapping flags (ITS#7665) LMDB 0.9.10 Release (2013/11/12) Add MDB_NOMEMINIT option Fix mdb_page_split() again (ITS#7589) Fix MDB_NORDAHEAD definition (ITS#7734) Fix mdb_cursor_del() positioning (ITS#7733) Partial fix for larger page sizes (ITS#7713) Fix Windows64/MSVC build issues LMDB 0.9.9 Release (2013/10/24) Add mdb_env_get_fd() Add MDB_NORDAHEAD option Add MDB_NOLOCK option Avoid wasting space in mdb_page_split() (ITS#7589) Fix mdb_page_merge() cursor fixup (ITS#7722) Fix mdb_cursor_del() on last delete (ITS#7718) Fix adding WRITEMAP on existing env (ITS#7715) Fix nested txns (ITS#7515) Fix mdb_env_copy() O_DIRECT bug (ITS#7682) Fix mdb_cursor_set(SET_RANGE) return code (ITS#7681) Fix mdb_rebalance() cursor fixup (ITS#7701) Misc code cleanup Documentation Note that by default, readers need write access LMDB 0.9.8 Release (2013/09/09) Allow mdb_env_set_mapsize() on an open environment Fix mdb_dbi_flags() (ITS#7672) Fix mdb_page_unspill() in nested txns Fix mdb_cursor_get(CURRENT|NEXT) after a delete Fix mdb_cursor_get(DUP) to always return key (ITS#7671) Fix mdb_cursor_del() to always advance to next item (ITS#7670) Fix mdb_cursor_set(SET_RANGE) for tree with single page (ITS#7681) Fix mdb_env_copy() retry open if O_DIRECT fails (ITS#7682) Tweak mdb_page_spill() to be less aggressive Documentation Update caveats since mdb_reader_check() added in 0.9.7 LMDB 0.9.7 Release (2013/08/17) Don't leave stale lockfile on failed RDONLY open (ITS#7664) Fix mdb_page_split() ref beyond cursor depth Fix read txn data race (ITS#7635) Fix mdb_rebalance (ITS#7536, #7538) Fix mdb_drop() (ITS#7561) Misc DEBUG macro fixes Add MDB_NOTLS envflag Add mdb_env_copyfd() Add mdb_txn_env() (ITS#7660) Add mdb_dbi_flags() (ITS#7661) Add mdb_env_get_maxkeysize() Add mdb_env_reader_list()/mdb_env_reader_check() Add mdb_page_spill/unspill, remove hard txn size limit Use shorter names for semaphores (ITS#7615) Build Fix install target (ITS#7656) Documentation Misc updates for cursors, DB handles, data lifetime LMDB 0.9.6 Release (2013/02/25) Many fixes/enhancements LMDB 0.9.5 Release (2012/11/30) Renamed from libmdb to liblmdb Many fixes/enhancements openldap-2.4.42+dfsg/libraries/liblmdb/Makefile0000644000175000017500000000566412563404150020064 0ustar ryanryan# Makefile for liblmdb (Lightning memory-mapped database library). ######################################################################## # Configuration. The compiler options must enable threaded compilation. # # Preprocessor macros (for CPPFLAGS) of interest... # Note that the defaults should already be correct for most # platforms; you should not need to change any of these. # Read their descriptions in mdb.c if you do: # # - MDB_USE_POSIX_SEM # - MDB_DSYNC # - MDB_FDATASYNC # - MDB_FDATASYNC_WORKS # - MDB_USE_PWRITEV # # There may be other macros in mdb.c of interest. You should # read mdb.c before changing any of them. # CC = gcc W = -W -Wall -Wno-unused-parameter -Wbad-function-cast -Wuninitialized THREADS = -pthread OPT = -O2 -g CFLAGS = $(THREADS) $(OPT) $(W) $(XCFLAGS) LDLIBS = SOLIBS = prefix = /usr/local ######################################################################## IHDRS = lmdb.h ILIBS = liblmdb.a liblmdb.so IPROGS = mdb_stat mdb_copy mdb_dump mdb_load IDOCS = mdb_stat.1 mdb_copy.1 mdb_dump.1 mdb_load.1 PROGS = $(IPROGS) mtest mtest2 mtest3 mtest4 mtest5 all: $(ILIBS) $(PROGS) install: $(ILIBS) $(IPROGS) $(IHDRS) for f in $(IPROGS); do cp $$f $(DESTDIR)$(prefix)/bin; done for f in $(ILIBS); do cp $$f $(DESTDIR)$(prefix)/lib; done for f in $(IHDRS); do cp $$f $(DESTDIR)$(prefix)/include; done for f in $(IDOCS); do cp $$f $(DESTDIR)$(prefix)/man/man1; done clean: rm -rf $(PROGS) *.[ao] *.[ls]o *~ testdb test: all rm -rf testdb && mkdir testdb ./mtest && ./mdb_stat testdb liblmdb.a: mdb.o midl.o ar rs $@ mdb.o midl.o liblmdb.so: mdb.lo midl.lo # $(CC) $(LDFLAGS) -pthread -shared -Wl,-Bsymbolic -o $@ mdb.o midl.o $(SOLIBS) $(CC) $(LDFLAGS) -pthread -shared -o $@ mdb.lo midl.lo $(SOLIBS) mdb_stat: mdb_stat.o liblmdb.a mdb_copy: mdb_copy.o liblmdb.a mdb_dump: mdb_dump.o liblmdb.a mdb_load: mdb_load.o liblmdb.a mtest: mtest.o liblmdb.a mtest2: mtest2.o liblmdb.a mtest3: mtest3.o liblmdb.a mtest4: mtest4.o liblmdb.a mtest5: mtest5.o liblmdb.a mtest6: mtest6.o liblmdb.a mdb.o: mdb.c lmdb.h midl.h $(CC) $(CFLAGS) $(CPPFLAGS) -c mdb.c midl.o: midl.c midl.h $(CC) $(CFLAGS) $(CPPFLAGS) -c midl.c mdb.lo: mdb.c lmdb.h midl.h $(CC) $(CFLAGS) -fPIC $(CPPFLAGS) -c mdb.c -o $@ midl.lo: midl.c midl.h $(CC) $(CFLAGS) -fPIC $(CPPFLAGS) -c midl.c -o $@ %: %.o $(CC) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $@ %.o: %.c lmdb.h $(CC) $(CFLAGS) $(CPPFLAGS) -c $< COV_FLAGS=-fprofile-arcs -ftest-coverage COV_OBJS=xmdb.o xmidl.o coverage: xmtest for i in mtest*.c [0-9]*.c; do j=`basename \$$i .c`; $(MAKE) $$j.o; \ gcc -o x$$j $$j.o $(COV_OBJS) -pthread $(COV_FLAGS); \ rm -rf testdb; mkdir testdb; ./x$$j; done gcov xmdb.c gcov xmidl.c xmtest: mtest.o xmdb.o xmidl.o gcc -o xmtest mtest.o xmdb.o xmidl.o -pthread $(COV_FLAGS) xmdb.o: mdb.c lmdb.h midl.h $(CC) $(CFLAGS) -fPIC $(CPPFLAGS) -O0 $(COV_FLAGS) -c mdb.c -o $@ xmidl.o: midl.c midl.h $(CC) $(CFLAGS) -fPIC $(CPPFLAGS) -O0 $(COV_FLAGS) -c midl.c -o $@ openldap-2.4.42+dfsg/libraries/liblmdb/mtest6.c0000644000175000017500000000756112563404150020010 0ustar ryanryan/* mtest6.c - memory-mapped database tester/toy */ /* * Copyright 2011-2015 Howard Chu, Symas Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Tests for DB splits and merges */ #include #include #include #include #include "lmdb.h" #define E(expr) CHECK((rc = (expr)) == MDB_SUCCESS, #expr) #define RES(err, expr) ((rc = expr) == (err) || (CHECK(!rc, #expr), 0)) #define CHECK(test, msg) ((test) ? (void)0 : ((void)fprintf(stderr, \ "%s:%d: %s: %s\n", __FILE__, __LINE__, msg, mdb_strerror(rc)), abort())) char dkbuf[1024]; int main(int argc,char * argv[]) { int i = 0, j = 0, rc; MDB_env *env; MDB_dbi dbi; MDB_val key, data, sdata; MDB_txn *txn; MDB_stat mst; MDB_cursor *cursor; int count; int *values; long kval; char *sval; srand(time(NULL)); E(mdb_env_create(&env)); E(mdb_env_set_mapsize(env, 10485760)); E(mdb_env_set_maxdbs(env, 4)); E(mdb_env_open(env, "./testdb", MDB_FIXEDMAP|MDB_NOSYNC, 0664)); E(mdb_txn_begin(env, NULL, 0, &txn)); E(mdb_dbi_open(txn, "id6", MDB_CREATE|MDB_INTEGERKEY, &dbi)); E(mdb_cursor_open(txn, dbi, &cursor)); E(mdb_stat(txn, dbi, &mst)); sval = calloc(1, mst.ms_psize / 4); key.mv_size = sizeof(long); key.mv_data = &kval; sdata.mv_size = mst.ms_psize / 4 - 30; sdata.mv_data = sval; printf("Adding 12 values, should yield 3 splits\n"); for (i=0;i<12;i++) { kval = i*5; sprintf(sval, "%08x", kval); data = sdata; (void)RES(MDB_KEYEXIST, mdb_cursor_put(cursor, &key, &data, MDB_NOOVERWRITE)); } printf("Adding 12 more values, should yield 3 splits\n"); for (i=0;i<12;i++) { kval = i*5+4; sprintf(sval, "%08x", kval); data = sdata; (void)RES(MDB_KEYEXIST, mdb_cursor_put(cursor, &key, &data, MDB_NOOVERWRITE)); } printf("Adding 12 more values, should yield 3 splits\n"); for (i=0;i<12;i++) { kval = i*5+1; sprintf(sval, "%08x", kval); data = sdata; (void)RES(MDB_KEYEXIST, mdb_cursor_put(cursor, &key, &data, MDB_NOOVERWRITE)); } E(mdb_cursor_get(cursor, &key, &data, MDB_FIRST)); do { printf("key: %p %s, data: %p %.*s\n", key.mv_data, mdb_dkey(&key, dkbuf), data.mv_data, (int) data.mv_size, (char *) data.mv_data); } while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0); CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get"); mdb_cursor_close(cursor); mdb_txn_commit(txn); #if 0 j=0; for (i= count - 1; i > -1; i-= (rand()%5)) { j++; txn=NULL; E(mdb_txn_begin(env, NULL, 0, &txn)); sprintf(kval, "%03x", values[i & ~0x0f]); sprintf(sval, "%03x %d foo bar", values[i], values[i]); key.mv_size = sizeof(int); key.mv_data = kval; data.mv_size = sizeof(sval); data.mv_data = sval; if (RES(MDB_NOTFOUND, mdb_del(txn, dbi, &key, &data))) { j--; mdb_txn_abort(txn); } else { E(mdb_txn_commit(txn)); } } free(values); printf("Deleted %d values\n", j); E(mdb_env_stat(env, &mst)); E(mdb_txn_begin(env, NULL, MDB_RDONLY, &txn)); E(mdb_cursor_open(txn, dbi, &cursor)); printf("Cursor next\n"); while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) { printf("key: %.*s, data: %.*s\n", (int) key.mv_size, (char *) key.mv_data, (int) data.mv_size, (char *) data.mv_data); } CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get"); printf("Cursor prev\n"); while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_PREV)) == 0) { printf("key: %.*s, data: %.*s\n", (int) key.mv_size, (char *) key.mv_data, (int) data.mv_size, (char *) data.mv_data); } CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get"); mdb_cursor_close(cursor); mdb_txn_abort(txn); mdb_dbi_close(env, dbi); #endif mdb_env_close(env); return 0; } openldap-2.4.42+dfsg/libraries/liblmdb/mtest3.c0000644000175000017500000000717012563404150020001 0ustar ryanryan/* mtest3.c - memory-mapped database tester/toy */ /* * Copyright 2011-2015 Howard Chu, Symas Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Tests for sorted duplicate DBs */ #include #include #include #include #include "lmdb.h" #define E(expr) CHECK((rc = (expr)) == MDB_SUCCESS, #expr) #define RES(err, expr) ((rc = expr) == (err) || (CHECK(!rc, #expr), 0)) #define CHECK(test, msg) ((test) ? (void)0 : ((void)fprintf(stderr, \ "%s:%d: %s: %s\n", __FILE__, __LINE__, msg, mdb_strerror(rc)), abort())) int main(int argc,char * argv[]) { int i = 0, j = 0, rc; MDB_env *env; MDB_dbi dbi; MDB_val key, data; MDB_txn *txn; MDB_stat mst; MDB_cursor *cursor; int count; int *values; char sval[32]; char kval[sizeof(int)]; srand(time(NULL)); memset(sval, 0, sizeof(sval)); count = (rand()%384) + 64; values = (int *)malloc(count*sizeof(int)); for(i = 0;i -1; i-= (rand()%5)) { j++; txn=NULL; E(mdb_txn_begin(env, NULL, 0, &txn)); sprintf(kval, "%03x", values[i & ~0x0f]); sprintf(sval, "%03x %d foo bar", values[i], values[i]); key.mv_size = sizeof(int); key.mv_data = kval; data.mv_size = sizeof(sval); data.mv_data = sval; if (RES(MDB_NOTFOUND, mdb_del(txn, dbi, &key, &data))) { j--; mdb_txn_abort(txn); } else { E(mdb_txn_commit(txn)); } } free(values); printf("Deleted %d values\n", j); E(mdb_env_stat(env, &mst)); E(mdb_txn_begin(env, NULL, MDB_RDONLY, &txn)); E(mdb_cursor_open(txn, dbi, &cursor)); printf("Cursor next\n"); while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) { printf("key: %.*s, data: %.*s\n", (int) key.mv_size, (char *) key.mv_data, (int) data.mv_size, (char *) data.mv_data); } CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get"); printf("Cursor prev\n"); while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_PREV)) == 0) { printf("key: %.*s, data: %.*s\n", (int) key.mv_size, (char *) key.mv_data, (int) data.mv_size, (char *) data.mv_data); } CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get"); mdb_cursor_close(cursor); mdb_txn_abort(txn); mdb_dbi_close(env, dbi); mdb_env_close(env); return 0; } openldap-2.4.42+dfsg/libraries/liblmdb/mtest5.c0000644000175000017500000000732112563404150020001 0ustar ryanryan/* mtest5.c - memory-mapped database tester/toy */ /* * Copyright 2011-2015 Howard Chu, Symas Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Tests for sorted duplicate DBs using cursor_put */ #include #include #include #include #include "lmdb.h" #define E(expr) CHECK((rc = (expr)) == MDB_SUCCESS, #expr) #define RES(err, expr) ((rc = expr) == (err) || (CHECK(!rc, #expr), 0)) #define CHECK(test, msg) ((test) ? (void)0 : ((void)fprintf(stderr, \ "%s:%d: %s: %s\n", __FILE__, __LINE__, msg, mdb_strerror(rc)), abort())) int main(int argc,char * argv[]) { int i = 0, j = 0, rc; MDB_env *env; MDB_dbi dbi; MDB_val key, data; MDB_txn *txn; MDB_stat mst; MDB_cursor *cursor; int count; int *values; char sval[32]; char kval[sizeof(int)]; srand(time(NULL)); memset(sval, 0, sizeof(sval)); count = (rand()%384) + 64; values = (int *)malloc(count*sizeof(int)); for(i = 0;i -1; i-= (rand()%5)) { j++; txn=NULL; E(mdb_txn_begin(env, NULL, 0, &txn)); sprintf(kval, "%03x", values[i & ~0x0f]); sprintf(sval, "%03x %d foo bar", values[i], values[i]); key.mv_size = sizeof(int); key.mv_data = kval; data.mv_size = sizeof(sval); data.mv_data = sval; if (RES(MDB_NOTFOUND, mdb_del(txn, dbi, &key, &data))) { j--; mdb_txn_abort(txn); } else { E(mdb_txn_commit(txn)); } } free(values); printf("Deleted %d values\n", j); E(mdb_env_stat(env, &mst)); E(mdb_txn_begin(env, NULL, MDB_RDONLY, &txn)); E(mdb_cursor_open(txn, dbi, &cursor)); printf("Cursor next\n"); while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) { printf("key: %.*s, data: %.*s\n", (int) key.mv_size, (char *) key.mv_data, (int) data.mv_size, (char *) data.mv_data); } CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get"); printf("Cursor prev\n"); while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_PREV)) == 0) { printf("key: %.*s, data: %.*s\n", (int) key.mv_size, (char *) key.mv_data, (int) data.mv_size, (char *) data.mv_data); } CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get"); mdb_cursor_close(cursor); mdb_txn_abort(txn); mdb_dbi_close(env, dbi); mdb_env_close(env); return 0; } openldap-2.4.42+dfsg/libraries/liblmdb/mdb_copy.c0000644000175000017500000000364212563404150020356 0ustar ryanryan/* mdb_copy.c - memory-mapped database backup tool */ /* * Copyright 2012-2015 Howard Chu, Symas Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #ifdef _WIN32 #include #define MDB_STDOUT GetStdHandle(STD_OUTPUT_HANDLE) #else #define MDB_STDOUT 1 #endif #include #include #include #include "lmdb.h" static void sighandle(int sig) { } int main(int argc,char * argv[]) { int rc; MDB_env *env; const char *progname = argv[0], *act; unsigned flags = MDB_RDONLY; unsigned cpflags = 0; for (; argc > 1 && argv[1][0] == '-'; argc--, argv++) { if (argv[1][1] == 'n' && argv[1][2] == '\0') flags |= MDB_NOSUBDIR; else if (argv[1][1] == 'c' && argv[1][2] == '\0') cpflags |= MDB_CP_COMPACT; else if (argv[1][1] == 'V' && argv[1][2] == '\0') { printf("%s\n", MDB_VERSION_STRING); exit(0); } else argc = 0; } if (argc<2 || argc>3) { fprintf(stderr, "usage: %s [-V] [-c] [-n] srcpath [dstpath]\n", progname); exit(EXIT_FAILURE); } #ifdef SIGPIPE signal(SIGPIPE, sighandle); #endif #ifdef SIGHUP signal(SIGHUP, sighandle); #endif signal(SIGINT, sighandle); signal(SIGTERM, sighandle); act = "opening environment"; rc = mdb_env_create(&env); if (rc == MDB_SUCCESS) { rc = mdb_env_open(env, argv[1], flags, 0600); } if (rc == MDB_SUCCESS) { act = "copying"; if (argc == 2) rc = mdb_env_copyfd2(env, MDB_STDOUT, cpflags); else rc = mdb_env_copy2(env, argv[2], cpflags); } if (rc) fprintf(stderr, "%s: %s failed, error %d (%s)\n", progname, act, rc, mdb_strerror(rc)); mdb_env_close(env); return rc ? EXIT_FAILURE : EXIT_SUCCESS; } openldap-2.4.42+dfsg/libraries/liblmdb/lmdb.h0000644000175000017500000021416512563404150017511 0ustar ryanryan/** @file lmdb.h * @brief Lightning memory-mapped database library * * @mainpage Lightning Memory-Mapped Database Manager (LMDB) * * @section intro_sec Introduction * LMDB is a Btree-based database management library modeled loosely on the * BerkeleyDB API, but much simplified. The entire database is exposed * in a memory map, and all data fetches return data directly * from the mapped memory, so no malloc's or memcpy's occur during * data fetches. As such, the library is extremely simple because it * requires no page caching layer of its own, and it is extremely high * performance and memory-efficient. It is also fully transactional with * full ACID semantics, and when the memory map is read-only, the * database integrity cannot be corrupted by stray pointer writes from * application code. * * The library is fully thread-aware and supports concurrent read/write * access from multiple processes and threads. Data pages use a copy-on- * write strategy so no active data pages are ever overwritten, which * also provides resistance to corruption and eliminates the need of any * special recovery procedures after a system crash. Writes are fully * serialized; only one write transaction may be active at a time, which * guarantees that writers can never deadlock. The database structure is * multi-versioned so readers run with no locks; writers cannot block * readers, and readers don't block writers. * * Unlike other well-known database mechanisms which use either write-ahead * transaction logs or append-only data writes, LMDB requires no maintenance * during operation. Both write-ahead loggers and append-only databases * require periodic checkpointing and/or compaction of their log or database * files otherwise they grow without bound. LMDB tracks free pages within * the database and re-uses them for new write operations, so the database * size does not grow without bound in normal use. * * The memory map can be used as a read-only or read-write map. It is * read-only by default as this provides total immunity to corruption. * Using read-write mode offers much higher write performance, but adds * the possibility for stray application writes thru pointers to silently * corrupt the database. Of course if your application code is known to * be bug-free (...) then this is not an issue. * * @section caveats_sec Caveats * Troubleshooting the lock file, plus semaphores on BSD systems: * * - A broken lockfile can cause sync issues. * Stale reader transactions left behind by an aborted program * cause further writes to grow the database quickly, and * stale locks can block further operation. * * Fix: Check for stale readers periodically, using the * #mdb_reader_check function or the \ref mdb_stat_1 "mdb_stat" tool. Or just * make all programs using the database close it; the lockfile * is always reset on first open of the environment. * * - On BSD systems or others configured with MDB_USE_POSIX_SEM, * startup can fail due to semaphores owned by another userid. * * Fix: Open and close the database as the user which owns the * semaphores (likely last user) or as root, while no other * process is using the database. * * Restrictions/caveats (in addition to those listed for some functions): * * - Only the database owner should normally use the database on * BSD systems or when otherwise configured with MDB_USE_POSIX_SEM. * Multiple users can cause startup to fail later, as noted above. * * - There is normally no pure read-only mode, since readers need write * access to locks and lock file. Exceptions: On read-only filesystems * or with the #MDB_NOLOCK flag described under #mdb_env_open(). * * - By default, in versions before 0.9.10, unused portions of the data * file might receive garbage data from memory freed by other code. * (This does not happen when using the #MDB_WRITEMAP flag.) As of * 0.9.10 the default behavior is to initialize such memory before * writing to the data file. Since there may be a slight performance * cost due to this initialization, applications may disable it using * the #MDB_NOMEMINIT flag. Applications handling sensitive data * which must not be written should not use this flag. This flag is * irrelevant when using #MDB_WRITEMAP. * * - A thread can only use one transaction at a time, plus any child * transactions. Each transaction belongs to one thread. See below. * The #MDB_NOTLS flag changes this for read-only transactions. * * - Use an MDB_env* in the process which opened it, without fork()ing. * * - Do not have open an LMDB database twice in the same process at * the same time. Not even from a plain open() call - close()ing it * breaks flock() advisory locking. * * - Avoid long-lived transactions. Read transactions prevent * reuse of pages freed by newer write transactions, thus the * database can grow quickly. Write transactions prevent * other write transactions, since writes are serialized. * * - Avoid suspending a process with active transactions. These * would then be "long-lived" as above. Also read transactions * suspended when writers commit could sometimes see wrong data. * * ...when several processes can use a database concurrently: * * - Avoid aborting a process with an active transaction. * The transaction becomes "long-lived" as above until a check * for stale readers is performed or the lockfile is reset, * since the process may not remove it from the lockfile. * * - If you do that anyway, do a periodic check for stale readers. Or * close the environment once in a while, so the lockfile can get reset. * * - Do not use LMDB databases on remote filesystems, even between * processes on the same host. This breaks flock() on some OSes, * possibly memory map sync, and certainly sync between programs * on different hosts. * * - Opening a database can fail if another process is opening or * closing it at exactly the same time. * * @author Howard Chu, Symas Corporation. * * @copyright Copyright 2011-2015 Howard Chu, Symas Corp. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . * * @par Derived From: * This code is derived from btree.c written by Martin Hedenfalk. * * Copyright (c) 2009, 2010 Martin Hedenfalk * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef _LMDB_H_ #define _LMDB_H_ #include #ifdef __cplusplus extern "C" { #endif /** Unix permissions for creating files, or dummy definition for Windows */ #ifdef _MSC_VER typedef int mdb_mode_t; #else typedef mode_t mdb_mode_t; #endif /** An abstraction for a file handle. * On POSIX systems file handles are small integers. On Windows * they're opaque pointers. */ #ifdef _WIN32 typedef void *mdb_filehandle_t; #else typedef int mdb_filehandle_t; #endif /** @defgroup mdb LMDB API * @{ * @brief OpenLDAP Lightning Memory-Mapped Database Manager */ /** @defgroup Version Version Macros * @{ */ /** Library major version */ #define MDB_VERSION_MAJOR 0 /** Library minor version */ #define MDB_VERSION_MINOR 9 /** Library patch version */ #define MDB_VERSION_PATCH 16 /** Combine args a,b,c into a single integer for easy version comparisons */ #define MDB_VERINT(a,b,c) (((a) << 24) | ((b) << 16) | (c)) /** The full library version as a single integer */ #define MDB_VERSION_FULL \ MDB_VERINT(MDB_VERSION_MAJOR,MDB_VERSION_MINOR,MDB_VERSION_PATCH) /** The release date of this library version */ #define MDB_VERSION_DATE "August 14, 2015" /** A stringifier for the version info */ #define MDB_VERSTR(a,b,c,d) "LMDB " #a "." #b "." #c ": (" d ")" /** A helper for the stringifier macro */ #define MDB_VERFOO(a,b,c,d) MDB_VERSTR(a,b,c,d) /** The full library version as a C string */ #define MDB_VERSION_STRING \ MDB_VERFOO(MDB_VERSION_MAJOR,MDB_VERSION_MINOR,MDB_VERSION_PATCH,MDB_VERSION_DATE) /** @} */ /** @brief Opaque structure for a database environment. * * A DB environment supports multiple databases, all residing in the same * shared-memory map. */ typedef struct MDB_env MDB_env; /** @brief Opaque structure for a transaction handle. * * All database operations require a transaction handle. Transactions may be * read-only or read-write. */ typedef struct MDB_txn MDB_txn; /** @brief A handle for an individual database in the DB environment. */ typedef unsigned int MDB_dbi; /** @brief Opaque structure for navigating through a database */ typedef struct MDB_cursor MDB_cursor; /** @brief Generic structure used for passing keys and data in and out * of the database. * * Values returned from the database are valid only until a subsequent * update operation, or the end of the transaction. Do not modify or * free them, they commonly point into the database itself. * * Key sizes must be between 1 and #mdb_env_get_maxkeysize() inclusive. * The same applies to data sizes in databases with the #MDB_DUPSORT flag. * Other data items can in theory be from 0 to 0xffffffff bytes long. */ typedef struct MDB_val { size_t mv_size; /**< size of the data item */ void *mv_data; /**< address of the data item */ } MDB_val; /** @brief A callback function used to compare two keys in a database */ typedef int (MDB_cmp_func)(const MDB_val *a, const MDB_val *b); /** @brief A callback function used to relocate a position-dependent data item * in a fixed-address database. * * The \b newptr gives the item's desired address in * the memory map, and \b oldptr gives its previous address. The item's actual * data resides at the address in \b item. This callback is expected to walk * through the fields of the record in \b item and modify any * values based at the \b oldptr address to be relative to the \b newptr address. * @param[in,out] item The item that is to be relocated. * @param[in] oldptr The previous address. * @param[in] newptr The new address to relocate to. * @param[in] relctx An application-provided context, set by #mdb_set_relctx(). * @todo This feature is currently unimplemented. */ typedef void (MDB_rel_func)(MDB_val *item, void *oldptr, void *newptr, void *relctx); /** @defgroup mdb_env Environment Flags * @{ */ /** mmap at a fixed address (experimental) */ #define MDB_FIXEDMAP 0x01 /** no environment directory */ #define MDB_NOSUBDIR 0x4000 /** don't fsync after commit */ #define MDB_NOSYNC 0x10000 /** read only */ #define MDB_RDONLY 0x20000 /** don't fsync metapage after commit */ #define MDB_NOMETASYNC 0x40000 /** use writable mmap */ #define MDB_WRITEMAP 0x80000 /** use asynchronous msync when #MDB_WRITEMAP is used */ #define MDB_MAPASYNC 0x100000 /** tie reader locktable slots to #MDB_txn objects instead of to threads */ #define MDB_NOTLS 0x200000 /** don't do any locking, caller must manage their own locks */ #define MDB_NOLOCK 0x400000 /** don't do readahead (no effect on Windows) */ #define MDB_NORDAHEAD 0x800000 /** don't initialize malloc'd memory before writing to datafile */ #define MDB_NOMEMINIT 0x1000000 /** @} */ /** @defgroup mdb_dbi_open Database Flags * @{ */ /** use reverse string keys */ #define MDB_REVERSEKEY 0x02 /** use sorted duplicates */ #define MDB_DUPSORT 0x04 /** numeric keys in native byte order: either unsigned int or size_t. * The keys must all be of the same size. */ #define MDB_INTEGERKEY 0x08 /** with #MDB_DUPSORT, sorted dup items have fixed size */ #define MDB_DUPFIXED 0x10 /** with #MDB_DUPSORT, dups are #MDB_INTEGERKEY-style integers */ #define MDB_INTEGERDUP 0x20 /** with #MDB_DUPSORT, use reverse string dups */ #define MDB_REVERSEDUP 0x40 /** create DB if not already existing */ #define MDB_CREATE 0x40000 /** @} */ /** @defgroup mdb_put Write Flags * @{ */ /** For put: Don't write if the key already exists. */ #define MDB_NOOVERWRITE 0x10 /** Only for #MDB_DUPSORT
* For put: don't write if the key and data pair already exist.
* For mdb_cursor_del: remove all duplicate data items. */ #define MDB_NODUPDATA 0x20 /** For mdb_cursor_put: overwrite the current key/data pair */ #define MDB_CURRENT 0x40 /** For put: Just reserve space for data, don't copy it. Return a * pointer to the reserved space. */ #define MDB_RESERVE 0x10000 /** Data is being appended, don't split full pages. */ #define MDB_APPEND 0x20000 /** Duplicate data is being appended, don't split full pages. */ #define MDB_APPENDDUP 0x40000 /** Store multiple data items in one call. Only for #MDB_DUPFIXED. */ #define MDB_MULTIPLE 0x80000 /* @} */ /** @defgroup mdb_copy Copy Flags * @{ */ /** Compacting copy: Omit free space from copy, and renumber all * pages sequentially. */ #define MDB_CP_COMPACT 0x01 /* @} */ /** @brief Cursor Get operations. * * This is the set of all operations for retrieving data * using a cursor. */ typedef enum MDB_cursor_op { MDB_FIRST, /**< Position at first key/data item */ MDB_FIRST_DUP, /**< Position at first data item of current key. Only for #MDB_DUPSORT */ MDB_GET_BOTH, /**< Position at key/data pair. Only for #MDB_DUPSORT */ MDB_GET_BOTH_RANGE, /**< position at key, nearest data. Only for #MDB_DUPSORT */ MDB_GET_CURRENT, /**< Return key/data at current cursor position */ MDB_GET_MULTIPLE, /**< Return key and up to a page of duplicate data items from current cursor position. Move cursor to prepare for #MDB_NEXT_MULTIPLE. Only for #MDB_DUPFIXED */ MDB_LAST, /**< Position at last key/data item */ MDB_LAST_DUP, /**< Position at last data item of current key. Only for #MDB_DUPSORT */ MDB_NEXT, /**< Position at next data item */ MDB_NEXT_DUP, /**< Position at next data item of current key. Only for #MDB_DUPSORT */ MDB_NEXT_MULTIPLE, /**< Return key and up to a page of duplicate data items from next cursor position. Move cursor to prepare for #MDB_NEXT_MULTIPLE. Only for #MDB_DUPFIXED */ MDB_NEXT_NODUP, /**< Position at first data item of next key */ MDB_PREV, /**< Position at previous data item */ MDB_PREV_DUP, /**< Position at previous data item of current key. Only for #MDB_DUPSORT */ MDB_PREV_NODUP, /**< Position at last data item of previous key */ MDB_SET, /**< Position at specified key */ MDB_SET_KEY, /**< Position at specified key, return key + data */ MDB_SET_RANGE /**< Position at first key greater than or equal to specified key. */ } MDB_cursor_op; /** @defgroup errors Return Codes * * BerkeleyDB uses -30800 to -30999, we'll go under them * @{ */ /** Successful result */ #define MDB_SUCCESS 0 /** key/data pair already exists */ #define MDB_KEYEXIST (-30799) /** key/data pair not found (EOF) */ #define MDB_NOTFOUND (-30798) /** Requested page not found - this usually indicates corruption */ #define MDB_PAGE_NOTFOUND (-30797) /** Located page was wrong type */ #define MDB_CORRUPTED (-30796) /** Update of meta page failed, probably I/O error */ #define MDB_PANIC (-30795) /** Environment version mismatch */ #define MDB_VERSION_MISMATCH (-30794) /** File is not a valid LMDB file */ #define MDB_INVALID (-30793) /** Environment mapsize reached */ #define MDB_MAP_FULL (-30792) /** Environment maxdbs reached */ #define MDB_DBS_FULL (-30791) /** Environment maxreaders reached */ #define MDB_READERS_FULL (-30790) /** Too many TLS keys in use - Windows only */ #define MDB_TLS_FULL (-30789) /** Txn has too many dirty pages */ #define MDB_TXN_FULL (-30788) /** Cursor stack too deep - internal error */ #define MDB_CURSOR_FULL (-30787) /** Page has not enough space - internal error */ #define MDB_PAGE_FULL (-30786) /** Database contents grew beyond environment mapsize */ #define MDB_MAP_RESIZED (-30785) /** Operation and DB incompatible, or DB type changed. This can mean: *
    *
  • The operation expects an #MDB_DUPSORT / #MDB_DUPFIXED database. *
  • Opening a named DB when the unnamed DB has #MDB_DUPSORT / #MDB_INTEGERKEY. *
  • Accessing a data record as a database, or vice versa. *
  • The database was dropped and recreated with different flags. *
*/ #define MDB_INCOMPATIBLE (-30784) /** Invalid reuse of reader locktable slot */ #define MDB_BAD_RSLOT (-30783) /** Transaction cannot recover - it must be aborted */ #define MDB_BAD_TXN (-30782) /** Unsupported size of key/DB name/data, or wrong DUPFIXED size */ #define MDB_BAD_VALSIZE (-30781) /** The specified DBI was changed unexpectedly */ #define MDB_BAD_DBI (-30780) /** The last defined error code */ #define MDB_LAST_ERRCODE MDB_BAD_DBI /** @} */ /** @brief Statistics for a database in the environment */ typedef struct MDB_stat { unsigned int ms_psize; /**< Size of a database page. This is currently the same for all databases. */ unsigned int ms_depth; /**< Depth (height) of the B-tree */ size_t ms_branch_pages; /**< Number of internal (non-leaf) pages */ size_t ms_leaf_pages; /**< Number of leaf pages */ size_t ms_overflow_pages; /**< Number of overflow pages */ size_t ms_entries; /**< Number of data items */ } MDB_stat; /** @brief Information about the environment */ typedef struct MDB_envinfo { void *me_mapaddr; /**< Address of map, if fixed */ size_t me_mapsize; /**< Size of the data memory map */ size_t me_last_pgno; /**< ID of the last used page */ size_t me_last_txnid; /**< ID of the last committed transaction */ unsigned int me_maxreaders; /**< max reader slots in the environment */ unsigned int me_numreaders; /**< max reader slots used in the environment */ } MDB_envinfo; /** @brief Return the LMDB library version information. * * @param[out] major if non-NULL, the library major version number is copied here * @param[out] minor if non-NULL, the library minor version number is copied here * @param[out] patch if non-NULL, the library patch version number is copied here * @retval "version string" The library version as a string */ char *mdb_version(int *major, int *minor, int *patch); /** @brief Return a string describing a given error code. * * This function is a superset of the ANSI C X3.159-1989 (ANSI C) strerror(3) * function. If the error code is greater than or equal to 0, then the string * returned by the system function strerror(3) is returned. If the error code * is less than 0, an error string corresponding to the LMDB library error is * returned. See @ref errors for a list of LMDB-specific error codes. * @param[in] err The error code * @retval "error message" The description of the error */ char *mdb_strerror(int err); /** @brief Create an LMDB environment handle. * * This function allocates memory for a #MDB_env structure. To release * the allocated memory and discard the handle, call #mdb_env_close(). * Before the handle may be used, it must be opened using #mdb_env_open(). * Various other options may also need to be set before opening the handle, * e.g. #mdb_env_set_mapsize(), #mdb_env_set_maxreaders(), #mdb_env_set_maxdbs(), * depending on usage requirements. * @param[out] env The address where the new handle will be stored * @return A non-zero error value on failure and 0 on success. */ int mdb_env_create(MDB_env **env); /** @brief Open an environment handle. * * If this function fails, #mdb_env_close() must be called to discard the #MDB_env handle. * @param[in] env An environment handle returned by #mdb_env_create() * @param[in] path The directory in which the database files reside. This * directory must already exist and be writable. * @param[in] flags Special options for this environment. This parameter * must be set to 0 or by bitwise OR'ing together one or more of the * values described here. * Flags set by mdb_env_set_flags() are also used. *
    *
  • #MDB_FIXEDMAP * use a fixed address for the mmap region. This flag must be specified * when creating the environment, and is stored persistently in the environment. * If successful, the memory map will always reside at the same virtual address * and pointers used to reference data items in the database will be constant * across multiple invocations. This option may not always work, depending on * how the operating system has allocated memory to shared libraries and other uses. * The feature is highly experimental. *
  • #MDB_NOSUBDIR * By default, LMDB creates its environment in a directory whose * pathname is given in \b path, and creates its data and lock files * under that directory. With this option, \b path is used as-is for * the database main data file. The database lock file is the \b path * with "-lock" appended. *
  • #MDB_RDONLY * Open the environment in read-only mode. No write operations will be * allowed. LMDB will still modify the lock file - except on read-only * filesystems, where LMDB does not use locks. *
  • #MDB_WRITEMAP * Use a writeable memory map unless MDB_RDONLY is set. This is faster * and uses fewer mallocs, but loses protection from application bugs * like wild pointer writes and other bad updates into the database. * Incompatible with nested transactions. * Do not mix processes with and without MDB_WRITEMAP on the same * environment. This can defeat durability (#mdb_env_sync etc). *
  • #MDB_NOMETASYNC * Flush system buffers to disk only once per transaction, omit the * metadata flush. Defer that until the system flushes files to disk, * or next non-MDB_RDONLY commit or #mdb_env_sync(). This optimization * maintains database integrity, but a system crash may undo the last * committed transaction. I.e. it preserves the ACI (atomicity, * consistency, isolation) but not D (durability) database property. * This flag may be changed at any time using #mdb_env_set_flags(). *
  • #MDB_NOSYNC * Don't flush system buffers to disk when committing a transaction. * This optimization means a system crash can corrupt the database or * lose the last transactions if buffers are not yet flushed to disk. * The risk is governed by how often the system flushes dirty buffers * to disk and how often #mdb_env_sync() is called. However, if the * filesystem preserves write order and the #MDB_WRITEMAP flag is not * used, transactions exhibit ACI (atomicity, consistency, isolation) * properties and only lose D (durability). I.e. database integrity * is maintained, but a system crash may undo the final transactions. * Note that (#MDB_NOSYNC | #MDB_WRITEMAP) leaves the system with no * hint for when to write transactions to disk, unless #mdb_env_sync() * is called. (#MDB_MAPASYNC | #MDB_WRITEMAP) may be preferable. * This flag may be changed at any time using #mdb_env_set_flags(). *
  • #MDB_MAPASYNC * When using #MDB_WRITEMAP, use asynchronous flushes to disk. * As with #MDB_NOSYNC, a system crash can then corrupt the * database or lose the last transactions. Calling #mdb_env_sync() * ensures on-disk database integrity until next commit. * This flag may be changed at any time using #mdb_env_set_flags(). *
  • #MDB_NOTLS * Don't use Thread-Local Storage. Tie reader locktable slots to * #MDB_txn objects instead of to threads. I.e. #mdb_txn_reset() keeps * the slot reseved for the #MDB_txn object. A thread may use parallel * read-only transactions. A read-only transaction may span threads if * the user synchronizes its use. Applications that multiplex many * user threads over individual OS threads need this option. Such an * application must also serialize the write transactions in an OS * thread, since LMDB's write locking is unaware of the user threads. *
  • #MDB_NOLOCK * Don't do any locking. If concurrent access is anticipated, the * caller must manage all concurrency itself. For proper operation * the caller must enforce single-writer semantics, and must ensure * that no readers are using old transactions while a writer is * active. The simplest approach is to use an exclusive lock so that * no readers may be active at all when a writer begins. *
  • #MDB_NORDAHEAD * Turn off readahead. Most operating systems perform readahead on * read requests by default. This option turns it off if the OS * supports it. Turning it off may help random read performance * when the DB is larger than RAM and system RAM is full. * The option is not implemented on Windows. *
  • #MDB_NOMEMINIT * Don't initialize malloc'd memory before writing to unused spaces * in the data file. By default, memory for pages written to the data * file is obtained using malloc. While these pages may be reused in * subsequent transactions, freshly malloc'd pages will be initialized * to zeroes before use. This avoids persisting leftover data from other * code (that used the heap and subsequently freed the memory) into the * data file. Note that many other system libraries may allocate * and free memory from the heap for arbitrary uses. E.g., stdio may * use the heap for file I/O buffers. This initialization step has a * modest performance cost so some applications may want to disable * it using this flag. This option can be a problem for applications * which handle sensitive data like passwords, and it makes memory * checkers like Valgrind noisy. This flag is not needed with #MDB_WRITEMAP, * which writes directly to the mmap instead of using malloc for pages. The * initialization is also skipped if #MDB_RESERVE is used; the * caller is expected to overwrite all of the memory that was * reserved in that case. * This flag may be changed at any time using #mdb_env_set_flags(). *
* @param[in] mode The UNIX permissions to set on created files and semaphores. * This parameter is ignored on Windows. * @return A non-zero error value on failure and 0 on success. Some possible * errors are: *
    *
  • #MDB_VERSION_MISMATCH - the version of the LMDB library doesn't match the * version that created the database environment. *
  • #MDB_INVALID - the environment file headers are corrupted. *
  • ENOENT - the directory specified by the path parameter doesn't exist. *
  • EACCES - the user didn't have permission to access the environment files. *
  • EAGAIN - the environment was locked by another process. *
*/ int mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mdb_mode_t mode); /** @brief Copy an LMDB environment to the specified path. * * This function may be used to make a backup of an existing environment. * No lockfile is created, since it gets recreated at need. * @note This call can trigger significant file size growth if run in * parallel with write transactions, because it employs a read-only * transaction. See long-lived transactions under @ref caveats_sec. * @param[in] env An environment handle returned by #mdb_env_create(). It * must have already been opened successfully. * @param[in] path The directory in which the copy will reside. This * directory must already exist and be writable but must otherwise be * empty. * @return A non-zero error value on failure and 0 on success. */ int mdb_env_copy(MDB_env *env, const char *path); /** @brief Copy an LMDB environment to the specified file descriptor. * * This function may be used to make a backup of an existing environment. * No lockfile is created, since it gets recreated at need. * @note This call can trigger significant file size growth if run in * parallel with write transactions, because it employs a read-only * transaction. See long-lived transactions under @ref caveats_sec. * @param[in] env An environment handle returned by #mdb_env_create(). It * must have already been opened successfully. * @param[in] fd The filedescriptor to write the copy to. It must * have already been opened for Write access. * @return A non-zero error value on failure and 0 on success. */ int mdb_env_copyfd(MDB_env *env, mdb_filehandle_t fd); /** @brief Copy an LMDB environment to the specified path, with options. * * This function may be used to make a backup of an existing environment. * No lockfile is created, since it gets recreated at need. * @note This call can trigger significant file size growth if run in * parallel with write transactions, because it employs a read-only * transaction. See long-lived transactions under @ref caveats_sec. * @param[in] env An environment handle returned by #mdb_env_create(). It * must have already been opened successfully. * @param[in] path The directory in which the copy will reside. This * directory must already exist and be writable but must otherwise be * empty. * @param[in] flags Special options for this operation. This parameter * must be set to 0 or by bitwise OR'ing together one or more of the * values described here. *
    *
  • #MDB_CP_COMPACT - Perform compaction while copying: omit free * pages and sequentially renumber all pages in output. This option * consumes more CPU and runs more slowly than the default. *
* @return A non-zero error value on failure and 0 on success. */ int mdb_env_copy2(MDB_env *env, const char *path, unsigned int flags); /** @brief Copy an LMDB environment to the specified file descriptor, * with options. * * This function may be used to make a backup of an existing environment. * No lockfile is created, since it gets recreated at need. See * #mdb_env_copy2() for further details. * @note This call can trigger significant file size growth if run in * parallel with write transactions, because it employs a read-only * transaction. See long-lived transactions under @ref caveats_sec. * @param[in] env An environment handle returned by #mdb_env_create(). It * must have already been opened successfully. * @param[in] fd The filedescriptor to write the copy to. It must * have already been opened for Write access. * @param[in] flags Special options for this operation. * See #mdb_env_copy2() for options. * @return A non-zero error value on failure and 0 on success. */ int mdb_env_copyfd2(MDB_env *env, mdb_filehandle_t fd, unsigned int flags); /** @brief Return statistics about the LMDB environment. * * @param[in] env An environment handle returned by #mdb_env_create() * @param[out] stat The address of an #MDB_stat structure * where the statistics will be copied */ int mdb_env_stat(MDB_env *env, MDB_stat *stat); /** @brief Return information about the LMDB environment. * * @param[in] env An environment handle returned by #mdb_env_create() * @param[out] stat The address of an #MDB_envinfo structure * where the information will be copied */ int mdb_env_info(MDB_env *env, MDB_envinfo *stat); /** @brief Flush the data buffers to disk. * * Data is always written to disk when #mdb_txn_commit() is called, * but the operating system may keep it buffered. LMDB always flushes * the OS buffers upon commit as well, unless the environment was * opened with #MDB_NOSYNC or in part #MDB_NOMETASYNC. This call is * not valid if the environment was opened with #MDB_RDONLY. * @param[in] env An environment handle returned by #mdb_env_create() * @param[in] force If non-zero, force a synchronous flush. Otherwise * if the environment has the #MDB_NOSYNC flag set the flushes * will be omitted, and with #MDB_MAPASYNC they will be asynchronous. * @return A non-zero error value on failure and 0 on success. Some possible * errors are: *
    *
  • EACCES - the environment is read-only. *
  • EINVAL - an invalid parameter was specified. *
  • EIO - an error occurred during synchronization. *
*/ int mdb_env_sync(MDB_env *env, int force); /** @brief Close the environment and release the memory map. * * Only a single thread may call this function. All transactions, databases, * and cursors must already be closed before calling this function. Attempts to * use any such handles after calling this function will cause a SIGSEGV. * The environment handle will be freed and must not be used again after this call. * @param[in] env An environment handle returned by #mdb_env_create() */ void mdb_env_close(MDB_env *env); /** @brief Set environment flags. * * This may be used to set some flags in addition to those from * #mdb_env_open(), or to unset these flags. If several threads * change the flags at the same time, the result is undefined. * @param[in] env An environment handle returned by #mdb_env_create() * @param[in] flags The flags to change, bitwise OR'ed together * @param[in] onoff A non-zero value sets the flags, zero clears them. * @return A non-zero error value on failure and 0 on success. Some possible * errors are: *
    *
  • EINVAL - an invalid parameter was specified. *
*/ int mdb_env_set_flags(MDB_env *env, unsigned int flags, int onoff); /** @brief Get environment flags. * * @param[in] env An environment handle returned by #mdb_env_create() * @param[out] flags The address of an integer to store the flags * @return A non-zero error value on failure and 0 on success. Some possible * errors are: *
    *
  • EINVAL - an invalid parameter was specified. *
*/ int mdb_env_get_flags(MDB_env *env, unsigned int *flags); /** @brief Return the path that was used in #mdb_env_open(). * * @param[in] env An environment handle returned by #mdb_env_create() * @param[out] path Address of a string pointer to contain the path. This * is the actual string in the environment, not a copy. It should not be * altered in any way. * @return A non-zero error value on failure and 0 on success. Some possible * errors are: *
    *
  • EINVAL - an invalid parameter was specified. *
*/ int mdb_env_get_path(MDB_env *env, const char **path); /** @brief Return the filedescriptor for the given environment. * * @param[in] env An environment handle returned by #mdb_env_create() * @param[out] fd Address of a mdb_filehandle_t to contain the descriptor. * @return A non-zero error value on failure and 0 on success. Some possible * errors are: *
    *
  • EINVAL - an invalid parameter was specified. *
*/ int mdb_env_get_fd(MDB_env *env, mdb_filehandle_t *fd); /** @brief Set the size of the memory map to use for this environment. * * The size should be a multiple of the OS page size. The default is * 10485760 bytes. The size of the memory map is also the maximum size * of the database. The value should be chosen as large as possible, * to accommodate future growth of the database. * This function should be called after #mdb_env_create() and before #mdb_env_open(). * It may be called at later times if no transactions are active in * this process. Note that the library does not check for this condition, * the caller must ensure it explicitly. * * The new size takes effect immediately for the current process but * will not be persisted to any others until a write transaction has been * committed by the current process. Also, only mapsize increases are * persisted into the environment. * * If the mapsize is increased by another process, and data has grown * beyond the range of the current mapsize, #mdb_txn_begin() will * return #MDB_MAP_RESIZED. This function may be called with a size * of zero to adopt the new size. * * Any attempt to set a size smaller than the space already consumed * by the environment will be silently changed to the current size of the used space. * @param[in] env An environment handle returned by #mdb_env_create() * @param[in] size The size in bytes * @return A non-zero error value on failure and 0 on success. Some possible * errors are: *
    *
  • EINVAL - an invalid parameter was specified, or the environment has * an active write transaction. *
*/ int mdb_env_set_mapsize(MDB_env *env, size_t size); /** @brief Set the maximum number of threads/reader slots for the environment. * * This defines the number of slots in the lock table that is used to track readers in the * the environment. The default is 126. * Starting a read-only transaction normally ties a lock table slot to the * current thread until the environment closes or the thread exits. If * MDB_NOTLS is in use, #mdb_txn_begin() instead ties the slot to the * MDB_txn object until it or the #MDB_env object is destroyed. * This function may only be called after #mdb_env_create() and before #mdb_env_open(). * @param[in] env An environment handle returned by #mdb_env_create() * @param[in] readers The maximum number of reader lock table slots * @return A non-zero error value on failure and 0 on success. Some possible * errors are: *
    *
  • EINVAL - an invalid parameter was specified, or the environment is already open. *
*/ int mdb_env_set_maxreaders(MDB_env *env, unsigned int readers); /** @brief Get the maximum number of threads/reader slots for the environment. * * @param[in] env An environment handle returned by #mdb_env_create() * @param[out] readers Address of an integer to store the number of readers * @return A non-zero error value on failure and 0 on success. Some possible * errors are: *
    *
  • EINVAL - an invalid parameter was specified. *
*/ int mdb_env_get_maxreaders(MDB_env *env, unsigned int *readers); /** @brief Set the maximum number of named databases for the environment. * * This function is only needed if multiple databases will be used in the * environment. Simpler applications that use the environment as a single * unnamed database can ignore this option. * This function may only be called after #mdb_env_create() and before #mdb_env_open(). * * Currently a moderate number of slots are cheap but a huge number gets * expensive: 7-120 words per transaction, and every #mdb_dbi_open() * does a linear search of the opened slots. * @param[in] env An environment handle returned by #mdb_env_create() * @param[in] dbs The maximum number of databases * @return A non-zero error value on failure and 0 on success. Some possible * errors are: *
    *
  • EINVAL - an invalid parameter was specified, or the environment is already open. *
*/ int mdb_env_set_maxdbs(MDB_env *env, MDB_dbi dbs); /** @brief Get the maximum size of keys and #MDB_DUPSORT data we can write. * * Depends on the compile-time constant #MDB_MAXKEYSIZE. Default 511. * See @ref MDB_val. * @param[in] env An environment handle returned by #mdb_env_create() * @return The maximum size of a key we can write */ int mdb_env_get_maxkeysize(MDB_env *env); /** @brief Set application information associated with the #MDB_env. * * @param[in] env An environment handle returned by #mdb_env_create() * @param[in] ctx An arbitrary pointer for whatever the application needs. * @return A non-zero error value on failure and 0 on success. */ int mdb_env_set_userctx(MDB_env *env, void *ctx); /** @brief Get the application information associated with the #MDB_env. * * @param[in] env An environment handle returned by #mdb_env_create() * @return The pointer set by #mdb_env_set_userctx(). */ void *mdb_env_get_userctx(MDB_env *env); /** @brief A callback function for most LMDB assert() failures, * called before printing the message and aborting. * * @param[in] env An environment handle returned by #mdb_env_create(). * @param[in] msg The assertion message, not including newline. */ typedef void MDB_assert_func(MDB_env *env, const char *msg); /** Set or reset the assert() callback of the environment. * Disabled if liblmdb is buillt with NDEBUG. * @note This hack should become obsolete as lmdb's error handling matures. * @param[in] env An environment handle returned by #mdb_env_create(). * @param[in] func An #MDB_assert_func function, or 0. * @return A non-zero error value on failure and 0 on success. */ int mdb_env_set_assert(MDB_env *env, MDB_assert_func *func); /** @brief Create a transaction for use with the environment. * * The transaction handle may be discarded using #mdb_txn_abort() or #mdb_txn_commit(). * @note A transaction and its cursors must only be used by a single * thread, and a thread may only have a single transaction at a time. * If #MDB_NOTLS is in use, this does not apply to read-only transactions. * @note Cursors may not span transactions. * @param[in] env An environment handle returned by #mdb_env_create() * @param[in] parent If this parameter is non-NULL, the new transaction * will be a nested transaction, with the transaction indicated by \b parent * as its parent. Transactions may be nested to any level. A parent * transaction and its cursors may not issue any other operations than * mdb_txn_commit and mdb_txn_abort while it has active child transactions. * @param[in] flags Special options for this transaction. This parameter * must be set to 0 or by bitwise OR'ing together one or more of the * values described here. *
    *
  • #MDB_RDONLY * This transaction will not perform any write operations. *
* @param[out] txn Address where the new #MDB_txn handle will be stored * @return A non-zero error value on failure and 0 on success. Some possible * errors are: *
    *
  • #MDB_PANIC - a fatal error occurred earlier and the environment * must be shut down. *
  • #MDB_MAP_RESIZED - another process wrote data beyond this MDB_env's * mapsize and this environment's map must be resized as well. * See #mdb_env_set_mapsize(). *
  • #MDB_READERS_FULL - a read-only transaction was requested and * the reader lock table is full. See #mdb_env_set_maxreaders(). *
  • ENOMEM - out of memory. *
*/ int mdb_txn_begin(MDB_env *env, MDB_txn *parent, unsigned int flags, MDB_txn **txn); /** @brief Returns the transaction's #MDB_env * * @param[in] txn A transaction handle returned by #mdb_txn_begin() */ MDB_env *mdb_txn_env(MDB_txn *txn); /** @brief Commit all the operations of a transaction into the database. * * The transaction handle is freed. It and its cursors must not be used * again after this call, except with #mdb_cursor_renew(). * @note Earlier documentation incorrectly said all cursors would be freed. * Only write-transactions free cursors. * @param[in] txn A transaction handle returned by #mdb_txn_begin() * @return A non-zero error value on failure and 0 on success. Some possible * errors are: *
    *
  • EINVAL - an invalid parameter was specified. *
  • ENOSPC - no more disk space. *
  • EIO - a low-level I/O error occurred while writing. *
  • ENOMEM - out of memory. *
*/ int mdb_txn_commit(MDB_txn *txn); /** @brief Abandon all the operations of the transaction instead of saving them. * * The transaction handle is freed. It and its cursors must not be used * again after this call, except with #mdb_cursor_renew(). * @note Earlier documentation incorrectly said all cursors would be freed. * Only write-transactions free cursors. * @param[in] txn A transaction handle returned by #mdb_txn_begin() */ void mdb_txn_abort(MDB_txn *txn); /** @brief Reset a read-only transaction. * * Abort the transaction like #mdb_txn_abort(), but keep the transaction * handle. #mdb_txn_renew() may reuse the handle. This saves allocation * overhead if the process will start a new read-only transaction soon, * and also locking overhead if #MDB_NOTLS is in use. The reader table * lock is released, but the table slot stays tied to its thread or * #MDB_txn. Use mdb_txn_abort() to discard a reset handle, and to free * its lock table slot if MDB_NOTLS is in use. * Cursors opened within the transaction must not be used * again after this call, except with #mdb_cursor_renew(). * Reader locks generally don't interfere with writers, but they keep old * versions of database pages allocated. Thus they prevent the old pages * from being reused when writers commit new data, and so under heavy load * the database size may grow much more rapidly than otherwise. * @param[in] txn A transaction handle returned by #mdb_txn_begin() */ void mdb_txn_reset(MDB_txn *txn); /** @brief Renew a read-only transaction. * * This acquires a new reader lock for a transaction handle that had been * released by #mdb_txn_reset(). It must be called before a reset transaction * may be used again. * @param[in] txn A transaction handle returned by #mdb_txn_begin() * @return A non-zero error value on failure and 0 on success. Some possible * errors are: *
    *
  • #MDB_PANIC - a fatal error occurred earlier and the environment * must be shut down. *
  • EINVAL - an invalid parameter was specified. *
*/ int mdb_txn_renew(MDB_txn *txn); /** Compat with version <= 0.9.4, avoid clash with libmdb from MDB Tools project */ #define mdb_open(txn,name,flags,dbi) mdb_dbi_open(txn,name,flags,dbi) /** Compat with version <= 0.9.4, avoid clash with libmdb from MDB Tools project */ #define mdb_close(env,dbi) mdb_dbi_close(env,dbi) /** @brief Open a database in the environment. * * A database handle denotes the name and parameters of a database, * independently of whether such a database exists. * The database handle may be discarded by calling #mdb_dbi_close(). * The old database handle is returned if the database was already open. * The handle may only be closed once. * * The database handle will be private to the current transaction until * the transaction is successfully committed. If the transaction is * aborted the handle will be closed automatically. * After a successful commit the handle will reside in the shared * environment, and may be used by other transactions. * * This function must not be called from multiple concurrent * transactions in the same process. A transaction that uses * this function must finish (either commit or abort) before * any other transaction in the process may use this function. * * To use named databases (with name != NULL), #mdb_env_set_maxdbs() * must be called before opening the environment. Database names are * keys in the unnamed database, and may be read but not written. * * @param[in] txn A transaction handle returned by #mdb_txn_begin() * @param[in] name The name of the database to open. If only a single * database is needed in the environment, this value may be NULL. * @param[in] flags Special options for this database. This parameter * must be set to 0 or by bitwise OR'ing together one or more of the * values described here. *
    *
  • #MDB_REVERSEKEY * Keys are strings to be compared in reverse order, from the end * of the strings to the beginning. By default, Keys are treated as strings and * compared from beginning to end. *
  • #MDB_DUPSORT * Duplicate keys may be used in the database. (Or, from another perspective, * keys may have multiple data items, stored in sorted order.) By default * keys must be unique and may have only a single data item. *
  • #MDB_INTEGERKEY * Keys are binary integers in native byte order, either unsigned int * or size_t, and will be sorted as such. * The keys must all be of the same size. *
  • #MDB_DUPFIXED * This flag may only be used in combination with #MDB_DUPSORT. This option * tells the library that the data items for this database are all the same * size, which allows further optimizations in storage and retrieval. When * all data items are the same size, the #MDB_GET_MULTIPLE and #MDB_NEXT_MULTIPLE * cursor operations may be used to retrieve multiple items at once. *
  • #MDB_INTEGERDUP * This option specifies that duplicate data items are binary integers, * similar to #MDB_INTEGERKEY keys. *
  • #MDB_REVERSEDUP * This option specifies that duplicate data items should be compared as * strings in reverse order. *
  • #MDB_CREATE * Create the named database if it doesn't exist. This option is not * allowed in a read-only transaction or a read-only environment. *
* @param[out] dbi Address where the new #MDB_dbi handle will be stored * @return A non-zero error value on failure and 0 on success. Some possible * errors are: *
    *
  • #MDB_NOTFOUND - the specified database doesn't exist in the environment * and #MDB_CREATE was not specified. *
  • #MDB_DBS_FULL - too many databases have been opened. See #mdb_env_set_maxdbs(). *
*/ int mdb_dbi_open(MDB_txn *txn, const char *name, unsigned int flags, MDB_dbi *dbi); /** @brief Retrieve statistics for a database. * * @param[in] txn A transaction handle returned by #mdb_txn_begin() * @param[in] dbi A database handle returned by #mdb_dbi_open() * @param[out] stat The address of an #MDB_stat structure * where the statistics will be copied * @return A non-zero error value on failure and 0 on success. Some possible * errors are: *
    *
  • EINVAL - an invalid parameter was specified. *
*/ int mdb_stat(MDB_txn *txn, MDB_dbi dbi, MDB_stat *stat); /** @brief Retrieve the DB flags for a database handle. * * @param[in] txn A transaction handle returned by #mdb_txn_begin() * @param[in] dbi A database handle returned by #mdb_dbi_open() * @param[out] flags Address where the flags will be returned. * @return A non-zero error value on failure and 0 on success. */ int mdb_dbi_flags(MDB_txn *txn, MDB_dbi dbi, unsigned int *flags); /** @brief Close a database handle. Normally unnecessary. Use with care: * * This call is not mutex protected. Handles should only be closed by * a single thread, and only if no other threads are going to reference * the database handle or one of its cursors any further. Do not close * a handle if an existing transaction has modified its database. * Doing so can cause misbehavior from database corruption to errors * like MDB_BAD_VALSIZE (since the DB name is gone). * * Closing a database handle is not necessary, but lets #mdb_dbi_open() * reuse the handle value. Usually it's better to set a bigger * #mdb_env_set_maxdbs(), unless that value would be large. * * @param[in] env An environment handle returned by #mdb_env_create() * @param[in] dbi A database handle returned by #mdb_dbi_open() */ void mdb_dbi_close(MDB_env *env, MDB_dbi dbi); /** @brief Empty or delete+close a database. * * See #mdb_dbi_close() for restrictions about closing the DB handle. * @param[in] txn A transaction handle returned by #mdb_txn_begin() * @param[in] dbi A database handle returned by #mdb_dbi_open() * @param[in] del 0 to empty the DB, 1 to delete it from the * environment and close the DB handle. * @return A non-zero error value on failure and 0 on success. */ int mdb_drop(MDB_txn *txn, MDB_dbi dbi, int del); /** @brief Set a custom key comparison function for a database. * * The comparison function is called whenever it is necessary to compare a * key specified by the application with a key currently stored in the database. * If no comparison function is specified, and no special key flags were specified * with #mdb_dbi_open(), the keys are compared lexically, with shorter keys collating * before longer keys. * @warning This function must be called before any data access functions are used, * otherwise data corruption may occur. The same comparison function must be used by every * program accessing the database, every time the database is used. * @param[in] txn A transaction handle returned by #mdb_txn_begin() * @param[in] dbi A database handle returned by #mdb_dbi_open() * @param[in] cmp A #MDB_cmp_func function * @return A non-zero error value on failure and 0 on success. Some possible * errors are: *
    *
  • EINVAL - an invalid parameter was specified. *
*/ int mdb_set_compare(MDB_txn *txn, MDB_dbi dbi, MDB_cmp_func *cmp); /** @brief Set a custom data comparison function for a #MDB_DUPSORT database. * * This comparison function is called whenever it is necessary to compare a data * item specified by the application with a data item currently stored in the database. * This function only takes effect if the database was opened with the #MDB_DUPSORT * flag. * If no comparison function is specified, and no special key flags were specified * with #mdb_dbi_open(), the data items are compared lexically, with shorter items collating * before longer items. * @warning This function must be called before any data access functions are used, * otherwise data corruption may occur. The same comparison function must be used by every * program accessing the database, every time the database is used. * @param[in] txn A transaction handle returned by #mdb_txn_begin() * @param[in] dbi A database handle returned by #mdb_dbi_open() * @param[in] cmp A #MDB_cmp_func function * @return A non-zero error value on failure and 0 on success. Some possible * errors are: *
    *
  • EINVAL - an invalid parameter was specified. *
*/ int mdb_set_dupsort(MDB_txn *txn, MDB_dbi dbi, MDB_cmp_func *cmp); /** @brief Set a relocation function for a #MDB_FIXEDMAP database. * * @todo The relocation function is called whenever it is necessary to move the data * of an item to a different position in the database (e.g. through tree * balancing operations, shifts as a result of adds or deletes, etc.). It is * intended to allow address/position-dependent data items to be stored in * a database in an environment opened with the #MDB_FIXEDMAP option. * Currently the relocation feature is unimplemented and setting * this function has no effect. * @param[in] txn A transaction handle returned by #mdb_txn_begin() * @param[in] dbi A database handle returned by #mdb_dbi_open() * @param[in] rel A #MDB_rel_func function * @return A non-zero error value on failure and 0 on success. Some possible * errors are: *
    *
  • EINVAL - an invalid parameter was specified. *
*/ int mdb_set_relfunc(MDB_txn *txn, MDB_dbi dbi, MDB_rel_func *rel); /** @brief Set a context pointer for a #MDB_FIXEDMAP database's relocation function. * * See #mdb_set_relfunc and #MDB_rel_func for more details. * @param[in] txn A transaction handle returned by #mdb_txn_begin() * @param[in] dbi A database handle returned by #mdb_dbi_open() * @param[in] ctx An arbitrary pointer for whatever the application needs. * It will be passed to the callback function set by #mdb_set_relfunc * as its \b relctx parameter whenever the callback is invoked. * @return A non-zero error value on failure and 0 on success. Some possible * errors are: *
    *
  • EINVAL - an invalid parameter was specified. *
*/ int mdb_set_relctx(MDB_txn *txn, MDB_dbi dbi, void *ctx); /** @brief Get items from a database. * * This function retrieves key/data pairs from the database. The address * and length of the data associated with the specified \b key are returned * in the structure to which \b data refers. * If the database supports duplicate keys (#MDB_DUPSORT) then the * first data item for the key will be returned. Retrieval of other * items requires the use of #mdb_cursor_get(). * * @note The memory pointed to by the returned values is owned by the * database. The caller need not dispose of the memory, and may not * modify it in any way. For values returned in a read-only transaction * any modification attempts will cause a SIGSEGV. * @note Values returned from the database are valid only until a * subsequent update operation, or the end of the transaction. * @param[in] txn A transaction handle returned by #mdb_txn_begin() * @param[in] dbi A database handle returned by #mdb_dbi_open() * @param[in] key The key to search for in the database * @param[out] data The data corresponding to the key * @return A non-zero error value on failure and 0 on success. Some possible * errors are: *
    *
  • #MDB_NOTFOUND - the key was not in the database. *
  • EINVAL - an invalid parameter was specified. *
*/ int mdb_get(MDB_txn *txn, MDB_dbi dbi, MDB_val *key, MDB_val *data); /** @brief Store items into a database. * * This function stores key/data pairs in the database. The default behavior * is to enter the new key/data pair, replacing any previously existing key * if duplicates are disallowed, or adding a duplicate data item if * duplicates are allowed (#MDB_DUPSORT). * @param[in] txn A transaction handle returned by #mdb_txn_begin() * @param[in] dbi A database handle returned by #mdb_dbi_open() * @param[in] key The key to store in the database * @param[in,out] data The data to store * @param[in] flags Special options for this operation. This parameter * must be set to 0 or by bitwise OR'ing together one or more of the * values described here. *
    *
  • #MDB_NODUPDATA - enter the new key/data pair only if it does not * already appear in the database. This flag may only be specified * if the database was opened with #MDB_DUPSORT. The function will * return #MDB_KEYEXIST if the key/data pair already appears in the * database. *
  • #MDB_NOOVERWRITE - enter the new key/data pair only if the key * does not already appear in the database. The function will return * #MDB_KEYEXIST if the key already appears in the database, even if * the database supports duplicates (#MDB_DUPSORT). The \b data * parameter will be set to point to the existing item. *
  • #MDB_RESERVE - reserve space for data of the given size, but * don't copy the given data. Instead, return a pointer to the * reserved space, which the caller can fill in later - before * the next update operation or the transaction ends. This saves * an extra memcpy if the data is being generated later. * LMDB does nothing else with this memory, the caller is expected * to modify all of the space requested. *
  • #MDB_APPEND - append the given key/data pair to the end of the * database. This option allows fast bulk loading when keys are * already known to be in the correct order. Loading unsorted keys * with this flag will cause a #MDB_KEYEXIST error. *
  • #MDB_APPENDDUP - as above, but for sorted dup data. *
* @return A non-zero error value on failure and 0 on success. Some possible * errors are: *
    *
  • #MDB_MAP_FULL - the database is full, see #mdb_env_set_mapsize(). *
  • #MDB_TXN_FULL - the transaction has too many dirty pages. *
  • EACCES - an attempt was made to write in a read-only transaction. *
  • EINVAL - an invalid parameter was specified. *
*/ int mdb_put(MDB_txn *txn, MDB_dbi dbi, MDB_val *key, MDB_val *data, unsigned int flags); /** @brief Delete items from a database. * * This function removes key/data pairs from the database. * If the database does not support sorted duplicate data items * (#MDB_DUPSORT) the data parameter is ignored. * If the database supports sorted duplicates and the data parameter * is NULL, all of the duplicate data items for the key will be * deleted. Otherwise, if the data parameter is non-NULL * only the matching data item will be deleted. * This function will return #MDB_NOTFOUND if the specified key/data * pair is not in the database. * @param[in] txn A transaction handle returned by #mdb_txn_begin() * @param[in] dbi A database handle returned by #mdb_dbi_open() * @param[in] key The key to delete from the database * @param[in] data The data to delete * @return A non-zero error value on failure and 0 on success. Some possible * errors are: *
    *
  • EACCES - an attempt was made to write in a read-only transaction. *
  • EINVAL - an invalid parameter was specified. *
*/ int mdb_del(MDB_txn *txn, MDB_dbi dbi, MDB_val *key, MDB_val *data); /** @brief Create a cursor handle. * * A cursor is associated with a specific transaction and database. * A cursor cannot be used when its database handle is closed. Nor * when its transaction has ended, except with #mdb_cursor_renew(). * It can be discarded with #mdb_cursor_close(). * A cursor in a write-transaction can be closed before its transaction * ends, and will otherwise be closed when its transaction ends. * A cursor in a read-only transaction must be closed explicitly, before * or after its transaction ends. It can be reused with * #mdb_cursor_renew() before finally closing it. * @note Earlier documentation said that cursors in every transaction * were closed when the transaction committed or aborted. * @param[in] txn A transaction handle returned by #mdb_txn_begin() * @param[in] dbi A database handle returned by #mdb_dbi_open() * @param[out] cursor Address where the new #MDB_cursor handle will be stored * @return A non-zero error value on failure and 0 on success. Some possible * errors are: *
    *
  • EINVAL - an invalid parameter was specified. *
*/ int mdb_cursor_open(MDB_txn *txn, MDB_dbi dbi, MDB_cursor **cursor); /** @brief Close a cursor handle. * * The cursor handle will be freed and must not be used again after this call. * Its transaction must still be live if it is a write-transaction. * @param[in] cursor A cursor handle returned by #mdb_cursor_open() */ void mdb_cursor_close(MDB_cursor *cursor); /** @brief Renew a cursor handle. * * A cursor is associated with a specific transaction and database. * Cursors that are only used in read-only * transactions may be re-used, to avoid unnecessary malloc/free overhead. * The cursor may be associated with a new read-only transaction, and * referencing the same database handle as it was created with. * This may be done whether the previous transaction is live or dead. * @param[in] txn A transaction handle returned by #mdb_txn_begin() * @param[in] cursor A cursor handle returned by #mdb_cursor_open() * @return A non-zero error value on failure and 0 on success. Some possible * errors are: *
    *
  • EINVAL - an invalid parameter was specified. *
*/ int mdb_cursor_renew(MDB_txn *txn, MDB_cursor *cursor); /** @brief Return the cursor's transaction handle. * * @param[in] cursor A cursor handle returned by #mdb_cursor_open() */ MDB_txn *mdb_cursor_txn(MDB_cursor *cursor); /** @brief Return the cursor's database handle. * * @param[in] cursor A cursor handle returned by #mdb_cursor_open() */ MDB_dbi mdb_cursor_dbi(MDB_cursor *cursor); /** @brief Retrieve by cursor. * * This function retrieves key/data pairs from the database. The address and length * of the key are returned in the object to which \b key refers (except for the * case of the #MDB_SET option, in which the \b key object is unchanged), and * the address and length of the data are returned in the object to which \b data * refers. * See #mdb_get() for restrictions on using the output values. * @param[in] cursor A cursor handle returned by #mdb_cursor_open() * @param[in,out] key The key for a retrieved item * @param[in,out] data The data of a retrieved item * @param[in] op A cursor operation #MDB_cursor_op * @return A non-zero error value on failure and 0 on success. Some possible * errors are: *
    *
  • #MDB_NOTFOUND - no matching key found. *
  • EINVAL - an invalid parameter was specified. *
*/ int mdb_cursor_get(MDB_cursor *cursor, MDB_val *key, MDB_val *data, MDB_cursor_op op); /** @brief Store by cursor. * * This function stores key/data pairs into the database. * The cursor is positioned at the new item, or on failure usually near it. * @note Earlier documentation incorrectly said errors would leave the * state of the cursor unchanged. * @param[in] cursor A cursor handle returned by #mdb_cursor_open() * @param[in] key The key operated on. * @param[in] data The data operated on. * @param[in] flags Options for this operation. This parameter * must be set to 0 or one of the values described here. *
    *
  • #MDB_CURRENT - replace the item at the current cursor position. * The \b key parameter must still be provided, and must match it. * If using sorted duplicates (#MDB_DUPSORT) the data item must still * sort into the same place. This is intended to be used when the * new data is the same size as the old. Otherwise it will simply * perform a delete of the old record followed by an insert. *
  • #MDB_NODUPDATA - enter the new key/data pair only if it does not * already appear in the database. This flag may only be specified * if the database was opened with #MDB_DUPSORT. The function will * return #MDB_KEYEXIST if the key/data pair already appears in the * database. *
  • #MDB_NOOVERWRITE - enter the new key/data pair only if the key * does not already appear in the database. The function will return * #MDB_KEYEXIST if the key already appears in the database, even if * the database supports duplicates (#MDB_DUPSORT). *
  • #MDB_RESERVE - reserve space for data of the given size, but * don't copy the given data. Instead, return a pointer to the * reserved space, which the caller can fill in later. This saves * an extra memcpy if the data is being generated later. *
  • #MDB_APPEND - append the given key/data pair to the end of the * database. No key comparisons are performed. This option allows * fast bulk loading when keys are already known to be in the * correct order. Loading unsorted keys with this flag will cause * data corruption. *
  • #MDB_APPENDDUP - as above, but for sorted dup data. *
  • #MDB_MULTIPLE - store multiple contiguous data elements in a * single request. This flag may only be specified if the database * was opened with #MDB_DUPFIXED. The \b data argument must be an * array of two MDB_vals. The mv_size of the first MDB_val must be * the size of a single data element. The mv_data of the first MDB_val * must point to the beginning of the array of contiguous data elements. * The mv_size of the second MDB_val must be the count of the number * of data elements to store. On return this field will be set to * the count of the number of elements actually written. The mv_data * of the second MDB_val is unused. *
* @return A non-zero error value on failure and 0 on success. Some possible * errors are: *
    *
  • #MDB_MAP_FULL - the database is full, see #mdb_env_set_mapsize(). *
  • #MDB_TXN_FULL - the transaction has too many dirty pages. *
  • EACCES - an attempt was made to write in a read-only transaction. *
  • EINVAL - an invalid parameter was specified. *
*/ int mdb_cursor_put(MDB_cursor *cursor, MDB_val *key, MDB_val *data, unsigned int flags); /** @brief Delete current key/data pair * * This function deletes the key/data pair to which the cursor refers. * @param[in] cursor A cursor handle returned by #mdb_cursor_open() * @param[in] flags Options for this operation. This parameter * must be set to 0 or one of the values described here. *
    *
  • #MDB_NODUPDATA - delete all of the data items for the current key. * This flag may only be specified if the database was opened with #MDB_DUPSORT. *
* @return A non-zero error value on failure and 0 on success. Some possible * errors are: *
    *
  • EACCES - an attempt was made to write in a read-only transaction. *
  • EINVAL - an invalid parameter was specified. *
*/ int mdb_cursor_del(MDB_cursor *cursor, unsigned int flags); /** @brief Return count of duplicates for current key. * * This call is only valid on databases that support sorted duplicate * data items #MDB_DUPSORT. * @param[in] cursor A cursor handle returned by #mdb_cursor_open() * @param[out] countp Address where the count will be stored * @return A non-zero error value on failure and 0 on success. Some possible * errors are: *
    *
  • EINVAL - cursor is not initialized, or an invalid parameter was specified. *
*/ int mdb_cursor_count(MDB_cursor *cursor, size_t *countp); /** @brief Compare two data items according to a particular database. * * This returns a comparison as if the two data items were keys in the * specified database. * @param[in] txn A transaction handle returned by #mdb_txn_begin() * @param[in] dbi A database handle returned by #mdb_dbi_open() * @param[in] a The first item to compare * @param[in] b The second item to compare * @return < 0 if a < b, 0 if a == b, > 0 if a > b */ int mdb_cmp(MDB_txn *txn, MDB_dbi dbi, const MDB_val *a, const MDB_val *b); /** @brief Compare two data items according to a particular database. * * This returns a comparison as if the two items were data items of * the specified database. The database must have the #MDB_DUPSORT flag. * @param[in] txn A transaction handle returned by #mdb_txn_begin() * @param[in] dbi A database handle returned by #mdb_dbi_open() * @param[in] a The first item to compare * @param[in] b The second item to compare * @return < 0 if a < b, 0 if a == b, > 0 if a > b */ int mdb_dcmp(MDB_txn *txn, MDB_dbi dbi, const MDB_val *a, const MDB_val *b); /** @brief A callback function used to print a message from the library. * * @param[in] msg The string to be printed. * @param[in] ctx An arbitrary context pointer for the callback. * @return < 0 on failure, >= 0 on success. */ typedef int (MDB_msg_func)(const char *msg, void *ctx); /** @brief Dump the entries in the reader lock table. * * @param[in] env An environment handle returned by #mdb_env_create() * @param[in] func A #MDB_msg_func function * @param[in] ctx Anything the message function needs * @return < 0 on failure, >= 0 on success. */ int mdb_reader_list(MDB_env *env, MDB_msg_func *func, void *ctx); /** @brief Check for stale entries in the reader lock table. * * @param[in] env An environment handle returned by #mdb_env_create() * @param[out] dead Number of stale slots that were cleared * @return 0 on success, non-zero on failure. */ int mdb_reader_check(MDB_env *env, int *dead); /** @} */ #ifdef __cplusplus } #endif /** @page tools LMDB Command Line Tools The following describes the command line tools that are available for LMDB. \li \ref mdb_copy_1 \li \ref mdb_dump_1 \li \ref mdb_load_1 \li \ref mdb_stat_1 */ #endif /* _LMDB_H_ */ openldap-2.4.42+dfsg/libraries/liblmdb/tooltag0000644000175000017500000000115712563404150020011 0ustar ryanryan mdb_copy_1 mdb_copy - environment copy tool mdb_copy.1 mdb_dump_1 mdb_dump - environment export tool mdb_dump.1 mdb_load_1 mdb_load - environment import tool mdb_load.1 mdb_stat_1 mdb_stat - environment status tool mdb_stat.1 openldap-2.4.42+dfsg/libraries/liblmdb/midl.h0000644000175000017500000001302712563404150017512 0ustar ryanryan/** @file midl.h * @brief LMDB ID List header file. * * This file was originally part of back-bdb but has been * modified for use in libmdb. Most of the macros defined * in this file are unused, just left over from the original. * * This file is only used internally in libmdb and its definitions * are not exposed publicly. */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 2000-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #ifndef _MDB_MIDL_H_ #define _MDB_MIDL_H_ #include #ifdef __cplusplus extern "C" { #endif /** @defgroup internal LMDB Internals * @{ */ /** @defgroup idls ID List Management * @{ */ /** A generic unsigned ID number. These were entryIDs in back-bdb. * Preferably it should have the same size as a pointer. */ typedef size_t MDB_ID; /** An IDL is an ID List, a sorted array of IDs. The first * element of the array is a counter for how many actual * IDs are in the list. In the original back-bdb code, IDLs are * sorted in ascending order. For libmdb IDLs are sorted in * descending order. */ typedef MDB_ID *MDB_IDL; /* IDL sizes - likely should be even bigger * limiting factors: sizeof(ID), thread stack size */ #define MDB_IDL_LOGN 16 /* DB_SIZE is 2^16, UM_SIZE is 2^17 */ #define MDB_IDL_DB_SIZE (1< openldap-2.4.42+dfsg/libraries/liblber/0000755000175000017500000000000012563404150016417 5ustar ryanryanopenldap-2.4.42+dfsg/libraries/liblber/Makefile.in0000644000175000017500000000255612563404150020474 0ustar ryanryan# LIBLBER # $OpenLDAP$ ## This work is part of OpenLDAP Software . ## ## Copyright 1998-2015 The OpenLDAP Foundation. ## All rights reserved. ## ## Redistribution and use in source and binary forms, with or without ## modification, are permitted only as authorized by the OpenLDAP ## Public License. ## ## A copy of this license is available in the file LICENSE in the ## top-level directory of the distribution or, alternatively, at ## . LIBRARY = liblber.la NT_SRCS = nt_err.c NT_OBJS = nt_err.lo UNIX_SRCS = stdio.c UNIX_OBJS = stdio.lo LIB_DEFS = -DLBER_LIBRARY SRCS= assert.c decode.c encode.c io.c bprint.c debug.c \ memory.c options.c sockbuf.c $(@PLAT@_SRCS) OBJS= assert.lo decode.lo encode.lo io.lo bprint.lo debug.lo \ memory.lo options.lo sockbuf.lo $(@PLAT@_OBJS) XSRCS= version.c PROGRAMS= dtest etest idtest LDAP_INCDIR= ../../include LDAP_LIBDIR= ../../libraries XLIBS = $(LIBRARY) $(LDAP_LIBLUTIL_A) XXLIBS = NT_LINK_LIBS = $(AC_LIBS) UNIX_LINK_LIBS = $(AC_LIBS) dtest: $(XLIBS) dtest.o $(LTLINK) -o $@ dtest.o $(LIBS) etest: $(XLIBS) etest.o $(LTLINK) -o $@ etest.o $(LIBS) idtest: $(XLIBS) idtest.o $(LTLINK) -o $@ idtest.o $(LIBS) install-local: FORCE -$(MKDIR) $(DESTDIR)$(libdir) $(LTINSTALL) $(INSTALLFLAGS) -m 644 $(LIBRARY) $(DESTDIR)$(libdir) $(LTFINISH) $(DESTDIR)$(libdir) openldap-2.4.42+dfsg/libraries/liblber/nt_err.c0000644000175000017500000000524312563404150020060 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #include "portable.h" #ifdef HAVE_WINSOCK2 #include #elif defined(HAVE_WINSOCK) #include #endif /* HAVE_WINSOCK(2) */ #define LBER_RETSTR( x ) case x: return #x; char *ber_pvt_wsa_err2string( int err ) { switch( err ) { LBER_RETSTR( WSAEINTR ) LBER_RETSTR( WSAEBADF ) LBER_RETSTR( WSAEACCES ) LBER_RETSTR( WSAEFAULT ) LBER_RETSTR( WSAEINVAL ) LBER_RETSTR( WSAEMFILE ) LBER_RETSTR( WSAEWOULDBLOCK ) LBER_RETSTR( WSAEINPROGRESS ) LBER_RETSTR( WSAEALREADY ) LBER_RETSTR( WSAENOTSOCK ) LBER_RETSTR( WSAEDESTADDRREQ ) LBER_RETSTR( WSAEMSGSIZE ) LBER_RETSTR( WSAEPROTOTYPE ) LBER_RETSTR( WSAENOPROTOOPT ) LBER_RETSTR( WSAEPROTONOSUPPORT ) LBER_RETSTR( WSAESOCKTNOSUPPORT ) LBER_RETSTR( WSAEOPNOTSUPP ) LBER_RETSTR( WSAEPFNOSUPPORT ) LBER_RETSTR( WSAEAFNOSUPPORT ) LBER_RETSTR( WSAEADDRINUSE ) LBER_RETSTR( WSAEADDRNOTAVAIL ) LBER_RETSTR( WSAENETDOWN ) LBER_RETSTR( WSAENETUNREACH ) LBER_RETSTR( WSAENETRESET ) LBER_RETSTR( WSAECONNABORTED ) LBER_RETSTR( WSAECONNRESET ) LBER_RETSTR( WSAENOBUFS ) LBER_RETSTR( WSAEISCONN ) LBER_RETSTR( WSAENOTCONN ) LBER_RETSTR( WSAESHUTDOWN ) LBER_RETSTR( WSAETOOMANYREFS ) LBER_RETSTR( WSAETIMEDOUT ) LBER_RETSTR( WSAECONNREFUSED ) LBER_RETSTR( WSAELOOP ) LBER_RETSTR( WSAENAMETOOLONG ) LBER_RETSTR( WSAEHOSTDOWN ) LBER_RETSTR( WSAEHOSTUNREACH ) LBER_RETSTR( WSAENOTEMPTY ) LBER_RETSTR( WSAEPROCLIM ) LBER_RETSTR( WSAEUSERS ) LBER_RETSTR( WSAEDQUOT ) LBER_RETSTR( WSAESTALE ) LBER_RETSTR( WSAEREMOTE ) LBER_RETSTR( WSASYSNOTREADY ) LBER_RETSTR( WSAVERNOTSUPPORTED ) LBER_RETSTR( WSANOTINITIALISED ) LBER_RETSTR( WSAEDISCON ) #ifdef HAVE_WINSOCK2 LBER_RETSTR( WSAENOMORE ) LBER_RETSTR( WSAECANCELLED ) LBER_RETSTR( WSAEINVALIDPROCTABLE ) LBER_RETSTR( WSAEINVALIDPROVIDER ) LBER_RETSTR( WSASYSCALLFAILURE ) LBER_RETSTR( WSASERVICE_NOT_FOUND ) LBER_RETSTR( WSATYPE_NOT_FOUND ) LBER_RETSTR( WSA_E_NO_MORE ) LBER_RETSTR( WSA_E_CANCELLED ) LBER_RETSTR( WSAEREFUSED ) #endif /* HAVE_WINSOCK2 */ LBER_RETSTR( WSAHOST_NOT_FOUND ) LBER_RETSTR( WSATRY_AGAIN ) LBER_RETSTR( WSANO_RECOVERY ) LBER_RETSTR( WSANO_DATA ) } return "unknown WSA error"; } openldap-2.4.42+dfsg/libraries/liblber/decode.c0000644000175000017500000005142512563404150020015 0ustar ryanryan/* decode.c - ber input decoding routines */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (c) 1990 Regents of the University of Michigan. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of Michigan at Ann Arbor. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. */ /* ACKNOWLEDGEMENTS: * This work was originally developed by the University of Michigan * (as part of U-MICH LDAP). */ #include "portable.h" #include #include #include #include #include #include "lber-int.h" /* out->bv_len should be the buffer size on input */ int ber_decode_oid( BerValue *in, BerValue *out ) { const unsigned char *der; unsigned long val; unsigned val1; ber_len_t i; char *ptr; assert( in != NULL ); assert( out != NULL ); /* need 4 chars/inbyte + \0 for input={7f 7f 7f...} */ if ( !out->bv_val || (out->bv_len+3)/4 <= in->bv_len ) return -1; ptr = NULL; der = (unsigned char *) in->bv_val; val = 0; for ( i=0; i < in->bv_len; i++ ) { val |= der[i] & 0x7f; if ( !( der[i] & 0x80 )) { if ( ptr == NULL ) { /* Initial "x.y": val=x*40+y, x<=2, y<40 if x<2 */ ptr = out->bv_val; val1 = (val < 80 ? val/40 : 2); val -= val1*40; ptr += sprintf( ptr, "%u", val1 ); } ptr += sprintf( ptr, ".%lu", val ); val = 0; } else if ( val - 1UL < LBER_OID_COMPONENT_MAX >> 7 ) { val <<= 7; } else { /* val would overflow, or is 0 from invalid initial 0x80 octet */ return -1; } } if ( ptr == NULL || val != 0 ) return -1; out->bv_len = ptr - out->bv_val; return 0; } /* Return tag, with *bv = rest of element (starting at length octets) */ static ber_tag_t ber_tag_and_rest( const BerElement *ber, struct berval *bv ) { ber_tag_t tag; ptrdiff_t rest; unsigned char *ptr; assert( ber != NULL ); assert( LBER_VALID( ber ) ); ptr = (unsigned char *) ber->ber_ptr; rest = (unsigned char *) ber->ber_end - ptr; if ( rest <= 0 ) { goto fail; } tag = ber->ber_tag; if ( (char *) ptr == ber->ber_buf ) { tag = *ptr; } ptr++; rest--; if ( (tag & LBER_BIG_TAG_MASK) != LBER_BIG_TAG_MASK ) { goto done; } do { if ( rest <= 0 ) { break; } tag <<= 8; tag |= *ptr++ & 0xffU; rest--; if ( ! (tag & LBER_MORE_TAG_MASK) ) { goto done; } } while ( tag <= (ber_tag_t)-1 / 256 ); fail: /* Error or unsupported tag size */ tag = LBER_DEFAULT; done: bv->bv_len = rest; bv->bv_val = (char *) ptr; return tag; } /* Return the tag - LBER_DEFAULT returned means trouble */ ber_tag_t ber_get_tag( BerElement *ber ) { struct berval bv; ber_tag_t tag = ber_tag_and_rest( ber, &bv ); ber->ber_ptr = bv.bv_val; return tag; } /* Return next element's tag and point *bv at its contents in-place */ ber_tag_t ber_peek_element( const BerElement *ber, struct berval *bv ) { ber_tag_t tag; ber_len_t len, rest; unsigned i; unsigned char *ptr; assert( bv != NULL ); /* * Any ber element looks like this: tag length contents. * Assuming everything's ok, we return the tag, and point * bv at the contents. * * Assumptions: * 1) definite lengths * 2) primitive encodings used whenever possible */ len = 0; /* * First, we read the tag. */ tag = ber_tag_and_rest( ber, bv ); rest = bv->bv_len; ptr = (unsigned char *) bv->bv_val; if ( tag == LBER_DEFAULT || rest == 0 ) { goto fail; } /* * Next, read the length. The first octet determines the length * of the length. If bit 8 is 0, the length is the short form, * otherwise if the octet != 0x80 it's the long form, otherwise * the ber element has the unsupported indefinite-length format. * Lengths that do not fit in a ber_len_t are not accepted. */ len = *ptr++; rest--; if ( len & 0x80U ) { len &= 0x7fU; if ( len - 1U > sizeof(ber_len_t) - 1U || rest < len ) { /* Indefinite-length/too long length/not enough data */ goto fail; } rest -= len; i = len; for( len = *ptr++ & 0xffU; --i; len |= *ptr++ & 0xffU ) { len <<= 8; } } /* BER element should have enough data left */ if( len > rest ) { fail: tag = LBER_DEFAULT; } bv->bv_len = len; bv->bv_val = (char *) ptr; return tag; } /* Move past next element, point *bv at it in-place, and return its tag. * The caller may \0-terminate *bv, as next octet is saved in ber->ber_tag. * Similar to ber_get_stringbv(ber, bv, LBER_BV_NOTERM) except on error. */ ber_tag_t ber_skip_element( BerElement *ber, struct berval *bv ) { ber_tag_t tag = ber_peek_element( ber, bv ); if ( tag != LBER_DEFAULT ) { ber->ber_ptr = bv->bv_val + bv->bv_len; ber->ber_tag = *(unsigned char *) ber->ber_ptr; } return tag; } ber_tag_t ber_peek_tag( BerElement *ber, ber_len_t *len ) { struct berval bv; ber_tag_t tag = ber_peek_element( ber, &bv ); *len = bv.bv_len; return tag; } ber_tag_t ber_skip_tag( BerElement *ber, ber_len_t *lenp ) { struct berval bv; ber_tag_t tag = ber_peek_element( ber, &bv ); ber->ber_ptr = bv.bv_val; ber->ber_tag = *(unsigned char *) ber->ber_ptr; *lenp = bv.bv_len; return tag; } ber_tag_t ber_get_int( BerElement *ber, ber_int_t *num ) { ber_tag_t tag; ber_len_t len; struct berval bv; assert( num != NULL ); tag = ber_skip_element( ber, &bv ); len = bv.bv_len; if ( tag == LBER_DEFAULT || len > sizeof(ber_int_t) ) { return LBER_DEFAULT; } /* parse two's complement integer */ if( len ) { unsigned char *buf = (unsigned char *) bv.bv_val; ber_len_t i; ber_int_t netnum = buf[0] & 0xff; /* sign extend */ netnum = (netnum ^ 0x80) - 0x80; /* shift in the bytes */ for( i = 1; i < len; i++ ) { netnum = (netnum << 8 ) | buf[i]; } *num = netnum; } else { *num = 0; } return tag; } ber_tag_t ber_get_enum( BerElement *ber, ber_int_t *num ) { return ber_get_int( ber, num ); } ber_tag_t ber_get_stringb( BerElement *ber, char *buf, ber_len_t *len ) { struct berval bv; ber_tag_t tag; if ( (tag = ber_skip_element( ber, &bv )) == LBER_DEFAULT ) { return LBER_DEFAULT; } /* must fit within allocated space with termination */ if ( bv.bv_len >= *len ) { return LBER_DEFAULT; } memcpy( buf, bv.bv_val, bv.bv_len ); buf[bv.bv_len] = '\0'; *len = bv.bv_len; return tag; } /* Definitions for get_string vector * * ChArray, BvArray, and BvVec are self-explanatory. * BvOff is a struct berval embedded in an array of larger structures * of siz bytes at off bytes from the beginning of the struct. */ enum bgbvc { ChArray, BvArray, BvVec, BvOff }; /* Use this single cookie for state, to keep actual * stack use to the absolute minimum. */ typedef struct bgbvr { const enum bgbvc choice; const int option; /* (ALLOC unless BvOff) | (STRING if ChArray) */ ber_len_t siz; /* input array element size, output count */ ber_len_t off; /* BvOff offset to the struct berval */ void *result; } bgbvr; static ber_tag_t ber_get_stringbvl( BerElement *ber, bgbvr *b ) { int i = 0, n; ber_tag_t tag; ber_len_t tot_size = 0, siz = b->siz; char *last, *orig; struct berval bv, *bvp = NULL; union stringbvl_u { char **ca; /* ChArray */ BerVarray ba; /* BvArray */ struct berval **bv; /* BvVec */ char *bo; /* BvOff */ } res; tag = ber_skip_tag( ber, &bv.bv_len ); if ( tag != LBER_DEFAULT ) { tag = 0; orig = ber->ber_ptr; last = orig + bv.bv_len; for ( ; ber->ber_ptr < last; i++, tot_size += siz ) { if ( ber_skip_element( ber, &bv ) == LBER_DEFAULT ) break; } if ( ber->ber_ptr != last ) { i = 0; tag = LBER_DEFAULT; } ber->ber_ptr = orig; ber->ber_tag = *(unsigned char *) orig; } b->siz = i; if ( i == 0 ) { return tag; } /* Allocate and NULL-terminate the result vector */ b->result = ber_memalloc_x( tot_size + siz, ber->ber_memctx ); if ( b->result == NULL ) { return LBER_DEFAULT; } switch (b->choice) { case ChArray: res.ca = b->result; res.ca[i] = NULL; break; case BvArray: res.ba = b->result; res.ba[i].bv_val = NULL; break; case BvVec: res.bv = b->result; res.bv[i] = NULL; break; case BvOff: res.bo = (char *) b->result + b->off; ((struct berval *) (res.bo + tot_size))->bv_val = NULL; tot_size = 0; break; } n = 0; do { tag = ber_get_stringbv( ber, &bv, b->option ); if ( tag == LBER_DEFAULT ) { goto failed; } /* store my result */ switch (b->choice) { case ChArray: res.ca[n] = bv.bv_val; break; case BvArray: res.ba[n] = bv; break; case BvVec: bvp = ber_memalloc_x( sizeof( struct berval ), ber->ber_memctx ); if ( !bvp ) { ber_memfree_x( bv.bv_val, ber->ber_memctx ); goto failed; } res.bv[n] = bvp; *bvp = bv; break; case BvOff: *(struct berval *)(res.bo + tot_size) = bv; tot_size += siz; break; } } while (++n < i); return tag; failed: if (b->choice != BvOff) { /* BvOff does not have LBER_BV_ALLOC set */ while (--n >= 0) { switch(b->choice) { case ChArray: ber_memfree_x(res.ca[n], ber->ber_memctx); break; case BvArray: ber_memfree_x(res.ba[n].bv_val, ber->ber_memctx); break; case BvVec: ber_memfree_x(res.bv[n]->bv_val, ber->ber_memctx); ber_memfree_x(res.bv[n], ber->ber_memctx); break; default: break; } } } ber_memfree_x(b->result, ber->ber_memctx); b->result = NULL; return LBER_DEFAULT; } ber_tag_t ber_get_stringbv( BerElement *ber, struct berval *bv, int option ) { ber_tag_t tag; char *data; tag = ber_skip_element( ber, bv ); if ( tag == LBER_DEFAULT || (( option & LBER_BV_STRING ) && bv->bv_len && memchr( bv->bv_val, 0, bv->bv_len - 1 ))) { bv->bv_val = NULL; return LBER_DEFAULT; } data = bv->bv_val; if ( option & LBER_BV_ALLOC ) { bv->bv_val = (char *) ber_memalloc_x( bv->bv_len + 1, ber->ber_memctx ); if ( bv->bv_val == NULL ) { return LBER_DEFAULT; } if ( bv->bv_len != 0 ) { memcpy( bv->bv_val, data, bv->bv_len ); } data = bv->bv_val; } if ( !( option & LBER_BV_NOTERM )) data[bv->bv_len] = '\0'; return tag; } ber_tag_t ber_get_stringbv_null( BerElement *ber, struct berval *bv, int option ) { ber_tag_t tag; char *data; tag = ber_skip_element( ber, bv ); if ( tag == LBER_DEFAULT || bv->bv_len == 0 ) { bv->bv_val = NULL; return tag; } if (( option & LBER_BV_STRING ) && memchr( bv->bv_val, 0, bv->bv_len - 1 )) { bv->bv_val = NULL; return LBER_DEFAULT; } data = bv->bv_val; if ( option & LBER_BV_ALLOC ) { bv->bv_val = (char *) ber_memalloc_x( bv->bv_len + 1, ber->ber_memctx ); if ( bv->bv_val == NULL ) { return LBER_DEFAULT; } memcpy( bv->bv_val, data, bv->bv_len ); data = bv->bv_val; } if ( !( option & LBER_BV_NOTERM )) data[bv->bv_len] = '\0'; return tag; } ber_tag_t ber_get_stringa( BerElement *ber, char **buf ) { BerValue bv; ber_tag_t tag; assert( buf != NULL ); tag = ber_get_stringbv( ber, &bv, LBER_BV_ALLOC | LBER_BV_STRING ); *buf = bv.bv_val; return tag; } ber_tag_t ber_get_stringa_null( BerElement *ber, char **buf ) { BerValue bv; ber_tag_t tag; assert( buf != NULL ); tag = ber_get_stringbv_null( ber, &bv, LBER_BV_ALLOC | LBER_BV_STRING ); *buf = bv.bv_val; return tag; } ber_tag_t ber_get_stringal( BerElement *ber, struct berval **bv ) { ber_tag_t tag; assert( ber != NULL ); assert( bv != NULL ); *bv = (struct berval *) ber_memalloc_x( sizeof(struct berval), ber->ber_memctx ); if ( *bv == NULL ) { return LBER_DEFAULT; } tag = ber_get_stringbv( ber, *bv, LBER_BV_ALLOC ); if ( tag == LBER_DEFAULT ) { ber_memfree_x( *bv, ber->ber_memctx ); *bv = NULL; } return tag; } ber_tag_t ber_get_bitstringa( BerElement *ber, char **buf, ber_len_t *blen ) { ber_tag_t tag; struct berval data; unsigned char unusedbits; assert( buf != NULL ); assert( blen != NULL ); if ( (tag = ber_skip_element( ber, &data )) == LBER_DEFAULT ) { goto fail; } if ( --data.bv_len > (ber_len_t)-1 / 8 ) { goto fail; } unusedbits = *(unsigned char *) data.bv_val++; if ( unusedbits > 7 ) { goto fail; } if ( memchr( data.bv_val, 0, data.bv_len )) { goto fail; } *buf = (char *) ber_memalloc_x( data.bv_len, ber->ber_memctx ); if ( *buf == NULL ) { return LBER_DEFAULT; } memcpy( *buf, data.bv_val, data.bv_len ); *blen = data.bv_len * 8 - unusedbits; return tag; fail: *buf = NULL; return LBER_DEFAULT; } ber_tag_t ber_get_null( BerElement *ber ) { ber_len_t len; ber_tag_t tag = ber_skip_tag( ber, &len ); return( len == 0 ? tag : LBER_DEFAULT ); } ber_tag_t ber_get_boolean( BerElement *ber, ber_int_t *boolval ) { return ber_get_int( ber, boolval ); } ber_tag_t ber_first_element( BerElement *ber, ber_len_t *len, char **last ) { assert( last != NULL ); /* skip the sequence header, use the len to mark where to stop */ if ( ber_skip_tag( ber, len ) == LBER_DEFAULT ) { *last = NULL; return LBER_DEFAULT; } *last = ber->ber_ptr + *len; if ( *len == 0 ) { return LBER_DEFAULT; } return ber_peek_tag( ber, len ); } ber_tag_t ber_next_element( BerElement *ber, ber_len_t *len, LDAP_CONST char *last ) { assert( ber != NULL ); assert( last != NULL ); assert( LBER_VALID( ber ) ); if ( ber->ber_ptr >= last ) { return LBER_DEFAULT; } return ber_peek_tag( ber, len ); } /* VARARGS */ ber_tag_t ber_scanf ( BerElement *ber, LDAP_CONST char *fmt, ... ) { va_list ap; LDAP_CONST char *fmt_reset; char *s, **ss, ***sss; struct berval data, *bval, **bvp, ***bvpp; ber_int_t *i; ber_len_t *l; ber_tag_t *t; ber_tag_t rc; ber_len_t len; va_start( ap, fmt ); assert( ber != NULL ); assert( fmt != NULL ); assert( LBER_VALID( ber ) ); fmt_reset = fmt; if ( ber->ber_debug & (LDAP_DEBUG_TRACE|LDAP_DEBUG_BER)) { ber_log_printf( LDAP_DEBUG_TRACE, ber->ber_debug, "ber_scanf fmt (%s) ber:\n", fmt ); ber_log_dump( LDAP_DEBUG_BER, ber->ber_debug, ber, 1 ); } for ( rc = 0; *fmt && rc != LBER_DEFAULT; fmt++ ) { /* When this is modified, remember to update * the error-cleanup code below accordingly. */ switch ( *fmt ) { case '!': { /* Hook */ BERDecodeCallback *f; void *p; f = va_arg( ap, BERDecodeCallback * ); p = va_arg( ap, void * ); rc = (*f)( ber, p, 0 ); } break; case 'a': /* octet string - allocate storage as needed */ ss = va_arg( ap, char ** ); rc = ber_get_stringa( ber, ss ); break; case 'A': /* octet string - allocate storage as needed, * but return NULL if len == 0 */ ss = va_arg( ap, char ** ); rc = ber_get_stringa_null( ber, ss ); break; case 'b': /* boolean */ i = va_arg( ap, ber_int_t * ); rc = ber_get_boolean( ber, i ); break; case 'B': /* bit string - allocate storage as needed */ ss = va_arg( ap, char ** ); l = va_arg( ap, ber_len_t * ); /* for length, in bits */ rc = ber_get_bitstringa( ber, ss, l ); break; case 'e': /* enumerated */ case 'i': /* integer */ i = va_arg( ap, ber_int_t * ); rc = ber_get_int( ber, i ); break; case 'l': /* length of next item */ l = va_arg( ap, ber_len_t * ); rc = ber_peek_tag( ber, l ); break; case 'm': /* octet string in berval, in-place */ bval = va_arg( ap, struct berval * ); rc = ber_get_stringbv( ber, bval, 0 ); break; case 'M': /* bvoffarray - must include address of * a record len, and record offset. * number of records will be returned thru * len ptr on finish. parsed in-place. */ { bgbvr cookie = { BvOff, 0 }; bvp = va_arg( ap, struct berval ** ); l = va_arg( ap, ber_len_t * ); cookie.siz = *l; cookie.off = va_arg( ap, ber_len_t ); rc = ber_get_stringbvl( ber, &cookie ); *bvp = cookie.result; *l = cookie.siz; break; } case 'n': /* null */ rc = ber_get_null( ber ); break; case 'o': /* octet string in a supplied berval */ bval = va_arg( ap, struct berval * ); rc = ber_get_stringbv( ber, bval, LBER_BV_ALLOC ); break; case 'O': /* octet string - allocate & include length */ bvp = va_arg( ap, struct berval ** ); rc = ber_get_stringal( ber, bvp ); break; case 's': /* octet string - in a buffer */ s = va_arg( ap, char * ); l = va_arg( ap, ber_len_t * ); rc = ber_get_stringb( ber, s, l ); break; case 't': /* tag of next item */ t = va_arg( ap, ber_tag_t * ); *t = rc = ber_peek_tag( ber, &len ); break; case 'T': /* skip tag of next item */ t = va_arg( ap, ber_tag_t * ); *t = rc = ber_skip_tag( ber, &len ); break; case 'v': /* sequence of strings */ { bgbvr cookie = { ChArray, LBER_BV_ALLOC | LBER_BV_STRING, sizeof( char * ) }; rc = ber_get_stringbvl( ber, &cookie ); *(va_arg( ap, char *** )) = cookie.result; break; } case 'V': /* sequence of strings + lengths */ { bgbvr cookie = { BvVec, LBER_BV_ALLOC, sizeof( struct berval * ) }; rc = ber_get_stringbvl( ber, &cookie ); *(va_arg( ap, struct berval *** )) = cookie.result; break; } case 'W': /* bvarray */ { bgbvr cookie = { BvArray, LBER_BV_ALLOC, sizeof( struct berval ) }; rc = ber_get_stringbvl( ber, &cookie ); *(va_arg( ap, struct berval ** )) = cookie.result; break; } case 'x': /* skip the next element - whatever it is */ rc = ber_skip_element( ber, &data ); break; case '{': /* begin sequence */ case '[': /* begin set */ switch ( fmt[1] ) { case 'v': case 'V': case 'W': case 'M': break; default: rc = ber_skip_tag( ber, &len ); break; } break; case '}': /* end sequence */ case ']': /* end set */ break; default: if( ber->ber_debug ) { ber_log_printf( LDAP_DEBUG_ANY, ber->ber_debug, "ber_scanf: unknown fmt %c\n", *fmt ); } rc = LBER_DEFAULT; break; } } va_end( ap ); if ( rc == LBER_DEFAULT ) { /* * Error. Reclaim malloced memory that was given to the caller. * Set allocated pointers to NULL, "data length" outvalues to 0. */ va_start( ap, fmt ); for ( ; fmt_reset < fmt; fmt_reset++ ) { switch ( *fmt_reset ) { case '!': { /* Hook */ BERDecodeCallback *f; void *p; f = va_arg( ap, BERDecodeCallback * ); p = va_arg( ap, void * ); (void) (*f)( ber, p, 1 ); } break; case 'a': /* octet string - allocate storage as needed */ case 'A': ss = va_arg( ap, char ** ); ber_memfree_x( *ss, ber->ber_memctx ); *ss = NULL; break; case 'b': /* boolean */ case 'e': /* enumerated */ case 'i': /* integer */ (void) va_arg( ap, ber_int_t * ); break; case 'l': /* length of next item */ *(va_arg( ap, ber_len_t * )) = 0; break; case 'm': /* berval in-place */ bval = va_arg( ap, struct berval * ); BER_BVZERO( bval ); break; case 'M': /* BVoff array in-place */ bvp = va_arg( ap, struct berval ** ); ber_memfree_x( *bvp, ber->ber_memctx ); *bvp = NULL; *(va_arg( ap, ber_len_t * )) = 0; (void) va_arg( ap, ber_len_t ); break; case 'o': /* octet string in a supplied berval */ bval = va_arg( ap, struct berval * ); ber_memfree_x( bval->bv_val, ber->ber_memctx ); BER_BVZERO( bval ); break; case 'O': /* octet string - allocate & include length */ bvp = va_arg( ap, struct berval ** ); ber_bvfree_x( *bvp, ber->ber_memctx ); *bvp = NULL; break; case 's': /* octet string - in a buffer */ (void) va_arg( ap, char * ); *(va_arg( ap, ber_len_t * )) = 0; break; case 't': /* tag of next item */ case 'T': /* skip tag of next item */ (void) va_arg( ap, ber_tag_t * ); break; case 'B': /* bit string - allocate storage as needed */ ss = va_arg( ap, char ** ); ber_memfree_x( *ss, ber->ber_memctx ); *ss = NULL; *(va_arg( ap, ber_len_t * )) = 0; /* for length, in bits */ break; case 'v': /* sequence of strings */ sss = va_arg( ap, char *** ); ber_memvfree_x( (void **) *sss, ber->ber_memctx ); *sss = NULL; break; case 'V': /* sequence of strings + lengths */ bvpp = va_arg( ap, struct berval *** ); ber_bvecfree_x( *bvpp, ber->ber_memctx ); *bvpp = NULL; break; case 'W': /* BerVarray */ bvp = va_arg( ap, struct berval ** ); ber_bvarray_free_x( *bvp, ber->ber_memctx ); *bvp = NULL; break; case 'n': /* null */ case 'x': /* skip the next element - whatever it is */ case '{': /* begin sequence */ case '[': /* begin set */ case '}': /* end sequence */ case ']': /* end set */ break; default: /* format should be good */ assert( 0 ); } } va_end( ap ); } return rc; } openldap-2.4.42+dfsg/libraries/liblber/dtest.c0000644000175000017500000000530312563404150017707 0ustar ryanryan/* dtest.c - lber decoding test program */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (c) 1990 Regents of the University of Michigan. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of Michigan at Ann Arbor. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. */ /* ACKNOWLEDGEMENTS: * This work was originally developed by the University of Michigan * (as part of U-MICH LDAP). */ #include "portable.h" #include #include #include #include #include #include #ifdef HAVE_CONSOLE_H #include #endif #include static void usage( const char *name ) { fprintf( stderr, "usage: %s fmt\n", name ); } int main( int argc, char **argv ) { char *s; ber_tag_t tag; ber_len_t len; BerElement *ber; Sockbuf *sb; int fd; /* enable debugging */ int ival = -1; ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &ival ); if ( argc < 2 ) { usage( argv[0] ); return( EXIT_FAILURE ); } #ifdef HAVE_CONSOLE_H ccommand( &argv ); cshow( stdout ); #endif sb = ber_sockbuf_alloc(); fd = fileno( stdin ); ber_sockbuf_add_io( sb, &ber_sockbuf_io_fd, LBER_SBIOD_LEVEL_PROVIDER, (void *)&fd ); ber = ber_alloc_t(LBER_USE_DER); if( ber == NULL ) { perror( "ber_alloc_t" ); return( EXIT_FAILURE ); } for (;;) { tag = ber_get_next( sb, &len, ber); if( tag != LBER_ERROR ) break; if( errno == EWOULDBLOCK ) continue; if( errno == EAGAIN ) continue; perror( "ber_get_next" ); return( EXIT_FAILURE ); } printf("decode: message tag 0x%lx and length %ld\n", (unsigned long) tag, (long) len ); for( s = argv[1]; *s; s++ ) { char buf[128]; char fmt[2]; fmt[0] = *s; fmt[1] = '\0'; printf("decode: format %s\n", fmt ); len = sizeof(buf); tag = ber_scanf( ber, fmt, &buf[0], &len ); if( tag == LBER_ERROR ) { perror( "ber_scanf" ); return( EXIT_FAILURE ); } } ber_sockbuf_free( sb ); return( EXIT_SUCCESS ); } openldap-2.4.42+dfsg/libraries/liblber/io.c0000644000175000017500000003752212563404150017203 0ustar ryanryan/* io.c - ber general i/o routines */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (c) 1990 Regents of the University of Michigan. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of Michigan at Ann Arbor. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. */ /* ACKNOWLEDGEMENTS: * This work was originally developed by the University of Michigan * (as part of U-MICH LDAP). */ #include "portable.h" #include #include #include #include #include #include #include #ifdef HAVE_IO_H #include #endif #include "lber-int.h" #include "ldap_log.h" ber_slen_t ber_skip_data( BerElement *ber, ber_len_t len ) { ber_len_t actuallen, nleft; assert( ber != NULL ); assert( LBER_VALID( ber ) ); nleft = ber_pvt_ber_remaining( ber ); actuallen = nleft < len ? nleft : len; ber->ber_ptr += actuallen; ber->ber_tag = *(unsigned char *)ber->ber_ptr; return( (ber_slen_t) actuallen ); } /* * Read from the ber buffer. The caller must maintain ber->ber_tag. * Do not use to read whole tags. See ber_get_tag() and ber_skip_data(). */ ber_slen_t ber_read( BerElement *ber, char *buf, ber_len_t len ) { ber_len_t actuallen, nleft; assert( ber != NULL ); assert( buf != NULL ); assert( LBER_VALID( ber ) ); nleft = ber_pvt_ber_remaining( ber ); actuallen = nleft < len ? nleft : len; AC_MEMCPY( buf, ber->ber_ptr, actuallen ); ber->ber_ptr += actuallen; return( (ber_slen_t) actuallen ); } /* * Write to the ber buffer. * Note that ber_start_seqorset/ber_put_seqorset() bypass ber_write(). */ ber_slen_t ber_write( BerElement *ber, LDAP_CONST char *buf, ber_len_t len, int zero ) /* nonzero is unsupported from OpenLDAP 2.4.18 */ { char **p; assert( ber != NULL ); assert( buf != NULL ); assert( LBER_VALID( ber ) ); if ( zero != 0 ) { ber_log_printf( LDAP_DEBUG_ANY, ber->ber_debug, "%s", "ber_write: nonzero 4th argument not supported\n" ); return( -1 ); } p = ber->ber_sos_ptr == NULL ? &ber->ber_ptr : &ber->ber_sos_ptr; if ( len > (ber_len_t) (ber->ber_end - *p) ) { if ( ber_realloc( ber, len ) != 0 ) return( -1 ); } AC_MEMCPY( *p, buf, len ); *p += len; return( (ber_slen_t) len ); } /* Resize the ber buffer */ int ber_realloc( BerElement *ber, ber_len_t len ) { ber_len_t total, offset, sos_offset; char *buf; assert( ber != NULL ); assert( LBER_VALID( ber ) ); /* leave room for ber_flatten() to \0-terminate ber_buf */ if ( ++len == 0 ) { return( -1 ); } total = ber_pvt_ber_total( ber ); #define LBER_EXBUFSIZ 4060 /* a few words less than 2^N for binary buddy */ #if defined( LBER_EXBUFSIZ ) && LBER_EXBUFSIZ > 0 # ifndef notdef /* don't realloc by small amounts */ total += len < LBER_EXBUFSIZ ? LBER_EXBUFSIZ : len; # else { /* not sure what value this adds. reduce fragmentation? */ ber_len_t have = (total + (LBER_EXBUFSIZE - 1)) / LBER_EXBUFSIZ; ber_len_t need = (len + (LBER_EXBUFSIZ - 1)) / LBER_EXBUFSIZ; total = ( have + need ) * LBER_EXBUFSIZ; } # endif #else total += len; /* realloc just what's needed */ #endif if ( total < len || total > (ber_len_t)-1 / 2 /* max ber_slen_t */ ) { return( -1 ); } buf = ber->ber_buf; offset = ber->ber_ptr - buf; sos_offset = ber->ber_sos_ptr ? ber->ber_sos_ptr - buf : 0; /* if ber_sos_ptr != NULL, it is > ber_buf so that sos_offset > 0 */ buf = (char *) ber_memrealloc_x( buf, total, ber->ber_memctx ); if ( buf == NULL ) { return( -1 ); } ber->ber_buf = buf; ber->ber_end = buf + total; ber->ber_ptr = buf + offset; if ( sos_offset ) ber->ber_sos_ptr = buf + sos_offset; return( 0 ); } void ber_free_buf( BerElement *ber ) { assert( LBER_VALID( ber ) ); if ( ber->ber_buf) ber_memfree_x( ber->ber_buf, ber->ber_memctx ); ber->ber_buf = NULL; ber->ber_sos_ptr = NULL; ber->ber_valid = LBER_UNINITIALIZED; } void ber_free( BerElement *ber, int freebuf ) { if( ber == NULL ) { LDAP_MEMORY_DEBUG_ASSERT( ber != NULL ); return; } if( freebuf ) ber_free_buf( ber ); ber_memfree_x( (char *) ber, ber->ber_memctx ); } int ber_flush( Sockbuf *sb, BerElement *ber, int freeit ) { return ber_flush2( sb, ber, freeit ? LBER_FLUSH_FREE_ON_SUCCESS : LBER_FLUSH_FREE_NEVER ); } int ber_flush2( Sockbuf *sb, BerElement *ber, int freeit ) { ber_len_t towrite; ber_slen_t rc; assert( sb != NULL ); assert( ber != NULL ); assert( SOCKBUF_VALID( sb ) ); assert( LBER_VALID( ber ) ); if ( ber->ber_rwptr == NULL ) { ber->ber_rwptr = ber->ber_buf; } towrite = ber->ber_ptr - ber->ber_rwptr; if ( sb->sb_debug ) { ber_log_printf( LDAP_DEBUG_TRACE, sb->sb_debug, "ber_flush2: %ld bytes to sd %ld%s\n", towrite, (long) sb->sb_fd, ber->ber_rwptr != ber->ber_buf ? " (re-flush)" : "" ); ber_log_bprint( LDAP_DEBUG_BER, sb->sb_debug, ber->ber_rwptr, towrite ); } while ( towrite > 0 ) { #ifdef LBER_TRICKLE sleep(1); rc = ber_int_sb_write( sb, ber->ber_rwptr, 1 ); #else rc = ber_int_sb_write( sb, ber->ber_rwptr, towrite ); #endif if ( rc <= 0 ) { if ( freeit & LBER_FLUSH_FREE_ON_ERROR ) ber_free( ber, 1 ); return -1; } towrite -= rc; ber->ber_rwptr += rc; } if ( freeit & LBER_FLUSH_FREE_ON_SUCCESS ) ber_free( ber, 1 ); return 0; } BerElement * ber_alloc_t( int options ) { BerElement *ber; ber = (BerElement *) LBER_CALLOC( 1, sizeof(BerElement) ); if ( ber == NULL ) { return NULL; } ber->ber_valid = LBER_VALID_BERELEMENT; ber->ber_tag = LBER_DEFAULT; ber->ber_options = options; ber->ber_debug = ber_int_debug; assert( LBER_VALID( ber ) ); return ber; } BerElement * ber_alloc( void ) /* deprecated */ { return ber_alloc_t( 0 ); } BerElement * der_alloc( void ) /* deprecated */ { return ber_alloc_t( LBER_USE_DER ); } BerElement * ber_dup( BerElement *ber ) { BerElement *new; assert( ber != NULL ); assert( LBER_VALID( ber ) ); if ( (new = ber_alloc_t( ber->ber_options )) == NULL ) { return NULL; } *new = *ber; assert( LBER_VALID( new ) ); return( new ); } void ber_init2( BerElement *ber, struct berval *bv, int options ) { assert( ber != NULL ); (void) memset( (char *)ber, '\0', sizeof( BerElement )); ber->ber_valid = LBER_VALID_BERELEMENT; ber->ber_tag = LBER_DEFAULT; ber->ber_options = (char) options; ber->ber_debug = ber_int_debug; if ( bv != NULL ) { ber->ber_buf = bv->bv_val; ber->ber_ptr = ber->ber_buf; ber->ber_end = ber->ber_buf + bv->bv_len; } assert( LBER_VALID( ber ) ); } /* OLD U-Mich ber_init() */ void ber_init_w_nullc( BerElement *ber, int options ) { ber_init2( ber, NULL, options ); } /* New C-API ber_init() */ /* This function constructs a BerElement containing a copy ** of the data in the bv argument. */ BerElement * ber_init( struct berval *bv ) { BerElement *ber; assert( bv != NULL ); if ( bv == NULL ) { return NULL; } ber = ber_alloc_t( 0 ); if( ber == NULL ) { /* allocation failed */ return NULL; } /* copy the data */ if ( ((ber_len_t) ber_write ( ber, bv->bv_val, bv->bv_len, 0 )) != bv->bv_len ) { /* write failed, so free and return NULL */ ber_free( ber, 1 ); return NULL; } ber_reset( ber, 1 ); /* reset the pointer to the start of the buffer */ return ber; } /* New C-API ber_flatten routine */ /* This routine allocates a struct berval whose contents are a BER ** encoding taken from the ber argument. The bvPtr pointer points to ** the returned berval. ** ** ber_flatten2 is the same, but uses a struct berval passed by ** the caller. If alloc is 0 the returned bv uses the ber buf directly. */ int ber_flatten2( BerElement *ber, struct berval *bv, int alloc ) { assert( bv != NULL ); if ( bv == NULL ) { return -1; } if ( ber == NULL ) { /* ber is null, create an empty berval */ bv->bv_val = NULL; bv->bv_len = 0; } else if ( ber->ber_sos_ptr != NULL ) { /* unmatched "{" and "}" */ return -1; } else { /* copy the berval */ ber_len_t len = ber_pvt_ber_write( ber ); if ( alloc ) { bv->bv_val = (char *) ber_memalloc_x( len + 1, ber->ber_memctx ); if ( bv->bv_val == NULL ) { return -1; } AC_MEMCPY( bv->bv_val, ber->ber_buf, len ); bv->bv_val[len] = '\0'; } else if ( ber->ber_buf != NULL ) { bv->bv_val = ber->ber_buf; bv->bv_val[len] = '\0'; } else { bv->bv_val = ""; } bv->bv_len = len; } return 0; } int ber_flatten( BerElement *ber, struct berval **bvPtr) { struct berval *bv; int rc; assert( bvPtr != NULL ); if(bvPtr == NULL) { return -1; } bv = ber_memalloc_x( sizeof(struct berval), ber->ber_memctx ); if ( bv == NULL ) { return -1; } rc = ber_flatten2(ber, bv, 1); if (rc == -1) { ber_memfree_x(bv, ber->ber_memctx); } else { *bvPtr = bv; } return rc; } void ber_reset( BerElement *ber, int was_writing ) { assert( ber != NULL ); assert( LBER_VALID( ber ) ); if ( was_writing ) { ber->ber_end = ber->ber_ptr; ber->ber_ptr = ber->ber_buf; } else { ber->ber_ptr = ber->ber_end; } ber->ber_rwptr = NULL; } /* * A rewrite of ber_get_next that can safely be called multiple times * for the same packet. It will simply continue where it stopped until * a full packet is read. */ #define LENSIZE 4 ber_tag_t ber_get_next( Sockbuf *sb, ber_len_t *len, BerElement *ber ) { assert( sb != NULL ); assert( len != NULL ); assert( ber != NULL ); assert( SOCKBUF_VALID( sb ) ); assert( LBER_VALID( ber ) ); if ( ber->ber_debug & LDAP_DEBUG_TRACE ) { ber_log_printf( LDAP_DEBUG_TRACE, ber->ber_debug, "ber_get_next\n" ); } /* * Any ber element looks like this: tag length contents. * Assuming everything's ok, we return the tag byte (we * can assume a single byte), return the length in len, * and the rest of the undecoded element in buf. * * Assumptions: * 1) small tags (less than 128) * 2) definite lengths * 3) primitive encodings used whenever possible * * The code also handles multi-byte tags. The first few bytes * of the message are read to check for multi-byte tags and * lengths. These bytes are temporarily stored in the ber_tag, * ber_len, and ber_usertag fields of the berelement until * tag/len parsing is complete. After this parsing, any leftover * bytes and the rest of the message are copied into the ber_buf. * * We expect tag and len to be at most 32 bits wide. */ if (ber->ber_rwptr == NULL) { assert( ber->ber_buf == NULL ); ber->ber_rwptr = (char *) &ber->ber_len-1; ber->ber_ptr = ber->ber_rwptr; ber->ber_tag = 0; } while (ber->ber_rwptr > (char *)&ber->ber_tag && ber->ber_rwptr < (char *)&ber->ber_len + LENSIZE*2) { ber_slen_t sblen; char buf[sizeof(ber->ber_len)-1]; ber_len_t tlen = 0; /* The tag & len can be at most 9 bytes; we try to read up to 8 here */ sock_errset(0); sblen=((char *)&ber->ber_len + LENSIZE*2 - 1)-ber->ber_rwptr; /* Trying to read the last len byte of a 9 byte tag+len */ if (sblen<1) sblen = 1; sblen=ber_int_sb_read( sb, ber->ber_rwptr, sblen ); if (sblen<=0) return LBER_DEFAULT; ber->ber_rwptr += sblen; /* We got at least one byte, try to parse the tag. */ if (ber->ber_ptr == (char *)&ber->ber_len-1) { ber_tag_t tag; unsigned char *p = (unsigned char *)ber->ber_ptr; tag = *p++; if ((tag & LBER_BIG_TAG_MASK) == LBER_BIG_TAG_MASK) { ber_len_t i; for (i=1; (char *)pber_rwptr; i++) { tag <<= 8; tag |= *p++; if (!(tag & LBER_MORE_TAG_MASK)) break; /* Is the tag too big? */ if (i == sizeof(ber_tag_t)-1) { sock_errset(ERANGE); return LBER_DEFAULT; } } /* Did we run out of bytes? */ if ((char *)p == ber->ber_rwptr) { sock_errset(EWOULDBLOCK); return LBER_DEFAULT; } } ber->ber_tag = tag; ber->ber_ptr = (char *)p; } if ( ber->ber_ptr == ber->ber_rwptr ) { sock_errset(EWOULDBLOCK); return LBER_DEFAULT; } /* Now look for the length */ if (*ber->ber_ptr & 0x80) { /* multi-byte */ int i; unsigned char *p = (unsigned char *)ber->ber_ptr; int llen = *p++ & 0x7f; if (llen > LENSIZE) { sock_errset(ERANGE); return LBER_DEFAULT; } /* Not enough bytes? */ if (ber->ber_rwptr - (char *)p < llen) { sock_errset(EWOULDBLOCK); return LBER_DEFAULT; } for (i=0; iber_ptr = (char *)p; } else { tlen = *(unsigned char *)ber->ber_ptr++; } /* Are there leftover data bytes inside ber->ber_len? */ if (ber->ber_ptr < (char *)&ber->ber_usertag) { if (ber->ber_rwptr < (char *)&ber->ber_usertag) { sblen = ber->ber_rwptr - ber->ber_ptr; } else { sblen = (char *)&ber->ber_usertag - ber->ber_ptr; } AC_MEMCPY(buf, ber->ber_ptr, sblen); ber->ber_ptr += sblen; } else { sblen = 0; } ber->ber_len = tlen; /* now fill the buffer. */ /* make sure length is reasonable */ if ( ber->ber_len == 0 ) { sock_errset(ERANGE); return LBER_DEFAULT; } if ( sb->sb_max_incoming && ber->ber_len > sb->sb_max_incoming ) { ber_log_printf( LDAP_DEBUG_CONNS, ber->ber_debug, "ber_get_next: sockbuf_max_incoming exceeded " "(%ld > %ld)\n", ber->ber_len, sb->sb_max_incoming ); sock_errset(ERANGE); return LBER_DEFAULT; } if (ber->ber_buf==NULL) { ber_len_t l = ber->ber_rwptr - ber->ber_ptr; /* ber->ber_ptr is always <= ber->ber->ber_rwptr. * make sure ber->ber_len agrees with what we've * already read. */ if ( ber->ber_len < sblen + l ) { sock_errset(ERANGE); return LBER_DEFAULT; } ber->ber_buf = (char *) ber_memalloc_x( ber->ber_len + 1, ber->ber_memctx ); if (ber->ber_buf==NULL) { return LBER_DEFAULT; } ber->ber_end = ber->ber_buf + ber->ber_len; if (sblen) { AC_MEMCPY(ber->ber_buf, buf, sblen); } if (l > 0) { AC_MEMCPY(ber->ber_buf + sblen, ber->ber_ptr, l); sblen += l; } *ber->ber_end = '\0'; ber->ber_ptr = ber->ber_buf; ber->ber_usertag = 0; if ((ber_len_t)sblen == ber->ber_len) { goto done; } ber->ber_rwptr = ber->ber_buf + sblen; } } if ((ber->ber_rwptr>=ber->ber_buf) && (ber->ber_rwptrber_end)) { ber_slen_t res; ber_slen_t to_go; to_go = ber->ber_end - ber->ber_rwptr; assert( to_go > 0 ); sock_errset(0); res = ber_int_sb_read( sb, ber->ber_rwptr, to_go ); if (res<=0) return LBER_DEFAULT; ber->ber_rwptr+=res; if (resber_rwptr = NULL; *len = ber->ber_len; if ( ber->ber_debug ) { ber_log_printf( LDAP_DEBUG_TRACE, ber->ber_debug, "ber_get_next: tag 0x%lx len %ld contents:\n", ber->ber_tag, ber->ber_len ); ber_log_dump( LDAP_DEBUG_BER, ber->ber_debug, ber, 1 ); } return (ber->ber_tag); } assert( 0 ); /* ber structure is messed up ?*/ return LBER_DEFAULT; } char * ber_start( BerElement* ber ) { return ber->ber_buf; } int ber_len( BerElement* ber ) { return ( ber->ber_end - ber->ber_buf ); } int ber_ptrlen( BerElement* ber ) { return ( ber->ber_ptr - ber->ber_buf ); } void ber_rewind ( BerElement * ber ) { ber->ber_rwptr = NULL; ber->ber_sos_ptr = NULL; ber->ber_end = ber->ber_ptr; ber->ber_ptr = ber->ber_buf; #if 0 /* TODO: Should we add this? */ ber->ber_tag = LBER_DEFAULT; ber->ber_usertag = 0; #endif } int ber_remaining( BerElement * ber ) { return ber_pvt_ber_remaining( ber ); } openldap-2.4.42+dfsg/libraries/liblber/sockbuf.c0000644000175000017500000005000712563404150020221 0ustar ryanryan/* sockbuf.c - i/o routines with support for adding i/o layers. */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #include "portable.h" #include #include #include #include #include #include #include #ifdef HAVE_IO_H #include #endif /* HAVE_IO_H */ #if defined( HAVE_FCNTL_H ) #include #endif #if defined( HAVE_SYS_FILIO_H ) #include #elif defined( HAVE_SYS_IOCTL_H ) #include #endif #include "lber-int.h" #ifndef LBER_MIN_BUFF_SIZE #define LBER_MIN_BUFF_SIZE 4096 #endif #ifndef LBER_MAX_BUFF_SIZE #define LBER_MAX_BUFF_SIZE (65536*256) #endif #ifndef LBER_DEFAULT_READAHEAD #define LBER_DEFAULT_READAHEAD 16384 #endif Sockbuf * ber_sockbuf_alloc( void ) { Sockbuf *sb; sb = LBER_CALLOC( 1, sizeof( Sockbuf ) ); if( sb == NULL ) return NULL; ber_int_sb_init( sb ); return sb; } void ber_sockbuf_free( Sockbuf *sb ) { assert( sb != NULL ); assert( SOCKBUF_VALID( sb ) ); ber_int_sb_close( sb ); ber_int_sb_destroy( sb ); LBER_FREE( sb ); } /* Return values: -1: error, 0: no operation performed or the answer is false, * 1: successful operation or the answer is true */ int ber_sockbuf_ctrl( Sockbuf *sb, int opt, void *arg ) { Sockbuf_IO_Desc *p; int ret = 0; assert( sb != NULL ); assert( SOCKBUF_VALID( sb ) ); switch ( opt ) { case LBER_SB_OPT_HAS_IO: p = sb->sb_iod; while ( p && p->sbiod_io != (Sockbuf_IO *)arg ) { p = p->sbiod_next; } if ( p ) { ret = 1; } break; case LBER_SB_OPT_GET_FD: if ( arg != NULL ) { *((ber_socket_t *)arg) = sb->sb_fd; } ret = ( sb->sb_fd == AC_SOCKET_INVALID ? -1 : 1); break; case LBER_SB_OPT_SET_FD: sb->sb_fd = *((ber_socket_t *)arg); ret = 1; break; case LBER_SB_OPT_SET_NONBLOCK: ret = ber_pvt_socket_set_nonblock( sb->sb_fd, arg != NULL) ? -1 : 1; break; case LBER_SB_OPT_DRAIN: { /* Drain the data source to enable possible errors (e.g. * TLS) to be propagated to the upper layers */ char buf[LBER_MIN_BUFF_SIZE]; do { ret = ber_int_sb_read( sb, buf, sizeof( buf ) ); } while ( ret == sizeof( buf ) ); ret = 1; } break; case LBER_SB_OPT_NEEDS_READ: ret = ( sb->sb_trans_needs_read ? 1 : 0 ); break; case LBER_SB_OPT_NEEDS_WRITE: ret = ( sb->sb_trans_needs_write ? 1 : 0 ); break; case LBER_SB_OPT_GET_MAX_INCOMING: if ( arg != NULL ) { *((ber_len_t *)arg) = sb->sb_max_incoming; } ret = 1; break; case LBER_SB_OPT_SET_MAX_INCOMING: sb->sb_max_incoming = *((ber_len_t *)arg); ret = 1; break; case LBER_SB_OPT_UNGET_BUF: #ifdef LDAP_PF_LOCAL_SENDMSG sb->sb_ungetlen = ((struct berval *)arg)->bv_len; if ( sb->sb_ungetlen <= sizeof( sb->sb_ungetbuf )) { AC_MEMCPY( sb->sb_ungetbuf, ((struct berval *)arg)->bv_val, sb->sb_ungetlen ); ret = 1; } else { sb->sb_ungetlen = 0; ret = -1; } #endif break; default: ret = sb->sb_iod->sbiod_io->sbi_ctrl( sb->sb_iod, opt, arg ); break; } return ret; } int ber_sockbuf_add_io( Sockbuf *sb, Sockbuf_IO *sbio, int layer, void *arg ) { Sockbuf_IO_Desc *d, *p, **q; assert( sb != NULL ); assert( SOCKBUF_VALID( sb ) ); if ( sbio == NULL ) { return -1; } q = &sb->sb_iod; p = *q; while ( p && p->sbiod_level > layer ) { q = &p->sbiod_next; p = *q; } d = LBER_MALLOC( sizeof( *d ) ); if ( d == NULL ) { return -1; } d->sbiod_level = layer; d->sbiod_sb = sb; d->sbiod_io = sbio; memset( &d->sbiod_pvt, '\0', sizeof( d->sbiod_pvt ) ); d->sbiod_next = p; *q = d; if ( sbio->sbi_setup != NULL && ( sbio->sbi_setup( d, arg ) < 0 ) ) { return -1; } return 0; } int ber_sockbuf_remove_io( Sockbuf *sb, Sockbuf_IO *sbio, int layer ) { Sockbuf_IO_Desc *p, **q; assert( sb != NULL ); assert( SOCKBUF_VALID( sb ) ); if ( sb->sb_iod == NULL ) { return -1; } q = &sb->sb_iod; while ( *q != NULL ) { p = *q; if ( layer == p->sbiod_level && p->sbiod_io == sbio ) { if ( p->sbiod_io->sbi_remove != NULL && p->sbiod_io->sbi_remove( p ) < 0 ) { return -1; } *q = p->sbiod_next; LBER_FREE( p ); break; } q = &p->sbiod_next; } return 0; } void ber_pvt_sb_buf_init( Sockbuf_Buf *buf ) { buf->buf_base = NULL; buf->buf_ptr = 0; buf->buf_end = 0; buf->buf_size = 0; } void ber_pvt_sb_buf_destroy( Sockbuf_Buf *buf ) { assert( buf != NULL); if (buf->buf_base) { LBER_FREE( buf->buf_base ); } ber_pvt_sb_buf_init( buf ); } int ber_pvt_sb_grow_buffer( Sockbuf_Buf *buf, ber_len_t minsize ) { ber_len_t pw; char *p; assert( buf != NULL ); for ( pw = LBER_MIN_BUFF_SIZE; pw < minsize; pw <<= 1 ) { if (pw > LBER_MAX_BUFF_SIZE) return -1; } if ( buf->buf_size < pw ) { p = LBER_REALLOC( buf->buf_base, pw ); if ( p == NULL ) return -1; buf->buf_base = p; buf->buf_size = pw; } return 0; } ber_len_t ber_pvt_sb_copy_out( Sockbuf_Buf *sbb, char *buf, ber_len_t len ) { ber_len_t max; assert( buf != NULL ); assert( sbb != NULL ); #if 0 assert( sbb->buf_size > 0 ); #endif max = sbb->buf_end - sbb->buf_ptr; max = ( max < len) ? max : len; if ( max ) { AC_MEMCPY( buf, sbb->buf_base + sbb->buf_ptr, max ); sbb->buf_ptr += max; if ( sbb->buf_ptr >= sbb->buf_end ) { sbb->buf_ptr = sbb->buf_end = 0; } } return max; } ber_slen_t ber_pvt_sb_do_write( Sockbuf_IO_Desc *sbiod, Sockbuf_Buf *buf_out ) { ber_len_t to_go; ber_slen_t ret; assert( sbiod != NULL ); assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); to_go = buf_out->buf_end - buf_out->buf_ptr; assert( to_go > 0 ); for(;;) { ret = LBER_SBIOD_WRITE_NEXT( sbiod, buf_out->buf_base + buf_out->buf_ptr, to_go ); #ifdef EINTR if ((ret<0) && (errno==EINTR)) continue; #endif break; } if ( ret <= 0 ) return ret; buf_out->buf_ptr += ret; if (buf_out->buf_ptr == buf_out->buf_end) { buf_out->buf_end = buf_out->buf_ptr = 0; } return ret; } int ber_pvt_socket_set_nonblock( ber_socket_t sd, int nb ) { #ifdef HAVE_FCNTL int flags = fcntl( sd, F_GETFL); if( nb ) { flags |= O_NONBLOCK; } else { flags &= ~O_NONBLOCK; } return fcntl( sd, F_SETFL, flags ); #elif defined( FIONBIO ) ioctl_t status = nb ? 1 : 0; return ioctl( sd, FIONBIO, &status ); #endif } int ber_int_sb_init( Sockbuf *sb ) { assert( sb != NULL); sb->sb_valid=LBER_VALID_SOCKBUF; sb->sb_options = 0; sb->sb_debug = ber_int_debug; sb->sb_fd = AC_SOCKET_INVALID; sb->sb_iod = NULL; sb->sb_trans_needs_read = 0; sb->sb_trans_needs_write = 0; assert( SOCKBUF_VALID( sb ) ); return 0; } int ber_int_sb_close( Sockbuf *sb ) { Sockbuf_IO_Desc *p; assert( sb != NULL); p = sb->sb_iod; while ( p ) { if ( p->sbiod_io->sbi_close && p->sbiod_io->sbi_close( p ) < 0 ) { return -1; } p = p->sbiod_next; } sb->sb_fd = AC_SOCKET_INVALID; return 0; } int ber_int_sb_destroy( Sockbuf *sb ) { Sockbuf_IO_Desc *p; assert( sb != NULL); assert( SOCKBUF_VALID( sb ) ); while ( sb->sb_iod ) { p = sb->sb_iod->sbiod_next; ber_sockbuf_remove_io( sb, sb->sb_iod->sbiod_io, sb->sb_iod->sbiod_level ); sb->sb_iod = p; } return ber_int_sb_init( sb ); } ber_slen_t ber_int_sb_read( Sockbuf *sb, void *buf, ber_len_t len ) { ber_slen_t ret; assert( buf != NULL ); assert( sb != NULL); assert( sb->sb_iod != NULL ); assert( SOCKBUF_VALID( sb ) ); for (;;) { ret = sb->sb_iod->sbiod_io->sbi_read( sb->sb_iod, buf, len ); #ifdef EINTR if ( ( ret < 0 ) && ( errno == EINTR ) ) continue; #endif break; } return ret; } ber_slen_t ber_int_sb_write( Sockbuf *sb, void *buf, ber_len_t len ) { ber_slen_t ret; assert( buf != NULL ); assert( sb != NULL); assert( sb->sb_iod != NULL ); assert( SOCKBUF_VALID( sb ) ); for (;;) { ret = sb->sb_iod->sbiod_io->sbi_write( sb->sb_iod, buf, len ); #ifdef EINTR if ( ( ret < 0 ) && ( errno == EINTR ) ) continue; #endif break; } return ret; } /* * Support for TCP */ static ber_slen_t sb_stream_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len ) { assert( sbiod != NULL); assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); #if defined(MACOS) /* * MacTCP/OpenTransport */ return tcpread( sbiod->sbiod_sb->sb_fd, 0, (unsigned char *)buf, len, NULL ); #elif defined( HAVE_PCNFS ) || \ defined( HAVE_WINSOCK ) || defined ( __BEOS__ ) /* * PCNFS (under DOS) */ /* * Windows Socket API (under DOS/Windows 3.x) */ /* * 32-bit Windows Socket API (under Windows NT or Windows 95) */ return recv( sbiod->sbiod_sb->sb_fd, buf, len, 0 ); #elif defined( HAVE_NCSA ) /* * NCSA Telnet TCP/IP stack (under DOS) */ return nread( sbiod->sbiod_sb->sb_fd, buf, len ); #else return read( sbiod->sbiod_sb->sb_fd, buf, len ); #endif } static ber_slen_t sb_stream_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len ) { assert( sbiod != NULL); assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); #if defined(MACOS) /* * MacTCP/OpenTransport */ #define MAX_WRITE 65535 return tcpwrite( sbiod->sbiod_sb->sb_fd, (unsigned char *)buf, (lensbiod_sb->sb_fd, buf, len, 0 ); #elif defined(HAVE_NCSA) return netwrite( sbiod->sbiod_sb->sb_fd, buf, len ); #elif defined(VMS) /* * VMS -- each write must be 64K or smaller */ #define MAX_WRITE 65535 return write( sbiod->sbiod_sb->sb_fd, buf, (lensbiod_sb->sb_fd, buf, len ); #endif } static int sb_stream_close( Sockbuf_IO_Desc *sbiod ) { assert( sbiod != NULL ); assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); if ( sbiod->sbiod_sb->sb_fd != AC_SOCKET_INVALID ) tcp_close( sbiod->sbiod_sb->sb_fd ); return 0; } /* The argument is a pointer to the socket descriptor */ static int sb_stream_setup( Sockbuf_IO_Desc *sbiod, void *arg ) { assert( sbiod != NULL ); if ( arg != NULL ) { sbiod->sbiod_sb->sb_fd = *((int *)arg); } return 0; } static int sb_stream_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) { /* This is an end IO descriptor */ return 0; } Sockbuf_IO ber_sockbuf_io_tcp = { sb_stream_setup, /* sbi_setup */ NULL, /* sbi_remove */ sb_stream_ctrl, /* sbi_ctrl */ sb_stream_read, /* sbi_read */ sb_stream_write, /* sbi_write */ sb_stream_close /* sbi_close */ }; /* * Support for readahead (UDP needs it) */ static int sb_rdahead_setup( Sockbuf_IO_Desc *sbiod, void *arg ) { Sockbuf_Buf *p; assert( sbiod != NULL ); p = LBER_MALLOC( sizeof( *p ) ); if ( p == NULL ) return -1; ber_pvt_sb_buf_init( p ); if ( arg == NULL ) { ber_pvt_sb_grow_buffer( p, LBER_DEFAULT_READAHEAD ); } else { ber_pvt_sb_grow_buffer( p, *((int *)arg) ); } sbiod->sbiod_pvt = p; return 0; } static int sb_rdahead_remove( Sockbuf_IO_Desc *sbiod ) { Sockbuf_Buf *p; assert( sbiod != NULL ); p = (Sockbuf_Buf *)sbiod->sbiod_pvt; if ( p->buf_ptr != p->buf_end ) return -1; ber_pvt_sb_buf_destroy( (Sockbuf_Buf *)(sbiod->sbiod_pvt) ); LBER_FREE( sbiod->sbiod_pvt ); sbiod->sbiod_pvt = NULL; return 0; } static ber_slen_t sb_rdahead_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len ) { Sockbuf_Buf *p; ber_slen_t bufptr = 0, ret, max; assert( sbiod != NULL ); assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); assert( sbiod->sbiod_next != NULL ); p = (Sockbuf_Buf *)sbiod->sbiod_pvt; assert( p->buf_size > 0 ); /* Are there anything left in the buffer? */ ret = ber_pvt_sb_copy_out( p, buf, len ); bufptr += ret; len -= ret; if ( len == 0 ) return bufptr; max = p->buf_size - p->buf_end; ret = 0; while ( max > 0 ) { ret = LBER_SBIOD_READ_NEXT( sbiod, p->buf_base + p->buf_end, max ); #ifdef EINTR if ( ( ret < 0 ) && ( errno == EINTR ) ) continue; #endif break; } if ( ret < 0 ) { return ( bufptr ? bufptr : ret ); } p->buf_end += ret; bufptr += ber_pvt_sb_copy_out( p, (char *) buf + bufptr, len ); return bufptr; } static ber_slen_t sb_rdahead_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len ) { assert( sbiod != NULL ); assert( sbiod->sbiod_next != NULL ); return LBER_SBIOD_WRITE_NEXT( sbiod, buf, len ); } static int sb_rdahead_close( Sockbuf_IO_Desc *sbiod ) { assert( sbiod != NULL ); /* Just erase the buffer */ ber_pvt_sb_buf_destroy((Sockbuf_Buf *)sbiod->sbiod_pvt); return 0; } static int sb_rdahead_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) { Sockbuf_Buf *p; p = (Sockbuf_Buf *)sbiod->sbiod_pvt; if ( opt == LBER_SB_OPT_DATA_READY ) { if ( p->buf_ptr != p->buf_end ) { return 1; } } else if ( opt == LBER_SB_OPT_SET_READAHEAD ) { if ( p->buf_size >= *((ber_len_t *)arg) ) { return 0; } return ( ber_pvt_sb_grow_buffer( p, *((int *)arg) ) ? -1 : 1 ); } return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg ); } Sockbuf_IO ber_sockbuf_io_readahead = { sb_rdahead_setup, /* sbi_setup */ sb_rdahead_remove, /* sbi_remove */ sb_rdahead_ctrl, /* sbi_ctrl */ sb_rdahead_read, /* sbi_read */ sb_rdahead_write, /* sbi_write */ sb_rdahead_close /* sbi_close */ }; /* * Support for simple file IO */ static ber_slen_t sb_fd_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len ) { assert( sbiod != NULL); assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); #ifdef LDAP_PF_LOCAL_SENDMSG if ( sbiod->sbiod_sb->sb_ungetlen ) { ber_len_t blen = sbiod->sbiod_sb->sb_ungetlen; if ( blen > len ) blen = len; AC_MEMCPY( buf, sbiod->sbiod_sb->sb_ungetbuf, blen ); buf = (char *) buf + blen; len -= blen; sbiod->sbiod_sb->sb_ungetlen -= blen; if ( sbiod->sbiod_sb->sb_ungetlen ) { AC_MEMCPY( sbiod->sbiod_sb->sb_ungetbuf, sbiod->sbiod_sb->sb_ungetbuf+blen, sbiod->sbiod_sb->sb_ungetlen ); } if ( len == 0 ) return blen; } #endif return read( sbiod->sbiod_sb->sb_fd, buf, len ); } static ber_slen_t sb_fd_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len ) { assert( sbiod != NULL); assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); return write( sbiod->sbiod_sb->sb_fd, buf, len ); } static int sb_fd_close( Sockbuf_IO_Desc *sbiod ) { assert( sbiod != NULL ); assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); if ( sbiod->sbiod_sb->sb_fd != AC_SOCKET_INVALID ) close( sbiod->sbiod_sb->sb_fd ); return 0; } /* The argument is a pointer to the file descriptor */ static int sb_fd_setup( Sockbuf_IO_Desc *sbiod, void *arg ) { assert( sbiod != NULL ); if ( arg != NULL ) sbiod->sbiod_sb->sb_fd = *((int *)arg); return 0; } static int sb_fd_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) { /* This is an end IO descriptor */ return 0; } Sockbuf_IO ber_sockbuf_io_fd = { sb_fd_setup, /* sbi_setup */ NULL, /* sbi_remove */ sb_fd_ctrl, /* sbi_ctrl */ sb_fd_read, /* sbi_read */ sb_fd_write, /* sbi_write */ sb_fd_close /* sbi_close */ }; /* * Debugging layer */ static int sb_debug_setup( Sockbuf_IO_Desc *sbiod, void *arg ) { assert( sbiod != NULL ); if ( arg == NULL ) arg = "sockbuf_"; sbiod->sbiod_pvt = LBER_MALLOC( strlen( arg ) + 1 ); if ( sbiod->sbiod_pvt == NULL ) return -1; strcpy( (char *)sbiod->sbiod_pvt, (char *)arg ); return 0; } static int sb_debug_remove( Sockbuf_IO_Desc *sbiod ) { assert( sbiod != NULL ); assert( sbiod->sbiod_pvt != NULL ); LBER_FREE( sbiod->sbiod_pvt ); sbiod->sbiod_pvt = NULL; return 0; } static int sb_debug_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) { return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg ); } static ber_slen_t sb_debug_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len ) { ber_slen_t ret; char ebuf[128]; ret = LBER_SBIOD_READ_NEXT( sbiod, buf, len ); if (sbiod->sbiod_sb->sb_debug & LDAP_DEBUG_PACKETS) { int err = sock_errno(); if ( ret < 0 ) { ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug, "%sread: want=%ld error=%s\n", (char *)sbiod->sbiod_pvt, (long)len, AC_STRERROR_R( err, ebuf, sizeof ebuf ) ); } else { ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug, "%sread: want=%ld, got=%ld\n", (char *)sbiod->sbiod_pvt, (long)len, (long)ret ); ber_log_bprint( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug, (const char *)buf, ret ); } sock_errset(err); } return ret; } static ber_slen_t sb_debug_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len ) { ber_slen_t ret; char ebuf[128]; ret = LBER_SBIOD_WRITE_NEXT( sbiod, buf, len ); if (sbiod->sbiod_sb->sb_debug & LDAP_DEBUG_PACKETS) { int err = sock_errno(); if ( ret < 0 ) { ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug, "%swrite: want=%ld error=%s\n", (char *)sbiod->sbiod_pvt, (long)len, AC_STRERROR_R( err, ebuf, sizeof ebuf ) ); } else { ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug, "%swrite: want=%ld, written=%ld\n", (char *)sbiod->sbiod_pvt, (long)len, (long)ret ); ber_log_bprint( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug, (const char *)buf, ret ); } sock_errset(err); } return ret; } Sockbuf_IO ber_sockbuf_io_debug = { sb_debug_setup, /* sbi_setup */ sb_debug_remove, /* sbi_remove */ sb_debug_ctrl, /* sbi_ctrl */ sb_debug_read, /* sbi_read */ sb_debug_write, /* sbi_write */ NULL /* sbi_close */ }; #ifdef LDAP_CONNECTIONLESS /* * Support for UDP (CLDAP) * * All I/O at this level must be atomic. For ease of use, the sb_readahead * must be used above this module. All data reads and writes are prefixed * with a sockaddr_storage containing the address of the remote entity. Upper levels * must read and write this sockaddr_storage before doing the usual ber_printf/scanf * operations on LDAP messages. */ static int sb_dgram_setup( Sockbuf_IO_Desc *sbiod, void *arg ) { assert( sbiod != NULL); assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); if ( arg != NULL ) sbiod->sbiod_sb->sb_fd = *((int *)arg); return 0; } static ber_slen_t sb_dgram_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len ) { ber_slen_t rc; ber_socklen_t addrlen; struct sockaddr *src; assert( sbiod != NULL ); assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); assert( buf != NULL ); addrlen = sizeof( struct sockaddr_storage ); src = buf; buf = (char *) buf + addrlen; len -= addrlen; rc = recvfrom( sbiod->sbiod_sb->sb_fd, buf, len, 0, src, &addrlen ); return rc > 0 ? rc+sizeof(struct sockaddr_storage) : rc; } static ber_slen_t sb_dgram_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len ) { ber_slen_t rc; struct sockaddr *dst; socklen_t dstsize; assert( sbiod != NULL ); assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); assert( buf != NULL ); dst = buf; buf = (char *) buf + sizeof( struct sockaddr_storage ); len -= sizeof( struct sockaddr_storage ); dstsize = dst->sa_family == AF_INET ? sizeof( struct sockaddr_in ) #ifdef LDAP_PF_INET6 : dst->sa_family == AF_INET6 ? sizeof( struct sockaddr_in6 ) #endif : sizeof( struct sockaddr_storage ); rc = sendto( sbiod->sbiod_sb->sb_fd, buf, len, 0, dst, dstsize ); if ( rc < 0 ) return -1; /* fake error if write was not atomic */ if (rc < len) { # ifdef EMSGSIZE errno = EMSGSIZE; # endif return -1; } rc = len + sizeof(struct sockaddr_storage); return rc; } static int sb_dgram_close( Sockbuf_IO_Desc *sbiod ) { assert( sbiod != NULL ); assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); if ( sbiod->sbiod_sb->sb_fd != AC_SOCKET_INVALID ) tcp_close( sbiod->sbiod_sb->sb_fd ); return 0; } static int sb_dgram_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) { /* This is an end IO descriptor */ return 0; } Sockbuf_IO ber_sockbuf_io_udp = { sb_dgram_setup, /* sbi_setup */ NULL, /* sbi_remove */ sb_dgram_ctrl, /* sbi_ctrl */ sb_dgram_read, /* sbi_read */ sb_dgram_write, /* sbi_write */ sb_dgram_close /* sbi_close */ }; #endif /* LDAP_CONNECTIONLESS */ openldap-2.4.42+dfsg/libraries/liblber/options.c0000644000175000017500000001315112563404150020257 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #include "portable.h" #include #include #include #include "lber-int.h" char ber_pvt_opt_on; /* used to get a non-NULL address for *_OPT_ON */ struct lber_options ber_int_options = { LBER_UNINITIALIZED, 0, 0 }; static BerMemoryFunctions ber_int_memory_fns_datum; int ber_get_option( void *item, int option, void *outvalue) { const BerElement *ber; const Sockbuf *sb; if(outvalue == NULL) { /* no place to get to */ ber_errno = LBER_ERROR_PARAM; return LBER_OPT_ERROR; } if(item == NULL) { switch ( option ) { case LBER_OPT_BER_DEBUG: * (int *) outvalue = ber_int_debug; return LBER_OPT_SUCCESS; case LBER_OPT_MEMORY_INUSE: /* The memory inuse is a global variable on kernal implementations. * This means that memory debug is shared by all LDAP processes * so for this variable to have much meaning, only one LDAP process * should be running and memory inuse should be initialized to zero * using the lber_set_option() function during startup. * The counter is not accurate for multithreaded ldap applications. */ #ifdef LDAP_MEMORY_DEBUG * (int *) outvalue = ber_int_meminuse; return LBER_OPT_SUCCESS; #else return LBER_OPT_ERROR; #endif case LBER_OPT_LOG_PRINT_FILE: *((FILE**)outvalue) = (FILE*)ber_pvt_err_file; return LBER_OPT_SUCCESS; } ber_errno = LBER_ERROR_PARAM; return LBER_OPT_ERROR; } ber = item; sb = item; switch(option) { case LBER_OPT_BER_OPTIONS: assert( LBER_VALID( ber ) ); * (int *) outvalue = ber->ber_options; return LBER_OPT_SUCCESS; case LBER_OPT_BER_DEBUG: assert( LBER_VALID( ber ) ); * (int *) outvalue = ber->ber_debug; return LBER_OPT_SUCCESS; case LBER_OPT_BER_REMAINING_BYTES: assert( LBER_VALID( ber ) ); *((ber_len_t *) outvalue) = ber_pvt_ber_remaining(ber); return LBER_OPT_SUCCESS; case LBER_OPT_BER_TOTAL_BYTES: assert( LBER_VALID( ber ) ); *((ber_len_t *) outvalue) = ber_pvt_ber_total(ber); return LBER_OPT_SUCCESS; case LBER_OPT_BER_BYTES_TO_WRITE: assert( LBER_VALID( ber ) ); *((ber_len_t *) outvalue) = ber_pvt_ber_write(ber); return LBER_OPT_SUCCESS; case LBER_OPT_BER_MEMCTX: assert( LBER_VALID( ber ) ); *((void **) outvalue) = ber->ber_memctx; return LBER_OPT_SUCCESS; default: /* bad param */ ber_errno = LBER_ERROR_PARAM; break; } return LBER_OPT_ERROR; } int ber_set_option( void *item, int option, LDAP_CONST void *invalue) { BerElement *ber; Sockbuf *sb; if(invalue == NULL) { /* no place to set from */ ber_errno = LBER_ERROR_PARAM; return LBER_OPT_ERROR; } if(item == NULL) { switch ( option ) { case LBER_OPT_BER_DEBUG: ber_int_debug = * (const int *) invalue; return LBER_OPT_SUCCESS; case LBER_OPT_LOG_PRINT_FN: ber_pvt_log_print = (BER_LOG_PRINT_FN) invalue; return LBER_OPT_SUCCESS; case LBER_OPT_LOG_PRINT_FILE: ber_pvt_err_file = (void *) invalue; return LBER_OPT_SUCCESS; case LBER_OPT_MEMORY_INUSE: /* The memory inuse is a global variable on kernal implementations. * This means that memory debug is shared by all LDAP processes * so for this variable to have much meaning, only one LDAP process * should be running and memory inuse should be initialized to zero * using the lber_set_option() function during startup. * The counter is not accurate for multithreaded applications. */ #ifdef LDAP_MEMORY_DEBUG ber_int_meminuse = * (int *) invalue; return LBER_OPT_SUCCESS; #else return LBER_OPT_ERROR; #endif case LBER_OPT_MEMORY_FNS: if ( ber_int_memory_fns == NULL ) { const BerMemoryFunctions *f = (const BerMemoryFunctions *) invalue; /* make sure all functions are provided */ if(!( f->bmf_malloc && f->bmf_calloc && f->bmf_realloc && f->bmf_free )) { ber_errno = LBER_ERROR_PARAM; return LBER_OPT_ERROR; } ber_int_memory_fns = &ber_int_memory_fns_datum; AC_MEMCPY(ber_int_memory_fns, f, sizeof(BerMemoryFunctions)); return LBER_OPT_SUCCESS; } break; case LBER_OPT_LOG_PROC: ber_int_log_proc = (BER_LOG_FN)invalue; return LBER_OPT_SUCCESS; } ber_errno = LBER_ERROR_PARAM; return LBER_OPT_ERROR; } ber = item; sb = item; switch(option) { case LBER_OPT_BER_OPTIONS: assert( LBER_VALID( ber ) ); ber->ber_options = * (const int *) invalue; return LBER_OPT_SUCCESS; case LBER_OPT_BER_DEBUG: assert( LBER_VALID( ber ) ); ber->ber_debug = * (const int *) invalue; return LBER_OPT_SUCCESS; case LBER_OPT_BER_REMAINING_BYTES: assert( LBER_VALID( ber ) ); ber->ber_end = &ber->ber_ptr[* (const ber_len_t *) invalue]; return LBER_OPT_SUCCESS; case LBER_OPT_BER_TOTAL_BYTES: assert( LBER_VALID( ber ) ); ber->ber_end = &ber->ber_buf[* (const ber_len_t *) invalue]; return LBER_OPT_SUCCESS; case LBER_OPT_BER_BYTES_TO_WRITE: assert( LBER_VALID( ber ) ); ber->ber_ptr = &ber->ber_buf[* (const ber_len_t *) invalue]; return LBER_OPT_SUCCESS; case LBER_OPT_BER_MEMCTX: assert( LBER_VALID( ber ) ); ber->ber_memctx = *(void **)invalue; return LBER_OPT_SUCCESS; default: /* bad param */ ber_errno = LBER_ERROR_PARAM; break; } return LBER_OPT_ERROR; } openldap-2.4.42+dfsg/libraries/liblber/encode.c0000644000175000017500000003643012563404150020026 0ustar ryanryan/* encode.c - ber output encoding routines */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (c) 1990 Regents of the University of Michigan. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of Michigan at Ann Arbor. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. */ /* ACKNOWLEDGEMENTS: * This work was originally developed by the University of Michigan * (as part of U-MICH LDAP). */ #include "portable.h" #include #include #include #include #include #include #include #include "lber-int.h" #define OCTET_SIZE(type) ((ber_len_t) (sizeof(type)*CHAR_BIT + 7) / 8) #define TAGBUF_SIZE OCTET_SIZE(ber_tag_t) #define LENBUF_SIZE (1 + OCTET_SIZE(ber_len_t)) #define HEADER_SIZE (TAGBUF_SIZE + LENBUF_SIZE) /* * BER element size constrains: * * - We traditionally support a length of max 0xffffffff. However * some functions return an int length so that is their max. * MAXINT_BERSIZE is the max for those functions. * * - MAXINT_BERSIZE must fit in MAXINT_BERSIZE_OCTETS octets. * * - sizeof(ber_elem_size_t) is normally MAXINT_BERSIZE_OCTETS: * Big enough for MAXINT_BERSIZE, but not more. (Larger wastes * space in the working encoding and DER encoding of a sequence * or set. Smaller further limits sizes near a sequence/set.) * * ber_len_t is mostly unrelated to this. Which may be for the best, * since it is also used for lengths of data that are never encoded. */ #define MAXINT_BERSIZE \ (INT_MAX>0xffffffffUL ? (ber_len_t) 0xffffffffUL : INT_MAX-HEADER_SIZE) #define MAXINT_BERSIZE_OCTETS 4 typedef ber_uint_t ber_elem_size_t; /* normally 32 bits */ /* Prepend tag to ptr, which points to the end of a tag buffer */ static unsigned char * ber_prepend_tag( unsigned char *ptr, ber_tag_t tag ) { do { *--ptr = (unsigned char) tag & 0xffU; } while ( (tag >>= 8) != 0 ); return ptr; } /* Prepend ber length to ptr, which points to the end of a length buffer */ static unsigned char * ber_prepend_len( unsigned char *ptr, ber_len_t len ) { /* * short len if it's less than 128 - one byte giving the len, * with bit 8 0. * long len otherwise - one byte with bit 8 set, giving the * length of the length, followed by the length itself. */ *--ptr = (unsigned char) len & 0xffU; if ( len >= 0x80 ) { unsigned char *endptr = ptr--; while ( (len >>= 8) != 0 ) { *ptr-- = (unsigned char) len & 0xffU; } *ptr = (unsigned char) (endptr - ptr) + 0x80U; } return ptr; } /* out->bv_len should be the buffer size on input */ int ber_encode_oid( BerValue *in, BerValue *out ) { unsigned char *der; unsigned long val1, val; int i, j, len; char *ptr, *end, *inend; assert( in != NULL ); assert( out != NULL ); if ( !out->bv_val || out->bv_len < in->bv_len/2 ) return -1; der = (unsigned char *) out->bv_val; ptr = in->bv_val; inend = ptr + in->bv_len; /* OIDs start with <0-1>.<0-39> or 2., DER-encoded 40*val1+val2 */ if ( !isdigit( (unsigned char) *ptr )) return -1; val1 = strtoul( ptr, &end, 10 ); if ( end == ptr || val1 > 2 ) return -1; if ( *end++ != '.' || !isdigit( (unsigned char) *end )) return -1; val = strtoul( end, &ptr, 10 ); if ( ptr == end ) return -1; if ( val > (val1 < 2 ? 39 : LBER_OID_COMPONENT_MAX - 80) ) return -1; val += val1 * 40; for (;;) { if ( ptr > inend ) return -1; /* Write the OID component little-endian, then reverse it */ len = 0; do { der[len++] = (val & 0xff) | 0x80; } while ( (val >>= 7) != 0 ); der[0] &= 0x7f; for ( i = 0, j = len; i < --j; i++ ) { unsigned char tmp = der[i]; der[i] = der[j]; der[j] = tmp; } der += len; if ( ptr == inend ) break; if ( *ptr++ != '.' ) return -1; if ( !isdigit( (unsigned char) *ptr )) return -1; val = strtoul( ptr, &end, 10 ); if ( end == ptr || val > LBER_OID_COMPONENT_MAX ) return -1; ptr = end; } out->bv_len = (char *)der - out->bv_val; return 0; } static int ber_put_int_or_enum( BerElement *ber, ber_int_t num, ber_tag_t tag ) { ber_uint_t unum; unsigned char sign, data[TAGBUF_SIZE+1 + OCTET_SIZE(ber_int_t)], *ptr; sign = 0; unum = num; /* Bit fiddling should be done with unsigned values */ if ( num < 0 ) { sign = 0xffU; unum = ~unum; } for ( ptr = &data[sizeof(data) - 1] ;; unum >>= 8 ) { *ptr-- = (sign ^ (unsigned char) unum) & 0xffU; if ( unum < 0x80 ) /* top bit at *ptr is sign bit */ break; } *ptr = (unsigned char) (&data[sizeof(data) - 1] - ptr); /* length */ ptr = ber_prepend_tag( ptr, tag ); return ber_write( ber, (char *) ptr, &data[sizeof(data)] - ptr, 0 ); } int ber_put_enum( BerElement *ber, ber_int_t num, ber_tag_t tag ) { if ( tag == LBER_DEFAULT ) { tag = LBER_ENUMERATED; } return ber_put_int_or_enum( ber, num, tag ); } int ber_put_int( BerElement *ber, ber_int_t num, ber_tag_t tag ) { if ( tag == LBER_DEFAULT ) { tag = LBER_INTEGER; } return ber_put_int_or_enum( ber, num, tag ); } int ber_put_ostring( BerElement *ber, LDAP_CONST char *str, ber_len_t len, ber_tag_t tag ) { int rc; unsigned char header[HEADER_SIZE], *ptr; if ( tag == LBER_DEFAULT ) { tag = LBER_OCTETSTRING; } if ( len > MAXINT_BERSIZE ) { return -1; } ptr = ber_prepend_len( &header[sizeof(header)], len ); ptr = ber_prepend_tag( ptr, tag ); rc = ber_write( ber, (char *) ptr, &header[sizeof(header)] - ptr, 0 ); if ( rc >= 0 && ber_write( ber, str, len, 0 ) >= 0 ) { /* length(tag + length + contents) */ return rc + (int) len; } return -1; } int ber_put_berval( BerElement *ber, struct berval *bv, ber_tag_t tag ) { if( bv == NULL || bv->bv_len == 0 ) { return ber_put_ostring( ber, "", (ber_len_t) 0, tag ); } return ber_put_ostring( ber, bv->bv_val, bv->bv_len, tag ); } int ber_put_string( BerElement *ber, LDAP_CONST char *str, ber_tag_t tag ) { assert( str != NULL ); return ber_put_ostring( ber, str, strlen( str ), tag ); } int ber_put_bitstring( BerElement *ber, LDAP_CONST char *str, ber_len_t blen /* in bits */, ber_tag_t tag ) { int rc; ber_len_t len; unsigned char unusedbits, header[HEADER_SIZE + 1], *ptr; if ( tag == LBER_DEFAULT ) { tag = LBER_BITSTRING; } unusedbits = (unsigned char) -blen & 7; len = blen / 8 + (unusedbits != 0); /* (blen+7)/8 without overflow */ if ( len >= MAXINT_BERSIZE ) { return -1; } header[sizeof(header) - 1] = unusedbits; ptr = ber_prepend_len( &header[sizeof(header) - 1], len + 1 ); ptr = ber_prepend_tag( ptr, tag ); rc = ber_write( ber, (char *) ptr, &header[sizeof(header)] - ptr, 0 ); if ( rc >= 0 && ber_write( ber, str, len, 0 ) >= 0 ) { /* length(tag + length + unused bit count + bitstring) */ return rc + (int) len; } return -1; } int ber_put_null( BerElement *ber, ber_tag_t tag ) { unsigned char data[TAGBUF_SIZE + 1], *ptr; if ( tag == LBER_DEFAULT ) { tag = LBER_NULL; } data[sizeof(data) - 1] = 0; /* length */ ptr = ber_prepend_tag( &data[sizeof(data) - 1], tag ); return ber_write( ber, (char *) ptr, &data[sizeof(data)] - ptr, 0 ); } int ber_put_boolean( BerElement *ber, ber_int_t boolval, ber_tag_t tag ) { unsigned char data[TAGBUF_SIZE + 2], *ptr; if ( tag == LBER_DEFAULT ) tag = LBER_BOOLEAN; data[sizeof(data) - 1] = boolval ? 0xff : 0; data[sizeof(data) - 2] = 1; /* length */ ptr = ber_prepend_tag( &data[sizeof(data) - 2], tag ); return ber_write( ber, (char *) ptr, &data[sizeof(data)] - ptr, 0 ); } /* Max number of length octets in a sequence or set, normally 5 */ #define SOS_LENLEN (1 + (sizeof(ber_elem_size_t) > MAXINT_BERSIZE_OCTETS ? \ (ber_len_t) sizeof(ber_elem_size_t) : MAXINT_BERSIZE_OCTETS)) /* Header of incomplete sequence or set */ typedef struct seqorset_header { char xtagbuf[TAGBUF_SIZE + 1]; /* room for tag + len(tag or len) */ union { ber_elem_size_t offset; /* enclosing seqence/set */ char padding[SOS_LENLEN-1]; /* for final length encoding */ } next_sos; # define SOS_TAG_END(header) ((unsigned char *) &(header).next_sos - 1) } Seqorset_header; /* Start a sequence or set */ static int ber_start_seqorset( BerElement *ber, ber_tag_t tag ) { /* * Write the tag and SOS_LENLEN octets reserved for length, to ber. * For now, length octets = (tag length, previous ber_sos_inner). * * Update ber_sos_inner and the write-cursor ber_sos_ptr. ber_ptr * will not move until the outermost sequence or set is complete. */ Seqorset_header header; unsigned char *headptr; ber_len_t taglen, headlen; char *dest, **p; assert( ber != NULL ); assert( LBER_VALID( ber ) ); if ( ber->ber_sos_ptr == NULL ) { /* outermost sequence/set? */ header.next_sos.offset = 0; p = &ber->ber_ptr; } else { if ( (ber_len_t) -1 > (ber_elem_size_t) -1 ) { if ( ber->ber_sos_inner > (ber_elem_size_t) -1 ) return -1; } header.next_sos.offset = ber->ber_sos_inner; p = &ber->ber_sos_ptr; } headptr = ber_prepend_tag( SOS_TAG_END(header), tag ); *SOS_TAG_END(header) = taglen = SOS_TAG_END(header) - headptr; headlen = taglen + SOS_LENLEN; /* As ber_write(,headptr,headlen,) except update ber_sos_ptr, not *p */ if ( headlen > (ber_len_t) (ber->ber_end - *p) ) { if ( ber_realloc( ber, headlen ) != 0 ) return -1; } dest = *p; AC_MEMCPY( dest, headptr, headlen ); ber->ber_sos_ptr = dest + headlen; ber->ber_sos_inner = dest + taglen - ber->ber_buf; /* * Do not return taglen + SOS_LENLEN here - then ber_put_seqorset() * should return lenlen - SOS_LENLEN + len, which can be < 0. */ return 0; } int ber_start_seq( BerElement *ber, ber_tag_t tag ) { if ( tag == LBER_DEFAULT ) { tag = LBER_SEQUENCE; } return ber_start_seqorset( ber, tag ); } int ber_start_set( BerElement *ber, ber_tag_t tag ) { if ( tag == LBER_DEFAULT ) { tag = LBER_SET; } return ber_start_seqorset( ber, tag ); } /* End a sequence or set */ static int ber_put_seqorset( BerElement *ber ) { Seqorset_header header; unsigned char *lenptr; /* length octets in the sequence/set */ ber_len_t len; /* length(contents) */ ber_len_t xlen; /* len + length(length) */ assert( ber != NULL ); assert( LBER_VALID( ber ) ); if ( ber->ber_sos_ptr == NULL ) return -1; lenptr = (unsigned char *) ber->ber_buf + ber->ber_sos_inner; xlen = ber->ber_sos_ptr - (char *) lenptr; if ( xlen > MAXINT_BERSIZE + SOS_LENLEN ) { return -1; } /* Extract sequence/set information from length octets */ memcpy( SOS_TAG_END(header), lenptr, SOS_LENLEN ); /* Store length, and close gap of leftover reserved length octets */ len = xlen - SOS_LENLEN; if ( !(ber->ber_options & LBER_USE_DER) ) { int i; lenptr[0] = SOS_LENLEN - 1 + 0x80; /* length(length)-1 */ for( i = SOS_LENLEN; --i > 0; len >>= 8 ) { lenptr[i] = len & 0xffU; } } else { unsigned char *p = ber_prepend_len( lenptr + SOS_LENLEN, len ); ber_len_t unused = p - lenptr; if ( unused != 0 ) { /* length(length) < the reserved SOS_LENLEN bytes */ xlen -= unused; AC_MEMCPY( lenptr, p, xlen ); ber->ber_sos_ptr = (char *) lenptr + xlen; } } ber->ber_sos_inner = header.next_sos.offset; if ( header.next_sos.offset == 0 ) { /* outermost sequence/set? */ /* The ber_ptr is at the set/seq start - move it to the end */ ber->ber_ptr = ber->ber_sos_ptr; ber->ber_sos_ptr = NULL; } return xlen + *SOS_TAG_END(header); /* lenlen + len + taglen */ } int ber_put_seq( BerElement *ber ) { return ber_put_seqorset( ber ); } int ber_put_set( BerElement *ber ) { return ber_put_seqorset( ber ); } /* N tag */ static ber_tag_t lber_int_null = 0; /* VARARGS */ int ber_printf( BerElement *ber, LDAP_CONST char *fmt, ... ) { va_list ap; char *s, **ss; struct berval *bv, **bvp; int rc; ber_int_t i; ber_len_t len; assert( ber != NULL ); assert( fmt != NULL ); assert( LBER_VALID( ber ) ); va_start( ap, fmt ); for ( rc = 0; *fmt && rc != -1; fmt++ ) { switch ( *fmt ) { case '!': { /* hook */ BEREncodeCallback *f; void *p; ber->ber_usertag = 0; f = va_arg( ap, BEREncodeCallback * ); p = va_arg( ap, void * ); rc = (*f)( ber, p ); if ( ber->ber_usertag ) { goto next; } } break; case 'b': /* boolean */ i = va_arg( ap, ber_int_t ); rc = ber_put_boolean( ber, i, ber->ber_tag ); break; case 'i': /* int */ i = va_arg( ap, ber_int_t ); rc = ber_put_int( ber, i, ber->ber_tag ); break; case 'e': /* enumeration */ i = va_arg( ap, ber_int_t ); rc = ber_put_enum( ber, i, ber->ber_tag ); break; case 'n': /* null */ rc = ber_put_null( ber, ber->ber_tag ); break; case 'N': /* Debug NULL */ rc = 0; if( lber_int_null != 0 ) { /* Insert NULL to ensure peer ignores unknown tags */ rc = ber_put_null( ber, lber_int_null ); } break; case 'o': /* octet string (non-null terminated) */ s = va_arg( ap, char * ); len = va_arg( ap, ber_len_t ); rc = ber_put_ostring( ber, s, len, ber->ber_tag ); break; case 'O': /* berval octet string */ bv = va_arg( ap, struct berval * ); if( bv == NULL ) break; rc = ber_put_berval( ber, bv, ber->ber_tag ); break; case 's': /* string */ s = va_arg( ap, char * ); rc = ber_put_string( ber, s, ber->ber_tag ); break; case 'B': /* bit string */ case 'X': /* bit string (deprecated) */ s = va_arg( ap, char * ); len = va_arg( ap, ber_len_t ); /* in bits */ rc = ber_put_bitstring( ber, s, len, ber->ber_tag ); break; case 't': /* tag for the next element */ ber->ber_tag = va_arg( ap, ber_tag_t ); goto next; case 'v': /* vector of strings */ if ( (ss = va_arg( ap, char ** )) == NULL ) break; for ( i = 0; ss[i] != NULL; i++ ) { if ( (rc = ber_put_string( ber, ss[i], ber->ber_tag )) == -1 ) break; } break; case 'V': /* sequences of strings + lengths */ if ( (bvp = va_arg( ap, struct berval ** )) == NULL ) break; for ( i = 0; bvp[i] != NULL; i++ ) { if ( (rc = ber_put_berval( ber, bvp[i], ber->ber_tag )) == -1 ) break; } break; case 'W': /* BerVarray */ if ( (bv = va_arg( ap, BerVarray )) == NULL ) break; for ( i = 0; bv[i].bv_val != NULL; i++ ) { if ( (rc = ber_put_berval( ber, &bv[i], ber->ber_tag )) == -1 ) break; } break; case '{': /* begin sequence */ rc = ber_start_seq( ber, ber->ber_tag ); break; case '}': /* end sequence */ rc = ber_put_seqorset( ber ); break; case '[': /* begin set */ rc = ber_start_set( ber, ber->ber_tag ); break; case ']': /* end set */ rc = ber_put_seqorset( ber ); break; default: if( ber->ber_debug ) { ber_log_printf( LDAP_DEBUG_ANY, ber->ber_debug, "ber_printf: unknown fmt %c\n", *fmt ); } rc = -1; break; } ber->ber_tag = LBER_DEFAULT; next:; } va_end( ap ); return rc; } openldap-2.4.42+dfsg/libraries/liblber/stdio.c0000644000175000017500000001400712563404150017707 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #include "portable.h" #include #include #include #include #include #if !defined(HAVE_VSNPRINTF) && !defined(HAVE_EBCDIC) /* Write at most n characters to the buffer in str, return the * number of chars written or -1 if the buffer would have been * overflowed. * * This is portable to any POSIX-compliant system. We use pipe() * to create a valid file descriptor, and then fdopen() it to get * a valid FILE pointer. The user's buffer and size are assigned * to the FILE pointer using setvbuf. Then we close the read side * of the pipe to invalidate the descriptor. * * If the write arguments all fit into size n, the write will * return successfully. If the write is too large, the stdio * buffer will need to be flushed to the underlying file descriptor. * The flush will fail because it is attempting to write to a * broken pipe, and the write will be terminated. * -- hyc, 2002-07-19 */ /* This emulation uses vfprintf; on OS/390 we're also emulating * that function so it's more efficient just to have a separate * version of vsnprintf there. */ #include int ber_pvt_vsnprintf( char *str, size_t n, const char *fmt, va_list ap ) { int fds[2], res; FILE *f; RETSIGTYPE (*sig)(); if (pipe( fds )) return -1; f = fdopen( fds[1], "w" ); if ( !f ) { close( fds[1] ); close( fds[0] ); return -1; } setvbuf( f, str, _IOFBF, n ); sig = signal( SIGPIPE, SIG_IGN ); close( fds[0] ); res = vfprintf( f, fmt, ap ); fclose( f ); signal( SIGPIPE, sig ); if ( res > 0 && res < n ) { res = vsprintf( str, fmt, ap ); } return res; } #endif #ifndef HAVE_SNPRINTF int ber_pvt_snprintf( char *str, size_t n, const char *fmt, ... ) { va_list ap; int res; va_start( ap, fmt ); res = vsnprintf( str, n, fmt, ap ); va_end( ap ); return res; } #endif /* !HAVE_SNPRINTF */ #ifdef HAVE_EBCDIC /* stdio replacements with ASCII/EBCDIC translation for OS/390. * The OS/390 port depends on the CONVLIT compiler option being * used to force character and string literals to be compiled in * ISO8859-1, and the __LIBASCII cpp symbol to be defined to use the * OS/390 ASCII-compatibility library. This library only supplies * an ASCII version of sprintf, so other needed functions are * provided here. * * All of the internal character manipulation is done in ASCII, * but file I/O is EBCDIC, so we catch any stdio reading/writing * of files here and do the translations. */ #undef fputs #undef fgets char *ber_pvt_fgets( char *s, int n, FILE *fp ) { s = (char *)fgets( s, n, fp ); if ( s ) __etoa( s ); return s; } int ber_pvt_fputs( const char *str, FILE *fp ) { char buf[8192]; strncpy( buf, str, sizeof(buf) ); __atoe( buf ); return fputs( buf, fp ); } /* The __LIBASCII doesn't include a working vsprintf, so we make do * using just sprintf. This is a very simplistic parser that looks for * format strings and uses sprintf to process them one at a time. * Literal text is just copied straight to the destination. * The result is appended to the destination string. The parser * recognizes field-width specifiers and the 'l' qualifier; it * may need to be extended to recognize other qualifiers but so * far this seems to be enough. */ int ber_pvt_vsnprintf( char *str, size_t n, const char *fmt, va_list ap ) { char *ptr, *pct, *s2, *f2, *end; char fm2[64]; int len, rem; ptr = (char *)fmt; s2 = str; fm2[0] = '%'; if (n) { end = str + n; } else { end = NULL; } for (pct = strchr(ptr, '%'); pct; pct = strchr(ptr, '%')) { len = pct-ptr; if (end) { rem = end-s2; if (rem < 1) return -1; if (rem < len) len = rem; } s2 = lutil_strncopy( s2, ptr, len ); /* Did we cheat the length above? If so, bail out */ if (len < pct-ptr) return -1; for (pct++, f2 = fm2+1; isdigit(*pct);) *f2++ = *pct++; if (*pct == 'l') *f2++ = *pct++; if (*pct == '%') { *s2++ = '%'; } else { *f2++ = *pct; *f2 = '\0'; if (*pct == 's') { char *ss = va_arg(ap, char *); /* Attempt to limit sprintf output. This * may be thrown off if field widths were * specified for this string. * * If it looks like the string is too * long for the remaining buffer, bypass * sprintf and just copy what fits, then * quit. */ if (end && strlen(ss) > (rem=end-s2)) { strncpy(s2, ss, rem); return -1; } else { s2 += sprintf(s2, fm2, ss); } } else { s2 += sprintf(s2, fm2, va_arg(ap, int)); } } ptr = pct + 1; } if (end) { rem = end-s2; if (rem > 0) { len = strlen(ptr); s2 = lutil_strncopy( s2, ptr, rem ); rem -= len; } if (rem < 0) return -1; } else { s2 = lutil_strcopy( s2, ptr ); } return s2 - str; } int ber_pvt_vsprintf( char *str, const char *fmt, va_list ap ) { return vsnprintf( str, 0, fmt, ap ); } /* The fixed buffer size here is a problem, we don't know how * to flush the buffer and keep printing if the msg is too big. * Hopefully we never try to write something bigger than this * in a log msg... */ int ber_pvt_vfprintf( FILE *fp, const char *fmt, va_list ap ) { char buf[8192]; int res; vsnprintf( buf, sizeof(buf), fmt, ap ); __atoe( buf ); res = fputs( buf, fp ); if (res == EOF) res = -1; return res; } int ber_pvt_printf( const char *fmt, ... ) { va_list ap; int res; va_start( ap, fmt ); res = ber_pvt_vfprintf( stdout, fmt, ap ); va_end( ap ); return res; } int ber_pvt_fprintf( FILE *fp, const char *fmt, ... ) { va_list ap; int res; va_start( ap, fmt ); res = ber_pvt_vfprintf( fp, fmt, ap ); va_end( ap ); return res; } #endif openldap-2.4.42+dfsg/libraries/liblber/lber-int.h0000644000175000017500000001443212563404150020310 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (c) 1990 Regents of the University of Michigan. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of Michigan at Ann Arbor. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. */ #ifndef _LBER_INT_H #define _LBER_INT_H #include "lber.h" #include "ldap_log.h" #include "lber_pvt.h" #include "ldap_queue.h" LDAP_BEGIN_DECL typedef void (*BER_LOG_FN)(FILE *file, const char *subsys, int level, const char *fmt, ... ); LBER_V (BER_ERRNO_FN) ber_int_errno_fn; #ifdef LDAP_MEMORY_TRACE # ifndef LDAP_MEMORY_DEBUG # define LDAP_MEMORY_DEBUG 1 # endif #endif #ifdef LDAP_MEMORY_DEBUG LBER_V (long) ber_int_meminuse; #endif #if defined(LDAP_MEMORY_DEBUG) && ((LDAP_MEMORY_DEBUG +0) & 2) # define LDAP_MEMORY_DEBUG_ASSERT assert #else # define LDAP_MEMORY_DEBUG_ASSERT(expr) ((void) 0) #endif struct lber_options { short lbo_valid; unsigned short lbo_options; int lbo_debug; }; LBER_F( int ) ber_pvt_log_output( const char *subsystem, int level, const char *fmt, ... ); #define LBER_UNINITIALIZED 0x0 #define LBER_INITIALIZED 0x1 #define LBER_VALID_BERELEMENT 0x2 #define LBER_VALID_SOCKBUF 0x3 LBER_V (struct lber_options) ber_int_options; #define ber_int_debug ber_int_options.lbo_debug /* Data encoded in ASN.1 BER format */ struct berelement { struct lber_options ber_opts; #define ber_valid ber_opts.lbo_valid #define ber_options ber_opts.lbo_options #define ber_debug ber_opts.lbo_debug /* * The members below, when not NULL/LBER_DEFAULT/etc, are: * ber_buf Data buffer. Other pointers normally point into it. * ber_rwptr Read/write cursor for Sockbuf I/O. * ber_memctx Context passed to ber_memalloc() & co. * When decoding data (reading it from the BerElement): * ber_end End of BER data. * ber_ptr Read cursor, except for 1st octet of tags. * ber_tag 1st octet of next tag, saved from *ber_ptr when * ber_ptr may be pointing at a tag and is >ber_buf. * The octet *ber_ptr itself may get overwritten with * a \0, to terminate the preceding element. * When encoding data (writing it to the BerElement): * ber_end End of allocated buffer - 1 (allowing a final \0). * ber_ptr Last complete BER element (normally write cursor). * ber_sos_ptr NULL or write cursor for incomplete sequence or set. * ber_sos_inner offset(seq/set length octets) if ber_sos_ptr!=NULL. * ber_tag Default tag for next ber_printf() element. * ber_usertag Boolean set by ber_printf "!" if it sets ber_tag. * ber_len Reused for ber_sos_inner. * When output to a Sockbuf: * ber_ptr End of encoded data to write. * When input from a Sockbuf: * See ber_get_next(). */ /* Do not change the order of these 3 fields! see ber_get_next */ ber_tag_t ber_tag; ber_len_t ber_len; ber_tag_t ber_usertag; char *ber_buf; char *ber_ptr; char *ber_end; char *ber_sos_ptr; # define ber_sos_inner ber_len /* reused for binary compat */ char *ber_rwptr; void *ber_memctx; }; #define LBER_VALID(ber) ((ber)->ber_valid==LBER_VALID_BERELEMENT) #define ber_pvt_ber_remaining(ber) ((ber)->ber_end - (ber)->ber_ptr) #define ber_pvt_ber_total(ber) ((ber)->ber_end - (ber)->ber_buf) #define ber_pvt_ber_write(ber) ((ber)->ber_ptr - (ber)->ber_buf) struct sockbuf { struct lber_options sb_opts; Sockbuf_IO_Desc *sb_iod; /* I/O functions */ #define sb_valid sb_opts.lbo_valid #define sb_options sb_opts.lbo_options #define sb_debug sb_opts.lbo_debug ber_socket_t sb_fd; ber_len_t sb_max_incoming; unsigned int sb_trans_needs_read:1; unsigned int sb_trans_needs_write:1; #ifdef LDAP_PF_LOCAL_SENDMSG char sb_ungetlen; char sb_ungetbuf[8]; #endif }; #define SOCKBUF_VALID( sb ) ( (sb)->sb_valid == LBER_VALID_SOCKBUF ) /* * decode.c, encode.c */ /* Simplest OID max-DER-component to implement in both decode and encode */ #define LBER_OID_COMPONENT_MAX ((unsigned long)-1 - 128) /* * io.c */ LBER_F( int ) ber_realloc LDAP_P(( BerElement *ber, ber_len_t len )); LBER_F (char *) ber_start LDAP_P(( BerElement * )); LBER_F (int) ber_len LDAP_P(( BerElement * )); LBER_F (int) ber_ptrlen LDAP_P(( BerElement * )); LBER_F (void) ber_rewind LDAP_P(( BerElement * )); /* * bprint.c */ #define ber_log_printf ber_pvt_log_printf LBER_F( int ) ber_log_bprint LDAP_P(( int errlvl, int loglvl, const char *data, ber_len_t len )); LBER_F( int ) ber_log_dump LDAP_P(( int errlvl, int loglvl, BerElement *ber, int inout )); LBER_V (BER_LOG_FN) ber_int_log_proc; LBER_V (FILE *) ber_pvt_err_file; /* memory.c */ /* simple macros to realloc for now */ LBER_V (BerMemoryFunctions *) ber_int_memory_fns; LBER_F (char *) ber_strndup( LDAP_CONST char *, ber_len_t ); LBER_F (char *) ber_strndup_x( LDAP_CONST char *, ber_len_t, void *ctx ); #define LBER_MALLOC(s) ber_memalloc((s)) #define LBER_CALLOC(n,s) ber_memcalloc((n),(s)) #define LBER_REALLOC(p,s) ber_memrealloc((p),(s)) #define LBER_FREE(p) ber_memfree((p)) #define LBER_VFREE(v) ber_memvfree((void**)(v)) #define LBER_STRDUP(s) ber_strdup((s)) #define LBER_STRNDUP(s,l) ber_strndup((s),(l)) /* sockbuf.c */ LBER_F( int ) ber_int_sb_init LDAP_P(( Sockbuf *sb )); LBER_F( int ) ber_int_sb_close LDAP_P(( Sockbuf *sb )); LBER_F( int ) ber_int_sb_destroy LDAP_P(( Sockbuf *sb )); LBER_F( ber_slen_t ) ber_int_sb_read LDAP_P(( Sockbuf *sb, void *buf, ber_len_t len )); LBER_F( ber_slen_t ) ber_int_sb_write LDAP_P(( Sockbuf *sb, void *buf, ber_len_t len )); LDAP_END_DECL #endif /* _LBER_INT_H */ openldap-2.4.42+dfsg/libraries/liblber/assert.c0000644000175000017500000000170712563404150020071 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #include "portable.h" #ifdef LDAP_NEED_ASSERT #include /* * helper for our private assert() macro * * note: if assert() doesn't exist, like abort() or raise() won't either. * could use kill() but that might be problematic. I'll just ignore this * issue for now. */ void ber_pvt_assert( const char *file, int line, const char *test ) { fprintf(stderr, _("Assertion failed: %s, file %s, line %d\n"), test, file, line); abort(); } #endif openldap-2.4.42+dfsg/libraries/liblber/idtest.c0000644000175000017500000000445512563404150020067 0ustar ryanryan/* idtest.c - ber decoding test program using isode libraries */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (c) 1990 Regents of the University of Michigan. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of Michigan at Ann Arbor. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. */ /* ACKNOWLEDGEMENTS: * This work was originally developed by the University of Michigan * (as part of U-MICH LDAP). */ #include "portable.h" #include #include #ifdef HAVE_PSAP_H #include #include #endif int main( int argc, char **argv ) { #ifdef HAVE_PSAP_H PE pe; PS psin, psout, pserr; /* read the pe from standard in */ if ( (psin = ps_alloc( std_open )) == NULLPS ) { perror( "ps_alloc" ); exit( EXIT_FAILURE ); } if ( std_setup( psin, stdin ) == NOTOK ) { perror( "std_setup" ); exit( EXIT_FAILURE ); } /* write the pe to standard out */ if ( (psout = ps_alloc( std_open )) == NULLPS ) { perror( "ps_alloc" ); exit( EXIT_FAILURE ); } if ( std_setup( psout, stdout ) == NOTOK ) { perror( "std_setup" ); exit( EXIT_FAILURE ); } /* pretty print it to standard error */ if ( (pserr = ps_alloc( std_open )) == NULLPS ) { perror( "ps_alloc" ); exit( EXIT_FAILURE ); } if ( std_setup( pserr, stderr ) == NOTOK ) { perror( "std_setup" ); exit( EXIT_FAILURE ); } while ( (pe = ps2pe( psin )) != NULLPE ) { pe2pl( pserr, pe ); pe2ps( psout, pe ); } exit( EXIT_SUCCESS ); #else fprintf(stderr, "requires ISODE X.500 distribution.\n"); return( EXIT_FAILURE ); #endif } openldap-2.4.42+dfsg/libraries/liblber/memory.c0000644000175000017500000004003312563404150020073 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #include "portable.h" #include #include #include "lber-int.h" #ifdef LDAP_MEMORY_TRACE #include #endif #ifdef LDAP_MEMORY_DEBUG /* * LDAP_MEMORY_DEBUG should only be enabled for the purposes of * debugging memory management within OpenLDAP libraries and slapd. * * It should only be enabled by an experienced developer as it causes * the inclusion of numerous assert()'s, many of which may be triggered * by a prefectly valid program. If LDAP_MEMORY_DEBUG & 2 is true, * that includes asserts known to break both slapd and current clients. * * The code behind this macro is subject to change as needed to * support this testing. */ struct ber_mem_hdr { ber_int_t bm_top; /* Pattern to detect buf overrun from prev buffer */ ber_int_t bm_length; /* Length of user allocated area */ #ifdef LDAP_MEMORY_TRACE ber_int_t bm_sequence; /* Allocation sequence number */ #endif union bmu_align_u { /* Force alignment, pattern to detect back clobber */ ber_len_t bmu_len_t; ber_tag_t bmu_tag_t; ber_int_t bmu_int_t; size_t bmu_size_t; void * bmu_voidp; double bmu_double; long bmu_long; long (*bmu_funcp)( double ); unsigned char bmu_char[4]; } ber_align; #define bm_junk ber_align.bmu_len_t #define bm_data ber_align.bmu_char[1] #define bm_char ber_align.bmu_char }; /* Pattern at top of allocated space */ #define LBER_MEM_JUNK ((ber_int_t) 0xdeaddada) static const struct ber_mem_hdr ber_int_mem_hdr = { LBER_MEM_JUNK }; /* Note sequence and ber_int_meminuse are counters, but are not * thread safe. If you want to use these values for multithreaded applications, * you must put mutexes around them, otherwise they will have incorrect values. * When debugging, if you sort the debug output, the sequence number will * put allocations/frees together. It is then a simple matter to write a script * to find any allocations that don't have a buffer free function. */ long ber_int_meminuse = 0; #ifdef LDAP_MEMORY_TRACE static ber_int_t sequence = 0; #endif /* Pattern placed just before user data */ static unsigned char toppattern[4] = { 0xde, 0xad, 0xba, 0xde }; /* Pattern placed just after user data */ static unsigned char endpattern[4] = { 0xd1, 0xed, 0xde, 0xca }; #define mbu_len sizeof(ber_int_mem_hdr.ber_align) /* Test if pattern placed just before user data is good */ #define testdatatop(val) ( \ *(val->bm_char+mbu_len-4)==toppattern[0] && \ *(val->bm_char+mbu_len-3)==toppattern[1] && \ *(val->bm_char+mbu_len-2)==toppattern[2] && \ *(val->bm_char+mbu_len-1)==toppattern[3] ) /* Place pattern just before user data */ #define setdatatop(val) *(val->bm_char+mbu_len-4)=toppattern[0]; \ *(val->bm_char+mbu_len-3)=toppattern[1]; \ *(val->bm_char+mbu_len-2)=toppattern[2]; \ *(val->bm_char+mbu_len-1)=toppattern[3]; /* Test if pattern placed just after user data is good */ #define testend(val) ( *((unsigned char *)val+0)==endpattern[0] && \ *((unsigned char *)val+1)==endpattern[1] && \ *((unsigned char *)val+2)==endpattern[2] && \ *((unsigned char *)val+3)==endpattern[3] ) /* Place pattern just after user data */ #define setend(val) *((unsigned char *)val+0)=endpattern[0]; \ *((unsigned char *)val+1)=endpattern[1]; \ *((unsigned char *)val+2)=endpattern[2]; \ *((unsigned char *)val+3)=endpattern[3]; #define BER_MEM_BADADDR ((void *) &ber_int_mem_hdr.bm_data) #define BER_MEM_VALID(p) do { \ assert( (p) != BER_MEM_BADADDR ); \ assert( (p) != (void *) &ber_int_mem_hdr ); \ } while(0) #else #define BER_MEM_VALID(p) /* no-op */ #endif BerMemoryFunctions *ber_int_memory_fns = NULL; void ber_memfree_x( void *p, void *ctx ) { if( p == NULL ) { return; } BER_MEM_VALID( p ); if( ber_int_memory_fns == NULL || ctx == NULL ) { #ifdef LDAP_MEMORY_DEBUG struct ber_mem_hdr *mh = (struct ber_mem_hdr *) ((char *)p - sizeof(struct ber_mem_hdr)); assert( mh->bm_top == LBER_MEM_JUNK); assert( testdatatop( mh)); assert( testend( (char *)&mh[1] + mh->bm_length) ); ber_int_meminuse -= mh->bm_length; #ifdef LDAP_MEMORY_TRACE fprintf(stderr, "0x%08lx 0x%08lx -f- %ld ber_memfree %ld\n", (long)mh->bm_sequence, (long)mh, (long)mh->bm_length, ber_int_meminuse); #endif /* Fill the free space with poison */ memset( mh, 0xff, mh->bm_length + sizeof(struct ber_mem_hdr) + sizeof(ber_int_t)); free( mh ); #else free( p ); #endif return; } assert( ber_int_memory_fns->bmf_free != 0 ); (*ber_int_memory_fns->bmf_free)( p, ctx ); } void ber_memfree( void *p ) { ber_memfree_x(p, NULL); } void ber_memvfree_x( void **vec, void *ctx ) { int i; if( vec == NULL ) { return; } BER_MEM_VALID( vec ); for ( i = 0; vec[i] != NULL; i++ ) { ber_memfree_x( vec[i], ctx ); } ber_memfree_x( vec, ctx ); } void ber_memvfree( void **vec ) { ber_memvfree_x( vec, NULL ); } void * ber_memalloc_x( ber_len_t s, void *ctx ) { void *new; if( s == 0 ) { LDAP_MEMORY_DEBUG_ASSERT( s != 0 ); return NULL; } if( ber_int_memory_fns == NULL || ctx == NULL ) { #ifdef LDAP_MEMORY_DEBUG new = malloc(s + sizeof(struct ber_mem_hdr) + sizeof( ber_int_t)); if( new ) { struct ber_mem_hdr *mh = new; mh->bm_top = LBER_MEM_JUNK; mh->bm_length = s; setdatatop( mh); setend( (char *)&mh[1] + mh->bm_length ); ber_int_meminuse += mh->bm_length; /* Count mem inuse */ #ifdef LDAP_MEMORY_TRACE mh->bm_sequence = sequence++; fprintf(stderr, "0x%08lx 0x%08lx -a- %ld ber_memalloc %ld\n", (long)mh->bm_sequence, (long)mh, (long)mh->bm_length, ber_int_meminuse); #endif /* poison new memory */ memset( (char *)&mh[1], 0xff, s); BER_MEM_VALID( &mh[1] ); new = &mh[1]; } #else new = malloc( s ); #endif } else { new = (*ber_int_memory_fns->bmf_malloc)( s, ctx ); } if( new == NULL ) { ber_errno = LBER_ERROR_MEMORY; } return new; } void * ber_memalloc( ber_len_t s ) { return ber_memalloc_x( s, NULL ); } void * ber_memcalloc_x( ber_len_t n, ber_len_t s, void *ctx ) { void *new; if( n == 0 || s == 0 ) { LDAP_MEMORY_DEBUG_ASSERT( n != 0 && s != 0); return NULL; } if( ber_int_memory_fns == NULL || ctx == NULL ) { #ifdef LDAP_MEMORY_DEBUG new = n < (-sizeof(struct ber_mem_hdr) - sizeof(ber_int_t)) / s ? calloc(1, n*s + sizeof(struct ber_mem_hdr) + sizeof(ber_int_t)) : NULL; if( new ) { struct ber_mem_hdr *mh = new; mh->bm_top = LBER_MEM_JUNK; mh->bm_length = n*s; setdatatop( mh); setend( (char *)&mh[1] + mh->bm_length ); ber_int_meminuse += mh->bm_length; #ifdef LDAP_MEMORY_TRACE mh->bm_sequence = sequence++; fprintf(stderr, "0x%08lx 0x%08lx -a- %ld ber_memcalloc %ld\n", (long)mh->bm_sequence, (long)mh, (long)mh->bm_length, ber_int_meminuse); #endif BER_MEM_VALID( &mh[1] ); new = &mh[1]; } #else new = calloc( n, s ); #endif } else { new = (*ber_int_memory_fns->bmf_calloc)( n, s, ctx ); } if( new == NULL ) { ber_errno = LBER_ERROR_MEMORY; } return new; } void * ber_memcalloc( ber_len_t n, ber_len_t s ) { return ber_memcalloc_x( n, s, NULL ); } void * ber_memrealloc_x( void* p, ber_len_t s, void *ctx ) { void *new = NULL; /* realloc(NULL,s) -> malloc(s) */ if( p == NULL ) { return ber_memalloc_x( s, ctx ); } /* realloc(p,0) -> free(p) */ if( s == 0 ) { ber_memfree_x( p, ctx ); return NULL; } BER_MEM_VALID( p ); if( ber_int_memory_fns == NULL || ctx == NULL ) { #ifdef LDAP_MEMORY_DEBUG ber_int_t oldlen; struct ber_mem_hdr *mh = (struct ber_mem_hdr *) ((char *)p - sizeof(struct ber_mem_hdr)); assert( mh->bm_top == LBER_MEM_JUNK); assert( testdatatop( mh)); assert( testend( (char *)&mh[1] + mh->bm_length) ); oldlen = mh->bm_length; p = realloc( mh, s + sizeof(struct ber_mem_hdr) + sizeof(ber_int_t) ); if( p == NULL ) { ber_errno = LBER_ERROR_MEMORY; return NULL; } mh = p; mh->bm_length = s; setend( (char *)&mh[1] + mh->bm_length ); if( s > oldlen ) { /* poison any new memory */ memset( (char *)&mh[1] + oldlen, 0xff, s - oldlen); } assert( mh->bm_top == LBER_MEM_JUNK); assert( testdatatop( mh)); ber_int_meminuse += s - oldlen; #ifdef LDAP_MEMORY_TRACE fprintf(stderr, "0x%08lx 0x%08lx -a- %ld ber_memrealloc %ld\n", (long)mh->bm_sequence, (long)mh, (long)mh->bm_length, ber_int_meminuse); #endif BER_MEM_VALID( &mh[1] ); return &mh[1]; #else new = realloc( p, s ); #endif } else { new = (*ber_int_memory_fns->bmf_realloc)( p, s, ctx ); } if( new == NULL ) { ber_errno = LBER_ERROR_MEMORY; } return new; } void * ber_memrealloc( void* p, ber_len_t s ) { return ber_memrealloc_x( p, s, NULL ); } void ber_bvfree_x( struct berval *bv, void *ctx ) { if( bv == NULL ) { return; } BER_MEM_VALID( bv ); if ( bv->bv_val != NULL ) { ber_memfree_x( bv->bv_val, ctx ); } ber_memfree_x( (char *) bv, ctx ); } void ber_bvfree( struct berval *bv ) { ber_bvfree_x( bv, NULL ); } void ber_bvecfree_x( struct berval **bv, void *ctx ) { int i; if( bv == NULL ) { return; } BER_MEM_VALID( bv ); /* count elements */ for ( i = 0; bv[i] != NULL; i++ ) ; /* free in reverse order */ for ( i--; i >= 0; i-- ) { ber_bvfree_x( bv[i], ctx ); } ber_memfree_x( (char *) bv, ctx ); } void ber_bvecfree( struct berval **bv ) { ber_bvecfree_x( bv, NULL ); } int ber_bvecadd_x( struct berval ***bvec, struct berval *bv, void *ctx ) { ber_len_t i; struct berval **new; if( *bvec == NULL ) { if( bv == NULL ) { /* nothing to add */ return 0; } *bvec = ber_memalloc_x( 2 * sizeof(struct berval *), ctx ); if( *bvec == NULL ) { return -1; } (*bvec)[0] = bv; (*bvec)[1] = NULL; return 1; } BER_MEM_VALID( bvec ); /* count entries */ for ( i = 0; (*bvec)[i] != NULL; i++ ) { /* EMPTY */; } if( bv == NULL ) { return i; } new = ber_memrealloc_x( *bvec, (i+2) * sizeof(struct berval *), ctx); if( new == NULL ) { return -1; } *bvec = new; (*bvec)[i++] = bv; (*bvec)[i] = NULL; return i; } int ber_bvecadd( struct berval ***bvec, struct berval *bv ) { return ber_bvecadd_x( bvec, bv, NULL ); } struct berval * ber_dupbv_x( struct berval *dst, struct berval *src, void *ctx ) { struct berval *new; if( src == NULL ) { ber_errno = LBER_ERROR_PARAM; return NULL; } if ( dst ) { new = dst; } else { if(( new = ber_memalloc_x( sizeof(struct berval), ctx )) == NULL ) { return NULL; } } if ( src->bv_val == NULL ) { new->bv_val = NULL; new->bv_len = 0; return new; } if(( new->bv_val = ber_memalloc_x( src->bv_len + 1, ctx )) == NULL ) { if ( !dst ) ber_memfree_x( new, ctx ); return NULL; } AC_MEMCPY( new->bv_val, src->bv_val, src->bv_len ); new->bv_val[src->bv_len] = '\0'; new->bv_len = src->bv_len; return new; } struct berval * ber_dupbv( struct berval *dst, struct berval *src ) { return ber_dupbv_x( dst, src, NULL ); } struct berval * ber_bvdup( struct berval *src ) { return ber_dupbv_x( NULL, src, NULL ); } struct berval * ber_str2bv_x( LDAP_CONST char *s, ber_len_t len, int dup, struct berval *bv, void *ctx) { struct berval *new; if( s == NULL ) { ber_errno = LBER_ERROR_PARAM; return NULL; } if( bv ) { new = bv; } else { if(( new = ber_memalloc_x( sizeof(struct berval), ctx )) == NULL ) { return NULL; } } new->bv_len = len ? len : strlen( s ); if ( dup ) { if ( (new->bv_val = ber_memalloc_x( new->bv_len+1, ctx )) == NULL ) { if ( !bv ) ber_memfree_x( new, ctx ); return NULL; } AC_MEMCPY( new->bv_val, s, new->bv_len ); new->bv_val[new->bv_len] = '\0'; } else { new->bv_val = (char *) s; } return( new ); } struct berval * ber_str2bv( LDAP_CONST char *s, ber_len_t len, int dup, struct berval *bv) { return ber_str2bv_x( s, len, dup, bv, NULL ); } struct berval * ber_mem2bv_x( LDAP_CONST char *s, ber_len_t len, int dup, struct berval *bv, void *ctx) { struct berval *new; if( s == NULL ) { ber_errno = LBER_ERROR_PARAM; return NULL; } if( bv ) { new = bv; } else { if(( new = ber_memalloc_x( sizeof(struct berval), ctx )) == NULL ) { return NULL; } } new->bv_len = len; if ( dup ) { if ( (new->bv_val = ber_memalloc_x( new->bv_len+1, ctx )) == NULL ) { if ( !bv ) { ber_memfree_x( new, ctx ); } return NULL; } AC_MEMCPY( new->bv_val, s, new->bv_len ); new->bv_val[new->bv_len] = '\0'; } else { new->bv_val = (char *) s; } return( new ); } struct berval * ber_mem2bv( LDAP_CONST char *s, ber_len_t len, int dup, struct berval *bv) { return ber_mem2bv_x( s, len, dup, bv, NULL ); } char * ber_strdup_x( LDAP_CONST char *s, void *ctx ) { char *p; size_t len; #ifdef LDAP_MEMORY_DEBUG assert(s != NULL); /* bv damn better point to something */ #endif if( s == NULL ) { ber_errno = LBER_ERROR_PARAM; return NULL; } len = strlen( s ) + 1; if ( (p = ber_memalloc_x( len, ctx )) != NULL ) { AC_MEMCPY( p, s, len ); } return p; } char * ber_strdup( LDAP_CONST char *s ) { return ber_strdup_x( s, NULL ); } ber_len_t ber_strnlen( LDAP_CONST char *s, ber_len_t len ) { ber_len_t l; for ( l = 0; l < len && s[l] != '\0'; l++ ) ; return l; } char * ber_strndup_x( LDAP_CONST char *s, ber_len_t l, void *ctx ) { char *p; size_t len; #ifdef LDAP_MEMORY_DEBUG assert(s != NULL); /* bv damn better point to something */ #endif if( s == NULL ) { ber_errno = LBER_ERROR_PARAM; return NULL; } len = ber_strnlen( s, l ); if ( (p = ber_memalloc_x( len + 1, ctx )) != NULL ) { AC_MEMCPY( p, s, len ); p[len] = '\0'; } return p; } char * ber_strndup( LDAP_CONST char *s, ber_len_t l ) { return ber_strndup_x( s, l, NULL ); } /* * dst is resized as required by src and the value of src is copied into dst * dst->bv_val must be NULL (and dst->bv_len must be 0), or it must be * alloc'ed with the context ctx */ struct berval * ber_bvreplace_x( struct berval *dst, LDAP_CONST struct berval *src, void *ctx ) { assert( dst != NULL ); assert( !BER_BVISNULL( src ) ); if ( BER_BVISNULL( dst ) || dst->bv_len < src->bv_len ) { dst->bv_val = ber_memrealloc_x( dst->bv_val, src->bv_len + 1, ctx ); } AC_MEMCPY( dst->bv_val, src->bv_val, src->bv_len + 1 ); dst->bv_len = src->bv_len; return dst; } struct berval * ber_bvreplace( struct berval *dst, LDAP_CONST struct berval *src ) { return ber_bvreplace_x( dst, src, NULL ); } void ber_bvarray_free_x( BerVarray a, void *ctx ) { int i; if (a) { BER_MEM_VALID( a ); /* count elements */ for (i=0; a[i].bv_val; i++) ; /* free in reverse order */ for (i--; i>=0; i--) { ber_memfree_x(a[i].bv_val, ctx); } ber_memfree_x(a, ctx); } } void ber_bvarray_free( BerVarray a ) { ber_bvarray_free_x(a, NULL); } int ber_bvarray_dup_x( BerVarray *dst, BerVarray src, void *ctx ) { int i, j; BerVarray new; if ( !src ) { *dst = NULL; return 0; } for (i=0; !BER_BVISNULL( &src[i] ); i++) ; new = ber_memalloc_x(( i+1 ) * sizeof(BerValue), ctx ); if ( !new ) return -1; for (j=0; j. * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (c) 1990 Regents of the University of Michigan. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of Michigan at Ann Arbor. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. */ /* ACKNOWLEDGEMENTS: * This work was originally developed by the University of Michigan * (as part of U-MICH LDAP). */ #include "portable.h" #include #include #include #include #include #ifdef HAVE_CONSOLE_H #include #endif /* HAVE_CONSOLE_H */ #include "lber.h" static void usage( const char *name ) { fprintf( stderr, "usage: %s fmtstring\n", name ); } static char* getbuf( void ) { char *p; static char buf[1024]; if ( fgets( buf, sizeof(buf), stdin ) == NULL ) return NULL; if ( (p = strchr( buf, '\n' )) != NULL ) *p = '\0'; return buf; } int main( int argc, char **argv ) { char *s; int tag; int fd, rc; BerElement *ber; Sockbuf *sb; /* enable debugging */ int ival = -1; ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &ival ); if ( argc < 2 ) { usage( argv[0] ); return( EXIT_FAILURE ); } #ifdef HAVE_CONSOLE_H ccommand( &argv ); cshow( stdout ); if (( fd = open( "lber-test", O_WRONLY|O_CREAT|O_TRUNC|O_BINARY )) < 0 ) { perror( "open" ); return( EXIT_FAILURE ); } #else fd = fileno(stdout); #endif sb = ber_sockbuf_alloc(); ber_sockbuf_add_io( sb, &ber_sockbuf_io_fd, LBER_SBIOD_LEVEL_PROVIDER, (void *)&fd ); if( sb == NULL ) { perror( "ber_sockbuf_alloc_fd" ); return( EXIT_FAILURE ); } if ( (ber = ber_alloc_t( LBER_USE_DER )) == NULL ) { perror( "ber_alloc" ); return( EXIT_FAILURE ); } fprintf(stderr, "encode: start\n" ); if( ber_printf( ber, "{" /*}*/ ) ) { perror( "ber_printf {" /*}*/ ); return( EXIT_FAILURE ); } for ( s = argv[1]; *s; s++ ) { char *buf; char fmt[2]; fmt[0] = *s; fmt[1] = '\0'; fprintf(stderr, "encode: %s\n", fmt ); switch ( *s ) { case 'i': /* int */ case 'b': /* boolean */ case 'e': /* enumeration */ buf = getbuf(); rc = ber_printf( ber, fmt, atoi(buf) ); break; case 'n': /* null */ case '{': /* begin sequence */ case '}': /* end sequence */ case '[': /* begin set */ case ']': /* end set */ rc = ber_printf( ber, fmt ); break; case 'o': /* octet string (non-null terminated) */ case 'B': /* bit string */ buf = getbuf(); rc = ber_printf( ber, fmt, buf, strlen(buf) ); break; case 's': /* string */ buf = getbuf(); rc = ber_printf( ber, fmt, buf ); break; case 't': /* tag for the next element */ buf = getbuf(); tag = atoi(buf); rc = ber_printf( ber, fmt, tag ); break; default: fprintf( stderr, "encode: unknown fmt %c\n", *fmt ); rc = -1; break; } if( rc == -1 ) { perror( "ber_printf" ); return( EXIT_FAILURE ); } } fprintf(stderr, "encode: end\n" ); if( ber_printf( ber, /*{*/ "N}" ) == -1 ) { perror( /*{*/ "ber_printf }" ); return( EXIT_FAILURE ); } if ( ber_flush2( sb, ber, LBER_FLUSH_FREE_ALWAYS ) == -1 ) { perror( "ber_flush2" ); return( EXIT_FAILURE ); } ber_sockbuf_free( sb ); return( EXIT_SUCCESS ); } openldap-2.4.42+dfsg/libraries/liblber/bprint.c0000644000175000017500000001275712563404150020075 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* * Copyright (c) 1991 Regents of the University of Michigan. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of Michigan at Ann Arbor. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. */ /* ACKNOWLEDGEMENTS: * This work was originally developed by the University of Michigan * (as part of U-MICH LDAP). */ #include "portable.h" #include #include #include #include #include "lber-int.h" #define ber_log_check(errlvl, loglvl) ((errlvl) & (loglvl)) BER_LOG_FN ber_int_log_proc = NULL; /* * We don't just set ber_pvt_err_file to stderr here, because in NT, * stderr is a symbol imported from a DLL. As such, the compiler * doesn't recognize the symbol as having a constant address. Thus * we set ber_pvt_err_file to stderr later, when it first gets * referenced. */ FILE *ber_pvt_err_file = NULL; /* * ber errno */ BER_ERRNO_FN ber_int_errno_fn = NULL; int * ber_errno_addr(void) { static int ber_int_errno = LBER_ERROR_NONE; if( ber_int_errno_fn ) { return (*ber_int_errno_fn)(); } return &ber_int_errno; } /* * Print stuff */ void ber_error_print( LDAP_CONST char *data ) { assert( data != NULL ); if (!ber_pvt_err_file) ber_pvt_err_file = stderr; fputs( data, ber_pvt_err_file ); /* Print to both streams */ if (ber_pvt_err_file != stderr) { fputs( data, stderr ); fflush( stderr ); } fflush( ber_pvt_err_file ); } BER_LOG_PRINT_FN ber_pvt_log_print = ber_error_print; /* * lber log */ int ber_pvt_log_output( const char *subsystem, int level, const char *fmt, ... ) { char buf[1024]; va_list vl; va_start( vl, fmt ); if ( ber_int_log_proc != NULL ) { ber_int_log_proc( ber_pvt_err_file, subsystem, level, fmt, vl ); } else { int level; ber_get_option( NULL, LBER_OPT_BER_DEBUG, &level ); buf[sizeof(buf) - 1] = '\0'; vsnprintf( buf, sizeof(buf)-1, fmt, vl ); if ( ber_log_check( LDAP_DEBUG_BER, level ) ) { (*ber_pvt_log_print)( buf ); } } va_end(vl); return 1; } int ber_pvt_log_printf( int errlvl, int loglvl, const char *fmt, ... ) { char buf[1024]; va_list ap; assert( fmt != NULL ); if ( !ber_log_check( errlvl, loglvl )) { return 0; } va_start( ap, fmt ); buf[sizeof(buf) - 1] = '\0'; vsnprintf( buf, sizeof(buf)-1, fmt, ap ); va_end(ap); (*ber_pvt_log_print)( buf ); return 1; } #if 0 static int ber_log_puts(int errlvl, int loglvl, char *buf) { assert( buf != NULL ); if ( !ber_log_check( errlvl, loglvl )) { return 0; } (*ber_pvt_log_print)( buf ); return 1; } #endif /* * Print arbitrary stuff, for debugging. */ int ber_log_bprint(int errlvl, int loglvl, const char *data, ber_len_t len ) { assert( data != NULL ); if ( !ber_log_check( errlvl, loglvl )) { return 0; } ber_bprint(data, len); return 1; } void ber_bprint( LDAP_CONST char *data, ber_len_t len ) { static const char hexdig[] = "0123456789abcdef"; #define BP_OFFSET 9 #define BP_GRAPH 60 #define BP_LEN 80 char line[BP_LEN]; ber_len_t i; assert( data != NULL ); /* in case len is zero */ line[0] = '\n'; line[1] = '\0'; for ( i = 0 ; i < len ; i++ ) { int n = i % 16; unsigned off; if( !n ) { if( i ) (*ber_pvt_log_print)( line ); memset( line, ' ', sizeof(line)-2 ); line[sizeof(line)-2] = '\n'; line[sizeof(line)-1] = '\0'; off = i % 0x0ffffU; line[2] = hexdig[0x0f & (off >> 12)]; line[3] = hexdig[0x0f & (off >> 8)]; line[4] = hexdig[0x0f & (off >> 4)]; line[5] = hexdig[0x0f & off]; line[6] = ':'; } off = BP_OFFSET + n*3 + ((n >= 8)?1:0); line[off] = hexdig[0x0f & ( data[i] >> 4 )]; line[off+1] = hexdig[0x0f & data[i]]; off = BP_GRAPH + n + ((n >= 8)?1:0); if ( isprint( (unsigned char) data[i] )) { line[BP_GRAPH + n] = data[i]; } else { line[BP_GRAPH + n] = '.'; } } (*ber_pvt_log_print)( line ); } int ber_log_dump( int errlvl, int loglvl, BerElement *ber, int inout ) { assert( ber != NULL ); assert( LBER_VALID( ber ) ); if ( !ber_log_check( errlvl, loglvl )) { return 0; } ber_dump(ber, inout); return 1; } void ber_dump( BerElement *ber, int inout ) { char buf[132]; ber_len_t len; assert( ber != NULL ); assert( LBER_VALID( ber ) ); if ( inout == 1 ) { len = ber_pvt_ber_remaining(ber); } else { len = ber_pvt_ber_write(ber); } sprintf( buf, "ber_dump: buf=%p ptr=%p end=%p len=%ld\n", ber->ber_buf, ber->ber_ptr, ber->ber_end, (long) len ); (void) (*ber_pvt_log_print)( buf ); ber_bprint( ber->ber_ptr, len ); } typedef struct seqorset Seqorset; /* Exists for binary compatibility with OpenLDAP 2.4.17-- */ int ber_log_sos_dump( int errlvl, int loglvl, Seqorset *sos ) { return 0; } /* Exists for binary compatibility with OpenLDAP 2.4.17-- */ void ber_sos_dump( Seqorset *sos ) { } openldap-2.4.42+dfsg/libraries/liblber/debug.c0000644000175000017500000000441512563404150017655 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #include "portable.h" #include #include #include #include #include #include #ifdef LDAP_SYSLOG #include #endif #include "ldap_log.h" #include "ldap_defaults.h" #include "lber.h" #include "ldap_pvt.h" static FILE *log_file = NULL; static int debug_lastc = '\n'; int lutil_debug_file( FILE *file ) { log_file = file; ber_set_option( NULL, LBER_OPT_LOG_PRINT_FILE, file ); return 0; } void (lutil_debug)( int debug, int level, const char *fmt, ... ) { char buffer[4096]; va_list vl; int len, off; if ( !(level & debug ) ) return; #ifdef HAVE_WINSOCK if( log_file == NULL ) { log_file = fopen( LDAP_RUNDIR LDAP_DIRSEP "openldap.log", "w" ); if ( log_file == NULL ) { log_file = fopen( "openldap.log", "w" ); if ( log_file == NULL ) return; } ber_set_option( NULL, LBER_OPT_LOG_PRINT_FILE, log_file ); } #endif if (debug_lastc == '\n') { sprintf(buffer, "%08x ", (unsigned) time(0L)); off = 9; } else { off = 0; } va_start( vl, fmt ); len = vsnprintf( buffer+off, sizeof(buffer)-off, fmt, vl ); if (len > sizeof(buffer)-off) len = sizeof(buffer)-off; debug_lastc = buffer[len+off-1]; buffer[sizeof(buffer)-1] = '\0'; if( log_file != NULL ) { fputs( buffer, log_file ); fflush( log_file ); } fputs( buffer, stderr ); va_end( vl ); } #if defined(HAVE_EBCDIC) && defined(LDAP_SYSLOG) #undef syslog void eb_syslog( int pri, const char *fmt, ... ) { char buffer[4096]; va_list vl; va_start( vl, fmt ); vsnprintf( buffer, sizeof(buffer), fmt, vl ); buffer[sizeof(buffer)-1] = '\0'; /* The syslog function appears to only work with pure EBCDIC */ __atoe(buffer); #pragma convlit(suspend) syslog( pri, "%s", buffer ); #pragma convlit(resume) va_end( vl ); } #endif openldap-2.4.42+dfsg/libraries/liblunicode/0000755000175000017500000000000012563404150017275 5ustar ryanryanopenldap-2.4.42+dfsg/libraries/liblunicode/Makefile.in0000644000175000017500000000262312563404150021345 0ustar ryanryan# Makefile.in for LDAP -llunicode # $OpenLDAP$ ## This work is part of OpenLDAP Software . ## ## Copyright 1998-2015 The OpenLDAP Foundation. ## All rights reserved. ## ## Redistribution and use in source and binary forms, with or without ## modification, are permitted only as authorized by the OpenLDAP ## Public License. ## ## A copy of this license is available in the file LICENSE in the ## top-level directory of the distribution or, alternatively, at ## . LIBRARY = liblunicode.a XXDIR = $(srcdir)/ucdata/ XXHEADERS = ucdata.h ure.h uctable.h XXSRCS = ucdata.c ucgendat.c ure.c urestubs.c SRCS = ucstr.c OBJS = ucdata.o ure.o urestubs.o ucstr.o XLIB = $(LIBRARY) XLIBS = $(LDAP_LIBLUTIL_A) $(LDAP_LIBLBER_LA) #PROGRAMS = ucgendat LDAP_INCDIR= ../../include LDAP_LIBDIR= ../../libraries uctable.h: $(XXDIR)/uctable.h $(XXDIR)/uctable.h: $(XXDIR)/ucgendat.c $(srcdir)/UnicodeData.txt $(srcdir)/CompositionExclusions.txt $(MAKE) ucgendat ./ucgendat $(srcdir)/UnicodeData.txt -x $(srcdir)/CompositionExclusions.txt ucgendat: $(XLIBS) ucgendat.o $(LTLINK) -o $@ ucgendat.o $(LIBS) .links : @for i in $(XXSRCS) $(XXHEADERS); do \ $(RM) $$i ; \ ii=`find $(srcdir) -name $$i` ; \ $(LN_S) $$ii . ; \ done touch .links $(XXSRCS) $(XXHEADERS) : .links clean-local: FORCE @$(RM) *.dat .links $(XXHEADERS) ucgendat depend-common: .links openldap-2.4.42+dfsg/libraries/liblunicode/UnicodeData.txt0000644000175000017500000314257512563404150022237 0ustar ryanryan0000;;Cc;0;BN;;;;;N;NULL;;;; 0001;;Cc;0;BN;;;;;N;START OF HEADING;;;; 0002;;Cc;0;BN;;;;;N;START OF TEXT;;;; 0003;;Cc;0;BN;;;;;N;END OF TEXT;;;; 0004;;Cc;0;BN;;;;;N;END OF TRANSMISSION;;;; 0005;;Cc;0;BN;;;;;N;ENQUIRY;;;; 0006;;Cc;0;BN;;;;;N;ACKNOWLEDGE;;;; 0007;;Cc;0;BN;;;;;N;BELL;;;; 0008;;Cc;0;BN;;;;;N;BACKSPACE;;;; 0009;;Cc;0;S;;;;;N;CHARACTER TABULATION;;;; 000A;;Cc;0;B;;;;;N;LINE FEED (LF);;;; 000B;;Cc;0;S;;;;;N;LINE TABULATION;;;; 000C;;Cc;0;WS;;;;;N;FORM FEED (FF);;;; 000D;;Cc;0;B;;;;;N;CARRIAGE RETURN (CR);;;; 000E;;Cc;0;BN;;;;;N;SHIFT OUT;;;; 000F;;Cc;0;BN;;;;;N;SHIFT IN;;;; 0010;;Cc;0;BN;;;;;N;DATA LINK ESCAPE;;;; 0011;;Cc;0;BN;;;;;N;DEVICE CONTROL ONE;;;; 0012;;Cc;0;BN;;;;;N;DEVICE CONTROL TWO;;;; 0013;;Cc;0;BN;;;;;N;DEVICE CONTROL THREE;;;; 0014;;Cc;0;BN;;;;;N;DEVICE CONTROL FOUR;;;; 0015;;Cc;0;BN;;;;;N;NEGATIVE ACKNOWLEDGE;;;; 0016;;Cc;0;BN;;;;;N;SYNCHRONOUS IDLE;;;; 0017;;Cc;0;BN;;;;;N;END OF TRANSMISSION BLOCK;;;; 0018;;Cc;0;BN;;;;;N;CANCEL;;;; 0019;;Cc;0;BN;;;;;N;END OF MEDIUM;;;; 001A;;Cc;0;BN;;;;;N;SUBSTITUTE;;;; 001B;;Cc;0;BN;;;;;N;ESCAPE;;;; 001C;;Cc;0;B;;;;;N;INFORMATION SEPARATOR FOUR;;;; 001D;;Cc;0;B;;;;;N;INFORMATION SEPARATOR THREE;;;; 001E;;Cc;0;B;;;;;N;INFORMATION SEPARATOR TWO;;;; 001F;;Cc;0;S;;;;;N;INFORMATION SEPARATOR ONE;;;; 0020;SPACE;Zs;0;WS;;;;;N;;;;; 0021;EXCLAMATION MARK;Po;0;ON;;;;;N;;;;; 0022;QUOTATION MARK;Po;0;ON;;;;;N;;;;; 0023;NUMBER SIGN;Po;0;ET;;;;;N;;;;; 0024;DOLLAR SIGN;Sc;0;ET;;;;;N;;;;; 0025;PERCENT SIGN;Po;0;ET;;;;;N;;;;; 0026;AMPERSAND;Po;0;ON;;;;;N;;;;; 0027;APOSTROPHE;Po;0;ON;;;;;N;APOSTROPHE-QUOTE;;;; 0028;LEFT PARENTHESIS;Ps;0;ON;;;;;Y;OPENING PARENTHESIS;;;; 0029;RIGHT PARENTHESIS;Pe;0;ON;;;;;Y;CLOSING PARENTHESIS;;;; 002A;ASTERISK;Po;0;ON;;;;;N;;;;; 002B;PLUS SIGN;Sm;0;ET;;;;;N;;;;; 002C;COMMA;Po;0;CS;;;;;N;;;;; 002D;HYPHEN-MINUS;Pd;0;ET;;;;;N;;;;; 002E;FULL STOP;Po;0;CS;;;;;N;PERIOD;;;; 002F;SOLIDUS;Po;0;ES;;;;;N;SLASH;;;; 0030;DIGIT ZERO;Nd;0;EN;;0;0;0;N;;;;; 0031;DIGIT ONE;Nd;0;EN;;1;1;1;N;;;;; 0032;DIGIT TWO;Nd;0;EN;;2;2;2;N;;;;; 0033;DIGIT THREE;Nd;0;EN;;3;3;3;N;;;;; 0034;DIGIT FOUR;Nd;0;EN;;4;4;4;N;;;;; 0035;DIGIT FIVE;Nd;0;EN;;5;5;5;N;;;;; 0036;DIGIT SIX;Nd;0;EN;;6;6;6;N;;;;; 0037;DIGIT SEVEN;Nd;0;EN;;7;7;7;N;;;;; 0038;DIGIT EIGHT;Nd;0;EN;;8;8;8;N;;;;; 0039;DIGIT NINE;Nd;0;EN;;9;9;9;N;;;;; 003A;COLON;Po;0;CS;;;;;N;;;;; 003B;SEMICOLON;Po;0;ON;;;;;N;;;;; 003C;LESS-THAN SIGN;Sm;0;ON;;;;;Y;;;;; 003D;EQUALS SIGN;Sm;0;ON;;;;;N;;;;; 003E;GREATER-THAN SIGN;Sm;0;ON;;;;;Y;;;;; 003F;QUESTION MARK;Po;0;ON;;;;;N;;;;; 0040;COMMERCIAL AT;Po;0;ON;;;;;N;;;;; 0041;LATIN CAPITAL LETTER A;Lu;0;L;;;;;N;;;;0061; 0042;LATIN CAPITAL LETTER B;Lu;0;L;;;;;N;;;;0062; 0043;LATIN CAPITAL LETTER C;Lu;0;L;;;;;N;;;;0063; 0044;LATIN CAPITAL LETTER D;Lu;0;L;;;;;N;;;;0064; 0045;LATIN CAPITAL LETTER E;Lu;0;L;;;;;N;;;;0065; 0046;LATIN CAPITAL LETTER F;Lu;0;L;;;;;N;;;;0066; 0047;LATIN CAPITAL LETTER G;Lu;0;L;;;;;N;;;;0067; 0048;LATIN CAPITAL LETTER H;Lu;0;L;;;;;N;;;;0068; 0049;LATIN CAPITAL LETTER I;Lu;0;L;;;;;N;;;;0069; 004A;LATIN CAPITAL LETTER J;Lu;0;L;;;;;N;;;;006A; 004B;LATIN CAPITAL LETTER K;Lu;0;L;;;;;N;;;;006B; 004C;LATIN CAPITAL LETTER L;Lu;0;L;;;;;N;;;;006C; 004D;LATIN CAPITAL LETTER M;Lu;0;L;;;;;N;;;;006D; 004E;LATIN CAPITAL LETTER N;Lu;0;L;;;;;N;;;;006E; 004F;LATIN CAPITAL LETTER O;Lu;0;L;;;;;N;;;;006F; 0050;LATIN CAPITAL LETTER P;Lu;0;L;;;;;N;;;;0070; 0051;LATIN CAPITAL LETTER Q;Lu;0;L;;;;;N;;;;0071; 0052;LATIN CAPITAL LETTER R;Lu;0;L;;;;;N;;;;0072; 0053;LATIN CAPITAL LETTER S;Lu;0;L;;;;;N;;;;0073; 0054;LATIN CAPITAL LETTER T;Lu;0;L;;;;;N;;;;0074; 0055;LATIN CAPITAL LETTER U;Lu;0;L;;;;;N;;;;0075; 0056;LATIN CAPITAL LETTER V;Lu;0;L;;;;;N;;;;0076; 0057;LATIN CAPITAL LETTER W;Lu;0;L;;;;;N;;;;0077; 0058;LATIN CAPITAL LETTER X;Lu;0;L;;;;;N;;;;0078; 0059;LATIN CAPITAL LETTER Y;Lu;0;L;;;;;N;;;;0079; 005A;LATIN CAPITAL LETTER Z;Lu;0;L;;;;;N;;;;007A; 005B;LEFT SQUARE BRACKET;Ps;0;ON;;;;;Y;OPENING SQUARE BRACKET;;;; 005C;REVERSE SOLIDUS;Po;0;ON;;;;;N;BACKSLASH;;;; 005D;RIGHT SQUARE BRACKET;Pe;0;ON;;;;;Y;CLOSING SQUARE BRACKET;;;; 005E;CIRCUMFLEX ACCENT;Sk;0;ON;;;;;N;SPACING CIRCUMFLEX;;;; 005F;LOW LINE;Pc;0;ON;;;;;N;SPACING UNDERSCORE;;;; 0060;GRAVE ACCENT;Sk;0;ON;;;;;N;SPACING GRAVE;;;; 0061;LATIN SMALL LETTER A;Ll;0;L;;;;;N;;;0041;;0041 0062;LATIN SMALL LETTER B;Ll;0;L;;;;;N;;;0042;;0042 0063;LATIN SMALL LETTER C;Ll;0;L;;;;;N;;;0043;;0043 0064;LATIN SMALL LETTER D;Ll;0;L;;;;;N;;;0044;;0044 0065;LATIN SMALL LETTER E;Ll;0;L;;;;;N;;;0045;;0045 0066;LATIN SMALL LETTER F;Ll;0;L;;;;;N;;;0046;;0046 0067;LATIN SMALL LETTER G;Ll;0;L;;;;;N;;;0047;;0047 0068;LATIN SMALL LETTER H;Ll;0;L;;;;;N;;;0048;;0048 0069;LATIN SMALL LETTER I;Ll;0;L;;;;;N;;;0049;;0049 006A;LATIN SMALL LETTER J;Ll;0;L;;;;;N;;;004A;;004A 006B;LATIN SMALL LETTER K;Ll;0;L;;;;;N;;;004B;;004B 006C;LATIN SMALL LETTER L;Ll;0;L;;;;;N;;;004C;;004C 006D;LATIN SMALL LETTER M;Ll;0;L;;;;;N;;;004D;;004D 006E;LATIN SMALL LETTER N;Ll;0;L;;;;;N;;;004E;;004E 006F;LATIN SMALL LETTER O;Ll;0;L;;;;;N;;;004F;;004F 0070;LATIN SMALL LETTER P;Ll;0;L;;;;;N;;;0050;;0050 0071;LATIN SMALL LETTER Q;Ll;0;L;;;;;N;;;0051;;0051 0072;LATIN SMALL LETTER R;Ll;0;L;;;;;N;;;0052;;0052 0073;LATIN SMALL LETTER S;Ll;0;L;;;;;N;;;0053;;0053 0074;LATIN SMALL LETTER T;Ll;0;L;;;;;N;;;0054;;0054 0075;LATIN SMALL LETTER U;Ll;0;L;;;;;N;;;0055;;0055 0076;LATIN SMALL LETTER V;Ll;0;L;;;;;N;;;0056;;0056 0077;LATIN SMALL LETTER W;Ll;0;L;;;;;N;;;0057;;0057 0078;LATIN SMALL LETTER X;Ll;0;L;;;;;N;;;0058;;0058 0079;LATIN SMALL LETTER Y;Ll;0;L;;;;;N;;;0059;;0059 007A;LATIN SMALL LETTER Z;Ll;0;L;;;;;N;;;005A;;005A 007B;LEFT CURLY BRACKET;Ps;0;ON;;;;;Y;OPENING CURLY BRACKET;;;; 007C;VERTICAL LINE;Sm;0;ON;;;;;N;VERTICAL BAR;;;; 007D;RIGHT CURLY BRACKET;Pe;0;ON;;;;;Y;CLOSING CURLY BRACKET;;;; 007E;TILDE;Sm;0;ON;;;;;N;;;;; 007F;;Cc;0;BN;;;;;N;DELETE;;;; 0080;;Cc;0;BN;;;;;N;;;;; 0081;;Cc;0;BN;;;;;N;;;;; 0082;;Cc;0;BN;;;;;N;BREAK PERMITTED HERE;;;; 0083;;Cc;0;BN;;;;;N;NO BREAK HERE;;;; 0084;;Cc;0;BN;;;;;N;;;;; 0085;;Cc;0;B;;;;;N;NEXT LINE (NEL);;;; 0086;;Cc;0;BN;;;;;N;START OF SELECTED AREA;;;; 0087;;Cc;0;BN;;;;;N;END OF SELECTED AREA;;;; 0088;;Cc;0;BN;;;;;N;CHARACTER TABULATION SET;;;; 0089;;Cc;0;BN;;;;;N;CHARACTER TABULATION WITH JUSTIFICATION;;;; 008A;;Cc;0;BN;;;;;N;LINE TABULATION SET;;;; 008B;;Cc;0;BN;;;;;N;PARTIAL LINE FORWARD;;;; 008C;;Cc;0;BN;;;;;N;PARTIAL LINE BACKWARD;;;; 008D;;Cc;0;BN;;;;;N;REVERSE LINE FEED;;;; 008E;;Cc;0;BN;;;;;N;SINGLE SHIFT TWO;;;; 008F;;Cc;0;BN;;;;;N;SINGLE SHIFT THREE;;;; 0090;;Cc;0;BN;;;;;N;DEVICE CONTROL STRING;;;; 0091;;Cc;0;BN;;;;;N;PRIVATE USE ONE;;;; 0092;;Cc;0;BN;;;;;N;PRIVATE USE TWO;;;; 0093;;Cc;0;BN;;;;;N;SET TRANSMIT STATE;;;; 0094;;Cc;0;BN;;;;;N;CANCEL CHARACTER;;;; 0095;;Cc;0;BN;;;;;N;MESSAGE WAITING;;;; 0096;;Cc;0;BN;;;;;N;START OF GUARDED AREA;;;; 0097;;Cc;0;BN;;;;;N;END OF GUARDED AREA;;;; 0098;;Cc;0;BN;;;;;N;START OF STRING;;;; 0099;;Cc;0;BN;;;;;N;;;;; 009A;;Cc;0;BN;;;;;N;SINGLE CHARACTER INTRODUCER;;;; 009B;;Cc;0;BN;;;;;N;CONTROL SEQUENCE INTRODUCER;;;; 009C;;Cc;0;BN;;;;;N;STRING TERMINATOR;;;; 009D;;Cc;0;BN;;;;;N;OPERATING SYSTEM COMMAND;;;; 009E;;Cc;0;BN;;;;;N;PRIVACY MESSAGE;;;; 009F;;Cc;0;BN;;;;;N;APPLICATION PROGRAM COMMAND;;;; 00A0;NO-BREAK SPACE;Zs;0;CS; 0020;;;;N;NON-BREAKING SPACE;;;; 00A1;INVERTED EXCLAMATION MARK;Po;0;ON;;;;;N;;;;; 00A2;CENT SIGN;Sc;0;ET;;;;;N;;;;; 00A3;POUND SIGN;Sc;0;ET;;;;;N;;;;; 00A4;CURRENCY SIGN;Sc;0;ET;;;;;N;;;;; 00A5;YEN SIGN;Sc;0;ET;;;;;N;;;;; 00A6;BROKEN BAR;So;0;ON;;;;;N;BROKEN VERTICAL BAR;;;; 00A7;SECTION SIGN;So;0;ON;;;;;N;;;;; 00A8;DIAERESIS;Sk;0;ON; 0020 0308;;;;N;SPACING DIAERESIS;;;; 00A9;COPYRIGHT SIGN;So;0;ON;;;;;N;;;;; 00AA;FEMININE ORDINAL INDICATOR;Ll;0;L; 0061;;;;N;;;;; 00AB;LEFT-POINTING DOUBLE ANGLE QUOTATION MARK;Pi;0;ON;;;;;Y;LEFT POINTING GUILLEMET;*;;; 00AC;NOT SIGN;Sm;0;ON;;;;;N;;;;; 00AD;SOFT HYPHEN;Pd;0;ON;;;;;N;;;;; 00AE;REGISTERED SIGN;So;0;ON;;;;;N;REGISTERED TRADE MARK SIGN;;;; 00AF;MACRON;Sk;0;ON; 0020 0304;;;;N;SPACING MACRON;;;; 00B0;DEGREE SIGN;So;0;ET;;;;;N;;;;; 00B1;PLUS-MINUS SIGN;Sm;0;ET;;;;;N;PLUS-OR-MINUS SIGN;;;; 00B2;SUPERSCRIPT TWO;No;0;EN; 0032;2;2;2;N;SUPERSCRIPT DIGIT TWO;;;; 00B3;SUPERSCRIPT THREE;No;0;EN; 0033;3;3;3;N;SUPERSCRIPT DIGIT THREE;;;; 00B4;ACUTE ACCENT;Sk;0;ON; 0020 0301;;;;N;SPACING ACUTE;;;; 00B5;MICRO SIGN;Ll;0;L; 03BC;;;;N;;;039C;;039C 00B6;PILCROW SIGN;So;0;ON;;;;;N;PARAGRAPH SIGN;;;; 00B7;MIDDLE DOT;Po;0;ON;;;;;N;;;;; 00B8;CEDILLA;Sk;0;ON; 0020 0327;;;;N;SPACING CEDILLA;;;; 00B9;SUPERSCRIPT ONE;No;0;EN; 0031;1;1;1;N;SUPERSCRIPT DIGIT ONE;;;; 00BA;MASCULINE ORDINAL INDICATOR;Ll;0;L; 006F;;;;N;;;;; 00BB;RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK;Pf;0;ON;;;;;Y;RIGHT POINTING GUILLEMET;*;;; 00BC;VULGAR FRACTION ONE QUARTER;No;0;ON; 0031 2044 0034;;;1/4;N;FRACTION ONE QUARTER;;;; 00BD;VULGAR FRACTION ONE HALF;No;0;ON; 0031 2044 0032;;;1/2;N;FRACTION ONE HALF;;;; 00BE;VULGAR FRACTION THREE QUARTERS;No;0;ON; 0033 2044 0034;;;3/4;N;FRACTION THREE QUARTERS;;;; 00BF;INVERTED QUESTION MARK;Po;0;ON;;;;;N;;;;; 00C0;LATIN CAPITAL LETTER A WITH GRAVE;Lu;0;L;0041 0300;;;;N;LATIN CAPITAL LETTER A GRAVE;;;00E0; 00C1;LATIN CAPITAL LETTER A WITH ACUTE;Lu;0;L;0041 0301;;;;N;LATIN CAPITAL LETTER A ACUTE;;;00E1; 00C2;LATIN CAPITAL LETTER A WITH CIRCUMFLEX;Lu;0;L;0041 0302;;;;N;LATIN CAPITAL LETTER A CIRCUMFLEX;;;00E2; 00C3;LATIN CAPITAL LETTER A WITH TILDE;Lu;0;L;0041 0303;;;;N;LATIN CAPITAL LETTER A TILDE;;;00E3; 00C4;LATIN CAPITAL LETTER A WITH DIAERESIS;Lu;0;L;0041 0308;;;;N;LATIN CAPITAL LETTER A DIAERESIS;;;00E4; 00C5;LATIN CAPITAL LETTER A WITH RING ABOVE;Lu;0;L;0041 030A;;;;N;LATIN CAPITAL LETTER A RING;;;00E5; 00C6;LATIN CAPITAL LETTER AE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER A E;ash *;;00E6; 00C7;LATIN CAPITAL LETTER C WITH CEDILLA;Lu;0;L;0043 0327;;;;N;LATIN CAPITAL LETTER C CEDILLA;;;00E7; 00C8;LATIN CAPITAL LETTER E WITH GRAVE;Lu;0;L;0045 0300;;;;N;LATIN CAPITAL LETTER E GRAVE;;;00E8; 00C9;LATIN CAPITAL LETTER E WITH ACUTE;Lu;0;L;0045 0301;;;;N;LATIN CAPITAL LETTER E ACUTE;;;00E9; 00CA;LATIN CAPITAL LETTER E WITH CIRCUMFLEX;Lu;0;L;0045 0302;;;;N;LATIN CAPITAL LETTER E CIRCUMFLEX;;;00EA; 00CB;LATIN CAPITAL LETTER E WITH DIAERESIS;Lu;0;L;0045 0308;;;;N;LATIN CAPITAL LETTER E DIAERESIS;;;00EB; 00CC;LATIN CAPITAL LETTER I WITH GRAVE;Lu;0;L;0049 0300;;;;N;LATIN CAPITAL LETTER I GRAVE;;;00EC; 00CD;LATIN CAPITAL LETTER I WITH ACUTE;Lu;0;L;0049 0301;;;;N;LATIN CAPITAL LETTER I ACUTE;;;00ED; 00CE;LATIN CAPITAL LETTER I WITH CIRCUMFLEX;Lu;0;L;0049 0302;;;;N;LATIN CAPITAL LETTER I CIRCUMFLEX;;;00EE; 00CF;LATIN CAPITAL LETTER I WITH DIAERESIS;Lu;0;L;0049 0308;;;;N;LATIN CAPITAL LETTER I DIAERESIS;;;00EF; 00D0;LATIN CAPITAL LETTER ETH;Lu;0;L;;;;;N;;Icelandic;;00F0; 00D1;LATIN CAPITAL LETTER N WITH TILDE;Lu;0;L;004E 0303;;;;N;LATIN CAPITAL LETTER N TILDE;;;00F1; 00D2;LATIN CAPITAL LETTER O WITH GRAVE;Lu;0;L;004F 0300;;;;N;LATIN CAPITAL LETTER O GRAVE;;;00F2; 00D3;LATIN CAPITAL LETTER O WITH ACUTE;Lu;0;L;004F 0301;;;;N;LATIN CAPITAL LETTER O ACUTE;;;00F3; 00D4;LATIN CAPITAL LETTER O WITH CIRCUMFLEX;Lu;0;L;004F 0302;;;;N;LATIN CAPITAL LETTER O CIRCUMFLEX;;;00F4; 00D5;LATIN CAPITAL LETTER O WITH TILDE;Lu;0;L;004F 0303;;;;N;LATIN CAPITAL LETTER O TILDE;;;00F5; 00D6;LATIN CAPITAL LETTER O WITH DIAERESIS;Lu;0;L;004F 0308;;;;N;LATIN CAPITAL LETTER O DIAERESIS;;;00F6; 00D7;MULTIPLICATION SIGN;Sm;0;ON;;;;;N;;;;; 00D8;LATIN CAPITAL LETTER O WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER O SLASH;;;00F8; 00D9;LATIN CAPITAL LETTER U WITH GRAVE;Lu;0;L;0055 0300;;;;N;LATIN CAPITAL LETTER U GRAVE;;;00F9; 00DA;LATIN CAPITAL LETTER U WITH ACUTE;Lu;0;L;0055 0301;;;;N;LATIN CAPITAL LETTER U ACUTE;;;00FA; 00DB;LATIN CAPITAL LETTER U WITH CIRCUMFLEX;Lu;0;L;0055 0302;;;;N;LATIN CAPITAL LETTER U CIRCUMFLEX;;;00FB; 00DC;LATIN CAPITAL LETTER U WITH DIAERESIS;Lu;0;L;0055 0308;;;;N;LATIN CAPITAL LETTER U DIAERESIS;;;00FC; 00DD;LATIN CAPITAL LETTER Y WITH ACUTE;Lu;0;L;0059 0301;;;;N;LATIN CAPITAL LETTER Y ACUTE;;;00FD; 00DE;LATIN CAPITAL LETTER THORN;Lu;0;L;;;;;N;;Icelandic;;00FE; 00DF;LATIN SMALL LETTER SHARP S;Ll;0;L;;;;;N;;German;;; 00E0;LATIN SMALL LETTER A WITH GRAVE;Ll;0;L;0061 0300;;;;N;LATIN SMALL LETTER A GRAVE;;00C0;;00C0 00E1;LATIN SMALL LETTER A WITH ACUTE;Ll;0;L;0061 0301;;;;N;LATIN SMALL LETTER A ACUTE;;00C1;;00C1 00E2;LATIN SMALL LETTER A WITH CIRCUMFLEX;Ll;0;L;0061 0302;;;;N;LATIN SMALL LETTER A CIRCUMFLEX;;00C2;;00C2 00E3;LATIN SMALL LETTER A WITH TILDE;Ll;0;L;0061 0303;;;;N;LATIN SMALL LETTER A TILDE;;00C3;;00C3 00E4;LATIN SMALL LETTER A WITH DIAERESIS;Ll;0;L;0061 0308;;;;N;LATIN SMALL LETTER A DIAERESIS;;00C4;;00C4 00E5;LATIN SMALL LETTER A WITH RING ABOVE;Ll;0;L;0061 030A;;;;N;LATIN SMALL LETTER A RING;;00C5;;00C5 00E6;LATIN SMALL LETTER AE;Ll;0;L;;;;;N;LATIN SMALL LETTER A E;ash *;00C6;;00C6 00E7;LATIN SMALL LETTER C WITH CEDILLA;Ll;0;L;0063 0327;;;;N;LATIN SMALL LETTER C CEDILLA;;00C7;;00C7 00E8;LATIN SMALL LETTER E WITH GRAVE;Ll;0;L;0065 0300;;;;N;LATIN SMALL LETTER E GRAVE;;00C8;;00C8 00E9;LATIN SMALL LETTER E WITH ACUTE;Ll;0;L;0065 0301;;;;N;LATIN SMALL LETTER E ACUTE;;00C9;;00C9 00EA;LATIN SMALL LETTER E WITH CIRCUMFLEX;Ll;0;L;0065 0302;;;;N;LATIN SMALL LETTER E CIRCUMFLEX;;00CA;;00CA 00EB;LATIN SMALL LETTER E WITH DIAERESIS;Ll;0;L;0065 0308;;;;N;LATIN SMALL LETTER E DIAERESIS;;00CB;;00CB 00EC;LATIN SMALL LETTER I WITH GRAVE;Ll;0;L;0069 0300;;;;N;LATIN SMALL LETTER I GRAVE;;00CC;;00CC 00ED;LATIN SMALL LETTER I WITH ACUTE;Ll;0;L;0069 0301;;;;N;LATIN SMALL LETTER I ACUTE;;00CD;;00CD 00EE;LATIN SMALL LETTER I WITH CIRCUMFLEX;Ll;0;L;0069 0302;;;;N;LATIN SMALL LETTER I CIRCUMFLEX;;00CE;;00CE 00EF;LATIN SMALL LETTER I WITH DIAERESIS;Ll;0;L;0069 0308;;;;N;LATIN SMALL LETTER I DIAERESIS;;00CF;;00CF 00F0;LATIN SMALL LETTER ETH;Ll;0;L;;;;;N;;Icelandic;00D0;;00D0 00F1;LATIN SMALL LETTER N WITH TILDE;Ll;0;L;006E 0303;;;;N;LATIN SMALL LETTER N TILDE;;00D1;;00D1 00F2;LATIN SMALL LETTER O WITH GRAVE;Ll;0;L;006F 0300;;;;N;LATIN SMALL LETTER O GRAVE;;00D2;;00D2 00F3;LATIN SMALL LETTER O WITH ACUTE;Ll;0;L;006F 0301;;;;N;LATIN SMALL LETTER O ACUTE;;00D3;;00D3 00F4;LATIN SMALL LETTER O WITH CIRCUMFLEX;Ll;0;L;006F 0302;;;;N;LATIN SMALL LETTER O CIRCUMFLEX;;00D4;;00D4 00F5;LATIN SMALL LETTER O WITH TILDE;Ll;0;L;006F 0303;;;;N;LATIN SMALL LETTER O TILDE;;00D5;;00D5 00F6;LATIN SMALL LETTER O WITH DIAERESIS;Ll;0;L;006F 0308;;;;N;LATIN SMALL LETTER O DIAERESIS;;00D6;;00D6 00F7;DIVISION SIGN;Sm;0;ON;;;;;N;;;;; 00F8;LATIN SMALL LETTER O WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER O SLASH;;00D8;;00D8 00F9;LATIN SMALL LETTER U WITH GRAVE;Ll;0;L;0075 0300;;;;N;LATIN SMALL LETTER U GRAVE;;00D9;;00D9 00FA;LATIN SMALL LETTER U WITH ACUTE;Ll;0;L;0075 0301;;;;N;LATIN SMALL LETTER U ACUTE;;00DA;;00DA 00FB;LATIN SMALL LETTER U WITH CIRCUMFLEX;Ll;0;L;0075 0302;;;;N;LATIN SMALL LETTER U CIRCUMFLEX;;00DB;;00DB 00FC;LATIN SMALL LETTER U WITH DIAERESIS;Ll;0;L;0075 0308;;;;N;LATIN SMALL LETTER U DIAERESIS;;00DC;;00DC 00FD;LATIN SMALL LETTER Y WITH ACUTE;Ll;0;L;0079 0301;;;;N;LATIN SMALL LETTER Y ACUTE;;00DD;;00DD 00FE;LATIN SMALL LETTER THORN;Ll;0;L;;;;;N;;Icelandic;00DE;;00DE 00FF;LATIN SMALL LETTER Y WITH DIAERESIS;Ll;0;L;0079 0308;;;;N;LATIN SMALL LETTER Y DIAERESIS;;0178;;0178 0100;LATIN CAPITAL LETTER A WITH MACRON;Lu;0;L;0041 0304;;;;N;LATIN CAPITAL LETTER A MACRON;;;0101; 0101;LATIN SMALL LETTER A WITH MACRON;Ll;0;L;0061 0304;;;;N;LATIN SMALL LETTER A MACRON;;0100;;0100 0102;LATIN CAPITAL LETTER A WITH BREVE;Lu;0;L;0041 0306;;;;N;LATIN CAPITAL LETTER A BREVE;;;0103; 0103;LATIN SMALL LETTER A WITH BREVE;Ll;0;L;0061 0306;;;;N;LATIN SMALL LETTER A BREVE;;0102;;0102 0104;LATIN CAPITAL LETTER A WITH OGONEK;Lu;0;L;0041 0328;;;;N;LATIN CAPITAL LETTER A OGONEK;;;0105; 0105;LATIN SMALL LETTER A WITH OGONEK;Ll;0;L;0061 0328;;;;N;LATIN SMALL LETTER A OGONEK;;0104;;0104 0106;LATIN CAPITAL LETTER C WITH ACUTE;Lu;0;L;0043 0301;;;;N;LATIN CAPITAL LETTER C ACUTE;;;0107; 0107;LATIN SMALL LETTER C WITH ACUTE;Ll;0;L;0063 0301;;;;N;LATIN SMALL LETTER C ACUTE;;0106;;0106 0108;LATIN CAPITAL LETTER C WITH CIRCUMFLEX;Lu;0;L;0043 0302;;;;N;LATIN CAPITAL LETTER C CIRCUMFLEX;;;0109; 0109;LATIN SMALL LETTER C WITH CIRCUMFLEX;Ll;0;L;0063 0302;;;;N;LATIN SMALL LETTER C CIRCUMFLEX;;0108;;0108 010A;LATIN CAPITAL LETTER C WITH DOT ABOVE;Lu;0;L;0043 0307;;;;N;LATIN CAPITAL LETTER C DOT;;;010B; 010B;LATIN SMALL LETTER C WITH DOT ABOVE;Ll;0;L;0063 0307;;;;N;LATIN SMALL LETTER C DOT;;010A;;010A 010C;LATIN CAPITAL LETTER C WITH CARON;Lu;0;L;0043 030C;;;;N;LATIN CAPITAL LETTER C HACEK;;;010D; 010D;LATIN SMALL LETTER C WITH CARON;Ll;0;L;0063 030C;;;;N;LATIN SMALL LETTER C HACEK;;010C;;010C 010E;LATIN CAPITAL LETTER D WITH CARON;Lu;0;L;0044 030C;;;;N;LATIN CAPITAL LETTER D HACEK;;;010F; 010F;LATIN SMALL LETTER D WITH CARON;Ll;0;L;0064 030C;;;;N;LATIN SMALL LETTER D HACEK;;010E;;010E 0110;LATIN CAPITAL LETTER D WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER D BAR;;;0111; 0111;LATIN SMALL LETTER D WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER D BAR;;0110;;0110 0112;LATIN CAPITAL LETTER E WITH MACRON;Lu;0;L;0045 0304;;;;N;LATIN CAPITAL LETTER E MACRON;;;0113; 0113;LATIN SMALL LETTER E WITH MACRON;Ll;0;L;0065 0304;;;;N;LATIN SMALL LETTER E MACRON;;0112;;0112 0114;LATIN CAPITAL LETTER E WITH BREVE;Lu;0;L;0045 0306;;;;N;LATIN CAPITAL LETTER E BREVE;;;0115; 0115;LATIN SMALL LETTER E WITH BREVE;Ll;0;L;0065 0306;;;;N;LATIN SMALL LETTER E BREVE;;0114;;0114 0116;LATIN CAPITAL LETTER E WITH DOT ABOVE;Lu;0;L;0045 0307;;;;N;LATIN CAPITAL LETTER E DOT;;;0117; 0117;LATIN SMALL LETTER E WITH DOT ABOVE;Ll;0;L;0065 0307;;;;N;LATIN SMALL LETTER E DOT;;0116;;0116 0118;LATIN CAPITAL LETTER E WITH OGONEK;Lu;0;L;0045 0328;;;;N;LATIN CAPITAL LETTER E OGONEK;;;0119; 0119;LATIN SMALL LETTER E WITH OGONEK;Ll;0;L;0065 0328;;;;N;LATIN SMALL LETTER E OGONEK;;0118;;0118 011A;LATIN CAPITAL LETTER E WITH CARON;Lu;0;L;0045 030C;;;;N;LATIN CAPITAL LETTER E HACEK;;;011B; 011B;LATIN SMALL LETTER E WITH CARON;Ll;0;L;0065 030C;;;;N;LATIN SMALL LETTER E HACEK;;011A;;011A 011C;LATIN CAPITAL LETTER G WITH CIRCUMFLEX;Lu;0;L;0047 0302;;;;N;LATIN CAPITAL LETTER G CIRCUMFLEX;;;011D; 011D;LATIN SMALL LETTER G WITH CIRCUMFLEX;Ll;0;L;0067 0302;;;;N;LATIN SMALL LETTER G CIRCUMFLEX;;011C;;011C 011E;LATIN CAPITAL LETTER G WITH BREVE;Lu;0;L;0047 0306;;;;N;LATIN CAPITAL LETTER G BREVE;;;011F; 011F;LATIN SMALL LETTER G WITH BREVE;Ll;0;L;0067 0306;;;;N;LATIN SMALL LETTER G BREVE;;011E;;011E 0120;LATIN CAPITAL LETTER G WITH DOT ABOVE;Lu;0;L;0047 0307;;;;N;LATIN CAPITAL LETTER G DOT;;;0121; 0121;LATIN SMALL LETTER G WITH DOT ABOVE;Ll;0;L;0067 0307;;;;N;LATIN SMALL LETTER G DOT;;0120;;0120 0122;LATIN CAPITAL LETTER G WITH CEDILLA;Lu;0;L;0047 0327;;;;N;LATIN CAPITAL LETTER G CEDILLA;;;0123; 0123;LATIN SMALL LETTER G WITH CEDILLA;Ll;0;L;0067 0327;;;;N;LATIN SMALL LETTER G CEDILLA;;0122;;0122 0124;LATIN CAPITAL LETTER H WITH CIRCUMFLEX;Lu;0;L;0048 0302;;;;N;LATIN CAPITAL LETTER H CIRCUMFLEX;;;0125; 0125;LATIN SMALL LETTER H WITH CIRCUMFLEX;Ll;0;L;0068 0302;;;;N;LATIN SMALL LETTER H CIRCUMFLEX;;0124;;0124 0126;LATIN CAPITAL LETTER H WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER H BAR;;;0127; 0127;LATIN SMALL LETTER H WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER H BAR;;0126;;0126 0128;LATIN CAPITAL LETTER I WITH TILDE;Lu;0;L;0049 0303;;;;N;LATIN CAPITAL LETTER I TILDE;;;0129; 0129;LATIN SMALL LETTER I WITH TILDE;Ll;0;L;0069 0303;;;;N;LATIN SMALL LETTER I TILDE;;0128;;0128 012A;LATIN CAPITAL LETTER I WITH MACRON;Lu;0;L;0049 0304;;;;N;LATIN CAPITAL LETTER I MACRON;;;012B; 012B;LATIN SMALL LETTER I WITH MACRON;Ll;0;L;0069 0304;;;;N;LATIN SMALL LETTER I MACRON;;012A;;012A 012C;LATIN CAPITAL LETTER I WITH BREVE;Lu;0;L;0049 0306;;;;N;LATIN CAPITAL LETTER I BREVE;;;012D; 012D;LATIN SMALL LETTER I WITH BREVE;Ll;0;L;0069 0306;;;;N;LATIN SMALL LETTER I BREVE;;012C;;012C 012E;LATIN CAPITAL LETTER I WITH OGONEK;Lu;0;L;0049 0328;;;;N;LATIN CAPITAL LETTER I OGONEK;;;012F; 012F;LATIN SMALL LETTER I WITH OGONEK;Ll;0;L;0069 0328;;;;N;LATIN SMALL LETTER I OGONEK;;012E;;012E 0130;LATIN CAPITAL LETTER I WITH DOT ABOVE;Lu;0;L;0049 0307;;;;N;LATIN CAPITAL LETTER I DOT;;;0069; 0131;LATIN SMALL LETTER DOTLESS I;Ll;0;L;;;;;N;;;0049;;0049 0132;LATIN CAPITAL LIGATURE IJ;Lu;0;L; 0049 004A;;;;N;LATIN CAPITAL LETTER I J;;;0133; 0133;LATIN SMALL LIGATURE IJ;Ll;0;L; 0069 006A;;;;N;LATIN SMALL LETTER I J;;0132;;0132 0134;LATIN CAPITAL LETTER J WITH CIRCUMFLEX;Lu;0;L;004A 0302;;;;N;LATIN CAPITAL LETTER J CIRCUMFLEX;;;0135; 0135;LATIN SMALL LETTER J WITH CIRCUMFLEX;Ll;0;L;006A 0302;;;;N;LATIN SMALL LETTER J CIRCUMFLEX;;0134;;0134 0136;LATIN CAPITAL LETTER K WITH CEDILLA;Lu;0;L;004B 0327;;;;N;LATIN CAPITAL LETTER K CEDILLA;;;0137; 0137;LATIN SMALL LETTER K WITH CEDILLA;Ll;0;L;006B 0327;;;;N;LATIN SMALL LETTER K CEDILLA;;0136;;0136 0138;LATIN SMALL LETTER KRA;Ll;0;L;;;;;N;;Greenlandic;;; 0139;LATIN CAPITAL LETTER L WITH ACUTE;Lu;0;L;004C 0301;;;;N;LATIN CAPITAL LETTER L ACUTE;;;013A; 013A;LATIN SMALL LETTER L WITH ACUTE;Ll;0;L;006C 0301;;;;N;LATIN SMALL LETTER L ACUTE;;0139;;0139 013B;LATIN CAPITAL LETTER L WITH CEDILLA;Lu;0;L;004C 0327;;;;N;LATIN CAPITAL LETTER L CEDILLA;;;013C; 013C;LATIN SMALL LETTER L WITH CEDILLA;Ll;0;L;006C 0327;;;;N;LATIN SMALL LETTER L CEDILLA;;013B;;013B 013D;LATIN CAPITAL LETTER L WITH CARON;Lu;0;L;004C 030C;;;;N;LATIN CAPITAL LETTER L HACEK;;;013E; 013E;LATIN SMALL LETTER L WITH CARON;Ll;0;L;006C 030C;;;;N;LATIN SMALL LETTER L HACEK;;013D;;013D 013F;LATIN CAPITAL LETTER L WITH MIDDLE DOT;Lu;0;L; 004C 00B7;;;;N;;;;0140; 0140;LATIN SMALL LETTER L WITH MIDDLE DOT;Ll;0;L; 006C 00B7;;;;N;;;013F;;013F 0141;LATIN CAPITAL LETTER L WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER L SLASH;;;0142; 0142;LATIN SMALL LETTER L WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER L SLASH;;0141;;0141 0143;LATIN CAPITAL LETTER N WITH ACUTE;Lu;0;L;004E 0301;;;;N;LATIN CAPITAL LETTER N ACUTE;;;0144; 0144;LATIN SMALL LETTER N WITH ACUTE;Ll;0;L;006E 0301;;;;N;LATIN SMALL LETTER N ACUTE;;0143;;0143 0145;LATIN CAPITAL LETTER N WITH CEDILLA;Lu;0;L;004E 0327;;;;N;LATIN CAPITAL LETTER N CEDILLA;;;0146; 0146;LATIN SMALL LETTER N WITH CEDILLA;Ll;0;L;006E 0327;;;;N;LATIN SMALL LETTER N CEDILLA;;0145;;0145 0147;LATIN CAPITAL LETTER N WITH CARON;Lu;0;L;004E 030C;;;;N;LATIN CAPITAL LETTER N HACEK;;;0148; 0148;LATIN SMALL LETTER N WITH CARON;Ll;0;L;006E 030C;;;;N;LATIN SMALL LETTER N HACEK;;0147;;0147 0149;LATIN SMALL LETTER N PRECEDED BY APOSTROPHE;Ll;0;L; 02BC 006E;;;;N;LATIN SMALL LETTER APOSTROPHE N;;;; 014A;LATIN CAPITAL LETTER ENG;Lu;0;L;;;;;N;;Sami;;014B; 014B;LATIN SMALL LETTER ENG;Ll;0;L;;;;;N;;Sami;014A;;014A 014C;LATIN CAPITAL LETTER O WITH MACRON;Lu;0;L;004F 0304;;;;N;LATIN CAPITAL LETTER O MACRON;;;014D; 014D;LATIN SMALL LETTER O WITH MACRON;Ll;0;L;006F 0304;;;;N;LATIN SMALL LETTER O MACRON;;014C;;014C 014E;LATIN CAPITAL LETTER O WITH BREVE;Lu;0;L;004F 0306;;;;N;LATIN CAPITAL LETTER O BREVE;;;014F; 014F;LATIN SMALL LETTER O WITH BREVE;Ll;0;L;006F 0306;;;;N;LATIN SMALL LETTER O BREVE;;014E;;014E 0150;LATIN CAPITAL LETTER O WITH DOUBLE ACUTE;Lu;0;L;004F 030B;;;;N;LATIN CAPITAL LETTER O DOUBLE ACUTE;;;0151; 0151;LATIN SMALL LETTER O WITH DOUBLE ACUTE;Ll;0;L;006F 030B;;;;N;LATIN SMALL LETTER O DOUBLE ACUTE;;0150;;0150 0152;LATIN CAPITAL LIGATURE OE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER O E;;;0153; 0153;LATIN SMALL LIGATURE OE;Ll;0;L;;;;;N;LATIN SMALL LETTER O E;;0152;;0152 0154;LATIN CAPITAL LETTER R WITH ACUTE;Lu;0;L;0052 0301;;;;N;LATIN CAPITAL LETTER R ACUTE;;;0155; 0155;LATIN SMALL LETTER R WITH ACUTE;Ll;0;L;0072 0301;;;;N;LATIN SMALL LETTER R ACUTE;;0154;;0154 0156;LATIN CAPITAL LETTER R WITH CEDILLA;Lu;0;L;0052 0327;;;;N;LATIN CAPITAL LETTER R CEDILLA;;;0157; 0157;LATIN SMALL LETTER R WITH CEDILLA;Ll;0;L;0072 0327;;;;N;LATIN SMALL LETTER R CEDILLA;;0156;;0156 0158;LATIN CAPITAL LETTER R WITH CARON;Lu;0;L;0052 030C;;;;N;LATIN CAPITAL LETTER R HACEK;;;0159; 0159;LATIN SMALL LETTER R WITH CARON;Ll;0;L;0072 030C;;;;N;LATIN SMALL LETTER R HACEK;;0158;;0158 015A;LATIN CAPITAL LETTER S WITH ACUTE;Lu;0;L;0053 0301;;;;N;LATIN CAPITAL LETTER S ACUTE;;;015B; 015B;LATIN SMALL LETTER S WITH ACUTE;Ll;0;L;0073 0301;;;;N;LATIN SMALL LETTER S ACUTE;;015A;;015A 015C;LATIN CAPITAL LETTER S WITH CIRCUMFLEX;Lu;0;L;0053 0302;;;;N;LATIN CAPITAL LETTER S CIRCUMFLEX;;;015D; 015D;LATIN SMALL LETTER S WITH CIRCUMFLEX;Ll;0;L;0073 0302;;;;N;LATIN SMALL LETTER S CIRCUMFLEX;;015C;;015C 015E;LATIN CAPITAL LETTER S WITH CEDILLA;Lu;0;L;0053 0327;;;;N;LATIN CAPITAL LETTER S CEDILLA;*;;015F; 015F;LATIN SMALL LETTER S WITH CEDILLA;Ll;0;L;0073 0327;;;;N;LATIN SMALL LETTER S CEDILLA;*;015E;;015E 0160;LATIN CAPITAL LETTER S WITH CARON;Lu;0;L;0053 030C;;;;N;LATIN CAPITAL LETTER S HACEK;;;0161; 0161;LATIN SMALL LETTER S WITH CARON;Ll;0;L;0073 030C;;;;N;LATIN SMALL LETTER S HACEK;;0160;;0160 0162;LATIN CAPITAL LETTER T WITH CEDILLA;Lu;0;L;0054 0327;;;;N;LATIN CAPITAL LETTER T CEDILLA;*;;0163; 0163;LATIN SMALL LETTER T WITH CEDILLA;Ll;0;L;0074 0327;;;;N;LATIN SMALL LETTER T CEDILLA;*;0162;;0162 0164;LATIN CAPITAL LETTER T WITH CARON;Lu;0;L;0054 030C;;;;N;LATIN CAPITAL LETTER T HACEK;;;0165; 0165;LATIN SMALL LETTER T WITH CARON;Ll;0;L;0074 030C;;;;N;LATIN SMALL LETTER T HACEK;;0164;;0164 0166;LATIN CAPITAL LETTER T WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER T BAR;;;0167; 0167;LATIN SMALL LETTER T WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER T BAR;;0166;;0166 0168;LATIN CAPITAL LETTER U WITH TILDE;Lu;0;L;0055 0303;;;;N;LATIN CAPITAL LETTER U TILDE;;;0169; 0169;LATIN SMALL LETTER U WITH TILDE;Ll;0;L;0075 0303;;;;N;LATIN SMALL LETTER U TILDE;;0168;;0168 016A;LATIN CAPITAL LETTER U WITH MACRON;Lu;0;L;0055 0304;;;;N;LATIN CAPITAL LETTER U MACRON;;;016B; 016B;LATIN SMALL LETTER U WITH MACRON;Ll;0;L;0075 0304;;;;N;LATIN SMALL LETTER U MACRON;;016A;;016A 016C;LATIN CAPITAL LETTER U WITH BREVE;Lu;0;L;0055 0306;;;;N;LATIN CAPITAL LETTER U BREVE;;;016D; 016D;LATIN SMALL LETTER U WITH BREVE;Ll;0;L;0075 0306;;;;N;LATIN SMALL LETTER U BREVE;;016C;;016C 016E;LATIN CAPITAL LETTER U WITH RING ABOVE;Lu;0;L;0055 030A;;;;N;LATIN CAPITAL LETTER U RING;;;016F; 016F;LATIN SMALL LETTER U WITH RING ABOVE;Ll;0;L;0075 030A;;;;N;LATIN SMALL LETTER U RING;;016E;;016E 0170;LATIN CAPITAL LETTER U WITH DOUBLE ACUTE;Lu;0;L;0055 030B;;;;N;LATIN CAPITAL LETTER U DOUBLE ACUTE;;;0171; 0171;LATIN SMALL LETTER U WITH DOUBLE ACUTE;Ll;0;L;0075 030B;;;;N;LATIN SMALL LETTER U DOUBLE ACUTE;;0170;;0170 0172;LATIN CAPITAL LETTER U WITH OGONEK;Lu;0;L;0055 0328;;;;N;LATIN CAPITAL LETTER U OGONEK;;;0173; 0173;LATIN SMALL LETTER U WITH OGONEK;Ll;0;L;0075 0328;;;;N;LATIN SMALL LETTER U OGONEK;;0172;;0172 0174;LATIN CAPITAL LETTER W WITH CIRCUMFLEX;Lu;0;L;0057 0302;;;;N;LATIN CAPITAL LETTER W CIRCUMFLEX;;;0175; 0175;LATIN SMALL LETTER W WITH CIRCUMFLEX;Ll;0;L;0077 0302;;;;N;LATIN SMALL LETTER W CIRCUMFLEX;;0174;;0174 0176;LATIN CAPITAL LETTER Y WITH CIRCUMFLEX;Lu;0;L;0059 0302;;;;N;LATIN CAPITAL LETTER Y CIRCUMFLEX;;;0177; 0177;LATIN SMALL LETTER Y WITH CIRCUMFLEX;Ll;0;L;0079 0302;;;;N;LATIN SMALL LETTER Y CIRCUMFLEX;;0176;;0176 0178;LATIN CAPITAL LETTER Y WITH DIAERESIS;Lu;0;L;0059 0308;;;;N;LATIN CAPITAL LETTER Y DIAERESIS;;;00FF; 0179;LATIN CAPITAL LETTER Z WITH ACUTE;Lu;0;L;005A 0301;;;;N;LATIN CAPITAL LETTER Z ACUTE;;;017A; 017A;LATIN SMALL LETTER Z WITH ACUTE;Ll;0;L;007A 0301;;;;N;LATIN SMALL LETTER Z ACUTE;;0179;;0179 017B;LATIN CAPITAL LETTER Z WITH DOT ABOVE;Lu;0;L;005A 0307;;;;N;LATIN CAPITAL LETTER Z DOT;;;017C; 017C;LATIN SMALL LETTER Z WITH DOT ABOVE;Ll;0;L;007A 0307;;;;N;LATIN SMALL LETTER Z DOT;;017B;;017B 017D;LATIN CAPITAL LETTER Z WITH CARON;Lu;0;L;005A 030C;;;;N;LATIN CAPITAL LETTER Z HACEK;;;017E; 017E;LATIN SMALL LETTER Z WITH CARON;Ll;0;L;007A 030C;;;;N;LATIN SMALL LETTER Z HACEK;;017D;;017D 017F;LATIN SMALL LETTER LONG S;Ll;0;L; 0073;;;;N;;;0053;;0053 0180;LATIN SMALL LETTER B WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER B BAR;;;; 0181;LATIN CAPITAL LETTER B WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER B HOOK;;;0253; 0182;LATIN CAPITAL LETTER B WITH TOPBAR;Lu;0;L;;;;;N;LATIN CAPITAL LETTER B TOPBAR;;;0183; 0183;LATIN SMALL LETTER B WITH TOPBAR;Ll;0;L;;;;;N;LATIN SMALL LETTER B TOPBAR;;0182;;0182 0184;LATIN CAPITAL LETTER TONE SIX;Lu;0;L;;;;;N;;;;0185; 0185;LATIN SMALL LETTER TONE SIX;Ll;0;L;;;;;N;;;0184;;0184 0186;LATIN CAPITAL LETTER OPEN O;Lu;0;L;;;;;N;;;;0254; 0187;LATIN CAPITAL LETTER C WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER C HOOK;;;0188; 0188;LATIN SMALL LETTER C WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER C HOOK;;0187;;0187 0189;LATIN CAPITAL LETTER AFRICAN D;Lu;0;L;;;;;N;;*;;0256; 018A;LATIN CAPITAL LETTER D WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER D HOOK;;;0257; 018B;LATIN CAPITAL LETTER D WITH TOPBAR;Lu;0;L;;;;;N;LATIN CAPITAL LETTER D TOPBAR;;;018C; 018C;LATIN SMALL LETTER D WITH TOPBAR;Ll;0;L;;;;;N;LATIN SMALL LETTER D TOPBAR;;018B;;018B 018D;LATIN SMALL LETTER TURNED DELTA;Ll;0;L;;;;;N;;;;; 018E;LATIN CAPITAL LETTER REVERSED E;Lu;0;L;;;;;N;LATIN CAPITAL LETTER TURNED E;;;01DD; 018F;LATIN CAPITAL LETTER SCHWA;Lu;0;L;;;;;N;;;;0259; 0190;LATIN CAPITAL LETTER OPEN E;Lu;0;L;;;;;N;LATIN CAPITAL LETTER EPSILON;;;025B; 0191;LATIN CAPITAL LETTER F WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER F HOOK;;;0192; 0192;LATIN SMALL LETTER F WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER SCRIPT F;;0191;;0191 0193;LATIN CAPITAL LETTER G WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER G HOOK;;;0260; 0194;LATIN CAPITAL LETTER GAMMA;Lu;0;L;;;;;N;;;;0263; 0195;LATIN SMALL LETTER HV;Ll;0;L;;;;;N;LATIN SMALL LETTER H V;hwair;01F6;;01F6 0196;LATIN CAPITAL LETTER IOTA;Lu;0;L;;;;;N;;;;0269; 0197;LATIN CAPITAL LETTER I WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER BARRED I;;;0268; 0198;LATIN CAPITAL LETTER K WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER K HOOK;;;0199; 0199;LATIN SMALL LETTER K WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER K HOOK;;0198;;0198 019A;LATIN SMALL LETTER L WITH BAR;Ll;0;L;;;;;N;LATIN SMALL LETTER BARRED L;;;; 019B;LATIN SMALL LETTER LAMBDA WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER BARRED LAMBDA;;;; 019C;LATIN CAPITAL LETTER TURNED M;Lu;0;L;;;;;N;;;;026F; 019D;LATIN CAPITAL LETTER N WITH LEFT HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER N HOOK;;;0272; 019E;LATIN SMALL LETTER N WITH LONG RIGHT LEG;Ll;0;L;;;;;N;;;0220;;0220 019F;LATIN CAPITAL LETTER O WITH MIDDLE TILDE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER BARRED O;*;;0275; 01A0;LATIN CAPITAL LETTER O WITH HORN;Lu;0;L;004F 031B;;;;N;LATIN CAPITAL LETTER O HORN;;;01A1; 01A1;LATIN SMALL LETTER O WITH HORN;Ll;0;L;006F 031B;;;;N;LATIN SMALL LETTER O HORN;;01A0;;01A0 01A2;LATIN CAPITAL LETTER OI;Lu;0;L;;;;;N;LATIN CAPITAL LETTER O I;gha;;01A3; 01A3;LATIN SMALL LETTER OI;Ll;0;L;;;;;N;LATIN SMALL LETTER O I;gha;01A2;;01A2 01A4;LATIN CAPITAL LETTER P WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER P HOOK;;;01A5; 01A5;LATIN SMALL LETTER P WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER P HOOK;;01A4;;01A4 01A6;LATIN LETTER YR;Lu;0;L;;;;;N;LATIN LETTER Y R;*;;0280; 01A7;LATIN CAPITAL LETTER TONE TWO;Lu;0;L;;;;;N;;;;01A8; 01A8;LATIN SMALL LETTER TONE TWO;Ll;0;L;;;;;N;;;01A7;;01A7 01A9;LATIN CAPITAL LETTER ESH;Lu;0;L;;;;;N;;;;0283; 01AA;LATIN LETTER REVERSED ESH LOOP;Ll;0;L;;;;;N;;;;; 01AB;LATIN SMALL LETTER T WITH PALATAL HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER T PALATAL HOOK;;;; 01AC;LATIN CAPITAL LETTER T WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER T HOOK;;;01AD; 01AD;LATIN SMALL LETTER T WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER T HOOK;;01AC;;01AC 01AE;LATIN CAPITAL LETTER T WITH RETROFLEX HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER T RETROFLEX HOOK;;;0288; 01AF;LATIN CAPITAL LETTER U WITH HORN;Lu;0;L;0055 031B;;;;N;LATIN CAPITAL LETTER U HORN;;;01B0; 01B0;LATIN SMALL LETTER U WITH HORN;Ll;0;L;0075 031B;;;;N;LATIN SMALL LETTER U HORN;;01AF;;01AF 01B1;LATIN CAPITAL LETTER UPSILON;Lu;0;L;;;;;N;;;;028A; 01B2;LATIN CAPITAL LETTER V WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER SCRIPT V;;;028B; 01B3;LATIN CAPITAL LETTER Y WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER Y HOOK;;;01B4; 01B4;LATIN SMALL LETTER Y WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER Y HOOK;;01B3;;01B3 01B5;LATIN CAPITAL LETTER Z WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER Z BAR;;;01B6; 01B6;LATIN SMALL LETTER Z WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER Z BAR;;01B5;;01B5 01B7;LATIN CAPITAL LETTER EZH;Lu;0;L;;;;;N;LATIN CAPITAL LETTER YOGH;;;0292; 01B8;LATIN CAPITAL LETTER EZH REVERSED;Lu;0;L;;;;;N;LATIN CAPITAL LETTER REVERSED YOGH;;;01B9; 01B9;LATIN SMALL LETTER EZH REVERSED;Ll;0;L;;;;;N;LATIN SMALL LETTER REVERSED YOGH;;01B8;;01B8 01BA;LATIN SMALL LETTER EZH WITH TAIL;Ll;0;L;;;;;N;LATIN SMALL LETTER YOGH WITH TAIL;;;; 01BB;LATIN LETTER TWO WITH STROKE;Lo;0;L;;;;;N;LATIN LETTER TWO BAR;;;; 01BC;LATIN CAPITAL LETTER TONE FIVE;Lu;0;L;;;;;N;;;;01BD; 01BD;LATIN SMALL LETTER TONE FIVE;Ll;0;L;;;;;N;;;01BC;;01BC 01BE;LATIN LETTER INVERTED GLOTTAL STOP WITH STROKE;Ll;0;L;;;;;N;LATIN LETTER INVERTED GLOTTAL STOP BAR;;;; 01BF;LATIN LETTER WYNN;Ll;0;L;;;;;N;;;01F7;;01F7 01C0;LATIN LETTER DENTAL CLICK;Lo;0;L;;;;;N;LATIN LETTER PIPE;;;; 01C1;LATIN LETTER LATERAL CLICK;Lo;0;L;;;;;N;LATIN LETTER DOUBLE PIPE;;;; 01C2;LATIN LETTER ALVEOLAR CLICK;Lo;0;L;;;;;N;LATIN LETTER PIPE DOUBLE BAR;;;; 01C3;LATIN LETTER RETROFLEX CLICK;Lo;0;L;;;;;N;LATIN LETTER EXCLAMATION MARK;;;; 01C4;LATIN CAPITAL LETTER DZ WITH CARON;Lu;0;L; 0044 017D;;;;N;LATIN CAPITAL LETTER D Z HACEK;;;01C6;01C5 01C5;LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON;Lt;0;L; 0044 017E;;;;N;LATIN LETTER CAPITAL D SMALL Z HACEK;;01C4;01C6; 01C6;LATIN SMALL LETTER DZ WITH CARON;Ll;0;L; 0064 017E;;;;N;LATIN SMALL LETTER D Z HACEK;;01C4;;01C5 01C7;LATIN CAPITAL LETTER LJ;Lu;0;L; 004C 004A;;;;N;LATIN CAPITAL LETTER L J;;;01C9;01C8 01C8;LATIN CAPITAL LETTER L WITH SMALL LETTER J;Lt;0;L; 004C 006A;;;;N;LATIN LETTER CAPITAL L SMALL J;;01C7;01C9; 01C9;LATIN SMALL LETTER LJ;Ll;0;L; 006C 006A;;;;N;LATIN SMALL LETTER L J;;01C7;;01C8 01CA;LATIN CAPITAL LETTER NJ;Lu;0;L; 004E 004A;;;;N;LATIN CAPITAL LETTER N J;;;01CC;01CB 01CB;LATIN CAPITAL LETTER N WITH SMALL LETTER J;Lt;0;L; 004E 006A;;;;N;LATIN LETTER CAPITAL N SMALL J;;01CA;01CC; 01CC;LATIN SMALL LETTER NJ;Ll;0;L; 006E 006A;;;;N;LATIN SMALL LETTER N J;;01CA;;01CB 01CD;LATIN CAPITAL LETTER A WITH CARON;Lu;0;L;0041 030C;;;;N;LATIN CAPITAL LETTER A HACEK;;;01CE; 01CE;LATIN SMALL LETTER A WITH CARON;Ll;0;L;0061 030C;;;;N;LATIN SMALL LETTER A HACEK;;01CD;;01CD 01CF;LATIN CAPITAL LETTER I WITH CARON;Lu;0;L;0049 030C;;;;N;LATIN CAPITAL LETTER I HACEK;;;01D0; 01D0;LATIN SMALL LETTER I WITH CARON;Ll;0;L;0069 030C;;;;N;LATIN SMALL LETTER I HACEK;;01CF;;01CF 01D1;LATIN CAPITAL LETTER O WITH CARON;Lu;0;L;004F 030C;;;;N;LATIN CAPITAL LETTER O HACEK;;;01D2; 01D2;LATIN SMALL LETTER O WITH CARON;Ll;0;L;006F 030C;;;;N;LATIN SMALL LETTER O HACEK;;01D1;;01D1 01D3;LATIN CAPITAL LETTER U WITH CARON;Lu;0;L;0055 030C;;;;N;LATIN CAPITAL LETTER U HACEK;;;01D4; 01D4;LATIN SMALL LETTER U WITH CARON;Ll;0;L;0075 030C;;;;N;LATIN SMALL LETTER U HACEK;;01D3;;01D3 01D5;LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON;Lu;0;L;00DC 0304;;;;N;LATIN CAPITAL LETTER U DIAERESIS MACRON;;;01D6; 01D6;LATIN SMALL LETTER U WITH DIAERESIS AND MACRON;Ll;0;L;00FC 0304;;;;N;LATIN SMALL LETTER U DIAERESIS MACRON;;01D5;;01D5 01D7;LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE;Lu;0;L;00DC 0301;;;;N;LATIN CAPITAL LETTER U DIAERESIS ACUTE;;;01D8; 01D8;LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE;Ll;0;L;00FC 0301;;;;N;LATIN SMALL LETTER U DIAERESIS ACUTE;;01D7;;01D7 01D9;LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON;Lu;0;L;00DC 030C;;;;N;LATIN CAPITAL LETTER U DIAERESIS HACEK;;;01DA; 01DA;LATIN SMALL LETTER U WITH DIAERESIS AND CARON;Ll;0;L;00FC 030C;;;;N;LATIN SMALL LETTER U DIAERESIS HACEK;;01D9;;01D9 01DB;LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE;Lu;0;L;00DC 0300;;;;N;LATIN CAPITAL LETTER U DIAERESIS GRAVE;;;01DC; 01DC;LATIN SMALL LETTER U WITH DIAERESIS AND GRAVE;Ll;0;L;00FC 0300;;;;N;LATIN SMALL LETTER U DIAERESIS GRAVE;;01DB;;01DB 01DD;LATIN SMALL LETTER TURNED E;Ll;0;L;;;;;N;;;018E;;018E 01DE;LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON;Lu;0;L;00C4 0304;;;;N;LATIN CAPITAL LETTER A DIAERESIS MACRON;;;01DF; 01DF;LATIN SMALL LETTER A WITH DIAERESIS AND MACRON;Ll;0;L;00E4 0304;;;;N;LATIN SMALL LETTER A DIAERESIS MACRON;;01DE;;01DE 01E0;LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON;Lu;0;L;0226 0304;;;;N;LATIN CAPITAL LETTER A DOT MACRON;;;01E1; 01E1;LATIN SMALL LETTER A WITH DOT ABOVE AND MACRON;Ll;0;L;0227 0304;;;;N;LATIN SMALL LETTER A DOT MACRON;;01E0;;01E0 01E2;LATIN CAPITAL LETTER AE WITH MACRON;Lu;0;L;00C6 0304;;;;N;LATIN CAPITAL LETTER A E MACRON;ash *;;01E3; 01E3;LATIN SMALL LETTER AE WITH MACRON;Ll;0;L;00E6 0304;;;;N;LATIN SMALL LETTER A E MACRON;ash *;01E2;;01E2 01E4;LATIN CAPITAL LETTER G WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER G BAR;;;01E5; 01E5;LATIN SMALL LETTER G WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER G BAR;;01E4;;01E4 01E6;LATIN CAPITAL LETTER G WITH CARON;Lu;0;L;0047 030C;;;;N;LATIN CAPITAL LETTER G HACEK;;;01E7; 01E7;LATIN SMALL LETTER G WITH CARON;Ll;0;L;0067 030C;;;;N;LATIN SMALL LETTER G HACEK;;01E6;;01E6 01E8;LATIN CAPITAL LETTER K WITH CARON;Lu;0;L;004B 030C;;;;N;LATIN CAPITAL LETTER K HACEK;;;01E9; 01E9;LATIN SMALL LETTER K WITH CARON;Ll;0;L;006B 030C;;;;N;LATIN SMALL LETTER K HACEK;;01E8;;01E8 01EA;LATIN CAPITAL LETTER O WITH OGONEK;Lu;0;L;004F 0328;;;;N;LATIN CAPITAL LETTER O OGONEK;;;01EB; 01EB;LATIN SMALL LETTER O WITH OGONEK;Ll;0;L;006F 0328;;;;N;LATIN SMALL LETTER O OGONEK;;01EA;;01EA 01EC;LATIN CAPITAL LETTER O WITH OGONEK AND MACRON;Lu;0;L;01EA 0304;;;;N;LATIN CAPITAL LETTER O OGONEK MACRON;;;01ED; 01ED;LATIN SMALL LETTER O WITH OGONEK AND MACRON;Ll;0;L;01EB 0304;;;;N;LATIN SMALL LETTER O OGONEK MACRON;;01EC;;01EC 01EE;LATIN CAPITAL LETTER EZH WITH CARON;Lu;0;L;01B7 030C;;;;N;LATIN CAPITAL LETTER YOGH HACEK;;;01EF; 01EF;LATIN SMALL LETTER EZH WITH CARON;Ll;0;L;0292 030C;;;;N;LATIN SMALL LETTER YOGH HACEK;;01EE;;01EE 01F0;LATIN SMALL LETTER J WITH CARON;Ll;0;L;006A 030C;;;;N;LATIN SMALL LETTER J HACEK;;;; 01F1;LATIN CAPITAL LETTER DZ;Lu;0;L; 0044 005A;;;;N;;;;01F3;01F2 01F2;LATIN CAPITAL LETTER D WITH SMALL LETTER Z;Lt;0;L; 0044 007A;;;;N;;;01F1;01F3; 01F3;LATIN SMALL LETTER DZ;Ll;0;L; 0064 007A;;;;N;;;01F1;;01F2 01F4;LATIN CAPITAL LETTER G WITH ACUTE;Lu;0;L;0047 0301;;;;N;;;;01F5; 01F5;LATIN SMALL LETTER G WITH ACUTE;Ll;0;L;0067 0301;;;;N;;;01F4;;01F4 01F6;LATIN CAPITAL LETTER HWAIR;Lu;0;L;;;;;N;;;;0195; 01F7;LATIN CAPITAL LETTER WYNN;Lu;0;L;;;;;N;;;;01BF; 01F8;LATIN CAPITAL LETTER N WITH GRAVE;Lu;0;L;004E 0300;;;;N;;;;01F9; 01F9;LATIN SMALL LETTER N WITH GRAVE;Ll;0;L;006E 0300;;;;N;;;01F8;;01F8 01FA;LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE;Lu;0;L;00C5 0301;;;;N;;;;01FB; 01FB;LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE;Ll;0;L;00E5 0301;;;;N;;;01FA;;01FA 01FC;LATIN CAPITAL LETTER AE WITH ACUTE;Lu;0;L;00C6 0301;;;;N;;ash *;;01FD; 01FD;LATIN SMALL LETTER AE WITH ACUTE;Ll;0;L;00E6 0301;;;;N;;ash *;01FC;;01FC 01FE;LATIN CAPITAL LETTER O WITH STROKE AND ACUTE;Lu;0;L;00D8 0301;;;;N;;;;01FF; 01FF;LATIN SMALL LETTER O WITH STROKE AND ACUTE;Ll;0;L;00F8 0301;;;;N;;;01FE;;01FE 0200;LATIN CAPITAL LETTER A WITH DOUBLE GRAVE;Lu;0;L;0041 030F;;;;N;;;;0201; 0201;LATIN SMALL LETTER A WITH DOUBLE GRAVE;Ll;0;L;0061 030F;;;;N;;;0200;;0200 0202;LATIN CAPITAL LETTER A WITH INVERTED BREVE;Lu;0;L;0041 0311;;;;N;;;;0203; 0203;LATIN SMALL LETTER A WITH INVERTED BREVE;Ll;0;L;0061 0311;;;;N;;;0202;;0202 0204;LATIN CAPITAL LETTER E WITH DOUBLE GRAVE;Lu;0;L;0045 030F;;;;N;;;;0205; 0205;LATIN SMALL LETTER E WITH DOUBLE GRAVE;Ll;0;L;0065 030F;;;;N;;;0204;;0204 0206;LATIN CAPITAL LETTER E WITH INVERTED BREVE;Lu;0;L;0045 0311;;;;N;;;;0207; 0207;LATIN SMALL LETTER E WITH INVERTED BREVE;Ll;0;L;0065 0311;;;;N;;;0206;;0206 0208;LATIN CAPITAL LETTER I WITH DOUBLE GRAVE;Lu;0;L;0049 030F;;;;N;;;;0209; 0209;LATIN SMALL LETTER I WITH DOUBLE GRAVE;Ll;0;L;0069 030F;;;;N;;;0208;;0208 020A;LATIN CAPITAL LETTER I WITH INVERTED BREVE;Lu;0;L;0049 0311;;;;N;;;;020B; 020B;LATIN SMALL LETTER I WITH INVERTED BREVE;Ll;0;L;0069 0311;;;;N;;;020A;;020A 020C;LATIN CAPITAL LETTER O WITH DOUBLE GRAVE;Lu;0;L;004F 030F;;;;N;;;;020D; 020D;LATIN SMALL LETTER O WITH DOUBLE GRAVE;Ll;0;L;006F 030F;;;;N;;;020C;;020C 020E;LATIN CAPITAL LETTER O WITH INVERTED BREVE;Lu;0;L;004F 0311;;;;N;;;;020F; 020F;LATIN SMALL LETTER O WITH INVERTED BREVE;Ll;0;L;006F 0311;;;;N;;;020E;;020E 0210;LATIN CAPITAL LETTER R WITH DOUBLE GRAVE;Lu;0;L;0052 030F;;;;N;;;;0211; 0211;LATIN SMALL LETTER R WITH DOUBLE GRAVE;Ll;0;L;0072 030F;;;;N;;;0210;;0210 0212;LATIN CAPITAL LETTER R WITH INVERTED BREVE;Lu;0;L;0052 0311;;;;N;;;;0213; 0213;LATIN SMALL LETTER R WITH INVERTED BREVE;Ll;0;L;0072 0311;;;;N;;;0212;;0212 0214;LATIN CAPITAL LETTER U WITH DOUBLE GRAVE;Lu;0;L;0055 030F;;;;N;;;;0215; 0215;LATIN SMALL LETTER U WITH DOUBLE GRAVE;Ll;0;L;0075 030F;;;;N;;;0214;;0214 0216;LATIN CAPITAL LETTER U WITH INVERTED BREVE;Lu;0;L;0055 0311;;;;N;;;;0217; 0217;LATIN SMALL LETTER U WITH INVERTED BREVE;Ll;0;L;0075 0311;;;;N;;;0216;;0216 0218;LATIN CAPITAL LETTER S WITH COMMA BELOW;Lu;0;L;0053 0326;;;;N;;*;;0219; 0219;LATIN SMALL LETTER S WITH COMMA BELOW;Ll;0;L;0073 0326;;;;N;;*;0218;;0218 021A;LATIN CAPITAL LETTER T WITH COMMA BELOW;Lu;0;L;0054 0326;;;;N;;*;;021B; 021B;LATIN SMALL LETTER T WITH COMMA BELOW;Ll;0;L;0074 0326;;;;N;;*;021A;;021A 021C;LATIN CAPITAL LETTER YOGH;Lu;0;L;;;;;N;;;;021D; 021D;LATIN SMALL LETTER YOGH;Ll;0;L;;;;;N;;;021C;;021C 021E;LATIN CAPITAL LETTER H WITH CARON;Lu;0;L;0048 030C;;;;N;;;;021F; 021F;LATIN SMALL LETTER H WITH CARON;Ll;0;L;0068 030C;;;;N;;;021E;;021E 0220;LATIN CAPITAL LETTER N WITH LONG RIGHT LEG;Lu;0;L;;;;;N;;;;019E; 0222;LATIN CAPITAL LETTER OU;Lu;0;L;;;;;N;;;;0223; 0223;LATIN SMALL LETTER OU;Ll;0;L;;;;;N;;;0222;;0222 0224;LATIN CAPITAL LETTER Z WITH HOOK;Lu;0;L;;;;;N;;;;0225; 0225;LATIN SMALL LETTER Z WITH HOOK;Ll;0;L;;;;;N;;;0224;;0224 0226;LATIN CAPITAL LETTER A WITH DOT ABOVE;Lu;0;L;0041 0307;;;;N;;;;0227; 0227;LATIN SMALL LETTER A WITH DOT ABOVE;Ll;0;L;0061 0307;;;;N;;;0226;;0226 0228;LATIN CAPITAL LETTER E WITH CEDILLA;Lu;0;L;0045 0327;;;;N;;;;0229; 0229;LATIN SMALL LETTER E WITH CEDILLA;Ll;0;L;0065 0327;;;;N;;;0228;;0228 022A;LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON;Lu;0;L;00D6 0304;;;;N;;;;022B; 022B;LATIN SMALL LETTER O WITH DIAERESIS AND MACRON;Ll;0;L;00F6 0304;;;;N;;;022A;;022A 022C;LATIN CAPITAL LETTER O WITH TILDE AND MACRON;Lu;0;L;00D5 0304;;;;N;;;;022D; 022D;LATIN SMALL LETTER O WITH TILDE AND MACRON;Ll;0;L;00F5 0304;;;;N;;;022C;;022C 022E;LATIN CAPITAL LETTER O WITH DOT ABOVE;Lu;0;L;004F 0307;;;;N;;;;022F; 022F;LATIN SMALL LETTER O WITH DOT ABOVE;Ll;0;L;006F 0307;;;;N;;;022E;;022E 0230;LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON;Lu;0;L;022E 0304;;;;N;;;;0231; 0231;LATIN SMALL LETTER O WITH DOT ABOVE AND MACRON;Ll;0;L;022F 0304;;;;N;;;0230;;0230 0232;LATIN CAPITAL LETTER Y WITH MACRON;Lu;0;L;0059 0304;;;;N;;;;0233; 0233;LATIN SMALL LETTER Y WITH MACRON;Ll;0;L;0079 0304;;;;N;;;0232;;0232 0250;LATIN SMALL LETTER TURNED A;Ll;0;L;;;;;N;;;;; 0251;LATIN SMALL LETTER ALPHA;Ll;0;L;;;;;N;LATIN SMALL LETTER SCRIPT A;;;; 0252;LATIN SMALL LETTER TURNED ALPHA;Ll;0;L;;;;;N;LATIN SMALL LETTER TURNED SCRIPT A;;;; 0253;LATIN SMALL LETTER B WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER B HOOK;;0181;;0181 0254;LATIN SMALL LETTER OPEN O;Ll;0;L;;;;;N;;;0186;;0186 0255;LATIN SMALL LETTER C WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER C CURL;;;; 0256;LATIN SMALL LETTER D WITH TAIL;Ll;0;L;;;;;N;LATIN SMALL LETTER D RETROFLEX HOOK;;0189;;0189 0257;LATIN SMALL LETTER D WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER D HOOK;;018A;;018A 0258;LATIN SMALL LETTER REVERSED E;Ll;0;L;;;;;N;;;;; 0259;LATIN SMALL LETTER SCHWA;Ll;0;L;;;;;N;;;018F;;018F 025A;LATIN SMALL LETTER SCHWA WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER SCHWA HOOK;;;; 025B;LATIN SMALL LETTER OPEN E;Ll;0;L;;;;;N;LATIN SMALL LETTER EPSILON;;0190;;0190 025C;LATIN SMALL LETTER REVERSED OPEN E;Ll;0;L;;;;;N;LATIN SMALL LETTER REVERSED EPSILON;;;; 025D;LATIN SMALL LETTER REVERSED OPEN E WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER REVERSED EPSILON HOOK;;;; 025E;LATIN SMALL LETTER CLOSED REVERSED OPEN E;Ll;0;L;;;;;N;LATIN SMALL LETTER CLOSED REVERSED EPSILON;;;; 025F;LATIN SMALL LETTER DOTLESS J WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER DOTLESS J BAR;;;; 0260;LATIN SMALL LETTER G WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER G HOOK;;0193;;0193 0261;LATIN SMALL LETTER SCRIPT G;Ll;0;L;;;;;N;;;;; 0262;LATIN LETTER SMALL CAPITAL G;Ll;0;L;;;;;N;;;;; 0263;LATIN SMALL LETTER GAMMA;Ll;0;L;;;;;N;;;0194;;0194 0264;LATIN SMALL LETTER RAMS HORN;Ll;0;L;;;;;N;LATIN SMALL LETTER BABY GAMMA;;;; 0265;LATIN SMALL LETTER TURNED H;Ll;0;L;;;;;N;;;;; 0266;LATIN SMALL LETTER H WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER H HOOK;;;; 0267;LATIN SMALL LETTER HENG WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER HENG HOOK;;;; 0268;LATIN SMALL LETTER I WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER BARRED I;;0197;;0197 0269;LATIN SMALL LETTER IOTA;Ll;0;L;;;;;N;;;0196;;0196 026A;LATIN LETTER SMALL CAPITAL I;Ll;0;L;;;;;N;;;;; 026B;LATIN SMALL LETTER L WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; 026C;LATIN SMALL LETTER L WITH BELT;Ll;0;L;;;;;N;LATIN SMALL LETTER L BELT;;;; 026D;LATIN SMALL LETTER L WITH RETROFLEX HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER L RETROFLEX HOOK;;;; 026E;LATIN SMALL LETTER LEZH;Ll;0;L;;;;;N;LATIN SMALL LETTER L YOGH;;;; 026F;LATIN SMALL LETTER TURNED M;Ll;0;L;;;;;N;;;019C;;019C 0270;LATIN SMALL LETTER TURNED M WITH LONG LEG;Ll;0;L;;;;;N;;;;; 0271;LATIN SMALL LETTER M WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER M HOOK;;;; 0272;LATIN SMALL LETTER N WITH LEFT HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER N HOOK;;019D;;019D 0273;LATIN SMALL LETTER N WITH RETROFLEX HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER N RETROFLEX HOOK;;;; 0274;LATIN LETTER SMALL CAPITAL N;Ll;0;L;;;;;N;;;;; 0275;LATIN SMALL LETTER BARRED O;Ll;0;L;;;;;N;;;019F;;019F 0276;LATIN LETTER SMALL CAPITAL OE;Ll;0;L;;;;;N;LATIN LETTER SMALL CAPITAL O E;;;; 0277;LATIN SMALL LETTER CLOSED OMEGA;Ll;0;L;;;;;N;;;;; 0278;LATIN SMALL LETTER PHI;Ll;0;L;;;;;N;;;;; 0279;LATIN SMALL LETTER TURNED R;Ll;0;L;;;;;N;;;;; 027A;LATIN SMALL LETTER TURNED R WITH LONG LEG;Ll;0;L;;;;;N;;;;; 027B;LATIN SMALL LETTER TURNED R WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER TURNED R HOOK;;;; 027C;LATIN SMALL LETTER R WITH LONG LEG;Ll;0;L;;;;;N;;;;; 027D;LATIN SMALL LETTER R WITH TAIL;Ll;0;L;;;;;N;LATIN SMALL LETTER R HOOK;;;; 027E;LATIN SMALL LETTER R WITH FISHHOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER FISHHOOK R;;;; 027F;LATIN SMALL LETTER REVERSED R WITH FISHHOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER REVERSED FISHHOOK R;;;; 0280;LATIN LETTER SMALL CAPITAL R;Ll;0;L;;;;;N;;*;01A6;;01A6 0281;LATIN LETTER SMALL CAPITAL INVERTED R;Ll;0;L;;;;;N;;;;; 0282;LATIN SMALL LETTER S WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER S HOOK;;;; 0283;LATIN SMALL LETTER ESH;Ll;0;L;;;;;N;;;01A9;;01A9 0284;LATIN SMALL LETTER DOTLESS J WITH STROKE AND HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER DOTLESS J BAR HOOK;;;; 0285;LATIN SMALL LETTER SQUAT REVERSED ESH;Ll;0;L;;;;;N;;;;; 0286;LATIN SMALL LETTER ESH WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER ESH CURL;;;; 0287;LATIN SMALL LETTER TURNED T;Ll;0;L;;;;;N;;;;; 0288;LATIN SMALL LETTER T WITH RETROFLEX HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER T RETROFLEX HOOK;;01AE;;01AE 0289;LATIN SMALL LETTER U BAR;Ll;0;L;;;;;N;;;;; 028A;LATIN SMALL LETTER UPSILON;Ll;0;L;;;;;N;;;01B1;;01B1 028B;LATIN SMALL LETTER V WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER SCRIPT V;;01B2;;01B2 028C;LATIN SMALL LETTER TURNED V;Ll;0;L;;;;;N;;;;; 028D;LATIN SMALL LETTER TURNED W;Ll;0;L;;;;;N;;;;; 028E;LATIN SMALL LETTER TURNED Y;Ll;0;L;;;;;N;;;;; 028F;LATIN LETTER SMALL CAPITAL Y;Ll;0;L;;;;;N;;;;; 0290;LATIN SMALL LETTER Z WITH RETROFLEX HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER Z RETROFLEX HOOK;;;; 0291;LATIN SMALL LETTER Z WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER Z CURL;;;; 0292;LATIN SMALL LETTER EZH;Ll;0;L;;;;;N;LATIN SMALL LETTER YOGH;;01B7;;01B7 0293;LATIN SMALL LETTER EZH WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER YOGH CURL;;;; 0294;LATIN LETTER GLOTTAL STOP;Ll;0;L;;;;;N;;;;; 0295;LATIN LETTER PHARYNGEAL VOICED FRICATIVE;Ll;0;L;;;;;N;LATIN LETTER REVERSED GLOTTAL STOP;;;; 0296;LATIN LETTER INVERTED GLOTTAL STOP;Ll;0;L;;;;;N;;;;; 0297;LATIN LETTER STRETCHED C;Ll;0;L;;;;;N;;;;; 0298;LATIN LETTER BILABIAL CLICK;Ll;0;L;;;;;N;LATIN LETTER BULLSEYE;;;; 0299;LATIN LETTER SMALL CAPITAL B;Ll;0;L;;;;;N;;;;; 029A;LATIN SMALL LETTER CLOSED OPEN E;Ll;0;L;;;;;N;LATIN SMALL LETTER CLOSED EPSILON;;;; 029B;LATIN LETTER SMALL CAPITAL G WITH HOOK;Ll;0;L;;;;;N;LATIN LETTER SMALL CAPITAL G HOOK;;;; 029C;LATIN LETTER SMALL CAPITAL H;Ll;0;L;;;;;N;;;;; 029D;LATIN SMALL LETTER J WITH CROSSED-TAIL;Ll;0;L;;;;;N;LATIN SMALL LETTER CROSSED-TAIL J;;;; 029E;LATIN SMALL LETTER TURNED K;Ll;0;L;;;;;N;;;;; 029F;LATIN LETTER SMALL CAPITAL L;Ll;0;L;;;;;N;;;;; 02A0;LATIN SMALL LETTER Q WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER Q HOOK;;;; 02A1;LATIN LETTER GLOTTAL STOP WITH STROKE;Ll;0;L;;;;;N;LATIN LETTER GLOTTAL STOP BAR;;;; 02A2;LATIN LETTER REVERSED GLOTTAL STOP WITH STROKE;Ll;0;L;;;;;N;LATIN LETTER REVERSED GLOTTAL STOP BAR;;;; 02A3;LATIN SMALL LETTER DZ DIGRAPH;Ll;0;L;;;;;N;LATIN SMALL LETTER D Z;;;; 02A4;LATIN SMALL LETTER DEZH DIGRAPH;Ll;0;L;;;;;N;LATIN SMALL LETTER D YOGH;;;; 02A5;LATIN SMALL LETTER DZ DIGRAPH WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER D Z CURL;;;; 02A6;LATIN SMALL LETTER TS DIGRAPH;Ll;0;L;;;;;N;LATIN SMALL LETTER T S;;;; 02A7;LATIN SMALL LETTER TESH DIGRAPH;Ll;0;L;;;;;N;LATIN SMALL LETTER T ESH;;;; 02A8;LATIN SMALL LETTER TC DIGRAPH WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER T C CURL;;;; 02A9;LATIN SMALL LETTER FENG DIGRAPH;Ll;0;L;;;;;N;;;;; 02AA;LATIN SMALL LETTER LS DIGRAPH;Ll;0;L;;;;;N;;;;; 02AB;LATIN SMALL LETTER LZ DIGRAPH;Ll;0;L;;;;;N;;;;; 02AC;LATIN LETTER BILABIAL PERCUSSIVE;Ll;0;L;;;;;N;;;;; 02AD;LATIN LETTER BIDENTAL PERCUSSIVE;Ll;0;L;;;;;N;;;;; 02B0;MODIFIER LETTER SMALL H;Lm;0;L; 0068;;;;N;;;;; 02B1;MODIFIER LETTER SMALL H WITH HOOK;Lm;0;L; 0266;;;;N;MODIFIER LETTER SMALL H HOOK;;;; 02B2;MODIFIER LETTER SMALL J;Lm;0;L; 006A;;;;N;;;;; 02B3;MODIFIER LETTER SMALL R;Lm;0;L; 0072;;;;N;;;;; 02B4;MODIFIER LETTER SMALL TURNED R;Lm;0;L; 0279;;;;N;;;;; 02B5;MODIFIER LETTER SMALL TURNED R WITH HOOK;Lm;0;L; 027B;;;;N;MODIFIER LETTER SMALL TURNED R HOOK;;;; 02B6;MODIFIER LETTER SMALL CAPITAL INVERTED R;Lm;0;L; 0281;;;;N;;;;; 02B7;MODIFIER LETTER SMALL W;Lm;0;L; 0077;;;;N;;;;; 02B8;MODIFIER LETTER SMALL Y;Lm;0;L; 0079;;;;N;;;;; 02B9;MODIFIER LETTER PRIME;Sk;0;ON;;;;;N;;;;; 02BA;MODIFIER LETTER DOUBLE PRIME;Sk;0;ON;;;;;N;;;;; 02BB;MODIFIER LETTER TURNED COMMA;Lm;0;L;;;;;N;;;;; 02BC;MODIFIER LETTER APOSTROPHE;Lm;0;L;;;;;N;;;;; 02BD;MODIFIER LETTER REVERSED COMMA;Lm;0;L;;;;;N;;;;; 02BE;MODIFIER LETTER RIGHT HALF RING;Lm;0;L;;;;;N;;;;; 02BF;MODIFIER LETTER LEFT HALF RING;Lm;0;L;;;;;N;;;;; 02C0;MODIFIER LETTER GLOTTAL STOP;Lm;0;L;;;;;N;;;;; 02C1;MODIFIER LETTER REVERSED GLOTTAL STOP;Lm;0;L;;;;;N;;;;; 02C2;MODIFIER LETTER LEFT ARROWHEAD;Sk;0;ON;;;;;N;;;;; 02C3;MODIFIER LETTER RIGHT ARROWHEAD;Sk;0;ON;;;;;N;;;;; 02C4;MODIFIER LETTER UP ARROWHEAD;Sk;0;ON;;;;;N;;;;; 02C5;MODIFIER LETTER DOWN ARROWHEAD;Sk;0;ON;;;;;N;;;;; 02C6;MODIFIER LETTER CIRCUMFLEX ACCENT;Sk;0;ON;;;;;N;MODIFIER LETTER CIRCUMFLEX;;;; 02C7;CARON;Sk;0;ON;;;;;N;MODIFIER LETTER HACEK;Mandarin Chinese third tone;;; 02C8;MODIFIER LETTER VERTICAL LINE;Sk;0;ON;;;;;N;;;;; 02C9;MODIFIER LETTER MACRON;Sk;0;ON;;;;;N;;Mandarin Chinese first tone;;; 02CA;MODIFIER LETTER ACUTE ACCENT;Sk;0;ON;;;;;N;MODIFIER LETTER ACUTE;Mandarin Chinese second tone;;; 02CB;MODIFIER LETTER GRAVE ACCENT;Sk;0;ON;;;;;N;MODIFIER LETTER GRAVE;Mandarin Chinese fourth tone;;; 02CC;MODIFIER LETTER LOW VERTICAL LINE;Sk;0;ON;;;;;N;;;;; 02CD;MODIFIER LETTER LOW MACRON;Sk;0;ON;;;;;N;;;;; 02CE;MODIFIER LETTER LOW GRAVE ACCENT;Sk;0;ON;;;;;N;MODIFIER LETTER LOW GRAVE;;;; 02CF;MODIFIER LETTER LOW ACUTE ACCENT;Sk;0;ON;;;;;N;MODIFIER LETTER LOW ACUTE;;;; 02D0;MODIFIER LETTER TRIANGULAR COLON;Lm;0;L;;;;;N;;;;; 02D1;MODIFIER LETTER HALF TRIANGULAR COLON;Lm;0;L;;;;;N;;;;; 02D2;MODIFIER LETTER CENTRED RIGHT HALF RING;Sk;0;ON;;;;;N;MODIFIER LETTER CENTERED RIGHT HALF RING;;;; 02D3;MODIFIER LETTER CENTRED LEFT HALF RING;Sk;0;ON;;;;;N;MODIFIER LETTER CENTERED LEFT HALF RING;;;; 02D4;MODIFIER LETTER UP TACK;Sk;0;ON;;;;;N;;;;; 02D5;MODIFIER LETTER DOWN TACK;Sk;0;ON;;;;;N;;;;; 02D6;MODIFIER LETTER PLUS SIGN;Sk;0;ON;;;;;N;;;;; 02D7;MODIFIER LETTER MINUS SIGN;Sk;0;ON;;;;;N;;;;; 02D8;BREVE;Sk;0;ON; 0020 0306;;;;N;SPACING BREVE;;;; 02D9;DOT ABOVE;Sk;0;ON; 0020 0307;;;;N;SPACING DOT ABOVE;Mandarin Chinese light tone;;; 02DA;RING ABOVE;Sk;0;ON; 0020 030A;;;;N;SPACING RING ABOVE;;;; 02DB;OGONEK;Sk;0;ON; 0020 0328;;;;N;SPACING OGONEK;;;; 02DC;SMALL TILDE;Sk;0;ON; 0020 0303;;;;N;SPACING TILDE;;;; 02DD;DOUBLE ACUTE ACCENT;Sk;0;ON; 0020 030B;;;;N;SPACING DOUBLE ACUTE;;;; 02DE;MODIFIER LETTER RHOTIC HOOK;Sk;0;ON;;;;;N;;;;; 02DF;MODIFIER LETTER CROSS ACCENT;Sk;0;ON;;;;;N;;;;; 02E0;MODIFIER LETTER SMALL GAMMA;Lm;0;L; 0263;;;;N;;;;; 02E1;MODIFIER LETTER SMALL L;Lm;0;L; 006C;;;;N;;;;; 02E2;MODIFIER LETTER SMALL S;Lm;0;L; 0073;;;;N;;;;; 02E3;MODIFIER LETTER SMALL X;Lm;0;L; 0078;;;;N;;;;; 02E4;MODIFIER LETTER SMALL REVERSED GLOTTAL STOP;Lm;0;L; 0295;;;;N;;;;; 02E5;MODIFIER LETTER EXTRA-HIGH TONE BAR;Sk;0;ON;;;;;N;;;;; 02E6;MODIFIER LETTER HIGH TONE BAR;Sk;0;ON;;;;;N;;;;; 02E7;MODIFIER LETTER MID TONE BAR;Sk;0;ON;;;;;N;;;;; 02E8;MODIFIER LETTER LOW TONE BAR;Sk;0;ON;;;;;N;;;;; 02E9;MODIFIER LETTER EXTRA-LOW TONE BAR;Sk;0;ON;;;;;N;;;;; 02EA;MODIFIER LETTER YIN DEPARTING TONE MARK;Sk;0;ON;;;;;N;;;;; 02EB;MODIFIER LETTER YANG DEPARTING TONE MARK;Sk;0;ON;;;;;N;;;;; 02EC;MODIFIER LETTER VOICING;Sk;0;ON;;;;;N;;;;; 02ED;MODIFIER LETTER UNASPIRATED;Sk;0;ON;;;;;N;;;;; 02EE;MODIFIER LETTER DOUBLE APOSTROPHE;Lm;0;L;;;;;N;;;;; 0300;COMBINING GRAVE ACCENT;Mn;230;NSM;;;;;N;NON-SPACING GRAVE;Varia;;; 0301;COMBINING ACUTE ACCENT;Mn;230;NSM;;;;;N;NON-SPACING ACUTE;Oxia, Tonos;;; 0302;COMBINING CIRCUMFLEX ACCENT;Mn;230;NSM;;;;;N;NON-SPACING CIRCUMFLEX;;;; 0303;COMBINING TILDE;Mn;230;NSM;;;;;N;NON-SPACING TILDE;;;; 0304;COMBINING MACRON;Mn;230;NSM;;;;;N;NON-SPACING MACRON;;;; 0305;COMBINING OVERLINE;Mn;230;NSM;;;;;N;NON-SPACING OVERSCORE;;;; 0306;COMBINING BREVE;Mn;230;NSM;;;;;N;NON-SPACING BREVE;Vrachy;;; 0307;COMBINING DOT ABOVE;Mn;230;NSM;;;;;N;NON-SPACING DOT ABOVE;;;; 0308;COMBINING DIAERESIS;Mn;230;NSM;;;;;N;NON-SPACING DIAERESIS;Dialytika;;; 0309;COMBINING HOOK ABOVE;Mn;230;NSM;;;;;N;NON-SPACING HOOK ABOVE;;;; 030A;COMBINING RING ABOVE;Mn;230;NSM;;;;;N;NON-SPACING RING ABOVE;;;; 030B;COMBINING DOUBLE ACUTE ACCENT;Mn;230;NSM;;;;;N;NON-SPACING DOUBLE ACUTE;;;; 030C;COMBINING CARON;Mn;230;NSM;;;;;N;NON-SPACING HACEK;;;; 030D;COMBINING VERTICAL LINE ABOVE;Mn;230;NSM;;;;;N;NON-SPACING VERTICAL LINE ABOVE;;;; 030E;COMBINING DOUBLE VERTICAL LINE ABOVE;Mn;230;NSM;;;;;N;NON-SPACING DOUBLE VERTICAL LINE ABOVE;;;; 030F;COMBINING DOUBLE GRAVE ACCENT;Mn;230;NSM;;;;;N;NON-SPACING DOUBLE GRAVE;;;; 0310;COMBINING CANDRABINDU;Mn;230;NSM;;;;;N;NON-SPACING CANDRABINDU;;;; 0311;COMBINING INVERTED BREVE;Mn;230;NSM;;;;;N;NON-SPACING INVERTED BREVE;;;; 0312;COMBINING TURNED COMMA ABOVE;Mn;230;NSM;;;;;N;NON-SPACING TURNED COMMA ABOVE;;;; 0313;COMBINING COMMA ABOVE;Mn;230;NSM;;;;;N;NON-SPACING COMMA ABOVE;Psili;;; 0314;COMBINING REVERSED COMMA ABOVE;Mn;230;NSM;;;;;N;NON-SPACING REVERSED COMMA ABOVE;Dasia;;; 0315;COMBINING COMMA ABOVE RIGHT;Mn;232;NSM;;;;;N;NON-SPACING COMMA ABOVE RIGHT;;;; 0316;COMBINING GRAVE ACCENT BELOW;Mn;220;NSM;;;;;N;NON-SPACING GRAVE BELOW;;;; 0317;COMBINING ACUTE ACCENT BELOW;Mn;220;NSM;;;;;N;NON-SPACING ACUTE BELOW;;;; 0318;COMBINING LEFT TACK BELOW;Mn;220;NSM;;;;;N;NON-SPACING LEFT TACK BELOW;;;; 0319;COMBINING RIGHT TACK BELOW;Mn;220;NSM;;;;;N;NON-SPACING RIGHT TACK BELOW;;;; 031A;COMBINING LEFT ANGLE ABOVE;Mn;232;NSM;;;;;N;NON-SPACING LEFT ANGLE ABOVE;;;; 031B;COMBINING HORN;Mn;216;NSM;;;;;N;NON-SPACING HORN;;;; 031C;COMBINING LEFT HALF RING BELOW;Mn;220;NSM;;;;;N;NON-SPACING LEFT HALF RING BELOW;;;; 031D;COMBINING UP TACK BELOW;Mn;220;NSM;;;;;N;NON-SPACING UP TACK BELOW;;;; 031E;COMBINING DOWN TACK BELOW;Mn;220;NSM;;;;;N;NON-SPACING DOWN TACK BELOW;;;; 031F;COMBINING PLUS SIGN BELOW;Mn;220;NSM;;;;;N;NON-SPACING PLUS SIGN BELOW;;;; 0320;COMBINING MINUS SIGN BELOW;Mn;220;NSM;;;;;N;NON-SPACING MINUS SIGN BELOW;;;; 0321;COMBINING PALATALIZED HOOK BELOW;Mn;202;NSM;;;;;N;NON-SPACING PALATALIZED HOOK BELOW;;;; 0322;COMBINING RETROFLEX HOOK BELOW;Mn;202;NSM;;;;;N;NON-SPACING RETROFLEX HOOK BELOW;;;; 0323;COMBINING DOT BELOW;Mn;220;NSM;;;;;N;NON-SPACING DOT BELOW;;;; 0324;COMBINING DIAERESIS BELOW;Mn;220;NSM;;;;;N;NON-SPACING DOUBLE DOT BELOW;;;; 0325;COMBINING RING BELOW;Mn;220;NSM;;;;;N;NON-SPACING RING BELOW;;;; 0326;COMBINING COMMA BELOW;Mn;220;NSM;;;;;N;NON-SPACING COMMA BELOW;;;; 0327;COMBINING CEDILLA;Mn;202;NSM;;;;;N;NON-SPACING CEDILLA;;;; 0328;COMBINING OGONEK;Mn;202;NSM;;;;;N;NON-SPACING OGONEK;;;; 0329;COMBINING VERTICAL LINE BELOW;Mn;220;NSM;;;;;N;NON-SPACING VERTICAL LINE BELOW;;;; 032A;COMBINING BRIDGE BELOW;Mn;220;NSM;;;;;N;NON-SPACING BRIDGE BELOW;;;; 032B;COMBINING INVERTED DOUBLE ARCH BELOW;Mn;220;NSM;;;;;N;NON-SPACING INVERTED DOUBLE ARCH BELOW;;;; 032C;COMBINING CARON BELOW;Mn;220;NSM;;;;;N;NON-SPACING HACEK BELOW;;;; 032D;COMBINING CIRCUMFLEX ACCENT BELOW;Mn;220;NSM;;;;;N;NON-SPACING CIRCUMFLEX BELOW;;;; 032E;COMBINING BREVE BELOW;Mn;220;NSM;;;;;N;NON-SPACING BREVE BELOW;;;; 032F;COMBINING INVERTED BREVE BELOW;Mn;220;NSM;;;;;N;NON-SPACING INVERTED BREVE BELOW;;;; 0330;COMBINING TILDE BELOW;Mn;220;NSM;;;;;N;NON-SPACING TILDE BELOW;;;; 0331;COMBINING MACRON BELOW;Mn;220;NSM;;;;;N;NON-SPACING MACRON BELOW;;;; 0332;COMBINING LOW LINE;Mn;220;NSM;;;;;N;NON-SPACING UNDERSCORE;;;; 0333;COMBINING DOUBLE LOW LINE;Mn;220;NSM;;;;;N;NON-SPACING DOUBLE UNDERSCORE;;;; 0334;COMBINING TILDE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING TILDE OVERLAY;;;; 0335;COMBINING SHORT STROKE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING SHORT BAR OVERLAY;;;; 0336;COMBINING LONG STROKE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING LONG BAR OVERLAY;;;; 0337;COMBINING SHORT SOLIDUS OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING SHORT SLASH OVERLAY;;;; 0338;COMBINING LONG SOLIDUS OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING LONG SLASH OVERLAY;;;; 0339;COMBINING RIGHT HALF RING BELOW;Mn;220;NSM;;;;;N;NON-SPACING RIGHT HALF RING BELOW;;;; 033A;COMBINING INVERTED BRIDGE BELOW;Mn;220;NSM;;;;;N;NON-SPACING INVERTED BRIDGE BELOW;;;; 033B;COMBINING SQUARE BELOW;Mn;220;NSM;;;;;N;NON-SPACING SQUARE BELOW;;;; 033C;COMBINING SEAGULL BELOW;Mn;220;NSM;;;;;N;NON-SPACING SEAGULL BELOW;;;; 033D;COMBINING X ABOVE;Mn;230;NSM;;;;;N;NON-SPACING X ABOVE;;;; 033E;COMBINING VERTICAL TILDE;Mn;230;NSM;;;;;N;NON-SPACING VERTICAL TILDE;;;; 033F;COMBINING DOUBLE OVERLINE;Mn;230;NSM;;;;;N;NON-SPACING DOUBLE OVERSCORE;;;; 0340;COMBINING GRAVE TONE MARK;Mn;230;NSM;0300;;;;N;NON-SPACING GRAVE TONE MARK;Vietnamese;;; 0341;COMBINING ACUTE TONE MARK;Mn;230;NSM;0301;;;;N;NON-SPACING ACUTE TONE MARK;Vietnamese;;; 0342;COMBINING GREEK PERISPOMENI;Mn;230;NSM;;;;;N;;;;; 0343;COMBINING GREEK KORONIS;Mn;230;NSM;0313;;;;N;;;;; 0344;COMBINING GREEK DIALYTIKA TONOS;Mn;230;NSM;0308 0301;;;;N;GREEK NON-SPACING DIAERESIS TONOS;;;; 0345;COMBINING GREEK YPOGEGRAMMENI;Mn;240;NSM;;;;;N;GREEK NON-SPACING IOTA BELOW;;0399;;0399 0346;COMBINING BRIDGE ABOVE;Mn;230;NSM;;;;;N;;;;; 0347;COMBINING EQUALS SIGN BELOW;Mn;220;NSM;;;;;N;;;;; 0348;COMBINING DOUBLE VERTICAL LINE BELOW;Mn;220;NSM;;;;;N;;;;; 0349;COMBINING LEFT ANGLE BELOW;Mn;220;NSM;;;;;N;;;;; 034A;COMBINING NOT TILDE ABOVE;Mn;230;NSM;;;;;N;;;;; 034B;COMBINING HOMOTHETIC ABOVE;Mn;230;NSM;;;;;N;;;;; 034C;COMBINING ALMOST EQUAL TO ABOVE;Mn;230;NSM;;;;;N;;;;; 034D;COMBINING LEFT RIGHT ARROW BELOW;Mn;220;NSM;;;;;N;;;;; 034E;COMBINING UPWARDS ARROW BELOW;Mn;220;NSM;;;;;N;;;;; 034F;COMBINING GRAPHEME JOINER;Mn;0;NSM;;;;;N;;;;; 0360;COMBINING DOUBLE TILDE;Mn;234;NSM;;;;;N;;;;; 0361;COMBINING DOUBLE INVERTED BREVE;Mn;234;NSM;;;;;N;;;;; 0362;COMBINING DOUBLE RIGHTWARDS ARROW BELOW;Mn;233;NSM;;;;;N;;;;; 0363;COMBINING LATIN SMALL LETTER A;Mn;230;NSM;;;;;N;;;;; 0364;COMBINING LATIN SMALL LETTER E;Mn;230;NSM;;;;;N;;;;; 0365;COMBINING LATIN SMALL LETTER I;Mn;230;NSM;;;;;N;;;;; 0366;COMBINING LATIN SMALL LETTER O;Mn;230;NSM;;;;;N;;;;; 0367;COMBINING LATIN SMALL LETTER U;Mn;230;NSM;;;;;N;;;;; 0368;COMBINING LATIN SMALL LETTER C;Mn;230;NSM;;;;;N;;;;; 0369;COMBINING LATIN SMALL LETTER D;Mn;230;NSM;;;;;N;;;;; 036A;COMBINING LATIN SMALL LETTER H;Mn;230;NSM;;;;;N;;;;; 036B;COMBINING LATIN SMALL LETTER M;Mn;230;NSM;;;;;N;;;;; 036C;COMBINING LATIN SMALL LETTER R;Mn;230;NSM;;;;;N;;;;; 036D;COMBINING LATIN SMALL LETTER T;Mn;230;NSM;;;;;N;;;;; 036E;COMBINING LATIN SMALL LETTER V;Mn;230;NSM;;;;;N;;;;; 036F;COMBINING LATIN SMALL LETTER X;Mn;230;NSM;;;;;N;;;;; 0374;GREEK NUMERAL SIGN;Sk;0;ON;02B9;;;;N;GREEK UPPER NUMERAL SIGN;Dexia keraia;;; 0375;GREEK LOWER NUMERAL SIGN;Sk;0;ON;;;;;N;;Aristeri keraia;;; 037A;GREEK YPOGEGRAMMENI;Lm;0;L; 0020 0345;;;;N;GREEK SPACING IOTA BELOW;;;; 037E;GREEK QUESTION MARK;Po;0;ON;003B;;;;N;;Erotimatiko;;; 0384;GREEK TONOS;Sk;0;ON; 0020 0301;;;;N;GREEK SPACING TONOS;;;; 0385;GREEK DIALYTIKA TONOS;Sk;0;ON;00A8 0301;;;;N;GREEK SPACING DIAERESIS TONOS;;;; 0386;GREEK CAPITAL LETTER ALPHA WITH TONOS;Lu;0;L;0391 0301;;;;N;GREEK CAPITAL LETTER ALPHA TONOS;;;03AC; 0387;GREEK ANO TELEIA;Po;0;ON;00B7;;;;N;;;;; 0388;GREEK CAPITAL LETTER EPSILON WITH TONOS;Lu;0;L;0395 0301;;;;N;GREEK CAPITAL LETTER EPSILON TONOS;;;03AD; 0389;GREEK CAPITAL LETTER ETA WITH TONOS;Lu;0;L;0397 0301;;;;N;GREEK CAPITAL LETTER ETA TONOS;;;03AE; 038A;GREEK CAPITAL LETTER IOTA WITH TONOS;Lu;0;L;0399 0301;;;;N;GREEK CAPITAL LETTER IOTA TONOS;;;03AF; 038C;GREEK CAPITAL LETTER OMICRON WITH TONOS;Lu;0;L;039F 0301;;;;N;GREEK CAPITAL LETTER OMICRON TONOS;;;03CC; 038E;GREEK CAPITAL LETTER UPSILON WITH TONOS;Lu;0;L;03A5 0301;;;;N;GREEK CAPITAL LETTER UPSILON TONOS;;;03CD; 038F;GREEK CAPITAL LETTER OMEGA WITH TONOS;Lu;0;L;03A9 0301;;;;N;GREEK CAPITAL LETTER OMEGA TONOS;;;03CE; 0390;GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS;Ll;0;L;03CA 0301;;;;N;GREEK SMALL LETTER IOTA DIAERESIS TONOS;;;; 0391;GREEK CAPITAL LETTER ALPHA;Lu;0;L;;;;;N;;;;03B1; 0392;GREEK CAPITAL LETTER BETA;Lu;0;L;;;;;N;;;;03B2; 0393;GREEK CAPITAL LETTER GAMMA;Lu;0;L;;;;;N;;;;03B3; 0394;GREEK CAPITAL LETTER DELTA;Lu;0;L;;;;;N;;;;03B4; 0395;GREEK CAPITAL LETTER EPSILON;Lu;0;L;;;;;N;;;;03B5; 0396;GREEK CAPITAL LETTER ZETA;Lu;0;L;;;;;N;;;;03B6; 0397;GREEK CAPITAL LETTER ETA;Lu;0;L;;;;;N;;;;03B7; 0398;GREEK CAPITAL LETTER THETA;Lu;0;L;;;;;N;;;;03B8; 0399;GREEK CAPITAL LETTER IOTA;Lu;0;L;;;;;N;;;;03B9; 039A;GREEK CAPITAL LETTER KAPPA;Lu;0;L;;;;;N;;;;03BA; 039B;GREEK CAPITAL LETTER LAMDA;Lu;0;L;;;;;N;GREEK CAPITAL LETTER LAMBDA;;;03BB; 039C;GREEK CAPITAL LETTER MU;Lu;0;L;;;;;N;;;;03BC; 039D;GREEK CAPITAL LETTER NU;Lu;0;L;;;;;N;;;;03BD; 039E;GREEK CAPITAL LETTER XI;Lu;0;L;;;;;N;;;;03BE; 039F;GREEK CAPITAL LETTER OMICRON;Lu;0;L;;;;;N;;;;03BF; 03A0;GREEK CAPITAL LETTER PI;Lu;0;L;;;;;N;;;;03C0; 03A1;GREEK CAPITAL LETTER RHO;Lu;0;L;;;;;N;;;;03C1; 03A3;GREEK CAPITAL LETTER SIGMA;Lu;0;L;;;;;N;;;;03C3; 03A4;GREEK CAPITAL LETTER TAU;Lu;0;L;;;;;N;;;;03C4; 03A5;GREEK CAPITAL LETTER UPSILON;Lu;0;L;;;;;N;;;;03C5; 03A6;GREEK CAPITAL LETTER PHI;Lu;0;L;;;;;N;;;;03C6; 03A7;GREEK CAPITAL LETTER CHI;Lu;0;L;;;;;N;;;;03C7; 03A8;GREEK CAPITAL LETTER PSI;Lu;0;L;;;;;N;;;;03C8; 03A9;GREEK CAPITAL LETTER OMEGA;Lu;0;L;;;;;N;;;;03C9; 03AA;GREEK CAPITAL LETTER IOTA WITH DIALYTIKA;Lu;0;L;0399 0308;;;;N;GREEK CAPITAL LETTER IOTA DIAERESIS;;;03CA; 03AB;GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA;Lu;0;L;03A5 0308;;;;N;GREEK CAPITAL LETTER UPSILON DIAERESIS;;;03CB; 03AC;GREEK SMALL LETTER ALPHA WITH TONOS;Ll;0;L;03B1 0301;;;;N;GREEK SMALL LETTER ALPHA TONOS;;0386;;0386 03AD;GREEK SMALL LETTER EPSILON WITH TONOS;Ll;0;L;03B5 0301;;;;N;GREEK SMALL LETTER EPSILON TONOS;;0388;;0388 03AE;GREEK SMALL LETTER ETA WITH TONOS;Ll;0;L;03B7 0301;;;;N;GREEK SMALL LETTER ETA TONOS;;0389;;0389 03AF;GREEK SMALL LETTER IOTA WITH TONOS;Ll;0;L;03B9 0301;;;;N;GREEK SMALL LETTER IOTA TONOS;;038A;;038A 03B0;GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS;Ll;0;L;03CB 0301;;;;N;GREEK SMALL LETTER UPSILON DIAERESIS TONOS;;;; 03B1;GREEK SMALL LETTER ALPHA;Ll;0;L;;;;;N;;;0391;;0391 03B2;GREEK SMALL LETTER BETA;Ll;0;L;;;;;N;;;0392;;0392 03B3;GREEK SMALL LETTER GAMMA;Ll;0;L;;;;;N;;;0393;;0393 03B4;GREEK SMALL LETTER DELTA;Ll;0;L;;;;;N;;;0394;;0394 03B5;GREEK SMALL LETTER EPSILON;Ll;0;L;;;;;N;;;0395;;0395 03B6;GREEK SMALL LETTER ZETA;Ll;0;L;;;;;N;;;0396;;0396 03B7;GREEK SMALL LETTER ETA;Ll;0;L;;;;;N;;;0397;;0397 03B8;GREEK SMALL LETTER THETA;Ll;0;L;;;;;N;;;0398;;0398 03B9;GREEK SMALL LETTER IOTA;Ll;0;L;;;;;N;;;0399;;0399 03BA;GREEK SMALL LETTER KAPPA;Ll;0;L;;;;;N;;;039A;;039A 03BB;GREEK SMALL LETTER LAMDA;Ll;0;L;;;;;N;GREEK SMALL LETTER LAMBDA;;039B;;039B 03BC;GREEK SMALL LETTER MU;Ll;0;L;;;;;N;;;039C;;039C 03BD;GREEK SMALL LETTER NU;Ll;0;L;;;;;N;;;039D;;039D 03BE;GREEK SMALL LETTER XI;Ll;0;L;;;;;N;;;039E;;039E 03BF;GREEK SMALL LETTER OMICRON;Ll;0;L;;;;;N;;;039F;;039F 03C0;GREEK SMALL LETTER PI;Ll;0;L;;;;;N;;;03A0;;03A0 03C1;GREEK SMALL LETTER RHO;Ll;0;L;;;;;N;;;03A1;;03A1 03C2;GREEK SMALL LETTER FINAL SIGMA;Ll;0;L;;;;;N;;;03A3;;03A3 03C3;GREEK SMALL LETTER SIGMA;Ll;0;L;;;;;N;;;03A3;;03A3 03C4;GREEK SMALL LETTER TAU;Ll;0;L;;;;;N;;;03A4;;03A4 03C5;GREEK SMALL LETTER UPSILON;Ll;0;L;;;;;N;;;03A5;;03A5 03C6;GREEK SMALL LETTER PHI;Ll;0;L;;;;;N;;;03A6;;03A6 03C7;GREEK SMALL LETTER CHI;Ll;0;L;;;;;N;;;03A7;;03A7 03C8;GREEK SMALL LETTER PSI;Ll;0;L;;;;;N;;;03A8;;03A8 03C9;GREEK SMALL LETTER OMEGA;Ll;0;L;;;;;N;;;03A9;;03A9 03CA;GREEK SMALL LETTER IOTA WITH DIALYTIKA;Ll;0;L;03B9 0308;;;;N;GREEK SMALL LETTER IOTA DIAERESIS;;03AA;;03AA 03CB;GREEK SMALL LETTER UPSILON WITH DIALYTIKA;Ll;0;L;03C5 0308;;;;N;GREEK SMALL LETTER UPSILON DIAERESIS;;03AB;;03AB 03CC;GREEK SMALL LETTER OMICRON WITH TONOS;Ll;0;L;03BF 0301;;;;N;GREEK SMALL LETTER OMICRON TONOS;;038C;;038C 03CD;GREEK SMALL LETTER UPSILON WITH TONOS;Ll;0;L;03C5 0301;;;;N;GREEK SMALL LETTER UPSILON TONOS;;038E;;038E 03CE;GREEK SMALL LETTER OMEGA WITH TONOS;Ll;0;L;03C9 0301;;;;N;GREEK SMALL LETTER OMEGA TONOS;;038F;;038F 03D0;GREEK BETA SYMBOL;Ll;0;L; 03B2;;;;N;GREEK SMALL LETTER CURLED BETA;;0392;;0392 03D1;GREEK THETA SYMBOL;Ll;0;L; 03B8;;;;N;GREEK SMALL LETTER SCRIPT THETA;;0398;;0398 03D2;GREEK UPSILON WITH HOOK SYMBOL;Lu;0;L; 03A5;;;;N;GREEK CAPITAL LETTER UPSILON HOOK;;;; 03D3;GREEK UPSILON WITH ACUTE AND HOOK SYMBOL;Lu;0;L;03D2 0301;;;;N;GREEK CAPITAL LETTER UPSILON HOOK TONOS;;;; 03D4;GREEK UPSILON WITH DIAERESIS AND HOOK SYMBOL;Lu;0;L;03D2 0308;;;;N;GREEK CAPITAL LETTER UPSILON HOOK DIAERESIS;;;; 03D5;GREEK PHI SYMBOL;Ll;0;L; 03C6;;;;N;GREEK SMALL LETTER SCRIPT PHI;;03A6;;03A6 03D6;GREEK PI SYMBOL;Ll;0;L; 03C0;;;;N;GREEK SMALL LETTER OMEGA PI;;03A0;;03A0 03D7;GREEK KAI SYMBOL;Ll;0;L;;;;;N;;;;; 03D8;GREEK LETTER ARCHAIC KOPPA;Lu;0;L;;;;;N;;*;;03D9; 03D9;GREEK SMALL LETTER ARCHAIC KOPPA;Ll;0;L;;;;;N;;*;03D8;;03D8 03DA;GREEK LETTER STIGMA;Lu;0;L;;;;;N;GREEK CAPITAL LETTER STIGMA;;;03DB; 03DB;GREEK SMALL LETTER STIGMA;Ll;0;L;;;;;N;;;03DA;;03DA 03DC;GREEK LETTER DIGAMMA;Lu;0;L;;;;;N;GREEK CAPITAL LETTER DIGAMMA;;;03DD; 03DD;GREEK SMALL LETTER DIGAMMA;Ll;0;L;;;;;N;;;03DC;;03DC 03DE;GREEK LETTER KOPPA;Lu;0;L;;;;;N;GREEK CAPITAL LETTER KOPPA;;;03DF; 03DF;GREEK SMALL LETTER KOPPA;Ll;0;L;;;;;N;;;03DE;;03DE 03E0;GREEK LETTER SAMPI;Lu;0;L;;;;;N;GREEK CAPITAL LETTER SAMPI;;;03E1; 03E1;GREEK SMALL LETTER SAMPI;Ll;0;L;;;;;N;;;03E0;;03E0 03E2;COPTIC CAPITAL LETTER SHEI;Lu;0;L;;;;;N;GREEK CAPITAL LETTER SHEI;;;03E3; 03E3;COPTIC SMALL LETTER SHEI;Ll;0;L;;;;;N;GREEK SMALL LETTER SHEI;;03E2;;03E2 03E4;COPTIC CAPITAL LETTER FEI;Lu;0;L;;;;;N;GREEK CAPITAL LETTER FEI;;;03E5; 03E5;COPTIC SMALL LETTER FEI;Ll;0;L;;;;;N;GREEK SMALL LETTER FEI;;03E4;;03E4 03E6;COPTIC CAPITAL LETTER KHEI;Lu;0;L;;;;;N;GREEK CAPITAL LETTER KHEI;;;03E7; 03E7;COPTIC SMALL LETTER KHEI;Ll;0;L;;;;;N;GREEK SMALL LETTER KHEI;;03E6;;03E6 03E8;COPTIC CAPITAL LETTER HORI;Lu;0;L;;;;;N;GREEK CAPITAL LETTER HORI;;;03E9; 03E9;COPTIC SMALL LETTER HORI;Ll;0;L;;;;;N;GREEK SMALL LETTER HORI;;03E8;;03E8 03EA;COPTIC CAPITAL LETTER GANGIA;Lu;0;L;;;;;N;GREEK CAPITAL LETTER GANGIA;;;03EB; 03EB;COPTIC SMALL LETTER GANGIA;Ll;0;L;;;;;N;GREEK SMALL LETTER GANGIA;;03EA;;03EA 03EC;COPTIC CAPITAL LETTER SHIMA;Lu;0;L;;;;;N;GREEK CAPITAL LETTER SHIMA;;;03ED; 03ED;COPTIC SMALL LETTER SHIMA;Ll;0;L;;;;;N;GREEK SMALL LETTER SHIMA;;03EC;;03EC 03EE;COPTIC CAPITAL LETTER DEI;Lu;0;L;;;;;N;GREEK CAPITAL LETTER DEI;;;03EF; 03EF;COPTIC SMALL LETTER DEI;Ll;0;L;;;;;N;GREEK SMALL LETTER DEI;;03EE;;03EE 03F0;GREEK KAPPA SYMBOL;Ll;0;L; 03BA;;;;N;GREEK SMALL LETTER SCRIPT KAPPA;;039A;;039A 03F1;GREEK RHO SYMBOL;Ll;0;L; 03C1;;;;N;GREEK SMALL LETTER TAILED RHO;;03A1;;03A1 03F2;GREEK LUNATE SIGMA SYMBOL;Ll;0;L; 03C2;;;;N;GREEK SMALL LETTER LUNATE SIGMA;;03A3;;03A3 03F3;GREEK LETTER YOT;Ll;0;L;;;;;N;;;;; 03F4;GREEK CAPITAL THETA SYMBOL;Lu;0;L; 0398;;;;N;;;;03B8; 03F5;GREEK LUNATE EPSILON SYMBOL;Ll;0;L; 03B5;;;;N;;;0395;;0395 03F6;GREEK REVERSED LUNATE EPSILON SYMBOL;Sm;0;ON;;;;;N;;;;; 0400;CYRILLIC CAPITAL LETTER IE WITH GRAVE;Lu;0;L;0415 0300;;;;N;;;;0450; 0401;CYRILLIC CAPITAL LETTER IO;Lu;0;L;0415 0308;;;;N;;;;0451; 0402;CYRILLIC CAPITAL LETTER DJE;Lu;0;L;;;;;N;;Serbocroatian;;0452; 0403;CYRILLIC CAPITAL LETTER GJE;Lu;0;L;0413 0301;;;;N;;;;0453; 0404;CYRILLIC CAPITAL LETTER UKRAINIAN IE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER E;;;0454; 0405;CYRILLIC CAPITAL LETTER DZE;Lu;0;L;;;;;N;;;;0455; 0406;CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER I;;;0456; 0407;CYRILLIC CAPITAL LETTER YI;Lu;0;L;0406 0308;;;;N;;Ukrainian;;0457; 0408;CYRILLIC CAPITAL LETTER JE;Lu;0;L;;;;;N;;;;0458; 0409;CYRILLIC CAPITAL LETTER LJE;Lu;0;L;;;;;N;;;;0459; 040A;CYRILLIC CAPITAL LETTER NJE;Lu;0;L;;;;;N;;;;045A; 040B;CYRILLIC CAPITAL LETTER TSHE;Lu;0;L;;;;;N;;Serbocroatian;;045B; 040C;CYRILLIC CAPITAL LETTER KJE;Lu;0;L;041A 0301;;;;N;;;;045C; 040D;CYRILLIC CAPITAL LETTER I WITH GRAVE;Lu;0;L;0418 0300;;;;N;;;;045D; 040E;CYRILLIC CAPITAL LETTER SHORT U;Lu;0;L;0423 0306;;;;N;;Byelorussian;;045E; 040F;CYRILLIC CAPITAL LETTER DZHE;Lu;0;L;;;;;N;;;;045F; 0410;CYRILLIC CAPITAL LETTER A;Lu;0;L;;;;;N;;;;0430; 0411;CYRILLIC CAPITAL LETTER BE;Lu;0;L;;;;;N;;;;0431; 0412;CYRILLIC CAPITAL LETTER VE;Lu;0;L;;;;;N;;;;0432; 0413;CYRILLIC CAPITAL LETTER GHE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER GE;;;0433; 0414;CYRILLIC CAPITAL LETTER DE;Lu;0;L;;;;;N;;;;0434; 0415;CYRILLIC CAPITAL LETTER IE;Lu;0;L;;;;;N;;;;0435; 0416;CYRILLIC CAPITAL LETTER ZHE;Lu;0;L;;;;;N;;;;0436; 0417;CYRILLIC CAPITAL LETTER ZE;Lu;0;L;;;;;N;;;;0437; 0418;CYRILLIC CAPITAL LETTER I;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER II;;;0438; 0419;CYRILLIC CAPITAL LETTER SHORT I;Lu;0;L;0418 0306;;;;N;CYRILLIC CAPITAL LETTER SHORT II;;;0439; 041A;CYRILLIC CAPITAL LETTER KA;Lu;0;L;;;;;N;;;;043A; 041B;CYRILLIC CAPITAL LETTER EL;Lu;0;L;;;;;N;;;;043B; 041C;CYRILLIC CAPITAL LETTER EM;Lu;0;L;;;;;N;;;;043C; 041D;CYRILLIC CAPITAL LETTER EN;Lu;0;L;;;;;N;;;;043D; 041E;CYRILLIC CAPITAL LETTER O;Lu;0;L;;;;;N;;;;043E; 041F;CYRILLIC CAPITAL LETTER PE;Lu;0;L;;;;;N;;;;043F; 0420;CYRILLIC CAPITAL LETTER ER;Lu;0;L;;;;;N;;;;0440; 0421;CYRILLIC CAPITAL LETTER ES;Lu;0;L;;;;;N;;;;0441; 0422;CYRILLIC CAPITAL LETTER TE;Lu;0;L;;;;;N;;;;0442; 0423;CYRILLIC CAPITAL LETTER U;Lu;0;L;;;;;N;;;;0443; 0424;CYRILLIC CAPITAL LETTER EF;Lu;0;L;;;;;N;;;;0444; 0425;CYRILLIC CAPITAL LETTER HA;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER KHA;;;0445; 0426;CYRILLIC CAPITAL LETTER TSE;Lu;0;L;;;;;N;;;;0446; 0427;CYRILLIC CAPITAL LETTER CHE;Lu;0;L;;;;;N;;;;0447; 0428;CYRILLIC CAPITAL LETTER SHA;Lu;0;L;;;;;N;;;;0448; 0429;CYRILLIC CAPITAL LETTER SHCHA;Lu;0;L;;;;;N;;;;0449; 042A;CYRILLIC CAPITAL LETTER HARD SIGN;Lu;0;L;;;;;N;;;;044A; 042B;CYRILLIC CAPITAL LETTER YERU;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER YERI;;;044B; 042C;CYRILLIC CAPITAL LETTER SOFT SIGN;Lu;0;L;;;;;N;;;;044C; 042D;CYRILLIC CAPITAL LETTER E;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER REVERSED E;;;044D; 042E;CYRILLIC CAPITAL LETTER YU;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER IU;;;044E; 042F;CYRILLIC CAPITAL LETTER YA;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER IA;;;044F; 0430;CYRILLIC SMALL LETTER A;Ll;0;L;;;;;N;;;0410;;0410 0431;CYRILLIC SMALL LETTER BE;Ll;0;L;;;;;N;;;0411;;0411 0432;CYRILLIC SMALL LETTER VE;Ll;0;L;;;;;N;;;0412;;0412 0433;CYRILLIC SMALL LETTER GHE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER GE;;0413;;0413 0434;CYRILLIC SMALL LETTER DE;Ll;0;L;;;;;N;;;0414;;0414 0435;CYRILLIC SMALL LETTER IE;Ll;0;L;;;;;N;;;0415;;0415 0436;CYRILLIC SMALL LETTER ZHE;Ll;0;L;;;;;N;;;0416;;0416 0437;CYRILLIC SMALL LETTER ZE;Ll;0;L;;;;;N;;;0417;;0417 0438;CYRILLIC SMALL LETTER I;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER II;;0418;;0418 0439;CYRILLIC SMALL LETTER SHORT I;Ll;0;L;0438 0306;;;;N;CYRILLIC SMALL LETTER SHORT II;;0419;;0419 043A;CYRILLIC SMALL LETTER KA;Ll;0;L;;;;;N;;;041A;;041A 043B;CYRILLIC SMALL LETTER EL;Ll;0;L;;;;;N;;;041B;;041B 043C;CYRILLIC SMALL LETTER EM;Ll;0;L;;;;;N;;;041C;;041C 043D;CYRILLIC SMALL LETTER EN;Ll;0;L;;;;;N;;;041D;;041D 043E;CYRILLIC SMALL LETTER O;Ll;0;L;;;;;N;;;041E;;041E 043F;CYRILLIC SMALL LETTER PE;Ll;0;L;;;;;N;;;041F;;041F 0440;CYRILLIC SMALL LETTER ER;Ll;0;L;;;;;N;;;0420;;0420 0441;CYRILLIC SMALL LETTER ES;Ll;0;L;;;;;N;;;0421;;0421 0442;CYRILLIC SMALL LETTER TE;Ll;0;L;;;;;N;;;0422;;0422 0443;CYRILLIC SMALL LETTER U;Ll;0;L;;;;;N;;;0423;;0423 0444;CYRILLIC SMALL LETTER EF;Ll;0;L;;;;;N;;;0424;;0424 0445;CYRILLIC SMALL LETTER HA;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER KHA;;0425;;0425 0446;CYRILLIC SMALL LETTER TSE;Ll;0;L;;;;;N;;;0426;;0426 0447;CYRILLIC SMALL LETTER CHE;Ll;0;L;;;;;N;;;0427;;0427 0448;CYRILLIC SMALL LETTER SHA;Ll;0;L;;;;;N;;;0428;;0428 0449;CYRILLIC SMALL LETTER SHCHA;Ll;0;L;;;;;N;;;0429;;0429 044A;CYRILLIC SMALL LETTER HARD SIGN;Ll;0;L;;;;;N;;;042A;;042A 044B;CYRILLIC SMALL LETTER YERU;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER YERI;;042B;;042B 044C;CYRILLIC SMALL LETTER SOFT SIGN;Ll;0;L;;;;;N;;;042C;;042C 044D;CYRILLIC SMALL LETTER E;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER REVERSED E;;042D;;042D 044E;CYRILLIC SMALL LETTER YU;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER IU;;042E;;042E 044F;CYRILLIC SMALL LETTER YA;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER IA;;042F;;042F 0450;CYRILLIC SMALL LETTER IE WITH GRAVE;Ll;0;L;0435 0300;;;;N;;;0400;;0400 0451;CYRILLIC SMALL LETTER IO;Ll;0;L;0435 0308;;;;N;;;0401;;0401 0452;CYRILLIC SMALL LETTER DJE;Ll;0;L;;;;;N;;Serbocroatian;0402;;0402 0453;CYRILLIC SMALL LETTER GJE;Ll;0;L;0433 0301;;;;N;;;0403;;0403 0454;CYRILLIC SMALL LETTER UKRAINIAN IE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER E;;0404;;0404 0455;CYRILLIC SMALL LETTER DZE;Ll;0;L;;;;;N;;;0405;;0405 0456;CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER I;;0406;;0406 0457;CYRILLIC SMALL LETTER YI;Ll;0;L;0456 0308;;;;N;;Ukrainian;0407;;0407 0458;CYRILLIC SMALL LETTER JE;Ll;0;L;;;;;N;;;0408;;0408 0459;CYRILLIC SMALL LETTER LJE;Ll;0;L;;;;;N;;;0409;;0409 045A;CYRILLIC SMALL LETTER NJE;Ll;0;L;;;;;N;;;040A;;040A 045B;CYRILLIC SMALL LETTER TSHE;Ll;0;L;;;;;N;;Serbocroatian;040B;;040B 045C;CYRILLIC SMALL LETTER KJE;Ll;0;L;043A 0301;;;;N;;;040C;;040C 045D;CYRILLIC SMALL LETTER I WITH GRAVE;Ll;0;L;0438 0300;;;;N;;;040D;;040D 045E;CYRILLIC SMALL LETTER SHORT U;Ll;0;L;0443 0306;;;;N;;Byelorussian;040E;;040E 045F;CYRILLIC SMALL LETTER DZHE;Ll;0;L;;;;;N;;;040F;;040F 0460;CYRILLIC CAPITAL LETTER OMEGA;Lu;0;L;;;;;N;;;;0461; 0461;CYRILLIC SMALL LETTER OMEGA;Ll;0;L;;;;;N;;;0460;;0460 0462;CYRILLIC CAPITAL LETTER YAT;Lu;0;L;;;;;N;;;;0463; 0463;CYRILLIC SMALL LETTER YAT;Ll;0;L;;;;;N;;;0462;;0462 0464;CYRILLIC CAPITAL LETTER IOTIFIED E;Lu;0;L;;;;;N;;;;0465; 0465;CYRILLIC SMALL LETTER IOTIFIED E;Ll;0;L;;;;;N;;;0464;;0464 0466;CYRILLIC CAPITAL LETTER LITTLE YUS;Lu;0;L;;;;;N;;;;0467; 0467;CYRILLIC SMALL LETTER LITTLE YUS;Ll;0;L;;;;;N;;;0466;;0466 0468;CYRILLIC CAPITAL LETTER IOTIFIED LITTLE YUS;Lu;0;L;;;;;N;;;;0469; 0469;CYRILLIC SMALL LETTER IOTIFIED LITTLE YUS;Ll;0;L;;;;;N;;;0468;;0468 046A;CYRILLIC CAPITAL LETTER BIG YUS;Lu;0;L;;;;;N;;;;046B; 046B;CYRILLIC SMALL LETTER BIG YUS;Ll;0;L;;;;;N;;;046A;;046A 046C;CYRILLIC CAPITAL LETTER IOTIFIED BIG YUS;Lu;0;L;;;;;N;;;;046D; 046D;CYRILLIC SMALL LETTER IOTIFIED BIG YUS;Ll;0;L;;;;;N;;;046C;;046C 046E;CYRILLIC CAPITAL LETTER KSI;Lu;0;L;;;;;N;;;;046F; 046F;CYRILLIC SMALL LETTER KSI;Ll;0;L;;;;;N;;;046E;;046E 0470;CYRILLIC CAPITAL LETTER PSI;Lu;0;L;;;;;N;;;;0471; 0471;CYRILLIC SMALL LETTER PSI;Ll;0;L;;;;;N;;;0470;;0470 0472;CYRILLIC CAPITAL LETTER FITA;Lu;0;L;;;;;N;;;;0473; 0473;CYRILLIC SMALL LETTER FITA;Ll;0;L;;;;;N;;;0472;;0472 0474;CYRILLIC CAPITAL LETTER IZHITSA;Lu;0;L;;;;;N;;;;0475; 0475;CYRILLIC SMALL LETTER IZHITSA;Ll;0;L;;;;;N;;;0474;;0474 0476;CYRILLIC CAPITAL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT;Lu;0;L;0474 030F;;;;N;CYRILLIC CAPITAL LETTER IZHITSA DOUBLE GRAVE;;;0477; 0477;CYRILLIC SMALL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT;Ll;0;L;0475 030F;;;;N;CYRILLIC SMALL LETTER IZHITSA DOUBLE GRAVE;;0476;;0476 0478;CYRILLIC CAPITAL LETTER UK;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER UK DIGRAPH;;;0479; 0479;CYRILLIC SMALL LETTER UK;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER UK DIGRAPH;;0478;;0478 047A;CYRILLIC CAPITAL LETTER ROUND OMEGA;Lu;0;L;;;;;N;;;;047B; 047B;CYRILLIC SMALL LETTER ROUND OMEGA;Ll;0;L;;;;;N;;;047A;;047A 047C;CYRILLIC CAPITAL LETTER OMEGA WITH TITLO;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER OMEGA TITLO;;;047D; 047D;CYRILLIC SMALL LETTER OMEGA WITH TITLO;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER OMEGA TITLO;;047C;;047C 047E;CYRILLIC CAPITAL LETTER OT;Lu;0;L;;;;;N;;;;047F; 047F;CYRILLIC SMALL LETTER OT;Ll;0;L;;;;;N;;;047E;;047E 0480;CYRILLIC CAPITAL LETTER KOPPA;Lu;0;L;;;;;N;;;;0481; 0481;CYRILLIC SMALL LETTER KOPPA;Ll;0;L;;;;;N;;;0480;;0480 0482;CYRILLIC THOUSANDS SIGN;So;0;L;;;;;N;;;;; 0483;COMBINING CYRILLIC TITLO;Mn;230;NSM;;;;;N;CYRILLIC NON-SPACING TITLO;;;; 0484;COMBINING CYRILLIC PALATALIZATION;Mn;230;NSM;;;;;N;CYRILLIC NON-SPACING PALATALIZATION;;;; 0485;COMBINING CYRILLIC DASIA PNEUMATA;Mn;230;NSM;;;;;N;CYRILLIC NON-SPACING DASIA PNEUMATA;;;; 0486;COMBINING CYRILLIC PSILI PNEUMATA;Mn;230;NSM;;;;;N;CYRILLIC NON-SPACING PSILI PNEUMATA;;;; 0488;COMBINING CYRILLIC HUNDRED THOUSANDS SIGN;Me;0;NSM;;;;;N;;;;; 0489;COMBINING CYRILLIC MILLIONS SIGN;Me;0;NSM;;;;;N;;;;; 048A;CYRILLIC CAPITAL LETTER SHORT I WITH TAIL;Lu;0;L;;;;;N;;;;048B; 048B;CYRILLIC SMALL LETTER SHORT I WITH TAIL;Ll;0;L;;;;;N;;;048A;;048A 048C;CYRILLIC CAPITAL LETTER SEMISOFT SIGN;Lu;0;L;;;;;N;;;;048D; 048D;CYRILLIC SMALL LETTER SEMISOFT SIGN;Ll;0;L;;;;;N;;;048C;;048C 048E;CYRILLIC CAPITAL LETTER ER WITH TICK;Lu;0;L;;;;;N;;;;048F; 048F;CYRILLIC SMALL LETTER ER WITH TICK;Ll;0;L;;;;;N;;;048E;;048E 0490;CYRILLIC CAPITAL LETTER GHE WITH UPTURN;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER GE WITH UPTURN;;;0491; 0491;CYRILLIC SMALL LETTER GHE WITH UPTURN;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER GE WITH UPTURN;;0490;;0490 0492;CYRILLIC CAPITAL LETTER GHE WITH STROKE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER GE BAR;;;0493; 0493;CYRILLIC SMALL LETTER GHE WITH STROKE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER GE BAR;;0492;;0492 0494;CYRILLIC CAPITAL LETTER GHE WITH MIDDLE HOOK;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER GE HOOK;;;0495; 0495;CYRILLIC SMALL LETTER GHE WITH MIDDLE HOOK;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER GE HOOK;;0494;;0494 0496;CYRILLIC CAPITAL LETTER ZHE WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER ZHE WITH RIGHT DESCENDER;;;0497; 0497;CYRILLIC SMALL LETTER ZHE WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER ZHE WITH RIGHT DESCENDER;;0496;;0496 0498;CYRILLIC CAPITAL LETTER ZE WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER ZE CEDILLA;;;0499; 0499;CYRILLIC SMALL LETTER ZE WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER ZE CEDILLA;;0498;;0498 049A;CYRILLIC CAPITAL LETTER KA WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER KA WITH RIGHT DESCENDER;;;049B; 049B;CYRILLIC SMALL LETTER KA WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER KA WITH RIGHT DESCENDER;;049A;;049A 049C;CYRILLIC CAPITAL LETTER KA WITH VERTICAL STROKE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER KA VERTICAL BAR;;;049D; 049D;CYRILLIC SMALL LETTER KA WITH VERTICAL STROKE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER KA VERTICAL BAR;;049C;;049C 049E;CYRILLIC CAPITAL LETTER KA WITH STROKE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER KA BAR;;;049F; 049F;CYRILLIC SMALL LETTER KA WITH STROKE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER KA BAR;;049E;;049E 04A0;CYRILLIC CAPITAL LETTER BASHKIR KA;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER REVERSED GE KA;;;04A1; 04A1;CYRILLIC SMALL LETTER BASHKIR KA;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER REVERSED GE KA;;04A0;;04A0 04A2;CYRILLIC CAPITAL LETTER EN WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER EN WITH RIGHT DESCENDER;;;04A3; 04A3;CYRILLIC SMALL LETTER EN WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER EN WITH RIGHT DESCENDER;;04A2;;04A2 04A4;CYRILLIC CAPITAL LIGATURE EN GHE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER EN GE;;;04A5; 04A5;CYRILLIC SMALL LIGATURE EN GHE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER EN GE;;04A4;;04A4 04A6;CYRILLIC CAPITAL LETTER PE WITH MIDDLE HOOK;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER PE HOOK;Abkhasian;;04A7; 04A7;CYRILLIC SMALL LETTER PE WITH MIDDLE HOOK;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER PE HOOK;Abkhasian;04A6;;04A6 04A8;CYRILLIC CAPITAL LETTER ABKHASIAN HA;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER O HOOK;;;04A9; 04A9;CYRILLIC SMALL LETTER ABKHASIAN HA;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER O HOOK;;04A8;;04A8 04AA;CYRILLIC CAPITAL LETTER ES WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER ES CEDILLA;;;04AB; 04AB;CYRILLIC SMALL LETTER ES WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER ES CEDILLA;;04AA;;04AA 04AC;CYRILLIC CAPITAL LETTER TE WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER TE WITH RIGHT DESCENDER;;;04AD; 04AD;CYRILLIC SMALL LETTER TE WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER TE WITH RIGHT DESCENDER;;04AC;;04AC 04AE;CYRILLIC CAPITAL LETTER STRAIGHT U;Lu;0;L;;;;;N;;;;04AF; 04AF;CYRILLIC SMALL LETTER STRAIGHT U;Ll;0;L;;;;;N;;;04AE;;04AE 04B0;CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER STRAIGHT U BAR;;;04B1; 04B1;CYRILLIC SMALL LETTER STRAIGHT U WITH STROKE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER STRAIGHT U BAR;;04B0;;04B0 04B2;CYRILLIC CAPITAL LETTER HA WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER KHA WITH RIGHT DESCENDER;;;04B3; 04B3;CYRILLIC SMALL LETTER HA WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER KHA WITH RIGHT DESCENDER;;04B2;;04B2 04B4;CYRILLIC CAPITAL LIGATURE TE TSE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER TE TSE;Abkhasian;;04B5; 04B5;CYRILLIC SMALL LIGATURE TE TSE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER TE TSE;Abkhasian;04B4;;04B4 04B6;CYRILLIC CAPITAL LETTER CHE WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER CHE WITH RIGHT DESCENDER;;;04B7; 04B7;CYRILLIC SMALL LETTER CHE WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER CHE WITH RIGHT DESCENDER;;04B6;;04B6 04B8;CYRILLIC CAPITAL LETTER CHE WITH VERTICAL STROKE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER CHE VERTICAL BAR;;;04B9; 04B9;CYRILLIC SMALL LETTER CHE WITH VERTICAL STROKE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER CHE VERTICAL BAR;;04B8;;04B8 04BA;CYRILLIC CAPITAL LETTER SHHA;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER H;;;04BB; 04BB;CYRILLIC SMALL LETTER SHHA;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER H;;04BA;;04BA 04BC;CYRILLIC CAPITAL LETTER ABKHASIAN CHE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER IE HOOK;;;04BD; 04BD;CYRILLIC SMALL LETTER ABKHASIAN CHE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER IE HOOK;;04BC;;04BC 04BE;CYRILLIC CAPITAL LETTER ABKHASIAN CHE WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER IE HOOK OGONEK;;;04BF; 04BF;CYRILLIC SMALL LETTER ABKHASIAN CHE WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER IE HOOK OGONEK;;04BE;;04BE 04C0;CYRILLIC LETTER PALOCHKA;Lu;0;L;;;;;N;CYRILLIC LETTER I;;;; 04C1;CYRILLIC CAPITAL LETTER ZHE WITH BREVE;Lu;0;L;0416 0306;;;;N;CYRILLIC CAPITAL LETTER SHORT ZHE;;;04C2; 04C2;CYRILLIC SMALL LETTER ZHE WITH BREVE;Ll;0;L;0436 0306;;;;N;CYRILLIC SMALL LETTER SHORT ZHE;;04C1;;04C1 04C3;CYRILLIC CAPITAL LETTER KA WITH HOOK;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER KA HOOK;;;04C4; 04C4;CYRILLIC SMALL LETTER KA WITH HOOK;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER KA HOOK;;04C3;;04C3 04C5;CYRILLIC CAPITAL LETTER EL WITH TAIL;Lu;0;L;;;;;N;;;;04C6; 04C6;CYRILLIC SMALL LETTER EL WITH TAIL;Ll;0;L;;;;;N;;;04C5;;04C5 04C7;CYRILLIC CAPITAL LETTER EN WITH HOOK;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER EN HOOK;;;04C8; 04C8;CYRILLIC SMALL LETTER EN WITH HOOK;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER EN HOOK;;04C7;;04C7 04C9;CYRILLIC CAPITAL LETTER EN WITH TAIL;Lu;0;L;;;;;N;;;;04CA; 04CA;CYRILLIC SMALL LETTER EN WITH TAIL;Ll;0;L;;;;;N;;;04C9;;04C9 04CB;CYRILLIC CAPITAL LETTER KHAKASSIAN CHE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER CHE WITH LEFT DESCENDER;;;04CC; 04CC;CYRILLIC SMALL LETTER KHAKASSIAN CHE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER CHE WITH LEFT DESCENDER;;04CB;;04CB 04CD;CYRILLIC CAPITAL LETTER EM WITH TAIL;Lu;0;L;;;;;N;;;;04CE; 04CE;CYRILLIC SMALL LETTER EM WITH TAIL;Ll;0;L;;;;;N;;;04CD;;04CD 04D0;CYRILLIC CAPITAL LETTER A WITH BREVE;Lu;0;L;0410 0306;;;;N;;;;04D1; 04D1;CYRILLIC SMALL LETTER A WITH BREVE;Ll;0;L;0430 0306;;;;N;;;04D0;;04D0 04D2;CYRILLIC CAPITAL LETTER A WITH DIAERESIS;Lu;0;L;0410 0308;;;;N;;;;04D3; 04D3;CYRILLIC SMALL LETTER A WITH DIAERESIS;Ll;0;L;0430 0308;;;;N;;;04D2;;04D2 04D4;CYRILLIC CAPITAL LIGATURE A IE;Lu;0;L;;;;;N;;;;04D5; 04D5;CYRILLIC SMALL LIGATURE A IE;Ll;0;L;;;;;N;;;04D4;;04D4 04D6;CYRILLIC CAPITAL LETTER IE WITH BREVE;Lu;0;L;0415 0306;;;;N;;;;04D7; 04D7;CYRILLIC SMALL LETTER IE WITH BREVE;Ll;0;L;0435 0306;;;;N;;;04D6;;04D6 04D8;CYRILLIC CAPITAL LETTER SCHWA;Lu;0;L;;;;;N;;;;04D9; 04D9;CYRILLIC SMALL LETTER SCHWA;Ll;0;L;;;;;N;;;04D8;;04D8 04DA;CYRILLIC CAPITAL LETTER SCHWA WITH DIAERESIS;Lu;0;L;04D8 0308;;;;N;;;;04DB; 04DB;CYRILLIC SMALL LETTER SCHWA WITH DIAERESIS;Ll;0;L;04D9 0308;;;;N;;;04DA;;04DA 04DC;CYRILLIC CAPITAL LETTER ZHE WITH DIAERESIS;Lu;0;L;0416 0308;;;;N;;;;04DD; 04DD;CYRILLIC SMALL LETTER ZHE WITH DIAERESIS;Ll;0;L;0436 0308;;;;N;;;04DC;;04DC 04DE;CYRILLIC CAPITAL LETTER ZE WITH DIAERESIS;Lu;0;L;0417 0308;;;;N;;;;04DF; 04DF;CYRILLIC SMALL LETTER ZE WITH DIAERESIS;Ll;0;L;0437 0308;;;;N;;;04DE;;04DE 04E0;CYRILLIC CAPITAL LETTER ABKHASIAN DZE;Lu;0;L;;;;;N;;;;04E1; 04E1;CYRILLIC SMALL LETTER ABKHASIAN DZE;Ll;0;L;;;;;N;;;04E0;;04E0 04E2;CYRILLIC CAPITAL LETTER I WITH MACRON;Lu;0;L;0418 0304;;;;N;;;;04E3; 04E3;CYRILLIC SMALL LETTER I WITH MACRON;Ll;0;L;0438 0304;;;;N;;;04E2;;04E2 04E4;CYRILLIC CAPITAL LETTER I WITH DIAERESIS;Lu;0;L;0418 0308;;;;N;;;;04E5; 04E5;CYRILLIC SMALL LETTER I WITH DIAERESIS;Ll;0;L;0438 0308;;;;N;;;04E4;;04E4 04E6;CYRILLIC CAPITAL LETTER O WITH DIAERESIS;Lu;0;L;041E 0308;;;;N;;;;04E7; 04E7;CYRILLIC SMALL LETTER O WITH DIAERESIS;Ll;0;L;043E 0308;;;;N;;;04E6;;04E6 04E8;CYRILLIC CAPITAL LETTER BARRED O;Lu;0;L;;;;;N;;;;04E9; 04E9;CYRILLIC SMALL LETTER BARRED O;Ll;0;L;;;;;N;;;04E8;;04E8 04EA;CYRILLIC CAPITAL LETTER BARRED O WITH DIAERESIS;Lu;0;L;04E8 0308;;;;N;;;;04EB; 04EB;CYRILLIC SMALL LETTER BARRED O WITH DIAERESIS;Ll;0;L;04E9 0308;;;;N;;;04EA;;04EA 04EC;CYRILLIC CAPITAL LETTER E WITH DIAERESIS;Lu;0;L;042D 0308;;;;N;;;;04ED; 04ED;CYRILLIC SMALL LETTER E WITH DIAERESIS;Ll;0;L;044D 0308;;;;N;;;04EC;;04EC 04EE;CYRILLIC CAPITAL LETTER U WITH MACRON;Lu;0;L;0423 0304;;;;N;;;;04EF; 04EF;CYRILLIC SMALL LETTER U WITH MACRON;Ll;0;L;0443 0304;;;;N;;;04EE;;04EE 04F0;CYRILLIC CAPITAL LETTER U WITH DIAERESIS;Lu;0;L;0423 0308;;;;N;;;;04F1; 04F1;CYRILLIC SMALL LETTER U WITH DIAERESIS;Ll;0;L;0443 0308;;;;N;;;04F0;;04F0 04F2;CYRILLIC CAPITAL LETTER U WITH DOUBLE ACUTE;Lu;0;L;0423 030B;;;;N;;;;04F3; 04F3;CYRILLIC SMALL LETTER U WITH DOUBLE ACUTE;Ll;0;L;0443 030B;;;;N;;;04F2;;04F2 04F4;CYRILLIC CAPITAL LETTER CHE WITH DIAERESIS;Lu;0;L;0427 0308;;;;N;;;;04F5; 04F5;CYRILLIC SMALL LETTER CHE WITH DIAERESIS;Ll;0;L;0447 0308;;;;N;;;04F4;;04F4 04F8;CYRILLIC CAPITAL LETTER YERU WITH DIAERESIS;Lu;0;L;042B 0308;;;;N;;;;04F9; 04F9;CYRILLIC SMALL LETTER YERU WITH DIAERESIS;Ll;0;L;044B 0308;;;;N;;;04F8;;04F8 0500;CYRILLIC CAPITAL LETTER KOMI DE;Lu;0;L;;;;;N;;;;0501; 0501;CYRILLIC SMALL LETTER KOMI DE;Ll;0;L;;;;;N;;;0500;;0500 0502;CYRILLIC CAPITAL LETTER KOMI DJE;Lu;0;L;;;;;N;;;;0503; 0503;CYRILLIC SMALL LETTER KOMI DJE;Ll;0;L;;;;;N;;;0502;;0502 0504;CYRILLIC CAPITAL LETTER KOMI ZJE;Lu;0;L;;;;;N;;;;0505; 0505;CYRILLIC SMALL LETTER KOMI ZJE;Ll;0;L;;;;;N;;;0504;;0504 0506;CYRILLIC CAPITAL LETTER KOMI DZJE;Lu;0;L;;;;;N;;;;0507; 0507;CYRILLIC SMALL LETTER KOMI DZJE;Ll;0;L;;;;;N;;;0506;;0506 0508;CYRILLIC CAPITAL LETTER KOMI LJE;Lu;0;L;;;;;N;;;;0509; 0509;CYRILLIC SMALL LETTER KOMI LJE;Ll;0;L;;;;;N;;;0508;;0508 050A;CYRILLIC CAPITAL LETTER KOMI NJE;Lu;0;L;;;;;N;;;;050B; 050B;CYRILLIC SMALL LETTER KOMI NJE;Ll;0;L;;;;;N;;;050A;;050A 050C;CYRILLIC CAPITAL LETTER KOMI SJE;Lu;0;L;;;;;N;;;;050D; 050D;CYRILLIC SMALL LETTER KOMI SJE;Ll;0;L;;;;;N;;;050C;;050C 050E;CYRILLIC CAPITAL LETTER KOMI TJE;Lu;0;L;;;;;N;;;;050F; 050F;CYRILLIC SMALL LETTER KOMI TJE;Ll;0;L;;;;;N;;;050E;;050E 0531;ARMENIAN CAPITAL LETTER AYB;Lu;0;L;;;;;N;;;;0561; 0532;ARMENIAN CAPITAL LETTER BEN;Lu;0;L;;;;;N;;;;0562; 0533;ARMENIAN CAPITAL LETTER GIM;Lu;0;L;;;;;N;;;;0563; 0534;ARMENIAN CAPITAL LETTER DA;Lu;0;L;;;;;N;;;;0564; 0535;ARMENIAN CAPITAL LETTER ECH;Lu;0;L;;;;;N;;;;0565; 0536;ARMENIAN CAPITAL LETTER ZA;Lu;0;L;;;;;N;;;;0566; 0537;ARMENIAN CAPITAL LETTER EH;Lu;0;L;;;;;N;;;;0567; 0538;ARMENIAN CAPITAL LETTER ET;Lu;0;L;;;;;N;;;;0568; 0539;ARMENIAN CAPITAL LETTER TO;Lu;0;L;;;;;N;;;;0569; 053A;ARMENIAN CAPITAL LETTER ZHE;Lu;0;L;;;;;N;;;;056A; 053B;ARMENIAN CAPITAL LETTER INI;Lu;0;L;;;;;N;;;;056B; 053C;ARMENIAN CAPITAL LETTER LIWN;Lu;0;L;;;;;N;;;;056C; 053D;ARMENIAN CAPITAL LETTER XEH;Lu;0;L;;;;;N;;;;056D; 053E;ARMENIAN CAPITAL LETTER CA;Lu;0;L;;;;;N;;;;056E; 053F;ARMENIAN CAPITAL LETTER KEN;Lu;0;L;;;;;N;;;;056F; 0540;ARMENIAN CAPITAL LETTER HO;Lu;0;L;;;;;N;;;;0570; 0541;ARMENIAN CAPITAL LETTER JA;Lu;0;L;;;;;N;;;;0571; 0542;ARMENIAN CAPITAL LETTER GHAD;Lu;0;L;;;;;N;ARMENIAN CAPITAL LETTER LAD;;;0572; 0543;ARMENIAN CAPITAL LETTER CHEH;Lu;0;L;;;;;N;;;;0573; 0544;ARMENIAN CAPITAL LETTER MEN;Lu;0;L;;;;;N;;;;0574; 0545;ARMENIAN CAPITAL LETTER YI;Lu;0;L;;;;;N;;;;0575; 0546;ARMENIAN CAPITAL LETTER NOW;Lu;0;L;;;;;N;;;;0576; 0547;ARMENIAN CAPITAL LETTER SHA;Lu;0;L;;;;;N;;;;0577; 0548;ARMENIAN CAPITAL LETTER VO;Lu;0;L;;;;;N;;;;0578; 0549;ARMENIAN CAPITAL LETTER CHA;Lu;0;L;;;;;N;;;;0579; 054A;ARMENIAN CAPITAL LETTER PEH;Lu;0;L;;;;;N;;;;057A; 054B;ARMENIAN CAPITAL LETTER JHEH;Lu;0;L;;;;;N;;;;057B; 054C;ARMENIAN CAPITAL LETTER RA;Lu;0;L;;;;;N;;;;057C; 054D;ARMENIAN CAPITAL LETTER SEH;Lu;0;L;;;;;N;;;;057D; 054E;ARMENIAN CAPITAL LETTER VEW;Lu;0;L;;;;;N;;;;057E; 054F;ARMENIAN CAPITAL LETTER TIWN;Lu;0;L;;;;;N;;;;057F; 0550;ARMENIAN CAPITAL LETTER REH;Lu;0;L;;;;;N;;;;0580; 0551;ARMENIAN CAPITAL LETTER CO;Lu;0;L;;;;;N;;;;0581; 0552;ARMENIAN CAPITAL LETTER YIWN;Lu;0;L;;;;;N;;;;0582; 0553;ARMENIAN CAPITAL LETTER PIWR;Lu;0;L;;;;;N;;;;0583; 0554;ARMENIAN CAPITAL LETTER KEH;Lu;0;L;;;;;N;;;;0584; 0555;ARMENIAN CAPITAL LETTER OH;Lu;0;L;;;;;N;;;;0585; 0556;ARMENIAN CAPITAL LETTER FEH;Lu;0;L;;;;;N;;;;0586; 0559;ARMENIAN MODIFIER LETTER LEFT HALF RING;Lm;0;L;;;;;N;;;;; 055A;ARMENIAN APOSTROPHE;Po;0;L;;;;;N;ARMENIAN MODIFIER LETTER RIGHT HALF RING;;;; 055B;ARMENIAN EMPHASIS MARK;Po;0;L;;;;;N;;;;; 055C;ARMENIAN EXCLAMATION MARK;Po;0;L;;;;;N;;;;; 055D;ARMENIAN COMMA;Po;0;L;;;;;N;;;;; 055E;ARMENIAN QUESTION MARK;Po;0;L;;;;;N;;;;; 055F;ARMENIAN ABBREVIATION MARK;Po;0;L;;;;;N;;;;; 0561;ARMENIAN SMALL LETTER AYB;Ll;0;L;;;;;N;;;0531;;0531 0562;ARMENIAN SMALL LETTER BEN;Ll;0;L;;;;;N;;;0532;;0532 0563;ARMENIAN SMALL LETTER GIM;Ll;0;L;;;;;N;;;0533;;0533 0564;ARMENIAN SMALL LETTER DA;Ll;0;L;;;;;N;;;0534;;0534 0565;ARMENIAN SMALL LETTER ECH;Ll;0;L;;;;;N;;;0535;;0535 0566;ARMENIAN SMALL LETTER ZA;Ll;0;L;;;;;N;;;0536;;0536 0567;ARMENIAN SMALL LETTER EH;Ll;0;L;;;;;N;;;0537;;0537 0568;ARMENIAN SMALL LETTER ET;Ll;0;L;;;;;N;;;0538;;0538 0569;ARMENIAN SMALL LETTER TO;Ll;0;L;;;;;N;;;0539;;0539 056A;ARMENIAN SMALL LETTER ZHE;Ll;0;L;;;;;N;;;053A;;053A 056B;ARMENIAN SMALL LETTER INI;Ll;0;L;;;;;N;;;053B;;053B 056C;ARMENIAN SMALL LETTER LIWN;Ll;0;L;;;;;N;;;053C;;053C 056D;ARMENIAN SMALL LETTER XEH;Ll;0;L;;;;;N;;;053D;;053D 056E;ARMENIAN SMALL LETTER CA;Ll;0;L;;;;;N;;;053E;;053E 056F;ARMENIAN SMALL LETTER KEN;Ll;0;L;;;;;N;;;053F;;053F 0570;ARMENIAN SMALL LETTER HO;Ll;0;L;;;;;N;;;0540;;0540 0571;ARMENIAN SMALL LETTER JA;Ll;0;L;;;;;N;;;0541;;0541 0572;ARMENIAN SMALL LETTER GHAD;Ll;0;L;;;;;N;ARMENIAN SMALL LETTER LAD;;0542;;0542 0573;ARMENIAN SMALL LETTER CHEH;Ll;0;L;;;;;N;;;0543;;0543 0574;ARMENIAN SMALL LETTER MEN;Ll;0;L;;;;;N;;;0544;;0544 0575;ARMENIAN SMALL LETTER YI;Ll;0;L;;;;;N;;;0545;;0545 0576;ARMENIAN SMALL LETTER NOW;Ll;0;L;;;;;N;;;0546;;0546 0577;ARMENIAN SMALL LETTER SHA;Ll;0;L;;;;;N;;;0547;;0547 0578;ARMENIAN SMALL LETTER VO;Ll;0;L;;;;;N;;;0548;;0548 0579;ARMENIAN SMALL LETTER CHA;Ll;0;L;;;;;N;;;0549;;0549 057A;ARMENIAN SMALL LETTER PEH;Ll;0;L;;;;;N;;;054A;;054A 057B;ARMENIAN SMALL LETTER JHEH;Ll;0;L;;;;;N;;;054B;;054B 057C;ARMENIAN SMALL LETTER RA;Ll;0;L;;;;;N;;;054C;;054C 057D;ARMENIAN SMALL LETTER SEH;Ll;0;L;;;;;N;;;054D;;054D 057E;ARMENIAN SMALL LETTER VEW;Ll;0;L;;;;;N;;;054E;;054E 057F;ARMENIAN SMALL LETTER TIWN;Ll;0;L;;;;;N;;;054F;;054F 0580;ARMENIAN SMALL LETTER REH;Ll;0;L;;;;;N;;;0550;;0550 0581;ARMENIAN SMALL LETTER CO;Ll;0;L;;;;;N;;;0551;;0551 0582;ARMENIAN SMALL LETTER YIWN;Ll;0;L;;;;;N;;;0552;;0552 0583;ARMENIAN SMALL LETTER PIWR;Ll;0;L;;;;;N;;;0553;;0553 0584;ARMENIAN SMALL LETTER KEH;Ll;0;L;;;;;N;;;0554;;0554 0585;ARMENIAN SMALL LETTER OH;Ll;0;L;;;;;N;;;0555;;0555 0586;ARMENIAN SMALL LETTER FEH;Ll;0;L;;;;;N;;;0556;;0556 0587;ARMENIAN SMALL LIGATURE ECH YIWN;Ll;0;L; 0565 0582;;;;N;;;;; 0589;ARMENIAN FULL STOP;Po;0;L;;;;;N;ARMENIAN PERIOD;;;; 058A;ARMENIAN HYPHEN;Pd;0;ON;;;;;N;;;;; 0591;HEBREW ACCENT ETNAHTA;Mn;220;NSM;;;;;N;;;;; 0592;HEBREW ACCENT SEGOL;Mn;230;NSM;;;;;N;;;;; 0593;HEBREW ACCENT SHALSHELET;Mn;230;NSM;;;;;N;;;;; 0594;HEBREW ACCENT ZAQEF QATAN;Mn;230;NSM;;;;;N;;;;; 0595;HEBREW ACCENT ZAQEF GADOL;Mn;230;NSM;;;;;N;;;;; 0596;HEBREW ACCENT TIPEHA;Mn;220;NSM;;;;;N;;*;;; 0597;HEBREW ACCENT REVIA;Mn;230;NSM;;;;;N;;;;; 0598;HEBREW ACCENT ZARQA;Mn;230;NSM;;;;;N;;*;;; 0599;HEBREW ACCENT PASHTA;Mn;230;NSM;;;;;N;;;;; 059A;HEBREW ACCENT YETIV;Mn;222;NSM;;;;;N;;;;; 059B;HEBREW ACCENT TEVIR;Mn;220;NSM;;;;;N;;;;; 059C;HEBREW ACCENT GERESH;Mn;230;NSM;;;;;N;;;;; 059D;HEBREW ACCENT GERESH MUQDAM;Mn;230;NSM;;;;;N;;;;; 059E;HEBREW ACCENT GERSHAYIM;Mn;230;NSM;;;;;N;;;;; 059F;HEBREW ACCENT QARNEY PARA;Mn;230;NSM;;;;;N;;;;; 05A0;HEBREW ACCENT TELISHA GEDOLA;Mn;230;NSM;;;;;N;;;;; 05A1;HEBREW ACCENT PAZER;Mn;230;NSM;;;;;N;;;;; 05A3;HEBREW ACCENT MUNAH;Mn;220;NSM;;;;;N;;;;; 05A4;HEBREW ACCENT MAHAPAKH;Mn;220;NSM;;;;;N;;;;; 05A5;HEBREW ACCENT MERKHA;Mn;220;NSM;;;;;N;;*;;; 05A6;HEBREW ACCENT MERKHA KEFULA;Mn;220;NSM;;;;;N;;;;; 05A7;HEBREW ACCENT DARGA;Mn;220;NSM;;;;;N;;;;; 05A8;HEBREW ACCENT QADMA;Mn;230;NSM;;;;;N;;*;;; 05A9;HEBREW ACCENT TELISHA QETANA;Mn;230;NSM;;;;;N;;;;; 05AA;HEBREW ACCENT YERAH BEN YOMO;Mn;220;NSM;;;;;N;;*;;; 05AB;HEBREW ACCENT OLE;Mn;230;NSM;;;;;N;;;;; 05AC;HEBREW ACCENT ILUY;Mn;230;NSM;;;;;N;;;;; 05AD;HEBREW ACCENT DEHI;Mn;222;NSM;;;;;N;;;;; 05AE;HEBREW ACCENT ZINOR;Mn;228;NSM;;;;;N;;;;; 05AF;HEBREW MARK MASORA CIRCLE;Mn;230;NSM;;;;;N;;;;; 05B0;HEBREW POINT SHEVA;Mn;10;NSM;;;;;N;;;;; 05B1;HEBREW POINT HATAF SEGOL;Mn;11;NSM;;;;;N;;;;; 05B2;HEBREW POINT HATAF PATAH;Mn;12;NSM;;;;;N;;;;; 05B3;HEBREW POINT HATAF QAMATS;Mn;13;NSM;;;;;N;;;;; 05B4;HEBREW POINT HIRIQ;Mn;14;NSM;;;;;N;;;;; 05B5;HEBREW POINT TSERE;Mn;15;NSM;;;;;N;;;;; 05B6;HEBREW POINT SEGOL;Mn;16;NSM;;;;;N;;;;; 05B7;HEBREW POINT PATAH;Mn;17;NSM;;;;;N;;;;; 05B8;HEBREW POINT QAMATS;Mn;18;NSM;;;;;N;;;;; 05B9;HEBREW POINT HOLAM;Mn;19;NSM;;;;;N;;;;; 05BB;HEBREW POINT QUBUTS;Mn;20;NSM;;;;;N;;;;; 05BC;HEBREW POINT DAGESH OR MAPIQ;Mn;21;NSM;;;;;N;HEBREW POINT DAGESH;or shuruq;;; 05BD;HEBREW POINT METEG;Mn;22;NSM;;;;;N;;*;;; 05BE;HEBREW PUNCTUATION MAQAF;Po;0;R;;;;;N;;;;; 05BF;HEBREW POINT RAFE;Mn;23;NSM;;;;;N;;;;; 05C0;HEBREW PUNCTUATION PASEQ;Po;0;R;;;;;N;HEBREW POINT PASEQ;*;;; 05C1;HEBREW POINT SHIN DOT;Mn;24;NSM;;;;;N;;;;; 05C2;HEBREW POINT SIN DOT;Mn;25;NSM;;;;;N;;;;; 05C3;HEBREW PUNCTUATION SOF PASUQ;Po;0;R;;;;;N;;*;;; 05C4;HEBREW MARK UPPER DOT;Mn;230;NSM;;;;;N;;;;; 05D0;HEBREW LETTER ALEF;Lo;0;R;;;;;N;;;;; 05D1;HEBREW LETTER BET;Lo;0;R;;;;;N;;;;; 05D2;HEBREW LETTER GIMEL;Lo;0;R;;;;;N;;;;; 05D3;HEBREW LETTER DALET;Lo;0;R;;;;;N;;;;; 05D4;HEBREW LETTER HE;Lo;0;R;;;;;N;;;;; 05D5;HEBREW LETTER VAV;Lo;0;R;;;;;N;;;;; 05D6;HEBREW LETTER ZAYIN;Lo;0;R;;;;;N;;;;; 05D7;HEBREW LETTER HET;Lo;0;R;;;;;N;;;;; 05D8;HEBREW LETTER TET;Lo;0;R;;;;;N;;;;; 05D9;HEBREW LETTER YOD;Lo;0;R;;;;;N;;;;; 05DA;HEBREW LETTER FINAL KAF;Lo;0;R;;;;;N;;;;; 05DB;HEBREW LETTER KAF;Lo;0;R;;;;;N;;;;; 05DC;HEBREW LETTER LAMED;Lo;0;R;;;;;N;;;;; 05DD;HEBREW LETTER FINAL MEM;Lo;0;R;;;;;N;;;;; 05DE;HEBREW LETTER MEM;Lo;0;R;;;;;N;;;;; 05DF;HEBREW LETTER FINAL NUN;Lo;0;R;;;;;N;;;;; 05E0;HEBREW LETTER NUN;Lo;0;R;;;;;N;;;;; 05E1;HEBREW LETTER SAMEKH;Lo;0;R;;;;;N;;;;; 05E2;HEBREW LETTER AYIN;Lo;0;R;;;;;N;;;;; 05E3;HEBREW LETTER FINAL PE;Lo;0;R;;;;;N;;;;; 05E4;HEBREW LETTER PE;Lo;0;R;;;;;N;;;;; 05E5;HEBREW LETTER FINAL TSADI;Lo;0;R;;;;;N;;;;; 05E6;HEBREW LETTER TSADI;Lo;0;R;;;;;N;;;;; 05E7;HEBREW LETTER QOF;Lo;0;R;;;;;N;;;;; 05E8;HEBREW LETTER RESH;Lo;0;R;;;;;N;;;;; 05E9;HEBREW LETTER SHIN;Lo;0;R;;;;;N;;;;; 05EA;HEBREW LETTER TAV;Lo;0;R;;;;;N;;;;; 05F0;HEBREW LIGATURE YIDDISH DOUBLE VAV;Lo;0;R;;;;;N;HEBREW LETTER DOUBLE VAV;;;; 05F1;HEBREW LIGATURE YIDDISH VAV YOD;Lo;0;R;;;;;N;HEBREW LETTER VAV YOD;;;; 05F2;HEBREW LIGATURE YIDDISH DOUBLE YOD;Lo;0;R;;;;;N;HEBREW LETTER DOUBLE YOD;;;; 05F3;HEBREW PUNCTUATION GERESH;Po;0;R;;;;;N;;;;; 05F4;HEBREW PUNCTUATION GERSHAYIM;Po;0;R;;;;;N;;;;; 060C;ARABIC COMMA;Po;0;CS;;;;;N;;;;; 061B;ARABIC SEMICOLON;Po;0;AL;;;;;N;;;;; 061F;ARABIC QUESTION MARK;Po;0;AL;;;;;N;;;;; 0621;ARABIC LETTER HAMZA;Lo;0;AL;;;;;N;ARABIC LETTER HAMZAH;;;; 0622;ARABIC LETTER ALEF WITH MADDA ABOVE;Lo;0;AL;0627 0653;;;;N;ARABIC LETTER MADDAH ON ALEF;;;; 0623;ARABIC LETTER ALEF WITH HAMZA ABOVE;Lo;0;AL;0627 0654;;;;N;ARABIC LETTER HAMZAH ON ALEF;;;; 0624;ARABIC LETTER WAW WITH HAMZA ABOVE;Lo;0;AL;0648 0654;;;;N;ARABIC LETTER HAMZAH ON WAW;;;; 0625;ARABIC LETTER ALEF WITH HAMZA BELOW;Lo;0;AL;0627 0655;;;;N;ARABIC LETTER HAMZAH UNDER ALEF;;;; 0626;ARABIC LETTER YEH WITH HAMZA ABOVE;Lo;0;AL;064A 0654;;;;N;ARABIC LETTER HAMZAH ON YA;;;; 0627;ARABIC LETTER ALEF;Lo;0;AL;;;;;N;;;;; 0628;ARABIC LETTER BEH;Lo;0;AL;;;;;N;ARABIC LETTER BAA;;;; 0629;ARABIC LETTER TEH MARBUTA;Lo;0;AL;;;;;N;ARABIC LETTER TAA MARBUTAH;;;; 062A;ARABIC LETTER TEH;Lo;0;AL;;;;;N;ARABIC LETTER TAA;;;; 062B;ARABIC LETTER THEH;Lo;0;AL;;;;;N;ARABIC LETTER THAA;;;; 062C;ARABIC LETTER JEEM;Lo;0;AL;;;;;N;;;;; 062D;ARABIC LETTER HAH;Lo;0;AL;;;;;N;ARABIC LETTER HAA;;;; 062E;ARABIC LETTER KHAH;Lo;0;AL;;;;;N;ARABIC LETTER KHAA;;;; 062F;ARABIC LETTER DAL;Lo;0;AL;;;;;N;;;;; 0630;ARABIC LETTER THAL;Lo;0;AL;;;;;N;;;;; 0631;ARABIC LETTER REH;Lo;0;AL;;;;;N;ARABIC LETTER RA;;;; 0632;ARABIC LETTER ZAIN;Lo;0;AL;;;;;N;;;;; 0633;ARABIC LETTER SEEN;Lo;0;AL;;;;;N;;;;; 0634;ARABIC LETTER SHEEN;Lo;0;AL;;;;;N;;;;; 0635;ARABIC LETTER SAD;Lo;0;AL;;;;;N;;;;; 0636;ARABIC LETTER DAD;Lo;0;AL;;;;;N;;;;; 0637;ARABIC LETTER TAH;Lo;0;AL;;;;;N;;;;; 0638;ARABIC LETTER ZAH;Lo;0;AL;;;;;N;ARABIC LETTER DHAH;;;; 0639;ARABIC LETTER AIN;Lo;0;AL;;;;;N;;;;; 063A;ARABIC LETTER GHAIN;Lo;0;AL;;;;;N;;;;; 0640;ARABIC TATWEEL;Lm;0;AL;;;;;N;;;;; 0641;ARABIC LETTER FEH;Lo;0;AL;;;;;N;ARABIC LETTER FA;;;; 0642;ARABIC LETTER QAF;Lo;0;AL;;;;;N;;;;; 0643;ARABIC LETTER KAF;Lo;0;AL;;;;;N;ARABIC LETTER CAF;;;; 0644;ARABIC LETTER LAM;Lo;0;AL;;;;;N;;;;; 0645;ARABIC LETTER MEEM;Lo;0;AL;;;;;N;;;;; 0646;ARABIC LETTER NOON;Lo;0;AL;;;;;N;;;;; 0647;ARABIC LETTER HEH;Lo;0;AL;;;;;N;ARABIC LETTER HA;;;; 0648;ARABIC LETTER WAW;Lo;0;AL;;;;;N;;;;; 0649;ARABIC LETTER ALEF MAKSURA;Lo;0;AL;;;;;N;ARABIC LETTER ALEF MAQSURAH;;;; 064A;ARABIC LETTER YEH;Lo;0;AL;;;;;N;ARABIC LETTER YA;;;; 064B;ARABIC FATHATAN;Mn;27;NSM;;;;;N;;;;; 064C;ARABIC DAMMATAN;Mn;28;NSM;;;;;N;;;;; 064D;ARABIC KASRATAN;Mn;29;NSM;;;;;N;;;;; 064E;ARABIC FATHA;Mn;30;NSM;;;;;N;ARABIC FATHAH;;;; 064F;ARABIC DAMMA;Mn;31;NSM;;;;;N;ARABIC DAMMAH;;;; 0650;ARABIC KASRA;Mn;32;NSM;;;;;N;ARABIC KASRAH;;;; 0651;ARABIC SHADDA;Mn;33;NSM;;;;;N;ARABIC SHADDAH;;;; 0652;ARABIC SUKUN;Mn;34;NSM;;;;;N;;;;; 0653;ARABIC MADDAH ABOVE;Mn;230;NSM;;;;;N;;;;; 0654;ARABIC HAMZA ABOVE;Mn;230;NSM;;;;;N;;;;; 0655;ARABIC HAMZA BELOW;Mn;220;NSM;;;;;N;;;;; 0660;ARABIC-INDIC DIGIT ZERO;Nd;0;AN;;0;0;0;N;;;;; 0661;ARABIC-INDIC DIGIT ONE;Nd;0;AN;;1;1;1;N;;;;; 0662;ARABIC-INDIC DIGIT TWO;Nd;0;AN;;2;2;2;N;;;;; 0663;ARABIC-INDIC DIGIT THREE;Nd;0;AN;;3;3;3;N;;;;; 0664;ARABIC-INDIC DIGIT FOUR;Nd;0;AN;;4;4;4;N;;;;; 0665;ARABIC-INDIC DIGIT FIVE;Nd;0;AN;;5;5;5;N;;;;; 0666;ARABIC-INDIC DIGIT SIX;Nd;0;AN;;6;6;6;N;;;;; 0667;ARABIC-INDIC DIGIT SEVEN;Nd;0;AN;;7;7;7;N;;;;; 0668;ARABIC-INDIC DIGIT EIGHT;Nd;0;AN;;8;8;8;N;;;;; 0669;ARABIC-INDIC DIGIT NINE;Nd;0;AN;;9;9;9;N;;;;; 066A;ARABIC PERCENT SIGN;Po;0;ET;;;;;N;;;;; 066B;ARABIC DECIMAL SEPARATOR;Po;0;AN;;;;;N;;;;; 066C;ARABIC THOUSANDS SEPARATOR;Po;0;AN;;;;;N;;;;; 066D;ARABIC FIVE POINTED STAR;Po;0;AL;;;;;N;;;;; 066E;ARABIC LETTER DOTLESS BEH;Lo;0;AL;;;;;N;;;;; 066F;ARABIC LETTER DOTLESS QAF;Lo;0;AL;;;;;N;;;;; 0670;ARABIC LETTER SUPERSCRIPT ALEF;Mn;35;NSM;;;;;N;ARABIC ALEF ABOVE;;;; 0671;ARABIC LETTER ALEF WASLA;Lo;0;AL;;;;;N;ARABIC LETTER HAMZAT WASL ON ALEF;;;; 0672;ARABIC LETTER ALEF WITH WAVY HAMZA ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER WAVY HAMZAH ON ALEF;;;; 0673;ARABIC LETTER ALEF WITH WAVY HAMZA BELOW;Lo;0;AL;;;;;N;ARABIC LETTER WAVY HAMZAH UNDER ALEF;;;; 0674;ARABIC LETTER HIGH HAMZA;Lo;0;AL;;;;;N;ARABIC LETTER HIGH HAMZAH;;;; 0675;ARABIC LETTER HIGH HAMZA ALEF;Lo;0;AL; 0627 0674;;;;N;ARABIC LETTER HIGH HAMZAH ALEF;;;; 0676;ARABIC LETTER HIGH HAMZA WAW;Lo;0;AL; 0648 0674;;;;N;ARABIC LETTER HIGH HAMZAH WAW;;;; 0677;ARABIC LETTER U WITH HAMZA ABOVE;Lo;0;AL; 06C7 0674;;;;N;ARABIC LETTER HIGH HAMZAH WAW WITH DAMMAH;;;; 0678;ARABIC LETTER HIGH HAMZA YEH;Lo;0;AL; 064A 0674;;;;N;ARABIC LETTER HIGH HAMZAH YA;;;; 0679;ARABIC LETTER TTEH;Lo;0;AL;;;;;N;ARABIC LETTER TAA WITH SMALL TAH;;;; 067A;ARABIC LETTER TTEHEH;Lo;0;AL;;;;;N;ARABIC LETTER TAA WITH TWO DOTS VERTICAL ABOVE;;;; 067B;ARABIC LETTER BEEH;Lo;0;AL;;;;;N;ARABIC LETTER BAA WITH TWO DOTS VERTICAL BELOW;;;; 067C;ARABIC LETTER TEH WITH RING;Lo;0;AL;;;;;N;ARABIC LETTER TAA WITH RING;;;; 067D;ARABIC LETTER TEH WITH THREE DOTS ABOVE DOWNWARDS;Lo;0;AL;;;;;N;ARABIC LETTER TAA WITH THREE DOTS ABOVE DOWNWARD;;;; 067E;ARABIC LETTER PEH;Lo;0;AL;;;;;N;ARABIC LETTER TAA WITH THREE DOTS BELOW;;;; 067F;ARABIC LETTER TEHEH;Lo;0;AL;;;;;N;ARABIC LETTER TAA WITH FOUR DOTS ABOVE;;;; 0680;ARABIC LETTER BEHEH;Lo;0;AL;;;;;N;ARABIC LETTER BAA WITH FOUR DOTS BELOW;;;; 0681;ARABIC LETTER HAH WITH HAMZA ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER HAMZAH ON HAA;;;; 0682;ARABIC LETTER HAH WITH TWO DOTS VERTICAL ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER HAA WITH TWO DOTS VERTICAL ABOVE;;;; 0683;ARABIC LETTER NYEH;Lo;0;AL;;;;;N;ARABIC LETTER HAA WITH MIDDLE TWO DOTS;;;; 0684;ARABIC LETTER DYEH;Lo;0;AL;;;;;N;ARABIC LETTER HAA WITH MIDDLE TWO DOTS VERTICAL;;;; 0685;ARABIC LETTER HAH WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER HAA WITH THREE DOTS ABOVE;;;; 0686;ARABIC LETTER TCHEH;Lo;0;AL;;;;;N;ARABIC LETTER HAA WITH MIDDLE THREE DOTS DOWNWARD;;;; 0687;ARABIC LETTER TCHEHEH;Lo;0;AL;;;;;N;ARABIC LETTER HAA WITH MIDDLE FOUR DOTS;;;; 0688;ARABIC LETTER DDAL;Lo;0;AL;;;;;N;ARABIC LETTER DAL WITH SMALL TAH;;;; 0689;ARABIC LETTER DAL WITH RING;Lo;0;AL;;;;;N;;;;; 068A;ARABIC LETTER DAL WITH DOT BELOW;Lo;0;AL;;;;;N;;;;; 068B;ARABIC LETTER DAL WITH DOT BELOW AND SMALL TAH;Lo;0;AL;;;;;N;;;;; 068C;ARABIC LETTER DAHAL;Lo;0;AL;;;;;N;ARABIC LETTER DAL WITH TWO DOTS ABOVE;;;; 068D;ARABIC LETTER DDAHAL;Lo;0;AL;;;;;N;ARABIC LETTER DAL WITH TWO DOTS BELOW;;;; 068E;ARABIC LETTER DUL;Lo;0;AL;;;;;N;ARABIC LETTER DAL WITH THREE DOTS ABOVE;;;; 068F;ARABIC LETTER DAL WITH THREE DOTS ABOVE DOWNWARDS;Lo;0;AL;;;;;N;ARABIC LETTER DAL WITH THREE DOTS ABOVE DOWNWARD;;;; 0690;ARABIC LETTER DAL WITH FOUR DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 0691;ARABIC LETTER RREH;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH SMALL TAH;;;; 0692;ARABIC LETTER REH WITH SMALL V;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH SMALL V;;;; 0693;ARABIC LETTER REH WITH RING;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH RING;;;; 0694;ARABIC LETTER REH WITH DOT BELOW;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH DOT BELOW;;;; 0695;ARABIC LETTER REH WITH SMALL V BELOW;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH SMALL V BELOW;;;; 0696;ARABIC LETTER REH WITH DOT BELOW AND DOT ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH DOT BELOW AND DOT ABOVE;;;; 0697;ARABIC LETTER REH WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH TWO DOTS ABOVE;;;; 0698;ARABIC LETTER JEH;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH THREE DOTS ABOVE;;;; 0699;ARABIC LETTER REH WITH FOUR DOTS ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH FOUR DOTS ABOVE;;;; 069A;ARABIC LETTER SEEN WITH DOT BELOW AND DOT ABOVE;Lo;0;AL;;;;;N;;;;; 069B;ARABIC LETTER SEEN WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;;;;; 069C;ARABIC LETTER SEEN WITH THREE DOTS BELOW AND THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 069D;ARABIC LETTER SAD WITH TWO DOTS BELOW;Lo;0;AL;;;;;N;;;;; 069E;ARABIC LETTER SAD WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 069F;ARABIC LETTER TAH WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 06A0;ARABIC LETTER AIN WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 06A1;ARABIC LETTER DOTLESS FEH;Lo;0;AL;;;;;N;ARABIC LETTER DOTLESS FA;;;; 06A2;ARABIC LETTER FEH WITH DOT MOVED BELOW;Lo;0;AL;;;;;N;ARABIC LETTER FA WITH DOT MOVED BELOW;;;; 06A3;ARABIC LETTER FEH WITH DOT BELOW;Lo;0;AL;;;;;N;ARABIC LETTER FA WITH DOT BELOW;;;; 06A4;ARABIC LETTER VEH;Lo;0;AL;;;;;N;ARABIC LETTER FA WITH THREE DOTS ABOVE;;;; 06A5;ARABIC LETTER FEH WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;ARABIC LETTER FA WITH THREE DOTS BELOW;;;; 06A6;ARABIC LETTER PEHEH;Lo;0;AL;;;;;N;ARABIC LETTER FA WITH FOUR DOTS ABOVE;;;; 06A7;ARABIC LETTER QAF WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;; 06A8;ARABIC LETTER QAF WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 06A9;ARABIC LETTER KEHEH;Lo;0;AL;;;;;N;ARABIC LETTER OPEN CAF;;;; 06AA;ARABIC LETTER SWASH KAF;Lo;0;AL;;;;;N;ARABIC LETTER SWASH CAF;;;; 06AB;ARABIC LETTER KAF WITH RING;Lo;0;AL;;;;;N;ARABIC LETTER CAF WITH RING;;;; 06AC;ARABIC LETTER KAF WITH DOT ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER CAF WITH DOT ABOVE;;;; 06AD;ARABIC LETTER NG;Lo;0;AL;;;;;N;ARABIC LETTER CAF WITH THREE DOTS ABOVE;;;; 06AE;ARABIC LETTER KAF WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;ARABIC LETTER CAF WITH THREE DOTS BELOW;;;; 06AF;ARABIC LETTER GAF;Lo;0;AL;;;;;N;;*;;; 06B0;ARABIC LETTER GAF WITH RING;Lo;0;AL;;;;;N;;;;; 06B1;ARABIC LETTER NGOEH;Lo;0;AL;;;;;N;ARABIC LETTER GAF WITH TWO DOTS ABOVE;;;; 06B2;ARABIC LETTER GAF WITH TWO DOTS BELOW;Lo;0;AL;;;;;N;;;;; 06B3;ARABIC LETTER GUEH;Lo;0;AL;;;;;N;ARABIC LETTER GAF WITH TWO DOTS VERTICAL BELOW;;;; 06B4;ARABIC LETTER GAF WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 06B5;ARABIC LETTER LAM WITH SMALL V;Lo;0;AL;;;;;N;;;;; 06B6;ARABIC LETTER LAM WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;; 06B7;ARABIC LETTER LAM WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 06B8;ARABIC LETTER LAM WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;;;;; 06B9;ARABIC LETTER NOON WITH DOT BELOW;Lo;0;AL;;;;;N;;;;; 06BA;ARABIC LETTER NOON GHUNNA;Lo;0;AL;;;;;N;ARABIC LETTER DOTLESS NOON;;;; 06BB;ARABIC LETTER RNOON;Lo;0;AL;;;;;N;ARABIC LETTER DOTLESS NOON WITH SMALL TAH;;;; 06BC;ARABIC LETTER NOON WITH RING;Lo;0;AL;;;;;N;;;;; 06BD;ARABIC LETTER NOON WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 06BE;ARABIC LETTER HEH DOACHASHMEE;Lo;0;AL;;;;;N;ARABIC LETTER KNOTTED HA;;;; 06BF;ARABIC LETTER TCHEH WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;; 06C0;ARABIC LETTER HEH WITH YEH ABOVE;Lo;0;AL;06D5 0654;;;;N;ARABIC LETTER HAMZAH ON HA;;;; 06C1;ARABIC LETTER HEH GOAL;Lo;0;AL;;;;;N;ARABIC LETTER HA GOAL;;;; 06C2;ARABIC LETTER HEH GOAL WITH HAMZA ABOVE;Lo;0;AL;06C1 0654;;;;N;ARABIC LETTER HAMZAH ON HA GOAL;;;; 06C3;ARABIC LETTER TEH MARBUTA GOAL;Lo;0;AL;;;;;N;ARABIC LETTER TAA MARBUTAH GOAL;;;; 06C4;ARABIC LETTER WAW WITH RING;Lo;0;AL;;;;;N;;;;; 06C5;ARABIC LETTER KIRGHIZ OE;Lo;0;AL;;;;;N;ARABIC LETTER WAW WITH BAR;;;; 06C6;ARABIC LETTER OE;Lo;0;AL;;;;;N;ARABIC LETTER WAW WITH SMALL V;;;; 06C7;ARABIC LETTER U;Lo;0;AL;;;;;N;ARABIC LETTER WAW WITH DAMMAH;;;; 06C8;ARABIC LETTER YU;Lo;0;AL;;;;;N;ARABIC LETTER WAW WITH ALEF ABOVE;;;; 06C9;ARABIC LETTER KIRGHIZ YU;Lo;0;AL;;;;;N;ARABIC LETTER WAW WITH INVERTED SMALL V;;;; 06CA;ARABIC LETTER WAW WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 06CB;ARABIC LETTER VE;Lo;0;AL;;;;;N;ARABIC LETTER WAW WITH THREE DOTS ABOVE;;;; 06CC;ARABIC LETTER FARSI YEH;Lo;0;AL;;;;;N;ARABIC LETTER DOTLESS YA;;;; 06CD;ARABIC LETTER YEH WITH TAIL;Lo;0;AL;;;;;N;ARABIC LETTER YA WITH TAIL;;;; 06CE;ARABIC LETTER YEH WITH SMALL V;Lo;0;AL;;;;;N;ARABIC LETTER YA WITH SMALL V;;;; 06CF;ARABIC LETTER WAW WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;; 06D0;ARABIC LETTER E;Lo;0;AL;;;;;N;ARABIC LETTER YA WITH TWO DOTS VERTICAL BELOW;*;;; 06D1;ARABIC LETTER YEH WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;ARABIC LETTER YA WITH THREE DOTS BELOW;;;; 06D2;ARABIC LETTER YEH BARREE;Lo;0;AL;;;;;N;ARABIC LETTER YA BARREE;;;; 06D3;ARABIC LETTER YEH BARREE WITH HAMZA ABOVE;Lo;0;AL;06D2 0654;;;;N;ARABIC LETTER HAMZAH ON YA BARREE;;;; 06D4;ARABIC FULL STOP;Po;0;AL;;;;;N;ARABIC PERIOD;;;; 06D5;ARABIC LETTER AE;Lo;0;AL;;;;;N;;;;; 06D6;ARABIC SMALL HIGH LIGATURE SAD WITH LAM WITH ALEF MAKSURA;Mn;230;NSM;;;;;N;;;;; 06D7;ARABIC SMALL HIGH LIGATURE QAF WITH LAM WITH ALEF MAKSURA;Mn;230;NSM;;;;;N;;;;; 06D8;ARABIC SMALL HIGH MEEM INITIAL FORM;Mn;230;NSM;;;;;N;;;;; 06D9;ARABIC SMALL HIGH LAM ALEF;Mn;230;NSM;;;;;N;;;;; 06DA;ARABIC SMALL HIGH JEEM;Mn;230;NSM;;;;;N;;;;; 06DB;ARABIC SMALL HIGH THREE DOTS;Mn;230;NSM;;;;;N;;;;; 06DC;ARABIC SMALL HIGH SEEN;Mn;230;NSM;;;;;N;;;;; 06DD;ARABIC END OF AYAH;Cf;0;AL;;;;;N;;;;; 06DE;ARABIC START OF RUB EL HIZB;Me;0;NSM;;;;;N;;;;; 06DF;ARABIC SMALL HIGH ROUNDED ZERO;Mn;230;NSM;;;;;N;;;;; 06E0;ARABIC SMALL HIGH UPRIGHT RECTANGULAR ZERO;Mn;230;NSM;;;;;N;;;;; 06E1;ARABIC SMALL HIGH DOTLESS HEAD OF KHAH;Mn;230;NSM;;;;;N;;;;; 06E2;ARABIC SMALL HIGH MEEM ISOLATED FORM;Mn;230;NSM;;;;;N;;;;; 06E3;ARABIC SMALL LOW SEEN;Mn;220;NSM;;;;;N;;;;; 06E4;ARABIC SMALL HIGH MADDA;Mn;230;NSM;;;;;N;;;;; 06E5;ARABIC SMALL WAW;Lm;0;AL;;;;;N;;;;; 06E6;ARABIC SMALL YEH;Lm;0;AL;;;;;N;;;;; 06E7;ARABIC SMALL HIGH YEH;Mn;230;NSM;;;;;N;;;;; 06E8;ARABIC SMALL HIGH NOON;Mn;230;NSM;;;;;N;;;;; 06E9;ARABIC PLACE OF SAJDAH;So;0;ON;;;;;N;;;;; 06EA;ARABIC EMPTY CENTRE LOW STOP;Mn;220;NSM;;;;;N;;;;; 06EB;ARABIC EMPTY CENTRE HIGH STOP;Mn;230;NSM;;;;;N;;;;; 06EC;ARABIC ROUNDED HIGH STOP WITH FILLED CENTRE;Mn;230;NSM;;;;;N;;;;; 06ED;ARABIC SMALL LOW MEEM;Mn;220;NSM;;;;;N;;;;; 06F0;EXTENDED ARABIC-INDIC DIGIT ZERO;Nd;0;EN;;0;0;0;N;EASTERN ARABIC-INDIC DIGIT ZERO;;;; 06F1;EXTENDED ARABIC-INDIC DIGIT ONE;Nd;0;EN;;1;1;1;N;EASTERN ARABIC-INDIC DIGIT ONE;;;; 06F2;EXTENDED ARABIC-INDIC DIGIT TWO;Nd;0;EN;;2;2;2;N;EASTERN ARABIC-INDIC DIGIT TWO;;;; 06F3;EXTENDED ARABIC-INDIC DIGIT THREE;Nd;0;EN;;3;3;3;N;EASTERN ARABIC-INDIC DIGIT THREE;;;; 06F4;EXTENDED ARABIC-INDIC DIGIT FOUR;Nd;0;EN;;4;4;4;N;EASTERN ARABIC-INDIC DIGIT FOUR;;;; 06F5;EXTENDED ARABIC-INDIC DIGIT FIVE;Nd;0;EN;;5;5;5;N;EASTERN ARABIC-INDIC DIGIT FIVE;;;; 06F6;EXTENDED ARABIC-INDIC DIGIT SIX;Nd;0;EN;;6;6;6;N;EASTERN ARABIC-INDIC DIGIT SIX;;;; 06F7;EXTENDED ARABIC-INDIC DIGIT SEVEN;Nd;0;EN;;7;7;7;N;EASTERN ARABIC-INDIC DIGIT SEVEN;;;; 06F8;EXTENDED ARABIC-INDIC DIGIT EIGHT;Nd;0;EN;;8;8;8;N;EASTERN ARABIC-INDIC DIGIT EIGHT;;;; 06F9;EXTENDED ARABIC-INDIC DIGIT NINE;Nd;0;EN;;9;9;9;N;EASTERN ARABIC-INDIC DIGIT NINE;;;; 06FA;ARABIC LETTER SHEEN WITH DOT BELOW;Lo;0;AL;;;;;N;;;;; 06FB;ARABIC LETTER DAD WITH DOT BELOW;Lo;0;AL;;;;;N;;;;; 06FC;ARABIC LETTER GHAIN WITH DOT BELOW;Lo;0;AL;;;;;N;;;;; 06FD;ARABIC SIGN SINDHI AMPERSAND;So;0;AL;;;;;N;;;;; 06FE;ARABIC SIGN SINDHI POSTPOSITION MEN;So;0;AL;;;;;N;;;;; 0700;SYRIAC END OF PARAGRAPH;Po;0;AL;;;;;N;;;;; 0701;SYRIAC SUPRALINEAR FULL STOP;Po;0;AL;;;;;N;;;;; 0702;SYRIAC SUBLINEAR FULL STOP;Po;0;AL;;;;;N;;;;; 0703;SYRIAC SUPRALINEAR COLON;Po;0;AL;;;;;N;;;;; 0704;SYRIAC SUBLINEAR COLON;Po;0;AL;;;;;N;;;;; 0705;SYRIAC HORIZONTAL COLON;Po;0;AL;;;;;N;;;;; 0706;SYRIAC COLON SKEWED LEFT;Po;0;AL;;;;;N;;;;; 0707;SYRIAC COLON SKEWED RIGHT;Po;0;AL;;;;;N;;;;; 0708;SYRIAC SUPRALINEAR COLON SKEWED LEFT;Po;0;AL;;;;;N;;;;; 0709;SYRIAC SUBLINEAR COLON SKEWED RIGHT;Po;0;AL;;;;;N;;;;; 070A;SYRIAC CONTRACTION;Po;0;AL;;;;;N;;;;; 070B;SYRIAC HARKLEAN OBELUS;Po;0;AL;;;;;N;;;;; 070C;SYRIAC HARKLEAN METOBELUS;Po;0;AL;;;;;N;;;;; 070D;SYRIAC HARKLEAN ASTERISCUS;Po;0;AL;;;;;N;;;;; 070F;SYRIAC ABBREVIATION MARK;Cf;0;BN;;;;;N;;;;; 0710;SYRIAC LETTER ALAPH;Lo;0;AL;;;;;N;;;;; 0711;SYRIAC LETTER SUPERSCRIPT ALAPH;Mn;36;NSM;;;;;N;;;;; 0712;SYRIAC LETTER BETH;Lo;0;AL;;;;;N;;;;; 0713;SYRIAC LETTER GAMAL;Lo;0;AL;;;;;N;;;;; 0714;SYRIAC LETTER GAMAL GARSHUNI;Lo;0;AL;;;;;N;;;;; 0715;SYRIAC LETTER DALATH;Lo;0;AL;;;;;N;;;;; 0716;SYRIAC LETTER DOTLESS DALATH RISH;Lo;0;AL;;;;;N;;;;; 0717;SYRIAC LETTER HE;Lo;0;AL;;;;;N;;;;; 0718;SYRIAC LETTER WAW;Lo;0;AL;;;;;N;;;;; 0719;SYRIAC LETTER ZAIN;Lo;0;AL;;;;;N;;;;; 071A;SYRIAC LETTER HETH;Lo;0;AL;;;;;N;;;;; 071B;SYRIAC LETTER TETH;Lo;0;AL;;;;;N;;;;; 071C;SYRIAC LETTER TETH GARSHUNI;Lo;0;AL;;;;;N;;;;; 071D;SYRIAC LETTER YUDH;Lo;0;AL;;;;;N;;;;; 071E;SYRIAC LETTER YUDH HE;Lo;0;AL;;;;;N;;;;; 071F;SYRIAC LETTER KAPH;Lo;0;AL;;;;;N;;;;; 0720;SYRIAC LETTER LAMADH;Lo;0;AL;;;;;N;;;;; 0721;SYRIAC LETTER MIM;Lo;0;AL;;;;;N;;;;; 0722;SYRIAC LETTER NUN;Lo;0;AL;;;;;N;;;;; 0723;SYRIAC LETTER SEMKATH;Lo;0;AL;;;;;N;;;;; 0724;SYRIAC LETTER FINAL SEMKATH;Lo;0;AL;;;;;N;;;;; 0725;SYRIAC LETTER E;Lo;0;AL;;;;;N;;;;; 0726;SYRIAC LETTER PE;Lo;0;AL;;;;;N;;;;; 0727;SYRIAC LETTER REVERSED PE;Lo;0;AL;;;;;N;;;;; 0728;SYRIAC LETTER SADHE;Lo;0;AL;;;;;N;;;;; 0729;SYRIAC LETTER QAPH;Lo;0;AL;;;;;N;;;;; 072A;SYRIAC LETTER RISH;Lo;0;AL;;;;;N;;;;; 072B;SYRIAC LETTER SHIN;Lo;0;AL;;;;;N;;;;; 072C;SYRIAC LETTER TAW;Lo;0;AL;;;;;N;;;;; 0730;SYRIAC PTHAHA ABOVE;Mn;230;NSM;;;;;N;;;;; 0731;SYRIAC PTHAHA BELOW;Mn;220;NSM;;;;;N;;;;; 0732;SYRIAC PTHAHA DOTTED;Mn;230;NSM;;;;;N;;;;; 0733;SYRIAC ZQAPHA ABOVE;Mn;230;NSM;;;;;N;;;;; 0734;SYRIAC ZQAPHA BELOW;Mn;220;NSM;;;;;N;;;;; 0735;SYRIAC ZQAPHA DOTTED;Mn;230;NSM;;;;;N;;;;; 0736;SYRIAC RBASA ABOVE;Mn;230;NSM;;;;;N;;;;; 0737;SYRIAC RBASA BELOW;Mn;220;NSM;;;;;N;;;;; 0738;SYRIAC DOTTED ZLAMA HORIZONTAL;Mn;220;NSM;;;;;N;;;;; 0739;SYRIAC DOTTED ZLAMA ANGULAR;Mn;220;NSM;;;;;N;;;;; 073A;SYRIAC HBASA ABOVE;Mn;230;NSM;;;;;N;;;;; 073B;SYRIAC HBASA BELOW;Mn;220;NSM;;;;;N;;;;; 073C;SYRIAC HBASA-ESASA DOTTED;Mn;220;NSM;;;;;N;;;;; 073D;SYRIAC ESASA ABOVE;Mn;230;NSM;;;;;N;;;;; 073E;SYRIAC ESASA BELOW;Mn;220;NSM;;;;;N;;;;; 073F;SYRIAC RWAHA;Mn;230;NSM;;;;;N;;;;; 0740;SYRIAC FEMININE DOT;Mn;230;NSM;;;;;N;;;;; 0741;SYRIAC QUSHSHAYA;Mn;230;NSM;;;;;N;;;;; 0742;SYRIAC RUKKAKHA;Mn;220;NSM;;;;;N;;;;; 0743;SYRIAC TWO VERTICAL DOTS ABOVE;Mn;230;NSM;;;;;N;;;;; 0744;SYRIAC TWO VERTICAL DOTS BELOW;Mn;220;NSM;;;;;N;;;;; 0745;SYRIAC THREE DOTS ABOVE;Mn;230;NSM;;;;;N;;;;; 0746;SYRIAC THREE DOTS BELOW;Mn;220;NSM;;;;;N;;;;; 0747;SYRIAC OBLIQUE LINE ABOVE;Mn;230;NSM;;;;;N;;;;; 0748;SYRIAC OBLIQUE LINE BELOW;Mn;220;NSM;;;;;N;;;;; 0749;SYRIAC MUSIC;Mn;230;NSM;;;;;N;;;;; 074A;SYRIAC BARREKH;Mn;230;NSM;;;;;N;;;;; 0780;THAANA LETTER HAA;Lo;0;AL;;;;;N;;;;; 0781;THAANA LETTER SHAVIYANI;Lo;0;AL;;;;;N;;;;; 0782;THAANA LETTER NOONU;Lo;0;AL;;;;;N;;;;; 0783;THAANA LETTER RAA;Lo;0;AL;;;;;N;;;;; 0784;THAANA LETTER BAA;Lo;0;AL;;;;;N;;;;; 0785;THAANA LETTER LHAVIYANI;Lo;0;AL;;;;;N;;;;; 0786;THAANA LETTER KAAFU;Lo;0;AL;;;;;N;;;;; 0787;THAANA LETTER ALIFU;Lo;0;AL;;;;;N;;;;; 0788;THAANA LETTER VAAVU;Lo;0;AL;;;;;N;;;;; 0789;THAANA LETTER MEEMU;Lo;0;AL;;;;;N;;;;; 078A;THAANA LETTER FAAFU;Lo;0;AL;;;;;N;;;;; 078B;THAANA LETTER DHAALU;Lo;0;AL;;;;;N;;;;; 078C;THAANA LETTER THAA;Lo;0;AL;;;;;N;;;;; 078D;THAANA LETTER LAAMU;Lo;0;AL;;;;;N;;;;; 078E;THAANA LETTER GAAFU;Lo;0;AL;;;;;N;;;;; 078F;THAANA LETTER GNAVIYANI;Lo;0;AL;;;;;N;;;;; 0790;THAANA LETTER SEENU;Lo;0;AL;;;;;N;;;;; 0791;THAANA LETTER DAVIYANI;Lo;0;AL;;;;;N;;;;; 0792;THAANA LETTER ZAVIYANI;Lo;0;AL;;;;;N;;;;; 0793;THAANA LETTER TAVIYANI;Lo;0;AL;;;;;N;;;;; 0794;THAANA LETTER YAA;Lo;0;AL;;;;;N;;;;; 0795;THAANA LETTER PAVIYANI;Lo;0;AL;;;;;N;;;;; 0796;THAANA LETTER JAVIYANI;Lo;0;AL;;;;;N;;;;; 0797;THAANA LETTER CHAVIYANI;Lo;0;AL;;;;;N;;;;; 0798;THAANA LETTER TTAA;Lo;0;AL;;;;;N;;;;; 0799;THAANA LETTER HHAA;Lo;0;AL;;;;;N;;;;; 079A;THAANA LETTER KHAA;Lo;0;AL;;;;;N;;;;; 079B;THAANA LETTER THAALU;Lo;0;AL;;;;;N;;;;; 079C;THAANA LETTER ZAA;Lo;0;AL;;;;;N;;;;; 079D;THAANA LETTER SHEENU;Lo;0;AL;;;;;N;;;;; 079E;THAANA LETTER SAADHU;Lo;0;AL;;;;;N;;;;; 079F;THAANA LETTER DAADHU;Lo;0;AL;;;;;N;;;;; 07A0;THAANA LETTER TO;Lo;0;AL;;;;;N;;;;; 07A1;THAANA LETTER ZO;Lo;0;AL;;;;;N;;;;; 07A2;THAANA LETTER AINU;Lo;0;AL;;;;;N;;;;; 07A3;THAANA LETTER GHAINU;Lo;0;AL;;;;;N;;;;; 07A4;THAANA LETTER QAAFU;Lo;0;AL;;;;;N;;;;; 07A5;THAANA LETTER WAAVU;Lo;0;AL;;;;;N;;;;; 07A6;THAANA ABAFILI;Mn;0;NSM;;;;;N;;;;; 07A7;THAANA AABAAFILI;Mn;0;NSM;;;;;N;;;;; 07A8;THAANA IBIFILI;Mn;0;NSM;;;;;N;;;;; 07A9;THAANA EEBEEFILI;Mn;0;NSM;;;;;N;;;;; 07AA;THAANA UBUFILI;Mn;0;NSM;;;;;N;;;;; 07AB;THAANA OOBOOFILI;Mn;0;NSM;;;;;N;;;;; 07AC;THAANA EBEFILI;Mn;0;NSM;;;;;N;;;;; 07AD;THAANA EYBEYFILI;Mn;0;NSM;;;;;N;;;;; 07AE;THAANA OBOFILI;Mn;0;NSM;;;;;N;;;;; 07AF;THAANA OABOAFILI;Mn;0;NSM;;;;;N;;;;; 07B0;THAANA SUKUN;Mn;0;NSM;;;;;N;;;;; 07B1;THAANA LETTER NAA;Lo;0;AL;;;;;N;;;;; 0901;DEVANAGARI SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; 0902;DEVANAGARI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; 0903;DEVANAGARI SIGN VISARGA;Mc;0;L;;;;;N;;;;; 0905;DEVANAGARI LETTER A;Lo;0;L;;;;;N;;;;; 0906;DEVANAGARI LETTER AA;Lo;0;L;;;;;N;;;;; 0907;DEVANAGARI LETTER I;Lo;0;L;;;;;N;;;;; 0908;DEVANAGARI LETTER II;Lo;0;L;;;;;N;;;;; 0909;DEVANAGARI LETTER U;Lo;0;L;;;;;N;;;;; 090A;DEVANAGARI LETTER UU;Lo;0;L;;;;;N;;;;; 090B;DEVANAGARI LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; 090C;DEVANAGARI LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; 090D;DEVANAGARI LETTER CANDRA E;Lo;0;L;;;;;N;;;;; 090E;DEVANAGARI LETTER SHORT E;Lo;0;L;;;;;N;;;;; 090F;DEVANAGARI LETTER E;Lo;0;L;;;;;N;;;;; 0910;DEVANAGARI LETTER AI;Lo;0;L;;;;;N;;;;; 0911;DEVANAGARI LETTER CANDRA O;Lo;0;L;;;;;N;;;;; 0912;DEVANAGARI LETTER SHORT O;Lo;0;L;;;;;N;;;;; 0913;DEVANAGARI LETTER O;Lo;0;L;;;;;N;;;;; 0914;DEVANAGARI LETTER AU;Lo;0;L;;;;;N;;;;; 0915;DEVANAGARI LETTER KA;Lo;0;L;;;;;N;;;;; 0916;DEVANAGARI LETTER KHA;Lo;0;L;;;;;N;;;;; 0917;DEVANAGARI LETTER GA;Lo;0;L;;;;;N;;;;; 0918;DEVANAGARI LETTER GHA;Lo;0;L;;;;;N;;;;; 0919;DEVANAGARI LETTER NGA;Lo;0;L;;;;;N;;;;; 091A;DEVANAGARI LETTER CA;Lo;0;L;;;;;N;;;;; 091B;DEVANAGARI LETTER CHA;Lo;0;L;;;;;N;;;;; 091C;DEVANAGARI LETTER JA;Lo;0;L;;;;;N;;;;; 091D;DEVANAGARI LETTER JHA;Lo;0;L;;;;;N;;;;; 091E;DEVANAGARI LETTER NYA;Lo;0;L;;;;;N;;;;; 091F;DEVANAGARI LETTER TTA;Lo;0;L;;;;;N;;;;; 0920;DEVANAGARI LETTER TTHA;Lo;0;L;;;;;N;;;;; 0921;DEVANAGARI LETTER DDA;Lo;0;L;;;;;N;;;;; 0922;DEVANAGARI LETTER DDHA;Lo;0;L;;;;;N;;;;; 0923;DEVANAGARI LETTER NNA;Lo;0;L;;;;;N;;;;; 0924;DEVANAGARI LETTER TA;Lo;0;L;;;;;N;;;;; 0925;DEVANAGARI LETTER THA;Lo;0;L;;;;;N;;;;; 0926;DEVANAGARI LETTER DA;Lo;0;L;;;;;N;;;;; 0927;DEVANAGARI LETTER DHA;Lo;0;L;;;;;N;;;;; 0928;DEVANAGARI LETTER NA;Lo;0;L;;;;;N;;;;; 0929;DEVANAGARI LETTER NNNA;Lo;0;L;0928 093C;;;;N;;;;; 092A;DEVANAGARI LETTER PA;Lo;0;L;;;;;N;;;;; 092B;DEVANAGARI LETTER PHA;Lo;0;L;;;;;N;;;;; 092C;DEVANAGARI LETTER BA;Lo;0;L;;;;;N;;;;; 092D;DEVANAGARI LETTER BHA;Lo;0;L;;;;;N;;;;; 092E;DEVANAGARI LETTER MA;Lo;0;L;;;;;N;;;;; 092F;DEVANAGARI LETTER YA;Lo;0;L;;;;;N;;;;; 0930;DEVANAGARI LETTER RA;Lo;0;L;;;;;N;;;;; 0931;DEVANAGARI LETTER RRA;Lo;0;L;0930 093C;;;;N;;;;; 0932;DEVANAGARI LETTER LA;Lo;0;L;;;;;N;;;;; 0933;DEVANAGARI LETTER LLA;Lo;0;L;;;;;N;;;;; 0934;DEVANAGARI LETTER LLLA;Lo;0;L;0933 093C;;;;N;;;;; 0935;DEVANAGARI LETTER VA;Lo;0;L;;;;;N;;;;; 0936;DEVANAGARI LETTER SHA;Lo;0;L;;;;;N;;;;; 0937;DEVANAGARI LETTER SSA;Lo;0;L;;;;;N;;;;; 0938;DEVANAGARI LETTER SA;Lo;0;L;;;;;N;;;;; 0939;DEVANAGARI LETTER HA;Lo;0;L;;;;;N;;;;; 093C;DEVANAGARI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; 093D;DEVANAGARI SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; 093E;DEVANAGARI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 093F;DEVANAGARI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 0940;DEVANAGARI VOWEL SIGN II;Mc;0;L;;;;;N;;;;; 0941;DEVANAGARI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 0942;DEVANAGARI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 0943;DEVANAGARI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; 0944;DEVANAGARI VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; 0945;DEVANAGARI VOWEL SIGN CANDRA E;Mn;0;NSM;;;;;N;;;;; 0946;DEVANAGARI VOWEL SIGN SHORT E;Mn;0;NSM;;;;;N;;;;; 0947;DEVANAGARI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; 0948;DEVANAGARI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; 0949;DEVANAGARI VOWEL SIGN CANDRA O;Mc;0;L;;;;;N;;;;; 094A;DEVANAGARI VOWEL SIGN SHORT O;Mc;0;L;;;;;N;;;;; 094B;DEVANAGARI VOWEL SIGN O;Mc;0;L;;;;;N;;;;; 094C;DEVANAGARI VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; 094D;DEVANAGARI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 0950;DEVANAGARI OM;Lo;0;L;;;;;N;;;;; 0951;DEVANAGARI STRESS SIGN UDATTA;Mn;230;NSM;;;;;N;;;;; 0952;DEVANAGARI STRESS SIGN ANUDATTA;Mn;220;NSM;;;;;N;;;;; 0953;DEVANAGARI GRAVE ACCENT;Mn;230;NSM;;;;;N;;;;; 0954;DEVANAGARI ACUTE ACCENT;Mn;230;NSM;;;;;N;;;;; 0958;DEVANAGARI LETTER QA;Lo;0;L;0915 093C;;;;N;;;;; 0959;DEVANAGARI LETTER KHHA;Lo;0;L;0916 093C;;;;N;;;;; 095A;DEVANAGARI LETTER GHHA;Lo;0;L;0917 093C;;;;N;;;;; 095B;DEVANAGARI LETTER ZA;Lo;0;L;091C 093C;;;;N;;;;; 095C;DEVANAGARI LETTER DDDHA;Lo;0;L;0921 093C;;;;N;;;;; 095D;DEVANAGARI LETTER RHA;Lo;0;L;0922 093C;;;;N;;;;; 095E;DEVANAGARI LETTER FA;Lo;0;L;092B 093C;;;;N;;;;; 095F;DEVANAGARI LETTER YYA;Lo;0;L;092F 093C;;;;N;;;;; 0960;DEVANAGARI LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 0961;DEVANAGARI LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; 0962;DEVANAGARI VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; 0963;DEVANAGARI VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; 0964;DEVANAGARI DANDA;Po;0;L;;;;;N;;;;; 0965;DEVANAGARI DOUBLE DANDA;Po;0;L;;;;;N;;;;; 0966;DEVANAGARI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 0967;DEVANAGARI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 0968;DEVANAGARI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 0969;DEVANAGARI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 096A;DEVANAGARI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 096B;DEVANAGARI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 096C;DEVANAGARI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 096D;DEVANAGARI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 096E;DEVANAGARI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 096F;DEVANAGARI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0970;DEVANAGARI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; 0981;BENGALI SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; 0982;BENGALI SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; 0983;BENGALI SIGN VISARGA;Mc;0;L;;;;;N;;;;; 0985;BENGALI LETTER A;Lo;0;L;;;;;N;;;;; 0986;BENGALI LETTER AA;Lo;0;L;;;;;N;;;;; 0987;BENGALI LETTER I;Lo;0;L;;;;;N;;;;; 0988;BENGALI LETTER II;Lo;0;L;;;;;N;;;;; 0989;BENGALI LETTER U;Lo;0;L;;;;;N;;;;; 098A;BENGALI LETTER UU;Lo;0;L;;;;;N;;;;; 098B;BENGALI LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; 098C;BENGALI LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; 098F;BENGALI LETTER E;Lo;0;L;;;;;N;;;;; 0990;BENGALI LETTER AI;Lo;0;L;;;;;N;;;;; 0993;BENGALI LETTER O;Lo;0;L;;;;;N;;;;; 0994;BENGALI LETTER AU;Lo;0;L;;;;;N;;;;; 0995;BENGALI LETTER KA;Lo;0;L;;;;;N;;;;; 0996;BENGALI LETTER KHA;Lo;0;L;;;;;N;;;;; 0997;BENGALI LETTER GA;Lo;0;L;;;;;N;;;;; 0998;BENGALI LETTER GHA;Lo;0;L;;;;;N;;;;; 0999;BENGALI LETTER NGA;Lo;0;L;;;;;N;;;;; 099A;BENGALI LETTER CA;Lo;0;L;;;;;N;;;;; 099B;BENGALI LETTER CHA;Lo;0;L;;;;;N;;;;; 099C;BENGALI LETTER JA;Lo;0;L;;;;;N;;;;; 099D;BENGALI LETTER JHA;Lo;0;L;;;;;N;;;;; 099E;BENGALI LETTER NYA;Lo;0;L;;;;;N;;;;; 099F;BENGALI LETTER TTA;Lo;0;L;;;;;N;;;;; 09A0;BENGALI LETTER TTHA;Lo;0;L;;;;;N;;;;; 09A1;BENGALI LETTER DDA;Lo;0;L;;;;;N;;;;; 09A2;BENGALI LETTER DDHA;Lo;0;L;;;;;N;;;;; 09A3;BENGALI LETTER NNA;Lo;0;L;;;;;N;;;;; 09A4;BENGALI LETTER TA;Lo;0;L;;;;;N;;;;; 09A5;BENGALI LETTER THA;Lo;0;L;;;;;N;;;;; 09A6;BENGALI LETTER DA;Lo;0;L;;;;;N;;;;; 09A7;BENGALI LETTER DHA;Lo;0;L;;;;;N;;;;; 09A8;BENGALI LETTER NA;Lo;0;L;;;;;N;;;;; 09AA;BENGALI LETTER PA;Lo;0;L;;;;;N;;;;; 09AB;BENGALI LETTER PHA;Lo;0;L;;;;;N;;;;; 09AC;BENGALI LETTER BA;Lo;0;L;;;;;N;;;;; 09AD;BENGALI LETTER BHA;Lo;0;L;;;;;N;;;;; 09AE;BENGALI LETTER MA;Lo;0;L;;;;;N;;;;; 09AF;BENGALI LETTER YA;Lo;0;L;;;;;N;;;;; 09B0;BENGALI LETTER RA;Lo;0;L;;;;;N;;;;; 09B2;BENGALI LETTER LA;Lo;0;L;;;;;N;;;;; 09B6;BENGALI LETTER SHA;Lo;0;L;;;;;N;;;;; 09B7;BENGALI LETTER SSA;Lo;0;L;;;;;N;;;;; 09B8;BENGALI LETTER SA;Lo;0;L;;;;;N;;;;; 09B9;BENGALI LETTER HA;Lo;0;L;;;;;N;;;;; 09BC;BENGALI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; 09BE;BENGALI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 09BF;BENGALI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 09C0;BENGALI VOWEL SIGN II;Mc;0;L;;;;;N;;;;; 09C1;BENGALI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 09C2;BENGALI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 09C3;BENGALI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; 09C4;BENGALI VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; 09C7;BENGALI VOWEL SIGN E;Mc;0;L;;;;;N;;;;; 09C8;BENGALI VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; 09CB;BENGALI VOWEL SIGN O;Mc;0;L;09C7 09BE;;;;N;;;;; 09CC;BENGALI VOWEL SIGN AU;Mc;0;L;09C7 09D7;;;;N;;;;; 09CD;BENGALI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 09D7;BENGALI AU LENGTH MARK;Mc;0;L;;;;;N;;;;; 09DC;BENGALI LETTER RRA;Lo;0;L;09A1 09BC;;;;N;;;;; 09DD;BENGALI LETTER RHA;Lo;0;L;09A2 09BC;;;;N;;;;; 09DF;BENGALI LETTER YYA;Lo;0;L;09AF 09BC;;;;N;;;;; 09E0;BENGALI LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 09E1;BENGALI LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; 09E2;BENGALI VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; 09E3;BENGALI VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; 09E6;BENGALI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 09E7;BENGALI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 09E8;BENGALI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 09E9;BENGALI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 09EA;BENGALI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 09EB;BENGALI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 09EC;BENGALI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 09ED;BENGALI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 09EE;BENGALI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 09EF;BENGALI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 09F0;BENGALI LETTER RA WITH MIDDLE DIAGONAL;Lo;0;L;;;;;N;;Assamese;;; 09F1;BENGALI LETTER RA WITH LOWER DIAGONAL;Lo;0;L;;;;;N;BENGALI LETTER VA WITH LOWER DIAGONAL;Assamese;;; 09F2;BENGALI RUPEE MARK;Sc;0;ET;;;;;N;;;;; 09F3;BENGALI RUPEE SIGN;Sc;0;ET;;;;;N;;;;; 09F4;BENGALI CURRENCY NUMERATOR ONE;No;0;L;;;;1;N;;;;; 09F5;BENGALI CURRENCY NUMERATOR TWO;No;0;L;;;;2;N;;;;; 09F6;BENGALI CURRENCY NUMERATOR THREE;No;0;L;;;;3;N;;;;; 09F7;BENGALI CURRENCY NUMERATOR FOUR;No;0;L;;;;4;N;;;;; 09F8;BENGALI CURRENCY NUMERATOR ONE LESS THAN THE DENOMINATOR;No;0;L;;;;;N;;;;; 09F9;BENGALI CURRENCY DENOMINATOR SIXTEEN;No;0;L;;;;16;N;;;;; 09FA;BENGALI ISSHAR;So;0;L;;;;;N;;;;; 0A02;GURMUKHI SIGN BINDI;Mn;0;NSM;;;;;N;;;;; 0A05;GURMUKHI LETTER A;Lo;0;L;;;;;N;;;;; 0A06;GURMUKHI LETTER AA;Lo;0;L;;;;;N;;;;; 0A07;GURMUKHI LETTER I;Lo;0;L;;;;;N;;;;; 0A08;GURMUKHI LETTER II;Lo;0;L;;;;;N;;;;; 0A09;GURMUKHI LETTER U;Lo;0;L;;;;;N;;;;; 0A0A;GURMUKHI LETTER UU;Lo;0;L;;;;;N;;;;; 0A0F;GURMUKHI LETTER EE;Lo;0;L;;;;;N;;;;; 0A10;GURMUKHI LETTER AI;Lo;0;L;;;;;N;;;;; 0A13;GURMUKHI LETTER OO;Lo;0;L;;;;;N;;;;; 0A14;GURMUKHI LETTER AU;Lo;0;L;;;;;N;;;;; 0A15;GURMUKHI LETTER KA;Lo;0;L;;;;;N;;;;; 0A16;GURMUKHI LETTER KHA;Lo;0;L;;;;;N;;;;; 0A17;GURMUKHI LETTER GA;Lo;0;L;;;;;N;;;;; 0A18;GURMUKHI LETTER GHA;Lo;0;L;;;;;N;;;;; 0A19;GURMUKHI LETTER NGA;Lo;0;L;;;;;N;;;;; 0A1A;GURMUKHI LETTER CA;Lo;0;L;;;;;N;;;;; 0A1B;GURMUKHI LETTER CHA;Lo;0;L;;;;;N;;;;; 0A1C;GURMUKHI LETTER JA;Lo;0;L;;;;;N;;;;; 0A1D;GURMUKHI LETTER JHA;Lo;0;L;;;;;N;;;;; 0A1E;GURMUKHI LETTER NYA;Lo;0;L;;;;;N;;;;; 0A1F;GURMUKHI LETTER TTA;Lo;0;L;;;;;N;;;;; 0A20;GURMUKHI LETTER TTHA;Lo;0;L;;;;;N;;;;; 0A21;GURMUKHI LETTER DDA;Lo;0;L;;;;;N;;;;; 0A22;GURMUKHI LETTER DDHA;Lo;0;L;;;;;N;;;;; 0A23;GURMUKHI LETTER NNA;Lo;0;L;;;;;N;;;;; 0A24;GURMUKHI LETTER TA;Lo;0;L;;;;;N;;;;; 0A25;GURMUKHI LETTER THA;Lo;0;L;;;;;N;;;;; 0A26;GURMUKHI LETTER DA;Lo;0;L;;;;;N;;;;; 0A27;GURMUKHI LETTER DHA;Lo;0;L;;;;;N;;;;; 0A28;GURMUKHI LETTER NA;Lo;0;L;;;;;N;;;;; 0A2A;GURMUKHI LETTER PA;Lo;0;L;;;;;N;;;;; 0A2B;GURMUKHI LETTER PHA;Lo;0;L;;;;;N;;;;; 0A2C;GURMUKHI LETTER BA;Lo;0;L;;;;;N;;;;; 0A2D;GURMUKHI LETTER BHA;Lo;0;L;;;;;N;;;;; 0A2E;GURMUKHI LETTER MA;Lo;0;L;;;;;N;;;;; 0A2F;GURMUKHI LETTER YA;Lo;0;L;;;;;N;;;;; 0A30;GURMUKHI LETTER RA;Lo;0;L;;;;;N;;;;; 0A32;GURMUKHI LETTER LA;Lo;0;L;;;;;N;;;;; 0A33;GURMUKHI LETTER LLA;Lo;0;L;0A32 0A3C;;;;N;;;;; 0A35;GURMUKHI LETTER VA;Lo;0;L;;;;;N;;;;; 0A36;GURMUKHI LETTER SHA;Lo;0;L;0A38 0A3C;;;;N;;;;; 0A38;GURMUKHI LETTER SA;Lo;0;L;;;;;N;;;;; 0A39;GURMUKHI LETTER HA;Lo;0;L;;;;;N;;;;; 0A3C;GURMUKHI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; 0A3E;GURMUKHI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 0A3F;GURMUKHI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 0A40;GURMUKHI VOWEL SIGN II;Mc;0;L;;;;;N;;;;; 0A41;GURMUKHI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 0A42;GURMUKHI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 0A47;GURMUKHI VOWEL SIGN EE;Mn;0;NSM;;;;;N;;;;; 0A48;GURMUKHI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; 0A4B;GURMUKHI VOWEL SIGN OO;Mn;0;NSM;;;;;N;;;;; 0A4C;GURMUKHI VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; 0A4D;GURMUKHI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 0A59;GURMUKHI LETTER KHHA;Lo;0;L;0A16 0A3C;;;;N;;;;; 0A5A;GURMUKHI LETTER GHHA;Lo;0;L;0A17 0A3C;;;;N;;;;; 0A5B;GURMUKHI LETTER ZA;Lo;0;L;0A1C 0A3C;;;;N;;;;; 0A5C;GURMUKHI LETTER RRA;Lo;0;L;;;;;N;;;;; 0A5E;GURMUKHI LETTER FA;Lo;0;L;0A2B 0A3C;;;;N;;;;; 0A66;GURMUKHI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 0A67;GURMUKHI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 0A68;GURMUKHI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 0A69;GURMUKHI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 0A6A;GURMUKHI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 0A6B;GURMUKHI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 0A6C;GURMUKHI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 0A6D;GURMUKHI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 0A6E;GURMUKHI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 0A6F;GURMUKHI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0A70;GURMUKHI TIPPI;Mn;0;NSM;;;;;N;;;;; 0A71;GURMUKHI ADDAK;Mn;0;NSM;;;;;N;;;;; 0A72;GURMUKHI IRI;Lo;0;L;;;;;N;;;;; 0A73;GURMUKHI URA;Lo;0;L;;;;;N;;;;; 0A74;GURMUKHI EK ONKAR;Lo;0;L;;;;;N;;;;; 0A81;GUJARATI SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; 0A82;GUJARATI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; 0A83;GUJARATI SIGN VISARGA;Mc;0;L;;;;;N;;;;; 0A85;GUJARATI LETTER A;Lo;0;L;;;;;N;;;;; 0A86;GUJARATI LETTER AA;Lo;0;L;;;;;N;;;;; 0A87;GUJARATI LETTER I;Lo;0;L;;;;;N;;;;; 0A88;GUJARATI LETTER II;Lo;0;L;;;;;N;;;;; 0A89;GUJARATI LETTER U;Lo;0;L;;;;;N;;;;; 0A8A;GUJARATI LETTER UU;Lo;0;L;;;;;N;;;;; 0A8B;GUJARATI LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; 0A8D;GUJARATI VOWEL CANDRA E;Lo;0;L;;;;;N;;;;; 0A8F;GUJARATI LETTER E;Lo;0;L;;;;;N;;;;; 0A90;GUJARATI LETTER AI;Lo;0;L;;;;;N;;;;; 0A91;GUJARATI VOWEL CANDRA O;Lo;0;L;;;;;N;;;;; 0A93;GUJARATI LETTER O;Lo;0;L;;;;;N;;;;; 0A94;GUJARATI LETTER AU;Lo;0;L;;;;;N;;;;; 0A95;GUJARATI LETTER KA;Lo;0;L;;;;;N;;;;; 0A96;GUJARATI LETTER KHA;Lo;0;L;;;;;N;;;;; 0A97;GUJARATI LETTER GA;Lo;0;L;;;;;N;;;;; 0A98;GUJARATI LETTER GHA;Lo;0;L;;;;;N;;;;; 0A99;GUJARATI LETTER NGA;Lo;0;L;;;;;N;;;;; 0A9A;GUJARATI LETTER CA;Lo;0;L;;;;;N;;;;; 0A9B;GUJARATI LETTER CHA;Lo;0;L;;;;;N;;;;; 0A9C;GUJARATI LETTER JA;Lo;0;L;;;;;N;;;;; 0A9D;GUJARATI LETTER JHA;Lo;0;L;;;;;N;;;;; 0A9E;GUJARATI LETTER NYA;Lo;0;L;;;;;N;;;;; 0A9F;GUJARATI LETTER TTA;Lo;0;L;;;;;N;;;;; 0AA0;GUJARATI LETTER TTHA;Lo;0;L;;;;;N;;;;; 0AA1;GUJARATI LETTER DDA;Lo;0;L;;;;;N;;;;; 0AA2;GUJARATI LETTER DDHA;Lo;0;L;;;;;N;;;;; 0AA3;GUJARATI LETTER NNA;Lo;0;L;;;;;N;;;;; 0AA4;GUJARATI LETTER TA;Lo;0;L;;;;;N;;;;; 0AA5;GUJARATI LETTER THA;Lo;0;L;;;;;N;;;;; 0AA6;GUJARATI LETTER DA;Lo;0;L;;;;;N;;;;; 0AA7;GUJARATI LETTER DHA;Lo;0;L;;;;;N;;;;; 0AA8;GUJARATI LETTER NA;Lo;0;L;;;;;N;;;;; 0AAA;GUJARATI LETTER PA;Lo;0;L;;;;;N;;;;; 0AAB;GUJARATI LETTER PHA;Lo;0;L;;;;;N;;;;; 0AAC;GUJARATI LETTER BA;Lo;0;L;;;;;N;;;;; 0AAD;GUJARATI LETTER BHA;Lo;0;L;;;;;N;;;;; 0AAE;GUJARATI LETTER MA;Lo;0;L;;;;;N;;;;; 0AAF;GUJARATI LETTER YA;Lo;0;L;;;;;N;;;;; 0AB0;GUJARATI LETTER RA;Lo;0;L;;;;;N;;;;; 0AB2;GUJARATI LETTER LA;Lo;0;L;;;;;N;;;;; 0AB3;GUJARATI LETTER LLA;Lo;0;L;;;;;N;;;;; 0AB5;GUJARATI LETTER VA;Lo;0;L;;;;;N;;;;; 0AB6;GUJARATI LETTER SHA;Lo;0;L;;;;;N;;;;; 0AB7;GUJARATI LETTER SSA;Lo;0;L;;;;;N;;;;; 0AB8;GUJARATI LETTER SA;Lo;0;L;;;;;N;;;;; 0AB9;GUJARATI LETTER HA;Lo;0;L;;;;;N;;;;; 0ABC;GUJARATI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; 0ABD;GUJARATI SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; 0ABE;GUJARATI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 0ABF;GUJARATI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 0AC0;GUJARATI VOWEL SIGN II;Mc;0;L;;;;;N;;;;; 0AC1;GUJARATI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 0AC2;GUJARATI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 0AC3;GUJARATI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; 0AC4;GUJARATI VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; 0AC5;GUJARATI VOWEL SIGN CANDRA E;Mn;0;NSM;;;;;N;;;;; 0AC7;GUJARATI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; 0AC8;GUJARATI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; 0AC9;GUJARATI VOWEL SIGN CANDRA O;Mc;0;L;;;;;N;;;;; 0ACB;GUJARATI VOWEL SIGN O;Mc;0;L;;;;;N;;;;; 0ACC;GUJARATI VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; 0ACD;GUJARATI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 0AD0;GUJARATI OM;Lo;0;L;;;;;N;;;;; 0AE0;GUJARATI LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 0AE6;GUJARATI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 0AE7;GUJARATI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 0AE8;GUJARATI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 0AE9;GUJARATI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 0AEA;GUJARATI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 0AEB;GUJARATI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 0AEC;GUJARATI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 0AED;GUJARATI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 0AEE;GUJARATI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 0AEF;GUJARATI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0B01;ORIYA SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; 0B02;ORIYA SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; 0B03;ORIYA SIGN VISARGA;Mc;0;L;;;;;N;;;;; 0B05;ORIYA LETTER A;Lo;0;L;;;;;N;;;;; 0B06;ORIYA LETTER AA;Lo;0;L;;;;;N;;;;; 0B07;ORIYA LETTER I;Lo;0;L;;;;;N;;;;; 0B08;ORIYA LETTER II;Lo;0;L;;;;;N;;;;; 0B09;ORIYA LETTER U;Lo;0;L;;;;;N;;;;; 0B0A;ORIYA LETTER UU;Lo;0;L;;;;;N;;;;; 0B0B;ORIYA LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; 0B0C;ORIYA LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; 0B0F;ORIYA LETTER E;Lo;0;L;;;;;N;;;;; 0B10;ORIYA LETTER AI;Lo;0;L;;;;;N;;;;; 0B13;ORIYA LETTER O;Lo;0;L;;;;;N;;;;; 0B14;ORIYA LETTER AU;Lo;0;L;;;;;N;;;;; 0B15;ORIYA LETTER KA;Lo;0;L;;;;;N;;;;; 0B16;ORIYA LETTER KHA;Lo;0;L;;;;;N;;;;; 0B17;ORIYA LETTER GA;Lo;0;L;;;;;N;;;;; 0B18;ORIYA LETTER GHA;Lo;0;L;;;;;N;;;;; 0B19;ORIYA LETTER NGA;Lo;0;L;;;;;N;;;;; 0B1A;ORIYA LETTER CA;Lo;0;L;;;;;N;;;;; 0B1B;ORIYA LETTER CHA;Lo;0;L;;;;;N;;;;; 0B1C;ORIYA LETTER JA;Lo;0;L;;;;;N;;;;; 0B1D;ORIYA LETTER JHA;Lo;0;L;;;;;N;;;;; 0B1E;ORIYA LETTER NYA;Lo;0;L;;;;;N;;;;; 0B1F;ORIYA LETTER TTA;Lo;0;L;;;;;N;;;;; 0B20;ORIYA LETTER TTHA;Lo;0;L;;;;;N;;;;; 0B21;ORIYA LETTER DDA;Lo;0;L;;;;;N;;;;; 0B22;ORIYA LETTER DDHA;Lo;0;L;;;;;N;;;;; 0B23;ORIYA LETTER NNA;Lo;0;L;;;;;N;;;;; 0B24;ORIYA LETTER TA;Lo;0;L;;;;;N;;;;; 0B25;ORIYA LETTER THA;Lo;0;L;;;;;N;;;;; 0B26;ORIYA LETTER DA;Lo;0;L;;;;;N;;;;; 0B27;ORIYA LETTER DHA;Lo;0;L;;;;;N;;;;; 0B28;ORIYA LETTER NA;Lo;0;L;;;;;N;;;;; 0B2A;ORIYA LETTER PA;Lo;0;L;;;;;N;;;;; 0B2B;ORIYA LETTER PHA;Lo;0;L;;;;;N;;;;; 0B2C;ORIYA LETTER BA;Lo;0;L;;;;;N;;;;; 0B2D;ORIYA LETTER BHA;Lo;0;L;;;;;N;;;;; 0B2E;ORIYA LETTER MA;Lo;0;L;;;;;N;;;;; 0B2F;ORIYA LETTER YA;Lo;0;L;;;;;N;;;;; 0B30;ORIYA LETTER RA;Lo;0;L;;;;;N;;;;; 0B32;ORIYA LETTER LA;Lo;0;L;;;;;N;;;;; 0B33;ORIYA LETTER LLA;Lo;0;L;;;;;N;;;;; 0B36;ORIYA LETTER SHA;Lo;0;L;;;;;N;;;;; 0B37;ORIYA LETTER SSA;Lo;0;L;;;;;N;;;;; 0B38;ORIYA LETTER SA;Lo;0;L;;;;;N;;;;; 0B39;ORIYA LETTER HA;Lo;0;L;;;;;N;;;;; 0B3C;ORIYA SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; 0B3D;ORIYA SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; 0B3E;ORIYA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 0B3F;ORIYA VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 0B40;ORIYA VOWEL SIGN II;Mc;0;L;;;;;N;;;;; 0B41;ORIYA VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 0B42;ORIYA VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 0B43;ORIYA VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; 0B47;ORIYA VOWEL SIGN E;Mc;0;L;;;;;N;;;;; 0B48;ORIYA VOWEL SIGN AI;Mc;0;L;0B47 0B56;;;;N;;;;; 0B4B;ORIYA VOWEL SIGN O;Mc;0;L;0B47 0B3E;;;;N;;;;; 0B4C;ORIYA VOWEL SIGN AU;Mc;0;L;0B47 0B57;;;;N;;;;; 0B4D;ORIYA SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 0B56;ORIYA AI LENGTH MARK;Mn;0;NSM;;;;;N;;;;; 0B57;ORIYA AU LENGTH MARK;Mc;0;L;;;;;N;;;;; 0B5C;ORIYA LETTER RRA;Lo;0;L;0B21 0B3C;;;;N;;;;; 0B5D;ORIYA LETTER RHA;Lo;0;L;0B22 0B3C;;;;N;;;;; 0B5F;ORIYA LETTER YYA;Lo;0;L;;;;;N;;;;; 0B60;ORIYA LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 0B61;ORIYA LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; 0B66;ORIYA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 0B67;ORIYA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 0B68;ORIYA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 0B69;ORIYA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 0B6A;ORIYA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 0B6B;ORIYA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 0B6C;ORIYA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 0B6D;ORIYA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 0B6E;ORIYA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 0B6F;ORIYA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0B70;ORIYA ISSHAR;So;0;L;;;;;N;;;;; 0B82;TAMIL SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; 0B83;TAMIL SIGN VISARGA;Lo;0;L;;;;;N;;;;; 0B85;TAMIL LETTER A;Lo;0;L;;;;;N;;;;; 0B86;TAMIL LETTER AA;Lo;0;L;;;;;N;;;;; 0B87;TAMIL LETTER I;Lo;0;L;;;;;N;;;;; 0B88;TAMIL LETTER II;Lo;0;L;;;;;N;;;;; 0B89;TAMIL LETTER U;Lo;0;L;;;;;N;;;;; 0B8A;TAMIL LETTER UU;Lo;0;L;;;;;N;;;;; 0B8E;TAMIL LETTER E;Lo;0;L;;;;;N;;;;; 0B8F;TAMIL LETTER EE;Lo;0;L;;;;;N;;;;; 0B90;TAMIL LETTER AI;Lo;0;L;;;;;N;;;;; 0B92;TAMIL LETTER O;Lo;0;L;;;;;N;;;;; 0B93;TAMIL LETTER OO;Lo;0;L;;;;;N;;;;; 0B94;TAMIL LETTER AU;Lo;0;L;0B92 0BD7;;;;N;;;;; 0B95;TAMIL LETTER KA;Lo;0;L;;;;;N;;;;; 0B99;TAMIL LETTER NGA;Lo;0;L;;;;;N;;;;; 0B9A;TAMIL LETTER CA;Lo;0;L;;;;;N;;;;; 0B9C;TAMIL LETTER JA;Lo;0;L;;;;;N;;;;; 0B9E;TAMIL LETTER NYA;Lo;0;L;;;;;N;;;;; 0B9F;TAMIL LETTER TTA;Lo;0;L;;;;;N;;;;; 0BA3;TAMIL LETTER NNA;Lo;0;L;;;;;N;;;;; 0BA4;TAMIL LETTER TA;Lo;0;L;;;;;N;;;;; 0BA8;TAMIL LETTER NA;Lo;0;L;;;;;N;;;;; 0BA9;TAMIL LETTER NNNA;Lo;0;L;;;;;N;;;;; 0BAA;TAMIL LETTER PA;Lo;0;L;;;;;N;;;;; 0BAE;TAMIL LETTER MA;Lo;0;L;;;;;N;;;;; 0BAF;TAMIL LETTER YA;Lo;0;L;;;;;N;;;;; 0BB0;TAMIL LETTER RA;Lo;0;L;;;;;N;;;;; 0BB1;TAMIL LETTER RRA;Lo;0;L;;;;;N;;;;; 0BB2;TAMIL LETTER LA;Lo;0;L;;;;;N;;;;; 0BB3;TAMIL LETTER LLA;Lo;0;L;;;;;N;;;;; 0BB4;TAMIL LETTER LLLA;Lo;0;L;;;;;N;;;;; 0BB5;TAMIL LETTER VA;Lo;0;L;;;;;N;;;;; 0BB7;TAMIL LETTER SSA;Lo;0;L;;;;;N;;;;; 0BB8;TAMIL LETTER SA;Lo;0;L;;;;;N;;;;; 0BB9;TAMIL LETTER HA;Lo;0;L;;;;;N;;;;; 0BBE;TAMIL VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 0BBF;TAMIL VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 0BC0;TAMIL VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; 0BC1;TAMIL VOWEL SIGN U;Mc;0;L;;;;;N;;;;; 0BC2;TAMIL VOWEL SIGN UU;Mc;0;L;;;;;N;;;;; 0BC6;TAMIL VOWEL SIGN E;Mc;0;L;;;;;N;;;;; 0BC7;TAMIL VOWEL SIGN EE;Mc;0;L;;;;;N;;;;; 0BC8;TAMIL VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; 0BCA;TAMIL VOWEL SIGN O;Mc;0;L;0BC6 0BBE;;;;N;;;;; 0BCB;TAMIL VOWEL SIGN OO;Mc;0;L;0BC7 0BBE;;;;N;;;;; 0BCC;TAMIL VOWEL SIGN AU;Mc;0;L;0BC6 0BD7;;;;N;;;;; 0BCD;TAMIL SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 0BD7;TAMIL AU LENGTH MARK;Mc;0;L;;;;;N;;;;; 0BE7;TAMIL DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 0BE8;TAMIL DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 0BE9;TAMIL DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 0BEA;TAMIL DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 0BEB;TAMIL DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 0BEC;TAMIL DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 0BED;TAMIL DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 0BEE;TAMIL DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 0BEF;TAMIL DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0BF0;TAMIL NUMBER TEN;No;0;L;;;;10;N;;;;; 0BF1;TAMIL NUMBER ONE HUNDRED;No;0;L;;;;100;N;;;;; 0BF2;TAMIL NUMBER ONE THOUSAND;No;0;L;;;;1000;N;;;;; 0C01;TELUGU SIGN CANDRABINDU;Mc;0;L;;;;;N;;;;; 0C02;TELUGU SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; 0C03;TELUGU SIGN VISARGA;Mc;0;L;;;;;N;;;;; 0C05;TELUGU LETTER A;Lo;0;L;;;;;N;;;;; 0C06;TELUGU LETTER AA;Lo;0;L;;;;;N;;;;; 0C07;TELUGU LETTER I;Lo;0;L;;;;;N;;;;; 0C08;TELUGU LETTER II;Lo;0;L;;;;;N;;;;; 0C09;TELUGU LETTER U;Lo;0;L;;;;;N;;;;; 0C0A;TELUGU LETTER UU;Lo;0;L;;;;;N;;;;; 0C0B;TELUGU LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; 0C0C;TELUGU LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; 0C0E;TELUGU LETTER E;Lo;0;L;;;;;N;;;;; 0C0F;TELUGU LETTER EE;Lo;0;L;;;;;N;;;;; 0C10;TELUGU LETTER AI;Lo;0;L;;;;;N;;;;; 0C12;TELUGU LETTER O;Lo;0;L;;;;;N;;;;; 0C13;TELUGU LETTER OO;Lo;0;L;;;;;N;;;;; 0C14;TELUGU LETTER AU;Lo;0;L;;;;;N;;;;; 0C15;TELUGU LETTER KA;Lo;0;L;;;;;N;;;;; 0C16;TELUGU LETTER KHA;Lo;0;L;;;;;N;;;;; 0C17;TELUGU LETTER GA;Lo;0;L;;;;;N;;;;; 0C18;TELUGU LETTER GHA;Lo;0;L;;;;;N;;;;; 0C19;TELUGU LETTER NGA;Lo;0;L;;;;;N;;;;; 0C1A;TELUGU LETTER CA;Lo;0;L;;;;;N;;;;; 0C1B;TELUGU LETTER CHA;Lo;0;L;;;;;N;;;;; 0C1C;TELUGU LETTER JA;Lo;0;L;;;;;N;;;;; 0C1D;TELUGU LETTER JHA;Lo;0;L;;;;;N;;;;; 0C1E;TELUGU LETTER NYA;Lo;0;L;;;;;N;;;;; 0C1F;TELUGU LETTER TTA;Lo;0;L;;;;;N;;;;; 0C20;TELUGU LETTER TTHA;Lo;0;L;;;;;N;;;;; 0C21;TELUGU LETTER DDA;Lo;0;L;;;;;N;;;;; 0C22;TELUGU LETTER DDHA;Lo;0;L;;;;;N;;;;; 0C23;TELUGU LETTER NNA;Lo;0;L;;;;;N;;;;; 0C24;TELUGU LETTER TA;Lo;0;L;;;;;N;;;;; 0C25;TELUGU LETTER THA;Lo;0;L;;;;;N;;;;; 0C26;TELUGU LETTER DA;Lo;0;L;;;;;N;;;;; 0C27;TELUGU LETTER DHA;Lo;0;L;;;;;N;;;;; 0C28;TELUGU LETTER NA;Lo;0;L;;;;;N;;;;; 0C2A;TELUGU LETTER PA;Lo;0;L;;;;;N;;;;; 0C2B;TELUGU LETTER PHA;Lo;0;L;;;;;N;;;;; 0C2C;TELUGU LETTER BA;Lo;0;L;;;;;N;;;;; 0C2D;TELUGU LETTER BHA;Lo;0;L;;;;;N;;;;; 0C2E;TELUGU LETTER MA;Lo;0;L;;;;;N;;;;; 0C2F;TELUGU LETTER YA;Lo;0;L;;;;;N;;;;; 0C30;TELUGU LETTER RA;Lo;0;L;;;;;N;;;;; 0C31;TELUGU LETTER RRA;Lo;0;L;;;;;N;;;;; 0C32;TELUGU LETTER LA;Lo;0;L;;;;;N;;;;; 0C33;TELUGU LETTER LLA;Lo;0;L;;;;;N;;;;; 0C35;TELUGU LETTER VA;Lo;0;L;;;;;N;;;;; 0C36;TELUGU LETTER SHA;Lo;0;L;;;;;N;;;;; 0C37;TELUGU LETTER SSA;Lo;0;L;;;;;N;;;;; 0C38;TELUGU LETTER SA;Lo;0;L;;;;;N;;;;; 0C39;TELUGU LETTER HA;Lo;0;L;;;;;N;;;;; 0C3E;TELUGU VOWEL SIGN AA;Mn;0;NSM;;;;;N;;;;; 0C3F;TELUGU VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 0C40;TELUGU VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; 0C41;TELUGU VOWEL SIGN U;Mc;0;L;;;;;N;;;;; 0C42;TELUGU VOWEL SIGN UU;Mc;0;L;;;;;N;;;;; 0C43;TELUGU VOWEL SIGN VOCALIC R;Mc;0;L;;;;;N;;;;; 0C44;TELUGU VOWEL SIGN VOCALIC RR;Mc;0;L;;;;;N;;;;; 0C46;TELUGU VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; 0C47;TELUGU VOWEL SIGN EE;Mn;0;NSM;;;;;N;;;;; 0C48;TELUGU VOWEL SIGN AI;Mn;0;NSM;0C46 0C56;;;;N;;;;; 0C4A;TELUGU VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; 0C4B;TELUGU VOWEL SIGN OO;Mn;0;NSM;;;;;N;;;;; 0C4C;TELUGU VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; 0C4D;TELUGU SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 0C55;TELUGU LENGTH MARK;Mn;84;NSM;;;;;N;;;;; 0C56;TELUGU AI LENGTH MARK;Mn;91;NSM;;;;;N;;;;; 0C60;TELUGU LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 0C61;TELUGU LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; 0C66;TELUGU DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 0C67;TELUGU DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 0C68;TELUGU DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 0C69;TELUGU DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 0C6A;TELUGU DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 0C6B;TELUGU DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 0C6C;TELUGU DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 0C6D;TELUGU DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 0C6E;TELUGU DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 0C6F;TELUGU DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0C82;KANNADA SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; 0C83;KANNADA SIGN VISARGA;Mc;0;L;;;;;N;;;;; 0C85;KANNADA LETTER A;Lo;0;L;;;;;N;;;;; 0C86;KANNADA LETTER AA;Lo;0;L;;;;;N;;;;; 0C87;KANNADA LETTER I;Lo;0;L;;;;;N;;;;; 0C88;KANNADA LETTER II;Lo;0;L;;;;;N;;;;; 0C89;KANNADA LETTER U;Lo;0;L;;;;;N;;;;; 0C8A;KANNADA LETTER UU;Lo;0;L;;;;;N;;;;; 0C8B;KANNADA LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; 0C8C;KANNADA LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; 0C8E;KANNADA LETTER E;Lo;0;L;;;;;N;;;;; 0C8F;KANNADA LETTER EE;Lo;0;L;;;;;N;;;;; 0C90;KANNADA LETTER AI;Lo;0;L;;;;;N;;;;; 0C92;KANNADA LETTER O;Lo;0;L;;;;;N;;;;; 0C93;KANNADA LETTER OO;Lo;0;L;;;;;N;;;;; 0C94;KANNADA LETTER AU;Lo;0;L;;;;;N;;;;; 0C95;KANNADA LETTER KA;Lo;0;L;;;;;N;;;;; 0C96;KANNADA LETTER KHA;Lo;0;L;;;;;N;;;;; 0C97;KANNADA LETTER GA;Lo;0;L;;;;;N;;;;; 0C98;KANNADA LETTER GHA;Lo;0;L;;;;;N;;;;; 0C99;KANNADA LETTER NGA;Lo;0;L;;;;;N;;;;; 0C9A;KANNADA LETTER CA;Lo;0;L;;;;;N;;;;; 0C9B;KANNADA LETTER CHA;Lo;0;L;;;;;N;;;;; 0C9C;KANNADA LETTER JA;Lo;0;L;;;;;N;;;;; 0C9D;KANNADA LETTER JHA;Lo;0;L;;;;;N;;;;; 0C9E;KANNADA LETTER NYA;Lo;0;L;;;;;N;;;;; 0C9F;KANNADA LETTER TTA;Lo;0;L;;;;;N;;;;; 0CA0;KANNADA LETTER TTHA;Lo;0;L;;;;;N;;;;; 0CA1;KANNADA LETTER DDA;Lo;0;L;;;;;N;;;;; 0CA2;KANNADA LETTER DDHA;Lo;0;L;;;;;N;;;;; 0CA3;KANNADA LETTER NNA;Lo;0;L;;;;;N;;;;; 0CA4;KANNADA LETTER TA;Lo;0;L;;;;;N;;;;; 0CA5;KANNADA LETTER THA;Lo;0;L;;;;;N;;;;; 0CA6;KANNADA LETTER DA;Lo;0;L;;;;;N;;;;; 0CA7;KANNADA LETTER DHA;Lo;0;L;;;;;N;;;;; 0CA8;KANNADA LETTER NA;Lo;0;L;;;;;N;;;;; 0CAA;KANNADA LETTER PA;Lo;0;L;;;;;N;;;;; 0CAB;KANNADA LETTER PHA;Lo;0;L;;;;;N;;;;; 0CAC;KANNADA LETTER BA;Lo;0;L;;;;;N;;;;; 0CAD;KANNADA LETTER BHA;Lo;0;L;;;;;N;;;;; 0CAE;KANNADA LETTER MA;Lo;0;L;;;;;N;;;;; 0CAF;KANNADA LETTER YA;Lo;0;L;;;;;N;;;;; 0CB0;KANNADA LETTER RA;Lo;0;L;;;;;N;;;;; 0CB1;KANNADA LETTER RRA;Lo;0;L;;;;;N;;;;; 0CB2;KANNADA LETTER LA;Lo;0;L;;;;;N;;;;; 0CB3;KANNADA LETTER LLA;Lo;0;L;;;;;N;;;;; 0CB5;KANNADA LETTER VA;Lo;0;L;;;;;N;;;;; 0CB6;KANNADA LETTER SHA;Lo;0;L;;;;;N;;;;; 0CB7;KANNADA LETTER SSA;Lo;0;L;;;;;N;;;;; 0CB8;KANNADA LETTER SA;Lo;0;L;;;;;N;;;;; 0CB9;KANNADA LETTER HA;Lo;0;L;;;;;N;;;;; 0CBE;KANNADA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 0CBF;KANNADA VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 0CC0;KANNADA VOWEL SIGN II;Mc;0;L;0CBF 0CD5;;;;N;;;;; 0CC1;KANNADA VOWEL SIGN U;Mc;0;L;;;;;N;;;;; 0CC2;KANNADA VOWEL SIGN UU;Mc;0;L;;;;;N;;;;; 0CC3;KANNADA VOWEL SIGN VOCALIC R;Mc;0;L;;;;;N;;;;; 0CC4;KANNADA VOWEL SIGN VOCALIC RR;Mc;0;L;;;;;N;;;;; 0CC6;KANNADA VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; 0CC7;KANNADA VOWEL SIGN EE;Mc;0;L;0CC6 0CD5;;;;N;;;;; 0CC8;KANNADA VOWEL SIGN AI;Mc;0;L;0CC6 0CD6;;;;N;;;;; 0CCA;KANNADA VOWEL SIGN O;Mc;0;L;0CC6 0CC2;;;;N;;;;; 0CCB;KANNADA VOWEL SIGN OO;Mc;0;L;0CCA 0CD5;;;;N;;;;; 0CCC;KANNADA VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; 0CCD;KANNADA SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 0CD5;KANNADA LENGTH MARK;Mc;0;L;;;;;N;;;;; 0CD6;KANNADA AI LENGTH MARK;Mc;0;L;;;;;N;;;;; 0CDE;KANNADA LETTER FA;Lo;0;L;;;;;N;;;;; 0CE0;KANNADA LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 0CE1;KANNADA LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; 0CE6;KANNADA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 0CE7;KANNADA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 0CE8;KANNADA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 0CE9;KANNADA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 0CEA;KANNADA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 0CEB;KANNADA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 0CEC;KANNADA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 0CED;KANNADA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 0CEE;KANNADA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 0CEF;KANNADA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0D02;MALAYALAM SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; 0D03;MALAYALAM SIGN VISARGA;Mc;0;L;;;;;N;;;;; 0D05;MALAYALAM LETTER A;Lo;0;L;;;;;N;;;;; 0D06;MALAYALAM LETTER AA;Lo;0;L;;;;;N;;;;; 0D07;MALAYALAM LETTER I;Lo;0;L;;;;;N;;;;; 0D08;MALAYALAM LETTER II;Lo;0;L;;;;;N;;;;; 0D09;MALAYALAM LETTER U;Lo;0;L;;;;;N;;;;; 0D0A;MALAYALAM LETTER UU;Lo;0;L;;;;;N;;;;; 0D0B;MALAYALAM LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; 0D0C;MALAYALAM LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; 0D0E;MALAYALAM LETTER E;Lo;0;L;;;;;N;;;;; 0D0F;MALAYALAM LETTER EE;Lo;0;L;;;;;N;;;;; 0D10;MALAYALAM LETTER AI;Lo;0;L;;;;;N;;;;; 0D12;MALAYALAM LETTER O;Lo;0;L;;;;;N;;;;; 0D13;MALAYALAM LETTER OO;Lo;0;L;;;;;N;;;;; 0D14;MALAYALAM LETTER AU;Lo;0;L;;;;;N;;;;; 0D15;MALAYALAM LETTER KA;Lo;0;L;;;;;N;;;;; 0D16;MALAYALAM LETTER KHA;Lo;0;L;;;;;N;;;;; 0D17;MALAYALAM LETTER GA;Lo;0;L;;;;;N;;;;; 0D18;MALAYALAM LETTER GHA;Lo;0;L;;;;;N;;;;; 0D19;MALAYALAM LETTER NGA;Lo;0;L;;;;;N;;;;; 0D1A;MALAYALAM LETTER CA;Lo;0;L;;;;;N;;;;; 0D1B;MALAYALAM LETTER CHA;Lo;0;L;;;;;N;;;;; 0D1C;MALAYALAM LETTER JA;Lo;0;L;;;;;N;;;;; 0D1D;MALAYALAM LETTER JHA;Lo;0;L;;;;;N;;;;; 0D1E;MALAYALAM LETTER NYA;Lo;0;L;;;;;N;;;;; 0D1F;MALAYALAM LETTER TTA;Lo;0;L;;;;;N;;;;; 0D20;MALAYALAM LETTER TTHA;Lo;0;L;;;;;N;;;;; 0D21;MALAYALAM LETTER DDA;Lo;0;L;;;;;N;;;;; 0D22;MALAYALAM LETTER DDHA;Lo;0;L;;;;;N;;;;; 0D23;MALAYALAM LETTER NNA;Lo;0;L;;;;;N;;;;; 0D24;MALAYALAM LETTER TA;Lo;0;L;;;;;N;;;;; 0D25;MALAYALAM LETTER THA;Lo;0;L;;;;;N;;;;; 0D26;MALAYALAM LETTER DA;Lo;0;L;;;;;N;;;;; 0D27;MALAYALAM LETTER DHA;Lo;0;L;;;;;N;;;;; 0D28;MALAYALAM LETTER NA;Lo;0;L;;;;;N;;;;; 0D2A;MALAYALAM LETTER PA;Lo;0;L;;;;;N;;;;; 0D2B;MALAYALAM LETTER PHA;Lo;0;L;;;;;N;;;;; 0D2C;MALAYALAM LETTER BA;Lo;0;L;;;;;N;;;;; 0D2D;MALAYALAM LETTER BHA;Lo;0;L;;;;;N;;;;; 0D2E;MALAYALAM LETTER MA;Lo;0;L;;;;;N;;;;; 0D2F;MALAYALAM LETTER YA;Lo;0;L;;;;;N;;;;; 0D30;MALAYALAM LETTER RA;Lo;0;L;;;;;N;;;;; 0D31;MALAYALAM LETTER RRA;Lo;0;L;;;;;N;;;;; 0D32;MALAYALAM LETTER LA;Lo;0;L;;;;;N;;;;; 0D33;MALAYALAM LETTER LLA;Lo;0;L;;;;;N;;;;; 0D34;MALAYALAM LETTER LLLA;Lo;0;L;;;;;N;;;;; 0D35;MALAYALAM LETTER VA;Lo;0;L;;;;;N;;;;; 0D36;MALAYALAM LETTER SHA;Lo;0;L;;;;;N;;;;; 0D37;MALAYALAM LETTER SSA;Lo;0;L;;;;;N;;;;; 0D38;MALAYALAM LETTER SA;Lo;0;L;;;;;N;;;;; 0D39;MALAYALAM LETTER HA;Lo;0;L;;;;;N;;;;; 0D3E;MALAYALAM VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 0D3F;MALAYALAM VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 0D40;MALAYALAM VOWEL SIGN II;Mc;0;L;;;;;N;;;;; 0D41;MALAYALAM VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 0D42;MALAYALAM VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 0D43;MALAYALAM VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; 0D46;MALAYALAM VOWEL SIGN E;Mc;0;L;;;;;N;;;;; 0D47;MALAYALAM VOWEL SIGN EE;Mc;0;L;;;;;N;;;;; 0D48;MALAYALAM VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; 0D4A;MALAYALAM VOWEL SIGN O;Mc;0;L;0D46 0D3E;;;;N;;;;; 0D4B;MALAYALAM VOWEL SIGN OO;Mc;0;L;0D47 0D3E;;;;N;;;;; 0D4C;MALAYALAM VOWEL SIGN AU;Mc;0;L;0D46 0D57;;;;N;;;;; 0D4D;MALAYALAM SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 0D57;MALAYALAM AU LENGTH MARK;Mc;0;L;;;;;N;;;;; 0D60;MALAYALAM LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 0D61;MALAYALAM LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; 0D66;MALAYALAM DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 0D67;MALAYALAM DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 0D68;MALAYALAM DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 0D69;MALAYALAM DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 0D6A;MALAYALAM DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 0D6B;MALAYALAM DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 0D6C;MALAYALAM DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 0D6D;MALAYALAM DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 0D6E;MALAYALAM DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 0D6F;MALAYALAM DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0D82;SINHALA SIGN ANUSVARAYA;Mc;0;L;;;;;N;;;;; 0D83;SINHALA SIGN VISARGAYA;Mc;0;L;;;;;N;;;;; 0D85;SINHALA LETTER AYANNA;Lo;0;L;;;;;N;;;;; 0D86;SINHALA LETTER AAYANNA;Lo;0;L;;;;;N;;;;; 0D87;SINHALA LETTER AEYANNA;Lo;0;L;;;;;N;;;;; 0D88;SINHALA LETTER AEEYANNA;Lo;0;L;;;;;N;;;;; 0D89;SINHALA LETTER IYANNA;Lo;0;L;;;;;N;;;;; 0D8A;SINHALA LETTER IIYANNA;Lo;0;L;;;;;N;;;;; 0D8B;SINHALA LETTER UYANNA;Lo;0;L;;;;;N;;;;; 0D8C;SINHALA LETTER UUYANNA;Lo;0;L;;;;;N;;;;; 0D8D;SINHALA LETTER IRUYANNA;Lo;0;L;;;;;N;;;;; 0D8E;SINHALA LETTER IRUUYANNA;Lo;0;L;;;;;N;;;;; 0D8F;SINHALA LETTER ILUYANNA;Lo;0;L;;;;;N;;;;; 0D90;SINHALA LETTER ILUUYANNA;Lo;0;L;;;;;N;;;;; 0D91;SINHALA LETTER EYANNA;Lo;0;L;;;;;N;;;;; 0D92;SINHALA LETTER EEYANNA;Lo;0;L;;;;;N;;;;; 0D93;SINHALA LETTER AIYANNA;Lo;0;L;;;;;N;;;;; 0D94;SINHALA LETTER OYANNA;Lo;0;L;;;;;N;;;;; 0D95;SINHALA LETTER OOYANNA;Lo;0;L;;;;;N;;;;; 0D96;SINHALA LETTER AUYANNA;Lo;0;L;;;;;N;;;;; 0D9A;SINHALA LETTER ALPAPRAANA KAYANNA;Lo;0;L;;;;;N;;;;; 0D9B;SINHALA LETTER MAHAAPRAANA KAYANNA;Lo;0;L;;;;;N;;;;; 0D9C;SINHALA LETTER ALPAPRAANA GAYANNA;Lo;0;L;;;;;N;;;;; 0D9D;SINHALA LETTER MAHAAPRAANA GAYANNA;Lo;0;L;;;;;N;;;;; 0D9E;SINHALA LETTER KANTAJA NAASIKYAYA;Lo;0;L;;;;;N;;;;; 0D9F;SINHALA LETTER SANYAKA GAYANNA;Lo;0;L;;;;;N;;;;; 0DA0;SINHALA LETTER ALPAPRAANA CAYANNA;Lo;0;L;;;;;N;;;;; 0DA1;SINHALA LETTER MAHAAPRAANA CAYANNA;Lo;0;L;;;;;N;;;;; 0DA2;SINHALA LETTER ALPAPRAANA JAYANNA;Lo;0;L;;;;;N;;;;; 0DA3;SINHALA LETTER MAHAAPRAANA JAYANNA;Lo;0;L;;;;;N;;;;; 0DA4;SINHALA LETTER TAALUJA NAASIKYAYA;Lo;0;L;;;;;N;;;;; 0DA5;SINHALA LETTER TAALUJA SANYOOGA NAAKSIKYAYA;Lo;0;L;;;;;N;;;;; 0DA6;SINHALA LETTER SANYAKA JAYANNA;Lo;0;L;;;;;N;;;;; 0DA7;SINHALA LETTER ALPAPRAANA TTAYANNA;Lo;0;L;;;;;N;;;;; 0DA8;SINHALA LETTER MAHAAPRAANA TTAYANNA;Lo;0;L;;;;;N;;;;; 0DA9;SINHALA LETTER ALPAPRAANA DDAYANNA;Lo;0;L;;;;;N;;;;; 0DAA;SINHALA LETTER MAHAAPRAANA DDAYANNA;Lo;0;L;;;;;N;;;;; 0DAB;SINHALA LETTER MUURDHAJA NAYANNA;Lo;0;L;;;;;N;;;;; 0DAC;SINHALA LETTER SANYAKA DDAYANNA;Lo;0;L;;;;;N;;;;; 0DAD;SINHALA LETTER ALPAPRAANA TAYANNA;Lo;0;L;;;;;N;;;;; 0DAE;SINHALA LETTER MAHAAPRAANA TAYANNA;Lo;0;L;;;;;N;;;;; 0DAF;SINHALA LETTER ALPAPRAANA DAYANNA;Lo;0;L;;;;;N;;;;; 0DB0;SINHALA LETTER MAHAAPRAANA DAYANNA;Lo;0;L;;;;;N;;;;; 0DB1;SINHALA LETTER DANTAJA NAYANNA;Lo;0;L;;;;;N;;;;; 0DB3;SINHALA LETTER SANYAKA DAYANNA;Lo;0;L;;;;;N;;;;; 0DB4;SINHALA LETTER ALPAPRAANA PAYANNA;Lo;0;L;;;;;N;;;;; 0DB5;SINHALA LETTER MAHAAPRAANA PAYANNA;Lo;0;L;;;;;N;;;;; 0DB6;SINHALA LETTER ALPAPRAANA BAYANNA;Lo;0;L;;;;;N;;;;; 0DB7;SINHALA LETTER MAHAAPRAANA BAYANNA;Lo;0;L;;;;;N;;;;; 0DB8;SINHALA LETTER MAYANNA;Lo;0;L;;;;;N;;;;; 0DB9;SINHALA LETTER AMBA BAYANNA;Lo;0;L;;;;;N;;;;; 0DBA;SINHALA LETTER YAYANNA;Lo;0;L;;;;;N;;;;; 0DBB;SINHALA LETTER RAYANNA;Lo;0;L;;;;;N;;;;; 0DBD;SINHALA LETTER DANTAJA LAYANNA;Lo;0;L;;;;;N;;;;; 0DC0;SINHALA LETTER VAYANNA;Lo;0;L;;;;;N;;;;; 0DC1;SINHALA LETTER TAALUJA SAYANNA;Lo;0;L;;;;;N;;;;; 0DC2;SINHALA LETTER MUURDHAJA SAYANNA;Lo;0;L;;;;;N;;;;; 0DC3;SINHALA LETTER DANTAJA SAYANNA;Lo;0;L;;;;;N;;;;; 0DC4;SINHALA LETTER HAYANNA;Lo;0;L;;;;;N;;;;; 0DC5;SINHALA LETTER MUURDHAJA LAYANNA;Lo;0;L;;;;;N;;;;; 0DC6;SINHALA LETTER FAYANNA;Lo;0;L;;;;;N;;;;; 0DCA;SINHALA SIGN AL-LAKUNA;Mn;9;NSM;;;;;N;;;;; 0DCF;SINHALA VOWEL SIGN AELA-PILLA;Mc;0;L;;;;;N;;;;; 0DD0;SINHALA VOWEL SIGN KETTI AEDA-PILLA;Mc;0;L;;;;;N;;;;; 0DD1;SINHALA VOWEL SIGN DIGA AEDA-PILLA;Mc;0;L;;;;;N;;;;; 0DD2;SINHALA VOWEL SIGN KETTI IS-PILLA;Mn;0;NSM;;;;;N;;;;; 0DD3;SINHALA VOWEL SIGN DIGA IS-PILLA;Mn;0;NSM;;;;;N;;;;; 0DD4;SINHALA VOWEL SIGN KETTI PAA-PILLA;Mn;0;NSM;;;;;N;;;;; 0DD6;SINHALA VOWEL SIGN DIGA PAA-PILLA;Mn;0;NSM;;;;;N;;;;; 0DD8;SINHALA VOWEL SIGN GAETTA-PILLA;Mc;0;L;;;;;N;;;;; 0DD9;SINHALA VOWEL SIGN KOMBUVA;Mc;0;L;;;;;N;;;;; 0DDA;SINHALA VOWEL SIGN DIGA KOMBUVA;Mc;0;L;0DD9 0DCA;;;;N;;;;; 0DDB;SINHALA VOWEL SIGN KOMBU DEKA;Mc;0;L;;;;;N;;;;; 0DDC;SINHALA VOWEL SIGN KOMBUVA HAA AELA-PILLA;Mc;0;L;0DD9 0DCF;;;;N;;;;; 0DDD;SINHALA VOWEL SIGN KOMBUVA HAA DIGA AELA-PILLA;Mc;0;L;0DDC 0DCA;;;;N;;;;; 0DDE;SINHALA VOWEL SIGN KOMBUVA HAA GAYANUKITTA;Mc;0;L;0DD9 0DDF;;;;N;;;;; 0DDF;SINHALA VOWEL SIGN GAYANUKITTA;Mc;0;L;;;;;N;;;;; 0DF2;SINHALA VOWEL SIGN DIGA GAETTA-PILLA;Mc;0;L;;;;;N;;;;; 0DF3;SINHALA VOWEL SIGN DIGA GAYANUKITTA;Mc;0;L;;;;;N;;;;; 0DF4;SINHALA PUNCTUATION KUNDDALIYA;Po;0;L;;;;;N;;;;; 0E01;THAI CHARACTER KO KAI;Lo;0;L;;;;;N;THAI LETTER KO KAI;;;; 0E02;THAI CHARACTER KHO KHAI;Lo;0;L;;;;;N;THAI LETTER KHO KHAI;;;; 0E03;THAI CHARACTER KHO KHUAT;Lo;0;L;;;;;N;THAI LETTER KHO KHUAT;;;; 0E04;THAI CHARACTER KHO KHWAI;Lo;0;L;;;;;N;THAI LETTER KHO KHWAI;;;; 0E05;THAI CHARACTER KHO KHON;Lo;0;L;;;;;N;THAI LETTER KHO KHON;;;; 0E06;THAI CHARACTER KHO RAKHANG;Lo;0;L;;;;;N;THAI LETTER KHO RAKHANG;;;; 0E07;THAI CHARACTER NGO NGU;Lo;0;L;;;;;N;THAI LETTER NGO NGU;;;; 0E08;THAI CHARACTER CHO CHAN;Lo;0;L;;;;;N;THAI LETTER CHO CHAN;;;; 0E09;THAI CHARACTER CHO CHING;Lo;0;L;;;;;N;THAI LETTER CHO CHING;;;; 0E0A;THAI CHARACTER CHO CHANG;Lo;0;L;;;;;N;THAI LETTER CHO CHANG;;;; 0E0B;THAI CHARACTER SO SO;Lo;0;L;;;;;N;THAI LETTER SO SO;;;; 0E0C;THAI CHARACTER CHO CHOE;Lo;0;L;;;;;N;THAI LETTER CHO CHOE;;;; 0E0D;THAI CHARACTER YO YING;Lo;0;L;;;;;N;THAI LETTER YO YING;;;; 0E0E;THAI CHARACTER DO CHADA;Lo;0;L;;;;;N;THAI LETTER DO CHADA;;;; 0E0F;THAI CHARACTER TO PATAK;Lo;0;L;;;;;N;THAI LETTER TO PATAK;;;; 0E10;THAI CHARACTER THO THAN;Lo;0;L;;;;;N;THAI LETTER THO THAN;;;; 0E11;THAI CHARACTER THO NANGMONTHO;Lo;0;L;;;;;N;THAI LETTER THO NANGMONTHO;;;; 0E12;THAI CHARACTER THO PHUTHAO;Lo;0;L;;;;;N;THAI LETTER THO PHUTHAO;;;; 0E13;THAI CHARACTER NO NEN;Lo;0;L;;;;;N;THAI LETTER NO NEN;;;; 0E14;THAI CHARACTER DO DEK;Lo;0;L;;;;;N;THAI LETTER DO DEK;;;; 0E15;THAI CHARACTER TO TAO;Lo;0;L;;;;;N;THAI LETTER TO TAO;;;; 0E16;THAI CHARACTER THO THUNG;Lo;0;L;;;;;N;THAI LETTER THO THUNG;;;; 0E17;THAI CHARACTER THO THAHAN;Lo;0;L;;;;;N;THAI LETTER THO THAHAN;;;; 0E18;THAI CHARACTER THO THONG;Lo;0;L;;;;;N;THAI LETTER THO THONG;;;; 0E19;THAI CHARACTER NO NU;Lo;0;L;;;;;N;THAI LETTER NO NU;;;; 0E1A;THAI CHARACTER BO BAIMAI;Lo;0;L;;;;;N;THAI LETTER BO BAIMAI;;;; 0E1B;THAI CHARACTER PO PLA;Lo;0;L;;;;;N;THAI LETTER PO PLA;;;; 0E1C;THAI CHARACTER PHO PHUNG;Lo;0;L;;;;;N;THAI LETTER PHO PHUNG;;;; 0E1D;THAI CHARACTER FO FA;Lo;0;L;;;;;N;THAI LETTER FO FA;;;; 0E1E;THAI CHARACTER PHO PHAN;Lo;0;L;;;;;N;THAI LETTER PHO PHAN;;;; 0E1F;THAI CHARACTER FO FAN;Lo;0;L;;;;;N;THAI LETTER FO FAN;;;; 0E20;THAI CHARACTER PHO SAMPHAO;Lo;0;L;;;;;N;THAI LETTER PHO SAMPHAO;;;; 0E21;THAI CHARACTER MO MA;Lo;0;L;;;;;N;THAI LETTER MO MA;;;; 0E22;THAI CHARACTER YO YAK;Lo;0;L;;;;;N;THAI LETTER YO YAK;;;; 0E23;THAI CHARACTER RO RUA;Lo;0;L;;;;;N;THAI LETTER RO RUA;;;; 0E24;THAI CHARACTER RU;Lo;0;L;;;;;N;THAI LETTER RU;;;; 0E25;THAI CHARACTER LO LING;Lo;0;L;;;;;N;THAI LETTER LO LING;;;; 0E26;THAI CHARACTER LU;Lo;0;L;;;;;N;THAI LETTER LU;;;; 0E27;THAI CHARACTER WO WAEN;Lo;0;L;;;;;N;THAI LETTER WO WAEN;;;; 0E28;THAI CHARACTER SO SALA;Lo;0;L;;;;;N;THAI LETTER SO SALA;;;; 0E29;THAI CHARACTER SO RUSI;Lo;0;L;;;;;N;THAI LETTER SO RUSI;;;; 0E2A;THAI CHARACTER SO SUA;Lo;0;L;;;;;N;THAI LETTER SO SUA;;;; 0E2B;THAI CHARACTER HO HIP;Lo;0;L;;;;;N;THAI LETTER HO HIP;;;; 0E2C;THAI CHARACTER LO CHULA;Lo;0;L;;;;;N;THAI LETTER LO CHULA;;;; 0E2D;THAI CHARACTER O ANG;Lo;0;L;;;;;N;THAI LETTER O ANG;;;; 0E2E;THAI CHARACTER HO NOKHUK;Lo;0;L;;;;;N;THAI LETTER HO NOK HUK;;;; 0E2F;THAI CHARACTER PAIYANNOI;Lo;0;L;;;;;N;THAI PAI YAN NOI;paiyan noi;;; 0E30;THAI CHARACTER SARA A;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA A;;;; 0E31;THAI CHARACTER MAI HAN-AKAT;Mn;0;NSM;;;;;N;THAI VOWEL SIGN MAI HAN-AKAT;;;; 0E32;THAI CHARACTER SARA AA;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA AA;;;; 0E33;THAI CHARACTER SARA AM;Lo;0;L; 0E4D 0E32;;;;N;THAI VOWEL SIGN SARA AM;;;; 0E34;THAI CHARACTER SARA I;Mn;0;NSM;;;;;N;THAI VOWEL SIGN SARA I;;;; 0E35;THAI CHARACTER SARA II;Mn;0;NSM;;;;;N;THAI VOWEL SIGN SARA II;;;; 0E36;THAI CHARACTER SARA UE;Mn;0;NSM;;;;;N;THAI VOWEL SIGN SARA UE;;;; 0E37;THAI CHARACTER SARA UEE;Mn;0;NSM;;;;;N;THAI VOWEL SIGN SARA UEE;sara uue;;; 0E38;THAI CHARACTER SARA U;Mn;103;NSM;;;;;N;THAI VOWEL SIGN SARA U;;;; 0E39;THAI CHARACTER SARA UU;Mn;103;NSM;;;;;N;THAI VOWEL SIGN SARA UU;;;; 0E3A;THAI CHARACTER PHINTHU;Mn;9;NSM;;;;;N;THAI VOWEL SIGN PHINTHU;;;; 0E3F;THAI CURRENCY SYMBOL BAHT;Sc;0;ET;;;;;N;THAI BAHT SIGN;;;; 0E40;THAI CHARACTER SARA E;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA E;;;; 0E41;THAI CHARACTER SARA AE;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA AE;;;; 0E42;THAI CHARACTER SARA O;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA O;;;; 0E43;THAI CHARACTER SARA AI MAIMUAN;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA MAI MUAN;sara ai mai muan;;; 0E44;THAI CHARACTER SARA AI MAIMALAI;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA MAI MALAI;sara ai mai malai;;; 0E45;THAI CHARACTER LAKKHANGYAO;Lo;0;L;;;;;N;THAI LAK KHANG YAO;lakkhang yao;;; 0E46;THAI CHARACTER MAIYAMOK;Lm;0;L;;;;;N;THAI MAI YAMOK;mai yamok;;; 0E47;THAI CHARACTER MAITAIKHU;Mn;0;NSM;;;;;N;THAI VOWEL SIGN MAI TAI KHU;mai taikhu;;; 0E48;THAI CHARACTER MAI EK;Mn;107;NSM;;;;;N;THAI TONE MAI EK;;;; 0E49;THAI CHARACTER MAI THO;Mn;107;NSM;;;;;N;THAI TONE MAI THO;;;; 0E4A;THAI CHARACTER MAI TRI;Mn;107;NSM;;;;;N;THAI TONE MAI TRI;;;; 0E4B;THAI CHARACTER MAI CHATTAWA;Mn;107;NSM;;;;;N;THAI TONE MAI CHATTAWA;;;; 0E4C;THAI CHARACTER THANTHAKHAT;Mn;0;NSM;;;;;N;THAI THANTHAKHAT;;;; 0E4D;THAI CHARACTER NIKHAHIT;Mn;0;NSM;;;;;N;THAI NIKKHAHIT;nikkhahit;;; 0E4E;THAI CHARACTER YAMAKKAN;Mn;0;NSM;;;;;N;THAI YAMAKKAN;;;; 0E4F;THAI CHARACTER FONGMAN;Po;0;L;;;;;N;THAI FONGMAN;;;; 0E50;THAI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 0E51;THAI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 0E52;THAI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 0E53;THAI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 0E54;THAI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 0E55;THAI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 0E56;THAI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 0E57;THAI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 0E58;THAI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 0E59;THAI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0E5A;THAI CHARACTER ANGKHANKHU;Po;0;L;;;;;N;THAI ANGKHANKHU;;;; 0E5B;THAI CHARACTER KHOMUT;Po;0;L;;;;;N;THAI KHOMUT;;;; 0E81;LAO LETTER KO;Lo;0;L;;;;;N;;;;; 0E82;LAO LETTER KHO SUNG;Lo;0;L;;;;;N;;;;; 0E84;LAO LETTER KHO TAM;Lo;0;L;;;;;N;;;;; 0E87;LAO LETTER NGO;Lo;0;L;;;;;N;;;;; 0E88;LAO LETTER CO;Lo;0;L;;;;;N;;;;; 0E8A;LAO LETTER SO TAM;Lo;0;L;;;;;N;;;;; 0E8D;LAO LETTER NYO;Lo;0;L;;;;;N;;;;; 0E94;LAO LETTER DO;Lo;0;L;;;;;N;;;;; 0E95;LAO LETTER TO;Lo;0;L;;;;;N;;;;; 0E96;LAO LETTER THO SUNG;Lo;0;L;;;;;N;;;;; 0E97;LAO LETTER THO TAM;Lo;0;L;;;;;N;;;;; 0E99;LAO LETTER NO;Lo;0;L;;;;;N;;;;; 0E9A;LAO LETTER BO;Lo;0;L;;;;;N;;;;; 0E9B;LAO LETTER PO;Lo;0;L;;;;;N;;;;; 0E9C;LAO LETTER PHO SUNG;Lo;0;L;;;;;N;;;;; 0E9D;LAO LETTER FO TAM;Lo;0;L;;;;;N;;;;; 0E9E;LAO LETTER PHO TAM;Lo;0;L;;;;;N;;;;; 0E9F;LAO LETTER FO SUNG;Lo;0;L;;;;;N;;;;; 0EA1;LAO LETTER MO;Lo;0;L;;;;;N;;;;; 0EA2;LAO LETTER YO;Lo;0;L;;;;;N;;;;; 0EA3;LAO LETTER LO LING;Lo;0;L;;;;;N;;;;; 0EA5;LAO LETTER LO LOOT;Lo;0;L;;;;;N;;;;; 0EA7;LAO LETTER WO;Lo;0;L;;;;;N;;;;; 0EAA;LAO LETTER SO SUNG;Lo;0;L;;;;;N;;;;; 0EAB;LAO LETTER HO SUNG;Lo;0;L;;;;;N;;;;; 0EAD;LAO LETTER O;Lo;0;L;;;;;N;;;;; 0EAE;LAO LETTER HO TAM;Lo;0;L;;;;;N;;;;; 0EAF;LAO ELLIPSIS;Lo;0;L;;;;;N;;;;; 0EB0;LAO VOWEL SIGN A;Lo;0;L;;;;;N;;;;; 0EB1;LAO VOWEL SIGN MAI KAN;Mn;0;NSM;;;;;N;;;;; 0EB2;LAO VOWEL SIGN AA;Lo;0;L;;;;;N;;;;; 0EB3;LAO VOWEL SIGN AM;Lo;0;L; 0ECD 0EB2;;;;N;;;;; 0EB4;LAO VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 0EB5;LAO VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; 0EB6;LAO VOWEL SIGN Y;Mn;0;NSM;;;;;N;;;;; 0EB7;LAO VOWEL SIGN YY;Mn;0;NSM;;;;;N;;;;; 0EB8;LAO VOWEL SIGN U;Mn;118;NSM;;;;;N;;;;; 0EB9;LAO VOWEL SIGN UU;Mn;118;NSM;;;;;N;;;;; 0EBB;LAO VOWEL SIGN MAI KON;Mn;0;NSM;;;;;N;;;;; 0EBC;LAO SEMIVOWEL SIGN LO;Mn;0;NSM;;;;;N;;;;; 0EBD;LAO SEMIVOWEL SIGN NYO;Lo;0;L;;;;;N;;;;; 0EC0;LAO VOWEL SIGN E;Lo;0;L;;;;;N;;;;; 0EC1;LAO VOWEL SIGN EI;Lo;0;L;;;;;N;;;;; 0EC2;LAO VOWEL SIGN O;Lo;0;L;;;;;N;;;;; 0EC3;LAO VOWEL SIGN AY;Lo;0;L;;;;;N;;;;; 0EC4;LAO VOWEL SIGN AI;Lo;0;L;;;;;N;;;;; 0EC6;LAO KO LA;Lm;0;L;;;;;N;;;;; 0EC8;LAO TONE MAI EK;Mn;122;NSM;;;;;N;;;;; 0EC9;LAO TONE MAI THO;Mn;122;NSM;;;;;N;;;;; 0ECA;LAO TONE MAI TI;Mn;122;NSM;;;;;N;;;;; 0ECB;LAO TONE MAI CATAWA;Mn;122;NSM;;;;;N;;;;; 0ECC;LAO CANCELLATION MARK;Mn;0;NSM;;;;;N;;;;; 0ECD;LAO NIGGAHITA;Mn;0;NSM;;;;;N;;;;; 0ED0;LAO DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 0ED1;LAO DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 0ED2;LAO DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 0ED3;LAO DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 0ED4;LAO DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 0ED5;LAO DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 0ED6;LAO DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 0ED7;LAO DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 0ED8;LAO DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 0ED9;LAO DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0EDC;LAO HO NO;Lo;0;L; 0EAB 0E99;;;;N;;;;; 0EDD;LAO HO MO;Lo;0;L; 0EAB 0EA1;;;;N;;;;; 0F00;TIBETAN SYLLABLE OM;Lo;0;L;;;;;N;;;;; 0F01;TIBETAN MARK GTER YIG MGO TRUNCATED A;So;0;L;;;;;N;;ter yik go a thung;;; 0F02;TIBETAN MARK GTER YIG MGO -UM RNAM BCAD MA;So;0;L;;;;;N;;ter yik go wum nam chey ma;;; 0F03;TIBETAN MARK GTER YIG MGO -UM GTER TSHEG MA;So;0;L;;;;;N;;ter yik go wum ter tsek ma;;; 0F04;TIBETAN MARK INITIAL YIG MGO MDUN MA;Po;0;L;;;;;N;TIBETAN SINGLE ORNAMENT;yik go dun ma;;; 0F05;TIBETAN MARK CLOSING YIG MGO SGAB MA;Po;0;L;;;;;N;;yik go kab ma;;; 0F06;TIBETAN MARK CARET YIG MGO PHUR SHAD MA;Po;0;L;;;;;N;;yik go pur shey ma;;; 0F07;TIBETAN MARK YIG MGO TSHEG SHAD MA;Po;0;L;;;;;N;;yik go tsek shey ma;;; 0F08;TIBETAN MARK SBRUL SHAD;Po;0;L;;;;;N;TIBETAN RGYANSHAD;drul shey;;; 0F09;TIBETAN MARK BSKUR YIG MGO;Po;0;L;;;;;N;;kur yik go;;; 0F0A;TIBETAN MARK BKA- SHOG YIG MGO;Po;0;L;;;;;N;;ka sho yik go;;; 0F0B;TIBETAN MARK INTERSYLLABIC TSHEG;Po;0;L;;;;;N;TIBETAN TSEG;tsek;;; 0F0C;TIBETAN MARK DELIMITER TSHEG BSTAR;Po;0;L; 0F0B;;;;N;;tsek tar;;; 0F0D;TIBETAN MARK SHAD;Po;0;L;;;;;N;TIBETAN SHAD;shey;;; 0F0E;TIBETAN MARK NYIS SHAD;Po;0;L;;;;;N;TIBETAN DOUBLE SHAD;nyi shey;;; 0F0F;TIBETAN MARK TSHEG SHAD;Po;0;L;;;;;N;;tsek shey;;; 0F10;TIBETAN MARK NYIS TSHEG SHAD;Po;0;L;;;;;N;;nyi tsek shey;;; 0F11;TIBETAN MARK RIN CHEN SPUNGS SHAD;Po;0;L;;;;;N;TIBETAN RINCHANPHUNGSHAD;rinchen pung shey;;; 0F12;TIBETAN MARK RGYA GRAM SHAD;Po;0;L;;;;;N;;gya tram shey;;; 0F13;TIBETAN MARK CARET -DZUD RTAGS ME LONG CAN;So;0;L;;;;;N;;dzu ta me long chen;;; 0F14;TIBETAN MARK GTER TSHEG;So;0;L;;;;;N;TIBETAN COMMA;ter tsek;;; 0F15;TIBETAN LOGOTYPE SIGN CHAD RTAGS;So;0;L;;;;;N;;che ta;;; 0F16;TIBETAN LOGOTYPE SIGN LHAG RTAGS;So;0;L;;;;;N;;hlak ta;;; 0F17;TIBETAN ASTROLOGICAL SIGN SGRA GCAN -CHAR RTAGS;So;0;L;;;;;N;;trachen char ta;;; 0F18;TIBETAN ASTROLOGICAL SIGN -KHYUD PA;Mn;220;NSM;;;;;N;;kyu pa;;; 0F19;TIBETAN ASTROLOGICAL SIGN SDONG TSHUGS;Mn;220;NSM;;;;;N;;dong tsu;;; 0F1A;TIBETAN SIGN RDEL DKAR GCIG;So;0;L;;;;;N;;deka chig;;; 0F1B;TIBETAN SIGN RDEL DKAR GNYIS;So;0;L;;;;;N;;deka nyi;;; 0F1C;TIBETAN SIGN RDEL DKAR GSUM;So;0;L;;;;;N;;deka sum;;; 0F1D;TIBETAN SIGN RDEL NAG GCIG;So;0;L;;;;;N;;dena chig;;; 0F1E;TIBETAN SIGN RDEL NAG GNYIS;So;0;L;;;;;N;;dena nyi;;; 0F1F;TIBETAN SIGN RDEL DKAR RDEL NAG;So;0;L;;;;;N;;deka dena;;; 0F20;TIBETAN DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 0F21;TIBETAN DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 0F22;TIBETAN DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 0F23;TIBETAN DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 0F24;TIBETAN DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 0F25;TIBETAN DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 0F26;TIBETAN DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 0F27;TIBETAN DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 0F28;TIBETAN DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 0F29;TIBETAN DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0F2A;TIBETAN DIGIT HALF ONE;No;0;L;;;;1/2;N;;;;; 0F2B;TIBETAN DIGIT HALF TWO;No;0;L;;;;3/2;N;;;;; 0F2C;TIBETAN DIGIT HALF THREE;No;0;L;;;;5/2;N;;;;; 0F2D;TIBETAN DIGIT HALF FOUR;No;0;L;;;;7/2;N;;;;; 0F2E;TIBETAN DIGIT HALF FIVE;No;0;L;;;;9/2;N;;;;; 0F2F;TIBETAN DIGIT HALF SIX;No;0;L;;;;11/2;N;;;;; 0F30;TIBETAN DIGIT HALF SEVEN;No;0;L;;;;13/2;N;;;;; 0F31;TIBETAN DIGIT HALF EIGHT;No;0;L;;;;15/2;N;;;;; 0F32;TIBETAN DIGIT HALF NINE;No;0;L;;;;17/2;N;;;;; 0F33;TIBETAN DIGIT HALF ZERO;No;0;L;;;;-1/2;N;;;;; 0F34;TIBETAN MARK BSDUS RTAGS;So;0;L;;;;;N;;du ta;;; 0F35;TIBETAN MARK NGAS BZUNG NYI ZLA;Mn;220;NSM;;;;;N;TIBETAN HONORIFIC UNDER RING;nge zung nyi da;;; 0F36;TIBETAN MARK CARET -DZUD RTAGS BZHI MIG CAN;So;0;L;;;;;N;;dzu ta shi mig chen;;; 0F37;TIBETAN MARK NGAS BZUNG SGOR RTAGS;Mn;220;NSM;;;;;N;TIBETAN UNDER RING;nge zung gor ta;;; 0F38;TIBETAN MARK CHE MGO;So;0;L;;;;;N;;che go;;; 0F39;TIBETAN MARK TSA -PHRU;Mn;216;NSM;;;;;N;TIBETAN LENITION MARK;tsa tru;;; 0F3A;TIBETAN MARK GUG RTAGS GYON;Ps;0;ON;;;;;N;;gug ta yun;;; 0F3B;TIBETAN MARK GUG RTAGS GYAS;Pe;0;ON;;;;;N;;gug ta ye;;; 0F3C;TIBETAN MARK ANG KHANG GYON;Ps;0;ON;;;;;N;TIBETAN LEFT BRACE;ang kang yun;;; 0F3D;TIBETAN MARK ANG KHANG GYAS;Pe;0;ON;;;;;N;TIBETAN RIGHT BRACE;ang kang ye;;; 0F3E;TIBETAN SIGN YAR TSHES;Mc;0;L;;;;;N;;yar tse;;; 0F3F;TIBETAN SIGN MAR TSHES;Mc;0;L;;;;;N;;mar tse;;; 0F40;TIBETAN LETTER KA;Lo;0;L;;;;;N;;;;; 0F41;TIBETAN LETTER KHA;Lo;0;L;;;;;N;;;;; 0F42;TIBETAN LETTER GA;Lo;0;L;;;;;N;;;;; 0F43;TIBETAN LETTER GHA;Lo;0;L;0F42 0FB7;;;;N;;;;; 0F44;TIBETAN LETTER NGA;Lo;0;L;;;;;N;;;;; 0F45;TIBETAN LETTER CA;Lo;0;L;;;;;N;;;;; 0F46;TIBETAN LETTER CHA;Lo;0;L;;;;;N;;;;; 0F47;TIBETAN LETTER JA;Lo;0;L;;;;;N;;;;; 0F49;TIBETAN LETTER NYA;Lo;0;L;;;;;N;;;;; 0F4A;TIBETAN LETTER TTA;Lo;0;L;;;;;N;TIBETAN LETTER REVERSED TA;;;; 0F4B;TIBETAN LETTER TTHA;Lo;0;L;;;;;N;TIBETAN LETTER REVERSED THA;;;; 0F4C;TIBETAN LETTER DDA;Lo;0;L;;;;;N;TIBETAN LETTER REVERSED DA;;;; 0F4D;TIBETAN LETTER DDHA;Lo;0;L;0F4C 0FB7;;;;N;;;;; 0F4E;TIBETAN LETTER NNA;Lo;0;L;;;;;N;TIBETAN LETTER REVERSED NA;;;; 0F4F;TIBETAN LETTER TA;Lo;0;L;;;;;N;;;;; 0F50;TIBETAN LETTER THA;Lo;0;L;;;;;N;;;;; 0F51;TIBETAN LETTER DA;Lo;0;L;;;;;N;;;;; 0F52;TIBETAN LETTER DHA;Lo;0;L;0F51 0FB7;;;;N;;;;; 0F53;TIBETAN LETTER NA;Lo;0;L;;;;;N;;;;; 0F54;TIBETAN LETTER PA;Lo;0;L;;;;;N;;;;; 0F55;TIBETAN LETTER PHA;Lo;0;L;;;;;N;;;;; 0F56;TIBETAN LETTER BA;Lo;0;L;;;;;N;;;;; 0F57;TIBETAN LETTER BHA;Lo;0;L;0F56 0FB7;;;;N;;;;; 0F58;TIBETAN LETTER MA;Lo;0;L;;;;;N;;;;; 0F59;TIBETAN LETTER TSA;Lo;0;L;;;;;N;;;;; 0F5A;TIBETAN LETTER TSHA;Lo;0;L;;;;;N;;;;; 0F5B;TIBETAN LETTER DZA;Lo;0;L;;;;;N;;;;; 0F5C;TIBETAN LETTER DZHA;Lo;0;L;0F5B 0FB7;;;;N;;;;; 0F5D;TIBETAN LETTER WA;Lo;0;L;;;;;N;;;;; 0F5E;TIBETAN LETTER ZHA;Lo;0;L;;;;;N;;;;; 0F5F;TIBETAN LETTER ZA;Lo;0;L;;;;;N;;;;; 0F60;TIBETAN LETTER -A;Lo;0;L;;;;;N;TIBETAN LETTER AA;;;; 0F61;TIBETAN LETTER YA;Lo;0;L;;;;;N;;;;; 0F62;TIBETAN LETTER RA;Lo;0;L;;;;;N;;*;;; 0F63;TIBETAN LETTER LA;Lo;0;L;;;;;N;;;;; 0F64;TIBETAN LETTER SHA;Lo;0;L;;;;;N;;;;; 0F65;TIBETAN LETTER SSA;Lo;0;L;;;;;N;TIBETAN LETTER REVERSED SHA;;;; 0F66;TIBETAN LETTER SA;Lo;0;L;;;;;N;;;;; 0F67;TIBETAN LETTER HA;Lo;0;L;;;;;N;;;;; 0F68;TIBETAN LETTER A;Lo;0;L;;;;;N;;;;; 0F69;TIBETAN LETTER KSSA;Lo;0;L;0F40 0FB5;;;;N;;;;; 0F6A;TIBETAN LETTER FIXED-FORM RA;Lo;0;L;;;;;N;;*;;; 0F71;TIBETAN VOWEL SIGN AA;Mn;129;NSM;;;;;N;;;;; 0F72;TIBETAN VOWEL SIGN I;Mn;130;NSM;;;;;N;;;;; 0F73;TIBETAN VOWEL SIGN II;Mn;0;NSM;0F71 0F72;;;;N;;;;; 0F74;TIBETAN VOWEL SIGN U;Mn;132;NSM;;;;;N;;;;; 0F75;TIBETAN VOWEL SIGN UU;Mn;0;NSM;0F71 0F74;;;;N;;;;; 0F76;TIBETAN VOWEL SIGN VOCALIC R;Mn;0;NSM;0FB2 0F80;;;;N;;;;; 0F77;TIBETAN VOWEL SIGN VOCALIC RR;Mn;0;NSM; 0FB2 0F81;;;;N;;;;; 0F78;TIBETAN VOWEL SIGN VOCALIC L;Mn;0;NSM;0FB3 0F80;;;;N;;;;; 0F79;TIBETAN VOWEL SIGN VOCALIC LL;Mn;0;NSM; 0FB3 0F81;;;;N;;;;; 0F7A;TIBETAN VOWEL SIGN E;Mn;130;NSM;;;;;N;;;;; 0F7B;TIBETAN VOWEL SIGN EE;Mn;130;NSM;;;;;N;TIBETAN VOWEL SIGN AI;;;; 0F7C;TIBETAN VOWEL SIGN O;Mn;130;NSM;;;;;N;;;;; 0F7D;TIBETAN VOWEL SIGN OO;Mn;130;NSM;;;;;N;TIBETAN VOWEL SIGN AU;;;; 0F7E;TIBETAN SIGN RJES SU NGA RO;Mn;0;NSM;;;;;N;TIBETAN ANUSVARA;je su nga ro;;; 0F7F;TIBETAN SIGN RNAM BCAD;Mc;0;L;;;;;N;TIBETAN VISARGA;nam chey;;; 0F80;TIBETAN VOWEL SIGN REVERSED I;Mn;130;NSM;;;;;N;TIBETAN VOWEL SIGN SHORT I;;;; 0F81;TIBETAN VOWEL SIGN REVERSED II;Mn;0;NSM;0F71 0F80;;;;N;;;;; 0F82;TIBETAN SIGN NYI ZLA NAA DA;Mn;230;NSM;;;;;N;TIBETAN CANDRABINDU WITH ORNAMENT;nyi da na da;;; 0F83;TIBETAN SIGN SNA LDAN;Mn;230;NSM;;;;;N;TIBETAN CANDRABINDU;nan de;;; 0F84;TIBETAN MARK HALANTA;Mn;9;NSM;;;;;N;TIBETAN VIRAMA;;;; 0F85;TIBETAN MARK PALUTA;Po;0;L;;;;;N;TIBETAN CHUCHENYIGE;;;; 0F86;TIBETAN SIGN LCI RTAGS;Mn;230;NSM;;;;;N;;ji ta;;; 0F87;TIBETAN SIGN YANG RTAGS;Mn;230;NSM;;;;;N;;yang ta;;; 0F88;TIBETAN SIGN LCE TSA CAN;Lo;0;L;;;;;N;;che tsa chen;;; 0F89;TIBETAN SIGN MCHU CAN;Lo;0;L;;;;;N;;chu chen;;; 0F8A;TIBETAN SIGN GRU CAN RGYINGS;Lo;0;L;;;;;N;;tru chen ging;;; 0F8B;TIBETAN SIGN GRU MED RGYINGS;Lo;0;L;;;;;N;;tru me ging;;; 0F90;TIBETAN SUBJOINED LETTER KA;Mn;0;NSM;;;;;N;;;;; 0F91;TIBETAN SUBJOINED LETTER KHA;Mn;0;NSM;;;;;N;;;;; 0F92;TIBETAN SUBJOINED LETTER GA;Mn;0;NSM;;;;;N;;;;; 0F93;TIBETAN SUBJOINED LETTER GHA;Mn;0;NSM;0F92 0FB7;;;;N;;;;; 0F94;TIBETAN SUBJOINED LETTER NGA;Mn;0;NSM;;;;;N;;;;; 0F95;TIBETAN SUBJOINED LETTER CA;Mn;0;NSM;;;;;N;;;;; 0F96;TIBETAN SUBJOINED LETTER CHA;Mn;0;NSM;;;;;N;;;;; 0F97;TIBETAN SUBJOINED LETTER JA;Mn;0;NSM;;;;;N;;;;; 0F99;TIBETAN SUBJOINED LETTER NYA;Mn;0;NSM;;;;;N;;;;; 0F9A;TIBETAN SUBJOINED LETTER TTA;Mn;0;NSM;;;;;N;;;;; 0F9B;TIBETAN SUBJOINED LETTER TTHA;Mn;0;NSM;;;;;N;;;;; 0F9C;TIBETAN SUBJOINED LETTER DDA;Mn;0;NSM;;;;;N;;;;; 0F9D;TIBETAN SUBJOINED LETTER DDHA;Mn;0;NSM;0F9C 0FB7;;;;N;;;;; 0F9E;TIBETAN SUBJOINED LETTER NNA;Mn;0;NSM;;;;;N;;;;; 0F9F;TIBETAN SUBJOINED LETTER TA;Mn;0;NSM;;;;;N;;;;; 0FA0;TIBETAN SUBJOINED LETTER THA;Mn;0;NSM;;;;;N;;;;; 0FA1;TIBETAN SUBJOINED LETTER DA;Mn;0;NSM;;;;;N;;;;; 0FA2;TIBETAN SUBJOINED LETTER DHA;Mn;0;NSM;0FA1 0FB7;;;;N;;;;; 0FA3;TIBETAN SUBJOINED LETTER NA;Mn;0;NSM;;;;;N;;;;; 0FA4;TIBETAN SUBJOINED LETTER PA;Mn;0;NSM;;;;;N;;;;; 0FA5;TIBETAN SUBJOINED LETTER PHA;Mn;0;NSM;;;;;N;;;;; 0FA6;TIBETAN SUBJOINED LETTER BA;Mn;0;NSM;;;;;N;;;;; 0FA7;TIBETAN SUBJOINED LETTER BHA;Mn;0;NSM;0FA6 0FB7;;;;N;;;;; 0FA8;TIBETAN SUBJOINED LETTER MA;Mn;0;NSM;;;;;N;;;;; 0FA9;TIBETAN SUBJOINED LETTER TSA;Mn;0;NSM;;;;;N;;;;; 0FAA;TIBETAN SUBJOINED LETTER TSHA;Mn;0;NSM;;;;;N;;;;; 0FAB;TIBETAN SUBJOINED LETTER DZA;Mn;0;NSM;;;;;N;;;;; 0FAC;TIBETAN SUBJOINED LETTER DZHA;Mn;0;NSM;0FAB 0FB7;;;;N;;;;; 0FAD;TIBETAN SUBJOINED LETTER WA;Mn;0;NSM;;;;;N;;*;;; 0FAE;TIBETAN SUBJOINED LETTER ZHA;Mn;0;NSM;;;;;N;;;;; 0FAF;TIBETAN SUBJOINED LETTER ZA;Mn;0;NSM;;;;;N;;;;; 0FB0;TIBETAN SUBJOINED LETTER -A;Mn;0;NSM;;;;;N;;;;; 0FB1;TIBETAN SUBJOINED LETTER YA;Mn;0;NSM;;;;;N;;*;;; 0FB2;TIBETAN SUBJOINED LETTER RA;Mn;0;NSM;;;;;N;;*;;; 0FB3;TIBETAN SUBJOINED LETTER LA;Mn;0;NSM;;;;;N;;;;; 0FB4;TIBETAN SUBJOINED LETTER SHA;Mn;0;NSM;;;;;N;;;;; 0FB5;TIBETAN SUBJOINED LETTER SSA;Mn;0;NSM;;;;;N;;;;; 0FB6;TIBETAN SUBJOINED LETTER SA;Mn;0;NSM;;;;;N;;;;; 0FB7;TIBETAN SUBJOINED LETTER HA;Mn;0;NSM;;;;;N;;;;; 0FB8;TIBETAN SUBJOINED LETTER A;Mn;0;NSM;;;;;N;;;;; 0FB9;TIBETAN SUBJOINED LETTER KSSA;Mn;0;NSM;0F90 0FB5;;;;N;;;;; 0FBA;TIBETAN SUBJOINED LETTER FIXED-FORM WA;Mn;0;NSM;;;;;N;;*;;; 0FBB;TIBETAN SUBJOINED LETTER FIXED-FORM YA;Mn;0;NSM;;;;;N;;*;;; 0FBC;TIBETAN SUBJOINED LETTER FIXED-FORM RA;Mn;0;NSM;;;;;N;;*;;; 0FBE;TIBETAN KU RU KHA;So;0;L;;;;;N;;kuruka;;; 0FBF;TIBETAN KU RU KHA BZHI MIG CAN;So;0;L;;;;;N;;kuruka shi mik chen;;; 0FC0;TIBETAN CANTILLATION SIGN HEAVY BEAT;So;0;L;;;;;N;;;;; 0FC1;TIBETAN CANTILLATION SIGN LIGHT BEAT;So;0;L;;;;;N;;;;; 0FC2;TIBETAN CANTILLATION SIGN CANG TE-U;So;0;L;;;;;N;;chang tyu;;; 0FC3;TIBETAN CANTILLATION SIGN SBUB -CHAL;So;0;L;;;;;N;;bub chey;;; 0FC4;TIBETAN SYMBOL DRIL BU;So;0;L;;;;;N;;drilbu;;; 0FC5;TIBETAN SYMBOL RDO RJE;So;0;L;;;;;N;;dorje;;; 0FC6;TIBETAN SYMBOL PADMA GDAN;Mn;220;NSM;;;;;N;;pema den;;; 0FC7;TIBETAN SYMBOL RDO RJE RGYA GRAM;So;0;L;;;;;N;;dorje gya dram;;; 0FC8;TIBETAN SYMBOL PHUR PA;So;0;L;;;;;N;;phurba;;; 0FC9;TIBETAN SYMBOL NOR BU;So;0;L;;;;;N;;norbu;;; 0FCA;TIBETAN SYMBOL NOR BU NYIS -KHYIL;So;0;L;;;;;N;;norbu nyi khyi;;; 0FCB;TIBETAN SYMBOL NOR BU GSUM -KHYIL;So;0;L;;;;;N;;norbu sum khyi;;; 0FCC;TIBETAN SYMBOL NOR BU BZHI -KHYIL;So;0;L;;;;;N;;norbu shi khyi;;; 0FCF;TIBETAN SIGN RDEL NAG GSUM;So;0;L;;;;;N;;dena sum;;; 1000;MYANMAR LETTER KA;Lo;0;L;;;;;N;;;;; 1001;MYANMAR LETTER KHA;Lo;0;L;;;;;N;;;;; 1002;MYANMAR LETTER GA;Lo;0;L;;;;;N;;;;; 1003;MYANMAR LETTER GHA;Lo;0;L;;;;;N;;;;; 1004;MYANMAR LETTER NGA;Lo;0;L;;;;;N;;;;; 1005;MYANMAR LETTER CA;Lo;0;L;;;;;N;;;;; 1006;MYANMAR LETTER CHA;Lo;0;L;;;;;N;;;;; 1007;MYANMAR LETTER JA;Lo;0;L;;;;;N;;;;; 1008;MYANMAR LETTER JHA;Lo;0;L;;;;;N;;;;; 1009;MYANMAR LETTER NYA;Lo;0;L;;;;;N;;;;; 100A;MYANMAR LETTER NNYA;Lo;0;L;;;;;N;;;;; 100B;MYANMAR LETTER TTA;Lo;0;L;;;;;N;;;;; 100C;MYANMAR LETTER TTHA;Lo;0;L;;;;;N;;;;; 100D;MYANMAR LETTER DDA;Lo;0;L;;;;;N;;;;; 100E;MYANMAR LETTER DDHA;Lo;0;L;;;;;N;;;;; 100F;MYANMAR LETTER NNA;Lo;0;L;;;;;N;;;;; 1010;MYANMAR LETTER TA;Lo;0;L;;;;;N;;;;; 1011;MYANMAR LETTER THA;Lo;0;L;;;;;N;;;;; 1012;MYANMAR LETTER DA;Lo;0;L;;;;;N;;;;; 1013;MYANMAR LETTER DHA;Lo;0;L;;;;;N;;;;; 1014;MYANMAR LETTER NA;Lo;0;L;;;;;N;;;;; 1015;MYANMAR LETTER PA;Lo;0;L;;;;;N;;;;; 1016;MYANMAR LETTER PHA;Lo;0;L;;;;;N;;;;; 1017;MYANMAR LETTER BA;Lo;0;L;;;;;N;;;;; 1018;MYANMAR LETTER BHA;Lo;0;L;;;;;N;;;;; 1019;MYANMAR LETTER MA;Lo;0;L;;;;;N;;;;; 101A;MYANMAR LETTER YA;Lo;0;L;;;;;N;;;;; 101B;MYANMAR LETTER RA;Lo;0;L;;;;;N;;;;; 101C;MYANMAR LETTER LA;Lo;0;L;;;;;N;;;;; 101D;MYANMAR LETTER WA;Lo;0;L;;;;;N;;;;; 101E;MYANMAR LETTER SA;Lo;0;L;;;;;N;;;;; 101F;MYANMAR LETTER HA;Lo;0;L;;;;;N;;;;; 1020;MYANMAR LETTER LLA;Lo;0;L;;;;;N;;;;; 1021;MYANMAR LETTER A;Lo;0;L;;;;;N;;;;; 1023;MYANMAR LETTER I;Lo;0;L;;;;;N;;;;; 1024;MYANMAR LETTER II;Lo;0;L;;;;;N;;;;; 1025;MYANMAR LETTER U;Lo;0;L;;;;;N;;;;; 1026;MYANMAR LETTER UU;Lo;0;L;1025 102E;;;;N;;;;; 1027;MYANMAR LETTER E;Lo;0;L;;;;;N;;;;; 1029;MYANMAR LETTER O;Lo;0;L;;;;;N;;;;; 102A;MYANMAR LETTER AU;Lo;0;L;;;;;N;;;;; 102C;MYANMAR VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 102D;MYANMAR VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 102E;MYANMAR VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; 102F;MYANMAR VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 1030;MYANMAR VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 1031;MYANMAR VOWEL SIGN E;Mc;0;L;;;;;N;;;;; 1032;MYANMAR VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; 1036;MYANMAR SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; 1037;MYANMAR SIGN DOT BELOW;Mn;7;NSM;;;;;N;;;;; 1038;MYANMAR SIGN VISARGA;Mc;0;L;;;;;N;;;;; 1039;MYANMAR SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 1040;MYANMAR DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 1041;MYANMAR DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 1042;MYANMAR DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 1043;MYANMAR DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 1044;MYANMAR DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 1045;MYANMAR DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 1046;MYANMAR DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 1047;MYANMAR DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 1048;MYANMAR DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 1049;MYANMAR DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 104A;MYANMAR SIGN LITTLE SECTION;Po;0;L;;;;;N;;;;; 104B;MYANMAR SIGN SECTION;Po;0;L;;;;;N;;;;; 104C;MYANMAR SYMBOL LOCATIVE;Po;0;L;;;;;N;;;;; 104D;MYANMAR SYMBOL COMPLETED;Po;0;L;;;;;N;;;;; 104E;MYANMAR SYMBOL AFOREMENTIONED;Po;0;L;;;;;N;;;;; 104F;MYANMAR SYMBOL GENITIVE;Po;0;L;;;;;N;;;;; 1050;MYANMAR LETTER SHA;Lo;0;L;;;;;N;;;;; 1051;MYANMAR LETTER SSA;Lo;0;L;;;;;N;;;;; 1052;MYANMAR LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; 1053;MYANMAR LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 1054;MYANMAR LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; 1055;MYANMAR LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; 1056;MYANMAR VOWEL SIGN VOCALIC R;Mc;0;L;;;;;N;;;;; 1057;MYANMAR VOWEL SIGN VOCALIC RR;Mc;0;L;;;;;N;;;;; 1058;MYANMAR VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; 1059;MYANMAR VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; 10A0;GEORGIAN CAPITAL LETTER AN;Lu;0;L;;;;;N;;Khutsuri;;; 10A1;GEORGIAN CAPITAL LETTER BAN;Lu;0;L;;;;;N;;Khutsuri;;; 10A2;GEORGIAN CAPITAL LETTER GAN;Lu;0;L;;;;;N;;Khutsuri;;; 10A3;GEORGIAN CAPITAL LETTER DON;Lu;0;L;;;;;N;;Khutsuri;;; 10A4;GEORGIAN CAPITAL LETTER EN;Lu;0;L;;;;;N;;Khutsuri;;; 10A5;GEORGIAN CAPITAL LETTER VIN;Lu;0;L;;;;;N;;Khutsuri;;; 10A6;GEORGIAN CAPITAL LETTER ZEN;Lu;0;L;;;;;N;;Khutsuri;;; 10A7;GEORGIAN CAPITAL LETTER TAN;Lu;0;L;;;;;N;;Khutsuri;;; 10A8;GEORGIAN CAPITAL LETTER IN;Lu;0;L;;;;;N;;Khutsuri;;; 10A9;GEORGIAN CAPITAL LETTER KAN;Lu;0;L;;;;;N;;Khutsuri;;; 10AA;GEORGIAN CAPITAL LETTER LAS;Lu;0;L;;;;;N;;Khutsuri;;; 10AB;GEORGIAN CAPITAL LETTER MAN;Lu;0;L;;;;;N;;Khutsuri;;; 10AC;GEORGIAN CAPITAL LETTER NAR;Lu;0;L;;;;;N;;Khutsuri;;; 10AD;GEORGIAN CAPITAL LETTER ON;Lu;0;L;;;;;N;;Khutsuri;;; 10AE;GEORGIAN CAPITAL LETTER PAR;Lu;0;L;;;;;N;;Khutsuri;;; 10AF;GEORGIAN CAPITAL LETTER ZHAR;Lu;0;L;;;;;N;;Khutsuri;;; 10B0;GEORGIAN CAPITAL LETTER RAE;Lu;0;L;;;;;N;;Khutsuri;;; 10B1;GEORGIAN CAPITAL LETTER SAN;Lu;0;L;;;;;N;;Khutsuri;;; 10B2;GEORGIAN CAPITAL LETTER TAR;Lu;0;L;;;;;N;;Khutsuri;;; 10B3;GEORGIAN CAPITAL LETTER UN;Lu;0;L;;;;;N;;Khutsuri;;; 10B4;GEORGIAN CAPITAL LETTER PHAR;Lu;0;L;;;;;N;;Khutsuri;;; 10B5;GEORGIAN CAPITAL LETTER KHAR;Lu;0;L;;;;;N;;Khutsuri;;; 10B6;GEORGIAN CAPITAL LETTER GHAN;Lu;0;L;;;;;N;;Khutsuri;;; 10B7;GEORGIAN CAPITAL LETTER QAR;Lu;0;L;;;;;N;;Khutsuri;;; 10B8;GEORGIAN CAPITAL LETTER SHIN;Lu;0;L;;;;;N;;Khutsuri;;; 10B9;GEORGIAN CAPITAL LETTER CHIN;Lu;0;L;;;;;N;;Khutsuri;;; 10BA;GEORGIAN CAPITAL LETTER CAN;Lu;0;L;;;;;N;;Khutsuri;;; 10BB;GEORGIAN CAPITAL LETTER JIL;Lu;0;L;;;;;N;;Khutsuri;;; 10BC;GEORGIAN CAPITAL LETTER CIL;Lu;0;L;;;;;N;;Khutsuri;;; 10BD;GEORGIAN CAPITAL LETTER CHAR;Lu;0;L;;;;;N;;Khutsuri;;; 10BE;GEORGIAN CAPITAL LETTER XAN;Lu;0;L;;;;;N;;Khutsuri;;; 10BF;GEORGIAN CAPITAL LETTER JHAN;Lu;0;L;;;;;N;;Khutsuri;;; 10C0;GEORGIAN CAPITAL LETTER HAE;Lu;0;L;;;;;N;;Khutsuri;;; 10C1;GEORGIAN CAPITAL LETTER HE;Lu;0;L;;;;;N;;Khutsuri;;; 10C2;GEORGIAN CAPITAL LETTER HIE;Lu;0;L;;;;;N;;Khutsuri;;; 10C3;GEORGIAN CAPITAL LETTER WE;Lu;0;L;;;;;N;;Khutsuri;;; 10C4;GEORGIAN CAPITAL LETTER HAR;Lu;0;L;;;;;N;;Khutsuri;;; 10C5;GEORGIAN CAPITAL LETTER HOE;Lu;0;L;;;;;N;;Khutsuri;;; 10D0;GEORGIAN LETTER AN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER AN;;;; 10D1;GEORGIAN LETTER BAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER BAN;;;; 10D2;GEORGIAN LETTER GAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER GAN;;;; 10D3;GEORGIAN LETTER DON;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER DON;;;; 10D4;GEORGIAN LETTER EN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER EN;;;; 10D5;GEORGIAN LETTER VIN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER VIN;;;; 10D6;GEORGIAN LETTER ZEN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER ZEN;;;; 10D7;GEORGIAN LETTER TAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER TAN;;;; 10D8;GEORGIAN LETTER IN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER IN;;;; 10D9;GEORGIAN LETTER KAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER KAN;;;; 10DA;GEORGIAN LETTER LAS;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER LAS;;;; 10DB;GEORGIAN LETTER MAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER MAN;;;; 10DC;GEORGIAN LETTER NAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER NAR;;;; 10DD;GEORGIAN LETTER ON;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER ON;;;; 10DE;GEORGIAN LETTER PAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER PAR;;;; 10DF;GEORGIAN LETTER ZHAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER ZHAR;;;; 10E0;GEORGIAN LETTER RAE;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER RAE;;;; 10E1;GEORGIAN LETTER SAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER SAN;;;; 10E2;GEORGIAN LETTER TAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER TAR;;;; 10E3;GEORGIAN LETTER UN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER UN;;;; 10E4;GEORGIAN LETTER PHAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER PHAR;;;; 10E5;GEORGIAN LETTER KHAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER KHAR;;;; 10E6;GEORGIAN LETTER GHAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER GHAN;;;; 10E7;GEORGIAN LETTER QAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER QAR;;;; 10E8;GEORGIAN LETTER SHIN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER SHIN;;;; 10E9;GEORGIAN LETTER CHIN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER CHIN;;;; 10EA;GEORGIAN LETTER CAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER CAN;;;; 10EB;GEORGIAN LETTER JIL;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER JIL;;;; 10EC;GEORGIAN LETTER CIL;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER CIL;;;; 10ED;GEORGIAN LETTER CHAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER CHAR;;;; 10EE;GEORGIAN LETTER XAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER XAN;;;; 10EF;GEORGIAN LETTER JHAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER JHAN;;;; 10F0;GEORGIAN LETTER HAE;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER HAE;;;; 10F1;GEORGIAN LETTER HE;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER HE;;;; 10F2;GEORGIAN LETTER HIE;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER HIE;;;; 10F3;GEORGIAN LETTER WE;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER WE;;;; 10F4;GEORGIAN LETTER HAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER HAR;;;; 10F5;GEORGIAN LETTER HOE;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER HOE;;;; 10F6;GEORGIAN LETTER FI;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER FI;;;; 10F7;GEORGIAN LETTER YN;Lo;0;L;;;;;N;;;;; 10F8;GEORGIAN LETTER ELIFI;Lo;0;L;;;;;N;;;;; 10FB;GEORGIAN PARAGRAPH SEPARATOR;Po;0;L;;;;;N;;;;; 1100;HANGUL CHOSEONG KIYEOK;Lo;0;L;;;;;N;;g *;;; 1101;HANGUL CHOSEONG SSANGKIYEOK;Lo;0;L;;;;;N;;gg *;;; 1102;HANGUL CHOSEONG NIEUN;Lo;0;L;;;;;N;;n *;;; 1103;HANGUL CHOSEONG TIKEUT;Lo;0;L;;;;;N;;d *;;; 1104;HANGUL CHOSEONG SSANGTIKEUT;Lo;0;L;;;;;N;;dd *;;; 1105;HANGUL CHOSEONG RIEUL;Lo;0;L;;;;;N;;r *;;; 1106;HANGUL CHOSEONG MIEUM;Lo;0;L;;;;;N;;m *;;; 1107;HANGUL CHOSEONG PIEUP;Lo;0;L;;;;;N;;b *;;; 1108;HANGUL CHOSEONG SSANGPIEUP;Lo;0;L;;;;;N;;bb *;;; 1109;HANGUL CHOSEONG SIOS;Lo;0;L;;;;;N;;s *;;; 110A;HANGUL CHOSEONG SSANGSIOS;Lo;0;L;;;;;N;;ss *;;; 110B;HANGUL CHOSEONG IEUNG;Lo;0;L;;;;;N;;;;; 110C;HANGUL CHOSEONG CIEUC;Lo;0;L;;;;;N;;j *;;; 110D;HANGUL CHOSEONG SSANGCIEUC;Lo;0;L;;;;;N;;jj *;;; 110E;HANGUL CHOSEONG CHIEUCH;Lo;0;L;;;;;N;;c *;;; 110F;HANGUL CHOSEONG KHIEUKH;Lo;0;L;;;;;N;;k *;;; 1110;HANGUL CHOSEONG THIEUTH;Lo;0;L;;;;;N;;t *;;; 1111;HANGUL CHOSEONG PHIEUPH;Lo;0;L;;;;;N;;p *;;; 1112;HANGUL CHOSEONG HIEUH;Lo;0;L;;;;;N;;h *;;; 1113;HANGUL CHOSEONG NIEUN-KIYEOK;Lo;0;L;;;;;N;;;;; 1114;HANGUL CHOSEONG SSANGNIEUN;Lo;0;L;;;;;N;;;;; 1115;HANGUL CHOSEONG NIEUN-TIKEUT;Lo;0;L;;;;;N;;;;; 1116;HANGUL CHOSEONG NIEUN-PIEUP;Lo;0;L;;;;;N;;;;; 1117;HANGUL CHOSEONG TIKEUT-KIYEOK;Lo;0;L;;;;;N;;;;; 1118;HANGUL CHOSEONG RIEUL-NIEUN;Lo;0;L;;;;;N;;;;; 1119;HANGUL CHOSEONG SSANGRIEUL;Lo;0;L;;;;;N;;;;; 111A;HANGUL CHOSEONG RIEUL-HIEUH;Lo;0;L;;;;;N;;;;; 111B;HANGUL CHOSEONG KAPYEOUNRIEUL;Lo;0;L;;;;;N;;;;; 111C;HANGUL CHOSEONG MIEUM-PIEUP;Lo;0;L;;;;;N;;;;; 111D;HANGUL CHOSEONG KAPYEOUNMIEUM;Lo;0;L;;;;;N;;;;; 111E;HANGUL CHOSEONG PIEUP-KIYEOK;Lo;0;L;;;;;N;;;;; 111F;HANGUL CHOSEONG PIEUP-NIEUN;Lo;0;L;;;;;N;;;;; 1120;HANGUL CHOSEONG PIEUP-TIKEUT;Lo;0;L;;;;;N;;;;; 1121;HANGUL CHOSEONG PIEUP-SIOS;Lo;0;L;;;;;N;;;;; 1122;HANGUL CHOSEONG PIEUP-SIOS-KIYEOK;Lo;0;L;;;;;N;;;;; 1123;HANGUL CHOSEONG PIEUP-SIOS-TIKEUT;Lo;0;L;;;;;N;;;;; 1124;HANGUL CHOSEONG PIEUP-SIOS-PIEUP;Lo;0;L;;;;;N;;;;; 1125;HANGUL CHOSEONG PIEUP-SSANGSIOS;Lo;0;L;;;;;N;;;;; 1126;HANGUL CHOSEONG PIEUP-SIOS-CIEUC;Lo;0;L;;;;;N;;;;; 1127;HANGUL CHOSEONG PIEUP-CIEUC;Lo;0;L;;;;;N;;;;; 1128;HANGUL CHOSEONG PIEUP-CHIEUCH;Lo;0;L;;;;;N;;;;; 1129;HANGUL CHOSEONG PIEUP-THIEUTH;Lo;0;L;;;;;N;;;;; 112A;HANGUL CHOSEONG PIEUP-PHIEUPH;Lo;0;L;;;;;N;;;;; 112B;HANGUL CHOSEONG KAPYEOUNPIEUP;Lo;0;L;;;;;N;;;;; 112C;HANGUL CHOSEONG KAPYEOUNSSANGPIEUP;Lo;0;L;;;;;N;;;;; 112D;HANGUL CHOSEONG SIOS-KIYEOK;Lo;0;L;;;;;N;;;;; 112E;HANGUL CHOSEONG SIOS-NIEUN;Lo;0;L;;;;;N;;;;; 112F;HANGUL CHOSEONG SIOS-TIKEUT;Lo;0;L;;;;;N;;;;; 1130;HANGUL CHOSEONG SIOS-RIEUL;Lo;0;L;;;;;N;;;;; 1131;HANGUL CHOSEONG SIOS-MIEUM;Lo;0;L;;;;;N;;;;; 1132;HANGUL CHOSEONG SIOS-PIEUP;Lo;0;L;;;;;N;;;;; 1133;HANGUL CHOSEONG SIOS-PIEUP-KIYEOK;Lo;0;L;;;;;N;;;;; 1134;HANGUL CHOSEONG SIOS-SSANGSIOS;Lo;0;L;;;;;N;;;;; 1135;HANGUL CHOSEONG SIOS-IEUNG;Lo;0;L;;;;;N;;;;; 1136;HANGUL CHOSEONG SIOS-CIEUC;Lo;0;L;;;;;N;;;;; 1137;HANGUL CHOSEONG SIOS-CHIEUCH;Lo;0;L;;;;;N;;;;; 1138;HANGUL CHOSEONG SIOS-KHIEUKH;Lo;0;L;;;;;N;;;;; 1139;HANGUL CHOSEONG SIOS-THIEUTH;Lo;0;L;;;;;N;;;;; 113A;HANGUL CHOSEONG SIOS-PHIEUPH;Lo;0;L;;;;;N;;;;; 113B;HANGUL CHOSEONG SIOS-HIEUH;Lo;0;L;;;;;N;;;;; 113C;HANGUL CHOSEONG CHITUEUMSIOS;Lo;0;L;;;;;N;;;;; 113D;HANGUL CHOSEONG CHITUEUMSSANGSIOS;Lo;0;L;;;;;N;;;;; 113E;HANGUL CHOSEONG CEONGCHIEUMSIOS;Lo;0;L;;;;;N;;;;; 113F;HANGUL CHOSEONG CEONGCHIEUMSSANGSIOS;Lo;0;L;;;;;N;;;;; 1140;HANGUL CHOSEONG PANSIOS;Lo;0;L;;;;;N;;;;; 1141;HANGUL CHOSEONG IEUNG-KIYEOK;Lo;0;L;;;;;N;;;;; 1142;HANGUL CHOSEONG IEUNG-TIKEUT;Lo;0;L;;;;;N;;;;; 1143;HANGUL CHOSEONG IEUNG-MIEUM;Lo;0;L;;;;;N;;;;; 1144;HANGUL CHOSEONG IEUNG-PIEUP;Lo;0;L;;;;;N;;;;; 1145;HANGUL CHOSEONG IEUNG-SIOS;Lo;0;L;;;;;N;;;;; 1146;HANGUL CHOSEONG IEUNG-PANSIOS;Lo;0;L;;;;;N;;;;; 1147;HANGUL CHOSEONG SSANGIEUNG;Lo;0;L;;;;;N;;;;; 1148;HANGUL CHOSEONG IEUNG-CIEUC;Lo;0;L;;;;;N;;;;; 1149;HANGUL CHOSEONG IEUNG-CHIEUCH;Lo;0;L;;;;;N;;;;; 114A;HANGUL CHOSEONG IEUNG-THIEUTH;Lo;0;L;;;;;N;;;;; 114B;HANGUL CHOSEONG IEUNG-PHIEUPH;Lo;0;L;;;;;N;;;;; 114C;HANGUL CHOSEONG YESIEUNG;Lo;0;L;;;;;N;;;;; 114D;HANGUL CHOSEONG CIEUC-IEUNG;Lo;0;L;;;;;N;;;;; 114E;HANGUL CHOSEONG CHITUEUMCIEUC;Lo;0;L;;;;;N;;;;; 114F;HANGUL CHOSEONG CHITUEUMSSANGCIEUC;Lo;0;L;;;;;N;;;;; 1150;HANGUL CHOSEONG CEONGCHIEUMCIEUC;Lo;0;L;;;;;N;;;;; 1151;HANGUL CHOSEONG CEONGCHIEUMSSANGCIEUC;Lo;0;L;;;;;N;;;;; 1152;HANGUL CHOSEONG CHIEUCH-KHIEUKH;Lo;0;L;;;;;N;;;;; 1153;HANGUL CHOSEONG CHIEUCH-HIEUH;Lo;0;L;;;;;N;;;;; 1154;HANGUL CHOSEONG CHITUEUMCHIEUCH;Lo;0;L;;;;;N;;;;; 1155;HANGUL CHOSEONG CEONGCHIEUMCHIEUCH;Lo;0;L;;;;;N;;;;; 1156;HANGUL CHOSEONG PHIEUPH-PIEUP;Lo;0;L;;;;;N;;;;; 1157;HANGUL CHOSEONG KAPYEOUNPHIEUPH;Lo;0;L;;;;;N;;;;; 1158;HANGUL CHOSEONG SSANGHIEUH;Lo;0;L;;;;;N;;;;; 1159;HANGUL CHOSEONG YEORINHIEUH;Lo;0;L;;;;;N;;;;; 115F;HANGUL CHOSEONG FILLER;Lo;0;L;;;;;N;;;;; 1160;HANGUL JUNGSEONG FILLER;Lo;0;L;;;;;N;;;;; 1161;HANGUL JUNGSEONG A;Lo;0;L;;;;;N;;;;; 1162;HANGUL JUNGSEONG AE;Lo;0;L;;;;;N;;;;; 1163;HANGUL JUNGSEONG YA;Lo;0;L;;;;;N;;;;; 1164;HANGUL JUNGSEONG YAE;Lo;0;L;;;;;N;;;;; 1165;HANGUL JUNGSEONG EO;Lo;0;L;;;;;N;;;;; 1166;HANGUL JUNGSEONG E;Lo;0;L;;;;;N;;;;; 1167;HANGUL JUNGSEONG YEO;Lo;0;L;;;;;N;;;;; 1168;HANGUL JUNGSEONG YE;Lo;0;L;;;;;N;;;;; 1169;HANGUL JUNGSEONG O;Lo;0;L;;;;;N;;;;; 116A;HANGUL JUNGSEONG WA;Lo;0;L;;;;;N;;;;; 116B;HANGUL JUNGSEONG WAE;Lo;0;L;;;;;N;;;;; 116C;HANGUL JUNGSEONG OE;Lo;0;L;;;;;N;;;;; 116D;HANGUL JUNGSEONG YO;Lo;0;L;;;;;N;;;;; 116E;HANGUL JUNGSEONG U;Lo;0;L;;;;;N;;;;; 116F;HANGUL JUNGSEONG WEO;Lo;0;L;;;;;N;;;;; 1170;HANGUL JUNGSEONG WE;Lo;0;L;;;;;N;;;;; 1171;HANGUL JUNGSEONG WI;Lo;0;L;;;;;N;;;;; 1172;HANGUL JUNGSEONG YU;Lo;0;L;;;;;N;;;;; 1173;HANGUL JUNGSEONG EU;Lo;0;L;;;;;N;;;;; 1174;HANGUL JUNGSEONG YI;Lo;0;L;;;;;N;;;;; 1175;HANGUL JUNGSEONG I;Lo;0;L;;;;;N;;;;; 1176;HANGUL JUNGSEONG A-O;Lo;0;L;;;;;N;;;;; 1177;HANGUL JUNGSEONG A-U;Lo;0;L;;;;;N;;;;; 1178;HANGUL JUNGSEONG YA-O;Lo;0;L;;;;;N;;;;; 1179;HANGUL JUNGSEONG YA-YO;Lo;0;L;;;;;N;;;;; 117A;HANGUL JUNGSEONG EO-O;Lo;0;L;;;;;N;;;;; 117B;HANGUL JUNGSEONG EO-U;Lo;0;L;;;;;N;;;;; 117C;HANGUL JUNGSEONG EO-EU;Lo;0;L;;;;;N;;;;; 117D;HANGUL JUNGSEONG YEO-O;Lo;0;L;;;;;N;;;;; 117E;HANGUL JUNGSEONG YEO-U;Lo;0;L;;;;;N;;;;; 117F;HANGUL JUNGSEONG O-EO;Lo;0;L;;;;;N;;;;; 1180;HANGUL JUNGSEONG O-E;Lo;0;L;;;;;N;;;;; 1181;HANGUL JUNGSEONG O-YE;Lo;0;L;;;;;N;;;;; 1182;HANGUL JUNGSEONG O-O;Lo;0;L;;;;;N;;;;; 1183;HANGUL JUNGSEONG O-U;Lo;0;L;;;;;N;;;;; 1184;HANGUL JUNGSEONG YO-YA;Lo;0;L;;;;;N;;;;; 1185;HANGUL JUNGSEONG YO-YAE;Lo;0;L;;;;;N;;;;; 1186;HANGUL JUNGSEONG YO-YEO;Lo;0;L;;;;;N;;;;; 1187;HANGUL JUNGSEONG YO-O;Lo;0;L;;;;;N;;;;; 1188;HANGUL JUNGSEONG YO-I;Lo;0;L;;;;;N;;;;; 1189;HANGUL JUNGSEONG U-A;Lo;0;L;;;;;N;;;;; 118A;HANGUL JUNGSEONG U-AE;Lo;0;L;;;;;N;;;;; 118B;HANGUL JUNGSEONG U-EO-EU;Lo;0;L;;;;;N;;;;; 118C;HANGUL JUNGSEONG U-YE;Lo;0;L;;;;;N;;;;; 118D;HANGUL JUNGSEONG U-U;Lo;0;L;;;;;N;;;;; 118E;HANGUL JUNGSEONG YU-A;Lo;0;L;;;;;N;;;;; 118F;HANGUL JUNGSEONG YU-EO;Lo;0;L;;;;;N;;;;; 1190;HANGUL JUNGSEONG YU-E;Lo;0;L;;;;;N;;;;; 1191;HANGUL JUNGSEONG YU-YEO;Lo;0;L;;;;;N;;;;; 1192;HANGUL JUNGSEONG YU-YE;Lo;0;L;;;;;N;;;;; 1193;HANGUL JUNGSEONG YU-U;Lo;0;L;;;;;N;;;;; 1194;HANGUL JUNGSEONG YU-I;Lo;0;L;;;;;N;;;;; 1195;HANGUL JUNGSEONG EU-U;Lo;0;L;;;;;N;;;;; 1196;HANGUL JUNGSEONG EU-EU;Lo;0;L;;;;;N;;;;; 1197;HANGUL JUNGSEONG YI-U;Lo;0;L;;;;;N;;;;; 1198;HANGUL JUNGSEONG I-A;Lo;0;L;;;;;N;;;;; 1199;HANGUL JUNGSEONG I-YA;Lo;0;L;;;;;N;;;;; 119A;HANGUL JUNGSEONG I-O;Lo;0;L;;;;;N;;;;; 119B;HANGUL JUNGSEONG I-U;Lo;0;L;;;;;N;;;;; 119C;HANGUL JUNGSEONG I-EU;Lo;0;L;;;;;N;;;;; 119D;HANGUL JUNGSEONG I-ARAEA;Lo;0;L;;;;;N;;;;; 119E;HANGUL JUNGSEONG ARAEA;Lo;0;L;;;;;N;;;;; 119F;HANGUL JUNGSEONG ARAEA-EO;Lo;0;L;;;;;N;;;;; 11A0;HANGUL JUNGSEONG ARAEA-U;Lo;0;L;;;;;N;;;;; 11A1;HANGUL JUNGSEONG ARAEA-I;Lo;0;L;;;;;N;;;;; 11A2;HANGUL JUNGSEONG SSANGARAEA;Lo;0;L;;;;;N;;;;; 11A8;HANGUL JONGSEONG KIYEOK;Lo;0;L;;;;;N;;g *;;; 11A9;HANGUL JONGSEONG SSANGKIYEOK;Lo;0;L;;;;;N;;gg *;;; 11AA;HANGUL JONGSEONG KIYEOK-SIOS;Lo;0;L;;;;;N;;gs *;;; 11AB;HANGUL JONGSEONG NIEUN;Lo;0;L;;;;;N;;n *;;; 11AC;HANGUL JONGSEONG NIEUN-CIEUC;Lo;0;L;;;;;N;;nj *;;; 11AD;HANGUL JONGSEONG NIEUN-HIEUH;Lo;0;L;;;;;N;;nh *;;; 11AE;HANGUL JONGSEONG TIKEUT;Lo;0;L;;;;;N;;d *;;; 11AF;HANGUL JONGSEONG RIEUL;Lo;0;L;;;;;N;;l *;;; 11B0;HANGUL JONGSEONG RIEUL-KIYEOK;Lo;0;L;;;;;N;;lg *;;; 11B1;HANGUL JONGSEONG RIEUL-MIEUM;Lo;0;L;;;;;N;;lm *;;; 11B2;HANGUL JONGSEONG RIEUL-PIEUP;Lo;0;L;;;;;N;;lb *;;; 11B3;HANGUL JONGSEONG RIEUL-SIOS;Lo;0;L;;;;;N;;ls *;;; 11B4;HANGUL JONGSEONG RIEUL-THIEUTH;Lo;0;L;;;;;N;;lt *;;; 11B5;HANGUL JONGSEONG RIEUL-PHIEUPH;Lo;0;L;;;;;N;;lp *;;; 11B6;HANGUL JONGSEONG RIEUL-HIEUH;Lo;0;L;;;;;N;;lh *;;; 11B7;HANGUL JONGSEONG MIEUM;Lo;0;L;;;;;N;;m *;;; 11B8;HANGUL JONGSEONG PIEUP;Lo;0;L;;;;;N;;b *;;; 11B9;HANGUL JONGSEONG PIEUP-SIOS;Lo;0;L;;;;;N;;bs *;;; 11BA;HANGUL JONGSEONG SIOS;Lo;0;L;;;;;N;;s *;;; 11BB;HANGUL JONGSEONG SSANGSIOS;Lo;0;L;;;;;N;;ss *;;; 11BC;HANGUL JONGSEONG IEUNG;Lo;0;L;;;;;N;;ng *;;; 11BD;HANGUL JONGSEONG CIEUC;Lo;0;L;;;;;N;;j *;;; 11BE;HANGUL JONGSEONG CHIEUCH;Lo;0;L;;;;;N;;c *;;; 11BF;HANGUL JONGSEONG KHIEUKH;Lo;0;L;;;;;N;;k *;;; 11C0;HANGUL JONGSEONG THIEUTH;Lo;0;L;;;;;N;;t *;;; 11C1;HANGUL JONGSEONG PHIEUPH;Lo;0;L;;;;;N;;p *;;; 11C2;HANGUL JONGSEONG HIEUH;Lo;0;L;;;;;N;;h *;;; 11C3;HANGUL JONGSEONG KIYEOK-RIEUL;Lo;0;L;;;;;N;;;;; 11C4;HANGUL JONGSEONG KIYEOK-SIOS-KIYEOK;Lo;0;L;;;;;N;;;;; 11C5;HANGUL JONGSEONG NIEUN-KIYEOK;Lo;0;L;;;;;N;;;;; 11C6;HANGUL JONGSEONG NIEUN-TIKEUT;Lo;0;L;;;;;N;;;;; 11C7;HANGUL JONGSEONG NIEUN-SIOS;Lo;0;L;;;;;N;;;;; 11C8;HANGUL JONGSEONG NIEUN-PANSIOS;Lo;0;L;;;;;N;;;;; 11C9;HANGUL JONGSEONG NIEUN-THIEUTH;Lo;0;L;;;;;N;;;;; 11CA;HANGUL JONGSEONG TIKEUT-KIYEOK;Lo;0;L;;;;;N;;;;; 11CB;HANGUL JONGSEONG TIKEUT-RIEUL;Lo;0;L;;;;;N;;;;; 11CC;HANGUL JONGSEONG RIEUL-KIYEOK-SIOS;Lo;0;L;;;;;N;;;;; 11CD;HANGUL JONGSEONG RIEUL-NIEUN;Lo;0;L;;;;;N;;;;; 11CE;HANGUL JONGSEONG RIEUL-TIKEUT;Lo;0;L;;;;;N;;;;; 11CF;HANGUL JONGSEONG RIEUL-TIKEUT-HIEUH;Lo;0;L;;;;;N;;;;; 11D0;HANGUL JONGSEONG SSANGRIEUL;Lo;0;L;;;;;N;;;;; 11D1;HANGUL JONGSEONG RIEUL-MIEUM-KIYEOK;Lo;0;L;;;;;N;;;;; 11D2;HANGUL JONGSEONG RIEUL-MIEUM-SIOS;Lo;0;L;;;;;N;;;;; 11D3;HANGUL JONGSEONG RIEUL-PIEUP-SIOS;Lo;0;L;;;;;N;;;;; 11D4;HANGUL JONGSEONG RIEUL-PIEUP-HIEUH;Lo;0;L;;;;;N;;;;; 11D5;HANGUL JONGSEONG RIEUL-KAPYEOUNPIEUP;Lo;0;L;;;;;N;;;;; 11D6;HANGUL JONGSEONG RIEUL-SSANGSIOS;Lo;0;L;;;;;N;;;;; 11D7;HANGUL JONGSEONG RIEUL-PANSIOS;Lo;0;L;;;;;N;;;;; 11D8;HANGUL JONGSEONG RIEUL-KHIEUKH;Lo;0;L;;;;;N;;;;; 11D9;HANGUL JONGSEONG RIEUL-YEORINHIEUH;Lo;0;L;;;;;N;;;;; 11DA;HANGUL JONGSEONG MIEUM-KIYEOK;Lo;0;L;;;;;N;;;;; 11DB;HANGUL JONGSEONG MIEUM-RIEUL;Lo;0;L;;;;;N;;;;; 11DC;HANGUL JONGSEONG MIEUM-PIEUP;Lo;0;L;;;;;N;;;;; 11DD;HANGUL JONGSEONG MIEUM-SIOS;Lo;0;L;;;;;N;;;;; 11DE;HANGUL JONGSEONG MIEUM-SSANGSIOS;Lo;0;L;;;;;N;;;;; 11DF;HANGUL JONGSEONG MIEUM-PANSIOS;Lo;0;L;;;;;N;;;;; 11E0;HANGUL JONGSEONG MIEUM-CHIEUCH;Lo;0;L;;;;;N;;;;; 11E1;HANGUL JONGSEONG MIEUM-HIEUH;Lo;0;L;;;;;N;;;;; 11E2;HANGUL JONGSEONG KAPYEOUNMIEUM;Lo;0;L;;;;;N;;;;; 11E3;HANGUL JONGSEONG PIEUP-RIEUL;Lo;0;L;;;;;N;;;;; 11E4;HANGUL JONGSEONG PIEUP-PHIEUPH;Lo;0;L;;;;;N;;;;; 11E5;HANGUL JONGSEONG PIEUP-HIEUH;Lo;0;L;;;;;N;;;;; 11E6;HANGUL JONGSEONG KAPYEOUNPIEUP;Lo;0;L;;;;;N;;;;; 11E7;HANGUL JONGSEONG SIOS-KIYEOK;Lo;0;L;;;;;N;;;;; 11E8;HANGUL JONGSEONG SIOS-TIKEUT;Lo;0;L;;;;;N;;;;; 11E9;HANGUL JONGSEONG SIOS-RIEUL;Lo;0;L;;;;;N;;;;; 11EA;HANGUL JONGSEONG SIOS-PIEUP;Lo;0;L;;;;;N;;;;; 11EB;HANGUL JONGSEONG PANSIOS;Lo;0;L;;;;;N;;;;; 11EC;HANGUL JONGSEONG IEUNG-KIYEOK;Lo;0;L;;;;;N;;;;; 11ED;HANGUL JONGSEONG IEUNG-SSANGKIYEOK;Lo;0;L;;;;;N;;;;; 11EE;HANGUL JONGSEONG SSANGIEUNG;Lo;0;L;;;;;N;;;;; 11EF;HANGUL JONGSEONG IEUNG-KHIEUKH;Lo;0;L;;;;;N;;;;; 11F0;HANGUL JONGSEONG YESIEUNG;Lo;0;L;;;;;N;;;;; 11F1;HANGUL JONGSEONG YESIEUNG-SIOS;Lo;0;L;;;;;N;;;;; 11F2;HANGUL JONGSEONG YESIEUNG-PANSIOS;Lo;0;L;;;;;N;;;;; 11F3;HANGUL JONGSEONG PHIEUPH-PIEUP;Lo;0;L;;;;;N;;;;; 11F4;HANGUL JONGSEONG KAPYEOUNPHIEUPH;Lo;0;L;;;;;N;;;;; 11F5;HANGUL JONGSEONG HIEUH-NIEUN;Lo;0;L;;;;;N;;;;; 11F6;HANGUL JONGSEONG HIEUH-RIEUL;Lo;0;L;;;;;N;;;;; 11F7;HANGUL JONGSEONG HIEUH-MIEUM;Lo;0;L;;;;;N;;;;; 11F8;HANGUL JONGSEONG HIEUH-PIEUP;Lo;0;L;;;;;N;;;;; 11F9;HANGUL JONGSEONG YEORINHIEUH;Lo;0;L;;;;;N;;;;; 1200;ETHIOPIC SYLLABLE HA;Lo;0;L;;;;;N;;;;; 1201;ETHIOPIC SYLLABLE HU;Lo;0;L;;;;;N;;;;; 1202;ETHIOPIC SYLLABLE HI;Lo;0;L;;;;;N;;;;; 1203;ETHIOPIC SYLLABLE HAA;Lo;0;L;;;;;N;;;;; 1204;ETHIOPIC SYLLABLE HEE;Lo;0;L;;;;;N;;;;; 1205;ETHIOPIC SYLLABLE HE;Lo;0;L;;;;;N;;;;; 1206;ETHIOPIC SYLLABLE HO;Lo;0;L;;;;;N;;;;; 1208;ETHIOPIC SYLLABLE LA;Lo;0;L;;;;;N;;;;; 1209;ETHIOPIC SYLLABLE LU;Lo;0;L;;;;;N;;;;; 120A;ETHIOPIC SYLLABLE LI;Lo;0;L;;;;;N;;;;; 120B;ETHIOPIC SYLLABLE LAA;Lo;0;L;;;;;N;;;;; 120C;ETHIOPIC SYLLABLE LEE;Lo;0;L;;;;;N;;;;; 120D;ETHIOPIC SYLLABLE LE;Lo;0;L;;;;;N;;;;; 120E;ETHIOPIC SYLLABLE LO;Lo;0;L;;;;;N;;;;; 120F;ETHIOPIC SYLLABLE LWA;Lo;0;L;;;;;N;;;;; 1210;ETHIOPIC SYLLABLE HHA;Lo;0;L;;;;;N;;;;; 1211;ETHIOPIC SYLLABLE HHU;Lo;0;L;;;;;N;;;;; 1212;ETHIOPIC SYLLABLE HHI;Lo;0;L;;;;;N;;;;; 1213;ETHIOPIC SYLLABLE HHAA;Lo;0;L;;;;;N;;;;; 1214;ETHIOPIC SYLLABLE HHEE;Lo;0;L;;;;;N;;;;; 1215;ETHIOPIC SYLLABLE HHE;Lo;0;L;;;;;N;;;;; 1216;ETHIOPIC SYLLABLE HHO;Lo;0;L;;;;;N;;;;; 1217;ETHIOPIC SYLLABLE HHWA;Lo;0;L;;;;;N;;;;; 1218;ETHIOPIC SYLLABLE MA;Lo;0;L;;;;;N;;;;; 1219;ETHIOPIC SYLLABLE MU;Lo;0;L;;;;;N;;;;; 121A;ETHIOPIC SYLLABLE MI;Lo;0;L;;;;;N;;;;; 121B;ETHIOPIC SYLLABLE MAA;Lo;0;L;;;;;N;;;;; 121C;ETHIOPIC SYLLABLE MEE;Lo;0;L;;;;;N;;;;; 121D;ETHIOPIC SYLLABLE ME;Lo;0;L;;;;;N;;;;; 121E;ETHIOPIC SYLLABLE MO;Lo;0;L;;;;;N;;;;; 121F;ETHIOPIC SYLLABLE MWA;Lo;0;L;;;;;N;;;;; 1220;ETHIOPIC SYLLABLE SZA;Lo;0;L;;;;;N;;;;; 1221;ETHIOPIC SYLLABLE SZU;Lo;0;L;;;;;N;;;;; 1222;ETHIOPIC SYLLABLE SZI;Lo;0;L;;;;;N;;;;; 1223;ETHIOPIC SYLLABLE SZAA;Lo;0;L;;;;;N;;;;; 1224;ETHIOPIC SYLLABLE SZEE;Lo;0;L;;;;;N;;;;; 1225;ETHIOPIC SYLLABLE SZE;Lo;0;L;;;;;N;;;;; 1226;ETHIOPIC SYLLABLE SZO;Lo;0;L;;;;;N;;;;; 1227;ETHIOPIC SYLLABLE SZWA;Lo;0;L;;;;;N;;;;; 1228;ETHIOPIC SYLLABLE RA;Lo;0;L;;;;;N;;;;; 1229;ETHIOPIC SYLLABLE RU;Lo;0;L;;;;;N;;;;; 122A;ETHIOPIC SYLLABLE RI;Lo;0;L;;;;;N;;;;; 122B;ETHIOPIC SYLLABLE RAA;Lo;0;L;;;;;N;;;;; 122C;ETHIOPIC SYLLABLE REE;Lo;0;L;;;;;N;;;;; 122D;ETHIOPIC SYLLABLE RE;Lo;0;L;;;;;N;;;;; 122E;ETHIOPIC SYLLABLE RO;Lo;0;L;;;;;N;;;;; 122F;ETHIOPIC SYLLABLE RWA;Lo;0;L;;;;;N;;;;; 1230;ETHIOPIC SYLLABLE SA;Lo;0;L;;;;;N;;;;; 1231;ETHIOPIC SYLLABLE SU;Lo;0;L;;;;;N;;;;; 1232;ETHIOPIC SYLLABLE SI;Lo;0;L;;;;;N;;;;; 1233;ETHIOPIC SYLLABLE SAA;Lo;0;L;;;;;N;;;;; 1234;ETHIOPIC SYLLABLE SEE;Lo;0;L;;;;;N;;;;; 1235;ETHIOPIC SYLLABLE SE;Lo;0;L;;;;;N;;;;; 1236;ETHIOPIC SYLLABLE SO;Lo;0;L;;;;;N;;;;; 1237;ETHIOPIC SYLLABLE SWA;Lo;0;L;;;;;N;;;;; 1238;ETHIOPIC SYLLABLE SHA;Lo;0;L;;;;;N;;;;; 1239;ETHIOPIC SYLLABLE SHU;Lo;0;L;;;;;N;;;;; 123A;ETHIOPIC SYLLABLE SHI;Lo;0;L;;;;;N;;;;; 123B;ETHIOPIC SYLLABLE SHAA;Lo;0;L;;;;;N;;;;; 123C;ETHIOPIC SYLLABLE SHEE;Lo;0;L;;;;;N;;;;; 123D;ETHIOPIC SYLLABLE SHE;Lo;0;L;;;;;N;;;;; 123E;ETHIOPIC SYLLABLE SHO;Lo;0;L;;;;;N;;;;; 123F;ETHIOPIC SYLLABLE SHWA;Lo;0;L;;;;;N;;;;; 1240;ETHIOPIC SYLLABLE QA;Lo;0;L;;;;;N;;;;; 1241;ETHIOPIC SYLLABLE QU;Lo;0;L;;;;;N;;;;; 1242;ETHIOPIC SYLLABLE QI;Lo;0;L;;;;;N;;;;; 1243;ETHIOPIC SYLLABLE QAA;Lo;0;L;;;;;N;;;;; 1244;ETHIOPIC SYLLABLE QEE;Lo;0;L;;;;;N;;;;; 1245;ETHIOPIC SYLLABLE QE;Lo;0;L;;;;;N;;;;; 1246;ETHIOPIC SYLLABLE QO;Lo;0;L;;;;;N;;;;; 1248;ETHIOPIC SYLLABLE QWA;Lo;0;L;;;;;N;;;;; 124A;ETHIOPIC SYLLABLE QWI;Lo;0;L;;;;;N;;;;; 124B;ETHIOPIC SYLLABLE QWAA;Lo;0;L;;;;;N;;;;; 124C;ETHIOPIC SYLLABLE QWEE;Lo;0;L;;;;;N;;;;; 124D;ETHIOPIC SYLLABLE QWE;Lo;0;L;;;;;N;;;;; 1250;ETHIOPIC SYLLABLE QHA;Lo;0;L;;;;;N;;;;; 1251;ETHIOPIC SYLLABLE QHU;Lo;0;L;;;;;N;;;;; 1252;ETHIOPIC SYLLABLE QHI;Lo;0;L;;;;;N;;;;; 1253;ETHIOPIC SYLLABLE QHAA;Lo;0;L;;;;;N;;;;; 1254;ETHIOPIC SYLLABLE QHEE;Lo;0;L;;;;;N;;;;; 1255;ETHIOPIC SYLLABLE QHE;Lo;0;L;;;;;N;;;;; 1256;ETHIOPIC SYLLABLE QHO;Lo;0;L;;;;;N;;;;; 1258;ETHIOPIC SYLLABLE QHWA;Lo;0;L;;;;;N;;;;; 125A;ETHIOPIC SYLLABLE QHWI;Lo;0;L;;;;;N;;;;; 125B;ETHIOPIC SYLLABLE QHWAA;Lo;0;L;;;;;N;;;;; 125C;ETHIOPIC SYLLABLE QHWEE;Lo;0;L;;;;;N;;;;; 125D;ETHIOPIC SYLLABLE QHWE;Lo;0;L;;;;;N;;;;; 1260;ETHIOPIC SYLLABLE BA;Lo;0;L;;;;;N;;;;; 1261;ETHIOPIC SYLLABLE BU;Lo;0;L;;;;;N;;;;; 1262;ETHIOPIC SYLLABLE BI;Lo;0;L;;;;;N;;;;; 1263;ETHIOPIC SYLLABLE BAA;Lo;0;L;;;;;N;;;;; 1264;ETHIOPIC SYLLABLE BEE;Lo;0;L;;;;;N;;;;; 1265;ETHIOPIC SYLLABLE BE;Lo;0;L;;;;;N;;;;; 1266;ETHIOPIC SYLLABLE BO;Lo;0;L;;;;;N;;;;; 1267;ETHIOPIC SYLLABLE BWA;Lo;0;L;;;;;N;;;;; 1268;ETHIOPIC SYLLABLE VA;Lo;0;L;;;;;N;;;;; 1269;ETHIOPIC SYLLABLE VU;Lo;0;L;;;;;N;;;;; 126A;ETHIOPIC SYLLABLE VI;Lo;0;L;;;;;N;;;;; 126B;ETHIOPIC SYLLABLE VAA;Lo;0;L;;;;;N;;;;; 126C;ETHIOPIC SYLLABLE VEE;Lo;0;L;;;;;N;;;;; 126D;ETHIOPIC SYLLABLE VE;Lo;0;L;;;;;N;;;;; 126E;ETHIOPIC SYLLABLE VO;Lo;0;L;;;;;N;;;;; 126F;ETHIOPIC SYLLABLE VWA;Lo;0;L;;;;;N;;;;; 1270;ETHIOPIC SYLLABLE TA;Lo;0;L;;;;;N;;;;; 1271;ETHIOPIC SYLLABLE TU;Lo;0;L;;;;;N;;;;; 1272;ETHIOPIC SYLLABLE TI;Lo;0;L;;;;;N;;;;; 1273;ETHIOPIC SYLLABLE TAA;Lo;0;L;;;;;N;;;;; 1274;ETHIOPIC SYLLABLE TEE;Lo;0;L;;;;;N;;;;; 1275;ETHIOPIC SYLLABLE TE;Lo;0;L;;;;;N;;;;; 1276;ETHIOPIC SYLLABLE TO;Lo;0;L;;;;;N;;;;; 1277;ETHIOPIC SYLLABLE TWA;Lo;0;L;;;;;N;;;;; 1278;ETHIOPIC SYLLABLE CA;Lo;0;L;;;;;N;;;;; 1279;ETHIOPIC SYLLABLE CU;Lo;0;L;;;;;N;;;;; 127A;ETHIOPIC SYLLABLE CI;Lo;0;L;;;;;N;;;;; 127B;ETHIOPIC SYLLABLE CAA;Lo;0;L;;;;;N;;;;; 127C;ETHIOPIC SYLLABLE CEE;Lo;0;L;;;;;N;;;;; 127D;ETHIOPIC SYLLABLE CE;Lo;0;L;;;;;N;;;;; 127E;ETHIOPIC SYLLABLE CO;Lo;0;L;;;;;N;;;;; 127F;ETHIOPIC SYLLABLE CWA;Lo;0;L;;;;;N;;;;; 1280;ETHIOPIC SYLLABLE XA;Lo;0;L;;;;;N;;;;; 1281;ETHIOPIC SYLLABLE XU;Lo;0;L;;;;;N;;;;; 1282;ETHIOPIC SYLLABLE XI;Lo;0;L;;;;;N;;;;; 1283;ETHIOPIC SYLLABLE XAA;Lo;0;L;;;;;N;;;;; 1284;ETHIOPIC SYLLABLE XEE;Lo;0;L;;;;;N;;;;; 1285;ETHIOPIC SYLLABLE XE;Lo;0;L;;;;;N;;;;; 1286;ETHIOPIC SYLLABLE XO;Lo;0;L;;;;;N;;;;; 1288;ETHIOPIC SYLLABLE XWA;Lo;0;L;;;;;N;;;;; 128A;ETHIOPIC SYLLABLE XWI;Lo;0;L;;;;;N;;;;; 128B;ETHIOPIC SYLLABLE XWAA;Lo;0;L;;;;;N;;;;; 128C;ETHIOPIC SYLLABLE XWEE;Lo;0;L;;;;;N;;;;; 128D;ETHIOPIC SYLLABLE XWE;Lo;0;L;;;;;N;;;;; 1290;ETHIOPIC SYLLABLE NA;Lo;0;L;;;;;N;;;;; 1291;ETHIOPIC SYLLABLE NU;Lo;0;L;;;;;N;;;;; 1292;ETHIOPIC SYLLABLE NI;Lo;0;L;;;;;N;;;;; 1293;ETHIOPIC SYLLABLE NAA;Lo;0;L;;;;;N;;;;; 1294;ETHIOPIC SYLLABLE NEE;Lo;0;L;;;;;N;;;;; 1295;ETHIOPIC SYLLABLE NE;Lo;0;L;;;;;N;;;;; 1296;ETHIOPIC SYLLABLE NO;Lo;0;L;;;;;N;;;;; 1297;ETHIOPIC SYLLABLE NWA;Lo;0;L;;;;;N;;;;; 1298;ETHIOPIC SYLLABLE NYA;Lo;0;L;;;;;N;;;;; 1299;ETHIOPIC SYLLABLE NYU;Lo;0;L;;;;;N;;;;; 129A;ETHIOPIC SYLLABLE NYI;Lo;0;L;;;;;N;;;;; 129B;ETHIOPIC SYLLABLE NYAA;Lo;0;L;;;;;N;;;;; 129C;ETHIOPIC SYLLABLE NYEE;Lo;0;L;;;;;N;;;;; 129D;ETHIOPIC SYLLABLE NYE;Lo;0;L;;;;;N;;;;; 129E;ETHIOPIC SYLLABLE NYO;Lo;0;L;;;;;N;;;;; 129F;ETHIOPIC SYLLABLE NYWA;Lo;0;L;;;;;N;;;;; 12A0;ETHIOPIC SYLLABLE GLOTTAL A;Lo;0;L;;;;;N;;;;; 12A1;ETHIOPIC SYLLABLE GLOTTAL U;Lo;0;L;;;;;N;;;;; 12A2;ETHIOPIC SYLLABLE GLOTTAL I;Lo;0;L;;;;;N;;;;; 12A3;ETHIOPIC SYLLABLE GLOTTAL AA;Lo;0;L;;;;;N;;;;; 12A4;ETHIOPIC SYLLABLE GLOTTAL EE;Lo;0;L;;;;;N;;;;; 12A5;ETHIOPIC SYLLABLE GLOTTAL E;Lo;0;L;;;;;N;;;;; 12A6;ETHIOPIC SYLLABLE GLOTTAL O;Lo;0;L;;;;;N;;;;; 12A7;ETHIOPIC SYLLABLE GLOTTAL WA;Lo;0;L;;;;;N;;;;; 12A8;ETHIOPIC SYLLABLE KA;Lo;0;L;;;;;N;;;;; 12A9;ETHIOPIC SYLLABLE KU;Lo;0;L;;;;;N;;;;; 12AA;ETHIOPIC SYLLABLE KI;Lo;0;L;;;;;N;;;;; 12AB;ETHIOPIC SYLLABLE KAA;Lo;0;L;;;;;N;;;;; 12AC;ETHIOPIC SYLLABLE KEE;Lo;0;L;;;;;N;;;;; 12AD;ETHIOPIC SYLLABLE KE;Lo;0;L;;;;;N;;;;; 12AE;ETHIOPIC SYLLABLE KO;Lo;0;L;;;;;N;;;;; 12B0;ETHIOPIC SYLLABLE KWA;Lo;0;L;;;;;N;;;;; 12B2;ETHIOPIC SYLLABLE KWI;Lo;0;L;;;;;N;;;;; 12B3;ETHIOPIC SYLLABLE KWAA;Lo;0;L;;;;;N;;;;; 12B4;ETHIOPIC SYLLABLE KWEE;Lo;0;L;;;;;N;;;;; 12B5;ETHIOPIC SYLLABLE KWE;Lo;0;L;;;;;N;;;;; 12B8;ETHIOPIC SYLLABLE KXA;Lo;0;L;;;;;N;;;;; 12B9;ETHIOPIC SYLLABLE KXU;Lo;0;L;;;;;N;;;;; 12BA;ETHIOPIC SYLLABLE KXI;Lo;0;L;;;;;N;;;;; 12BB;ETHIOPIC SYLLABLE KXAA;Lo;0;L;;;;;N;;;;; 12BC;ETHIOPIC SYLLABLE KXEE;Lo;0;L;;;;;N;;;;; 12BD;ETHIOPIC SYLLABLE KXE;Lo;0;L;;;;;N;;;;; 12BE;ETHIOPIC SYLLABLE KXO;Lo;0;L;;;;;N;;;;; 12C0;ETHIOPIC SYLLABLE KXWA;Lo;0;L;;;;;N;;;;; 12C2;ETHIOPIC SYLLABLE KXWI;Lo;0;L;;;;;N;;;;; 12C3;ETHIOPIC SYLLABLE KXWAA;Lo;0;L;;;;;N;;;;; 12C4;ETHIOPIC SYLLABLE KXWEE;Lo;0;L;;;;;N;;;;; 12C5;ETHIOPIC SYLLABLE KXWE;Lo;0;L;;;;;N;;;;; 12C8;ETHIOPIC SYLLABLE WA;Lo;0;L;;;;;N;;;;; 12C9;ETHIOPIC SYLLABLE WU;Lo;0;L;;;;;N;;;;; 12CA;ETHIOPIC SYLLABLE WI;Lo;0;L;;;;;N;;;;; 12CB;ETHIOPIC SYLLABLE WAA;Lo;0;L;;;;;N;;;;; 12CC;ETHIOPIC SYLLABLE WEE;Lo;0;L;;;;;N;;;;; 12CD;ETHIOPIC SYLLABLE WE;Lo;0;L;;;;;N;;;;; 12CE;ETHIOPIC SYLLABLE WO;Lo;0;L;;;;;N;;;;; 12D0;ETHIOPIC SYLLABLE PHARYNGEAL A;Lo;0;L;;;;;N;;;;; 12D1;ETHIOPIC SYLLABLE PHARYNGEAL U;Lo;0;L;;;;;N;;;;; 12D2;ETHIOPIC SYLLABLE PHARYNGEAL I;Lo;0;L;;;;;N;;;;; 12D3;ETHIOPIC SYLLABLE PHARYNGEAL AA;Lo;0;L;;;;;N;;;;; 12D4;ETHIOPIC SYLLABLE PHARYNGEAL EE;Lo;0;L;;;;;N;;;;; 12D5;ETHIOPIC SYLLABLE PHARYNGEAL E;Lo;0;L;;;;;N;;;;; 12D6;ETHIOPIC SYLLABLE PHARYNGEAL O;Lo;0;L;;;;;N;;;;; 12D8;ETHIOPIC SYLLABLE ZA;Lo;0;L;;;;;N;;;;; 12D9;ETHIOPIC SYLLABLE ZU;Lo;0;L;;;;;N;;;;; 12DA;ETHIOPIC SYLLABLE ZI;Lo;0;L;;;;;N;;;;; 12DB;ETHIOPIC SYLLABLE ZAA;Lo;0;L;;;;;N;;;;; 12DC;ETHIOPIC SYLLABLE ZEE;Lo;0;L;;;;;N;;;;; 12DD;ETHIOPIC SYLLABLE ZE;Lo;0;L;;;;;N;;;;; 12DE;ETHIOPIC SYLLABLE ZO;Lo;0;L;;;;;N;;;;; 12DF;ETHIOPIC SYLLABLE ZWA;Lo;0;L;;;;;N;;;;; 12E0;ETHIOPIC SYLLABLE ZHA;Lo;0;L;;;;;N;;;;; 12E1;ETHIOPIC SYLLABLE ZHU;Lo;0;L;;;;;N;;;;; 12E2;ETHIOPIC SYLLABLE ZHI;Lo;0;L;;;;;N;;;;; 12E3;ETHIOPIC SYLLABLE ZHAA;Lo;0;L;;;;;N;;;;; 12E4;ETHIOPIC SYLLABLE ZHEE;Lo;0;L;;;;;N;;;;; 12E5;ETHIOPIC SYLLABLE ZHE;Lo;0;L;;;;;N;;;;; 12E6;ETHIOPIC SYLLABLE ZHO;Lo;0;L;;;;;N;;;;; 12E7;ETHIOPIC SYLLABLE ZHWA;Lo;0;L;;;;;N;;;;; 12E8;ETHIOPIC SYLLABLE YA;Lo;0;L;;;;;N;;;;; 12E9;ETHIOPIC SYLLABLE YU;Lo;0;L;;;;;N;;;;; 12EA;ETHIOPIC SYLLABLE YI;Lo;0;L;;;;;N;;;;; 12EB;ETHIOPIC SYLLABLE YAA;Lo;0;L;;;;;N;;;;; 12EC;ETHIOPIC SYLLABLE YEE;Lo;0;L;;;;;N;;;;; 12ED;ETHIOPIC SYLLABLE YE;Lo;0;L;;;;;N;;;;; 12EE;ETHIOPIC SYLLABLE YO;Lo;0;L;;;;;N;;;;; 12F0;ETHIOPIC SYLLABLE DA;Lo;0;L;;;;;N;;;;; 12F1;ETHIOPIC SYLLABLE DU;Lo;0;L;;;;;N;;;;; 12F2;ETHIOPIC SYLLABLE DI;Lo;0;L;;;;;N;;;;; 12F3;ETHIOPIC SYLLABLE DAA;Lo;0;L;;;;;N;;;;; 12F4;ETHIOPIC SYLLABLE DEE;Lo;0;L;;;;;N;;;;; 12F5;ETHIOPIC SYLLABLE DE;Lo;0;L;;;;;N;;;;; 12F6;ETHIOPIC SYLLABLE DO;Lo;0;L;;;;;N;;;;; 12F7;ETHIOPIC SYLLABLE DWA;Lo;0;L;;;;;N;;;;; 12F8;ETHIOPIC SYLLABLE DDA;Lo;0;L;;;;;N;;;;; 12F9;ETHIOPIC SYLLABLE DDU;Lo;0;L;;;;;N;;;;; 12FA;ETHIOPIC SYLLABLE DDI;Lo;0;L;;;;;N;;;;; 12FB;ETHIOPIC SYLLABLE DDAA;Lo;0;L;;;;;N;;;;; 12FC;ETHIOPIC SYLLABLE DDEE;Lo;0;L;;;;;N;;;;; 12FD;ETHIOPIC SYLLABLE DDE;Lo;0;L;;;;;N;;;;; 12FE;ETHIOPIC SYLLABLE DDO;Lo;0;L;;;;;N;;;;; 12FF;ETHIOPIC SYLLABLE DDWA;Lo;0;L;;;;;N;;;;; 1300;ETHIOPIC SYLLABLE JA;Lo;0;L;;;;;N;;;;; 1301;ETHIOPIC SYLLABLE JU;Lo;0;L;;;;;N;;;;; 1302;ETHIOPIC SYLLABLE JI;Lo;0;L;;;;;N;;;;; 1303;ETHIOPIC SYLLABLE JAA;Lo;0;L;;;;;N;;;;; 1304;ETHIOPIC SYLLABLE JEE;Lo;0;L;;;;;N;;;;; 1305;ETHIOPIC SYLLABLE JE;Lo;0;L;;;;;N;;;;; 1306;ETHIOPIC SYLLABLE JO;Lo;0;L;;;;;N;;;;; 1307;ETHIOPIC SYLLABLE JWA;Lo;0;L;;;;;N;;;;; 1308;ETHIOPIC SYLLABLE GA;Lo;0;L;;;;;N;;;;; 1309;ETHIOPIC SYLLABLE GU;Lo;0;L;;;;;N;;;;; 130A;ETHIOPIC SYLLABLE GI;Lo;0;L;;;;;N;;;;; 130B;ETHIOPIC SYLLABLE GAA;Lo;0;L;;;;;N;;;;; 130C;ETHIOPIC SYLLABLE GEE;Lo;0;L;;;;;N;;;;; 130D;ETHIOPIC SYLLABLE GE;Lo;0;L;;;;;N;;;;; 130E;ETHIOPIC SYLLABLE GO;Lo;0;L;;;;;N;;;;; 1310;ETHIOPIC SYLLABLE GWA;Lo;0;L;;;;;N;;;;; 1312;ETHIOPIC SYLLABLE GWI;Lo;0;L;;;;;N;;;;; 1313;ETHIOPIC SYLLABLE GWAA;Lo;0;L;;;;;N;;;;; 1314;ETHIOPIC SYLLABLE GWEE;Lo;0;L;;;;;N;;;;; 1315;ETHIOPIC SYLLABLE GWE;Lo;0;L;;;;;N;;;;; 1318;ETHIOPIC SYLLABLE GGA;Lo;0;L;;;;;N;;;;; 1319;ETHIOPIC SYLLABLE GGU;Lo;0;L;;;;;N;;;;; 131A;ETHIOPIC SYLLABLE GGI;Lo;0;L;;;;;N;;;;; 131B;ETHIOPIC SYLLABLE GGAA;Lo;0;L;;;;;N;;;;; 131C;ETHIOPIC SYLLABLE GGEE;Lo;0;L;;;;;N;;;;; 131D;ETHIOPIC SYLLABLE GGE;Lo;0;L;;;;;N;;;;; 131E;ETHIOPIC SYLLABLE GGO;Lo;0;L;;;;;N;;;;; 1320;ETHIOPIC SYLLABLE THA;Lo;0;L;;;;;N;;;;; 1321;ETHIOPIC SYLLABLE THU;Lo;0;L;;;;;N;;;;; 1322;ETHIOPIC SYLLABLE THI;Lo;0;L;;;;;N;;;;; 1323;ETHIOPIC SYLLABLE THAA;Lo;0;L;;;;;N;;;;; 1324;ETHIOPIC SYLLABLE THEE;Lo;0;L;;;;;N;;;;; 1325;ETHIOPIC SYLLABLE THE;Lo;0;L;;;;;N;;;;; 1326;ETHIOPIC SYLLABLE THO;Lo;0;L;;;;;N;;;;; 1327;ETHIOPIC SYLLABLE THWA;Lo;0;L;;;;;N;;;;; 1328;ETHIOPIC SYLLABLE CHA;Lo;0;L;;;;;N;;;;; 1329;ETHIOPIC SYLLABLE CHU;Lo;0;L;;;;;N;;;;; 132A;ETHIOPIC SYLLABLE CHI;Lo;0;L;;;;;N;;;;; 132B;ETHIOPIC SYLLABLE CHAA;Lo;0;L;;;;;N;;;;; 132C;ETHIOPIC SYLLABLE CHEE;Lo;0;L;;;;;N;;;;; 132D;ETHIOPIC SYLLABLE CHE;Lo;0;L;;;;;N;;;;; 132E;ETHIOPIC SYLLABLE CHO;Lo;0;L;;;;;N;;;;; 132F;ETHIOPIC SYLLABLE CHWA;Lo;0;L;;;;;N;;;;; 1330;ETHIOPIC SYLLABLE PHA;Lo;0;L;;;;;N;;;;; 1331;ETHIOPIC SYLLABLE PHU;Lo;0;L;;;;;N;;;;; 1332;ETHIOPIC SYLLABLE PHI;Lo;0;L;;;;;N;;;;; 1333;ETHIOPIC SYLLABLE PHAA;Lo;0;L;;;;;N;;;;; 1334;ETHIOPIC SYLLABLE PHEE;Lo;0;L;;;;;N;;;;; 1335;ETHIOPIC SYLLABLE PHE;Lo;0;L;;;;;N;;;;; 1336;ETHIOPIC SYLLABLE PHO;Lo;0;L;;;;;N;;;;; 1337;ETHIOPIC SYLLABLE PHWA;Lo;0;L;;;;;N;;;;; 1338;ETHIOPIC SYLLABLE TSA;Lo;0;L;;;;;N;;;;; 1339;ETHIOPIC SYLLABLE TSU;Lo;0;L;;;;;N;;;;; 133A;ETHIOPIC SYLLABLE TSI;Lo;0;L;;;;;N;;;;; 133B;ETHIOPIC SYLLABLE TSAA;Lo;0;L;;;;;N;;;;; 133C;ETHIOPIC SYLLABLE TSEE;Lo;0;L;;;;;N;;;;; 133D;ETHIOPIC SYLLABLE TSE;Lo;0;L;;;;;N;;;;; 133E;ETHIOPIC SYLLABLE TSO;Lo;0;L;;;;;N;;;;; 133F;ETHIOPIC SYLLABLE TSWA;Lo;0;L;;;;;N;;;;; 1340;ETHIOPIC SYLLABLE TZA;Lo;0;L;;;;;N;;;;; 1341;ETHIOPIC SYLLABLE TZU;Lo;0;L;;;;;N;;;;; 1342;ETHIOPIC SYLLABLE TZI;Lo;0;L;;;;;N;;;;; 1343;ETHIOPIC SYLLABLE TZAA;Lo;0;L;;;;;N;;;;; 1344;ETHIOPIC SYLLABLE TZEE;Lo;0;L;;;;;N;;;;; 1345;ETHIOPIC SYLLABLE TZE;Lo;0;L;;;;;N;;;;; 1346;ETHIOPIC SYLLABLE TZO;Lo;0;L;;;;;N;;;;; 1348;ETHIOPIC SYLLABLE FA;Lo;0;L;;;;;N;;;;; 1349;ETHIOPIC SYLLABLE FU;Lo;0;L;;;;;N;;;;; 134A;ETHIOPIC SYLLABLE FI;Lo;0;L;;;;;N;;;;; 134B;ETHIOPIC SYLLABLE FAA;Lo;0;L;;;;;N;;;;; 134C;ETHIOPIC SYLLABLE FEE;Lo;0;L;;;;;N;;;;; 134D;ETHIOPIC SYLLABLE FE;Lo;0;L;;;;;N;;;;; 134E;ETHIOPIC SYLLABLE FO;Lo;0;L;;;;;N;;;;; 134F;ETHIOPIC SYLLABLE FWA;Lo;0;L;;;;;N;;;;; 1350;ETHIOPIC SYLLABLE PA;Lo;0;L;;;;;N;;;;; 1351;ETHIOPIC SYLLABLE PU;Lo;0;L;;;;;N;;;;; 1352;ETHIOPIC SYLLABLE PI;Lo;0;L;;;;;N;;;;; 1353;ETHIOPIC SYLLABLE PAA;Lo;0;L;;;;;N;;;;; 1354;ETHIOPIC SYLLABLE PEE;Lo;0;L;;;;;N;;;;; 1355;ETHIOPIC SYLLABLE PE;Lo;0;L;;;;;N;;;;; 1356;ETHIOPIC SYLLABLE PO;Lo;0;L;;;;;N;;;;; 1357;ETHIOPIC SYLLABLE PWA;Lo;0;L;;;;;N;;;;; 1358;ETHIOPIC SYLLABLE RYA;Lo;0;L;;;;;N;;;;; 1359;ETHIOPIC SYLLABLE MYA;Lo;0;L;;;;;N;;;;; 135A;ETHIOPIC SYLLABLE FYA;Lo;0;L;;;;;N;;;;; 1361;ETHIOPIC WORDSPACE;Po;0;L;;;;;N;;;;; 1362;ETHIOPIC FULL STOP;Po;0;L;;;;;N;;;;; 1363;ETHIOPIC COMMA;Po;0;L;;;;;N;;;;; 1364;ETHIOPIC SEMICOLON;Po;0;L;;;;;N;;;;; 1365;ETHIOPIC COLON;Po;0;L;;;;;N;;;;; 1366;ETHIOPIC PREFACE COLON;Po;0;L;;;;;N;;;;; 1367;ETHIOPIC QUESTION MARK;Po;0;L;;;;;N;;;;; 1368;ETHIOPIC PARAGRAPH SEPARATOR;Po;0;L;;;;;N;;;;; 1369;ETHIOPIC DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 136A;ETHIOPIC DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 136B;ETHIOPIC DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 136C;ETHIOPIC DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 136D;ETHIOPIC DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 136E;ETHIOPIC DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 136F;ETHIOPIC DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 1370;ETHIOPIC DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 1371;ETHIOPIC DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 1372;ETHIOPIC NUMBER TEN;No;0;L;;;;10;N;;;;; 1373;ETHIOPIC NUMBER TWENTY;No;0;L;;;;20;N;;;;; 1374;ETHIOPIC NUMBER THIRTY;No;0;L;;;;30;N;;;;; 1375;ETHIOPIC NUMBER FORTY;No;0;L;;;;40;N;;;;; 1376;ETHIOPIC NUMBER FIFTY;No;0;L;;;;50;N;;;;; 1377;ETHIOPIC NUMBER SIXTY;No;0;L;;;;60;N;;;;; 1378;ETHIOPIC NUMBER SEVENTY;No;0;L;;;;70;N;;;;; 1379;ETHIOPIC NUMBER EIGHTY;No;0;L;;;;80;N;;;;; 137A;ETHIOPIC NUMBER NINETY;No;0;L;;;;90;N;;;;; 137B;ETHIOPIC NUMBER HUNDRED;No;0;L;;;;100;N;;;;; 137C;ETHIOPIC NUMBER TEN THOUSAND;No;0;L;;;;10000;N;;;;; 13A0;CHEROKEE LETTER A;Lo;0;L;;;;;N;;;;; 13A1;CHEROKEE LETTER E;Lo;0;L;;;;;N;;;;; 13A2;CHEROKEE LETTER I;Lo;0;L;;;;;N;;;;; 13A3;CHEROKEE LETTER O;Lo;0;L;;;;;N;;;;; 13A4;CHEROKEE LETTER U;Lo;0;L;;;;;N;;;;; 13A5;CHEROKEE LETTER V;Lo;0;L;;;;;N;;;;; 13A6;CHEROKEE LETTER GA;Lo;0;L;;;;;N;;;;; 13A7;CHEROKEE LETTER KA;Lo;0;L;;;;;N;;;;; 13A8;CHEROKEE LETTER GE;Lo;0;L;;;;;N;;;;; 13A9;CHEROKEE LETTER GI;Lo;0;L;;;;;N;;;;; 13AA;CHEROKEE LETTER GO;Lo;0;L;;;;;N;;;;; 13AB;CHEROKEE LETTER GU;Lo;0;L;;;;;N;;;;; 13AC;CHEROKEE LETTER GV;Lo;0;L;;;;;N;;;;; 13AD;CHEROKEE LETTER HA;Lo;0;L;;;;;N;;;;; 13AE;CHEROKEE LETTER HE;Lo;0;L;;;;;N;;;;; 13AF;CHEROKEE LETTER HI;Lo;0;L;;;;;N;;;;; 13B0;CHEROKEE LETTER HO;Lo;0;L;;;;;N;;;;; 13B1;CHEROKEE LETTER HU;Lo;0;L;;;;;N;;;;; 13B2;CHEROKEE LETTER HV;Lo;0;L;;;;;N;;;;; 13B3;CHEROKEE LETTER LA;Lo;0;L;;;;;N;;;;; 13B4;CHEROKEE LETTER LE;Lo;0;L;;;;;N;;;;; 13B5;CHEROKEE LETTER LI;Lo;0;L;;;;;N;;;;; 13B6;CHEROKEE LETTER LO;Lo;0;L;;;;;N;;;;; 13B7;CHEROKEE LETTER LU;Lo;0;L;;;;;N;;;;; 13B8;CHEROKEE LETTER LV;Lo;0;L;;;;;N;;;;; 13B9;CHEROKEE LETTER MA;Lo;0;L;;;;;N;;;;; 13BA;CHEROKEE LETTER ME;Lo;0;L;;;;;N;;;;; 13BB;CHEROKEE LETTER MI;Lo;0;L;;;;;N;;;;; 13BC;CHEROKEE LETTER MO;Lo;0;L;;;;;N;;;;; 13BD;CHEROKEE LETTER MU;Lo;0;L;;;;;N;;;;; 13BE;CHEROKEE LETTER NA;Lo;0;L;;;;;N;;;;; 13BF;CHEROKEE LETTER HNA;Lo;0;L;;;;;N;;;;; 13C0;CHEROKEE LETTER NAH;Lo;0;L;;;;;N;;;;; 13C1;CHEROKEE LETTER NE;Lo;0;L;;;;;N;;;;; 13C2;CHEROKEE LETTER NI;Lo;0;L;;;;;N;;;;; 13C3;CHEROKEE LETTER NO;Lo;0;L;;;;;N;;;;; 13C4;CHEROKEE LETTER NU;Lo;0;L;;;;;N;;;;; 13C5;CHEROKEE LETTER NV;Lo;0;L;;;;;N;;;;; 13C6;CHEROKEE LETTER QUA;Lo;0;L;;;;;N;;;;; 13C7;CHEROKEE LETTER QUE;Lo;0;L;;;;;N;;;;; 13C8;CHEROKEE LETTER QUI;Lo;0;L;;;;;N;;;;; 13C9;CHEROKEE LETTER QUO;Lo;0;L;;;;;N;;;;; 13CA;CHEROKEE LETTER QUU;Lo;0;L;;;;;N;;;;; 13CB;CHEROKEE LETTER QUV;Lo;0;L;;;;;N;;;;; 13CC;CHEROKEE LETTER SA;Lo;0;L;;;;;N;;;;; 13CD;CHEROKEE LETTER S;Lo;0;L;;;;;N;;;;; 13CE;CHEROKEE LETTER SE;Lo;0;L;;;;;N;;;;; 13CF;CHEROKEE LETTER SI;Lo;0;L;;;;;N;;;;; 13D0;CHEROKEE LETTER SO;Lo;0;L;;;;;N;;;;; 13D1;CHEROKEE LETTER SU;Lo;0;L;;;;;N;;;;; 13D2;CHEROKEE LETTER SV;Lo;0;L;;;;;N;;;;; 13D3;CHEROKEE LETTER DA;Lo;0;L;;;;;N;;;;; 13D4;CHEROKEE LETTER TA;Lo;0;L;;;;;N;;;;; 13D5;CHEROKEE LETTER DE;Lo;0;L;;;;;N;;;;; 13D6;CHEROKEE LETTER TE;Lo;0;L;;;;;N;;;;; 13D7;CHEROKEE LETTER DI;Lo;0;L;;;;;N;;;;; 13D8;CHEROKEE LETTER TI;Lo;0;L;;;;;N;;;;; 13D9;CHEROKEE LETTER DO;Lo;0;L;;;;;N;;;;; 13DA;CHEROKEE LETTER DU;Lo;0;L;;;;;N;;;;; 13DB;CHEROKEE LETTER DV;Lo;0;L;;;;;N;;;;; 13DC;CHEROKEE LETTER DLA;Lo;0;L;;;;;N;;;;; 13DD;CHEROKEE LETTER TLA;Lo;0;L;;;;;N;;;;; 13DE;CHEROKEE LETTER TLE;Lo;0;L;;;;;N;;;;; 13DF;CHEROKEE LETTER TLI;Lo;0;L;;;;;N;;;;; 13E0;CHEROKEE LETTER TLO;Lo;0;L;;;;;N;;;;; 13E1;CHEROKEE LETTER TLU;Lo;0;L;;;;;N;;;;; 13E2;CHEROKEE LETTER TLV;Lo;0;L;;;;;N;;;;; 13E3;CHEROKEE LETTER TSA;Lo;0;L;;;;;N;;;;; 13E4;CHEROKEE LETTER TSE;Lo;0;L;;;;;N;;;;; 13E5;CHEROKEE LETTER TSI;Lo;0;L;;;;;N;;;;; 13E6;CHEROKEE LETTER TSO;Lo;0;L;;;;;N;;;;; 13E7;CHEROKEE LETTER TSU;Lo;0;L;;;;;N;;;;; 13E8;CHEROKEE LETTER TSV;Lo;0;L;;;;;N;;;;; 13E9;CHEROKEE LETTER WA;Lo;0;L;;;;;N;;;;; 13EA;CHEROKEE LETTER WE;Lo;0;L;;;;;N;;;;; 13EB;CHEROKEE LETTER WI;Lo;0;L;;;;;N;;;;; 13EC;CHEROKEE LETTER WO;Lo;0;L;;;;;N;;;;; 13ED;CHEROKEE LETTER WU;Lo;0;L;;;;;N;;;;; 13EE;CHEROKEE LETTER WV;Lo;0;L;;;;;N;;;;; 13EF;CHEROKEE LETTER YA;Lo;0;L;;;;;N;;;;; 13F0;CHEROKEE LETTER YE;Lo;0;L;;;;;N;;;;; 13F1;CHEROKEE LETTER YI;Lo;0;L;;;;;N;;;;; 13F2;CHEROKEE LETTER YO;Lo;0;L;;;;;N;;;;; 13F3;CHEROKEE LETTER YU;Lo;0;L;;;;;N;;;;; 13F4;CHEROKEE LETTER YV;Lo;0;L;;;;;N;;;;; 1401;CANADIAN SYLLABICS E;Lo;0;L;;;;;N;;;;; 1402;CANADIAN SYLLABICS AAI;Lo;0;L;;;;;N;;;;; 1403;CANADIAN SYLLABICS I;Lo;0;L;;;;;N;;;;; 1404;CANADIAN SYLLABICS II;Lo;0;L;;;;;N;;;;; 1405;CANADIAN SYLLABICS O;Lo;0;L;;;;;N;;;;; 1406;CANADIAN SYLLABICS OO;Lo;0;L;;;;;N;;;;; 1407;CANADIAN SYLLABICS Y-CREE OO;Lo;0;L;;;;;N;;;;; 1408;CANADIAN SYLLABICS CARRIER EE;Lo;0;L;;;;;N;;;;; 1409;CANADIAN SYLLABICS CARRIER I;Lo;0;L;;;;;N;;;;; 140A;CANADIAN SYLLABICS A;Lo;0;L;;;;;N;;;;; 140B;CANADIAN SYLLABICS AA;Lo;0;L;;;;;N;;;;; 140C;CANADIAN SYLLABICS WE;Lo;0;L;;;;;N;;;;; 140D;CANADIAN SYLLABICS WEST-CREE WE;Lo;0;L;;;;;N;;;;; 140E;CANADIAN SYLLABICS WI;Lo;0;L;;;;;N;;;;; 140F;CANADIAN SYLLABICS WEST-CREE WI;Lo;0;L;;;;;N;;;;; 1410;CANADIAN SYLLABICS WII;Lo;0;L;;;;;N;;;;; 1411;CANADIAN SYLLABICS WEST-CREE WII;Lo;0;L;;;;;N;;;;; 1412;CANADIAN SYLLABICS WO;Lo;0;L;;;;;N;;;;; 1413;CANADIAN SYLLABICS WEST-CREE WO;Lo;0;L;;;;;N;;;;; 1414;CANADIAN SYLLABICS WOO;Lo;0;L;;;;;N;;;;; 1415;CANADIAN SYLLABICS WEST-CREE WOO;Lo;0;L;;;;;N;;;;; 1416;CANADIAN SYLLABICS NASKAPI WOO;Lo;0;L;;;;;N;;;;; 1417;CANADIAN SYLLABICS WA;Lo;0;L;;;;;N;;;;; 1418;CANADIAN SYLLABICS WEST-CREE WA;Lo;0;L;;;;;N;;;;; 1419;CANADIAN SYLLABICS WAA;Lo;0;L;;;;;N;;;;; 141A;CANADIAN SYLLABICS WEST-CREE WAA;Lo;0;L;;;;;N;;;;; 141B;CANADIAN SYLLABICS NASKAPI WAA;Lo;0;L;;;;;N;;;;; 141C;CANADIAN SYLLABICS AI;Lo;0;L;;;;;N;;;;; 141D;CANADIAN SYLLABICS Y-CREE W;Lo;0;L;;;;;N;;;;; 141E;CANADIAN SYLLABICS GLOTTAL STOP;Lo;0;L;;;;;N;;;;; 141F;CANADIAN SYLLABICS FINAL ACUTE;Lo;0;L;;;;;N;;;;; 1420;CANADIAN SYLLABICS FINAL GRAVE;Lo;0;L;;;;;N;;;;; 1421;CANADIAN SYLLABICS FINAL BOTTOM HALF RING;Lo;0;L;;;;;N;;;;; 1422;CANADIAN SYLLABICS FINAL TOP HALF RING;Lo;0;L;;;;;N;;;;; 1423;CANADIAN SYLLABICS FINAL RIGHT HALF RING;Lo;0;L;;;;;N;;;;; 1424;CANADIAN SYLLABICS FINAL RING;Lo;0;L;;;;;N;;;;; 1425;CANADIAN SYLLABICS FINAL DOUBLE ACUTE;Lo;0;L;;;;;N;;;;; 1426;CANADIAN SYLLABICS FINAL DOUBLE SHORT VERTICAL STROKES;Lo;0;L;;;;;N;;;;; 1427;CANADIAN SYLLABICS FINAL MIDDLE DOT;Lo;0;L;;;;;N;;;;; 1428;CANADIAN SYLLABICS FINAL SHORT HORIZONTAL STROKE;Lo;0;L;;;;;N;;;;; 1429;CANADIAN SYLLABICS FINAL PLUS;Lo;0;L;;;;;N;;;;; 142A;CANADIAN SYLLABICS FINAL DOWN TACK;Lo;0;L;;;;;N;;;;; 142B;CANADIAN SYLLABICS EN;Lo;0;L;;;;;N;;;;; 142C;CANADIAN SYLLABICS IN;Lo;0;L;;;;;N;;;;; 142D;CANADIAN SYLLABICS ON;Lo;0;L;;;;;N;;;;; 142E;CANADIAN SYLLABICS AN;Lo;0;L;;;;;N;;;;; 142F;CANADIAN SYLLABICS PE;Lo;0;L;;;;;N;;;;; 1430;CANADIAN SYLLABICS PAAI;Lo;0;L;;;;;N;;;;; 1431;CANADIAN SYLLABICS PI;Lo;0;L;;;;;N;;;;; 1432;CANADIAN SYLLABICS PII;Lo;0;L;;;;;N;;;;; 1433;CANADIAN SYLLABICS PO;Lo;0;L;;;;;N;;;;; 1434;CANADIAN SYLLABICS POO;Lo;0;L;;;;;N;;;;; 1435;CANADIAN SYLLABICS Y-CREE POO;Lo;0;L;;;;;N;;;;; 1436;CANADIAN SYLLABICS CARRIER HEE;Lo;0;L;;;;;N;;;;; 1437;CANADIAN SYLLABICS CARRIER HI;Lo;0;L;;;;;N;;;;; 1438;CANADIAN SYLLABICS PA;Lo;0;L;;;;;N;;;;; 1439;CANADIAN SYLLABICS PAA;Lo;0;L;;;;;N;;;;; 143A;CANADIAN SYLLABICS PWE;Lo;0;L;;;;;N;;;;; 143B;CANADIAN SYLLABICS WEST-CREE PWE;Lo;0;L;;;;;N;;;;; 143C;CANADIAN SYLLABICS PWI;Lo;0;L;;;;;N;;;;; 143D;CANADIAN SYLLABICS WEST-CREE PWI;Lo;0;L;;;;;N;;;;; 143E;CANADIAN SYLLABICS PWII;Lo;0;L;;;;;N;;;;; 143F;CANADIAN SYLLABICS WEST-CREE PWII;Lo;0;L;;;;;N;;;;; 1440;CANADIAN SYLLABICS PWO;Lo;0;L;;;;;N;;;;; 1441;CANADIAN SYLLABICS WEST-CREE PWO;Lo;0;L;;;;;N;;;;; 1442;CANADIAN SYLLABICS PWOO;Lo;0;L;;;;;N;;;;; 1443;CANADIAN SYLLABICS WEST-CREE PWOO;Lo;0;L;;;;;N;;;;; 1444;CANADIAN SYLLABICS PWA;Lo;0;L;;;;;N;;;;; 1445;CANADIAN SYLLABICS WEST-CREE PWA;Lo;0;L;;;;;N;;;;; 1446;CANADIAN SYLLABICS PWAA;Lo;0;L;;;;;N;;;;; 1447;CANADIAN SYLLABICS WEST-CREE PWAA;Lo;0;L;;;;;N;;;;; 1448;CANADIAN SYLLABICS Y-CREE PWAA;Lo;0;L;;;;;N;;;;; 1449;CANADIAN SYLLABICS P;Lo;0;L;;;;;N;;;;; 144A;CANADIAN SYLLABICS WEST-CREE P;Lo;0;L;;;;;N;;;;; 144B;CANADIAN SYLLABICS CARRIER H;Lo;0;L;;;;;N;;;;; 144C;CANADIAN SYLLABICS TE;Lo;0;L;;;;;N;;;;; 144D;CANADIAN SYLLABICS TAAI;Lo;0;L;;;;;N;;;;; 144E;CANADIAN SYLLABICS TI;Lo;0;L;;;;;N;;;;; 144F;CANADIAN SYLLABICS TII;Lo;0;L;;;;;N;;;;; 1450;CANADIAN SYLLABICS TO;Lo;0;L;;;;;N;;;;; 1451;CANADIAN SYLLABICS TOO;Lo;0;L;;;;;N;;;;; 1452;CANADIAN SYLLABICS Y-CREE TOO;Lo;0;L;;;;;N;;;;; 1453;CANADIAN SYLLABICS CARRIER DEE;Lo;0;L;;;;;N;;;;; 1454;CANADIAN SYLLABICS CARRIER DI;Lo;0;L;;;;;N;;;;; 1455;CANADIAN SYLLABICS TA;Lo;0;L;;;;;N;;;;; 1456;CANADIAN SYLLABICS TAA;Lo;0;L;;;;;N;;;;; 1457;CANADIAN SYLLABICS TWE;Lo;0;L;;;;;N;;;;; 1458;CANADIAN SYLLABICS WEST-CREE TWE;Lo;0;L;;;;;N;;;;; 1459;CANADIAN SYLLABICS TWI;Lo;0;L;;;;;N;;;;; 145A;CANADIAN SYLLABICS WEST-CREE TWI;Lo;0;L;;;;;N;;;;; 145B;CANADIAN SYLLABICS TWII;Lo;0;L;;;;;N;;;;; 145C;CANADIAN SYLLABICS WEST-CREE TWII;Lo;0;L;;;;;N;;;;; 145D;CANADIAN SYLLABICS TWO;Lo;0;L;;;;;N;;;;; 145E;CANADIAN SYLLABICS WEST-CREE TWO;Lo;0;L;;;;;N;;;;; 145F;CANADIAN SYLLABICS TWOO;Lo;0;L;;;;;N;;;;; 1460;CANADIAN SYLLABICS WEST-CREE TWOO;Lo;0;L;;;;;N;;;;; 1461;CANADIAN SYLLABICS TWA;Lo;0;L;;;;;N;;;;; 1462;CANADIAN SYLLABICS WEST-CREE TWA;Lo;0;L;;;;;N;;;;; 1463;CANADIAN SYLLABICS TWAA;Lo;0;L;;;;;N;;;;; 1464;CANADIAN SYLLABICS WEST-CREE TWAA;Lo;0;L;;;;;N;;;;; 1465;CANADIAN SYLLABICS NASKAPI TWAA;Lo;0;L;;;;;N;;;;; 1466;CANADIAN SYLLABICS T;Lo;0;L;;;;;N;;;;; 1467;CANADIAN SYLLABICS TTE;Lo;0;L;;;;;N;;;;; 1468;CANADIAN SYLLABICS TTI;Lo;0;L;;;;;N;;;;; 1469;CANADIAN SYLLABICS TTO;Lo;0;L;;;;;N;;;;; 146A;CANADIAN SYLLABICS TTA;Lo;0;L;;;;;N;;;;; 146B;CANADIAN SYLLABICS KE;Lo;0;L;;;;;N;;;;; 146C;CANADIAN SYLLABICS KAAI;Lo;0;L;;;;;N;;;;; 146D;CANADIAN SYLLABICS KI;Lo;0;L;;;;;N;;;;; 146E;CANADIAN SYLLABICS KII;Lo;0;L;;;;;N;;;;; 146F;CANADIAN SYLLABICS KO;Lo;0;L;;;;;N;;;;; 1470;CANADIAN SYLLABICS KOO;Lo;0;L;;;;;N;;;;; 1471;CANADIAN SYLLABICS Y-CREE KOO;Lo;0;L;;;;;N;;;;; 1472;CANADIAN SYLLABICS KA;Lo;0;L;;;;;N;;;;; 1473;CANADIAN SYLLABICS KAA;Lo;0;L;;;;;N;;;;; 1474;CANADIAN SYLLABICS KWE;Lo;0;L;;;;;N;;;;; 1475;CANADIAN SYLLABICS WEST-CREE KWE;Lo;0;L;;;;;N;;;;; 1476;CANADIAN SYLLABICS KWI;Lo;0;L;;;;;N;;;;; 1477;CANADIAN SYLLABICS WEST-CREE KWI;Lo;0;L;;;;;N;;;;; 1478;CANADIAN SYLLABICS KWII;Lo;0;L;;;;;N;;;;; 1479;CANADIAN SYLLABICS WEST-CREE KWII;Lo;0;L;;;;;N;;;;; 147A;CANADIAN SYLLABICS KWO;Lo;0;L;;;;;N;;;;; 147B;CANADIAN SYLLABICS WEST-CREE KWO;Lo;0;L;;;;;N;;;;; 147C;CANADIAN SYLLABICS KWOO;Lo;0;L;;;;;N;;;;; 147D;CANADIAN SYLLABICS WEST-CREE KWOO;Lo;0;L;;;;;N;;;;; 147E;CANADIAN SYLLABICS KWA;Lo;0;L;;;;;N;;;;; 147F;CANADIAN SYLLABICS WEST-CREE KWA;Lo;0;L;;;;;N;;;;; 1480;CANADIAN SYLLABICS KWAA;Lo;0;L;;;;;N;;;;; 1481;CANADIAN SYLLABICS WEST-CREE KWAA;Lo;0;L;;;;;N;;;;; 1482;CANADIAN SYLLABICS NASKAPI KWAA;Lo;0;L;;;;;N;;;;; 1483;CANADIAN SYLLABICS K;Lo;0;L;;;;;N;;;;; 1484;CANADIAN SYLLABICS KW;Lo;0;L;;;;;N;;;;; 1485;CANADIAN SYLLABICS SOUTH-SLAVEY KEH;Lo;0;L;;;;;N;;;;; 1486;CANADIAN SYLLABICS SOUTH-SLAVEY KIH;Lo;0;L;;;;;N;;;;; 1487;CANADIAN SYLLABICS SOUTH-SLAVEY KOH;Lo;0;L;;;;;N;;;;; 1488;CANADIAN SYLLABICS SOUTH-SLAVEY KAH;Lo;0;L;;;;;N;;;;; 1489;CANADIAN SYLLABICS CE;Lo;0;L;;;;;N;;;;; 148A;CANADIAN SYLLABICS CAAI;Lo;0;L;;;;;N;;;;; 148B;CANADIAN SYLLABICS CI;Lo;0;L;;;;;N;;;;; 148C;CANADIAN SYLLABICS CII;Lo;0;L;;;;;N;;;;; 148D;CANADIAN SYLLABICS CO;Lo;0;L;;;;;N;;;;; 148E;CANADIAN SYLLABICS COO;Lo;0;L;;;;;N;;;;; 148F;CANADIAN SYLLABICS Y-CREE COO;Lo;0;L;;;;;N;;;;; 1490;CANADIAN SYLLABICS CA;Lo;0;L;;;;;N;;;;; 1491;CANADIAN SYLLABICS CAA;Lo;0;L;;;;;N;;;;; 1492;CANADIAN SYLLABICS CWE;Lo;0;L;;;;;N;;;;; 1493;CANADIAN SYLLABICS WEST-CREE CWE;Lo;0;L;;;;;N;;;;; 1494;CANADIAN SYLLABICS CWI;Lo;0;L;;;;;N;;;;; 1495;CANADIAN SYLLABICS WEST-CREE CWI;Lo;0;L;;;;;N;;;;; 1496;CANADIAN SYLLABICS CWII;Lo;0;L;;;;;N;;;;; 1497;CANADIAN SYLLABICS WEST-CREE CWII;Lo;0;L;;;;;N;;;;; 1498;CANADIAN SYLLABICS CWO;Lo;0;L;;;;;N;;;;; 1499;CANADIAN SYLLABICS WEST-CREE CWO;Lo;0;L;;;;;N;;;;; 149A;CANADIAN SYLLABICS CWOO;Lo;0;L;;;;;N;;;;; 149B;CANADIAN SYLLABICS WEST-CREE CWOO;Lo;0;L;;;;;N;;;;; 149C;CANADIAN SYLLABICS CWA;Lo;0;L;;;;;N;;;;; 149D;CANADIAN SYLLABICS WEST-CREE CWA;Lo;0;L;;;;;N;;;;; 149E;CANADIAN SYLLABICS CWAA;Lo;0;L;;;;;N;;;;; 149F;CANADIAN SYLLABICS WEST-CREE CWAA;Lo;0;L;;;;;N;;;;; 14A0;CANADIAN SYLLABICS NASKAPI CWAA;Lo;0;L;;;;;N;;;;; 14A1;CANADIAN SYLLABICS C;Lo;0;L;;;;;N;;;;; 14A2;CANADIAN SYLLABICS SAYISI TH;Lo;0;L;;;;;N;;;;; 14A3;CANADIAN SYLLABICS ME;Lo;0;L;;;;;N;;;;; 14A4;CANADIAN SYLLABICS MAAI;Lo;0;L;;;;;N;;;;; 14A5;CANADIAN SYLLABICS MI;Lo;0;L;;;;;N;;;;; 14A6;CANADIAN SYLLABICS MII;Lo;0;L;;;;;N;;;;; 14A7;CANADIAN SYLLABICS MO;Lo;0;L;;;;;N;;;;; 14A8;CANADIAN SYLLABICS MOO;Lo;0;L;;;;;N;;;;; 14A9;CANADIAN SYLLABICS Y-CREE MOO;Lo;0;L;;;;;N;;;;; 14AA;CANADIAN SYLLABICS MA;Lo;0;L;;;;;N;;;;; 14AB;CANADIAN SYLLABICS MAA;Lo;0;L;;;;;N;;;;; 14AC;CANADIAN SYLLABICS MWE;Lo;0;L;;;;;N;;;;; 14AD;CANADIAN SYLLABICS WEST-CREE MWE;Lo;0;L;;;;;N;;;;; 14AE;CANADIAN SYLLABICS MWI;Lo;0;L;;;;;N;;;;; 14AF;CANADIAN SYLLABICS WEST-CREE MWI;Lo;0;L;;;;;N;;;;; 14B0;CANADIAN SYLLABICS MWII;Lo;0;L;;;;;N;;;;; 14B1;CANADIAN SYLLABICS WEST-CREE MWII;Lo;0;L;;;;;N;;;;; 14B2;CANADIAN SYLLABICS MWO;Lo;0;L;;;;;N;;;;; 14B3;CANADIAN SYLLABICS WEST-CREE MWO;Lo;0;L;;;;;N;;;;; 14B4;CANADIAN SYLLABICS MWOO;Lo;0;L;;;;;N;;;;; 14B5;CANADIAN SYLLABICS WEST-CREE MWOO;Lo;0;L;;;;;N;;;;; 14B6;CANADIAN SYLLABICS MWA;Lo;0;L;;;;;N;;;;; 14B7;CANADIAN SYLLABICS WEST-CREE MWA;Lo;0;L;;;;;N;;;;; 14B8;CANADIAN SYLLABICS MWAA;Lo;0;L;;;;;N;;;;; 14B9;CANADIAN SYLLABICS WEST-CREE MWAA;Lo;0;L;;;;;N;;;;; 14BA;CANADIAN SYLLABICS NASKAPI MWAA;Lo;0;L;;;;;N;;;;; 14BB;CANADIAN SYLLABICS M;Lo;0;L;;;;;N;;;;; 14BC;CANADIAN SYLLABICS WEST-CREE M;Lo;0;L;;;;;N;;;;; 14BD;CANADIAN SYLLABICS MH;Lo;0;L;;;;;N;;;;; 14BE;CANADIAN SYLLABICS ATHAPASCAN M;Lo;0;L;;;;;N;;;;; 14BF;CANADIAN SYLLABICS SAYISI M;Lo;0;L;;;;;N;;;;; 14C0;CANADIAN SYLLABICS NE;Lo;0;L;;;;;N;;;;; 14C1;CANADIAN SYLLABICS NAAI;Lo;0;L;;;;;N;;;;; 14C2;CANADIAN SYLLABICS NI;Lo;0;L;;;;;N;;;;; 14C3;CANADIAN SYLLABICS NII;Lo;0;L;;;;;N;;;;; 14C4;CANADIAN SYLLABICS NO;Lo;0;L;;;;;N;;;;; 14C5;CANADIAN SYLLABICS NOO;Lo;0;L;;;;;N;;;;; 14C6;CANADIAN SYLLABICS Y-CREE NOO;Lo;0;L;;;;;N;;;;; 14C7;CANADIAN SYLLABICS NA;Lo;0;L;;;;;N;;;;; 14C8;CANADIAN SYLLABICS NAA;Lo;0;L;;;;;N;;;;; 14C9;CANADIAN SYLLABICS NWE;Lo;0;L;;;;;N;;;;; 14CA;CANADIAN SYLLABICS WEST-CREE NWE;Lo;0;L;;;;;N;;;;; 14CB;CANADIAN SYLLABICS NWA;Lo;0;L;;;;;N;;;;; 14CC;CANADIAN SYLLABICS WEST-CREE NWA;Lo;0;L;;;;;N;;;;; 14CD;CANADIAN SYLLABICS NWAA;Lo;0;L;;;;;N;;;;; 14CE;CANADIAN SYLLABICS WEST-CREE NWAA;Lo;0;L;;;;;N;;;;; 14CF;CANADIAN SYLLABICS NASKAPI NWAA;Lo;0;L;;;;;N;;;;; 14D0;CANADIAN SYLLABICS N;Lo;0;L;;;;;N;;;;; 14D1;CANADIAN SYLLABICS CARRIER NG;Lo;0;L;;;;;N;;;;; 14D2;CANADIAN SYLLABICS NH;Lo;0;L;;;;;N;;;;; 14D3;CANADIAN SYLLABICS LE;Lo;0;L;;;;;N;;;;; 14D4;CANADIAN SYLLABICS LAAI;Lo;0;L;;;;;N;;;;; 14D5;CANADIAN SYLLABICS LI;Lo;0;L;;;;;N;;;;; 14D6;CANADIAN SYLLABICS LII;Lo;0;L;;;;;N;;;;; 14D7;CANADIAN SYLLABICS LO;Lo;0;L;;;;;N;;;;; 14D8;CANADIAN SYLLABICS LOO;Lo;0;L;;;;;N;;;;; 14D9;CANADIAN SYLLABICS Y-CREE LOO;Lo;0;L;;;;;N;;;;; 14DA;CANADIAN SYLLABICS LA;Lo;0;L;;;;;N;;;;; 14DB;CANADIAN SYLLABICS LAA;Lo;0;L;;;;;N;;;;; 14DC;CANADIAN SYLLABICS LWE;Lo;0;L;;;;;N;;;;; 14DD;CANADIAN SYLLABICS WEST-CREE LWE;Lo;0;L;;;;;N;;;;; 14DE;CANADIAN SYLLABICS LWI;Lo;0;L;;;;;N;;;;; 14DF;CANADIAN SYLLABICS WEST-CREE LWI;Lo;0;L;;;;;N;;;;; 14E0;CANADIAN SYLLABICS LWII;Lo;0;L;;;;;N;;;;; 14E1;CANADIAN SYLLABICS WEST-CREE LWII;Lo;0;L;;;;;N;;;;; 14E2;CANADIAN SYLLABICS LWO;Lo;0;L;;;;;N;;;;; 14E3;CANADIAN SYLLABICS WEST-CREE LWO;Lo;0;L;;;;;N;;;;; 14E4;CANADIAN SYLLABICS LWOO;Lo;0;L;;;;;N;;;;; 14E5;CANADIAN SYLLABICS WEST-CREE LWOO;Lo;0;L;;;;;N;;;;; 14E6;CANADIAN SYLLABICS LWA;Lo;0;L;;;;;N;;;;; 14E7;CANADIAN SYLLABICS WEST-CREE LWA;Lo;0;L;;;;;N;;;;; 14E8;CANADIAN SYLLABICS LWAA;Lo;0;L;;;;;N;;;;; 14E9;CANADIAN SYLLABICS WEST-CREE LWAA;Lo;0;L;;;;;N;;;;; 14EA;CANADIAN SYLLABICS L;Lo;0;L;;;;;N;;;;; 14EB;CANADIAN SYLLABICS WEST-CREE L;Lo;0;L;;;;;N;;;;; 14EC;CANADIAN SYLLABICS MEDIAL L;Lo;0;L;;;;;N;;;;; 14ED;CANADIAN SYLLABICS SE;Lo;0;L;;;;;N;;;;; 14EE;CANADIAN SYLLABICS SAAI;Lo;0;L;;;;;N;;;;; 14EF;CANADIAN SYLLABICS SI;Lo;0;L;;;;;N;;;;; 14F0;CANADIAN SYLLABICS SII;Lo;0;L;;;;;N;;;;; 14F1;CANADIAN SYLLABICS SO;Lo;0;L;;;;;N;;;;; 14F2;CANADIAN SYLLABICS SOO;Lo;0;L;;;;;N;;;;; 14F3;CANADIAN SYLLABICS Y-CREE SOO;Lo;0;L;;;;;N;;;;; 14F4;CANADIAN SYLLABICS SA;Lo;0;L;;;;;N;;;;; 14F5;CANADIAN SYLLABICS SAA;Lo;0;L;;;;;N;;;;; 14F6;CANADIAN SYLLABICS SWE;Lo;0;L;;;;;N;;;;; 14F7;CANADIAN SYLLABICS WEST-CREE SWE;Lo;0;L;;;;;N;;;;; 14F8;CANADIAN SYLLABICS SWI;Lo;0;L;;;;;N;;;;; 14F9;CANADIAN SYLLABICS WEST-CREE SWI;Lo;0;L;;;;;N;;;;; 14FA;CANADIAN SYLLABICS SWII;Lo;0;L;;;;;N;;;;; 14FB;CANADIAN SYLLABICS WEST-CREE SWII;Lo;0;L;;;;;N;;;;; 14FC;CANADIAN SYLLABICS SWO;Lo;0;L;;;;;N;;;;; 14FD;CANADIAN SYLLABICS WEST-CREE SWO;Lo;0;L;;;;;N;;;;; 14FE;CANADIAN SYLLABICS SWOO;Lo;0;L;;;;;N;;;;; 14FF;CANADIAN SYLLABICS WEST-CREE SWOO;Lo;0;L;;;;;N;;;;; 1500;CANADIAN SYLLABICS SWA;Lo;0;L;;;;;N;;;;; 1501;CANADIAN SYLLABICS WEST-CREE SWA;Lo;0;L;;;;;N;;;;; 1502;CANADIAN SYLLABICS SWAA;Lo;0;L;;;;;N;;;;; 1503;CANADIAN SYLLABICS WEST-CREE SWAA;Lo;0;L;;;;;N;;;;; 1504;CANADIAN SYLLABICS NASKAPI SWAA;Lo;0;L;;;;;N;;;;; 1505;CANADIAN SYLLABICS S;Lo;0;L;;;;;N;;;;; 1506;CANADIAN SYLLABICS ATHAPASCAN S;Lo;0;L;;;;;N;;;;; 1507;CANADIAN SYLLABICS SW;Lo;0;L;;;;;N;;;;; 1508;CANADIAN SYLLABICS BLACKFOOT S;Lo;0;L;;;;;N;;;;; 1509;CANADIAN SYLLABICS MOOSE-CREE SK;Lo;0;L;;;;;N;;;;; 150A;CANADIAN SYLLABICS NASKAPI SKW;Lo;0;L;;;;;N;;;;; 150B;CANADIAN SYLLABICS NASKAPI S-W;Lo;0;L;;;;;N;;;;; 150C;CANADIAN SYLLABICS NASKAPI SPWA;Lo;0;L;;;;;N;;;;; 150D;CANADIAN SYLLABICS NASKAPI STWA;Lo;0;L;;;;;N;;;;; 150E;CANADIAN SYLLABICS NASKAPI SKWA;Lo;0;L;;;;;N;;;;; 150F;CANADIAN SYLLABICS NASKAPI SCWA;Lo;0;L;;;;;N;;;;; 1510;CANADIAN SYLLABICS SHE;Lo;0;L;;;;;N;;;;; 1511;CANADIAN SYLLABICS SHI;Lo;0;L;;;;;N;;;;; 1512;CANADIAN SYLLABICS SHII;Lo;0;L;;;;;N;;;;; 1513;CANADIAN SYLLABICS SHO;Lo;0;L;;;;;N;;;;; 1514;CANADIAN SYLLABICS SHOO;Lo;0;L;;;;;N;;;;; 1515;CANADIAN SYLLABICS SHA;Lo;0;L;;;;;N;;;;; 1516;CANADIAN SYLLABICS SHAA;Lo;0;L;;;;;N;;;;; 1517;CANADIAN SYLLABICS SHWE;Lo;0;L;;;;;N;;;;; 1518;CANADIAN SYLLABICS WEST-CREE SHWE;Lo;0;L;;;;;N;;;;; 1519;CANADIAN SYLLABICS SHWI;Lo;0;L;;;;;N;;;;; 151A;CANADIAN SYLLABICS WEST-CREE SHWI;Lo;0;L;;;;;N;;;;; 151B;CANADIAN SYLLABICS SHWII;Lo;0;L;;;;;N;;;;; 151C;CANADIAN SYLLABICS WEST-CREE SHWII;Lo;0;L;;;;;N;;;;; 151D;CANADIAN SYLLABICS SHWO;Lo;0;L;;;;;N;;;;; 151E;CANADIAN SYLLABICS WEST-CREE SHWO;Lo;0;L;;;;;N;;;;; 151F;CANADIAN SYLLABICS SHWOO;Lo;0;L;;;;;N;;;;; 1520;CANADIAN SYLLABICS WEST-CREE SHWOO;Lo;0;L;;;;;N;;;;; 1521;CANADIAN SYLLABICS SHWA;Lo;0;L;;;;;N;;;;; 1522;CANADIAN SYLLABICS WEST-CREE SHWA;Lo;0;L;;;;;N;;;;; 1523;CANADIAN SYLLABICS SHWAA;Lo;0;L;;;;;N;;;;; 1524;CANADIAN SYLLABICS WEST-CREE SHWAA;Lo;0;L;;;;;N;;;;; 1525;CANADIAN SYLLABICS SH;Lo;0;L;;;;;N;;;;; 1526;CANADIAN SYLLABICS YE;Lo;0;L;;;;;N;;;;; 1527;CANADIAN SYLLABICS YAAI;Lo;0;L;;;;;N;;;;; 1528;CANADIAN SYLLABICS YI;Lo;0;L;;;;;N;;;;; 1529;CANADIAN SYLLABICS YII;Lo;0;L;;;;;N;;;;; 152A;CANADIAN SYLLABICS YO;Lo;0;L;;;;;N;;;;; 152B;CANADIAN SYLLABICS YOO;Lo;0;L;;;;;N;;;;; 152C;CANADIAN SYLLABICS Y-CREE YOO;Lo;0;L;;;;;N;;;;; 152D;CANADIAN SYLLABICS YA;Lo;0;L;;;;;N;;;;; 152E;CANADIAN SYLLABICS YAA;Lo;0;L;;;;;N;;;;; 152F;CANADIAN SYLLABICS YWE;Lo;0;L;;;;;N;;;;; 1530;CANADIAN SYLLABICS WEST-CREE YWE;Lo;0;L;;;;;N;;;;; 1531;CANADIAN SYLLABICS YWI;Lo;0;L;;;;;N;;;;; 1532;CANADIAN SYLLABICS WEST-CREE YWI;Lo;0;L;;;;;N;;;;; 1533;CANADIAN SYLLABICS YWII;Lo;0;L;;;;;N;;;;; 1534;CANADIAN SYLLABICS WEST-CREE YWII;Lo;0;L;;;;;N;;;;; 1535;CANADIAN SYLLABICS YWO;Lo;0;L;;;;;N;;;;; 1536;CANADIAN SYLLABICS WEST-CREE YWO;Lo;0;L;;;;;N;;;;; 1537;CANADIAN SYLLABICS YWOO;Lo;0;L;;;;;N;;;;; 1538;CANADIAN SYLLABICS WEST-CREE YWOO;Lo;0;L;;;;;N;;;;; 1539;CANADIAN SYLLABICS YWA;Lo;0;L;;;;;N;;;;; 153A;CANADIAN SYLLABICS WEST-CREE YWA;Lo;0;L;;;;;N;;;;; 153B;CANADIAN SYLLABICS YWAA;Lo;0;L;;;;;N;;;;; 153C;CANADIAN SYLLABICS WEST-CREE YWAA;Lo;0;L;;;;;N;;;;; 153D;CANADIAN SYLLABICS NASKAPI YWAA;Lo;0;L;;;;;N;;;;; 153E;CANADIAN SYLLABICS Y;Lo;0;L;;;;;N;;;;; 153F;CANADIAN SYLLABICS BIBLE-CREE Y;Lo;0;L;;;;;N;;;;; 1540;CANADIAN SYLLABICS WEST-CREE Y;Lo;0;L;;;;;N;;;;; 1541;CANADIAN SYLLABICS SAYISI YI;Lo;0;L;;;;;N;;;;; 1542;CANADIAN SYLLABICS RE;Lo;0;L;;;;;N;;;;; 1543;CANADIAN SYLLABICS R-CREE RE;Lo;0;L;;;;;N;;;;; 1544;CANADIAN SYLLABICS WEST-CREE LE;Lo;0;L;;;;;N;;;;; 1545;CANADIAN SYLLABICS RAAI;Lo;0;L;;;;;N;;;;; 1546;CANADIAN SYLLABICS RI;Lo;0;L;;;;;N;;;;; 1547;CANADIAN SYLLABICS RII;Lo;0;L;;;;;N;;;;; 1548;CANADIAN SYLLABICS RO;Lo;0;L;;;;;N;;;;; 1549;CANADIAN SYLLABICS ROO;Lo;0;L;;;;;N;;;;; 154A;CANADIAN SYLLABICS WEST-CREE LO;Lo;0;L;;;;;N;;;;; 154B;CANADIAN SYLLABICS RA;Lo;0;L;;;;;N;;;;; 154C;CANADIAN SYLLABICS RAA;Lo;0;L;;;;;N;;;;; 154D;CANADIAN SYLLABICS WEST-CREE LA;Lo;0;L;;;;;N;;;;; 154E;CANADIAN SYLLABICS RWAA;Lo;0;L;;;;;N;;;;; 154F;CANADIAN SYLLABICS WEST-CREE RWAA;Lo;0;L;;;;;N;;;;; 1550;CANADIAN SYLLABICS R;Lo;0;L;;;;;N;;;;; 1551;CANADIAN SYLLABICS WEST-CREE R;Lo;0;L;;;;;N;;;;; 1552;CANADIAN SYLLABICS MEDIAL R;Lo;0;L;;;;;N;;;;; 1553;CANADIAN SYLLABICS FE;Lo;0;L;;;;;N;;;;; 1554;CANADIAN SYLLABICS FAAI;Lo;0;L;;;;;N;;;;; 1555;CANADIAN SYLLABICS FI;Lo;0;L;;;;;N;;;;; 1556;CANADIAN SYLLABICS FII;Lo;0;L;;;;;N;;;;; 1557;CANADIAN SYLLABICS FO;Lo;0;L;;;;;N;;;;; 1558;CANADIAN SYLLABICS FOO;Lo;0;L;;;;;N;;;;; 1559;CANADIAN SYLLABICS FA;Lo;0;L;;;;;N;;;;; 155A;CANADIAN SYLLABICS FAA;Lo;0;L;;;;;N;;;;; 155B;CANADIAN SYLLABICS FWAA;Lo;0;L;;;;;N;;;;; 155C;CANADIAN SYLLABICS WEST-CREE FWAA;Lo;0;L;;;;;N;;;;; 155D;CANADIAN SYLLABICS F;Lo;0;L;;;;;N;;;;; 155E;CANADIAN SYLLABICS THE;Lo;0;L;;;;;N;;;;; 155F;CANADIAN SYLLABICS N-CREE THE;Lo;0;L;;;;;N;;;;; 1560;CANADIAN SYLLABICS THI;Lo;0;L;;;;;N;;;;; 1561;CANADIAN SYLLABICS N-CREE THI;Lo;0;L;;;;;N;;;;; 1562;CANADIAN SYLLABICS THII;Lo;0;L;;;;;N;;;;; 1563;CANADIAN SYLLABICS N-CREE THII;Lo;0;L;;;;;N;;;;; 1564;CANADIAN SYLLABICS THO;Lo;0;L;;;;;N;;;;; 1565;CANADIAN SYLLABICS THOO;Lo;0;L;;;;;N;;;;; 1566;CANADIAN SYLLABICS THA;Lo;0;L;;;;;N;;;;; 1567;CANADIAN SYLLABICS THAA;Lo;0;L;;;;;N;;;;; 1568;CANADIAN SYLLABICS THWAA;Lo;0;L;;;;;N;;;;; 1569;CANADIAN SYLLABICS WEST-CREE THWAA;Lo;0;L;;;;;N;;;;; 156A;CANADIAN SYLLABICS TH;Lo;0;L;;;;;N;;;;; 156B;CANADIAN SYLLABICS TTHE;Lo;0;L;;;;;N;;;;; 156C;CANADIAN SYLLABICS TTHI;Lo;0;L;;;;;N;;;;; 156D;CANADIAN SYLLABICS TTHO;Lo;0;L;;;;;N;;;;; 156E;CANADIAN SYLLABICS TTHA;Lo;0;L;;;;;N;;;;; 156F;CANADIAN SYLLABICS TTH;Lo;0;L;;;;;N;;;;; 1570;CANADIAN SYLLABICS TYE;Lo;0;L;;;;;N;;;;; 1571;CANADIAN SYLLABICS TYI;Lo;0;L;;;;;N;;;;; 1572;CANADIAN SYLLABICS TYO;Lo;0;L;;;;;N;;;;; 1573;CANADIAN SYLLABICS TYA;Lo;0;L;;;;;N;;;;; 1574;CANADIAN SYLLABICS NUNAVIK HE;Lo;0;L;;;;;N;;;;; 1575;CANADIAN SYLLABICS NUNAVIK HI;Lo;0;L;;;;;N;;;;; 1576;CANADIAN SYLLABICS NUNAVIK HII;Lo;0;L;;;;;N;;;;; 1577;CANADIAN SYLLABICS NUNAVIK HO;Lo;0;L;;;;;N;;;;; 1578;CANADIAN SYLLABICS NUNAVIK HOO;Lo;0;L;;;;;N;;;;; 1579;CANADIAN SYLLABICS NUNAVIK HA;Lo;0;L;;;;;N;;;;; 157A;CANADIAN SYLLABICS NUNAVIK HAA;Lo;0;L;;;;;N;;;;; 157B;CANADIAN SYLLABICS NUNAVIK H;Lo;0;L;;;;;N;;;;; 157C;CANADIAN SYLLABICS NUNAVUT H;Lo;0;L;;;;;N;;;;; 157D;CANADIAN SYLLABICS HK;Lo;0;L;;;;;N;;;;; 157E;CANADIAN SYLLABICS QAAI;Lo;0;L;;;;;N;;;;; 157F;CANADIAN SYLLABICS QI;Lo;0;L;;;;;N;;;;; 1580;CANADIAN SYLLABICS QII;Lo;0;L;;;;;N;;;;; 1581;CANADIAN SYLLABICS QO;Lo;0;L;;;;;N;;;;; 1582;CANADIAN SYLLABICS QOO;Lo;0;L;;;;;N;;;;; 1583;CANADIAN SYLLABICS QA;Lo;0;L;;;;;N;;;;; 1584;CANADIAN SYLLABICS QAA;Lo;0;L;;;;;N;;;;; 1585;CANADIAN SYLLABICS Q;Lo;0;L;;;;;N;;;;; 1586;CANADIAN SYLLABICS TLHE;Lo;0;L;;;;;N;;;;; 1587;CANADIAN SYLLABICS TLHI;Lo;0;L;;;;;N;;;;; 1588;CANADIAN SYLLABICS TLHO;Lo;0;L;;;;;N;;;;; 1589;CANADIAN SYLLABICS TLHA;Lo;0;L;;;;;N;;;;; 158A;CANADIAN SYLLABICS WEST-CREE RE;Lo;0;L;;;;;N;;;;; 158B;CANADIAN SYLLABICS WEST-CREE RI;Lo;0;L;;;;;N;;;;; 158C;CANADIAN SYLLABICS WEST-CREE RO;Lo;0;L;;;;;N;;;;; 158D;CANADIAN SYLLABICS WEST-CREE RA;Lo;0;L;;;;;N;;;;; 158E;CANADIAN SYLLABICS NGAAI;Lo;0;L;;;;;N;;;;; 158F;CANADIAN SYLLABICS NGI;Lo;0;L;;;;;N;;;;; 1590;CANADIAN SYLLABICS NGII;Lo;0;L;;;;;N;;;;; 1591;CANADIAN SYLLABICS NGO;Lo;0;L;;;;;N;;;;; 1592;CANADIAN SYLLABICS NGOO;Lo;0;L;;;;;N;;;;; 1593;CANADIAN SYLLABICS NGA;Lo;0;L;;;;;N;;;;; 1594;CANADIAN SYLLABICS NGAA;Lo;0;L;;;;;N;;;;; 1595;CANADIAN SYLLABICS NG;Lo;0;L;;;;;N;;;;; 1596;CANADIAN SYLLABICS NNG;Lo;0;L;;;;;N;;;;; 1597;CANADIAN SYLLABICS SAYISI SHE;Lo;0;L;;;;;N;;;;; 1598;CANADIAN SYLLABICS SAYISI SHI;Lo;0;L;;;;;N;;;;; 1599;CANADIAN SYLLABICS SAYISI SHO;Lo;0;L;;;;;N;;;;; 159A;CANADIAN SYLLABICS SAYISI SHA;Lo;0;L;;;;;N;;;;; 159B;CANADIAN SYLLABICS WOODS-CREE THE;Lo;0;L;;;;;N;;;;; 159C;CANADIAN SYLLABICS WOODS-CREE THI;Lo;0;L;;;;;N;;;;; 159D;CANADIAN SYLLABICS WOODS-CREE THO;Lo;0;L;;;;;N;;;;; 159E;CANADIAN SYLLABICS WOODS-CREE THA;Lo;0;L;;;;;N;;;;; 159F;CANADIAN SYLLABICS WOODS-CREE TH;Lo;0;L;;;;;N;;;;; 15A0;CANADIAN SYLLABICS LHI;Lo;0;L;;;;;N;;;;; 15A1;CANADIAN SYLLABICS LHII;Lo;0;L;;;;;N;;;;; 15A2;CANADIAN SYLLABICS LHO;Lo;0;L;;;;;N;;;;; 15A3;CANADIAN SYLLABICS LHOO;Lo;0;L;;;;;N;;;;; 15A4;CANADIAN SYLLABICS LHA;Lo;0;L;;;;;N;;;;; 15A5;CANADIAN SYLLABICS LHAA;Lo;0;L;;;;;N;;;;; 15A6;CANADIAN SYLLABICS LH;Lo;0;L;;;;;N;;;;; 15A7;CANADIAN SYLLABICS TH-CREE THE;Lo;0;L;;;;;N;;;;; 15A8;CANADIAN SYLLABICS TH-CREE THI;Lo;0;L;;;;;N;;;;; 15A9;CANADIAN SYLLABICS TH-CREE THII;Lo;0;L;;;;;N;;;;; 15AA;CANADIAN SYLLABICS TH-CREE THO;Lo;0;L;;;;;N;;;;; 15AB;CANADIAN SYLLABICS TH-CREE THOO;Lo;0;L;;;;;N;;;;; 15AC;CANADIAN SYLLABICS TH-CREE THA;Lo;0;L;;;;;N;;;;; 15AD;CANADIAN SYLLABICS TH-CREE THAA;Lo;0;L;;;;;N;;;;; 15AE;CANADIAN SYLLABICS TH-CREE TH;Lo;0;L;;;;;N;;;;; 15AF;CANADIAN SYLLABICS AIVILIK B;Lo;0;L;;;;;N;;;;; 15B0;CANADIAN SYLLABICS BLACKFOOT E;Lo;0;L;;;;;N;;;;; 15B1;CANADIAN SYLLABICS BLACKFOOT I;Lo;0;L;;;;;N;;;;; 15B2;CANADIAN SYLLABICS BLACKFOOT O;Lo;0;L;;;;;N;;;;; 15B3;CANADIAN SYLLABICS BLACKFOOT A;Lo;0;L;;;;;N;;;;; 15B4;CANADIAN SYLLABICS BLACKFOOT WE;Lo;0;L;;;;;N;;;;; 15B5;CANADIAN SYLLABICS BLACKFOOT WI;Lo;0;L;;;;;N;;;;; 15B6;CANADIAN SYLLABICS BLACKFOOT WO;Lo;0;L;;;;;N;;;;; 15B7;CANADIAN SYLLABICS BLACKFOOT WA;Lo;0;L;;;;;N;;;;; 15B8;CANADIAN SYLLABICS BLACKFOOT NE;Lo;0;L;;;;;N;;;;; 15B9;CANADIAN SYLLABICS BLACKFOOT NI;Lo;0;L;;;;;N;;;;; 15BA;CANADIAN SYLLABICS BLACKFOOT NO;Lo;0;L;;;;;N;;;;; 15BB;CANADIAN SYLLABICS BLACKFOOT NA;Lo;0;L;;;;;N;;;;; 15BC;CANADIAN SYLLABICS BLACKFOOT KE;Lo;0;L;;;;;N;;;;; 15BD;CANADIAN SYLLABICS BLACKFOOT KI;Lo;0;L;;;;;N;;;;; 15BE;CANADIAN SYLLABICS BLACKFOOT KO;Lo;0;L;;;;;N;;;;; 15BF;CANADIAN SYLLABICS BLACKFOOT KA;Lo;0;L;;;;;N;;;;; 15C0;CANADIAN SYLLABICS SAYISI HE;Lo;0;L;;;;;N;;;;; 15C1;CANADIAN SYLLABICS SAYISI HI;Lo;0;L;;;;;N;;;;; 15C2;CANADIAN SYLLABICS SAYISI HO;Lo;0;L;;;;;N;;;;; 15C3;CANADIAN SYLLABICS SAYISI HA;Lo;0;L;;;;;N;;;;; 15C4;CANADIAN SYLLABICS CARRIER GHU;Lo;0;L;;;;;N;;;;; 15C5;CANADIAN SYLLABICS CARRIER GHO;Lo;0;L;;;;;N;;;;; 15C6;CANADIAN SYLLABICS CARRIER GHE;Lo;0;L;;;;;N;;;;; 15C7;CANADIAN SYLLABICS CARRIER GHEE;Lo;0;L;;;;;N;;;;; 15C8;CANADIAN SYLLABICS CARRIER GHI;Lo;0;L;;;;;N;;;;; 15C9;CANADIAN SYLLABICS CARRIER GHA;Lo;0;L;;;;;N;;;;; 15CA;CANADIAN SYLLABICS CARRIER RU;Lo;0;L;;;;;N;;;;; 15CB;CANADIAN SYLLABICS CARRIER RO;Lo;0;L;;;;;N;;;;; 15CC;CANADIAN SYLLABICS CARRIER RE;Lo;0;L;;;;;N;;;;; 15CD;CANADIAN SYLLABICS CARRIER REE;Lo;0;L;;;;;N;;;;; 15CE;CANADIAN SYLLABICS CARRIER RI;Lo;0;L;;;;;N;;;;; 15CF;CANADIAN SYLLABICS CARRIER RA;Lo;0;L;;;;;N;;;;; 15D0;CANADIAN SYLLABICS CARRIER WU;Lo;0;L;;;;;N;;;;; 15D1;CANADIAN SYLLABICS CARRIER WO;Lo;0;L;;;;;N;;;;; 15D2;CANADIAN SYLLABICS CARRIER WE;Lo;0;L;;;;;N;;;;; 15D3;CANADIAN SYLLABICS CARRIER WEE;Lo;0;L;;;;;N;;;;; 15D4;CANADIAN SYLLABICS CARRIER WI;Lo;0;L;;;;;N;;;;; 15D5;CANADIAN SYLLABICS CARRIER WA;Lo;0;L;;;;;N;;;;; 15D6;CANADIAN SYLLABICS CARRIER HWU;Lo;0;L;;;;;N;;;;; 15D7;CANADIAN SYLLABICS CARRIER HWO;Lo;0;L;;;;;N;;;;; 15D8;CANADIAN SYLLABICS CARRIER HWE;Lo;0;L;;;;;N;;;;; 15D9;CANADIAN SYLLABICS CARRIER HWEE;Lo;0;L;;;;;N;;;;; 15DA;CANADIAN SYLLABICS CARRIER HWI;Lo;0;L;;;;;N;;;;; 15DB;CANADIAN SYLLABICS CARRIER HWA;Lo;0;L;;;;;N;;;;; 15DC;CANADIAN SYLLABICS CARRIER THU;Lo;0;L;;;;;N;;;;; 15DD;CANADIAN SYLLABICS CARRIER THO;Lo;0;L;;;;;N;;;;; 15DE;CANADIAN SYLLABICS CARRIER THE;Lo;0;L;;;;;N;;;;; 15DF;CANADIAN SYLLABICS CARRIER THEE;Lo;0;L;;;;;N;;;;; 15E0;CANADIAN SYLLABICS CARRIER THI;Lo;0;L;;;;;N;;;;; 15E1;CANADIAN SYLLABICS CARRIER THA;Lo;0;L;;;;;N;;;;; 15E2;CANADIAN SYLLABICS CARRIER TTU;Lo;0;L;;;;;N;;;;; 15E3;CANADIAN SYLLABICS CARRIER TTO;Lo;0;L;;;;;N;;;;; 15E4;CANADIAN SYLLABICS CARRIER TTE;Lo;0;L;;;;;N;;;;; 15E5;CANADIAN SYLLABICS CARRIER TTEE;Lo;0;L;;;;;N;;;;; 15E6;CANADIAN SYLLABICS CARRIER TTI;Lo;0;L;;;;;N;;;;; 15E7;CANADIAN SYLLABICS CARRIER TTA;Lo;0;L;;;;;N;;;;; 15E8;CANADIAN SYLLABICS CARRIER PU;Lo;0;L;;;;;N;;;;; 15E9;CANADIAN SYLLABICS CARRIER PO;Lo;0;L;;;;;N;;;;; 15EA;CANADIAN SYLLABICS CARRIER PE;Lo;0;L;;;;;N;;;;; 15EB;CANADIAN SYLLABICS CARRIER PEE;Lo;0;L;;;;;N;;;;; 15EC;CANADIAN SYLLABICS CARRIER PI;Lo;0;L;;;;;N;;;;; 15ED;CANADIAN SYLLABICS CARRIER PA;Lo;0;L;;;;;N;;;;; 15EE;CANADIAN SYLLABICS CARRIER P;Lo;0;L;;;;;N;;;;; 15EF;CANADIAN SYLLABICS CARRIER GU;Lo;0;L;;;;;N;;;;; 15F0;CANADIAN SYLLABICS CARRIER GO;Lo;0;L;;;;;N;;;;; 15F1;CANADIAN SYLLABICS CARRIER GE;Lo;0;L;;;;;N;;;;; 15F2;CANADIAN SYLLABICS CARRIER GEE;Lo;0;L;;;;;N;;;;; 15F3;CANADIAN SYLLABICS CARRIER GI;Lo;0;L;;;;;N;;;;; 15F4;CANADIAN SYLLABICS CARRIER GA;Lo;0;L;;;;;N;;;;; 15F5;CANADIAN SYLLABICS CARRIER KHU;Lo;0;L;;;;;N;;;;; 15F6;CANADIAN SYLLABICS CARRIER KHO;Lo;0;L;;;;;N;;;;; 15F7;CANADIAN SYLLABICS CARRIER KHE;Lo;0;L;;;;;N;;;;; 15F8;CANADIAN SYLLABICS CARRIER KHEE;Lo;0;L;;;;;N;;;;; 15F9;CANADIAN SYLLABICS CARRIER KHI;Lo;0;L;;;;;N;;;;; 15FA;CANADIAN SYLLABICS CARRIER KHA;Lo;0;L;;;;;N;;;;; 15FB;CANADIAN SYLLABICS CARRIER KKU;Lo;0;L;;;;;N;;;;; 15FC;CANADIAN SYLLABICS CARRIER KKO;Lo;0;L;;;;;N;;;;; 15FD;CANADIAN SYLLABICS CARRIER KKE;Lo;0;L;;;;;N;;;;; 15FE;CANADIAN SYLLABICS CARRIER KKEE;Lo;0;L;;;;;N;;;;; 15FF;CANADIAN SYLLABICS CARRIER KKI;Lo;0;L;;;;;N;;;;; 1600;CANADIAN SYLLABICS CARRIER KKA;Lo;0;L;;;;;N;;;;; 1601;CANADIAN SYLLABICS CARRIER KK;Lo;0;L;;;;;N;;;;; 1602;CANADIAN SYLLABICS CARRIER NU;Lo;0;L;;;;;N;;;;; 1603;CANADIAN SYLLABICS CARRIER NO;Lo;0;L;;;;;N;;;;; 1604;CANADIAN SYLLABICS CARRIER NE;Lo;0;L;;;;;N;;;;; 1605;CANADIAN SYLLABICS CARRIER NEE;Lo;0;L;;;;;N;;;;; 1606;CANADIAN SYLLABICS CARRIER NI;Lo;0;L;;;;;N;;;;; 1607;CANADIAN SYLLABICS CARRIER NA;Lo;0;L;;;;;N;;;;; 1608;CANADIAN SYLLABICS CARRIER MU;Lo;0;L;;;;;N;;;;; 1609;CANADIAN SYLLABICS CARRIER MO;Lo;0;L;;;;;N;;;;; 160A;CANADIAN SYLLABICS CARRIER ME;Lo;0;L;;;;;N;;;;; 160B;CANADIAN SYLLABICS CARRIER MEE;Lo;0;L;;;;;N;;;;; 160C;CANADIAN SYLLABICS CARRIER MI;Lo;0;L;;;;;N;;;;; 160D;CANADIAN SYLLABICS CARRIER MA;Lo;0;L;;;;;N;;;;; 160E;CANADIAN SYLLABICS CARRIER YU;Lo;0;L;;;;;N;;;;; 160F;CANADIAN SYLLABICS CARRIER YO;Lo;0;L;;;;;N;;;;; 1610;CANADIAN SYLLABICS CARRIER YE;Lo;0;L;;;;;N;;;;; 1611;CANADIAN SYLLABICS CARRIER YEE;Lo;0;L;;;;;N;;;;; 1612;CANADIAN SYLLABICS CARRIER YI;Lo;0;L;;;;;N;;;;; 1613;CANADIAN SYLLABICS CARRIER YA;Lo;0;L;;;;;N;;;;; 1614;CANADIAN SYLLABICS CARRIER JU;Lo;0;L;;;;;N;;;;; 1615;CANADIAN SYLLABICS SAYISI JU;Lo;0;L;;;;;N;;;;; 1616;CANADIAN SYLLABICS CARRIER JO;Lo;0;L;;;;;N;;;;; 1617;CANADIAN SYLLABICS CARRIER JE;Lo;0;L;;;;;N;;;;; 1618;CANADIAN SYLLABICS CARRIER JEE;Lo;0;L;;;;;N;;;;; 1619;CANADIAN SYLLABICS CARRIER JI;Lo;0;L;;;;;N;;;;; 161A;CANADIAN SYLLABICS SAYISI JI;Lo;0;L;;;;;N;;;;; 161B;CANADIAN SYLLABICS CARRIER JA;Lo;0;L;;;;;N;;;;; 161C;CANADIAN SYLLABICS CARRIER JJU;Lo;0;L;;;;;N;;;;; 161D;CANADIAN SYLLABICS CARRIER JJO;Lo;0;L;;;;;N;;;;; 161E;CANADIAN SYLLABICS CARRIER JJE;Lo;0;L;;;;;N;;;;; 161F;CANADIAN SYLLABICS CARRIER JJEE;Lo;0;L;;;;;N;;;;; 1620;CANADIAN SYLLABICS CARRIER JJI;Lo;0;L;;;;;N;;;;; 1621;CANADIAN SYLLABICS CARRIER JJA;Lo;0;L;;;;;N;;;;; 1622;CANADIAN SYLLABICS CARRIER LU;Lo;0;L;;;;;N;;;;; 1623;CANADIAN SYLLABICS CARRIER LO;Lo;0;L;;;;;N;;;;; 1624;CANADIAN SYLLABICS CARRIER LE;Lo;0;L;;;;;N;;;;; 1625;CANADIAN SYLLABICS CARRIER LEE;Lo;0;L;;;;;N;;;;; 1626;CANADIAN SYLLABICS CARRIER LI;Lo;0;L;;;;;N;;;;; 1627;CANADIAN SYLLABICS CARRIER LA;Lo;0;L;;;;;N;;;;; 1628;CANADIAN SYLLABICS CARRIER DLU;Lo;0;L;;;;;N;;;;; 1629;CANADIAN SYLLABICS CARRIER DLO;Lo;0;L;;;;;N;;;;; 162A;CANADIAN SYLLABICS CARRIER DLE;Lo;0;L;;;;;N;;;;; 162B;CANADIAN SYLLABICS CARRIER DLEE;Lo;0;L;;;;;N;;;;; 162C;CANADIAN SYLLABICS CARRIER DLI;Lo;0;L;;;;;N;;;;; 162D;CANADIAN SYLLABICS CARRIER DLA;Lo;0;L;;;;;N;;;;; 162E;CANADIAN SYLLABICS CARRIER LHU;Lo;0;L;;;;;N;;;;; 162F;CANADIAN SYLLABICS CARRIER LHO;Lo;0;L;;;;;N;;;;; 1630;CANADIAN SYLLABICS CARRIER LHE;Lo;0;L;;;;;N;;;;; 1631;CANADIAN SYLLABICS CARRIER LHEE;Lo;0;L;;;;;N;;;;; 1632;CANADIAN SYLLABICS CARRIER LHI;Lo;0;L;;;;;N;;;;; 1633;CANADIAN SYLLABICS CARRIER LHA;Lo;0;L;;;;;N;;;;; 1634;CANADIAN SYLLABICS CARRIER TLHU;Lo;0;L;;;;;N;;;;; 1635;CANADIAN SYLLABICS CARRIER TLHO;Lo;0;L;;;;;N;;;;; 1636;CANADIAN SYLLABICS CARRIER TLHE;Lo;0;L;;;;;N;;;;; 1637;CANADIAN SYLLABICS CARRIER TLHEE;Lo;0;L;;;;;N;;;;; 1638;CANADIAN SYLLABICS CARRIER TLHI;Lo;0;L;;;;;N;;;;; 1639;CANADIAN SYLLABICS CARRIER TLHA;Lo;0;L;;;;;N;;;;; 163A;CANADIAN SYLLABICS CARRIER TLU;Lo;0;L;;;;;N;;;;; 163B;CANADIAN SYLLABICS CARRIER TLO;Lo;0;L;;;;;N;;;;; 163C;CANADIAN SYLLABICS CARRIER TLE;Lo;0;L;;;;;N;;;;; 163D;CANADIAN SYLLABICS CARRIER TLEE;Lo;0;L;;;;;N;;;;; 163E;CANADIAN SYLLABICS CARRIER TLI;Lo;0;L;;;;;N;;;;; 163F;CANADIAN SYLLABICS CARRIER TLA;Lo;0;L;;;;;N;;;;; 1640;CANADIAN SYLLABICS CARRIER ZU;Lo;0;L;;;;;N;;;;; 1641;CANADIAN SYLLABICS CARRIER ZO;Lo;0;L;;;;;N;;;;; 1642;CANADIAN SYLLABICS CARRIER ZE;Lo;0;L;;;;;N;;;;; 1643;CANADIAN SYLLABICS CARRIER ZEE;Lo;0;L;;;;;N;;;;; 1644;CANADIAN SYLLABICS CARRIER ZI;Lo;0;L;;;;;N;;;;; 1645;CANADIAN SYLLABICS CARRIER ZA;Lo;0;L;;;;;N;;;;; 1646;CANADIAN SYLLABICS CARRIER Z;Lo;0;L;;;;;N;;;;; 1647;CANADIAN SYLLABICS CARRIER INITIAL Z;Lo;0;L;;;;;N;;;;; 1648;CANADIAN SYLLABICS CARRIER DZU;Lo;0;L;;;;;N;;;;; 1649;CANADIAN SYLLABICS CARRIER DZO;Lo;0;L;;;;;N;;;;; 164A;CANADIAN SYLLABICS CARRIER DZE;Lo;0;L;;;;;N;;;;; 164B;CANADIAN SYLLABICS CARRIER DZEE;Lo;0;L;;;;;N;;;;; 164C;CANADIAN SYLLABICS CARRIER DZI;Lo;0;L;;;;;N;;;;; 164D;CANADIAN SYLLABICS CARRIER DZA;Lo;0;L;;;;;N;;;;; 164E;CANADIAN SYLLABICS CARRIER SU;Lo;0;L;;;;;N;;;;; 164F;CANADIAN SYLLABICS CARRIER SO;Lo;0;L;;;;;N;;;;; 1650;CANADIAN SYLLABICS CARRIER SE;Lo;0;L;;;;;N;;;;; 1651;CANADIAN SYLLABICS CARRIER SEE;Lo;0;L;;;;;N;;;;; 1652;CANADIAN SYLLABICS CARRIER SI;Lo;0;L;;;;;N;;;;; 1653;CANADIAN SYLLABICS CARRIER SA;Lo;0;L;;;;;N;;;;; 1654;CANADIAN SYLLABICS CARRIER SHU;Lo;0;L;;;;;N;;;;; 1655;CANADIAN SYLLABICS CARRIER SHO;Lo;0;L;;;;;N;;;;; 1656;CANADIAN SYLLABICS CARRIER SHE;Lo;0;L;;;;;N;;;;; 1657;CANADIAN SYLLABICS CARRIER SHEE;Lo;0;L;;;;;N;;;;; 1658;CANADIAN SYLLABICS CARRIER SHI;Lo;0;L;;;;;N;;;;; 1659;CANADIAN SYLLABICS CARRIER SHA;Lo;0;L;;;;;N;;;;; 165A;CANADIAN SYLLABICS CARRIER SH;Lo;0;L;;;;;N;;;;; 165B;CANADIAN SYLLABICS CARRIER TSU;Lo;0;L;;;;;N;;;;; 165C;CANADIAN SYLLABICS CARRIER TSO;Lo;0;L;;;;;N;;;;; 165D;CANADIAN SYLLABICS CARRIER TSE;Lo;0;L;;;;;N;;;;; 165E;CANADIAN SYLLABICS CARRIER TSEE;Lo;0;L;;;;;N;;;;; 165F;CANADIAN SYLLABICS CARRIER TSI;Lo;0;L;;;;;N;;;;; 1660;CANADIAN SYLLABICS CARRIER TSA;Lo;0;L;;;;;N;;;;; 1661;CANADIAN SYLLABICS CARRIER CHU;Lo;0;L;;;;;N;;;;; 1662;CANADIAN SYLLABICS CARRIER CHO;Lo;0;L;;;;;N;;;;; 1663;CANADIAN SYLLABICS CARRIER CHE;Lo;0;L;;;;;N;;;;; 1664;CANADIAN SYLLABICS CARRIER CHEE;Lo;0;L;;;;;N;;;;; 1665;CANADIAN SYLLABICS CARRIER CHI;Lo;0;L;;;;;N;;;;; 1666;CANADIAN SYLLABICS CARRIER CHA;Lo;0;L;;;;;N;;;;; 1667;CANADIAN SYLLABICS CARRIER TTSU;Lo;0;L;;;;;N;;;;; 1668;CANADIAN SYLLABICS CARRIER TTSO;Lo;0;L;;;;;N;;;;; 1669;CANADIAN SYLLABICS CARRIER TTSE;Lo;0;L;;;;;N;;;;; 166A;CANADIAN SYLLABICS CARRIER TTSEE;Lo;0;L;;;;;N;;;;; 166B;CANADIAN SYLLABICS CARRIER TTSI;Lo;0;L;;;;;N;;;;; 166C;CANADIAN SYLLABICS CARRIER TTSA;Lo;0;L;;;;;N;;;;; 166D;CANADIAN SYLLABICS CHI SIGN;Po;0;L;;;;;N;;;;; 166E;CANADIAN SYLLABICS FULL STOP;Po;0;L;;;;;N;;;;; 166F;CANADIAN SYLLABICS QAI;Lo;0;L;;;;;N;;;;; 1670;CANADIAN SYLLABICS NGAI;Lo;0;L;;;;;N;;;;; 1671;CANADIAN SYLLABICS NNGI;Lo;0;L;;;;;N;;;;; 1672;CANADIAN SYLLABICS NNGII;Lo;0;L;;;;;N;;;;; 1673;CANADIAN SYLLABICS NNGO;Lo;0;L;;;;;N;;;;; 1674;CANADIAN SYLLABICS NNGOO;Lo;0;L;;;;;N;;;;; 1675;CANADIAN SYLLABICS NNGA;Lo;0;L;;;;;N;;;;; 1676;CANADIAN SYLLABICS NNGAA;Lo;0;L;;;;;N;;;;; 1680;OGHAM SPACE MARK;Zs;0;WS;;;;;N;;;;; 1681;OGHAM LETTER BEITH;Lo;0;L;;;;;N;;;;; 1682;OGHAM LETTER LUIS;Lo;0;L;;;;;N;;;;; 1683;OGHAM LETTER FEARN;Lo;0;L;;;;;N;;;;; 1684;OGHAM LETTER SAIL;Lo;0;L;;;;;N;;;;; 1685;OGHAM LETTER NION;Lo;0;L;;;;;N;;;;; 1686;OGHAM LETTER UATH;Lo;0;L;;;;;N;;;;; 1687;OGHAM LETTER DAIR;Lo;0;L;;;;;N;;;;; 1688;OGHAM LETTER TINNE;Lo;0;L;;;;;N;;;;; 1689;OGHAM LETTER COLL;Lo;0;L;;;;;N;;;;; 168A;OGHAM LETTER CEIRT;Lo;0;L;;;;;N;;;;; 168B;OGHAM LETTER MUIN;Lo;0;L;;;;;N;;;;; 168C;OGHAM LETTER GORT;Lo;0;L;;;;;N;;;;; 168D;OGHAM LETTER NGEADAL;Lo;0;L;;;;;N;;;;; 168E;OGHAM LETTER STRAIF;Lo;0;L;;;;;N;;;;; 168F;OGHAM LETTER RUIS;Lo;0;L;;;;;N;;;;; 1690;OGHAM LETTER AILM;Lo;0;L;;;;;N;;;;; 1691;OGHAM LETTER ONN;Lo;0;L;;;;;N;;;;; 1692;OGHAM LETTER UR;Lo;0;L;;;;;N;;;;; 1693;OGHAM LETTER EADHADH;Lo;0;L;;;;;N;;;;; 1694;OGHAM LETTER IODHADH;Lo;0;L;;;;;N;;;;; 1695;OGHAM LETTER EABHADH;Lo;0;L;;;;;N;;;;; 1696;OGHAM LETTER OR;Lo;0;L;;;;;N;;;;; 1697;OGHAM LETTER UILLEANN;Lo;0;L;;;;;N;;;;; 1698;OGHAM LETTER IFIN;Lo;0;L;;;;;N;;;;; 1699;OGHAM LETTER EAMHANCHOLL;Lo;0;L;;;;;N;;;;; 169A;OGHAM LETTER PEITH;Lo;0;L;;;;;N;;;;; 169B;OGHAM FEATHER MARK;Ps;0;ON;;;;;N;;;;; 169C;OGHAM REVERSED FEATHER MARK;Pe;0;ON;;;;;N;;;;; 16A0;RUNIC LETTER FEHU FEOH FE F;Lo;0;L;;;;;N;;;;; 16A1;RUNIC LETTER V;Lo;0;L;;;;;N;;;;; 16A2;RUNIC LETTER URUZ UR U;Lo;0;L;;;;;N;;;;; 16A3;RUNIC LETTER YR;Lo;0;L;;;;;N;;;;; 16A4;RUNIC LETTER Y;Lo;0;L;;;;;N;;;;; 16A5;RUNIC LETTER W;Lo;0;L;;;;;N;;;;; 16A6;RUNIC LETTER THURISAZ THURS THORN;Lo;0;L;;;;;N;;;;; 16A7;RUNIC LETTER ETH;Lo;0;L;;;;;N;;;;; 16A8;RUNIC LETTER ANSUZ A;Lo;0;L;;;;;N;;;;; 16A9;RUNIC LETTER OS O;Lo;0;L;;;;;N;;;;; 16AA;RUNIC LETTER AC A;Lo;0;L;;;;;N;;;;; 16AB;RUNIC LETTER AESC;Lo;0;L;;;;;N;;;;; 16AC;RUNIC LETTER LONG-BRANCH-OSS O;Lo;0;L;;;;;N;;;;; 16AD;RUNIC LETTER SHORT-TWIG-OSS O;Lo;0;L;;;;;N;;;;; 16AE;RUNIC LETTER O;Lo;0;L;;;;;N;;;;; 16AF;RUNIC LETTER OE;Lo;0;L;;;;;N;;;;; 16B0;RUNIC LETTER ON;Lo;0;L;;;;;N;;;;; 16B1;RUNIC LETTER RAIDO RAD REID R;Lo;0;L;;;;;N;;;;; 16B2;RUNIC LETTER KAUNA;Lo;0;L;;;;;N;;;;; 16B3;RUNIC LETTER CEN;Lo;0;L;;;;;N;;;;; 16B4;RUNIC LETTER KAUN K;Lo;0;L;;;;;N;;;;; 16B5;RUNIC LETTER G;Lo;0;L;;;;;N;;;;; 16B6;RUNIC LETTER ENG;Lo;0;L;;;;;N;;;;; 16B7;RUNIC LETTER GEBO GYFU G;Lo;0;L;;;;;N;;;;; 16B8;RUNIC LETTER GAR;Lo;0;L;;;;;N;;;;; 16B9;RUNIC LETTER WUNJO WYNN W;Lo;0;L;;;;;N;;;;; 16BA;RUNIC LETTER HAGLAZ H;Lo;0;L;;;;;N;;;;; 16BB;RUNIC LETTER HAEGL H;Lo;0;L;;;;;N;;;;; 16BC;RUNIC LETTER LONG-BRANCH-HAGALL H;Lo;0;L;;;;;N;;;;; 16BD;RUNIC LETTER SHORT-TWIG-HAGALL H;Lo;0;L;;;;;N;;;;; 16BE;RUNIC LETTER NAUDIZ NYD NAUD N;Lo;0;L;;;;;N;;;;; 16BF;RUNIC LETTER SHORT-TWIG-NAUD N;Lo;0;L;;;;;N;;;;; 16C0;RUNIC LETTER DOTTED-N;Lo;0;L;;;;;N;;;;; 16C1;RUNIC LETTER ISAZ IS ISS I;Lo;0;L;;;;;N;;;;; 16C2;RUNIC LETTER E;Lo;0;L;;;;;N;;;;; 16C3;RUNIC LETTER JERAN J;Lo;0;L;;;;;N;;;;; 16C4;RUNIC LETTER GER;Lo;0;L;;;;;N;;;;; 16C5;RUNIC LETTER LONG-BRANCH-AR AE;Lo;0;L;;;;;N;;;;; 16C6;RUNIC LETTER SHORT-TWIG-AR A;Lo;0;L;;;;;N;;;;; 16C7;RUNIC LETTER IWAZ EOH;Lo;0;L;;;;;N;;;;; 16C8;RUNIC LETTER PERTHO PEORTH P;Lo;0;L;;;;;N;;;;; 16C9;RUNIC LETTER ALGIZ EOLHX;Lo;0;L;;;;;N;;;;; 16CA;RUNIC LETTER SOWILO S;Lo;0;L;;;;;N;;;;; 16CB;RUNIC LETTER SIGEL LONG-BRANCH-SOL S;Lo;0;L;;;;;N;;;;; 16CC;RUNIC LETTER SHORT-TWIG-SOL S;Lo;0;L;;;;;N;;;;; 16CD;RUNIC LETTER C;Lo;0;L;;;;;N;;;;; 16CE;RUNIC LETTER Z;Lo;0;L;;;;;N;;;;; 16CF;RUNIC LETTER TIWAZ TIR TYR T;Lo;0;L;;;;;N;;;;; 16D0;RUNIC LETTER SHORT-TWIG-TYR T;Lo;0;L;;;;;N;;;;; 16D1;RUNIC LETTER D;Lo;0;L;;;;;N;;;;; 16D2;RUNIC LETTER BERKANAN BEORC BJARKAN B;Lo;0;L;;;;;N;;;;; 16D3;RUNIC LETTER SHORT-TWIG-BJARKAN B;Lo;0;L;;;;;N;;;;; 16D4;RUNIC LETTER DOTTED-P;Lo;0;L;;;;;N;;;;; 16D5;RUNIC LETTER OPEN-P;Lo;0;L;;;;;N;;;;; 16D6;RUNIC LETTER EHWAZ EH E;Lo;0;L;;;;;N;;;;; 16D7;RUNIC LETTER MANNAZ MAN M;Lo;0;L;;;;;N;;;;; 16D8;RUNIC LETTER LONG-BRANCH-MADR M;Lo;0;L;;;;;N;;;;; 16D9;RUNIC LETTER SHORT-TWIG-MADR M;Lo;0;L;;;;;N;;;;; 16DA;RUNIC LETTER LAUKAZ LAGU LOGR L;Lo;0;L;;;;;N;;;;; 16DB;RUNIC LETTER DOTTED-L;Lo;0;L;;;;;N;;;;; 16DC;RUNIC LETTER INGWAZ;Lo;0;L;;;;;N;;;;; 16DD;RUNIC LETTER ING;Lo;0;L;;;;;N;;;;; 16DE;RUNIC LETTER DAGAZ DAEG D;Lo;0;L;;;;;N;;;;; 16DF;RUNIC LETTER OTHALAN ETHEL O;Lo;0;L;;;;;N;;;;; 16E0;RUNIC LETTER EAR;Lo;0;L;;;;;N;;;;; 16E1;RUNIC LETTER IOR;Lo;0;L;;;;;N;;;;; 16E2;RUNIC LETTER CWEORTH;Lo;0;L;;;;;N;;;;; 16E3;RUNIC LETTER CALC;Lo;0;L;;;;;N;;;;; 16E4;RUNIC LETTER CEALC;Lo;0;L;;;;;N;;;;; 16E5;RUNIC LETTER STAN;Lo;0;L;;;;;N;;;;; 16E6;RUNIC LETTER LONG-BRANCH-YR;Lo;0;L;;;;;N;;;;; 16E7;RUNIC LETTER SHORT-TWIG-YR;Lo;0;L;;;;;N;;;;; 16E8;RUNIC LETTER ICELANDIC-YR;Lo;0;L;;;;;N;;;;; 16E9;RUNIC LETTER Q;Lo;0;L;;;;;N;;;;; 16EA;RUNIC LETTER X;Lo;0;L;;;;;N;;;;; 16EB;RUNIC SINGLE PUNCTUATION;Po;0;L;;;;;N;;;;; 16EC;RUNIC MULTIPLE PUNCTUATION;Po;0;L;;;;;N;;;;; 16ED;RUNIC CROSS PUNCTUATION;Po;0;L;;;;;N;;;;; 16EE;RUNIC ARLAUG SYMBOL;Nl;0;L;;;;17;N;;golden number 17;;; 16EF;RUNIC TVIMADUR SYMBOL;Nl;0;L;;;;18;N;;golden number 18;;; 16F0;RUNIC BELGTHOR SYMBOL;Nl;0;L;;;;19;N;;golden number 19;;; 1700;TAGALOG LETTER A;Lo;0;L;;;;;N;;;;; 1701;TAGALOG LETTER I;Lo;0;L;;;;;N;;;;; 1702;TAGALOG LETTER U;Lo;0;L;;;;;N;;;;; 1703;TAGALOG LETTER KA;Lo;0;L;;;;;N;;;;; 1704;TAGALOG LETTER GA;Lo;0;L;;;;;N;;;;; 1705;TAGALOG LETTER NGA;Lo;0;L;;;;;N;;;;; 1706;TAGALOG LETTER TA;Lo;0;L;;;;;N;;;;; 1707;TAGALOG LETTER DA;Lo;0;L;;;;;N;;;;; 1708;TAGALOG LETTER NA;Lo;0;L;;;;;N;;;;; 1709;TAGALOG LETTER PA;Lo;0;L;;;;;N;;;;; 170A;TAGALOG LETTER BA;Lo;0;L;;;;;N;;;;; 170B;TAGALOG LETTER MA;Lo;0;L;;;;;N;;;;; 170C;TAGALOG LETTER YA;Lo;0;L;;;;;N;;;;; 170E;TAGALOG LETTER LA;Lo;0;L;;;;;N;;;;; 170F;TAGALOG LETTER WA;Lo;0;L;;;;;N;;;;; 1710;TAGALOG LETTER SA;Lo;0;L;;;;;N;;;;; 1711;TAGALOG LETTER HA;Lo;0;L;;;;;N;;;;; 1712;TAGALOG VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 1713;TAGALOG VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 1714;TAGALOG SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 1720;HANUNOO LETTER A;Lo;0;L;;;;;N;;;;; 1721;HANUNOO LETTER I;Lo;0;L;;;;;N;;;;; 1722;HANUNOO LETTER U;Lo;0;L;;;;;N;;;;; 1723;HANUNOO LETTER KA;Lo;0;L;;;;;N;;;;; 1724;HANUNOO LETTER GA;Lo;0;L;;;;;N;;;;; 1725;HANUNOO LETTER NGA;Lo;0;L;;;;;N;;;;; 1726;HANUNOO LETTER TA;Lo;0;L;;;;;N;;;;; 1727;HANUNOO LETTER DA;Lo;0;L;;;;;N;;;;; 1728;HANUNOO LETTER NA;Lo;0;L;;;;;N;;;;; 1729;HANUNOO LETTER PA;Lo;0;L;;;;;N;;;;; 172A;HANUNOO LETTER BA;Lo;0;L;;;;;N;;;;; 172B;HANUNOO LETTER MA;Lo;0;L;;;;;N;;;;; 172C;HANUNOO LETTER YA;Lo;0;L;;;;;N;;;;; 172D;HANUNOO LETTER RA;Lo;0;L;;;;;N;;;;; 172E;HANUNOO LETTER LA;Lo;0;L;;;;;N;;;;; 172F;HANUNOO LETTER WA;Lo;0;L;;;;;N;;;;; 1730;HANUNOO LETTER SA;Lo;0;L;;;;;N;;;;; 1731;HANUNOO LETTER HA;Lo;0;L;;;;;N;;;;; 1732;HANUNOO VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 1733;HANUNOO VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 1734;HANUNOO SIGN PAMUDPOD;Mn;9;NSM;;;;;N;;;;; 1735;PHILIPPINE SINGLE PUNCTUATION;Po;0;L;;;;;N;;;;; 1736;PHILIPPINE DOUBLE PUNCTUATION;Po;0;L;;;;;N;;;;; 1740;BUHID LETTER A;Lo;0;L;;;;;N;;;;; 1741;BUHID LETTER I;Lo;0;L;;;;;N;;;;; 1742;BUHID LETTER U;Lo;0;L;;;;;N;;;;; 1743;BUHID LETTER KA;Lo;0;L;;;;;N;;;;; 1744;BUHID LETTER GA;Lo;0;L;;;;;N;;;;; 1745;BUHID LETTER NGA;Lo;0;L;;;;;N;;;;; 1746;BUHID LETTER TA;Lo;0;L;;;;;N;;;;; 1747;BUHID LETTER DA;Lo;0;L;;;;;N;;;;; 1748;BUHID LETTER NA;Lo;0;L;;;;;N;;;;; 1749;BUHID LETTER PA;Lo;0;L;;;;;N;;;;; 174A;BUHID LETTER BA;Lo;0;L;;;;;N;;;;; 174B;BUHID LETTER MA;Lo;0;L;;;;;N;;;;; 174C;BUHID LETTER YA;Lo;0;L;;;;;N;;;;; 174D;BUHID LETTER RA;Lo;0;L;;;;;N;;;;; 174E;BUHID LETTER LA;Lo;0;L;;;;;N;;;;; 174F;BUHID LETTER WA;Lo;0;L;;;;;N;;;;; 1750;BUHID LETTER SA;Lo;0;L;;;;;N;;;;; 1751;BUHID LETTER HA;Lo;0;L;;;;;N;;;;; 1752;BUHID VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 1753;BUHID VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 1760;TAGBANWA LETTER A;Lo;0;L;;;;;N;;;;; 1761;TAGBANWA LETTER I;Lo;0;L;;;;;N;;;;; 1762;TAGBANWA LETTER U;Lo;0;L;;;;;N;;;;; 1763;TAGBANWA LETTER KA;Lo;0;L;;;;;N;;;;; 1764;TAGBANWA LETTER GA;Lo;0;L;;;;;N;;;;; 1765;TAGBANWA LETTER NGA;Lo;0;L;;;;;N;;;;; 1766;TAGBANWA LETTER TA;Lo;0;L;;;;;N;;;;; 1767;TAGBANWA LETTER DA;Lo;0;L;;;;;N;;;;; 1768;TAGBANWA LETTER NA;Lo;0;L;;;;;N;;;;; 1769;TAGBANWA LETTER PA;Lo;0;L;;;;;N;;;;; 176A;TAGBANWA LETTER BA;Lo;0;L;;;;;N;;;;; 176B;TAGBANWA LETTER MA;Lo;0;L;;;;;N;;;;; 176C;TAGBANWA LETTER YA;Lo;0;L;;;;;N;;;;; 176E;TAGBANWA LETTER LA;Lo;0;L;;;;;N;;;;; 176F;TAGBANWA LETTER WA;Lo;0;L;;;;;N;;;;; 1770;TAGBANWA LETTER SA;Lo;0;L;;;;;N;;;;; 1772;TAGBANWA VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 1773;TAGBANWA VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 1780;KHMER LETTER KA;Lo;0;L;;;;;N;;;;; 1781;KHMER LETTER KHA;Lo;0;L;;;;;N;;;;; 1782;KHMER LETTER KO;Lo;0;L;;;;;N;;;;; 1783;KHMER LETTER KHO;Lo;0;L;;;;;N;;;;; 1784;KHMER LETTER NGO;Lo;0;L;;;;;N;;;;; 1785;KHMER LETTER CA;Lo;0;L;;;;;N;;;;; 1786;KHMER LETTER CHA;Lo;0;L;;;;;N;;;;; 1787;KHMER LETTER CO;Lo;0;L;;;;;N;;;;; 1788;KHMER LETTER CHO;Lo;0;L;;;;;N;;;;; 1789;KHMER LETTER NYO;Lo;0;L;;;;;N;;;;; 178A;KHMER LETTER DA;Lo;0;L;;;;;N;;;;; 178B;KHMER LETTER TTHA;Lo;0;L;;;;;N;;;;; 178C;KHMER LETTER DO;Lo;0;L;;;;;N;;;;; 178D;KHMER LETTER TTHO;Lo;0;L;;;;;N;;;;; 178E;KHMER LETTER NNO;Lo;0;L;;;;;N;;;;; 178F;KHMER LETTER TA;Lo;0;L;;;;;N;;;;; 1790;KHMER LETTER THA;Lo;0;L;;;;;N;;;;; 1791;KHMER LETTER TO;Lo;0;L;;;;;N;;;;; 1792;KHMER LETTER THO;Lo;0;L;;;;;N;;;;; 1793;KHMER LETTER NO;Lo;0;L;;;;;N;;;;; 1794;KHMER LETTER BA;Lo;0;L;;;;;N;;;;; 1795;KHMER LETTER PHA;Lo;0;L;;;;;N;;;;; 1796;KHMER LETTER PO;Lo;0;L;;;;;N;;;;; 1797;KHMER LETTER PHO;Lo;0;L;;;;;N;;;;; 1798;KHMER LETTER MO;Lo;0;L;;;;;N;;;;; 1799;KHMER LETTER YO;Lo;0;L;;;;;N;;;;; 179A;KHMER LETTER RO;Lo;0;L;;;;;N;;;;; 179B;KHMER LETTER LO;Lo;0;L;;;;;N;;;;; 179C;KHMER LETTER VO;Lo;0;L;;;;;N;;;;; 179D;KHMER LETTER SHA;Lo;0;L;;;;;N;;;;; 179E;KHMER LETTER SSO;Lo;0;L;;;;;N;;;;; 179F;KHMER LETTER SA;Lo;0;L;;;;;N;;;;; 17A0;KHMER LETTER HA;Lo;0;L;;;;;N;;;;; 17A1;KHMER LETTER LA;Lo;0;L;;;;;N;;;;; 17A2;KHMER LETTER QA;Lo;0;L;;;;;N;;;;; 17A3;KHMER INDEPENDENT VOWEL QAQ;Lo;0;L;;;;;N;;;;; 17A4;KHMER INDEPENDENT VOWEL QAA;Lo;0;L;;;;;N;;;;; 17A5;KHMER INDEPENDENT VOWEL QI;Lo;0;L;;;;;N;;;;; 17A6;KHMER INDEPENDENT VOWEL QII;Lo;0;L;;;;;N;;;;; 17A7;KHMER INDEPENDENT VOWEL QU;Lo;0;L;;;;;N;;;;; 17A8;KHMER INDEPENDENT VOWEL QUK;Lo;0;L;;;;;N;;;;; 17A9;KHMER INDEPENDENT VOWEL QUU;Lo;0;L;;;;;N;;;;; 17AA;KHMER INDEPENDENT VOWEL QUUV;Lo;0;L;;;;;N;;;;; 17AB;KHMER INDEPENDENT VOWEL RY;Lo;0;L;;;;;N;;;;; 17AC;KHMER INDEPENDENT VOWEL RYY;Lo;0;L;;;;;N;;;;; 17AD;KHMER INDEPENDENT VOWEL LY;Lo;0;L;;;;;N;;;;; 17AE;KHMER INDEPENDENT VOWEL LYY;Lo;0;L;;;;;N;;;;; 17AF;KHMER INDEPENDENT VOWEL QE;Lo;0;L;;;;;N;;;;; 17B0;KHMER INDEPENDENT VOWEL QAI;Lo;0;L;;;;;N;;;;; 17B1;KHMER INDEPENDENT VOWEL QOO TYPE ONE;Lo;0;L;;;;;N;;;;; 17B2;KHMER INDEPENDENT VOWEL QOO TYPE TWO;Lo;0;L;;;;;N;;;;; 17B3;KHMER INDEPENDENT VOWEL QAU;Lo;0;L;;;;;N;;;;; 17B4;KHMER VOWEL INHERENT AQ;Mc;0;L;;;;;N;;;;; 17B5;KHMER VOWEL INHERENT AA;Mc;0;L;;;;;N;;;;; 17B6;KHMER VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 17B7;KHMER VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 17B8;KHMER VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; 17B9;KHMER VOWEL SIGN Y;Mn;0;NSM;;;;;N;;;;; 17BA;KHMER VOWEL SIGN YY;Mn;0;NSM;;;;;N;;;;; 17BB;KHMER VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 17BC;KHMER VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 17BD;KHMER VOWEL SIGN UA;Mn;0;NSM;;;;;N;;;;; 17BE;KHMER VOWEL SIGN OE;Mc;0;L;;;;;N;;;;; 17BF;KHMER VOWEL SIGN YA;Mc;0;L;;;;;N;;;;; 17C0;KHMER VOWEL SIGN IE;Mc;0;L;;;;;N;;;;; 17C1;KHMER VOWEL SIGN E;Mc;0;L;;;;;N;;;;; 17C2;KHMER VOWEL SIGN AE;Mc;0;L;;;;;N;;;;; 17C3;KHMER VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; 17C4;KHMER VOWEL SIGN OO;Mc;0;L;;;;;N;;;;; 17C5;KHMER VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; 17C6;KHMER SIGN NIKAHIT;Mn;0;NSM;;;;;N;;;;; 17C7;KHMER SIGN REAHMUK;Mc;0;L;;;;;N;;;;; 17C8;KHMER SIGN YUUKALEAPINTU;Mc;0;L;;;;;N;;;;; 17C9;KHMER SIGN MUUSIKATOAN;Mn;0;NSM;;;;;N;;;;; 17CA;KHMER SIGN TRIISAP;Mn;0;NSM;;;;;N;;;;; 17CB;KHMER SIGN BANTOC;Mn;0;NSM;;;;;N;;;;; 17CC;KHMER SIGN ROBAT;Mn;0;NSM;;;;;N;;;;; 17CD;KHMER SIGN TOANDAKHIAT;Mn;0;NSM;;;;;N;;;;; 17CE;KHMER SIGN KAKABAT;Mn;0;NSM;;;;;N;;;;; 17CF;KHMER SIGN AHSDA;Mn;0;NSM;;;;;N;;;;; 17D0;KHMER SIGN SAMYOK SANNYA;Mn;0;NSM;;;;;N;;;;; 17D1;KHMER SIGN VIRIAM;Mn;0;NSM;;;;;N;;;;; 17D2;KHMER SIGN COENG;Mn;9;NSM;;;;;N;;;;; 17D3;KHMER SIGN BATHAMASAT;Mn;0;NSM;;;;;N;;;;; 17D4;KHMER SIGN KHAN;Po;0;L;;;;;N;;;;; 17D5;KHMER SIGN BARIYOOSAN;Po;0;L;;;;;N;;;;; 17D6;KHMER SIGN CAMNUC PII KUUH;Po;0;L;;;;;N;;;;; 17D7;KHMER SIGN LEK TOO;Lm;0;L;;;;;N;;;;; 17D8;KHMER SIGN BEYYAL;Po;0;L;;;;;N;;;;; 17D9;KHMER SIGN PHNAEK MUAN;Po;0;L;;;;;N;;;;; 17DA;KHMER SIGN KOOMUUT;Po;0;L;;;;;N;;;;; 17DB;KHMER CURRENCY SYMBOL RIEL;Sc;0;ET;;;;;N;;;;; 17DC;KHMER SIGN AVAKRAHASANYA;Lo;0;L;;;;;N;;;;; 17E0;KHMER DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 17E1;KHMER DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 17E2;KHMER DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 17E3;KHMER DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 17E4;KHMER DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 17E5;KHMER DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 17E6;KHMER DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 17E7;KHMER DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 17E8;KHMER DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 17E9;KHMER DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 1800;MONGOLIAN BIRGA;Po;0;ON;;;;;N;;;;; 1801;MONGOLIAN ELLIPSIS;Po;0;ON;;;;;N;;;;; 1802;MONGOLIAN COMMA;Po;0;ON;;;;;N;;;;; 1803;MONGOLIAN FULL STOP;Po;0;ON;;;;;N;;;;; 1804;MONGOLIAN COLON;Po;0;ON;;;;;N;;;;; 1805;MONGOLIAN FOUR DOTS;Po;0;ON;;;;;N;;;;; 1806;MONGOLIAN TODO SOFT HYPHEN;Pd;0;ON;;;;;N;;;;; 1807;MONGOLIAN SIBE SYLLABLE BOUNDARY MARKER;Po;0;ON;;;;;N;;;;; 1808;MONGOLIAN MANCHU COMMA;Po;0;ON;;;;;N;;;;; 1809;MONGOLIAN MANCHU FULL STOP;Po;0;ON;;;;;N;;;;; 180A;MONGOLIAN NIRUGU;Po;0;ON;;;;;N;;;;; 180B;MONGOLIAN FREE VARIATION SELECTOR ONE;Mn;0;NSM;;;;;N;;;;; 180C;MONGOLIAN FREE VARIATION SELECTOR TWO;Mn;0;NSM;;;;;N;;;;; 180D;MONGOLIAN FREE VARIATION SELECTOR THREE;Mn;0;NSM;;;;;N;;;;; 180E;MONGOLIAN VOWEL SEPARATOR;Cf;0;BN;;;;;N;;;;; 1810;MONGOLIAN DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 1811;MONGOLIAN DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 1812;MONGOLIAN DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 1813;MONGOLIAN DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 1814;MONGOLIAN DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 1815;MONGOLIAN DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 1816;MONGOLIAN DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 1817;MONGOLIAN DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 1818;MONGOLIAN DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 1819;MONGOLIAN DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 1820;MONGOLIAN LETTER A;Lo;0;L;;;;;N;;;;; 1821;MONGOLIAN LETTER E;Lo;0;L;;;;;N;;;;; 1822;MONGOLIAN LETTER I;Lo;0;L;;;;;N;;;;; 1823;MONGOLIAN LETTER O;Lo;0;L;;;;;N;;;;; 1824;MONGOLIAN LETTER U;Lo;0;L;;;;;N;;;;; 1825;MONGOLIAN LETTER OE;Lo;0;L;;;;;N;;;;; 1826;MONGOLIAN LETTER UE;Lo;0;L;;;;;N;;;;; 1827;MONGOLIAN LETTER EE;Lo;0;L;;;;;N;;;;; 1828;MONGOLIAN LETTER NA;Lo;0;L;;;;;N;;;;; 1829;MONGOLIAN LETTER ANG;Lo;0;L;;;;;N;;;;; 182A;MONGOLIAN LETTER BA;Lo;0;L;;;;;N;;;;; 182B;MONGOLIAN LETTER PA;Lo;0;L;;;;;N;;;;; 182C;MONGOLIAN LETTER QA;Lo;0;L;;;;;N;;;;; 182D;MONGOLIAN LETTER GA;Lo;0;L;;;;;N;;;;; 182E;MONGOLIAN LETTER MA;Lo;0;L;;;;;N;;;;; 182F;MONGOLIAN LETTER LA;Lo;0;L;;;;;N;;;;; 1830;MONGOLIAN LETTER SA;Lo;0;L;;;;;N;;;;; 1831;MONGOLIAN LETTER SHA;Lo;0;L;;;;;N;;;;; 1832;MONGOLIAN LETTER TA;Lo;0;L;;;;;N;;;;; 1833;MONGOLIAN LETTER DA;Lo;0;L;;;;;N;;;;; 1834;MONGOLIAN LETTER CHA;Lo;0;L;;;;;N;;;;; 1835;MONGOLIAN LETTER JA;Lo;0;L;;;;;N;;;;; 1836;MONGOLIAN LETTER YA;Lo;0;L;;;;;N;;;;; 1837;MONGOLIAN LETTER RA;Lo;0;L;;;;;N;;;;; 1838;MONGOLIAN LETTER WA;Lo;0;L;;;;;N;;;;; 1839;MONGOLIAN LETTER FA;Lo;0;L;;;;;N;;;;; 183A;MONGOLIAN LETTER KA;Lo;0;L;;;;;N;;;;; 183B;MONGOLIAN LETTER KHA;Lo;0;L;;;;;N;;;;; 183C;MONGOLIAN LETTER TSA;Lo;0;L;;;;;N;;;;; 183D;MONGOLIAN LETTER ZA;Lo;0;L;;;;;N;;;;; 183E;MONGOLIAN LETTER HAA;Lo;0;L;;;;;N;;;;; 183F;MONGOLIAN LETTER ZRA;Lo;0;L;;;;;N;;;;; 1840;MONGOLIAN LETTER LHA;Lo;0;L;;;;;N;;;;; 1841;MONGOLIAN LETTER ZHI;Lo;0;L;;;;;N;;;;; 1842;MONGOLIAN LETTER CHI;Lo;0;L;;;;;N;;;;; 1843;MONGOLIAN LETTER TODO LONG VOWEL SIGN;Lm;0;L;;;;;N;;;;; 1844;MONGOLIAN LETTER TODO E;Lo;0;L;;;;;N;;;;; 1845;MONGOLIAN LETTER TODO I;Lo;0;L;;;;;N;;;;; 1846;MONGOLIAN LETTER TODO O;Lo;0;L;;;;;N;;;;; 1847;MONGOLIAN LETTER TODO U;Lo;0;L;;;;;N;;;;; 1848;MONGOLIAN LETTER TODO OE;Lo;0;L;;;;;N;;;;; 1849;MONGOLIAN LETTER TODO UE;Lo;0;L;;;;;N;;;;; 184A;MONGOLIAN LETTER TODO ANG;Lo;0;L;;;;;N;;;;; 184B;MONGOLIAN LETTER TODO BA;Lo;0;L;;;;;N;;;;; 184C;MONGOLIAN LETTER TODO PA;Lo;0;L;;;;;N;;;;; 184D;MONGOLIAN LETTER TODO QA;Lo;0;L;;;;;N;;;;; 184E;MONGOLIAN LETTER TODO GA;Lo;0;L;;;;;N;;;;; 184F;MONGOLIAN LETTER TODO MA;Lo;0;L;;;;;N;;;;; 1850;MONGOLIAN LETTER TODO TA;Lo;0;L;;;;;N;;;;; 1851;MONGOLIAN LETTER TODO DA;Lo;0;L;;;;;N;;;;; 1852;MONGOLIAN LETTER TODO CHA;Lo;0;L;;;;;N;;;;; 1853;MONGOLIAN LETTER TODO JA;Lo;0;L;;;;;N;;;;; 1854;MONGOLIAN LETTER TODO TSA;Lo;0;L;;;;;N;;;;; 1855;MONGOLIAN LETTER TODO YA;Lo;0;L;;;;;N;;;;; 1856;MONGOLIAN LETTER TODO WA;Lo;0;L;;;;;N;;;;; 1857;MONGOLIAN LETTER TODO KA;Lo;0;L;;;;;N;;;;; 1858;MONGOLIAN LETTER TODO GAA;Lo;0;L;;;;;N;;;;; 1859;MONGOLIAN LETTER TODO HAA;Lo;0;L;;;;;N;;;;; 185A;MONGOLIAN LETTER TODO JIA;Lo;0;L;;;;;N;;;;; 185B;MONGOLIAN LETTER TODO NIA;Lo;0;L;;;;;N;;;;; 185C;MONGOLIAN LETTER TODO DZA;Lo;0;L;;;;;N;;;;; 185D;MONGOLIAN LETTER SIBE E;Lo;0;L;;;;;N;;;;; 185E;MONGOLIAN LETTER SIBE I;Lo;0;L;;;;;N;;;;; 185F;MONGOLIAN LETTER SIBE IY;Lo;0;L;;;;;N;;;;; 1860;MONGOLIAN LETTER SIBE UE;Lo;0;L;;;;;N;;;;; 1861;MONGOLIAN LETTER SIBE U;Lo;0;L;;;;;N;;;;; 1862;MONGOLIAN LETTER SIBE ANG;Lo;0;L;;;;;N;;;;; 1863;MONGOLIAN LETTER SIBE KA;Lo;0;L;;;;;N;;;;; 1864;MONGOLIAN LETTER SIBE GA;Lo;0;L;;;;;N;;;;; 1865;MONGOLIAN LETTER SIBE HA;Lo;0;L;;;;;N;;;;; 1866;MONGOLIAN LETTER SIBE PA;Lo;0;L;;;;;N;;;;; 1867;MONGOLIAN LETTER SIBE SHA;Lo;0;L;;;;;N;;;;; 1868;MONGOLIAN LETTER SIBE TA;Lo;0;L;;;;;N;;;;; 1869;MONGOLIAN LETTER SIBE DA;Lo;0;L;;;;;N;;;;; 186A;MONGOLIAN LETTER SIBE JA;Lo;0;L;;;;;N;;;;; 186B;MONGOLIAN LETTER SIBE FA;Lo;0;L;;;;;N;;;;; 186C;MONGOLIAN LETTER SIBE GAA;Lo;0;L;;;;;N;;;;; 186D;MONGOLIAN LETTER SIBE HAA;Lo;0;L;;;;;N;;;;; 186E;MONGOLIAN LETTER SIBE TSA;Lo;0;L;;;;;N;;;;; 186F;MONGOLIAN LETTER SIBE ZA;Lo;0;L;;;;;N;;;;; 1870;MONGOLIAN LETTER SIBE RAA;Lo;0;L;;;;;N;;;;; 1871;MONGOLIAN LETTER SIBE CHA;Lo;0;L;;;;;N;;;;; 1872;MONGOLIAN LETTER SIBE ZHA;Lo;0;L;;;;;N;;;;; 1873;MONGOLIAN LETTER MANCHU I;Lo;0;L;;;;;N;;;;; 1874;MONGOLIAN LETTER MANCHU KA;Lo;0;L;;;;;N;;;;; 1875;MONGOLIAN LETTER MANCHU RA;Lo;0;L;;;;;N;;;;; 1876;MONGOLIAN LETTER MANCHU FA;Lo;0;L;;;;;N;;;;; 1877;MONGOLIAN LETTER MANCHU ZHA;Lo;0;L;;;;;N;;;;; 1880;MONGOLIAN LETTER ALI GALI ANUSVARA ONE;Lo;0;L;;;;;N;;;;; 1881;MONGOLIAN LETTER ALI GALI VISARGA ONE;Lo;0;L;;;;;N;;;;; 1882;MONGOLIAN LETTER ALI GALI DAMARU;Lo;0;L;;;;;N;;;;; 1883;MONGOLIAN LETTER ALI GALI UBADAMA;Lo;0;L;;;;;N;;;;; 1884;MONGOLIAN LETTER ALI GALI INVERTED UBADAMA;Lo;0;L;;;;;N;;;;; 1885;MONGOLIAN LETTER ALI GALI BALUDA;Lo;0;L;;;;;N;;;;; 1886;MONGOLIAN LETTER ALI GALI THREE BALUDA;Lo;0;L;;;;;N;;;;; 1887;MONGOLIAN LETTER ALI GALI A;Lo;0;L;;;;;N;;;;; 1888;MONGOLIAN LETTER ALI GALI I;Lo;0;L;;;;;N;;;;; 1889;MONGOLIAN LETTER ALI GALI KA;Lo;0;L;;;;;N;;;;; 188A;MONGOLIAN LETTER ALI GALI NGA;Lo;0;L;;;;;N;;;;; 188B;MONGOLIAN LETTER ALI GALI CA;Lo;0;L;;;;;N;;;;; 188C;MONGOLIAN LETTER ALI GALI TTA;Lo;0;L;;;;;N;;;;; 188D;MONGOLIAN LETTER ALI GALI TTHA;Lo;0;L;;;;;N;;;;; 188E;MONGOLIAN LETTER ALI GALI DDA;Lo;0;L;;;;;N;;;;; 188F;MONGOLIAN LETTER ALI GALI NNA;Lo;0;L;;;;;N;;;;; 1890;MONGOLIAN LETTER ALI GALI TA;Lo;0;L;;;;;N;;;;; 1891;MONGOLIAN LETTER ALI GALI DA;Lo;0;L;;;;;N;;;;; 1892;MONGOLIAN LETTER ALI GALI PA;Lo;0;L;;;;;N;;;;; 1893;MONGOLIAN LETTER ALI GALI PHA;Lo;0;L;;;;;N;;;;; 1894;MONGOLIAN LETTER ALI GALI SSA;Lo;0;L;;;;;N;;;;; 1895;MONGOLIAN LETTER ALI GALI ZHA;Lo;0;L;;;;;N;;;;; 1896;MONGOLIAN LETTER ALI GALI ZA;Lo;0;L;;;;;N;;;;; 1897;MONGOLIAN LETTER ALI GALI AH;Lo;0;L;;;;;N;;;;; 1898;MONGOLIAN LETTER TODO ALI GALI TA;Lo;0;L;;;;;N;;;;; 1899;MONGOLIAN LETTER TODO ALI GALI ZHA;Lo;0;L;;;;;N;;;;; 189A;MONGOLIAN LETTER MANCHU ALI GALI GHA;Lo;0;L;;;;;N;;;;; 189B;MONGOLIAN LETTER MANCHU ALI GALI NGA;Lo;0;L;;;;;N;;;;; 189C;MONGOLIAN LETTER MANCHU ALI GALI CA;Lo;0;L;;;;;N;;;;; 189D;MONGOLIAN LETTER MANCHU ALI GALI JHA;Lo;0;L;;;;;N;;;;; 189E;MONGOLIAN LETTER MANCHU ALI GALI TTA;Lo;0;L;;;;;N;;;;; 189F;MONGOLIAN LETTER MANCHU ALI GALI DDHA;Lo;0;L;;;;;N;;;;; 18A0;MONGOLIAN LETTER MANCHU ALI GALI TA;Lo;0;L;;;;;N;;;;; 18A1;MONGOLIAN LETTER MANCHU ALI GALI DHA;Lo;0;L;;;;;N;;;;; 18A2;MONGOLIAN LETTER MANCHU ALI GALI SSA;Lo;0;L;;;;;N;;;;; 18A3;MONGOLIAN LETTER MANCHU ALI GALI CYA;Lo;0;L;;;;;N;;;;; 18A4;MONGOLIAN LETTER MANCHU ALI GALI ZHA;Lo;0;L;;;;;N;;;;; 18A5;MONGOLIAN LETTER MANCHU ALI GALI ZA;Lo;0;L;;;;;N;;;;; 18A6;MONGOLIAN LETTER ALI GALI HALF U;Lo;0;L;;;;;N;;;;; 18A7;MONGOLIAN LETTER ALI GALI HALF YA;Lo;0;L;;;;;N;;;;; 18A8;MONGOLIAN LETTER MANCHU ALI GALI BHA;Lo;0;L;;;;;N;;;;; 18A9;MONGOLIAN LETTER ALI GALI DAGALGA;Mn;228;NSM;;;;;N;;;;; 1E00;LATIN CAPITAL LETTER A WITH RING BELOW;Lu;0;L;0041 0325;;;;N;;;;1E01; 1E01;LATIN SMALL LETTER A WITH RING BELOW;Ll;0;L;0061 0325;;;;N;;;1E00;;1E00 1E02;LATIN CAPITAL LETTER B WITH DOT ABOVE;Lu;0;L;0042 0307;;;;N;;;;1E03; 1E03;LATIN SMALL LETTER B WITH DOT ABOVE;Ll;0;L;0062 0307;;;;N;;;1E02;;1E02 1E04;LATIN CAPITAL LETTER B WITH DOT BELOW;Lu;0;L;0042 0323;;;;N;;;;1E05; 1E05;LATIN SMALL LETTER B WITH DOT BELOW;Ll;0;L;0062 0323;;;;N;;;1E04;;1E04 1E06;LATIN CAPITAL LETTER B WITH LINE BELOW;Lu;0;L;0042 0331;;;;N;;;;1E07; 1E07;LATIN SMALL LETTER B WITH LINE BELOW;Ll;0;L;0062 0331;;;;N;;;1E06;;1E06 1E08;LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE;Lu;0;L;00C7 0301;;;;N;;;;1E09; 1E09;LATIN SMALL LETTER C WITH CEDILLA AND ACUTE;Ll;0;L;00E7 0301;;;;N;;;1E08;;1E08 1E0A;LATIN CAPITAL LETTER D WITH DOT ABOVE;Lu;0;L;0044 0307;;;;N;;;;1E0B; 1E0B;LATIN SMALL LETTER D WITH DOT ABOVE;Ll;0;L;0064 0307;;;;N;;;1E0A;;1E0A 1E0C;LATIN CAPITAL LETTER D WITH DOT BELOW;Lu;0;L;0044 0323;;;;N;;;;1E0D; 1E0D;LATIN SMALL LETTER D WITH DOT BELOW;Ll;0;L;0064 0323;;;;N;;;1E0C;;1E0C 1E0E;LATIN CAPITAL LETTER D WITH LINE BELOW;Lu;0;L;0044 0331;;;;N;;;;1E0F; 1E0F;LATIN SMALL LETTER D WITH LINE BELOW;Ll;0;L;0064 0331;;;;N;;;1E0E;;1E0E 1E10;LATIN CAPITAL LETTER D WITH CEDILLA;Lu;0;L;0044 0327;;;;N;;;;1E11; 1E11;LATIN SMALL LETTER D WITH CEDILLA;Ll;0;L;0064 0327;;;;N;;;1E10;;1E10 1E12;LATIN CAPITAL LETTER D WITH CIRCUMFLEX BELOW;Lu;0;L;0044 032D;;;;N;;;;1E13; 1E13;LATIN SMALL LETTER D WITH CIRCUMFLEX BELOW;Ll;0;L;0064 032D;;;;N;;;1E12;;1E12 1E14;LATIN CAPITAL LETTER E WITH MACRON AND GRAVE;Lu;0;L;0112 0300;;;;N;;;;1E15; 1E15;LATIN SMALL LETTER E WITH MACRON AND GRAVE;Ll;0;L;0113 0300;;;;N;;;1E14;;1E14 1E16;LATIN CAPITAL LETTER E WITH MACRON AND ACUTE;Lu;0;L;0112 0301;;;;N;;;;1E17; 1E17;LATIN SMALL LETTER E WITH MACRON AND ACUTE;Ll;0;L;0113 0301;;;;N;;;1E16;;1E16 1E18;LATIN CAPITAL LETTER E WITH CIRCUMFLEX BELOW;Lu;0;L;0045 032D;;;;N;;;;1E19; 1E19;LATIN SMALL LETTER E WITH CIRCUMFLEX BELOW;Ll;0;L;0065 032D;;;;N;;;1E18;;1E18 1E1A;LATIN CAPITAL LETTER E WITH TILDE BELOW;Lu;0;L;0045 0330;;;;N;;;;1E1B; 1E1B;LATIN SMALL LETTER E WITH TILDE BELOW;Ll;0;L;0065 0330;;;;N;;;1E1A;;1E1A 1E1C;LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE;Lu;0;L;0228 0306;;;;N;;;;1E1D; 1E1D;LATIN SMALL LETTER E WITH CEDILLA AND BREVE;Ll;0;L;0229 0306;;;;N;;;1E1C;;1E1C 1E1E;LATIN CAPITAL LETTER F WITH DOT ABOVE;Lu;0;L;0046 0307;;;;N;;;;1E1F; 1E1F;LATIN SMALL LETTER F WITH DOT ABOVE;Ll;0;L;0066 0307;;;;N;;;1E1E;;1E1E 1E20;LATIN CAPITAL LETTER G WITH MACRON;Lu;0;L;0047 0304;;;;N;;;;1E21; 1E21;LATIN SMALL LETTER G WITH MACRON;Ll;0;L;0067 0304;;;;N;;;1E20;;1E20 1E22;LATIN CAPITAL LETTER H WITH DOT ABOVE;Lu;0;L;0048 0307;;;;N;;;;1E23; 1E23;LATIN SMALL LETTER H WITH DOT ABOVE;Ll;0;L;0068 0307;;;;N;;;1E22;;1E22 1E24;LATIN CAPITAL LETTER H WITH DOT BELOW;Lu;0;L;0048 0323;;;;N;;;;1E25; 1E25;LATIN SMALL LETTER H WITH DOT BELOW;Ll;0;L;0068 0323;;;;N;;;1E24;;1E24 1E26;LATIN CAPITAL LETTER H WITH DIAERESIS;Lu;0;L;0048 0308;;;;N;;;;1E27; 1E27;LATIN SMALL LETTER H WITH DIAERESIS;Ll;0;L;0068 0308;;;;N;;;1E26;;1E26 1E28;LATIN CAPITAL LETTER H WITH CEDILLA;Lu;0;L;0048 0327;;;;N;;;;1E29; 1E29;LATIN SMALL LETTER H WITH CEDILLA;Ll;0;L;0068 0327;;;;N;;;1E28;;1E28 1E2A;LATIN CAPITAL LETTER H WITH BREVE BELOW;Lu;0;L;0048 032E;;;;N;;;;1E2B; 1E2B;LATIN SMALL LETTER H WITH BREVE BELOW;Ll;0;L;0068 032E;;;;N;;;1E2A;;1E2A 1E2C;LATIN CAPITAL LETTER I WITH TILDE BELOW;Lu;0;L;0049 0330;;;;N;;;;1E2D; 1E2D;LATIN SMALL LETTER I WITH TILDE BELOW;Ll;0;L;0069 0330;;;;N;;;1E2C;;1E2C 1E2E;LATIN CAPITAL LETTER I WITH DIAERESIS AND ACUTE;Lu;0;L;00CF 0301;;;;N;;;;1E2F; 1E2F;LATIN SMALL LETTER I WITH DIAERESIS AND ACUTE;Ll;0;L;00EF 0301;;;;N;;;1E2E;;1E2E 1E30;LATIN CAPITAL LETTER K WITH ACUTE;Lu;0;L;004B 0301;;;;N;;;;1E31; 1E31;LATIN SMALL LETTER K WITH ACUTE;Ll;0;L;006B 0301;;;;N;;;1E30;;1E30 1E32;LATIN CAPITAL LETTER K WITH DOT BELOW;Lu;0;L;004B 0323;;;;N;;;;1E33; 1E33;LATIN SMALL LETTER K WITH DOT BELOW;Ll;0;L;006B 0323;;;;N;;;1E32;;1E32 1E34;LATIN CAPITAL LETTER K WITH LINE BELOW;Lu;0;L;004B 0331;;;;N;;;;1E35; 1E35;LATIN SMALL LETTER K WITH LINE BELOW;Ll;0;L;006B 0331;;;;N;;;1E34;;1E34 1E36;LATIN CAPITAL LETTER L WITH DOT BELOW;Lu;0;L;004C 0323;;;;N;;;;1E37; 1E37;LATIN SMALL LETTER L WITH DOT BELOW;Ll;0;L;006C 0323;;;;N;;;1E36;;1E36 1E38;LATIN CAPITAL LETTER L WITH DOT BELOW AND MACRON;Lu;0;L;1E36 0304;;;;N;;;;1E39; 1E39;LATIN SMALL LETTER L WITH DOT BELOW AND MACRON;Ll;0;L;1E37 0304;;;;N;;;1E38;;1E38 1E3A;LATIN CAPITAL LETTER L WITH LINE BELOW;Lu;0;L;004C 0331;;;;N;;;;1E3B; 1E3B;LATIN SMALL LETTER L WITH LINE BELOW;Ll;0;L;006C 0331;;;;N;;;1E3A;;1E3A 1E3C;LATIN CAPITAL LETTER L WITH CIRCUMFLEX BELOW;Lu;0;L;004C 032D;;;;N;;;;1E3D; 1E3D;LATIN SMALL LETTER L WITH CIRCUMFLEX BELOW;Ll;0;L;006C 032D;;;;N;;;1E3C;;1E3C 1E3E;LATIN CAPITAL LETTER M WITH ACUTE;Lu;0;L;004D 0301;;;;N;;;;1E3F; 1E3F;LATIN SMALL LETTER M WITH ACUTE;Ll;0;L;006D 0301;;;;N;;;1E3E;;1E3E 1E40;LATIN CAPITAL LETTER M WITH DOT ABOVE;Lu;0;L;004D 0307;;;;N;;;;1E41; 1E41;LATIN SMALL LETTER M WITH DOT ABOVE;Ll;0;L;006D 0307;;;;N;;;1E40;;1E40 1E42;LATIN CAPITAL LETTER M WITH DOT BELOW;Lu;0;L;004D 0323;;;;N;;;;1E43; 1E43;LATIN SMALL LETTER M WITH DOT BELOW;Ll;0;L;006D 0323;;;;N;;;1E42;;1E42 1E44;LATIN CAPITAL LETTER N WITH DOT ABOVE;Lu;0;L;004E 0307;;;;N;;;;1E45; 1E45;LATIN SMALL LETTER N WITH DOT ABOVE;Ll;0;L;006E 0307;;;;N;;;1E44;;1E44 1E46;LATIN CAPITAL LETTER N WITH DOT BELOW;Lu;0;L;004E 0323;;;;N;;;;1E47; 1E47;LATIN SMALL LETTER N WITH DOT BELOW;Ll;0;L;006E 0323;;;;N;;;1E46;;1E46 1E48;LATIN CAPITAL LETTER N WITH LINE BELOW;Lu;0;L;004E 0331;;;;N;;;;1E49; 1E49;LATIN SMALL LETTER N WITH LINE BELOW;Ll;0;L;006E 0331;;;;N;;;1E48;;1E48 1E4A;LATIN CAPITAL LETTER N WITH CIRCUMFLEX BELOW;Lu;0;L;004E 032D;;;;N;;;;1E4B; 1E4B;LATIN SMALL LETTER N WITH CIRCUMFLEX BELOW;Ll;0;L;006E 032D;;;;N;;;1E4A;;1E4A 1E4C;LATIN CAPITAL LETTER O WITH TILDE AND ACUTE;Lu;0;L;00D5 0301;;;;N;;;;1E4D; 1E4D;LATIN SMALL LETTER O WITH TILDE AND ACUTE;Ll;0;L;00F5 0301;;;;N;;;1E4C;;1E4C 1E4E;LATIN CAPITAL LETTER O WITH TILDE AND DIAERESIS;Lu;0;L;00D5 0308;;;;N;;;;1E4F; 1E4F;LATIN SMALL LETTER O WITH TILDE AND DIAERESIS;Ll;0;L;00F5 0308;;;;N;;;1E4E;;1E4E 1E50;LATIN CAPITAL LETTER O WITH MACRON AND GRAVE;Lu;0;L;014C 0300;;;;N;;;;1E51; 1E51;LATIN SMALL LETTER O WITH MACRON AND GRAVE;Ll;0;L;014D 0300;;;;N;;;1E50;;1E50 1E52;LATIN CAPITAL LETTER O WITH MACRON AND ACUTE;Lu;0;L;014C 0301;;;;N;;;;1E53; 1E53;LATIN SMALL LETTER O WITH MACRON AND ACUTE;Ll;0;L;014D 0301;;;;N;;;1E52;;1E52 1E54;LATIN CAPITAL LETTER P WITH ACUTE;Lu;0;L;0050 0301;;;;N;;;;1E55; 1E55;LATIN SMALL LETTER P WITH ACUTE;Ll;0;L;0070 0301;;;;N;;;1E54;;1E54 1E56;LATIN CAPITAL LETTER P WITH DOT ABOVE;Lu;0;L;0050 0307;;;;N;;;;1E57; 1E57;LATIN SMALL LETTER P WITH DOT ABOVE;Ll;0;L;0070 0307;;;;N;;;1E56;;1E56 1E58;LATIN CAPITAL LETTER R WITH DOT ABOVE;Lu;0;L;0052 0307;;;;N;;;;1E59; 1E59;LATIN SMALL LETTER R WITH DOT ABOVE;Ll;0;L;0072 0307;;;;N;;;1E58;;1E58 1E5A;LATIN CAPITAL LETTER R WITH DOT BELOW;Lu;0;L;0052 0323;;;;N;;;;1E5B; 1E5B;LATIN SMALL LETTER R WITH DOT BELOW;Ll;0;L;0072 0323;;;;N;;;1E5A;;1E5A 1E5C;LATIN CAPITAL LETTER R WITH DOT BELOW AND MACRON;Lu;0;L;1E5A 0304;;;;N;;;;1E5D; 1E5D;LATIN SMALL LETTER R WITH DOT BELOW AND MACRON;Ll;0;L;1E5B 0304;;;;N;;;1E5C;;1E5C 1E5E;LATIN CAPITAL LETTER R WITH LINE BELOW;Lu;0;L;0052 0331;;;;N;;;;1E5F; 1E5F;LATIN SMALL LETTER R WITH LINE BELOW;Ll;0;L;0072 0331;;;;N;;;1E5E;;1E5E 1E60;LATIN CAPITAL LETTER S WITH DOT ABOVE;Lu;0;L;0053 0307;;;;N;;;;1E61; 1E61;LATIN SMALL LETTER S WITH DOT ABOVE;Ll;0;L;0073 0307;;;;N;;;1E60;;1E60 1E62;LATIN CAPITAL LETTER S WITH DOT BELOW;Lu;0;L;0053 0323;;;;N;;;;1E63; 1E63;LATIN SMALL LETTER S WITH DOT BELOW;Ll;0;L;0073 0323;;;;N;;;1E62;;1E62 1E64;LATIN CAPITAL LETTER S WITH ACUTE AND DOT ABOVE;Lu;0;L;015A 0307;;;;N;;;;1E65; 1E65;LATIN SMALL LETTER S WITH ACUTE AND DOT ABOVE;Ll;0;L;015B 0307;;;;N;;;1E64;;1E64 1E66;LATIN CAPITAL LETTER S WITH CARON AND DOT ABOVE;Lu;0;L;0160 0307;;;;N;;;;1E67; 1E67;LATIN SMALL LETTER S WITH CARON AND DOT ABOVE;Ll;0;L;0161 0307;;;;N;;;1E66;;1E66 1E68;LATIN CAPITAL LETTER S WITH DOT BELOW AND DOT ABOVE;Lu;0;L;1E62 0307;;;;N;;;;1E69; 1E69;LATIN SMALL LETTER S WITH DOT BELOW AND DOT ABOVE;Ll;0;L;1E63 0307;;;;N;;;1E68;;1E68 1E6A;LATIN CAPITAL LETTER T WITH DOT ABOVE;Lu;0;L;0054 0307;;;;N;;;;1E6B; 1E6B;LATIN SMALL LETTER T WITH DOT ABOVE;Ll;0;L;0074 0307;;;;N;;;1E6A;;1E6A 1E6C;LATIN CAPITAL LETTER T WITH DOT BELOW;Lu;0;L;0054 0323;;;;N;;;;1E6D; 1E6D;LATIN SMALL LETTER T WITH DOT BELOW;Ll;0;L;0074 0323;;;;N;;;1E6C;;1E6C 1E6E;LATIN CAPITAL LETTER T WITH LINE BELOW;Lu;0;L;0054 0331;;;;N;;;;1E6F; 1E6F;LATIN SMALL LETTER T WITH LINE BELOW;Ll;0;L;0074 0331;;;;N;;;1E6E;;1E6E 1E70;LATIN CAPITAL LETTER T WITH CIRCUMFLEX BELOW;Lu;0;L;0054 032D;;;;N;;;;1E71; 1E71;LATIN SMALL LETTER T WITH CIRCUMFLEX BELOW;Ll;0;L;0074 032D;;;;N;;;1E70;;1E70 1E72;LATIN CAPITAL LETTER U WITH DIAERESIS BELOW;Lu;0;L;0055 0324;;;;N;;;;1E73; 1E73;LATIN SMALL LETTER U WITH DIAERESIS BELOW;Ll;0;L;0075 0324;;;;N;;;1E72;;1E72 1E74;LATIN CAPITAL LETTER U WITH TILDE BELOW;Lu;0;L;0055 0330;;;;N;;;;1E75; 1E75;LATIN SMALL LETTER U WITH TILDE BELOW;Ll;0;L;0075 0330;;;;N;;;1E74;;1E74 1E76;LATIN CAPITAL LETTER U WITH CIRCUMFLEX BELOW;Lu;0;L;0055 032D;;;;N;;;;1E77; 1E77;LATIN SMALL LETTER U WITH CIRCUMFLEX BELOW;Ll;0;L;0075 032D;;;;N;;;1E76;;1E76 1E78;LATIN CAPITAL LETTER U WITH TILDE AND ACUTE;Lu;0;L;0168 0301;;;;N;;;;1E79; 1E79;LATIN SMALL LETTER U WITH TILDE AND ACUTE;Ll;0;L;0169 0301;;;;N;;;1E78;;1E78 1E7A;LATIN CAPITAL LETTER U WITH MACRON AND DIAERESIS;Lu;0;L;016A 0308;;;;N;;;;1E7B; 1E7B;LATIN SMALL LETTER U WITH MACRON AND DIAERESIS;Ll;0;L;016B 0308;;;;N;;;1E7A;;1E7A 1E7C;LATIN CAPITAL LETTER V WITH TILDE;Lu;0;L;0056 0303;;;;N;;;;1E7D; 1E7D;LATIN SMALL LETTER V WITH TILDE;Ll;0;L;0076 0303;;;;N;;;1E7C;;1E7C 1E7E;LATIN CAPITAL LETTER V WITH DOT BELOW;Lu;0;L;0056 0323;;;;N;;;;1E7F; 1E7F;LATIN SMALL LETTER V WITH DOT BELOW;Ll;0;L;0076 0323;;;;N;;;1E7E;;1E7E 1E80;LATIN CAPITAL LETTER W WITH GRAVE;Lu;0;L;0057 0300;;;;N;;;;1E81; 1E81;LATIN SMALL LETTER W WITH GRAVE;Ll;0;L;0077 0300;;;;N;;;1E80;;1E80 1E82;LATIN CAPITAL LETTER W WITH ACUTE;Lu;0;L;0057 0301;;;;N;;;;1E83; 1E83;LATIN SMALL LETTER W WITH ACUTE;Ll;0;L;0077 0301;;;;N;;;1E82;;1E82 1E84;LATIN CAPITAL LETTER W WITH DIAERESIS;Lu;0;L;0057 0308;;;;N;;;;1E85; 1E85;LATIN SMALL LETTER W WITH DIAERESIS;Ll;0;L;0077 0308;;;;N;;;1E84;;1E84 1E86;LATIN CAPITAL LETTER W WITH DOT ABOVE;Lu;0;L;0057 0307;;;;N;;;;1E87; 1E87;LATIN SMALL LETTER W WITH DOT ABOVE;Ll;0;L;0077 0307;;;;N;;;1E86;;1E86 1E88;LATIN CAPITAL LETTER W WITH DOT BELOW;Lu;0;L;0057 0323;;;;N;;;;1E89; 1E89;LATIN SMALL LETTER W WITH DOT BELOW;Ll;0;L;0077 0323;;;;N;;;1E88;;1E88 1E8A;LATIN CAPITAL LETTER X WITH DOT ABOVE;Lu;0;L;0058 0307;;;;N;;;;1E8B; 1E8B;LATIN SMALL LETTER X WITH DOT ABOVE;Ll;0;L;0078 0307;;;;N;;;1E8A;;1E8A 1E8C;LATIN CAPITAL LETTER X WITH DIAERESIS;Lu;0;L;0058 0308;;;;N;;;;1E8D; 1E8D;LATIN SMALL LETTER X WITH DIAERESIS;Ll;0;L;0078 0308;;;;N;;;1E8C;;1E8C 1E8E;LATIN CAPITAL LETTER Y WITH DOT ABOVE;Lu;0;L;0059 0307;;;;N;;;;1E8F; 1E8F;LATIN SMALL LETTER Y WITH DOT ABOVE;Ll;0;L;0079 0307;;;;N;;;1E8E;;1E8E 1E90;LATIN CAPITAL LETTER Z WITH CIRCUMFLEX;Lu;0;L;005A 0302;;;;N;;;;1E91; 1E91;LATIN SMALL LETTER Z WITH CIRCUMFLEX;Ll;0;L;007A 0302;;;;N;;;1E90;;1E90 1E92;LATIN CAPITAL LETTER Z WITH DOT BELOW;Lu;0;L;005A 0323;;;;N;;;;1E93; 1E93;LATIN SMALL LETTER Z WITH DOT BELOW;Ll;0;L;007A 0323;;;;N;;;1E92;;1E92 1E94;LATIN CAPITAL LETTER Z WITH LINE BELOW;Lu;0;L;005A 0331;;;;N;;;;1E95; 1E95;LATIN SMALL LETTER Z WITH LINE BELOW;Ll;0;L;007A 0331;;;;N;;;1E94;;1E94 1E96;LATIN SMALL LETTER H WITH LINE BELOW;Ll;0;L;0068 0331;;;;N;;;;; 1E97;LATIN SMALL LETTER T WITH DIAERESIS;Ll;0;L;0074 0308;;;;N;;;;; 1E98;LATIN SMALL LETTER W WITH RING ABOVE;Ll;0;L;0077 030A;;;;N;;;;; 1E99;LATIN SMALL LETTER Y WITH RING ABOVE;Ll;0;L;0079 030A;;;;N;;;;; 1E9A;LATIN SMALL LETTER A WITH RIGHT HALF RING;Ll;0;L; 0061 02BE;;;;N;;;;; 1E9B;LATIN SMALL LETTER LONG S WITH DOT ABOVE;Ll;0;L;017F 0307;;;;N;;;1E60;;1E60 1EA0;LATIN CAPITAL LETTER A WITH DOT BELOW;Lu;0;L;0041 0323;;;;N;;;;1EA1; 1EA1;LATIN SMALL LETTER A WITH DOT BELOW;Ll;0;L;0061 0323;;;;N;;;1EA0;;1EA0 1EA2;LATIN CAPITAL LETTER A WITH HOOK ABOVE;Lu;0;L;0041 0309;;;;N;;;;1EA3; 1EA3;LATIN SMALL LETTER A WITH HOOK ABOVE;Ll;0;L;0061 0309;;;;N;;;1EA2;;1EA2 1EA4;LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE;Lu;0;L;00C2 0301;;;;N;;;;1EA5; 1EA5;LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE;Ll;0;L;00E2 0301;;;;N;;;1EA4;;1EA4 1EA6;LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE;Lu;0;L;00C2 0300;;;;N;;;;1EA7; 1EA7;LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE;Ll;0;L;00E2 0300;;;;N;;;1EA6;;1EA6 1EA8;LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE;Lu;0;L;00C2 0309;;;;N;;;;1EA9; 1EA9;LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE;Ll;0;L;00E2 0309;;;;N;;;1EA8;;1EA8 1EAA;LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE;Lu;0;L;00C2 0303;;;;N;;;;1EAB; 1EAB;LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE;Ll;0;L;00E2 0303;;;;N;;;1EAA;;1EAA 1EAC;LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW;Lu;0;L;1EA0 0302;;;;N;;;;1EAD; 1EAD;LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW;Ll;0;L;1EA1 0302;;;;N;;;1EAC;;1EAC 1EAE;LATIN CAPITAL LETTER A WITH BREVE AND ACUTE;Lu;0;L;0102 0301;;;;N;;;;1EAF; 1EAF;LATIN SMALL LETTER A WITH BREVE AND ACUTE;Ll;0;L;0103 0301;;;;N;;;1EAE;;1EAE 1EB0;LATIN CAPITAL LETTER A WITH BREVE AND GRAVE;Lu;0;L;0102 0300;;;;N;;;;1EB1; 1EB1;LATIN SMALL LETTER A WITH BREVE AND GRAVE;Ll;0;L;0103 0300;;;;N;;;1EB0;;1EB0 1EB2;LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE;Lu;0;L;0102 0309;;;;N;;;;1EB3; 1EB3;LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE;Ll;0;L;0103 0309;;;;N;;;1EB2;;1EB2 1EB4;LATIN CAPITAL LETTER A WITH BREVE AND TILDE;Lu;0;L;0102 0303;;;;N;;;;1EB5; 1EB5;LATIN SMALL LETTER A WITH BREVE AND TILDE;Ll;0;L;0103 0303;;;;N;;;1EB4;;1EB4 1EB6;LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW;Lu;0;L;1EA0 0306;;;;N;;;;1EB7; 1EB7;LATIN SMALL LETTER A WITH BREVE AND DOT BELOW;Ll;0;L;1EA1 0306;;;;N;;;1EB6;;1EB6 1EB8;LATIN CAPITAL LETTER E WITH DOT BELOW;Lu;0;L;0045 0323;;;;N;;;;1EB9; 1EB9;LATIN SMALL LETTER E WITH DOT BELOW;Ll;0;L;0065 0323;;;;N;;;1EB8;;1EB8 1EBA;LATIN CAPITAL LETTER E WITH HOOK ABOVE;Lu;0;L;0045 0309;;;;N;;;;1EBB; 1EBB;LATIN SMALL LETTER E WITH HOOK ABOVE;Ll;0;L;0065 0309;;;;N;;;1EBA;;1EBA 1EBC;LATIN CAPITAL LETTER E WITH TILDE;Lu;0;L;0045 0303;;;;N;;;;1EBD; 1EBD;LATIN SMALL LETTER E WITH TILDE;Ll;0;L;0065 0303;;;;N;;;1EBC;;1EBC 1EBE;LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE;Lu;0;L;00CA 0301;;;;N;;;;1EBF; 1EBF;LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE;Ll;0;L;00EA 0301;;;;N;;;1EBE;;1EBE 1EC0;LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE;Lu;0;L;00CA 0300;;;;N;;;;1EC1; 1EC1;LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE;Ll;0;L;00EA 0300;;;;N;;;1EC0;;1EC0 1EC2;LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE;Lu;0;L;00CA 0309;;;;N;;;;1EC3; 1EC3;LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE;Ll;0;L;00EA 0309;;;;N;;;1EC2;;1EC2 1EC4;LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE;Lu;0;L;00CA 0303;;;;N;;;;1EC5; 1EC5;LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE;Ll;0;L;00EA 0303;;;;N;;;1EC4;;1EC4 1EC6;LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW;Lu;0;L;1EB8 0302;;;;N;;;;1EC7; 1EC7;LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW;Ll;0;L;1EB9 0302;;;;N;;;1EC6;;1EC6 1EC8;LATIN CAPITAL LETTER I WITH HOOK ABOVE;Lu;0;L;0049 0309;;;;N;;;;1EC9; 1EC9;LATIN SMALL LETTER I WITH HOOK ABOVE;Ll;0;L;0069 0309;;;;N;;;1EC8;;1EC8 1ECA;LATIN CAPITAL LETTER I WITH DOT BELOW;Lu;0;L;0049 0323;;;;N;;;;1ECB; 1ECB;LATIN SMALL LETTER I WITH DOT BELOW;Ll;0;L;0069 0323;;;;N;;;1ECA;;1ECA 1ECC;LATIN CAPITAL LETTER O WITH DOT BELOW;Lu;0;L;004F 0323;;;;N;;;;1ECD; 1ECD;LATIN SMALL LETTER O WITH DOT BELOW;Ll;0;L;006F 0323;;;;N;;;1ECC;;1ECC 1ECE;LATIN CAPITAL LETTER O WITH HOOK ABOVE;Lu;0;L;004F 0309;;;;N;;;;1ECF; 1ECF;LATIN SMALL LETTER O WITH HOOK ABOVE;Ll;0;L;006F 0309;;;;N;;;1ECE;;1ECE 1ED0;LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE;Lu;0;L;00D4 0301;;;;N;;;;1ED1; 1ED1;LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE;Ll;0;L;00F4 0301;;;;N;;;1ED0;;1ED0 1ED2;LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE;Lu;0;L;00D4 0300;;;;N;;;;1ED3; 1ED3;LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE;Ll;0;L;00F4 0300;;;;N;;;1ED2;;1ED2 1ED4;LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE;Lu;0;L;00D4 0309;;;;N;;;;1ED5; 1ED5;LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE;Ll;0;L;00F4 0309;;;;N;;;1ED4;;1ED4 1ED6;LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE;Lu;0;L;00D4 0303;;;;N;;;;1ED7; 1ED7;LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE;Ll;0;L;00F4 0303;;;;N;;;1ED6;;1ED6 1ED8;LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW;Lu;0;L;1ECC 0302;;;;N;;;;1ED9; 1ED9;LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW;Ll;0;L;1ECD 0302;;;;N;;;1ED8;;1ED8 1EDA;LATIN CAPITAL LETTER O WITH HORN AND ACUTE;Lu;0;L;01A0 0301;;;;N;;;;1EDB; 1EDB;LATIN SMALL LETTER O WITH HORN AND ACUTE;Ll;0;L;01A1 0301;;;;N;;;1EDA;;1EDA 1EDC;LATIN CAPITAL LETTER O WITH HORN AND GRAVE;Lu;0;L;01A0 0300;;;;N;;;;1EDD; 1EDD;LATIN SMALL LETTER O WITH HORN AND GRAVE;Ll;0;L;01A1 0300;;;;N;;;1EDC;;1EDC 1EDE;LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE;Lu;0;L;01A0 0309;;;;N;;;;1EDF; 1EDF;LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE;Ll;0;L;01A1 0309;;;;N;;;1EDE;;1EDE 1EE0;LATIN CAPITAL LETTER O WITH HORN AND TILDE;Lu;0;L;01A0 0303;;;;N;;;;1EE1; 1EE1;LATIN SMALL LETTER O WITH HORN AND TILDE;Ll;0;L;01A1 0303;;;;N;;;1EE0;;1EE0 1EE2;LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW;Lu;0;L;01A0 0323;;;;N;;;;1EE3; 1EE3;LATIN SMALL LETTER O WITH HORN AND DOT BELOW;Ll;0;L;01A1 0323;;;;N;;;1EE2;;1EE2 1EE4;LATIN CAPITAL LETTER U WITH DOT BELOW;Lu;0;L;0055 0323;;;;N;;;;1EE5; 1EE5;LATIN SMALL LETTER U WITH DOT BELOW;Ll;0;L;0075 0323;;;;N;;;1EE4;;1EE4 1EE6;LATIN CAPITAL LETTER U WITH HOOK ABOVE;Lu;0;L;0055 0309;;;;N;;;;1EE7; 1EE7;LATIN SMALL LETTER U WITH HOOK ABOVE;Ll;0;L;0075 0309;;;;N;;;1EE6;;1EE6 1EE8;LATIN CAPITAL LETTER U WITH HORN AND ACUTE;Lu;0;L;01AF 0301;;;;N;;;;1EE9; 1EE9;LATIN SMALL LETTER U WITH HORN AND ACUTE;Ll;0;L;01B0 0301;;;;N;;;1EE8;;1EE8 1EEA;LATIN CAPITAL LETTER U WITH HORN AND GRAVE;Lu;0;L;01AF 0300;;;;N;;;;1EEB; 1EEB;LATIN SMALL LETTER U WITH HORN AND GRAVE;Ll;0;L;01B0 0300;;;;N;;;1EEA;;1EEA 1EEC;LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE;Lu;0;L;01AF 0309;;;;N;;;;1EED; 1EED;LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE;Ll;0;L;01B0 0309;;;;N;;;1EEC;;1EEC 1EEE;LATIN CAPITAL LETTER U WITH HORN AND TILDE;Lu;0;L;01AF 0303;;;;N;;;;1EEF; 1EEF;LATIN SMALL LETTER U WITH HORN AND TILDE;Ll;0;L;01B0 0303;;;;N;;;1EEE;;1EEE 1EF0;LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW;Lu;0;L;01AF 0323;;;;N;;;;1EF1; 1EF1;LATIN SMALL LETTER U WITH HORN AND DOT BELOW;Ll;0;L;01B0 0323;;;;N;;;1EF0;;1EF0 1EF2;LATIN CAPITAL LETTER Y WITH GRAVE;Lu;0;L;0059 0300;;;;N;;;;1EF3; 1EF3;LATIN SMALL LETTER Y WITH GRAVE;Ll;0;L;0079 0300;;;;N;;;1EF2;;1EF2 1EF4;LATIN CAPITAL LETTER Y WITH DOT BELOW;Lu;0;L;0059 0323;;;;N;;;;1EF5; 1EF5;LATIN SMALL LETTER Y WITH DOT BELOW;Ll;0;L;0079 0323;;;;N;;;1EF4;;1EF4 1EF6;LATIN CAPITAL LETTER Y WITH HOOK ABOVE;Lu;0;L;0059 0309;;;;N;;;;1EF7; 1EF7;LATIN SMALL LETTER Y WITH HOOK ABOVE;Ll;0;L;0079 0309;;;;N;;;1EF6;;1EF6 1EF8;LATIN CAPITAL LETTER Y WITH TILDE;Lu;0;L;0059 0303;;;;N;;;;1EF9; 1EF9;LATIN SMALL LETTER Y WITH TILDE;Ll;0;L;0079 0303;;;;N;;;1EF8;;1EF8 1F00;GREEK SMALL LETTER ALPHA WITH PSILI;Ll;0;L;03B1 0313;;;;N;;;1F08;;1F08 1F01;GREEK SMALL LETTER ALPHA WITH DASIA;Ll;0;L;03B1 0314;;;;N;;;1F09;;1F09 1F02;GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA;Ll;0;L;1F00 0300;;;;N;;;1F0A;;1F0A 1F03;GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA;Ll;0;L;1F01 0300;;;;N;;;1F0B;;1F0B 1F04;GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA;Ll;0;L;1F00 0301;;;;N;;;1F0C;;1F0C 1F05;GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA;Ll;0;L;1F01 0301;;;;N;;;1F0D;;1F0D 1F06;GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI;Ll;0;L;1F00 0342;;;;N;;;1F0E;;1F0E 1F07;GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI;Ll;0;L;1F01 0342;;;;N;;;1F0F;;1F0F 1F08;GREEK CAPITAL LETTER ALPHA WITH PSILI;Lu;0;L;0391 0313;;;;N;;;;1F00; 1F09;GREEK CAPITAL LETTER ALPHA WITH DASIA;Lu;0;L;0391 0314;;;;N;;;;1F01; 1F0A;GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA;Lu;0;L;1F08 0300;;;;N;;;;1F02; 1F0B;GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA;Lu;0;L;1F09 0300;;;;N;;;;1F03; 1F0C;GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA;Lu;0;L;1F08 0301;;;;N;;;;1F04; 1F0D;GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA;Lu;0;L;1F09 0301;;;;N;;;;1F05; 1F0E;GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI;Lu;0;L;1F08 0342;;;;N;;;;1F06; 1F0F;GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI;Lu;0;L;1F09 0342;;;;N;;;;1F07; 1F10;GREEK SMALL LETTER EPSILON WITH PSILI;Ll;0;L;03B5 0313;;;;N;;;1F18;;1F18 1F11;GREEK SMALL LETTER EPSILON WITH DASIA;Ll;0;L;03B5 0314;;;;N;;;1F19;;1F19 1F12;GREEK SMALL LETTER EPSILON WITH PSILI AND VARIA;Ll;0;L;1F10 0300;;;;N;;;1F1A;;1F1A 1F13;GREEK SMALL LETTER EPSILON WITH DASIA AND VARIA;Ll;0;L;1F11 0300;;;;N;;;1F1B;;1F1B 1F14;GREEK SMALL LETTER EPSILON WITH PSILI AND OXIA;Ll;0;L;1F10 0301;;;;N;;;1F1C;;1F1C 1F15;GREEK SMALL LETTER EPSILON WITH DASIA AND OXIA;Ll;0;L;1F11 0301;;;;N;;;1F1D;;1F1D 1F18;GREEK CAPITAL LETTER EPSILON WITH PSILI;Lu;0;L;0395 0313;;;;N;;;;1F10; 1F19;GREEK CAPITAL LETTER EPSILON WITH DASIA;Lu;0;L;0395 0314;;;;N;;;;1F11; 1F1A;GREEK CAPITAL LETTER EPSILON WITH PSILI AND VARIA;Lu;0;L;1F18 0300;;;;N;;;;1F12; 1F1B;GREEK CAPITAL LETTER EPSILON WITH DASIA AND VARIA;Lu;0;L;1F19 0300;;;;N;;;;1F13; 1F1C;GREEK CAPITAL LETTER EPSILON WITH PSILI AND OXIA;Lu;0;L;1F18 0301;;;;N;;;;1F14; 1F1D;GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA;Lu;0;L;1F19 0301;;;;N;;;;1F15; 1F20;GREEK SMALL LETTER ETA WITH PSILI;Ll;0;L;03B7 0313;;;;N;;;1F28;;1F28 1F21;GREEK SMALL LETTER ETA WITH DASIA;Ll;0;L;03B7 0314;;;;N;;;1F29;;1F29 1F22;GREEK SMALL LETTER ETA WITH PSILI AND VARIA;Ll;0;L;1F20 0300;;;;N;;;1F2A;;1F2A 1F23;GREEK SMALL LETTER ETA WITH DASIA AND VARIA;Ll;0;L;1F21 0300;;;;N;;;1F2B;;1F2B 1F24;GREEK SMALL LETTER ETA WITH PSILI AND OXIA;Ll;0;L;1F20 0301;;;;N;;;1F2C;;1F2C 1F25;GREEK SMALL LETTER ETA WITH DASIA AND OXIA;Ll;0;L;1F21 0301;;;;N;;;1F2D;;1F2D 1F26;GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI;Ll;0;L;1F20 0342;;;;N;;;1F2E;;1F2E 1F27;GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI;Ll;0;L;1F21 0342;;;;N;;;1F2F;;1F2F 1F28;GREEK CAPITAL LETTER ETA WITH PSILI;Lu;0;L;0397 0313;;;;N;;;;1F20; 1F29;GREEK CAPITAL LETTER ETA WITH DASIA;Lu;0;L;0397 0314;;;;N;;;;1F21; 1F2A;GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA;Lu;0;L;1F28 0300;;;;N;;;;1F22; 1F2B;GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA;Lu;0;L;1F29 0300;;;;N;;;;1F23; 1F2C;GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA;Lu;0;L;1F28 0301;;;;N;;;;1F24; 1F2D;GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA;Lu;0;L;1F29 0301;;;;N;;;;1F25; 1F2E;GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI;Lu;0;L;1F28 0342;;;;N;;;;1F26; 1F2F;GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI;Lu;0;L;1F29 0342;;;;N;;;;1F27; 1F30;GREEK SMALL LETTER IOTA WITH PSILI;Ll;0;L;03B9 0313;;;;N;;;1F38;;1F38 1F31;GREEK SMALL LETTER IOTA WITH DASIA;Ll;0;L;03B9 0314;;;;N;;;1F39;;1F39 1F32;GREEK SMALL LETTER IOTA WITH PSILI AND VARIA;Ll;0;L;1F30 0300;;;;N;;;1F3A;;1F3A 1F33;GREEK SMALL LETTER IOTA WITH DASIA AND VARIA;Ll;0;L;1F31 0300;;;;N;;;1F3B;;1F3B 1F34;GREEK SMALL LETTER IOTA WITH PSILI AND OXIA;Ll;0;L;1F30 0301;;;;N;;;1F3C;;1F3C 1F35;GREEK SMALL LETTER IOTA WITH DASIA AND OXIA;Ll;0;L;1F31 0301;;;;N;;;1F3D;;1F3D 1F36;GREEK SMALL LETTER IOTA WITH PSILI AND PERISPOMENI;Ll;0;L;1F30 0342;;;;N;;;1F3E;;1F3E 1F37;GREEK SMALL LETTER IOTA WITH DASIA AND PERISPOMENI;Ll;0;L;1F31 0342;;;;N;;;1F3F;;1F3F 1F38;GREEK CAPITAL LETTER IOTA WITH PSILI;Lu;0;L;0399 0313;;;;N;;;;1F30; 1F39;GREEK CAPITAL LETTER IOTA WITH DASIA;Lu;0;L;0399 0314;;;;N;;;;1F31; 1F3A;GREEK CAPITAL LETTER IOTA WITH PSILI AND VARIA;Lu;0;L;1F38 0300;;;;N;;;;1F32; 1F3B;GREEK CAPITAL LETTER IOTA WITH DASIA AND VARIA;Lu;0;L;1F39 0300;;;;N;;;;1F33; 1F3C;GREEK CAPITAL LETTER IOTA WITH PSILI AND OXIA;Lu;0;L;1F38 0301;;;;N;;;;1F34; 1F3D;GREEK CAPITAL LETTER IOTA WITH DASIA AND OXIA;Lu;0;L;1F39 0301;;;;N;;;;1F35; 1F3E;GREEK CAPITAL LETTER IOTA WITH PSILI AND PERISPOMENI;Lu;0;L;1F38 0342;;;;N;;;;1F36; 1F3F;GREEK CAPITAL LETTER IOTA WITH DASIA AND PERISPOMENI;Lu;0;L;1F39 0342;;;;N;;;;1F37; 1F40;GREEK SMALL LETTER OMICRON WITH PSILI;Ll;0;L;03BF 0313;;;;N;;;1F48;;1F48 1F41;GREEK SMALL LETTER OMICRON WITH DASIA;Ll;0;L;03BF 0314;;;;N;;;1F49;;1F49 1F42;GREEK SMALL LETTER OMICRON WITH PSILI AND VARIA;Ll;0;L;1F40 0300;;;;N;;;1F4A;;1F4A 1F43;GREEK SMALL LETTER OMICRON WITH DASIA AND VARIA;Ll;0;L;1F41 0300;;;;N;;;1F4B;;1F4B 1F44;GREEK SMALL LETTER OMICRON WITH PSILI AND OXIA;Ll;0;L;1F40 0301;;;;N;;;1F4C;;1F4C 1F45;GREEK SMALL LETTER OMICRON WITH DASIA AND OXIA;Ll;0;L;1F41 0301;;;;N;;;1F4D;;1F4D 1F48;GREEK CAPITAL LETTER OMICRON WITH PSILI;Lu;0;L;039F 0313;;;;N;;;;1F40; 1F49;GREEK CAPITAL LETTER OMICRON WITH DASIA;Lu;0;L;039F 0314;;;;N;;;;1F41; 1F4A;GREEK CAPITAL LETTER OMICRON WITH PSILI AND VARIA;Lu;0;L;1F48 0300;;;;N;;;;1F42; 1F4B;GREEK CAPITAL LETTER OMICRON WITH DASIA AND VARIA;Lu;0;L;1F49 0300;;;;N;;;;1F43; 1F4C;GREEK CAPITAL LETTER OMICRON WITH PSILI AND OXIA;Lu;0;L;1F48 0301;;;;N;;;;1F44; 1F4D;GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA;Lu;0;L;1F49 0301;;;;N;;;;1F45; 1F50;GREEK SMALL LETTER UPSILON WITH PSILI;Ll;0;L;03C5 0313;;;;N;;;;; 1F51;GREEK SMALL LETTER UPSILON WITH DASIA;Ll;0;L;03C5 0314;;;;N;;;1F59;;1F59 1F52;GREEK SMALL LETTER UPSILON WITH PSILI AND VARIA;Ll;0;L;1F50 0300;;;;N;;;;; 1F53;GREEK SMALL LETTER UPSILON WITH DASIA AND VARIA;Ll;0;L;1F51 0300;;;;N;;;1F5B;;1F5B 1F54;GREEK SMALL LETTER UPSILON WITH PSILI AND OXIA;Ll;0;L;1F50 0301;;;;N;;;;; 1F55;GREEK SMALL LETTER UPSILON WITH DASIA AND OXIA;Ll;0;L;1F51 0301;;;;N;;;1F5D;;1F5D 1F56;GREEK SMALL LETTER UPSILON WITH PSILI AND PERISPOMENI;Ll;0;L;1F50 0342;;;;N;;;;; 1F57;GREEK SMALL LETTER UPSILON WITH DASIA AND PERISPOMENI;Ll;0;L;1F51 0342;;;;N;;;1F5F;;1F5F 1F59;GREEK CAPITAL LETTER UPSILON WITH DASIA;Lu;0;L;03A5 0314;;;;N;;;;1F51; 1F5B;GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA;Lu;0;L;1F59 0300;;;;N;;;;1F53; 1F5D;GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA;Lu;0;L;1F59 0301;;;;N;;;;1F55; 1F5F;GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI;Lu;0;L;1F59 0342;;;;N;;;;1F57; 1F60;GREEK SMALL LETTER OMEGA WITH PSILI;Ll;0;L;03C9 0313;;;;N;;;1F68;;1F68 1F61;GREEK SMALL LETTER OMEGA WITH DASIA;Ll;0;L;03C9 0314;;;;N;;;1F69;;1F69 1F62;GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA;Ll;0;L;1F60 0300;;;;N;;;1F6A;;1F6A 1F63;GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA;Ll;0;L;1F61 0300;;;;N;;;1F6B;;1F6B 1F64;GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA;Ll;0;L;1F60 0301;;;;N;;;1F6C;;1F6C 1F65;GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA;Ll;0;L;1F61 0301;;;;N;;;1F6D;;1F6D 1F66;GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI;Ll;0;L;1F60 0342;;;;N;;;1F6E;;1F6E 1F67;GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI;Ll;0;L;1F61 0342;;;;N;;;1F6F;;1F6F 1F68;GREEK CAPITAL LETTER OMEGA WITH PSILI;Lu;0;L;03A9 0313;;;;N;;;;1F60; 1F69;GREEK CAPITAL LETTER OMEGA WITH DASIA;Lu;0;L;03A9 0314;;;;N;;;;1F61; 1F6A;GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA;Lu;0;L;1F68 0300;;;;N;;;;1F62; 1F6B;GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA;Lu;0;L;1F69 0300;;;;N;;;;1F63; 1F6C;GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA;Lu;0;L;1F68 0301;;;;N;;;;1F64; 1F6D;GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA;Lu;0;L;1F69 0301;;;;N;;;;1F65; 1F6E;GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI;Lu;0;L;1F68 0342;;;;N;;;;1F66; 1F6F;GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI;Lu;0;L;1F69 0342;;;;N;;;;1F67; 1F70;GREEK SMALL LETTER ALPHA WITH VARIA;Ll;0;L;03B1 0300;;;;N;;;1FBA;;1FBA 1F71;GREEK SMALL LETTER ALPHA WITH OXIA;Ll;0;L;03AC;;;;N;;;1FBB;;1FBB 1F72;GREEK SMALL LETTER EPSILON WITH VARIA;Ll;0;L;03B5 0300;;;;N;;;1FC8;;1FC8 1F73;GREEK SMALL LETTER EPSILON WITH OXIA;Ll;0;L;03AD;;;;N;;;1FC9;;1FC9 1F74;GREEK SMALL LETTER ETA WITH VARIA;Ll;0;L;03B7 0300;;;;N;;;1FCA;;1FCA 1F75;GREEK SMALL LETTER ETA WITH OXIA;Ll;0;L;03AE;;;;N;;;1FCB;;1FCB 1F76;GREEK SMALL LETTER IOTA WITH VARIA;Ll;0;L;03B9 0300;;;;N;;;1FDA;;1FDA 1F77;GREEK SMALL LETTER IOTA WITH OXIA;Ll;0;L;03AF;;;;N;;;1FDB;;1FDB 1F78;GREEK SMALL LETTER OMICRON WITH VARIA;Ll;0;L;03BF 0300;;;;N;;;1FF8;;1FF8 1F79;GREEK SMALL LETTER OMICRON WITH OXIA;Ll;0;L;03CC;;;;N;;;1FF9;;1FF9 1F7A;GREEK SMALL LETTER UPSILON WITH VARIA;Ll;0;L;03C5 0300;;;;N;;;1FEA;;1FEA 1F7B;GREEK SMALL LETTER UPSILON WITH OXIA;Ll;0;L;03CD;;;;N;;;1FEB;;1FEB 1F7C;GREEK SMALL LETTER OMEGA WITH VARIA;Ll;0;L;03C9 0300;;;;N;;;1FFA;;1FFA 1F7D;GREEK SMALL LETTER OMEGA WITH OXIA;Ll;0;L;03CE;;;;N;;;1FFB;;1FFB 1F80;GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI;Ll;0;L;1F00 0345;;;;N;;;1F88;;1F88 1F81;GREEK SMALL LETTER ALPHA WITH DASIA AND YPOGEGRAMMENI;Ll;0;L;1F01 0345;;;;N;;;1F89;;1F89 1F82;GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA AND YPOGEGRAMMENI;Ll;0;L;1F02 0345;;;;N;;;1F8A;;1F8A 1F83;GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA AND YPOGEGRAMMENI;Ll;0;L;1F03 0345;;;;N;;;1F8B;;1F8B 1F84;GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI;Ll;0;L;1F04 0345;;;;N;;;1F8C;;1F8C 1F85;GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI;Ll;0;L;1F05 0345;;;;N;;;1F8D;;1F8D 1F86;GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1F06 0345;;;;N;;;1F8E;;1F8E 1F87;GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1F07 0345;;;;N;;;1F8F;;1F8F 1F88;GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI;Lt;0;L;1F08 0345;;;;N;;;;1F80; 1F89;GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI;Lt;0;L;1F09 0345;;;;N;;;;1F81; 1F8A;GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI;Lt;0;L;1F0A 0345;;;;N;;;;1F82; 1F8B;GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI;Lt;0;L;1F0B 0345;;;;N;;;;1F83; 1F8C;GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI;Lt;0;L;1F0C 0345;;;;N;;;;1F84; 1F8D;GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI;Lt;0;L;1F0D 0345;;;;N;;;;1F85; 1F8E;GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI;Lt;0;L;1F0E 0345;;;;N;;;;1F86; 1F8F;GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI;Lt;0;L;1F0F 0345;;;;N;;;;1F87; 1F90;GREEK SMALL LETTER ETA WITH PSILI AND YPOGEGRAMMENI;Ll;0;L;1F20 0345;;;;N;;;1F98;;1F98 1F91;GREEK SMALL LETTER ETA WITH DASIA AND YPOGEGRAMMENI;Ll;0;L;1F21 0345;;;;N;;;1F99;;1F99 1F92;GREEK SMALL LETTER ETA WITH PSILI AND VARIA AND YPOGEGRAMMENI;Ll;0;L;1F22 0345;;;;N;;;1F9A;;1F9A 1F93;GREEK SMALL LETTER ETA WITH DASIA AND VARIA AND YPOGEGRAMMENI;Ll;0;L;1F23 0345;;;;N;;;1F9B;;1F9B 1F94;GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI;Ll;0;L;1F24 0345;;;;N;;;1F9C;;1F9C 1F95;GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI;Ll;0;L;1F25 0345;;;;N;;;1F9D;;1F9D 1F96;GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1F26 0345;;;;N;;;1F9E;;1F9E 1F97;GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1F27 0345;;;;N;;;1F9F;;1F9F 1F98;GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI;Lt;0;L;1F28 0345;;;;N;;;;1F90; 1F99;GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI;Lt;0;L;1F29 0345;;;;N;;;;1F91; 1F9A;GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI;Lt;0;L;1F2A 0345;;;;N;;;;1F92; 1F9B;GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI;Lt;0;L;1F2B 0345;;;;N;;;;1F93; 1F9C;GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI;Lt;0;L;1F2C 0345;;;;N;;;;1F94; 1F9D;GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI;Lt;0;L;1F2D 0345;;;;N;;;;1F95; 1F9E;GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI;Lt;0;L;1F2E 0345;;;;N;;;;1F96; 1F9F;GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI;Lt;0;L;1F2F 0345;;;;N;;;;1F97; 1FA0;GREEK SMALL LETTER OMEGA WITH PSILI AND YPOGEGRAMMENI;Ll;0;L;1F60 0345;;;;N;;;1FA8;;1FA8 1FA1;GREEK SMALL LETTER OMEGA WITH DASIA AND YPOGEGRAMMENI;Ll;0;L;1F61 0345;;;;N;;;1FA9;;1FA9 1FA2;GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA AND YPOGEGRAMMENI;Ll;0;L;1F62 0345;;;;N;;;1FAA;;1FAA 1FA3;GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA AND YPOGEGRAMMENI;Ll;0;L;1F63 0345;;;;N;;;1FAB;;1FAB 1FA4;GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI;Ll;0;L;1F64 0345;;;;N;;;1FAC;;1FAC 1FA5;GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI;Ll;0;L;1F65 0345;;;;N;;;1FAD;;1FAD 1FA6;GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1F66 0345;;;;N;;;1FAE;;1FAE 1FA7;GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1F67 0345;;;;N;;;1FAF;;1FAF 1FA8;GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI;Lt;0;L;1F68 0345;;;;N;;;;1FA0; 1FA9;GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI;Lt;0;L;1F69 0345;;;;N;;;;1FA1; 1FAA;GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI;Lt;0;L;1F6A 0345;;;;N;;;;1FA2; 1FAB;GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI;Lt;0;L;1F6B 0345;;;;N;;;;1FA3; 1FAC;GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI;Lt;0;L;1F6C 0345;;;;N;;;;1FA4; 1FAD;GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI;Lt;0;L;1F6D 0345;;;;N;;;;1FA5; 1FAE;GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI;Lt;0;L;1F6E 0345;;;;N;;;;1FA6; 1FAF;GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI;Lt;0;L;1F6F 0345;;;;N;;;;1FA7; 1FB0;GREEK SMALL LETTER ALPHA WITH VRACHY;Ll;0;L;03B1 0306;;;;N;;;1FB8;;1FB8 1FB1;GREEK SMALL LETTER ALPHA WITH MACRON;Ll;0;L;03B1 0304;;;;N;;;1FB9;;1FB9 1FB2;GREEK SMALL LETTER ALPHA WITH VARIA AND YPOGEGRAMMENI;Ll;0;L;1F70 0345;;;;N;;;;; 1FB3;GREEK SMALL LETTER ALPHA WITH YPOGEGRAMMENI;Ll;0;L;03B1 0345;;;;N;;;1FBC;;1FBC 1FB4;GREEK SMALL LETTER ALPHA WITH OXIA AND YPOGEGRAMMENI;Ll;0;L;03AC 0345;;;;N;;;;; 1FB6;GREEK SMALL LETTER ALPHA WITH PERISPOMENI;Ll;0;L;03B1 0342;;;;N;;;;; 1FB7;GREEK SMALL LETTER ALPHA WITH PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1FB6 0345;;;;N;;;;; 1FB8;GREEK CAPITAL LETTER ALPHA WITH VRACHY;Lu;0;L;0391 0306;;;;N;;;;1FB0; 1FB9;GREEK CAPITAL LETTER ALPHA WITH MACRON;Lu;0;L;0391 0304;;;;N;;;;1FB1; 1FBA;GREEK CAPITAL LETTER ALPHA WITH VARIA;Lu;0;L;0391 0300;;;;N;;;;1F70; 1FBB;GREEK CAPITAL LETTER ALPHA WITH OXIA;Lu;0;L;0386;;;;N;;;;1F71; 1FBC;GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI;Lt;0;L;0391 0345;;;;N;;;;1FB3; 1FBD;GREEK KORONIS;Sk;0;ON; 0020 0313;;;;N;;;;; 1FBE;GREEK PROSGEGRAMMENI;Ll;0;L;03B9;;;;N;;;0399;;0399 1FBF;GREEK PSILI;Sk;0;ON; 0020 0313;;;;N;;;;; 1FC0;GREEK PERISPOMENI;Sk;0;ON; 0020 0342;;;;N;;;;; 1FC1;GREEK DIALYTIKA AND PERISPOMENI;Sk;0;ON;00A8 0342;;;;N;;;;; 1FC2;GREEK SMALL LETTER ETA WITH VARIA AND YPOGEGRAMMENI;Ll;0;L;1F74 0345;;;;N;;;;; 1FC3;GREEK SMALL LETTER ETA WITH YPOGEGRAMMENI;Ll;0;L;03B7 0345;;;;N;;;1FCC;;1FCC 1FC4;GREEK SMALL LETTER ETA WITH OXIA AND YPOGEGRAMMENI;Ll;0;L;03AE 0345;;;;N;;;;; 1FC6;GREEK SMALL LETTER ETA WITH PERISPOMENI;Ll;0;L;03B7 0342;;;;N;;;;; 1FC7;GREEK SMALL LETTER ETA WITH PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1FC6 0345;;;;N;;;;; 1FC8;GREEK CAPITAL LETTER EPSILON WITH VARIA;Lu;0;L;0395 0300;;;;N;;;;1F72; 1FC9;GREEK CAPITAL LETTER EPSILON WITH OXIA;Lu;0;L;0388;;;;N;;;;1F73; 1FCA;GREEK CAPITAL LETTER ETA WITH VARIA;Lu;0;L;0397 0300;;;;N;;;;1F74; 1FCB;GREEK CAPITAL LETTER ETA WITH OXIA;Lu;0;L;0389;;;;N;;;;1F75; 1FCC;GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI;Lt;0;L;0397 0345;;;;N;;;;1FC3; 1FCD;GREEK PSILI AND VARIA;Sk;0;ON;1FBF 0300;;;;N;;;;; 1FCE;GREEK PSILI AND OXIA;Sk;0;ON;1FBF 0301;;;;N;;;;; 1FCF;GREEK PSILI AND PERISPOMENI;Sk;0;ON;1FBF 0342;;;;N;;;;; 1FD0;GREEK SMALL LETTER IOTA WITH VRACHY;Ll;0;L;03B9 0306;;;;N;;;1FD8;;1FD8 1FD1;GREEK SMALL LETTER IOTA WITH MACRON;Ll;0;L;03B9 0304;;;;N;;;1FD9;;1FD9 1FD2;GREEK SMALL LETTER IOTA WITH DIALYTIKA AND VARIA;Ll;0;L;03CA 0300;;;;N;;;;; 1FD3;GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA;Ll;0;L;0390;;;;N;;;;; 1FD6;GREEK SMALL LETTER IOTA WITH PERISPOMENI;Ll;0;L;03B9 0342;;;;N;;;;; 1FD7;GREEK SMALL LETTER IOTA WITH DIALYTIKA AND PERISPOMENI;Ll;0;L;03CA 0342;;;;N;;;;; 1FD8;GREEK CAPITAL LETTER IOTA WITH VRACHY;Lu;0;L;0399 0306;;;;N;;;;1FD0; 1FD9;GREEK CAPITAL LETTER IOTA WITH MACRON;Lu;0;L;0399 0304;;;;N;;;;1FD1; 1FDA;GREEK CAPITAL LETTER IOTA WITH VARIA;Lu;0;L;0399 0300;;;;N;;;;1F76; 1FDB;GREEK CAPITAL LETTER IOTA WITH OXIA;Lu;0;L;038A;;;;N;;;;1F77; 1FDD;GREEK DASIA AND VARIA;Sk;0;ON;1FFE 0300;;;;N;;;;; 1FDE;GREEK DASIA AND OXIA;Sk;0;ON;1FFE 0301;;;;N;;;;; 1FDF;GREEK DASIA AND PERISPOMENI;Sk;0;ON;1FFE 0342;;;;N;;;;; 1FE0;GREEK SMALL LETTER UPSILON WITH VRACHY;Ll;0;L;03C5 0306;;;;N;;;1FE8;;1FE8 1FE1;GREEK SMALL LETTER UPSILON WITH MACRON;Ll;0;L;03C5 0304;;;;N;;;1FE9;;1FE9 1FE2;GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND VARIA;Ll;0;L;03CB 0300;;;;N;;;;; 1FE3;GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND OXIA;Ll;0;L;03B0;;;;N;;;;; 1FE4;GREEK SMALL LETTER RHO WITH PSILI;Ll;0;L;03C1 0313;;;;N;;;;; 1FE5;GREEK SMALL LETTER RHO WITH DASIA;Ll;0;L;03C1 0314;;;;N;;;1FEC;;1FEC 1FE6;GREEK SMALL LETTER UPSILON WITH PERISPOMENI;Ll;0;L;03C5 0342;;;;N;;;;; 1FE7;GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND PERISPOMENI;Ll;0;L;03CB 0342;;;;N;;;;; 1FE8;GREEK CAPITAL LETTER UPSILON WITH VRACHY;Lu;0;L;03A5 0306;;;;N;;;;1FE0; 1FE9;GREEK CAPITAL LETTER UPSILON WITH MACRON;Lu;0;L;03A5 0304;;;;N;;;;1FE1; 1FEA;GREEK CAPITAL LETTER UPSILON WITH VARIA;Lu;0;L;03A5 0300;;;;N;;;;1F7A; 1FEB;GREEK CAPITAL LETTER UPSILON WITH OXIA;Lu;0;L;038E;;;;N;;;;1F7B; 1FEC;GREEK CAPITAL LETTER RHO WITH DASIA;Lu;0;L;03A1 0314;;;;N;;;;1FE5; 1FED;GREEK DIALYTIKA AND VARIA;Sk;0;ON;00A8 0300;;;;N;;;;; 1FEE;GREEK DIALYTIKA AND OXIA;Sk;0;ON;0385;;;;N;;;;; 1FEF;GREEK VARIA;Sk;0;ON;0060;;;;N;;;;; 1FF2;GREEK SMALL LETTER OMEGA WITH VARIA AND YPOGEGRAMMENI;Ll;0;L;1F7C 0345;;;;N;;;;; 1FF3;GREEK SMALL LETTER OMEGA WITH YPOGEGRAMMENI;Ll;0;L;03C9 0345;;;;N;;;1FFC;;1FFC 1FF4;GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI;Ll;0;L;03CE 0345;;;;N;;;;; 1FF6;GREEK SMALL LETTER OMEGA WITH PERISPOMENI;Ll;0;L;03C9 0342;;;;N;;;;; 1FF7;GREEK SMALL LETTER OMEGA WITH PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1FF6 0345;;;;N;;;;; 1FF8;GREEK CAPITAL LETTER OMICRON WITH VARIA;Lu;0;L;039F 0300;;;;N;;;;1F78; 1FF9;GREEK CAPITAL LETTER OMICRON WITH OXIA;Lu;0;L;038C;;;;N;;;;1F79; 1FFA;GREEK CAPITAL LETTER OMEGA WITH VARIA;Lu;0;L;03A9 0300;;;;N;;;;1F7C; 1FFB;GREEK CAPITAL LETTER OMEGA WITH OXIA;Lu;0;L;038F;;;;N;;;;1F7D; 1FFC;GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI;Lt;0;L;03A9 0345;;;;N;;;;1FF3; 1FFD;GREEK OXIA;Sk;0;ON;00B4;;;;N;;;;; 1FFE;GREEK DASIA;Sk;0;ON; 0020 0314;;;;N;;;;; 2000;EN QUAD;Zs;0;WS;2002;;;;N;;;;; 2001;EM QUAD;Zs;0;WS;2003;;;;N;;;;; 2002;EN SPACE;Zs;0;WS; 0020;;;;N;;;;; 2003;EM SPACE;Zs;0;WS; 0020;;;;N;;;;; 2004;THREE-PER-EM SPACE;Zs;0;WS; 0020;;;;N;;;;; 2005;FOUR-PER-EM SPACE;Zs;0;WS; 0020;;;;N;;;;; 2006;SIX-PER-EM SPACE;Zs;0;WS; 0020;;;;N;;;;; 2007;FIGURE SPACE;Zs;0;WS; 0020;;;;N;;;;; 2008;PUNCTUATION SPACE;Zs;0;WS; 0020;;;;N;;;;; 2009;THIN SPACE;Zs;0;WS; 0020;;;;N;;;;; 200A;HAIR SPACE;Zs;0;WS; 0020;;;;N;;;;; 200B;ZERO WIDTH SPACE;Zs;0;BN;;;;;N;;;;; 200C;ZERO WIDTH NON-JOINER;Cf;0;BN;;;;;N;;;;; 200D;ZERO WIDTH JOINER;Cf;0;BN;;;;;N;;;;; 200E;LEFT-TO-RIGHT MARK;Cf;0;L;;;;;N;;;;; 200F;RIGHT-TO-LEFT MARK;Cf;0;R;;;;;N;;;;; 2010;HYPHEN;Pd;0;ON;;;;;N;;;;; 2011;NON-BREAKING HYPHEN;Pd;0;ON; 2010;;;;N;;;;; 2012;FIGURE DASH;Pd;0;ON;;;;;N;;;;; 2013;EN DASH;Pd;0;ON;;;;;N;;;;; 2014;EM DASH;Pd;0;ON;;;;;N;;;;; 2015;HORIZONTAL BAR;Pd;0;ON;;;;;N;QUOTATION DASH;;;; 2016;DOUBLE VERTICAL LINE;Po;0;ON;;;;;N;DOUBLE VERTICAL BAR;;;; 2017;DOUBLE LOW LINE;Po;0;ON; 0020 0333;;;;N;SPACING DOUBLE UNDERSCORE;;;; 2018;LEFT SINGLE QUOTATION MARK;Pi;0;ON;;;;;N;SINGLE TURNED COMMA QUOTATION MARK;;;; 2019;RIGHT SINGLE QUOTATION MARK;Pf;0;ON;;;;;N;SINGLE COMMA QUOTATION MARK;;;; 201A;SINGLE LOW-9 QUOTATION MARK;Ps;0;ON;;;;;N;LOW SINGLE COMMA QUOTATION MARK;;;; 201B;SINGLE HIGH-REVERSED-9 QUOTATION MARK;Pi;0;ON;;;;;N;SINGLE REVERSED COMMA QUOTATION MARK;;;; 201C;LEFT DOUBLE QUOTATION MARK;Pi;0;ON;;;;;N;DOUBLE TURNED COMMA QUOTATION MARK;;;; 201D;RIGHT DOUBLE QUOTATION MARK;Pf;0;ON;;;;;N;DOUBLE COMMA QUOTATION MARK;;;; 201E;DOUBLE LOW-9 QUOTATION MARK;Ps;0;ON;;;;;N;LOW DOUBLE COMMA QUOTATION MARK;;;; 201F;DOUBLE HIGH-REVERSED-9 QUOTATION MARK;Pi;0;ON;;;;;N;DOUBLE REVERSED COMMA QUOTATION MARK;;;; 2020;DAGGER;Po;0;ON;;;;;N;;;;; 2021;DOUBLE DAGGER;Po;0;ON;;;;;N;;;;; 2022;BULLET;Po;0;ON;;;;;N;;;;; 2023;TRIANGULAR BULLET;Po;0;ON;;;;;N;;;;; 2024;ONE DOT LEADER;Po;0;ON; 002E;;;;N;;;;; 2025;TWO DOT LEADER;Po;0;ON; 002E 002E;;;;N;;;;; 2026;HORIZONTAL ELLIPSIS;Po;0;ON; 002E 002E 002E;;;;N;;;;; 2027;HYPHENATION POINT;Po;0;ON;;;;;N;;;;; 2028;LINE SEPARATOR;Zl;0;WS;;;;;N;;;;; 2029;PARAGRAPH SEPARATOR;Zp;0;B;;;;;N;;;;; 202A;LEFT-TO-RIGHT EMBEDDING;Cf;0;LRE;;;;;N;;;;; 202B;RIGHT-TO-LEFT EMBEDDING;Cf;0;RLE;;;;;N;;;;; 202C;POP DIRECTIONAL FORMATTING;Cf;0;PDF;;;;;N;;;;; 202D;LEFT-TO-RIGHT OVERRIDE;Cf;0;LRO;;;;;N;;;;; 202E;RIGHT-TO-LEFT OVERRIDE;Cf;0;RLO;;;;;N;;;;; 202F;NARROW NO-BREAK SPACE;Zs;0;WS; 0020;;;;N;;;;; 2030;PER MILLE SIGN;Po;0;ET;;;;;N;;;;; 2031;PER TEN THOUSAND SIGN;Po;0;ET;;;;;N;;;;; 2032;PRIME;Po;0;ET;;;;;N;;;;; 2033;DOUBLE PRIME;Po;0;ET; 2032 2032;;;;N;;;;; 2034;TRIPLE PRIME;Po;0;ET; 2032 2032 2032;;;;N;;;;; 2035;REVERSED PRIME;Po;0;ON;;;;;N;;;;; 2036;REVERSED DOUBLE PRIME;Po;0;ON; 2035 2035;;;;N;;;;; 2037;REVERSED TRIPLE PRIME;Po;0;ON; 2035 2035 2035;;;;N;;;;; 2038;CARET;Po;0;ON;;;;;N;;;;; 2039;SINGLE LEFT-POINTING ANGLE QUOTATION MARK;Pi;0;ON;;;;;Y;LEFT POINTING SINGLE GUILLEMET;;;; 203A;SINGLE RIGHT-POINTING ANGLE QUOTATION MARK;Pf;0;ON;;;;;Y;RIGHT POINTING SINGLE GUILLEMET;;;; 203B;REFERENCE MARK;Po;0;ON;;;;;N;;;;; 203C;DOUBLE EXCLAMATION MARK;Po;0;ON; 0021 0021;;;;N;;;;; 203D;INTERROBANG;Po;0;ON;;;;;N;;;;; 203E;OVERLINE;Po;0;ON; 0020 0305;;;;N;SPACING OVERSCORE;;;; 203F;UNDERTIE;Pc;0;ON;;;;;N;;Enotikon;;; 2040;CHARACTER TIE;Pc;0;ON;;;;;N;;;;; 2041;CARET INSERTION POINT;Po;0;ON;;;;;N;;;;; 2042;ASTERISM;Po;0;ON;;;;;N;;;;; 2043;HYPHEN BULLET;Po;0;ON;;;;;N;;;;; 2044;FRACTION SLASH;Sm;0;ON;;;;;N;;;;; 2045;LEFT SQUARE BRACKET WITH QUILL;Ps;0;ON;;;;;Y;;;;; 2046;RIGHT SQUARE BRACKET WITH QUILL;Pe;0;ON;;;;;Y;;;;; 2047;DOUBLE QUESTION MARK;Po;0;ON; 003F 003F;;;;N;;;;; 2048;QUESTION EXCLAMATION MARK;Po;0;ON; 003F 0021;;;;N;;;;; 2049;EXCLAMATION QUESTION MARK;Po;0;ON; 0021 003F;;;;N;;;;; 204A;TIRONIAN SIGN ET;Po;0;ON;;;;;N;;;;; 204B;REVERSED PILCROW SIGN;Po;0;ON;;;;;N;;;;; 204C;BLACK LEFTWARDS BULLET;Po;0;ON;;;;;N;;;;; 204D;BLACK RIGHTWARDS BULLET;Po;0;ON;;;;;N;;;;; 204E;LOW ASTERISK;Po;0;ON;;;;;N;;;;; 204F;REVERSED SEMICOLON;Po;0;ON;;;;;N;;;;; 2050;CLOSE UP;Po;0;ON;;;;;N;;;;; 2051;TWO ASTERISKS ALIGNED VERTICALLY;Po;0;ON;;;;;N;;;;; 2052;COMMERCIAL MINUS SIGN;Sm;0;ON;;;;;N;;;;; 2057;QUADRUPLE PRIME;Po;0;ON; 2032 2032 2032 2032;;;;N;;;;; 205F;MEDIUM MATHEMATICAL SPACE;Zs;0;WS; 0020;;;;N;;;;; 2060;WORD JOINER;Cf;0;BN;;;;;N;;;;; 2061;FUNCTION APPLICATION;Cf;0;BN;;;;;N;;;;; 2062;INVISIBLE TIMES;Cf;0;BN;;;;;N;;;;; 2063;INVISIBLE SEPARATOR;Cf;0;BN;;;;;N;;;;; 206A;INHIBIT SYMMETRIC SWAPPING;Cf;0;BN;;;;;N;;;;; 206B;ACTIVATE SYMMETRIC SWAPPING;Cf;0;BN;;;;;N;;;;; 206C;INHIBIT ARABIC FORM SHAPING;Cf;0;BN;;;;;N;;;;; 206D;ACTIVATE ARABIC FORM SHAPING;Cf;0;BN;;;;;N;;;;; 206E;NATIONAL DIGIT SHAPES;Cf;0;BN;;;;;N;;;;; 206F;NOMINAL DIGIT SHAPES;Cf;0;BN;;;;;N;;;;; 2070;SUPERSCRIPT ZERO;No;0;EN; 0030;0;0;0;N;SUPERSCRIPT DIGIT ZERO;;;; 2071;SUPERSCRIPT LATIN SMALL LETTER I;Ll;0;L; 0069;;;;N;;;;; 2074;SUPERSCRIPT FOUR;No;0;EN; 0034;4;4;4;N;SUPERSCRIPT DIGIT FOUR;;;; 2075;SUPERSCRIPT FIVE;No;0;EN; 0035;5;5;5;N;SUPERSCRIPT DIGIT FIVE;;;; 2076;SUPERSCRIPT SIX;No;0;EN; 0036;6;6;6;N;SUPERSCRIPT DIGIT SIX;;;; 2077;SUPERSCRIPT SEVEN;No;0;EN; 0037;7;7;7;N;SUPERSCRIPT DIGIT SEVEN;;;; 2078;SUPERSCRIPT EIGHT;No;0;EN; 0038;8;8;8;N;SUPERSCRIPT DIGIT EIGHT;;;; 2079;SUPERSCRIPT NINE;No;0;EN; 0039;9;9;9;N;SUPERSCRIPT DIGIT NINE;;;; 207A;SUPERSCRIPT PLUS SIGN;Sm;0;ET; 002B;;;;N;;;;; 207B;SUPERSCRIPT MINUS;Sm;0;ET; 2212;;;;N;SUPERSCRIPT HYPHEN-MINUS;;;; 207C;SUPERSCRIPT EQUALS SIGN;Sm;0;ON; 003D;;;;N;;;;; 207D;SUPERSCRIPT LEFT PARENTHESIS;Ps;0;ON; 0028;;;;Y;SUPERSCRIPT OPENING PARENTHESIS;;;; 207E;SUPERSCRIPT RIGHT PARENTHESIS;Pe;0;ON; 0029;;;;Y;SUPERSCRIPT CLOSING PARENTHESIS;;;; 207F;SUPERSCRIPT LATIN SMALL LETTER N;Ll;0;L; 006E;;;;N;;;;; 2080;SUBSCRIPT ZERO;No;0;EN; 0030;0;0;0;N;SUBSCRIPT DIGIT ZERO;;;; 2081;SUBSCRIPT ONE;No;0;EN; 0031;1;1;1;N;SUBSCRIPT DIGIT ONE;;;; 2082;SUBSCRIPT TWO;No;0;EN; 0032;2;2;2;N;SUBSCRIPT DIGIT TWO;;;; 2083;SUBSCRIPT THREE;No;0;EN; 0033;3;3;3;N;SUBSCRIPT DIGIT THREE;;;; 2084;SUBSCRIPT FOUR;No;0;EN; 0034;4;4;4;N;SUBSCRIPT DIGIT FOUR;;;; 2085;SUBSCRIPT FIVE;No;0;EN; 0035;5;5;5;N;SUBSCRIPT DIGIT FIVE;;;; 2086;SUBSCRIPT SIX;No;0;EN; 0036;6;6;6;N;SUBSCRIPT DIGIT SIX;;;; 2087;SUBSCRIPT SEVEN;No;0;EN; 0037;7;7;7;N;SUBSCRIPT DIGIT SEVEN;;;; 2088;SUBSCRIPT EIGHT;No;0;EN; 0038;8;8;8;N;SUBSCRIPT DIGIT EIGHT;;;; 2089;SUBSCRIPT NINE;No;0;EN; 0039;9;9;9;N;SUBSCRIPT DIGIT NINE;;;; 208A;SUBSCRIPT PLUS SIGN;Sm;0;ET; 002B;;;;N;;;;; 208B;SUBSCRIPT MINUS;Sm;0;ET; 2212;;;;N;SUBSCRIPT HYPHEN-MINUS;;;; 208C;SUBSCRIPT EQUALS SIGN;Sm;0;ON; 003D;;;;N;;;;; 208D;SUBSCRIPT LEFT PARENTHESIS;Ps;0;ON; 0028;;;;Y;SUBSCRIPT OPENING PARENTHESIS;;;; 208E;SUBSCRIPT RIGHT PARENTHESIS;Pe;0;ON; 0029;;;;Y;SUBSCRIPT CLOSING PARENTHESIS;;;; 20A0;EURO-CURRENCY SIGN;Sc;0;ET;;;;;N;;;;; 20A1;COLON SIGN;Sc;0;ET;;;;;N;;;;; 20A2;CRUZEIRO SIGN;Sc;0;ET;;;;;N;;;;; 20A3;FRENCH FRANC SIGN;Sc;0;ET;;;;;N;;;;; 20A4;LIRA SIGN;Sc;0;ET;;;;;N;;;;; 20A5;MILL SIGN;Sc;0;ET;;;;;N;;;;; 20A6;NAIRA SIGN;Sc;0;ET;;;;;N;;;;; 20A7;PESETA SIGN;Sc;0;ET;;;;;N;;;;; 20A8;RUPEE SIGN;Sc;0;ET; 0052 0073;;;;N;;;;; 20A9;WON SIGN;Sc;0;ET;;;;;N;;;;; 20AA;NEW SHEQEL SIGN;Sc;0;ET;;;;;N;;;;; 20AB;DONG SIGN;Sc;0;ET;;;;;N;;;;; 20AC;EURO SIGN;Sc;0;ET;;;;;N;;;;; 20AD;KIP SIGN;Sc;0;ET;;;;;N;;;;; 20AE;TUGRIK SIGN;Sc;0;ET;;;;;N;;;;; 20AF;DRACHMA SIGN;Sc;0;ET;;;;;N;;;;; 20B0;GERMAN PENNY SIGN;Sc;0;ET;;;;;N;;;;; 20B1;PESO SIGN;Sc;0;ET;;;;;N;;;;; 20D0;COMBINING LEFT HARPOON ABOVE;Mn;230;NSM;;;;;N;NON-SPACING LEFT HARPOON ABOVE;;;; 20D1;COMBINING RIGHT HARPOON ABOVE;Mn;230;NSM;;;;;N;NON-SPACING RIGHT HARPOON ABOVE;;;; 20D2;COMBINING LONG VERTICAL LINE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING LONG VERTICAL BAR OVERLAY;;;; 20D3;COMBINING SHORT VERTICAL LINE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING SHORT VERTICAL BAR OVERLAY;;;; 20D4;COMBINING ANTICLOCKWISE ARROW ABOVE;Mn;230;NSM;;;;;N;NON-SPACING ANTICLOCKWISE ARROW ABOVE;;;; 20D5;COMBINING CLOCKWISE ARROW ABOVE;Mn;230;NSM;;;;;N;NON-SPACING CLOCKWISE ARROW ABOVE;;;; 20D6;COMBINING LEFT ARROW ABOVE;Mn;230;NSM;;;;;N;NON-SPACING LEFT ARROW ABOVE;;;; 20D7;COMBINING RIGHT ARROW ABOVE;Mn;230;NSM;;;;;N;NON-SPACING RIGHT ARROW ABOVE;;;; 20D8;COMBINING RING OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING RING OVERLAY;;;; 20D9;COMBINING CLOCKWISE RING OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING CLOCKWISE RING OVERLAY;;;; 20DA;COMBINING ANTICLOCKWISE RING OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING ANTICLOCKWISE RING OVERLAY;;;; 20DB;COMBINING THREE DOTS ABOVE;Mn;230;NSM;;;;;N;NON-SPACING THREE DOTS ABOVE;;;; 20DC;COMBINING FOUR DOTS ABOVE;Mn;230;NSM;;;;;N;NON-SPACING FOUR DOTS ABOVE;;;; 20DD;COMBINING ENCLOSING CIRCLE;Me;0;NSM;;;;;N;ENCLOSING CIRCLE;;;; 20DE;COMBINING ENCLOSING SQUARE;Me;0;NSM;;;;;N;ENCLOSING SQUARE;;;; 20DF;COMBINING ENCLOSING DIAMOND;Me;0;NSM;;;;;N;ENCLOSING DIAMOND;;;; 20E0;COMBINING ENCLOSING CIRCLE BACKSLASH;Me;0;NSM;;;;;N;ENCLOSING CIRCLE SLASH;;;; 20E1;COMBINING LEFT RIGHT ARROW ABOVE;Mn;230;NSM;;;;;N;NON-SPACING LEFT RIGHT ARROW ABOVE;;;; 20E2;COMBINING ENCLOSING SCREEN;Me;0;NSM;;;;;N;;;;; 20E3;COMBINING ENCLOSING KEYCAP;Me;0;NSM;;;;;N;;;;; 20E4;COMBINING ENCLOSING UPWARD POINTING TRIANGLE;Me;0;NSM;;;;;N;;;;; 20E5;COMBINING REVERSE SOLIDUS OVERLAY;Mn;1;NSM;;;;;N;;;;; 20E6;COMBINING DOUBLE VERTICAL STROKE OVERLAY;Mn;1;NSM;;;;;N;;;;; 20E7;COMBINING ANNUITY SYMBOL;Mn;230;NSM;;;;;N;;;;; 20E8;COMBINING TRIPLE UNDERDOT;Mn;220;NSM;;;;;N;;;;; 20E9;COMBINING WIDE BRIDGE ABOVE;Mn;230;NSM;;;;;N;;;;; 20EA;COMBINING LEFTWARDS ARROW OVERLAY;Mn;1;NSM;;;;;N;;;;; 2100;ACCOUNT OF;So;0;ON; 0061 002F 0063;;;;N;;;;; 2101;ADDRESSED TO THE SUBJECT;So;0;ON; 0061 002F 0073;;;;N;;;;; 2102;DOUBLE-STRUCK CAPITAL C;Lu;0;L; 0043;;;;N;DOUBLE-STRUCK C;;;; 2103;DEGREE CELSIUS;So;0;ON; 00B0 0043;;;;N;DEGREES CENTIGRADE;;;; 2104;CENTRE LINE SYMBOL;So;0;ON;;;;;N;C L SYMBOL;;;; 2105;CARE OF;So;0;ON; 0063 002F 006F;;;;N;;;;; 2106;CADA UNA;So;0;ON; 0063 002F 0075;;;;N;;;;; 2107;EULER CONSTANT;Lu;0;L; 0190;;;;N;EULERS;;;; 2108;SCRUPLE;So;0;ON;;;;;N;;;;; 2109;DEGREE FAHRENHEIT;So;0;ON; 00B0 0046;;;;N;DEGREES FAHRENHEIT;;;; 210A;SCRIPT SMALL G;Ll;0;L; 0067;;;;N;;;;; 210B;SCRIPT CAPITAL H;Lu;0;L; 0048;;;;N;SCRIPT H;;;; 210C;BLACK-LETTER CAPITAL H;Lu;0;L; 0048;;;;N;BLACK-LETTER H;;;; 210D;DOUBLE-STRUCK CAPITAL H;Lu;0;L; 0048;;;;N;DOUBLE-STRUCK H;;;; 210E;PLANCK CONSTANT;Ll;0;L; 0068;;;;N;;;;; 210F;PLANCK CONSTANT OVER TWO PI;Ll;0;L; 0127;;;;N;PLANCK CONSTANT OVER 2 PI;;;; 2110;SCRIPT CAPITAL I;Lu;0;L; 0049;;;;N;SCRIPT I;;;; 2111;BLACK-LETTER CAPITAL I;Lu;0;L; 0049;;;;N;BLACK-LETTER I;;;; 2112;SCRIPT CAPITAL L;Lu;0;L; 004C;;;;N;SCRIPT L;;;; 2113;SCRIPT SMALL L;Ll;0;L; 006C;;;;N;;;;; 2114;L B BAR SYMBOL;So;0;ON;;;;;N;;;;; 2115;DOUBLE-STRUCK CAPITAL N;Lu;0;L; 004E;;;;N;DOUBLE-STRUCK N;;;; 2116;NUMERO SIGN;So;0;ON; 004E 006F;;;;N;NUMERO;;;; 2117;SOUND RECORDING COPYRIGHT;So;0;ON;;;;;N;;;;; 2118;SCRIPT CAPITAL P;So;0;ON;;;;;N;SCRIPT P;;;; 2119;DOUBLE-STRUCK CAPITAL P;Lu;0;L; 0050;;;;N;DOUBLE-STRUCK P;;;; 211A;DOUBLE-STRUCK CAPITAL Q;Lu;0;L; 0051;;;;N;DOUBLE-STRUCK Q;;;; 211B;SCRIPT CAPITAL R;Lu;0;L; 0052;;;;N;SCRIPT R;;;; 211C;BLACK-LETTER CAPITAL R;Lu;0;L; 0052;;;;N;BLACK-LETTER R;;;; 211D;DOUBLE-STRUCK CAPITAL R;Lu;0;L; 0052;;;;N;DOUBLE-STRUCK R;;;; 211E;PRESCRIPTION TAKE;So;0;ON;;;;;N;;;;; 211F;RESPONSE;So;0;ON;;;;;N;;;;; 2120;SERVICE MARK;So;0;ON; 0053 004D;;;;N;;;;; 2121;TELEPHONE SIGN;So;0;ON; 0054 0045 004C;;;;N;T E L SYMBOL;;;; 2122;TRADE MARK SIGN;So;0;ON; 0054 004D;;;;N;TRADEMARK;;;; 2123;VERSICLE;So;0;ON;;;;;N;;;;; 2124;DOUBLE-STRUCK CAPITAL Z;Lu;0;L; 005A;;;;N;DOUBLE-STRUCK Z;;;; 2125;OUNCE SIGN;So;0;ON;;;;;N;OUNCE;;;; 2126;OHM SIGN;Lu;0;L;03A9;;;;N;OHM;;;03C9; 2127;INVERTED OHM SIGN;So;0;ON;;;;;N;MHO;;;; 2128;BLACK-LETTER CAPITAL Z;Lu;0;L; 005A;;;;N;BLACK-LETTER Z;;;; 2129;TURNED GREEK SMALL LETTER IOTA;So;0;ON;;;;;N;;;;; 212A;KELVIN SIGN;Lu;0;L;004B;;;;N;DEGREES KELVIN;;;006B; 212B;ANGSTROM SIGN;Lu;0;L;00C5;;;;N;ANGSTROM UNIT;;;00E5; 212C;SCRIPT CAPITAL B;Lu;0;L; 0042;;;;N;SCRIPT B;;;; 212D;BLACK-LETTER CAPITAL C;Lu;0;L; 0043;;;;N;BLACK-LETTER C;;;; 212E;ESTIMATED SYMBOL;So;0;ET;;;;;N;;;;; 212F;SCRIPT SMALL E;Ll;0;L; 0065;;;;N;;;;; 2130;SCRIPT CAPITAL E;Lu;0;L; 0045;;;;N;SCRIPT E;;;; 2131;SCRIPT CAPITAL F;Lu;0;L; 0046;;;;N;SCRIPT F;;;; 2132;TURNED CAPITAL F;So;0;ON;;;;;N;TURNED F;;;; 2133;SCRIPT CAPITAL M;Lu;0;L; 004D;;;;N;SCRIPT M;;;; 2134;SCRIPT SMALL O;Ll;0;L; 006F;;;;N;;;;; 2135;ALEF SYMBOL;Lo;0;L; 05D0;;;;N;FIRST TRANSFINITE CARDINAL;;;; 2136;BET SYMBOL;Lo;0;L; 05D1;;;;N;SECOND TRANSFINITE CARDINAL;;;; 2137;GIMEL SYMBOL;Lo;0;L; 05D2;;;;N;THIRD TRANSFINITE CARDINAL;;;; 2138;DALET SYMBOL;Lo;0;L; 05D3;;;;N;FOURTH TRANSFINITE CARDINAL;;;; 2139;INFORMATION SOURCE;Ll;0;L; 0069;;;;N;;;;; 213A;ROTATED CAPITAL Q;So;0;ON;;;;;N;;;;; 213D;DOUBLE-STRUCK SMALL GAMMA;Ll;0;L; 03B3;;;;N;;;;; 213E;DOUBLE-STRUCK CAPITAL GAMMA;Lu;0;L; 0393;;;;N;;;;; 213F;DOUBLE-STRUCK CAPITAL PI;Lu;0;L; 03A0;;;;N;;;;; 2140;DOUBLE-STRUCK N-ARY SUMMATION;Sm;0;ON; 2211;;;;Y;;;;; 2141;TURNED SANS-SERIF CAPITAL G;Sm;0;ON;;;;;N;;;;; 2142;TURNED SANS-SERIF CAPITAL L;Sm;0;ON;;;;;N;;;;; 2143;REVERSED SANS-SERIF CAPITAL L;Sm;0;ON;;;;;N;;;;; 2144;TURNED SANS-SERIF CAPITAL Y;Sm;0;ON;;;;;N;;;;; 2145;DOUBLE-STRUCK ITALIC CAPITAL D;Lu;0;L; 0044;;;;N;;;;; 2146;DOUBLE-STRUCK ITALIC SMALL D;Ll;0;L; 0064;;;;N;;;;; 2147;DOUBLE-STRUCK ITALIC SMALL E;Ll;0;L; 0065;;;;N;;;;; 2148;DOUBLE-STRUCK ITALIC SMALL I;Ll;0;L; 0069;;;;N;;;;; 2149;DOUBLE-STRUCK ITALIC SMALL J;Ll;0;L; 006A;;;;N;;;;; 214A;PROPERTY LINE;So;0;ON;;;;;N;;;;; 214B;TURNED AMPERSAND;Sm;0;ON;;;;;N;;;;; 2153;VULGAR FRACTION ONE THIRD;No;0;ON; 0031 2044 0033;;;1/3;N;FRACTION ONE THIRD;;;; 2154;VULGAR FRACTION TWO THIRDS;No;0;ON; 0032 2044 0033;;;2/3;N;FRACTION TWO THIRDS;;;; 2155;VULGAR FRACTION ONE FIFTH;No;0;ON; 0031 2044 0035;;;1/5;N;FRACTION ONE FIFTH;;;; 2156;VULGAR FRACTION TWO FIFTHS;No;0;ON; 0032 2044 0035;;;2/5;N;FRACTION TWO FIFTHS;;;; 2157;VULGAR FRACTION THREE FIFTHS;No;0;ON; 0033 2044 0035;;;3/5;N;FRACTION THREE FIFTHS;;;; 2158;VULGAR FRACTION FOUR FIFTHS;No;0;ON; 0034 2044 0035;;;4/5;N;FRACTION FOUR FIFTHS;;;; 2159;VULGAR FRACTION ONE SIXTH;No;0;ON; 0031 2044 0036;;;1/6;N;FRACTION ONE SIXTH;;;; 215A;VULGAR FRACTION FIVE SIXTHS;No;0;ON; 0035 2044 0036;;;5/6;N;FRACTION FIVE SIXTHS;;;; 215B;VULGAR FRACTION ONE EIGHTH;No;0;ON; 0031 2044 0038;;;1/8;N;FRACTION ONE EIGHTH;;;; 215C;VULGAR FRACTION THREE EIGHTHS;No;0;ON; 0033 2044 0038;;;3/8;N;FRACTION THREE EIGHTHS;;;; 215D;VULGAR FRACTION FIVE EIGHTHS;No;0;ON; 0035 2044 0038;;;5/8;N;FRACTION FIVE EIGHTHS;;;; 215E;VULGAR FRACTION SEVEN EIGHTHS;No;0;ON; 0037 2044 0038;;;7/8;N;FRACTION SEVEN EIGHTHS;;;; 215F;FRACTION NUMERATOR ONE;No;0;ON; 0031 2044;;;1;N;;;;; 2160;ROMAN NUMERAL ONE;Nl;0;L; 0049;;;1;N;;;;2170; 2161;ROMAN NUMERAL TWO;Nl;0;L; 0049 0049;;;2;N;;;;2171; 2162;ROMAN NUMERAL THREE;Nl;0;L; 0049 0049 0049;;;3;N;;;;2172; 2163;ROMAN NUMERAL FOUR;Nl;0;L; 0049 0056;;;4;N;;;;2173; 2164;ROMAN NUMERAL FIVE;Nl;0;L; 0056;;;5;N;;;;2174; 2165;ROMAN NUMERAL SIX;Nl;0;L; 0056 0049;;;6;N;;;;2175; 2166;ROMAN NUMERAL SEVEN;Nl;0;L; 0056 0049 0049;;;7;N;;;;2176; 2167;ROMAN NUMERAL EIGHT;Nl;0;L; 0056 0049 0049 0049;;;8;N;;;;2177; 2168;ROMAN NUMERAL NINE;Nl;0;L; 0049 0058;;;9;N;;;;2178; 2169;ROMAN NUMERAL TEN;Nl;0;L; 0058;;;10;N;;;;2179; 216A;ROMAN NUMERAL ELEVEN;Nl;0;L; 0058 0049;;;11;N;;;;217A; 216B;ROMAN NUMERAL TWELVE;Nl;0;L; 0058 0049 0049;;;12;N;;;;217B; 216C;ROMAN NUMERAL FIFTY;Nl;0;L; 004C;;;50;N;;;;217C; 216D;ROMAN NUMERAL ONE HUNDRED;Nl;0;L; 0043;;;100;N;;;;217D; 216E;ROMAN NUMERAL FIVE HUNDRED;Nl;0;L; 0044;;;500;N;;;;217E; 216F;ROMAN NUMERAL ONE THOUSAND;Nl;0;L; 004D;;;1000;N;;;;217F; 2170;SMALL ROMAN NUMERAL ONE;Nl;0;L; 0069;;;1;N;;;2160;;2160 2171;SMALL ROMAN NUMERAL TWO;Nl;0;L; 0069 0069;;;2;N;;;2161;;2161 2172;SMALL ROMAN NUMERAL THREE;Nl;0;L; 0069 0069 0069;;;3;N;;;2162;;2162 2173;SMALL ROMAN NUMERAL FOUR;Nl;0;L; 0069 0076;;;4;N;;;2163;;2163 2174;SMALL ROMAN NUMERAL FIVE;Nl;0;L; 0076;;;5;N;;;2164;;2164 2175;SMALL ROMAN NUMERAL SIX;Nl;0;L; 0076 0069;;;6;N;;;2165;;2165 2176;SMALL ROMAN NUMERAL SEVEN;Nl;0;L; 0076 0069 0069;;;7;N;;;2166;;2166 2177;SMALL ROMAN NUMERAL EIGHT;Nl;0;L; 0076 0069 0069 0069;;;8;N;;;2167;;2167 2178;SMALL ROMAN NUMERAL NINE;Nl;0;L; 0069 0078;;;9;N;;;2168;;2168 2179;SMALL ROMAN NUMERAL TEN;Nl;0;L; 0078;;;10;N;;;2169;;2169 217A;SMALL ROMAN NUMERAL ELEVEN;Nl;0;L; 0078 0069;;;11;N;;;216A;;216A 217B;SMALL ROMAN NUMERAL TWELVE;Nl;0;L; 0078 0069 0069;;;12;N;;;216B;;216B 217C;SMALL ROMAN NUMERAL FIFTY;Nl;0;L; 006C;;;50;N;;;216C;;216C 217D;SMALL ROMAN NUMERAL ONE HUNDRED;Nl;0;L; 0063;;;100;N;;;216D;;216D 217E;SMALL ROMAN NUMERAL FIVE HUNDRED;Nl;0;L; 0064;;;500;N;;;216E;;216E 217F;SMALL ROMAN NUMERAL ONE THOUSAND;Nl;0;L; 006D;;;1000;N;;;216F;;216F 2180;ROMAN NUMERAL ONE THOUSAND C D;Nl;0;L;;;;1000;N;;;;; 2181;ROMAN NUMERAL FIVE THOUSAND;Nl;0;L;;;;5000;N;;;;; 2182;ROMAN NUMERAL TEN THOUSAND;Nl;0;L;;;;10000;N;;;;; 2183;ROMAN NUMERAL REVERSED ONE HUNDRED;Nl;0;L;;;;;N;;;;; 2190;LEFTWARDS ARROW;Sm;0;ON;;;;;N;LEFT ARROW;;;; 2191;UPWARDS ARROW;Sm;0;ON;;;;;N;UP ARROW;;;; 2192;RIGHTWARDS ARROW;Sm;0;ON;;;;;N;RIGHT ARROW;;;; 2193;DOWNWARDS ARROW;Sm;0;ON;;;;;N;DOWN ARROW;;;; 2194;LEFT RIGHT ARROW;Sm;0;ON;;;;;N;;;;; 2195;UP DOWN ARROW;So;0;ON;;;;;N;;;;; 2196;NORTH WEST ARROW;So;0;ON;;;;;N;UPPER LEFT ARROW;;;; 2197;NORTH EAST ARROW;So;0;ON;;;;;N;UPPER RIGHT ARROW;;;; 2198;SOUTH EAST ARROW;So;0;ON;;;;;N;LOWER RIGHT ARROW;;;; 2199;SOUTH WEST ARROW;So;0;ON;;;;;N;LOWER LEFT ARROW;;;; 219A;LEFTWARDS ARROW WITH STROKE;Sm;0;ON;2190 0338;;;;N;LEFT ARROW WITH STROKE;;;; 219B;RIGHTWARDS ARROW WITH STROKE;Sm;0;ON;2192 0338;;;;N;RIGHT ARROW WITH STROKE;;;; 219C;LEFTWARDS WAVE ARROW;So;0;ON;;;;;N;LEFT WAVE ARROW;;;; 219D;RIGHTWARDS WAVE ARROW;So;0;ON;;;;;N;RIGHT WAVE ARROW;;;; 219E;LEFTWARDS TWO HEADED ARROW;So;0;ON;;;;;N;LEFT TWO HEADED ARROW;;;; 219F;UPWARDS TWO HEADED ARROW;So;0;ON;;;;;N;UP TWO HEADED ARROW;;;; 21A0;RIGHTWARDS TWO HEADED ARROW;Sm;0;ON;;;;;N;RIGHT TWO HEADED ARROW;;;; 21A1;DOWNWARDS TWO HEADED ARROW;So;0;ON;;;;;N;DOWN TWO HEADED ARROW;;;; 21A2;LEFTWARDS ARROW WITH TAIL;So;0;ON;;;;;N;LEFT ARROW WITH TAIL;;;; 21A3;RIGHTWARDS ARROW WITH TAIL;Sm;0;ON;;;;;N;RIGHT ARROW WITH TAIL;;;; 21A4;LEFTWARDS ARROW FROM BAR;So;0;ON;;;;;N;LEFT ARROW FROM BAR;;;; 21A5;UPWARDS ARROW FROM BAR;So;0;ON;;;;;N;UP ARROW FROM BAR;;;; 21A6;RIGHTWARDS ARROW FROM BAR;Sm;0;ON;;;;;N;RIGHT ARROW FROM BAR;;;; 21A7;DOWNWARDS ARROW FROM BAR;So;0;ON;;;;;N;DOWN ARROW FROM BAR;;;; 21A8;UP DOWN ARROW WITH BASE;So;0;ON;;;;;N;;;;; 21A9;LEFTWARDS ARROW WITH HOOK;So;0;ON;;;;;N;LEFT ARROW WITH HOOK;;;; 21AA;RIGHTWARDS ARROW WITH HOOK;So;0;ON;;;;;N;RIGHT ARROW WITH HOOK;;;; 21AB;LEFTWARDS ARROW WITH LOOP;So;0;ON;;;;;N;LEFT ARROW WITH LOOP;;;; 21AC;RIGHTWARDS ARROW WITH LOOP;So;0;ON;;;;;N;RIGHT ARROW WITH LOOP;;;; 21AD;LEFT RIGHT WAVE ARROW;So;0;ON;;;;;N;;;;; 21AE;LEFT RIGHT ARROW WITH STROKE;Sm;0;ON;2194 0338;;;;N;;;;; 21AF;DOWNWARDS ZIGZAG ARROW;So;0;ON;;;;;N;DOWN ZIGZAG ARROW;;;; 21B0;UPWARDS ARROW WITH TIP LEFTWARDS;So;0;ON;;;;;N;UP ARROW WITH TIP LEFT;;;; 21B1;UPWARDS ARROW WITH TIP RIGHTWARDS;So;0;ON;;;;;N;UP ARROW WITH TIP RIGHT;;;; 21B2;DOWNWARDS ARROW WITH TIP LEFTWARDS;So;0;ON;;;;;N;DOWN ARROW WITH TIP LEFT;;;; 21B3;DOWNWARDS ARROW WITH TIP RIGHTWARDS;So;0;ON;;;;;N;DOWN ARROW WITH TIP RIGHT;;;; 21B4;RIGHTWARDS ARROW WITH CORNER DOWNWARDS;So;0;ON;;;;;N;RIGHT ARROW WITH CORNER DOWN;;;; 21B5;DOWNWARDS ARROW WITH CORNER LEFTWARDS;So;0;ON;;;;;N;DOWN ARROW WITH CORNER LEFT;;;; 21B6;ANTICLOCKWISE TOP SEMICIRCLE ARROW;So;0;ON;;;;;N;;;;; 21B7;CLOCKWISE TOP SEMICIRCLE ARROW;So;0;ON;;;;;N;;;;; 21B8;NORTH WEST ARROW TO LONG BAR;So;0;ON;;;;;N;UPPER LEFT ARROW TO LONG BAR;;;; 21B9;LEFTWARDS ARROW TO BAR OVER RIGHTWARDS ARROW TO BAR;So;0;ON;;;;;N;LEFT ARROW TO BAR OVER RIGHT ARROW TO BAR;;;; 21BA;ANTICLOCKWISE OPEN CIRCLE ARROW;So;0;ON;;;;;N;;;;; 21BB;CLOCKWISE OPEN CIRCLE ARROW;So;0;ON;;;;;N;;;;; 21BC;LEFTWARDS HARPOON WITH BARB UPWARDS;So;0;ON;;;;;N;LEFT HARPOON WITH BARB UP;;;; 21BD;LEFTWARDS HARPOON WITH BARB DOWNWARDS;So;0;ON;;;;;N;LEFT HARPOON WITH BARB DOWN;;;; 21BE;UPWARDS HARPOON WITH BARB RIGHTWARDS;So;0;ON;;;;;N;UP HARPOON WITH BARB RIGHT;;;; 21BF;UPWARDS HARPOON WITH BARB LEFTWARDS;So;0;ON;;;;;N;UP HARPOON WITH BARB LEFT;;;; 21C0;RIGHTWARDS HARPOON WITH BARB UPWARDS;So;0;ON;;;;;N;RIGHT HARPOON WITH BARB UP;;;; 21C1;RIGHTWARDS HARPOON WITH BARB DOWNWARDS;So;0;ON;;;;;N;RIGHT HARPOON WITH BARB DOWN;;;; 21C2;DOWNWARDS HARPOON WITH BARB RIGHTWARDS;So;0;ON;;;;;N;DOWN HARPOON WITH BARB RIGHT;;;; 21C3;DOWNWARDS HARPOON WITH BARB LEFTWARDS;So;0;ON;;;;;N;DOWN HARPOON WITH BARB LEFT;;;; 21C4;RIGHTWARDS ARROW OVER LEFTWARDS ARROW;So;0;ON;;;;;N;RIGHT ARROW OVER LEFT ARROW;;;; 21C5;UPWARDS ARROW LEFTWARDS OF DOWNWARDS ARROW;So;0;ON;;;;;N;UP ARROW LEFT OF DOWN ARROW;;;; 21C6;LEFTWARDS ARROW OVER RIGHTWARDS ARROW;So;0;ON;;;;;N;LEFT ARROW OVER RIGHT ARROW;;;; 21C7;LEFTWARDS PAIRED ARROWS;So;0;ON;;;;;N;LEFT PAIRED ARROWS;;;; 21C8;UPWARDS PAIRED ARROWS;So;0;ON;;;;;N;UP PAIRED ARROWS;;;; 21C9;RIGHTWARDS PAIRED ARROWS;So;0;ON;;;;;N;RIGHT PAIRED ARROWS;;;; 21CA;DOWNWARDS PAIRED ARROWS;So;0;ON;;;;;N;DOWN PAIRED ARROWS;;;; 21CB;LEFTWARDS HARPOON OVER RIGHTWARDS HARPOON;So;0;ON;;;;;N;LEFT HARPOON OVER RIGHT HARPOON;;;; 21CC;RIGHTWARDS HARPOON OVER LEFTWARDS HARPOON;So;0;ON;;;;;N;RIGHT HARPOON OVER LEFT HARPOON;;;; 21CD;LEFTWARDS DOUBLE ARROW WITH STROKE;So;0;ON;21D0 0338;;;;N;LEFT DOUBLE ARROW WITH STROKE;;;; 21CE;LEFT RIGHT DOUBLE ARROW WITH STROKE;Sm;0;ON;21D4 0338;;;;N;;;;; 21CF;RIGHTWARDS DOUBLE ARROW WITH STROKE;Sm;0;ON;21D2 0338;;;;N;RIGHT DOUBLE ARROW WITH STROKE;;;; 21D0;LEFTWARDS DOUBLE ARROW;So;0;ON;;;;;N;LEFT DOUBLE ARROW;;;; 21D1;UPWARDS DOUBLE ARROW;So;0;ON;;;;;N;UP DOUBLE ARROW;;;; 21D2;RIGHTWARDS DOUBLE ARROW;Sm;0;ON;;;;;N;RIGHT DOUBLE ARROW;;;; 21D3;DOWNWARDS DOUBLE ARROW;So;0;ON;;;;;N;DOWN DOUBLE ARROW;;;; 21D4;LEFT RIGHT DOUBLE ARROW;Sm;0;ON;;;;;N;;;;; 21D5;UP DOWN DOUBLE ARROW;So;0;ON;;;;;N;;;;; 21D6;NORTH WEST DOUBLE ARROW;So;0;ON;;;;;N;UPPER LEFT DOUBLE ARROW;;;; 21D7;NORTH EAST DOUBLE ARROW;So;0;ON;;;;;N;UPPER RIGHT DOUBLE ARROW;;;; 21D8;SOUTH EAST DOUBLE ARROW;So;0;ON;;;;;N;LOWER RIGHT DOUBLE ARROW;;;; 21D9;SOUTH WEST DOUBLE ARROW;So;0;ON;;;;;N;LOWER LEFT DOUBLE ARROW;;;; 21DA;LEFTWARDS TRIPLE ARROW;So;0;ON;;;;;N;LEFT TRIPLE ARROW;;;; 21DB;RIGHTWARDS TRIPLE ARROW;So;0;ON;;;;;N;RIGHT TRIPLE ARROW;;;; 21DC;LEFTWARDS SQUIGGLE ARROW;So;0;ON;;;;;N;LEFT SQUIGGLE ARROW;;;; 21DD;RIGHTWARDS SQUIGGLE ARROW;So;0;ON;;;;;N;RIGHT SQUIGGLE ARROW;;;; 21DE;UPWARDS ARROW WITH DOUBLE STROKE;So;0;ON;;;;;N;UP ARROW WITH DOUBLE STROKE;;;; 21DF;DOWNWARDS ARROW WITH DOUBLE STROKE;So;0;ON;;;;;N;DOWN ARROW WITH DOUBLE STROKE;;;; 21E0;LEFTWARDS DASHED ARROW;So;0;ON;;;;;N;LEFT DASHED ARROW;;;; 21E1;UPWARDS DASHED ARROW;So;0;ON;;;;;N;UP DASHED ARROW;;;; 21E2;RIGHTWARDS DASHED ARROW;So;0;ON;;;;;N;RIGHT DASHED ARROW;;;; 21E3;DOWNWARDS DASHED ARROW;So;0;ON;;;;;N;DOWN DASHED ARROW;;;; 21E4;LEFTWARDS ARROW TO BAR;So;0;ON;;;;;N;LEFT ARROW TO BAR;;;; 21E5;RIGHTWARDS ARROW TO BAR;So;0;ON;;;;;N;RIGHT ARROW TO BAR;;;; 21E6;LEFTWARDS WHITE ARROW;So;0;ON;;;;;N;WHITE LEFT ARROW;;;; 21E7;UPWARDS WHITE ARROW;So;0;ON;;;;;N;WHITE UP ARROW;;;; 21E8;RIGHTWARDS WHITE ARROW;So;0;ON;;;;;N;WHITE RIGHT ARROW;;;; 21E9;DOWNWARDS WHITE ARROW;So;0;ON;;;;;N;WHITE DOWN ARROW;;;; 21EA;UPWARDS WHITE ARROW FROM BAR;So;0;ON;;;;;N;WHITE UP ARROW FROM BAR;;;; 21EB;UPWARDS WHITE ARROW ON PEDESTAL;So;0;ON;;;;;N;;;;; 21EC;UPWARDS WHITE ARROW ON PEDESTAL WITH HORIZONTAL BAR;So;0;ON;;;;;N;;;;; 21ED;UPWARDS WHITE ARROW ON PEDESTAL WITH VERTICAL BAR;So;0;ON;;;;;N;;;;; 21EE;UPWARDS WHITE DOUBLE ARROW;So;0;ON;;;;;N;;;;; 21EF;UPWARDS WHITE DOUBLE ARROW ON PEDESTAL;So;0;ON;;;;;N;;;;; 21F0;RIGHTWARDS WHITE ARROW FROM WALL;So;0;ON;;;;;N;;;;; 21F1;NORTH WEST ARROW TO CORNER;So;0;ON;;;;;N;;;;; 21F2;SOUTH EAST ARROW TO CORNER;So;0;ON;;;;;N;;;;; 21F3;UP DOWN WHITE ARROW;So;0;ON;;;;;N;;;;; 21F4;RIGHT ARROW WITH SMALL CIRCLE;Sm;0;ON;;;;;N;;;;; 21F5;DOWNWARDS ARROW LEFTWARDS OF UPWARDS ARROW;Sm;0;ON;;;;;N;;;;; 21F6;THREE RIGHTWARDS ARROWS;Sm;0;ON;;;;;N;;;;; 21F7;LEFTWARDS ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 21F8;RIGHTWARDS ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 21F9;LEFT RIGHT ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 21FA;LEFTWARDS ARROW WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 21FB;RIGHTWARDS ARROW WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 21FC;LEFT RIGHT ARROW WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 21FD;LEFTWARDS OPEN-HEADED ARROW;Sm;0;ON;;;;;N;;;;; 21FE;RIGHTWARDS OPEN-HEADED ARROW;Sm;0;ON;;;;;N;;;;; 21FF;LEFT RIGHT OPEN-HEADED ARROW;Sm;0;ON;;;;;N;;;;; 2200;FOR ALL;Sm;0;ON;;;;;N;;;;; 2201;COMPLEMENT;Sm;0;ON;;;;;Y;;;;; 2202;PARTIAL DIFFERENTIAL;Sm;0;ON;;;;;Y;;;;; 2203;THERE EXISTS;Sm;0;ON;;;;;Y;;;;; 2204;THERE DOES NOT EXIST;Sm;0;ON;2203 0338;;;;Y;;;;; 2205;EMPTY SET;Sm;0;ON;;;;;N;;;;; 2206;INCREMENT;Sm;0;ON;;;;;N;;;;; 2207;NABLA;Sm;0;ON;;;;;N;;;;; 2208;ELEMENT OF;Sm;0;ON;;;;;Y;;;;; 2209;NOT AN ELEMENT OF;Sm;0;ON;2208 0338;;;;Y;;;;; 220A;SMALL ELEMENT OF;Sm;0;ON;;;;;Y;;;;; 220B;CONTAINS AS MEMBER;Sm;0;ON;;;;;Y;;;;; 220C;DOES NOT CONTAIN AS MEMBER;Sm;0;ON;220B 0338;;;;Y;;;;; 220D;SMALL CONTAINS AS MEMBER;Sm;0;ON;;;;;Y;;;;; 220E;END OF PROOF;Sm;0;ON;;;;;N;;;;; 220F;N-ARY PRODUCT;Sm;0;ON;;;;;N;;;;; 2210;N-ARY COPRODUCT;Sm;0;ON;;;;;N;;;;; 2211;N-ARY SUMMATION;Sm;0;ON;;;;;Y;;;;; 2212;MINUS SIGN;Sm;0;ET;;;;;N;;;;; 2213;MINUS-OR-PLUS SIGN;Sm;0;ET;;;;;N;;;;; 2214;DOT PLUS;Sm;0;ON;;;;;N;;;;; 2215;DIVISION SLASH;Sm;0;ON;;;;;Y;;;;; 2216;SET MINUS;Sm;0;ON;;;;;Y;;;;; 2217;ASTERISK OPERATOR;Sm;0;ON;;;;;N;;;;; 2218;RING OPERATOR;Sm;0;ON;;;;;N;;;;; 2219;BULLET OPERATOR;Sm;0;ON;;;;;N;;;;; 221A;SQUARE ROOT;Sm;0;ON;;;;;Y;;;;; 221B;CUBE ROOT;Sm;0;ON;;;;;Y;;;;; 221C;FOURTH ROOT;Sm;0;ON;;;;;Y;;;;; 221D;PROPORTIONAL TO;Sm;0;ON;;;;;Y;;;;; 221E;INFINITY;Sm;0;ON;;;;;N;;;;; 221F;RIGHT ANGLE;Sm;0;ON;;;;;Y;;;;; 2220;ANGLE;Sm;0;ON;;;;;Y;;;;; 2221;MEASURED ANGLE;Sm;0;ON;;;;;Y;;;;; 2222;SPHERICAL ANGLE;Sm;0;ON;;;;;Y;;;;; 2223;DIVIDES;Sm;0;ON;;;;;N;;;;; 2224;DOES NOT DIVIDE;Sm;0;ON;2223 0338;;;;Y;;;;; 2225;PARALLEL TO;Sm;0;ON;;;;;N;;;;; 2226;NOT PARALLEL TO;Sm;0;ON;2225 0338;;;;Y;;;;; 2227;LOGICAL AND;Sm;0;ON;;;;;N;;;;; 2228;LOGICAL OR;Sm;0;ON;;;;;N;;;;; 2229;INTERSECTION;Sm;0;ON;;;;;N;;;;; 222A;UNION;Sm;0;ON;;;;;N;;;;; 222B;INTEGRAL;Sm;0;ON;;;;;Y;;;;; 222C;DOUBLE INTEGRAL;Sm;0;ON; 222B 222B;;;;Y;;;;; 222D;TRIPLE INTEGRAL;Sm;0;ON; 222B 222B 222B;;;;Y;;;;; 222E;CONTOUR INTEGRAL;Sm;0;ON;;;;;Y;;;;; 222F;SURFACE INTEGRAL;Sm;0;ON; 222E 222E;;;;Y;;;;; 2230;VOLUME INTEGRAL;Sm;0;ON; 222E 222E 222E;;;;Y;;;;; 2231;CLOCKWISE INTEGRAL;Sm;0;ON;;;;;Y;;;;; 2232;CLOCKWISE CONTOUR INTEGRAL;Sm;0;ON;;;;;Y;;;;; 2233;ANTICLOCKWISE CONTOUR INTEGRAL;Sm;0;ON;;;;;Y;;;;; 2234;THEREFORE;Sm;0;ON;;;;;N;;;;; 2235;BECAUSE;Sm;0;ON;;;;;N;;;;; 2236;RATIO;Sm;0;ON;;;;;N;;;;; 2237;PROPORTION;Sm;0;ON;;;;;N;;;;; 2238;DOT MINUS;Sm;0;ON;;;;;N;;;;; 2239;EXCESS;Sm;0;ON;;;;;Y;;;;; 223A;GEOMETRIC PROPORTION;Sm;0;ON;;;;;N;;;;; 223B;HOMOTHETIC;Sm;0;ON;;;;;Y;;;;; 223C;TILDE OPERATOR;Sm;0;ON;;;;;Y;;;;; 223D;REVERSED TILDE;Sm;0;ON;;;;;Y;;lazy S;;; 223E;INVERTED LAZY S;Sm;0;ON;;;;;Y;;;;; 223F;SINE WAVE;Sm;0;ON;;;;;Y;;;;; 2240;WREATH PRODUCT;Sm;0;ON;;;;;Y;;;;; 2241;NOT TILDE;Sm;0;ON;223C 0338;;;;Y;;;;; 2242;MINUS TILDE;Sm;0;ON;;;;;Y;;;;; 2243;ASYMPTOTICALLY EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2244;NOT ASYMPTOTICALLY EQUAL TO;Sm;0;ON;2243 0338;;;;Y;;;;; 2245;APPROXIMATELY EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2246;APPROXIMATELY BUT NOT ACTUALLY EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2247;NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO;Sm;0;ON;2245 0338;;;;Y;;;;; 2248;ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2249;NOT ALMOST EQUAL TO;Sm;0;ON;2248 0338;;;;Y;;;;; 224A;ALMOST EQUAL OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 224B;TRIPLE TILDE;Sm;0;ON;;;;;Y;;;;; 224C;ALL EQUAL TO;Sm;0;ON;;;;;Y;;;;; 224D;EQUIVALENT TO;Sm;0;ON;;;;;N;;;;; 224E;GEOMETRICALLY EQUIVALENT TO;Sm;0;ON;;;;;N;;;;; 224F;DIFFERENCE BETWEEN;Sm;0;ON;;;;;N;;;;; 2250;APPROACHES THE LIMIT;Sm;0;ON;;;;;N;;;;; 2251;GEOMETRICALLY EQUAL TO;Sm;0;ON;;;;;N;;;;; 2252;APPROXIMATELY EQUAL TO OR THE IMAGE OF;Sm;0;ON;;;;;Y;;;;; 2253;IMAGE OF OR APPROXIMATELY EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2254;COLON EQUALS;Sm;0;ON;;;;;Y;COLON EQUAL;;;; 2255;EQUALS COLON;Sm;0;ON;;;;;Y;EQUAL COLON;;;; 2256;RING IN EQUAL TO;Sm;0;ON;;;;;N;;;;; 2257;RING EQUAL TO;Sm;0;ON;;;;;N;;;;; 2258;CORRESPONDS TO;Sm;0;ON;;;;;N;;;;; 2259;ESTIMATES;Sm;0;ON;;;;;N;;;;; 225A;EQUIANGULAR TO;Sm;0;ON;;;;;N;;;;; 225B;STAR EQUALS;Sm;0;ON;;;;;N;;;;; 225C;DELTA EQUAL TO;Sm;0;ON;;;;;N;;;;; 225D;EQUAL TO BY DEFINITION;Sm;0;ON;;;;;N;;;;; 225E;MEASURED BY;Sm;0;ON;;;;;N;;;;; 225F;QUESTIONED EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2260;NOT EQUAL TO;Sm;0;ON;003D 0338;;;;Y;;;;; 2261;IDENTICAL TO;Sm;0;ON;;;;;N;;;;; 2262;NOT IDENTICAL TO;Sm;0;ON;2261 0338;;;;Y;;;;; 2263;STRICTLY EQUIVALENT TO;Sm;0;ON;;;;;N;;;;; 2264;LESS-THAN OR EQUAL TO;Sm;0;ON;;;;;Y;LESS THAN OR EQUAL TO;;;; 2265;GREATER-THAN OR EQUAL TO;Sm;0;ON;;;;;Y;GREATER THAN OR EQUAL TO;;;; 2266;LESS-THAN OVER EQUAL TO;Sm;0;ON;;;;;Y;LESS THAN OVER EQUAL TO;;;; 2267;GREATER-THAN OVER EQUAL TO;Sm;0;ON;;;;;Y;GREATER THAN OVER EQUAL TO;;;; 2268;LESS-THAN BUT NOT EQUAL TO;Sm;0;ON;;;;;Y;LESS THAN BUT NOT EQUAL TO;;;; 2269;GREATER-THAN BUT NOT EQUAL TO;Sm;0;ON;;;;;Y;GREATER THAN BUT NOT EQUAL TO;;;; 226A;MUCH LESS-THAN;Sm;0;ON;;;;;Y;MUCH LESS THAN;;;; 226B;MUCH GREATER-THAN;Sm;0;ON;;;;;Y;MUCH GREATER THAN;;;; 226C;BETWEEN;Sm;0;ON;;;;;N;;;;; 226D;NOT EQUIVALENT TO;Sm;0;ON;224D 0338;;;;N;;;;; 226E;NOT LESS-THAN;Sm;0;ON;003C 0338;;;;Y;NOT LESS THAN;;;; 226F;NOT GREATER-THAN;Sm;0;ON;003E 0338;;;;Y;NOT GREATER THAN;;;; 2270;NEITHER LESS-THAN NOR EQUAL TO;Sm;0;ON;2264 0338;;;;Y;NEITHER LESS THAN NOR EQUAL TO;;;; 2271;NEITHER GREATER-THAN NOR EQUAL TO;Sm;0;ON;2265 0338;;;;Y;NEITHER GREATER THAN NOR EQUAL TO;;;; 2272;LESS-THAN OR EQUIVALENT TO;Sm;0;ON;;;;;Y;LESS THAN OR EQUIVALENT TO;;;; 2273;GREATER-THAN OR EQUIVALENT TO;Sm;0;ON;;;;;Y;GREATER THAN OR EQUIVALENT TO;;;; 2274;NEITHER LESS-THAN NOR EQUIVALENT TO;Sm;0;ON;2272 0338;;;;Y;NEITHER LESS THAN NOR EQUIVALENT TO;;;; 2275;NEITHER GREATER-THAN NOR EQUIVALENT TO;Sm;0;ON;2273 0338;;;;Y;NEITHER GREATER THAN NOR EQUIVALENT TO;;;; 2276;LESS-THAN OR GREATER-THAN;Sm;0;ON;;;;;Y;LESS THAN OR GREATER THAN;;;; 2277;GREATER-THAN OR LESS-THAN;Sm;0;ON;;;;;Y;GREATER THAN OR LESS THAN;;;; 2278;NEITHER LESS-THAN NOR GREATER-THAN;Sm;0;ON;2276 0338;;;;Y;NEITHER LESS THAN NOR GREATER THAN;;;; 2279;NEITHER GREATER-THAN NOR LESS-THAN;Sm;0;ON;2277 0338;;;;Y;NEITHER GREATER THAN NOR LESS THAN;;;; 227A;PRECEDES;Sm;0;ON;;;;;Y;;;;; 227B;SUCCEEDS;Sm;0;ON;;;;;Y;;;;; 227C;PRECEDES OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 227D;SUCCEEDS OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 227E;PRECEDES OR EQUIVALENT TO;Sm;0;ON;;;;;Y;;;;; 227F;SUCCEEDS OR EQUIVALENT TO;Sm;0;ON;;;;;Y;;;;; 2280;DOES NOT PRECEDE;Sm;0;ON;227A 0338;;;;Y;;;;; 2281;DOES NOT SUCCEED;Sm;0;ON;227B 0338;;;;Y;;;;; 2282;SUBSET OF;Sm;0;ON;;;;;Y;;;;; 2283;SUPERSET OF;Sm;0;ON;;;;;Y;;;;; 2284;NOT A SUBSET OF;Sm;0;ON;2282 0338;;;;Y;;;;; 2285;NOT A SUPERSET OF;Sm;0;ON;2283 0338;;;;Y;;;;; 2286;SUBSET OF OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2287;SUPERSET OF OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2288;NEITHER A SUBSET OF NOR EQUAL TO;Sm;0;ON;2286 0338;;;;Y;;;;; 2289;NEITHER A SUPERSET OF NOR EQUAL TO;Sm;0;ON;2287 0338;;;;Y;;;;; 228A;SUBSET OF WITH NOT EQUAL TO;Sm;0;ON;;;;;Y;SUBSET OF OR NOT EQUAL TO;;;; 228B;SUPERSET OF WITH NOT EQUAL TO;Sm;0;ON;;;;;Y;SUPERSET OF OR NOT EQUAL TO;;;; 228C;MULTISET;Sm;0;ON;;;;;Y;;;;; 228D;MULTISET MULTIPLICATION;Sm;0;ON;;;;;N;;;;; 228E;MULTISET UNION;Sm;0;ON;;;;;N;;;;; 228F;SQUARE IMAGE OF;Sm;0;ON;;;;;Y;;;;; 2290;SQUARE ORIGINAL OF;Sm;0;ON;;;;;Y;;;;; 2291;SQUARE IMAGE OF OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2292;SQUARE ORIGINAL OF OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2293;SQUARE CAP;Sm;0;ON;;;;;N;;;;; 2294;SQUARE CUP;Sm;0;ON;;;;;N;;;;; 2295;CIRCLED PLUS;Sm;0;ON;;;;;N;;;;; 2296;CIRCLED MINUS;Sm;0;ON;;;;;N;;;;; 2297;CIRCLED TIMES;Sm;0;ON;;;;;N;;;;; 2298;CIRCLED DIVISION SLASH;Sm;0;ON;;;;;Y;;;;; 2299;CIRCLED DOT OPERATOR;Sm;0;ON;;;;;N;;;;; 229A;CIRCLED RING OPERATOR;Sm;0;ON;;;;;N;;;;; 229B;CIRCLED ASTERISK OPERATOR;Sm;0;ON;;;;;N;;;;; 229C;CIRCLED EQUALS;Sm;0;ON;;;;;N;;;;; 229D;CIRCLED DASH;Sm;0;ON;;;;;N;;;;; 229E;SQUARED PLUS;Sm;0;ON;;;;;N;;;;; 229F;SQUARED MINUS;Sm;0;ON;;;;;N;;;;; 22A0;SQUARED TIMES;Sm;0;ON;;;;;N;;;;; 22A1;SQUARED DOT OPERATOR;Sm;0;ON;;;;;N;;;;; 22A2;RIGHT TACK;Sm;0;ON;;;;;Y;;;;; 22A3;LEFT TACK;Sm;0;ON;;;;;Y;;;;; 22A4;DOWN TACK;Sm;0;ON;;;;;N;;;;; 22A5;UP TACK;Sm;0;ON;;;;;N;;;;; 22A6;ASSERTION;Sm;0;ON;;;;;Y;;;;; 22A7;MODELS;Sm;0;ON;;;;;Y;;;;; 22A8;TRUE;Sm;0;ON;;;;;Y;;;;; 22A9;FORCES;Sm;0;ON;;;;;Y;;;;; 22AA;TRIPLE VERTICAL BAR RIGHT TURNSTILE;Sm;0;ON;;;;;Y;;;;; 22AB;DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE;Sm;0;ON;;;;;Y;;;;; 22AC;DOES NOT PROVE;Sm;0;ON;22A2 0338;;;;Y;;;;; 22AD;NOT TRUE;Sm;0;ON;22A8 0338;;;;Y;;;;; 22AE;DOES NOT FORCE;Sm;0;ON;22A9 0338;;;;Y;;;;; 22AF;NEGATED DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE;Sm;0;ON;22AB 0338;;;;Y;;;;; 22B0;PRECEDES UNDER RELATION;Sm;0;ON;;;;;Y;;;;; 22B1;SUCCEEDS UNDER RELATION;Sm;0;ON;;;;;Y;;;;; 22B2;NORMAL SUBGROUP OF;Sm;0;ON;;;;;Y;;;;; 22B3;CONTAINS AS NORMAL SUBGROUP;Sm;0;ON;;;;;Y;;;;; 22B4;NORMAL SUBGROUP OF OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 22B5;CONTAINS AS NORMAL SUBGROUP OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 22B6;ORIGINAL OF;Sm;0;ON;;;;;Y;;;;; 22B7;IMAGE OF;Sm;0;ON;;;;;Y;;;;; 22B8;MULTIMAP;Sm;0;ON;;;;;Y;;;;; 22B9;HERMITIAN CONJUGATE MATRIX;Sm;0;ON;;;;;N;;;;; 22BA;INTERCALATE;Sm;0;ON;;;;;N;;;;; 22BB;XOR;Sm;0;ON;;;;;N;;;;; 22BC;NAND;Sm;0;ON;;;;;N;;;;; 22BD;NOR;Sm;0;ON;;;;;N;;;;; 22BE;RIGHT ANGLE WITH ARC;Sm;0;ON;;;;;Y;;;;; 22BF;RIGHT TRIANGLE;Sm;0;ON;;;;;Y;;;;; 22C0;N-ARY LOGICAL AND;Sm;0;ON;;;;;N;;;;; 22C1;N-ARY LOGICAL OR;Sm;0;ON;;;;;N;;;;; 22C2;N-ARY INTERSECTION;Sm;0;ON;;;;;N;;;;; 22C3;N-ARY UNION;Sm;0;ON;;;;;N;;;;; 22C4;DIAMOND OPERATOR;Sm;0;ON;;;;;N;;;;; 22C5;DOT OPERATOR;Sm;0;ON;;;;;N;;;;; 22C6;STAR OPERATOR;Sm;0;ON;;;;;N;;;;; 22C7;DIVISION TIMES;Sm;0;ON;;;;;N;;;;; 22C8;BOWTIE;Sm;0;ON;;;;;N;;;;; 22C9;LEFT NORMAL FACTOR SEMIDIRECT PRODUCT;Sm;0;ON;;;;;Y;;;;; 22CA;RIGHT NORMAL FACTOR SEMIDIRECT PRODUCT;Sm;0;ON;;;;;Y;;;;; 22CB;LEFT SEMIDIRECT PRODUCT;Sm;0;ON;;;;;Y;;;;; 22CC;RIGHT SEMIDIRECT PRODUCT;Sm;0;ON;;;;;Y;;;;; 22CD;REVERSED TILDE EQUALS;Sm;0;ON;;;;;Y;;;;; 22CE;CURLY LOGICAL OR;Sm;0;ON;;;;;N;;;;; 22CF;CURLY LOGICAL AND;Sm;0;ON;;;;;N;;;;; 22D0;DOUBLE SUBSET;Sm;0;ON;;;;;Y;;;;; 22D1;DOUBLE SUPERSET;Sm;0;ON;;;;;Y;;;;; 22D2;DOUBLE INTERSECTION;Sm;0;ON;;;;;N;;;;; 22D3;DOUBLE UNION;Sm;0;ON;;;;;N;;;;; 22D4;PITCHFORK;Sm;0;ON;;;;;N;;;;; 22D5;EQUAL AND PARALLEL TO;Sm;0;ON;;;;;N;;;;; 22D6;LESS-THAN WITH DOT;Sm;0;ON;;;;;Y;LESS THAN WITH DOT;;;; 22D7;GREATER-THAN WITH DOT;Sm;0;ON;;;;;Y;GREATER THAN WITH DOT;;;; 22D8;VERY MUCH LESS-THAN;Sm;0;ON;;;;;Y;VERY MUCH LESS THAN;;;; 22D9;VERY MUCH GREATER-THAN;Sm;0;ON;;;;;Y;VERY MUCH GREATER THAN;;;; 22DA;LESS-THAN EQUAL TO OR GREATER-THAN;Sm;0;ON;;;;;Y;LESS THAN EQUAL TO OR GREATER THAN;;;; 22DB;GREATER-THAN EQUAL TO OR LESS-THAN;Sm;0;ON;;;;;Y;GREATER THAN EQUAL TO OR LESS THAN;;;; 22DC;EQUAL TO OR LESS-THAN;Sm;0;ON;;;;;Y;EQUAL TO OR LESS THAN;;;; 22DD;EQUAL TO OR GREATER-THAN;Sm;0;ON;;;;;Y;EQUAL TO OR GREATER THAN;;;; 22DE;EQUAL TO OR PRECEDES;Sm;0;ON;;;;;Y;;;;; 22DF;EQUAL TO OR SUCCEEDS;Sm;0;ON;;;;;Y;;;;; 22E0;DOES NOT PRECEDE OR EQUAL;Sm;0;ON;227C 0338;;;;Y;;;;; 22E1;DOES NOT SUCCEED OR EQUAL;Sm;0;ON;227D 0338;;;;Y;;;;; 22E2;NOT SQUARE IMAGE OF OR EQUAL TO;Sm;0;ON;2291 0338;;;;Y;;;;; 22E3;NOT SQUARE ORIGINAL OF OR EQUAL TO;Sm;0;ON;2292 0338;;;;Y;;;;; 22E4;SQUARE IMAGE OF OR NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; 22E5;SQUARE ORIGINAL OF OR NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; 22E6;LESS-THAN BUT NOT EQUIVALENT TO;Sm;0;ON;;;;;Y;LESS THAN BUT NOT EQUIVALENT TO;;;; 22E7;GREATER-THAN BUT NOT EQUIVALENT TO;Sm;0;ON;;;;;Y;GREATER THAN BUT NOT EQUIVALENT TO;;;; 22E8;PRECEDES BUT NOT EQUIVALENT TO;Sm;0;ON;;;;;Y;;;;; 22E9;SUCCEEDS BUT NOT EQUIVALENT TO;Sm;0;ON;;;;;Y;;;;; 22EA;NOT NORMAL SUBGROUP OF;Sm;0;ON;22B2 0338;;;;Y;;;;; 22EB;DOES NOT CONTAIN AS NORMAL SUBGROUP;Sm;0;ON;22B3 0338;;;;Y;;;;; 22EC;NOT NORMAL SUBGROUP OF OR EQUAL TO;Sm;0;ON;22B4 0338;;;;Y;;;;; 22ED;DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL;Sm;0;ON;22B5 0338;;;;Y;;;;; 22EE;VERTICAL ELLIPSIS;Sm;0;ON;;;;;N;;;;; 22EF;MIDLINE HORIZONTAL ELLIPSIS;Sm;0;ON;;;;;N;;;;; 22F0;UP RIGHT DIAGONAL ELLIPSIS;Sm;0;ON;;;;;Y;;;;; 22F1;DOWN RIGHT DIAGONAL ELLIPSIS;Sm;0;ON;;;;;Y;;;;; 22F2;ELEMENT OF WITH LONG HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;; 22F3;ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;; 22F4;SMALL ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;; 22F5;ELEMENT OF WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;; 22F6;ELEMENT OF WITH OVERBAR;Sm;0;ON;;;;;Y;;;;; 22F7;SMALL ELEMENT OF WITH OVERBAR;Sm;0;ON;;;;;Y;;;;; 22F8;ELEMENT OF WITH UNDERBAR;Sm;0;ON;;;;;Y;;;;; 22F9;ELEMENT OF WITH TWO HORIZONTAL STROKES;Sm;0;ON;;;;;Y;;;;; 22FA;CONTAINS WITH LONG HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;; 22FB;CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;; 22FC;SMALL CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;; 22FD;CONTAINS WITH OVERBAR;Sm;0;ON;;;;;Y;;;;; 22FE;SMALL CONTAINS WITH OVERBAR;Sm;0;ON;;;;;Y;;;;; 22FF;Z NOTATION BAG MEMBERSHIP;Sm;0;ON;;;;;Y;;;;; 2300;DIAMETER SIGN;So;0;ON;;;;;N;;;;; 2301;ELECTRIC ARROW;So;0;ON;;;;;N;;;;; 2302;HOUSE;So;0;ON;;;;;N;;;;; 2303;UP ARROWHEAD;So;0;ON;;;;;N;;;;; 2304;DOWN ARROWHEAD;So;0;ON;;;;;N;;;;; 2305;PROJECTIVE;So;0;ON;;;;;N;;;;; 2306;PERSPECTIVE;So;0;ON;;;;;N;;;;; 2307;WAVY LINE;So;0;ON;;;;;N;;;;; 2308;LEFT CEILING;Sm;0;ON;;;;;Y;;;;; 2309;RIGHT CEILING;Sm;0;ON;;;;;Y;;;;; 230A;LEFT FLOOR;Sm;0;ON;;;;;Y;;;;; 230B;RIGHT FLOOR;Sm;0;ON;;;;;Y;;;;; 230C;BOTTOM RIGHT CROP;So;0;ON;;;;;N;;;;; 230D;BOTTOM LEFT CROP;So;0;ON;;;;;N;;;;; 230E;TOP RIGHT CROP;So;0;ON;;;;;N;;;;; 230F;TOP LEFT CROP;So;0;ON;;;;;N;;;;; 2310;REVERSED NOT SIGN;So;0;ON;;;;;N;;;;; 2311;SQUARE LOZENGE;So;0;ON;;;;;N;;;;; 2312;ARC;So;0;ON;;;;;N;;;;; 2313;SEGMENT;So;0;ON;;;;;N;;;;; 2314;SECTOR;So;0;ON;;;;;N;;;;; 2315;TELEPHONE RECORDER;So;0;ON;;;;;N;;;;; 2316;POSITION INDICATOR;So;0;ON;;;;;N;;;;; 2317;VIEWDATA SQUARE;So;0;ON;;;;;N;;;;; 2318;PLACE OF INTEREST SIGN;So;0;ON;;;;;N;COMMAND KEY;;;; 2319;TURNED NOT SIGN;So;0;ON;;;;;N;;;;; 231A;WATCH;So;0;ON;;;;;N;;;;; 231B;HOURGLASS;So;0;ON;;;;;N;;;;; 231C;TOP LEFT CORNER;So;0;ON;;;;;N;;;;; 231D;TOP RIGHT CORNER;So;0;ON;;;;;N;;;;; 231E;BOTTOM LEFT CORNER;So;0;ON;;;;;N;;;;; 231F;BOTTOM RIGHT CORNER;So;0;ON;;;;;N;;;;; 2320;TOP HALF INTEGRAL;Sm;0;ON;;;;;Y;;;;; 2321;BOTTOM HALF INTEGRAL;Sm;0;ON;;;;;Y;;;;; 2322;FROWN;So;0;ON;;;;;N;;;;; 2323;SMILE;So;0;ON;;;;;N;;;;; 2324;UP ARROWHEAD BETWEEN TWO HORIZONTAL BARS;So;0;ON;;;;;N;ENTER KEY;;;; 2325;OPTION KEY;So;0;ON;;;;;N;;;;; 2326;ERASE TO THE RIGHT;So;0;ON;;;;;N;DELETE TO THE RIGHT KEY;;;; 2327;X IN A RECTANGLE BOX;So;0;ON;;;;;N;CLEAR KEY;;;; 2328;KEYBOARD;So;0;ON;;;;;N;;;;; 2329;LEFT-POINTING ANGLE BRACKET;Ps;0;ON;3008;;;;Y;BRA;;;; 232A;RIGHT-POINTING ANGLE BRACKET;Pe;0;ON;3009;;;;Y;KET;;;; 232B;ERASE TO THE LEFT;So;0;ON;;;;;N;DELETE TO THE LEFT KEY;;;; 232C;BENZENE RING;So;0;ON;;;;;N;;;;; 232D;CYLINDRICITY;So;0;ON;;;;;N;;;;; 232E;ALL AROUND-PROFILE;So;0;ON;;;;;N;;;;; 232F;SYMMETRY;So;0;ON;;;;;N;;;;; 2330;TOTAL RUNOUT;So;0;ON;;;;;N;;;;; 2331;DIMENSION ORIGIN;So;0;ON;;;;;N;;;;; 2332;CONICAL TAPER;So;0;ON;;;;;N;;;;; 2333;SLOPE;So;0;ON;;;;;N;;;;; 2334;COUNTERBORE;So;0;ON;;;;;N;;;;; 2335;COUNTERSINK;So;0;ON;;;;;N;;;;; 2336;APL FUNCTIONAL SYMBOL I-BEAM;So;0;L;;;;;N;;;;; 2337;APL FUNCTIONAL SYMBOL SQUISH QUAD;So;0;L;;;;;N;;;;; 2338;APL FUNCTIONAL SYMBOL QUAD EQUAL;So;0;L;;;;;N;;;;; 2339;APL FUNCTIONAL SYMBOL QUAD DIVIDE;So;0;L;;;;;N;;;;; 233A;APL FUNCTIONAL SYMBOL QUAD DIAMOND;So;0;L;;;;;N;;;;; 233B;APL FUNCTIONAL SYMBOL QUAD JOT;So;0;L;;;;;N;;;;; 233C;APL FUNCTIONAL SYMBOL QUAD CIRCLE;So;0;L;;;;;N;;;;; 233D;APL FUNCTIONAL SYMBOL CIRCLE STILE;So;0;L;;;;;N;;;;; 233E;APL FUNCTIONAL SYMBOL CIRCLE JOT;So;0;L;;;;;N;;;;; 233F;APL FUNCTIONAL SYMBOL SLASH BAR;So;0;L;;;;;N;;;;; 2340;APL FUNCTIONAL SYMBOL BACKSLASH BAR;So;0;L;;;;;N;;;;; 2341;APL FUNCTIONAL SYMBOL QUAD SLASH;So;0;L;;;;;N;;;;; 2342;APL FUNCTIONAL SYMBOL QUAD BACKSLASH;So;0;L;;;;;N;;;;; 2343;APL FUNCTIONAL SYMBOL QUAD LESS-THAN;So;0;L;;;;;N;;;;; 2344;APL FUNCTIONAL SYMBOL QUAD GREATER-THAN;So;0;L;;;;;N;;;;; 2345;APL FUNCTIONAL SYMBOL LEFTWARDS VANE;So;0;L;;;;;N;;;;; 2346;APL FUNCTIONAL SYMBOL RIGHTWARDS VANE;So;0;L;;;;;N;;;;; 2347;APL FUNCTIONAL SYMBOL QUAD LEFTWARDS ARROW;So;0;L;;;;;N;;;;; 2348;APL FUNCTIONAL SYMBOL QUAD RIGHTWARDS ARROW;So;0;L;;;;;N;;;;; 2349;APL FUNCTIONAL SYMBOL CIRCLE BACKSLASH;So;0;L;;;;;N;;;;; 234A;APL FUNCTIONAL SYMBOL DOWN TACK UNDERBAR;So;0;L;;;;;N;;*;;; 234B;APL FUNCTIONAL SYMBOL DELTA STILE;So;0;L;;;;;N;;;;; 234C;APL FUNCTIONAL SYMBOL QUAD DOWN CARET;So;0;L;;;;;N;;;;; 234D;APL FUNCTIONAL SYMBOL QUAD DELTA;So;0;L;;;;;N;;;;; 234E;APL FUNCTIONAL SYMBOL DOWN TACK JOT;So;0;L;;;;;N;;*;;; 234F;APL FUNCTIONAL SYMBOL UPWARDS VANE;So;0;L;;;;;N;;;;; 2350;APL FUNCTIONAL SYMBOL QUAD UPWARDS ARROW;So;0;L;;;;;N;;;;; 2351;APL FUNCTIONAL SYMBOL UP TACK OVERBAR;So;0;L;;;;;N;;*;;; 2352;APL FUNCTIONAL SYMBOL DEL STILE;So;0;L;;;;;N;;;;; 2353;APL FUNCTIONAL SYMBOL QUAD UP CARET;So;0;L;;;;;N;;;;; 2354;APL FUNCTIONAL SYMBOL QUAD DEL;So;0;L;;;;;N;;;;; 2355;APL FUNCTIONAL SYMBOL UP TACK JOT;So;0;L;;;;;N;;*;;; 2356;APL FUNCTIONAL SYMBOL DOWNWARDS VANE;So;0;L;;;;;N;;;;; 2357;APL FUNCTIONAL SYMBOL QUAD DOWNWARDS ARROW;So;0;L;;;;;N;;;;; 2358;APL FUNCTIONAL SYMBOL QUOTE UNDERBAR;So;0;L;;;;;N;;;;; 2359;APL FUNCTIONAL SYMBOL DELTA UNDERBAR;So;0;L;;;;;N;;;;; 235A;APL FUNCTIONAL SYMBOL DIAMOND UNDERBAR;So;0;L;;;;;N;;;;; 235B;APL FUNCTIONAL SYMBOL JOT UNDERBAR;So;0;L;;;;;N;;;;; 235C;APL FUNCTIONAL SYMBOL CIRCLE UNDERBAR;So;0;L;;;;;N;;;;; 235D;APL FUNCTIONAL SYMBOL UP SHOE JOT;So;0;L;;;;;N;;;;; 235E;APL FUNCTIONAL SYMBOL QUOTE QUAD;So;0;L;;;;;N;;;;; 235F;APL FUNCTIONAL SYMBOL CIRCLE STAR;So;0;L;;;;;N;;;;; 2360;APL FUNCTIONAL SYMBOL QUAD COLON;So;0;L;;;;;N;;;;; 2361;APL FUNCTIONAL SYMBOL UP TACK DIAERESIS;So;0;L;;;;;N;;*;;; 2362;APL FUNCTIONAL SYMBOL DEL DIAERESIS;So;0;L;;;;;N;;;;; 2363;APL FUNCTIONAL SYMBOL STAR DIAERESIS;So;0;L;;;;;N;;;;; 2364;APL FUNCTIONAL SYMBOL JOT DIAERESIS;So;0;L;;;;;N;;;;; 2365;APL FUNCTIONAL SYMBOL CIRCLE DIAERESIS;So;0;L;;;;;N;;;;; 2366;APL FUNCTIONAL SYMBOL DOWN SHOE STILE;So;0;L;;;;;N;;;;; 2367;APL FUNCTIONAL SYMBOL LEFT SHOE STILE;So;0;L;;;;;N;;;;; 2368;APL FUNCTIONAL SYMBOL TILDE DIAERESIS;So;0;L;;;;;N;;;;; 2369;APL FUNCTIONAL SYMBOL GREATER-THAN DIAERESIS;So;0;L;;;;;N;;;;; 236A;APL FUNCTIONAL SYMBOL COMMA BAR;So;0;L;;;;;N;;;;; 236B;APL FUNCTIONAL SYMBOL DEL TILDE;So;0;L;;;;;N;;;;; 236C;APL FUNCTIONAL SYMBOL ZILDE;So;0;L;;;;;N;;;;; 236D;APL FUNCTIONAL SYMBOL STILE TILDE;So;0;L;;;;;N;;;;; 236E;APL FUNCTIONAL SYMBOL SEMICOLON UNDERBAR;So;0;L;;;;;N;;;;; 236F;APL FUNCTIONAL SYMBOL QUAD NOT EQUAL;So;0;L;;;;;N;;;;; 2370;APL FUNCTIONAL SYMBOL QUAD QUESTION;So;0;L;;;;;N;;;;; 2371;APL FUNCTIONAL SYMBOL DOWN CARET TILDE;So;0;L;;;;;N;;;;; 2372;APL FUNCTIONAL SYMBOL UP CARET TILDE;So;0;L;;;;;N;;;;; 2373;APL FUNCTIONAL SYMBOL IOTA;So;0;L;;;;;N;;;;; 2374;APL FUNCTIONAL SYMBOL RHO;So;0;L;;;;;N;;;;; 2375;APL FUNCTIONAL SYMBOL OMEGA;So;0;L;;;;;N;;;;; 2376;APL FUNCTIONAL SYMBOL ALPHA UNDERBAR;So;0;L;;;;;N;;;;; 2377;APL FUNCTIONAL SYMBOL EPSILON UNDERBAR;So;0;L;;;;;N;;;;; 2378;APL FUNCTIONAL SYMBOL IOTA UNDERBAR;So;0;L;;;;;N;;;;; 2379;APL FUNCTIONAL SYMBOL OMEGA UNDERBAR;So;0;L;;;;;N;;;;; 237A;APL FUNCTIONAL SYMBOL ALPHA;So;0;L;;;;;N;;;;; 237B;NOT CHECK MARK;So;0;ON;;;;;N;;;;; 237C;RIGHT ANGLE WITH DOWNWARDS ZIGZAG ARROW;Sm;0;ON;;;;;N;;;;; 237D;SHOULDERED OPEN BOX;So;0;ON;;;;;N;;;;; 237E;BELL SYMBOL;So;0;ON;;;;;N;;;;; 237F;VERTICAL LINE WITH MIDDLE DOT;So;0;ON;;;;;N;;;;; 2380;INSERTION SYMBOL;So;0;ON;;;;;N;;;;; 2381;CONTINUOUS UNDERLINE SYMBOL;So;0;ON;;;;;N;;;;; 2382;DISCONTINUOUS UNDERLINE SYMBOL;So;0;ON;;;;;N;;;;; 2383;EMPHASIS SYMBOL;So;0;ON;;;;;N;;;;; 2384;COMPOSITION SYMBOL;So;0;ON;;;;;N;;;;; 2385;WHITE SQUARE WITH CENTRE VERTICAL LINE;So;0;ON;;;;;N;;;;; 2386;ENTER SYMBOL;So;0;ON;;;;;N;;;;; 2387;ALTERNATIVE KEY SYMBOL;So;0;ON;;;;;N;;;;; 2388;HELM SYMBOL;So;0;ON;;;;;N;;;;; 2389;CIRCLED HORIZONTAL BAR WITH NOTCH;So;0;ON;;;;;N;;pause;;; 238A;CIRCLED TRIANGLE DOWN;So;0;ON;;;;;N;;break;;; 238B;BROKEN CIRCLE WITH NORTHWEST ARROW;So;0;ON;;;;;N;;escape;;; 238C;UNDO SYMBOL;So;0;ON;;;;;N;;;;; 238D;MONOSTABLE SYMBOL;So;0;ON;;;;;N;;;;; 238E;HYSTERESIS SYMBOL;So;0;ON;;;;;N;;;;; 238F;OPEN-CIRCUIT-OUTPUT H-TYPE SYMBOL;So;0;ON;;;;;N;;;;; 2390;OPEN-CIRCUIT-OUTPUT L-TYPE SYMBOL;So;0;ON;;;;;N;;;;; 2391;PASSIVE-PULL-DOWN-OUTPUT SYMBOL;So;0;ON;;;;;N;;;;; 2392;PASSIVE-PULL-UP-OUTPUT SYMBOL;So;0;ON;;;;;N;;;;; 2393;DIRECT CURRENT SYMBOL FORM TWO;So;0;ON;;;;;N;;;;; 2394;SOFTWARE-FUNCTION SYMBOL;So;0;ON;;;;;N;;;;; 2395;APL FUNCTIONAL SYMBOL QUAD;So;0;L;;;;;N;;;;; 2396;DECIMAL SEPARATOR KEY SYMBOL;So;0;ON;;;;;N;;;;; 2397;PREVIOUS PAGE;So;0;ON;;;;;N;;;;; 2398;NEXT PAGE;So;0;ON;;;;;N;;;;; 2399;PRINT SCREEN SYMBOL;So;0;ON;;;;;N;;;;; 239A;CLEAR SCREEN SYMBOL;So;0;ON;;;;;N;;;;; 239B;LEFT PARENTHESIS UPPER HOOK;Sm;0;ON;;;;;N;;;;; 239C;LEFT PARENTHESIS EXTENSION;Sm;0;ON;;;;;N;;;;; 239D;LEFT PARENTHESIS LOWER HOOK;Sm;0;ON;;;;;N;;;;; 239E;RIGHT PARENTHESIS UPPER HOOK;Sm;0;ON;;;;;N;;;;; 239F;RIGHT PARENTHESIS EXTENSION;Sm;0;ON;;;;;N;;;;; 23A0;RIGHT PARENTHESIS LOWER HOOK;Sm;0;ON;;;;;N;;;;; 23A1;LEFT SQUARE BRACKET UPPER CORNER;Sm;0;ON;;;;;N;;;;; 23A2;LEFT SQUARE BRACKET EXTENSION;Sm;0;ON;;;;;N;;;;; 23A3;LEFT SQUARE BRACKET LOWER CORNER;Sm;0;ON;;;;;N;;;;; 23A4;RIGHT SQUARE BRACKET UPPER CORNER;Sm;0;ON;;;;;N;;;;; 23A5;RIGHT SQUARE BRACKET EXTENSION;Sm;0;ON;;;;;N;;;;; 23A6;RIGHT SQUARE BRACKET LOWER CORNER;Sm;0;ON;;;;;N;;;;; 23A7;LEFT CURLY BRACKET UPPER HOOK;Sm;0;ON;;;;;N;;;;; 23A8;LEFT CURLY BRACKET MIDDLE PIECE;Sm;0;ON;;;;;N;;;;; 23A9;LEFT CURLY BRACKET LOWER HOOK;Sm;0;ON;;;;;N;;;;; 23AA;CURLY BRACKET EXTENSION;Sm;0;ON;;;;;N;;;;; 23AB;RIGHT CURLY BRACKET UPPER HOOK;Sm;0;ON;;;;;N;;;;; 23AC;RIGHT CURLY BRACKET MIDDLE PIECE;Sm;0;ON;;;;;N;;;;; 23AD;RIGHT CURLY BRACKET LOWER HOOK;Sm;0;ON;;;;;N;;;;; 23AE;INTEGRAL EXTENSION;Sm;0;ON;;;;;N;;;;; 23AF;HORIZONTAL LINE EXTENSION;Sm;0;ON;;;;;N;;;;; 23B0;UPPER LEFT OR LOWER RIGHT CURLY BRACKET SECTION;Sm;0;ON;;;;;N;;;;; 23B1;UPPER RIGHT OR LOWER LEFT CURLY BRACKET SECTION;Sm;0;ON;;;;;N;;;;; 23B2;SUMMATION TOP;Sm;0;ON;;;;;N;;;;; 23B3;SUMMATION BOTTOM;Sm;0;ON;;;;;N;;;;; 23B4;TOP SQUARE BRACKET;Ps;0;ON;;;;;N;;;;; 23B5;BOTTOM SQUARE BRACKET;Pe;0;ON;;;;;N;;;;; 23B6;BOTTOM SQUARE BRACKET OVER TOP SQUARE BRACKET;Po;0;ON;;;;;N;;;;; 23B7;RADICAL SYMBOL BOTTOM;So;0;ON;;;;;N;;;;; 23B8;LEFT VERTICAL BOX LINE;So;0;ON;;;;;N;;;;; 23B9;RIGHT VERTICAL BOX LINE;So;0;ON;;;;;N;;;;; 23BA;HORIZONTAL SCAN LINE-1;So;0;ON;;;;;N;;;;; 23BB;HORIZONTAL SCAN LINE-3;So;0;ON;;;;;N;;;;; 23BC;HORIZONTAL SCAN LINE-7;So;0;ON;;;;;N;;;;; 23BD;HORIZONTAL SCAN LINE-9;So;0;ON;;;;;N;;;;; 23BE;DENTISTRY SYMBOL LIGHT VERTICAL AND TOP RIGHT;So;0;ON;;;;;N;;;;; 23BF;DENTISTRY SYMBOL LIGHT VERTICAL AND BOTTOM RIGHT;So;0;ON;;;;;N;;;;; 23C0;DENTISTRY SYMBOL LIGHT VERTICAL WITH CIRCLE;So;0;ON;;;;;N;;;;; 23C1;DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL WITH CIRCLE;So;0;ON;;;;;N;;;;; 23C2;DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL WITH CIRCLE;So;0;ON;;;;;N;;;;; 23C3;DENTISTRY SYMBOL LIGHT VERTICAL WITH TRIANGLE;So;0;ON;;;;;N;;;;; 23C4;DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL WITH TRIANGLE;So;0;ON;;;;;N;;;;; 23C5;DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL WITH TRIANGLE;So;0;ON;;;;;N;;;;; 23C6;DENTISTRY SYMBOL LIGHT VERTICAL AND WAVE;So;0;ON;;;;;N;;;;; 23C7;DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL WITH WAVE;So;0;ON;;;;;N;;;;; 23C8;DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL WITH WAVE;So;0;ON;;;;;N;;;;; 23C9;DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL;So;0;ON;;;;;N;;;;; 23CA;DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL;So;0;ON;;;;;N;;;;; 23CB;DENTISTRY SYMBOL LIGHT VERTICAL AND TOP LEFT;So;0;ON;;;;;N;;;;; 23CC;DENTISTRY SYMBOL LIGHT VERTICAL AND BOTTOM LEFT;So;0;ON;;;;;N;;;;; 23CD;SQUARE FOOT;So;0;ON;;;;;N;;;;; 23CE;RETURN SYMBOL;So;0;ON;;;;;N;;;;; 2400;SYMBOL FOR NULL;So;0;ON;;;;;N;GRAPHIC FOR NULL;;;; 2401;SYMBOL FOR START OF HEADING;So;0;ON;;;;;N;GRAPHIC FOR START OF HEADING;;;; 2402;SYMBOL FOR START OF TEXT;So;0;ON;;;;;N;GRAPHIC FOR START OF TEXT;;;; 2403;SYMBOL FOR END OF TEXT;So;0;ON;;;;;N;GRAPHIC FOR END OF TEXT;;;; 2404;SYMBOL FOR END OF TRANSMISSION;So;0;ON;;;;;N;GRAPHIC FOR END OF TRANSMISSION;;;; 2405;SYMBOL FOR ENQUIRY;So;0;ON;;;;;N;GRAPHIC FOR ENQUIRY;;;; 2406;SYMBOL FOR ACKNOWLEDGE;So;0;ON;;;;;N;GRAPHIC FOR ACKNOWLEDGE;;;; 2407;SYMBOL FOR BELL;So;0;ON;;;;;N;GRAPHIC FOR BELL;;;; 2408;SYMBOL FOR BACKSPACE;So;0;ON;;;;;N;GRAPHIC FOR BACKSPACE;;;; 2409;SYMBOL FOR HORIZONTAL TABULATION;So;0;ON;;;;;N;GRAPHIC FOR HORIZONTAL TABULATION;;;; 240A;SYMBOL FOR LINE FEED;So;0;ON;;;;;N;GRAPHIC FOR LINE FEED;;;; 240B;SYMBOL FOR VERTICAL TABULATION;So;0;ON;;;;;N;GRAPHIC FOR VERTICAL TABULATION;;;; 240C;SYMBOL FOR FORM FEED;So;0;ON;;;;;N;GRAPHIC FOR FORM FEED;;;; 240D;SYMBOL FOR CARRIAGE RETURN;So;0;ON;;;;;N;GRAPHIC FOR CARRIAGE RETURN;;;; 240E;SYMBOL FOR SHIFT OUT;So;0;ON;;;;;N;GRAPHIC FOR SHIFT OUT;;;; 240F;SYMBOL FOR SHIFT IN;So;0;ON;;;;;N;GRAPHIC FOR SHIFT IN;;;; 2410;SYMBOL FOR DATA LINK ESCAPE;So;0;ON;;;;;N;GRAPHIC FOR DATA LINK ESCAPE;;;; 2411;SYMBOL FOR DEVICE CONTROL ONE;So;0;ON;;;;;N;GRAPHIC FOR DEVICE CONTROL ONE;;;; 2412;SYMBOL FOR DEVICE CONTROL TWO;So;0;ON;;;;;N;GRAPHIC FOR DEVICE CONTROL TWO;;;; 2413;SYMBOL FOR DEVICE CONTROL THREE;So;0;ON;;;;;N;GRAPHIC FOR DEVICE CONTROL THREE;;;; 2414;SYMBOL FOR DEVICE CONTROL FOUR;So;0;ON;;;;;N;GRAPHIC FOR DEVICE CONTROL FOUR;;;; 2415;SYMBOL FOR NEGATIVE ACKNOWLEDGE;So;0;ON;;;;;N;GRAPHIC FOR NEGATIVE ACKNOWLEDGE;;;; 2416;SYMBOL FOR SYNCHRONOUS IDLE;So;0;ON;;;;;N;GRAPHIC FOR SYNCHRONOUS IDLE;;;; 2417;SYMBOL FOR END OF TRANSMISSION BLOCK;So;0;ON;;;;;N;GRAPHIC FOR END OF TRANSMISSION BLOCK;;;; 2418;SYMBOL FOR CANCEL;So;0;ON;;;;;N;GRAPHIC FOR CANCEL;;;; 2419;SYMBOL FOR END OF MEDIUM;So;0;ON;;;;;N;GRAPHIC FOR END OF MEDIUM;;;; 241A;SYMBOL FOR SUBSTITUTE;So;0;ON;;;;;N;GRAPHIC FOR SUBSTITUTE;;;; 241B;SYMBOL FOR ESCAPE;So;0;ON;;;;;N;GRAPHIC FOR ESCAPE;;;; 241C;SYMBOL FOR FILE SEPARATOR;So;0;ON;;;;;N;GRAPHIC FOR FILE SEPARATOR;;;; 241D;SYMBOL FOR GROUP SEPARATOR;So;0;ON;;;;;N;GRAPHIC FOR GROUP SEPARATOR;;;; 241E;SYMBOL FOR RECORD SEPARATOR;So;0;ON;;;;;N;GRAPHIC FOR RECORD SEPARATOR;;;; 241F;SYMBOL FOR UNIT SEPARATOR;So;0;ON;;;;;N;GRAPHIC FOR UNIT SEPARATOR;;;; 2420;SYMBOL FOR SPACE;So;0;ON;;;;;N;GRAPHIC FOR SPACE;;;; 2421;SYMBOL FOR DELETE;So;0;ON;;;;;N;GRAPHIC FOR DELETE;;;; 2422;BLANK SYMBOL;So;0;ON;;;;;N;BLANK;;;; 2423;OPEN BOX;So;0;ON;;;;;N;;;;; 2424;SYMBOL FOR NEWLINE;So;0;ON;;;;;N;GRAPHIC FOR NEWLINE;;;; 2425;SYMBOL FOR DELETE FORM TWO;So;0;ON;;;;;N;;;;; 2426;SYMBOL FOR SUBSTITUTE FORM TWO;So;0;ON;;;;;N;;;;; 2440;OCR HOOK;So;0;ON;;;;;N;;;;; 2441;OCR CHAIR;So;0;ON;;;;;N;;;;; 2442;OCR FORK;So;0;ON;;;;;N;;;;; 2443;OCR INVERTED FORK;So;0;ON;;;;;N;;;;; 2444;OCR BELT BUCKLE;So;0;ON;;;;;N;;;;; 2445;OCR BOW TIE;So;0;ON;;;;;N;;;;; 2446;OCR BRANCH BANK IDENTIFICATION;So;0;ON;;;;;N;;;;; 2447;OCR AMOUNT OF CHECK;So;0;ON;;;;;N;;;;; 2448;OCR DASH;So;0;ON;;;;;N;;;;; 2449;OCR CUSTOMER ACCOUNT NUMBER;So;0;ON;;;;;N;;;;; 244A;OCR DOUBLE BACKSLASH;So;0;ON;;;;;N;;;;; 2460;CIRCLED DIGIT ONE;No;0;EN; 0031;;1;1;N;;;;; 2461;CIRCLED DIGIT TWO;No;0;EN; 0032;;2;2;N;;;;; 2462;CIRCLED DIGIT THREE;No;0;EN; 0033;;3;3;N;;;;; 2463;CIRCLED DIGIT FOUR;No;0;EN; 0034;;4;4;N;;;;; 2464;CIRCLED DIGIT FIVE;No;0;EN; 0035;;5;5;N;;;;; 2465;CIRCLED DIGIT SIX;No;0;EN; 0036;;6;6;N;;;;; 2466;CIRCLED DIGIT SEVEN;No;0;EN; 0037;;7;7;N;;;;; 2467;CIRCLED DIGIT EIGHT;No;0;EN; 0038;;8;8;N;;;;; 2468;CIRCLED DIGIT NINE;No;0;EN; 0039;;9;9;N;;;;; 2469;CIRCLED NUMBER TEN;No;0;EN; 0031 0030;;;10;N;;;;; 246A;CIRCLED NUMBER ELEVEN;No;0;EN; 0031 0031;;;11;N;;;;; 246B;CIRCLED NUMBER TWELVE;No;0;EN; 0031 0032;;;12;N;;;;; 246C;CIRCLED NUMBER THIRTEEN;No;0;EN; 0031 0033;;;13;N;;;;; 246D;CIRCLED NUMBER FOURTEEN;No;0;EN; 0031 0034;;;14;N;;;;; 246E;CIRCLED NUMBER FIFTEEN;No;0;EN; 0031 0035;;;15;N;;;;; 246F;CIRCLED NUMBER SIXTEEN;No;0;EN; 0031 0036;;;16;N;;;;; 2470;CIRCLED NUMBER SEVENTEEN;No;0;EN; 0031 0037;;;17;N;;;;; 2471;CIRCLED NUMBER EIGHTEEN;No;0;EN; 0031 0038;;;18;N;;;;; 2472;CIRCLED NUMBER NINETEEN;No;0;EN; 0031 0039;;;19;N;;;;; 2473;CIRCLED NUMBER TWENTY;No;0;EN; 0032 0030;;;20;N;;;;; 2474;PARENTHESIZED DIGIT ONE;No;0;EN; 0028 0031 0029;;1;1;N;;;;; 2475;PARENTHESIZED DIGIT TWO;No;0;EN; 0028 0032 0029;;2;2;N;;;;; 2476;PARENTHESIZED DIGIT THREE;No;0;EN; 0028 0033 0029;;3;3;N;;;;; 2477;PARENTHESIZED DIGIT FOUR;No;0;EN; 0028 0034 0029;;4;4;N;;;;; 2478;PARENTHESIZED DIGIT FIVE;No;0;EN; 0028 0035 0029;;5;5;N;;;;; 2479;PARENTHESIZED DIGIT SIX;No;0;EN; 0028 0036 0029;;6;6;N;;;;; 247A;PARENTHESIZED DIGIT SEVEN;No;0;EN; 0028 0037 0029;;7;7;N;;;;; 247B;PARENTHESIZED DIGIT EIGHT;No;0;EN; 0028 0038 0029;;8;8;N;;;;; 247C;PARENTHESIZED DIGIT NINE;No;0;EN; 0028 0039 0029;;9;9;N;;;;; 247D;PARENTHESIZED NUMBER TEN;No;0;EN; 0028 0031 0030 0029;;;10;N;;;;; 247E;PARENTHESIZED NUMBER ELEVEN;No;0;EN; 0028 0031 0031 0029;;;11;N;;;;; 247F;PARENTHESIZED NUMBER TWELVE;No;0;EN; 0028 0031 0032 0029;;;12;N;;;;; 2480;PARENTHESIZED NUMBER THIRTEEN;No;0;EN; 0028 0031 0033 0029;;;13;N;;;;; 2481;PARENTHESIZED NUMBER FOURTEEN;No;0;EN; 0028 0031 0034 0029;;;14;N;;;;; 2482;PARENTHESIZED NUMBER FIFTEEN;No;0;EN; 0028 0031 0035 0029;;;15;N;;;;; 2483;PARENTHESIZED NUMBER SIXTEEN;No;0;EN; 0028 0031 0036 0029;;;16;N;;;;; 2484;PARENTHESIZED NUMBER SEVENTEEN;No;0;EN; 0028 0031 0037 0029;;;17;N;;;;; 2485;PARENTHESIZED NUMBER EIGHTEEN;No;0;EN; 0028 0031 0038 0029;;;18;N;;;;; 2486;PARENTHESIZED NUMBER NINETEEN;No;0;EN; 0028 0031 0039 0029;;;19;N;;;;; 2487;PARENTHESIZED NUMBER TWENTY;No;0;EN; 0028 0032 0030 0029;;;20;N;;;;; 2488;DIGIT ONE FULL STOP;No;0;EN; 0031 002E;;1;1;N;DIGIT ONE PERIOD;;;; 2489;DIGIT TWO FULL STOP;No;0;EN; 0032 002E;;2;2;N;DIGIT TWO PERIOD;;;; 248A;DIGIT THREE FULL STOP;No;0;EN; 0033 002E;;3;3;N;DIGIT THREE PERIOD;;;; 248B;DIGIT FOUR FULL STOP;No;0;EN; 0034 002E;;4;4;N;DIGIT FOUR PERIOD;;;; 248C;DIGIT FIVE FULL STOP;No;0;EN; 0035 002E;;5;5;N;DIGIT FIVE PERIOD;;;; 248D;DIGIT SIX FULL STOP;No;0;EN; 0036 002E;;6;6;N;DIGIT SIX PERIOD;;;; 248E;DIGIT SEVEN FULL STOP;No;0;EN; 0037 002E;;7;7;N;DIGIT SEVEN PERIOD;;;; 248F;DIGIT EIGHT FULL STOP;No;0;EN; 0038 002E;;8;8;N;DIGIT EIGHT PERIOD;;;; 2490;DIGIT NINE FULL STOP;No;0;EN; 0039 002E;;9;9;N;DIGIT NINE PERIOD;;;; 2491;NUMBER TEN FULL STOP;No;0;EN; 0031 0030 002E;;;10;N;NUMBER TEN PERIOD;;;; 2492;NUMBER ELEVEN FULL STOP;No;0;EN; 0031 0031 002E;;;11;N;NUMBER ELEVEN PERIOD;;;; 2493;NUMBER TWELVE FULL STOP;No;0;EN; 0031 0032 002E;;;12;N;NUMBER TWELVE PERIOD;;;; 2494;NUMBER THIRTEEN FULL STOP;No;0;EN; 0031 0033 002E;;;13;N;NUMBER THIRTEEN PERIOD;;;; 2495;NUMBER FOURTEEN FULL STOP;No;0;EN; 0031 0034 002E;;;14;N;NUMBER FOURTEEN PERIOD;;;; 2496;NUMBER FIFTEEN FULL STOP;No;0;EN; 0031 0035 002E;;;15;N;NUMBER FIFTEEN PERIOD;;;; 2497;NUMBER SIXTEEN FULL STOP;No;0;EN; 0031 0036 002E;;;16;N;NUMBER SIXTEEN PERIOD;;;; 2498;NUMBER SEVENTEEN FULL STOP;No;0;EN; 0031 0037 002E;;;17;N;NUMBER SEVENTEEN PERIOD;;;; 2499;NUMBER EIGHTEEN FULL STOP;No;0;EN; 0031 0038 002E;;;18;N;NUMBER EIGHTEEN PERIOD;;;; 249A;NUMBER NINETEEN FULL STOP;No;0;EN; 0031 0039 002E;;;19;N;NUMBER NINETEEN PERIOD;;;; 249B;NUMBER TWENTY FULL STOP;No;0;EN; 0032 0030 002E;;;20;N;NUMBER TWENTY PERIOD;;;; 249C;PARENTHESIZED LATIN SMALL LETTER A;So;0;L; 0028 0061 0029;;;;N;;;;; 249D;PARENTHESIZED LATIN SMALL LETTER B;So;0;L; 0028 0062 0029;;;;N;;;;; 249E;PARENTHESIZED LATIN SMALL LETTER C;So;0;L; 0028 0063 0029;;;;N;;;;; 249F;PARENTHESIZED LATIN SMALL LETTER D;So;0;L; 0028 0064 0029;;;;N;;;;; 24A0;PARENTHESIZED LATIN SMALL LETTER E;So;0;L; 0028 0065 0029;;;;N;;;;; 24A1;PARENTHESIZED LATIN SMALL LETTER F;So;0;L; 0028 0066 0029;;;;N;;;;; 24A2;PARENTHESIZED LATIN SMALL LETTER G;So;0;L; 0028 0067 0029;;;;N;;;;; 24A3;PARENTHESIZED LATIN SMALL LETTER H;So;0;L; 0028 0068 0029;;;;N;;;;; 24A4;PARENTHESIZED LATIN SMALL LETTER I;So;0;L; 0028 0069 0029;;;;N;;;;; 24A5;PARENTHESIZED LATIN SMALL LETTER J;So;0;L; 0028 006A 0029;;;;N;;;;; 24A6;PARENTHESIZED LATIN SMALL LETTER K;So;0;L; 0028 006B 0029;;;;N;;;;; 24A7;PARENTHESIZED LATIN SMALL LETTER L;So;0;L; 0028 006C 0029;;;;N;;;;; 24A8;PARENTHESIZED LATIN SMALL LETTER M;So;0;L; 0028 006D 0029;;;;N;;;;; 24A9;PARENTHESIZED LATIN SMALL LETTER N;So;0;L; 0028 006E 0029;;;;N;;;;; 24AA;PARENTHESIZED LATIN SMALL LETTER O;So;0;L; 0028 006F 0029;;;;N;;;;; 24AB;PARENTHESIZED LATIN SMALL LETTER P;So;0;L; 0028 0070 0029;;;;N;;;;; 24AC;PARENTHESIZED LATIN SMALL LETTER Q;So;0;L; 0028 0071 0029;;;;N;;;;; 24AD;PARENTHESIZED LATIN SMALL LETTER R;So;0;L; 0028 0072 0029;;;;N;;;;; 24AE;PARENTHESIZED LATIN SMALL LETTER S;So;0;L; 0028 0073 0029;;;;N;;;;; 24AF;PARENTHESIZED LATIN SMALL LETTER T;So;0;L; 0028 0074 0029;;;;N;;;;; 24B0;PARENTHESIZED LATIN SMALL LETTER U;So;0;L; 0028 0075 0029;;;;N;;;;; 24B1;PARENTHESIZED LATIN SMALL LETTER V;So;0;L; 0028 0076 0029;;;;N;;;;; 24B2;PARENTHESIZED LATIN SMALL LETTER W;So;0;L; 0028 0077 0029;;;;N;;;;; 24B3;PARENTHESIZED LATIN SMALL LETTER X;So;0;L; 0028 0078 0029;;;;N;;;;; 24B4;PARENTHESIZED LATIN SMALL LETTER Y;So;0;L; 0028 0079 0029;;;;N;;;;; 24B5;PARENTHESIZED LATIN SMALL LETTER Z;So;0;L; 0028 007A 0029;;;;N;;;;; 24B6;CIRCLED LATIN CAPITAL LETTER A;So;0;L; 0041;;;;N;;;;24D0; 24B7;CIRCLED LATIN CAPITAL LETTER B;So;0;L; 0042;;;;N;;;;24D1; 24B8;CIRCLED LATIN CAPITAL LETTER C;So;0;L; 0043;;;;N;;;;24D2; 24B9;CIRCLED LATIN CAPITAL LETTER D;So;0;L; 0044;;;;N;;;;24D3; 24BA;CIRCLED LATIN CAPITAL LETTER E;So;0;L; 0045;;;;N;;;;24D4; 24BB;CIRCLED LATIN CAPITAL LETTER F;So;0;L; 0046;;;;N;;;;24D5; 24BC;CIRCLED LATIN CAPITAL LETTER G;So;0;L; 0047;;;;N;;;;24D6; 24BD;CIRCLED LATIN CAPITAL LETTER H;So;0;L; 0048;;;;N;;;;24D7; 24BE;CIRCLED LATIN CAPITAL LETTER I;So;0;L; 0049;;;;N;;;;24D8; 24BF;CIRCLED LATIN CAPITAL LETTER J;So;0;L; 004A;;;;N;;;;24D9; 24C0;CIRCLED LATIN CAPITAL LETTER K;So;0;L; 004B;;;;N;;;;24DA; 24C1;CIRCLED LATIN CAPITAL LETTER L;So;0;L; 004C;;;;N;;;;24DB; 24C2;CIRCLED LATIN CAPITAL LETTER M;So;0;L; 004D;;;;N;;;;24DC; 24C3;CIRCLED LATIN CAPITAL LETTER N;So;0;L; 004E;;;;N;;;;24DD; 24C4;CIRCLED LATIN CAPITAL LETTER O;So;0;L; 004F;;;;N;;;;24DE; 24C5;CIRCLED LATIN CAPITAL LETTER P;So;0;L; 0050;;;;N;;;;24DF; 24C6;CIRCLED LATIN CAPITAL LETTER Q;So;0;L; 0051;;;;N;;;;24E0; 24C7;CIRCLED LATIN CAPITAL LETTER R;So;0;L; 0052;;;;N;;;;24E1; 24C8;CIRCLED LATIN CAPITAL LETTER S;So;0;L; 0053;;;;N;;;;24E2; 24C9;CIRCLED LATIN CAPITAL LETTER T;So;0;L; 0054;;;;N;;;;24E3; 24CA;CIRCLED LATIN CAPITAL LETTER U;So;0;L; 0055;;;;N;;;;24E4; 24CB;CIRCLED LATIN CAPITAL LETTER V;So;0;L; 0056;;;;N;;;;24E5; 24CC;CIRCLED LATIN CAPITAL LETTER W;So;0;L; 0057;;;;N;;;;24E6; 24CD;CIRCLED LATIN CAPITAL LETTER X;So;0;L; 0058;;;;N;;;;24E7; 24CE;CIRCLED LATIN CAPITAL LETTER Y;So;0;L; 0059;;;;N;;;;24E8; 24CF;CIRCLED LATIN CAPITAL LETTER Z;So;0;L; 005A;;;;N;;;;24E9; 24D0;CIRCLED LATIN SMALL LETTER A;So;0;L; 0061;;;;N;;;24B6;;24B6 24D1;CIRCLED LATIN SMALL LETTER B;So;0;L; 0062;;;;N;;;24B7;;24B7 24D2;CIRCLED LATIN SMALL LETTER C;So;0;L; 0063;;;;N;;;24B8;;24B8 24D3;CIRCLED LATIN SMALL LETTER D;So;0;L; 0064;;;;N;;;24B9;;24B9 24D4;CIRCLED LATIN SMALL LETTER E;So;0;L; 0065;;;;N;;;24BA;;24BA 24D5;CIRCLED LATIN SMALL LETTER F;So;0;L; 0066;;;;N;;;24BB;;24BB 24D6;CIRCLED LATIN SMALL LETTER G;So;0;L; 0067;;;;N;;;24BC;;24BC 24D7;CIRCLED LATIN SMALL LETTER H;So;0;L; 0068;;;;N;;;24BD;;24BD 24D8;CIRCLED LATIN SMALL LETTER I;So;0;L; 0069;;;;N;;;24BE;;24BE 24D9;CIRCLED LATIN SMALL LETTER J;So;0;L; 006A;;;;N;;;24BF;;24BF 24DA;CIRCLED LATIN SMALL LETTER K;So;0;L; 006B;;;;N;;;24C0;;24C0 24DB;CIRCLED LATIN SMALL LETTER L;So;0;L; 006C;;;;N;;;24C1;;24C1 24DC;CIRCLED LATIN SMALL LETTER M;So;0;L; 006D;;;;N;;;24C2;;24C2 24DD;CIRCLED LATIN SMALL LETTER N;So;0;L; 006E;;;;N;;;24C3;;24C3 24DE;CIRCLED LATIN SMALL LETTER O;So;0;L; 006F;;;;N;;;24C4;;24C4 24DF;CIRCLED LATIN SMALL LETTER P;So;0;L; 0070;;;;N;;;24C5;;24C5 24E0;CIRCLED LATIN SMALL LETTER Q;So;0;L; 0071;;;;N;;;24C6;;24C6 24E1;CIRCLED LATIN SMALL LETTER R;So;0;L; 0072;;;;N;;;24C7;;24C7 24E2;CIRCLED LATIN SMALL LETTER S;So;0;L; 0073;;;;N;;;24C8;;24C8 24E3;CIRCLED LATIN SMALL LETTER T;So;0;L; 0074;;;;N;;;24C9;;24C9 24E4;CIRCLED LATIN SMALL LETTER U;So;0;L; 0075;;;;N;;;24CA;;24CA 24E5;CIRCLED LATIN SMALL LETTER V;So;0;L; 0076;;;;N;;;24CB;;24CB 24E6;CIRCLED LATIN SMALL LETTER W;So;0;L; 0077;;;;N;;;24CC;;24CC 24E7;CIRCLED LATIN SMALL LETTER X;So;0;L; 0078;;;;N;;;24CD;;24CD 24E8;CIRCLED LATIN SMALL LETTER Y;So;0;L; 0079;;;;N;;;24CE;;24CE 24E9;CIRCLED LATIN SMALL LETTER Z;So;0;L; 007A;;;;N;;;24CF;;24CF 24EA;CIRCLED DIGIT ZERO;No;0;EN; 0030;;0;0;N;;;;; 24EB;NEGATIVE CIRCLED NUMBER ELEVEN;No;0;ON;;;;11;N;;;;; 24EC;NEGATIVE CIRCLED NUMBER TWELVE;No;0;ON;;;;12;N;;;;; 24ED;NEGATIVE CIRCLED NUMBER THIRTEEN;No;0;ON;;;;13;N;;;;; 24EE;NEGATIVE CIRCLED NUMBER FOURTEEN;No;0;ON;;;;14;N;;;;; 24EF;NEGATIVE CIRCLED NUMBER FIFTEEN;No;0;ON;;;;15;N;;;;; 24F0;NEGATIVE CIRCLED NUMBER SIXTEEN;No;0;ON;;;;16;N;;;;; 24F1;NEGATIVE CIRCLED NUMBER SEVENTEEN;No;0;ON;;;;17;N;;;;; 24F2;NEGATIVE CIRCLED NUMBER EIGHTEEN;No;0;ON;;;;18;N;;;;; 24F3;NEGATIVE CIRCLED NUMBER NINETEEN;No;0;ON;;;;19;N;;;;; 24F4;NEGATIVE CIRCLED NUMBER TWENTY;No;0;ON;;;;20;N;;;;; 24F5;DOUBLE CIRCLED DIGIT ONE;No;0;ON;;;1;1;N;;;;; 24F6;DOUBLE CIRCLED DIGIT TWO;No;0;ON;;;2;2;N;;;;; 24F7;DOUBLE CIRCLED DIGIT THREE;No;0;ON;;;3;3;N;;;;; 24F8;DOUBLE CIRCLED DIGIT FOUR;No;0;ON;;;4;4;N;;;;; 24F9;DOUBLE CIRCLED DIGIT FIVE;No;0;ON;;;5;5;N;;;;; 24FA;DOUBLE CIRCLED DIGIT SIX;No;0;ON;;;6;6;N;;;;; 24FB;DOUBLE CIRCLED DIGIT SEVEN;No;0;ON;;;7;7;N;;;;; 24FC;DOUBLE CIRCLED DIGIT EIGHT;No;0;ON;;;8;8;N;;;;; 24FD;DOUBLE CIRCLED DIGIT NINE;No;0;ON;;;9;9;N;;;;; 24FE;DOUBLE CIRCLED NUMBER TEN;No;0;ON;;;;10;N;;;;; 2500;BOX DRAWINGS LIGHT HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT HORIZONTAL;;;; 2501;BOX DRAWINGS HEAVY HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY HORIZONTAL;;;; 2502;BOX DRAWINGS LIGHT VERTICAL;So;0;ON;;;;;N;FORMS LIGHT VERTICAL;;;; 2503;BOX DRAWINGS HEAVY VERTICAL;So;0;ON;;;;;N;FORMS HEAVY VERTICAL;;;; 2504;BOX DRAWINGS LIGHT TRIPLE DASH HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT TRIPLE DASH HORIZONTAL;;;; 2505;BOX DRAWINGS HEAVY TRIPLE DASH HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY TRIPLE DASH HORIZONTAL;;;; 2506;BOX DRAWINGS LIGHT TRIPLE DASH VERTICAL;So;0;ON;;;;;N;FORMS LIGHT TRIPLE DASH VERTICAL;;;; 2507;BOX DRAWINGS HEAVY TRIPLE DASH VERTICAL;So;0;ON;;;;;N;FORMS HEAVY TRIPLE DASH VERTICAL;;;; 2508;BOX DRAWINGS LIGHT QUADRUPLE DASH HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT QUADRUPLE DASH HORIZONTAL;;;; 2509;BOX DRAWINGS HEAVY QUADRUPLE DASH HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY QUADRUPLE DASH HORIZONTAL;;;; 250A;BOX DRAWINGS LIGHT QUADRUPLE DASH VERTICAL;So;0;ON;;;;;N;FORMS LIGHT QUADRUPLE DASH VERTICAL;;;; 250B;BOX DRAWINGS HEAVY QUADRUPLE DASH VERTICAL;So;0;ON;;;;;N;FORMS HEAVY QUADRUPLE DASH VERTICAL;;;; 250C;BOX DRAWINGS LIGHT DOWN AND RIGHT;So;0;ON;;;;;N;FORMS LIGHT DOWN AND RIGHT;;;; 250D;BOX DRAWINGS DOWN LIGHT AND RIGHT HEAVY;So;0;ON;;;;;N;FORMS DOWN LIGHT AND RIGHT HEAVY;;;; 250E;BOX DRAWINGS DOWN HEAVY AND RIGHT LIGHT;So;0;ON;;;;;N;FORMS DOWN HEAVY AND RIGHT LIGHT;;;; 250F;BOX DRAWINGS HEAVY DOWN AND RIGHT;So;0;ON;;;;;N;FORMS HEAVY DOWN AND RIGHT;;;; 2510;BOX DRAWINGS LIGHT DOWN AND LEFT;So;0;ON;;;;;N;FORMS LIGHT DOWN AND LEFT;;;; 2511;BOX DRAWINGS DOWN LIGHT AND LEFT HEAVY;So;0;ON;;;;;N;FORMS DOWN LIGHT AND LEFT HEAVY;;;; 2512;BOX DRAWINGS DOWN HEAVY AND LEFT LIGHT;So;0;ON;;;;;N;FORMS DOWN HEAVY AND LEFT LIGHT;;;; 2513;BOX DRAWINGS HEAVY DOWN AND LEFT;So;0;ON;;;;;N;FORMS HEAVY DOWN AND LEFT;;;; 2514;BOX DRAWINGS LIGHT UP AND RIGHT;So;0;ON;;;;;N;FORMS LIGHT UP AND RIGHT;;;; 2515;BOX DRAWINGS UP LIGHT AND RIGHT HEAVY;So;0;ON;;;;;N;FORMS UP LIGHT AND RIGHT HEAVY;;;; 2516;BOX DRAWINGS UP HEAVY AND RIGHT LIGHT;So;0;ON;;;;;N;FORMS UP HEAVY AND RIGHT LIGHT;;;; 2517;BOX DRAWINGS HEAVY UP AND RIGHT;So;0;ON;;;;;N;FORMS HEAVY UP AND RIGHT;;;; 2518;BOX DRAWINGS LIGHT UP AND LEFT;So;0;ON;;;;;N;FORMS LIGHT UP AND LEFT;;;; 2519;BOX DRAWINGS UP LIGHT AND LEFT HEAVY;So;0;ON;;;;;N;FORMS UP LIGHT AND LEFT HEAVY;;;; 251A;BOX DRAWINGS UP HEAVY AND LEFT LIGHT;So;0;ON;;;;;N;FORMS UP HEAVY AND LEFT LIGHT;;;; 251B;BOX DRAWINGS HEAVY UP AND LEFT;So;0;ON;;;;;N;FORMS HEAVY UP AND LEFT;;;; 251C;BOX DRAWINGS LIGHT VERTICAL AND RIGHT;So;0;ON;;;;;N;FORMS LIGHT VERTICAL AND RIGHT;;;; 251D;BOX DRAWINGS VERTICAL LIGHT AND RIGHT HEAVY;So;0;ON;;;;;N;FORMS VERTICAL LIGHT AND RIGHT HEAVY;;;; 251E;BOX DRAWINGS UP HEAVY AND RIGHT DOWN LIGHT;So;0;ON;;;;;N;FORMS UP HEAVY AND RIGHT DOWN LIGHT;;;; 251F;BOX DRAWINGS DOWN HEAVY AND RIGHT UP LIGHT;So;0;ON;;;;;N;FORMS DOWN HEAVY AND RIGHT UP LIGHT;;;; 2520;BOX DRAWINGS VERTICAL HEAVY AND RIGHT LIGHT;So;0;ON;;;;;N;FORMS VERTICAL HEAVY AND RIGHT LIGHT;;;; 2521;BOX DRAWINGS DOWN LIGHT AND RIGHT UP HEAVY;So;0;ON;;;;;N;FORMS DOWN LIGHT AND RIGHT UP HEAVY;;;; 2522;BOX DRAWINGS UP LIGHT AND RIGHT DOWN HEAVY;So;0;ON;;;;;N;FORMS UP LIGHT AND RIGHT DOWN HEAVY;;;; 2523;BOX DRAWINGS HEAVY VERTICAL AND RIGHT;So;0;ON;;;;;N;FORMS HEAVY VERTICAL AND RIGHT;;;; 2524;BOX DRAWINGS LIGHT VERTICAL AND LEFT;So;0;ON;;;;;N;FORMS LIGHT VERTICAL AND LEFT;;;; 2525;BOX DRAWINGS VERTICAL LIGHT AND LEFT HEAVY;So;0;ON;;;;;N;FORMS VERTICAL LIGHT AND LEFT HEAVY;;;; 2526;BOX DRAWINGS UP HEAVY AND LEFT DOWN LIGHT;So;0;ON;;;;;N;FORMS UP HEAVY AND LEFT DOWN LIGHT;;;; 2527;BOX DRAWINGS DOWN HEAVY AND LEFT UP LIGHT;So;0;ON;;;;;N;FORMS DOWN HEAVY AND LEFT UP LIGHT;;;; 2528;BOX DRAWINGS VERTICAL HEAVY AND LEFT LIGHT;So;0;ON;;;;;N;FORMS VERTICAL HEAVY AND LEFT LIGHT;;;; 2529;BOX DRAWINGS DOWN LIGHT AND LEFT UP HEAVY;So;0;ON;;;;;N;FORMS DOWN LIGHT AND LEFT UP HEAVY;;;; 252A;BOX DRAWINGS UP LIGHT AND LEFT DOWN HEAVY;So;0;ON;;;;;N;FORMS UP LIGHT AND LEFT DOWN HEAVY;;;; 252B;BOX DRAWINGS HEAVY VERTICAL AND LEFT;So;0;ON;;;;;N;FORMS HEAVY VERTICAL AND LEFT;;;; 252C;BOX DRAWINGS LIGHT DOWN AND HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT DOWN AND HORIZONTAL;;;; 252D;BOX DRAWINGS LEFT HEAVY AND RIGHT DOWN LIGHT;So;0;ON;;;;;N;FORMS LEFT HEAVY AND RIGHT DOWN LIGHT;;;; 252E;BOX DRAWINGS RIGHT HEAVY AND LEFT DOWN LIGHT;So;0;ON;;;;;N;FORMS RIGHT HEAVY AND LEFT DOWN LIGHT;;;; 252F;BOX DRAWINGS DOWN LIGHT AND HORIZONTAL HEAVY;So;0;ON;;;;;N;FORMS DOWN LIGHT AND HORIZONTAL HEAVY;;;; 2530;BOX DRAWINGS DOWN HEAVY AND HORIZONTAL LIGHT;So;0;ON;;;;;N;FORMS DOWN HEAVY AND HORIZONTAL LIGHT;;;; 2531;BOX DRAWINGS RIGHT LIGHT AND LEFT DOWN HEAVY;So;0;ON;;;;;N;FORMS RIGHT LIGHT AND LEFT DOWN HEAVY;;;; 2532;BOX DRAWINGS LEFT LIGHT AND RIGHT DOWN HEAVY;So;0;ON;;;;;N;FORMS LEFT LIGHT AND RIGHT DOWN HEAVY;;;; 2533;BOX DRAWINGS HEAVY DOWN AND HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY DOWN AND HORIZONTAL;;;; 2534;BOX DRAWINGS LIGHT UP AND HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT UP AND HORIZONTAL;;;; 2535;BOX DRAWINGS LEFT HEAVY AND RIGHT UP LIGHT;So;0;ON;;;;;N;FORMS LEFT HEAVY AND RIGHT UP LIGHT;;;; 2536;BOX DRAWINGS RIGHT HEAVY AND LEFT UP LIGHT;So;0;ON;;;;;N;FORMS RIGHT HEAVY AND LEFT UP LIGHT;;;; 2537;BOX DRAWINGS UP LIGHT AND HORIZONTAL HEAVY;So;0;ON;;;;;N;FORMS UP LIGHT AND HORIZONTAL HEAVY;;;; 2538;BOX DRAWINGS UP HEAVY AND HORIZONTAL LIGHT;So;0;ON;;;;;N;FORMS UP HEAVY AND HORIZONTAL LIGHT;;;; 2539;BOX DRAWINGS RIGHT LIGHT AND LEFT UP HEAVY;So;0;ON;;;;;N;FORMS RIGHT LIGHT AND LEFT UP HEAVY;;;; 253A;BOX DRAWINGS LEFT LIGHT AND RIGHT UP HEAVY;So;0;ON;;;;;N;FORMS LEFT LIGHT AND RIGHT UP HEAVY;;;; 253B;BOX DRAWINGS HEAVY UP AND HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY UP AND HORIZONTAL;;;; 253C;BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT VERTICAL AND HORIZONTAL;;;; 253D;BOX DRAWINGS LEFT HEAVY AND RIGHT VERTICAL LIGHT;So;0;ON;;;;;N;FORMS LEFT HEAVY AND RIGHT VERTICAL LIGHT;;;; 253E;BOX DRAWINGS RIGHT HEAVY AND LEFT VERTICAL LIGHT;So;0;ON;;;;;N;FORMS RIGHT HEAVY AND LEFT VERTICAL LIGHT;;;; 253F;BOX DRAWINGS VERTICAL LIGHT AND HORIZONTAL HEAVY;So;0;ON;;;;;N;FORMS VERTICAL LIGHT AND HORIZONTAL HEAVY;;;; 2540;BOX DRAWINGS UP HEAVY AND DOWN HORIZONTAL LIGHT;So;0;ON;;;;;N;FORMS UP HEAVY AND DOWN HORIZONTAL LIGHT;;;; 2541;BOX DRAWINGS DOWN HEAVY AND UP HORIZONTAL LIGHT;So;0;ON;;;;;N;FORMS DOWN HEAVY AND UP HORIZONTAL LIGHT;;;; 2542;BOX DRAWINGS VERTICAL HEAVY AND HORIZONTAL LIGHT;So;0;ON;;;;;N;FORMS VERTICAL HEAVY AND HORIZONTAL LIGHT;;;; 2543;BOX DRAWINGS LEFT UP HEAVY AND RIGHT DOWN LIGHT;So;0;ON;;;;;N;FORMS LEFT UP HEAVY AND RIGHT DOWN LIGHT;;;; 2544;BOX DRAWINGS RIGHT UP HEAVY AND LEFT DOWN LIGHT;So;0;ON;;;;;N;FORMS RIGHT UP HEAVY AND LEFT DOWN LIGHT;;;; 2545;BOX DRAWINGS LEFT DOWN HEAVY AND RIGHT UP LIGHT;So;0;ON;;;;;N;FORMS LEFT DOWN HEAVY AND RIGHT UP LIGHT;;;; 2546;BOX DRAWINGS RIGHT DOWN HEAVY AND LEFT UP LIGHT;So;0;ON;;;;;N;FORMS RIGHT DOWN HEAVY AND LEFT UP LIGHT;;;; 2547;BOX DRAWINGS DOWN LIGHT AND UP HORIZONTAL HEAVY;So;0;ON;;;;;N;FORMS DOWN LIGHT AND UP HORIZONTAL HEAVY;;;; 2548;BOX DRAWINGS UP LIGHT AND DOWN HORIZONTAL HEAVY;So;0;ON;;;;;N;FORMS UP LIGHT AND DOWN HORIZONTAL HEAVY;;;; 2549;BOX DRAWINGS RIGHT LIGHT AND LEFT VERTICAL HEAVY;So;0;ON;;;;;N;FORMS RIGHT LIGHT AND LEFT VERTICAL HEAVY;;;; 254A;BOX DRAWINGS LEFT LIGHT AND RIGHT VERTICAL HEAVY;So;0;ON;;;;;N;FORMS LEFT LIGHT AND RIGHT VERTICAL HEAVY;;;; 254B;BOX DRAWINGS HEAVY VERTICAL AND HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY VERTICAL AND HORIZONTAL;;;; 254C;BOX DRAWINGS LIGHT DOUBLE DASH HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT DOUBLE DASH HORIZONTAL;;;; 254D;BOX DRAWINGS HEAVY DOUBLE DASH HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY DOUBLE DASH HORIZONTAL;;;; 254E;BOX DRAWINGS LIGHT DOUBLE DASH VERTICAL;So;0;ON;;;;;N;FORMS LIGHT DOUBLE DASH VERTICAL;;;; 254F;BOX DRAWINGS HEAVY DOUBLE DASH VERTICAL;So;0;ON;;;;;N;FORMS HEAVY DOUBLE DASH VERTICAL;;;; 2550;BOX DRAWINGS DOUBLE HORIZONTAL;So;0;ON;;;;;N;FORMS DOUBLE HORIZONTAL;;;; 2551;BOX DRAWINGS DOUBLE VERTICAL;So;0;ON;;;;;N;FORMS DOUBLE VERTICAL;;;; 2552;BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE;So;0;ON;;;;;N;FORMS DOWN SINGLE AND RIGHT DOUBLE;;;; 2553;BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE;So;0;ON;;;;;N;FORMS DOWN DOUBLE AND RIGHT SINGLE;;;; 2554;BOX DRAWINGS DOUBLE DOWN AND RIGHT;So;0;ON;;;;;N;FORMS DOUBLE DOWN AND RIGHT;;;; 2555;BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE;So;0;ON;;;;;N;FORMS DOWN SINGLE AND LEFT DOUBLE;;;; 2556;BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE;So;0;ON;;;;;N;FORMS DOWN DOUBLE AND LEFT SINGLE;;;; 2557;BOX DRAWINGS DOUBLE DOWN AND LEFT;So;0;ON;;;;;N;FORMS DOUBLE DOWN AND LEFT;;;; 2558;BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE;So;0;ON;;;;;N;FORMS UP SINGLE AND RIGHT DOUBLE;;;; 2559;BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE;So;0;ON;;;;;N;FORMS UP DOUBLE AND RIGHT SINGLE;;;; 255A;BOX DRAWINGS DOUBLE UP AND RIGHT;So;0;ON;;;;;N;FORMS DOUBLE UP AND RIGHT;;;; 255B;BOX DRAWINGS UP SINGLE AND LEFT DOUBLE;So;0;ON;;;;;N;FORMS UP SINGLE AND LEFT DOUBLE;;;; 255C;BOX DRAWINGS UP DOUBLE AND LEFT SINGLE;So;0;ON;;;;;N;FORMS UP DOUBLE AND LEFT SINGLE;;;; 255D;BOX DRAWINGS DOUBLE UP AND LEFT;So;0;ON;;;;;N;FORMS DOUBLE UP AND LEFT;;;; 255E;BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE;So;0;ON;;;;;N;FORMS VERTICAL SINGLE AND RIGHT DOUBLE;;;; 255F;BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE;So;0;ON;;;;;N;FORMS VERTICAL DOUBLE AND RIGHT SINGLE;;;; 2560;BOX DRAWINGS DOUBLE VERTICAL AND RIGHT;So;0;ON;;;;;N;FORMS DOUBLE VERTICAL AND RIGHT;;;; 2561;BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE;So;0;ON;;;;;N;FORMS VERTICAL SINGLE AND LEFT DOUBLE;;;; 2562;BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE;So;0;ON;;;;;N;FORMS VERTICAL DOUBLE AND LEFT SINGLE;;;; 2563;BOX DRAWINGS DOUBLE VERTICAL AND LEFT;So;0;ON;;;;;N;FORMS DOUBLE VERTICAL AND LEFT;;;; 2564;BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE;So;0;ON;;;;;N;FORMS DOWN SINGLE AND HORIZONTAL DOUBLE;;;; 2565;BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE;So;0;ON;;;;;N;FORMS DOWN DOUBLE AND HORIZONTAL SINGLE;;;; 2566;BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL;So;0;ON;;;;;N;FORMS DOUBLE DOWN AND HORIZONTAL;;;; 2567;BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE;So;0;ON;;;;;N;FORMS UP SINGLE AND HORIZONTAL DOUBLE;;;; 2568;BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE;So;0;ON;;;;;N;FORMS UP DOUBLE AND HORIZONTAL SINGLE;;;; 2569;BOX DRAWINGS DOUBLE UP AND HORIZONTAL;So;0;ON;;;;;N;FORMS DOUBLE UP AND HORIZONTAL;;;; 256A;BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE;So;0;ON;;;;;N;FORMS VERTICAL SINGLE AND HORIZONTAL DOUBLE;;;; 256B;BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE;So;0;ON;;;;;N;FORMS VERTICAL DOUBLE AND HORIZONTAL SINGLE;;;; 256C;BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL;So;0;ON;;;;;N;FORMS DOUBLE VERTICAL AND HORIZONTAL;;;; 256D;BOX DRAWINGS LIGHT ARC DOWN AND RIGHT;So;0;ON;;;;;N;FORMS LIGHT ARC DOWN AND RIGHT;;;; 256E;BOX DRAWINGS LIGHT ARC DOWN AND LEFT;So;0;ON;;;;;N;FORMS LIGHT ARC DOWN AND LEFT;;;; 256F;BOX DRAWINGS LIGHT ARC UP AND LEFT;So;0;ON;;;;;N;FORMS LIGHT ARC UP AND LEFT;;;; 2570;BOX DRAWINGS LIGHT ARC UP AND RIGHT;So;0;ON;;;;;N;FORMS LIGHT ARC UP AND RIGHT;;;; 2571;BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT;So;0;ON;;;;;N;FORMS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT;;;; 2572;BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT;So;0;ON;;;;;N;FORMS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT;;;; 2573;BOX DRAWINGS LIGHT DIAGONAL CROSS;So;0;ON;;;;;N;FORMS LIGHT DIAGONAL CROSS;;;; 2574;BOX DRAWINGS LIGHT LEFT;So;0;ON;;;;;N;FORMS LIGHT LEFT;;;; 2575;BOX DRAWINGS LIGHT UP;So;0;ON;;;;;N;FORMS LIGHT UP;;;; 2576;BOX DRAWINGS LIGHT RIGHT;So;0;ON;;;;;N;FORMS LIGHT RIGHT;;;; 2577;BOX DRAWINGS LIGHT DOWN;So;0;ON;;;;;N;FORMS LIGHT DOWN;;;; 2578;BOX DRAWINGS HEAVY LEFT;So;0;ON;;;;;N;FORMS HEAVY LEFT;;;; 2579;BOX DRAWINGS HEAVY UP;So;0;ON;;;;;N;FORMS HEAVY UP;;;; 257A;BOX DRAWINGS HEAVY RIGHT;So;0;ON;;;;;N;FORMS HEAVY RIGHT;;;; 257B;BOX DRAWINGS HEAVY DOWN;So;0;ON;;;;;N;FORMS HEAVY DOWN;;;; 257C;BOX DRAWINGS LIGHT LEFT AND HEAVY RIGHT;So;0;ON;;;;;N;FORMS LIGHT LEFT AND HEAVY RIGHT;;;; 257D;BOX DRAWINGS LIGHT UP AND HEAVY DOWN;So;0;ON;;;;;N;FORMS LIGHT UP AND HEAVY DOWN;;;; 257E;BOX DRAWINGS HEAVY LEFT AND LIGHT RIGHT;So;0;ON;;;;;N;FORMS HEAVY LEFT AND LIGHT RIGHT;;;; 257F;BOX DRAWINGS HEAVY UP AND LIGHT DOWN;So;0;ON;;;;;N;FORMS HEAVY UP AND LIGHT DOWN;;;; 2580;UPPER HALF BLOCK;So;0;ON;;;;;N;;;;; 2581;LOWER ONE EIGHTH BLOCK;So;0;ON;;;;;N;;;;; 2582;LOWER ONE QUARTER BLOCK;So;0;ON;;;;;N;;;;; 2583;LOWER THREE EIGHTHS BLOCK;So;0;ON;;;;;N;;;;; 2584;LOWER HALF BLOCK;So;0;ON;;;;;N;;;;; 2585;LOWER FIVE EIGHTHS BLOCK;So;0;ON;;;;;N;;;;; 2586;LOWER THREE QUARTERS BLOCK;So;0;ON;;;;;N;LOWER THREE QUARTER BLOCK;;;; 2587;LOWER SEVEN EIGHTHS BLOCK;So;0;ON;;;;;N;;;;; 2588;FULL BLOCK;So;0;ON;;;;;N;;;;; 2589;LEFT SEVEN EIGHTHS BLOCK;So;0;ON;;;;;N;;;;; 258A;LEFT THREE QUARTERS BLOCK;So;0;ON;;;;;N;LEFT THREE QUARTER BLOCK;;;; 258B;LEFT FIVE EIGHTHS BLOCK;So;0;ON;;;;;N;;;;; 258C;LEFT HALF BLOCK;So;0;ON;;;;;N;;;;; 258D;LEFT THREE EIGHTHS BLOCK;So;0;ON;;;;;N;;;;; 258E;LEFT ONE QUARTER BLOCK;So;0;ON;;;;;N;;;;; 258F;LEFT ONE EIGHTH BLOCK;So;0;ON;;;;;N;;;;; 2590;RIGHT HALF BLOCK;So;0;ON;;;;;N;;;;; 2591;LIGHT SHADE;So;0;ON;;;;;N;;;;; 2592;MEDIUM SHADE;So;0;ON;;;;;N;;;;; 2593;DARK SHADE;So;0;ON;;;;;N;;;;; 2594;UPPER ONE EIGHTH BLOCK;So;0;ON;;;;;N;;;;; 2595;RIGHT ONE EIGHTH BLOCK;So;0;ON;;;;;N;;;;; 2596;QUADRANT LOWER LEFT;So;0;ON;;;;;N;;;;; 2597;QUADRANT LOWER RIGHT;So;0;ON;;;;;N;;;;; 2598;QUADRANT UPPER LEFT;So;0;ON;;;;;N;;;;; 2599;QUADRANT UPPER LEFT AND LOWER LEFT AND LOWER RIGHT;So;0;ON;;;;;N;;;;; 259A;QUADRANT UPPER LEFT AND LOWER RIGHT;So;0;ON;;;;;N;;;;; 259B;QUADRANT UPPER LEFT AND UPPER RIGHT AND LOWER LEFT;So;0;ON;;;;;N;;;;; 259C;QUADRANT UPPER LEFT AND UPPER RIGHT AND LOWER RIGHT;So;0;ON;;;;;N;;;;; 259D;QUADRANT UPPER RIGHT;So;0;ON;;;;;N;;;;; 259E;QUADRANT UPPER RIGHT AND LOWER LEFT;So;0;ON;;;;;N;;;;; 259F;QUADRANT UPPER RIGHT AND LOWER LEFT AND LOWER RIGHT;So;0;ON;;;;;N;;;;; 25A0;BLACK SQUARE;So;0;ON;;;;;N;;;;; 25A1;WHITE SQUARE;So;0;ON;;;;;N;;;;; 25A2;WHITE SQUARE WITH ROUNDED CORNERS;So;0;ON;;;;;N;;;;; 25A3;WHITE SQUARE CONTAINING BLACK SMALL SQUARE;So;0;ON;;;;;N;;;;; 25A4;SQUARE WITH HORIZONTAL FILL;So;0;ON;;;;;N;;;;; 25A5;SQUARE WITH VERTICAL FILL;So;0;ON;;;;;N;;;;; 25A6;SQUARE WITH ORTHOGONAL CROSSHATCH FILL;So;0;ON;;;;;N;;;;; 25A7;SQUARE WITH UPPER LEFT TO LOWER RIGHT FILL;So;0;ON;;;;;N;;;;; 25A8;SQUARE WITH UPPER RIGHT TO LOWER LEFT FILL;So;0;ON;;;;;N;;;;; 25A9;SQUARE WITH DIAGONAL CROSSHATCH FILL;So;0;ON;;;;;N;;;;; 25AA;BLACK SMALL SQUARE;So;0;ON;;;;;N;;;;; 25AB;WHITE SMALL SQUARE;So;0;ON;;;;;N;;;;; 25AC;BLACK RECTANGLE;So;0;ON;;;;;N;;;;; 25AD;WHITE RECTANGLE;So;0;ON;;;;;N;;;;; 25AE;BLACK VERTICAL RECTANGLE;So;0;ON;;;;;N;;;;; 25AF;WHITE VERTICAL RECTANGLE;So;0;ON;;;;;N;;;;; 25B0;BLACK PARALLELOGRAM;So;0;ON;;;;;N;;;;; 25B1;WHITE PARALLELOGRAM;So;0;ON;;;;;N;;;;; 25B2;BLACK UP-POINTING TRIANGLE;So;0;ON;;;;;N;BLACK UP POINTING TRIANGLE;;;; 25B3;WHITE UP-POINTING TRIANGLE;So;0;ON;;;;;N;WHITE UP POINTING TRIANGLE;;;; 25B4;BLACK UP-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;BLACK UP POINTING SMALL TRIANGLE;;;; 25B5;WHITE UP-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;WHITE UP POINTING SMALL TRIANGLE;;;; 25B6;BLACK RIGHT-POINTING TRIANGLE;So;0;ON;;;;;N;BLACK RIGHT POINTING TRIANGLE;;;; 25B7;WHITE RIGHT-POINTING TRIANGLE;Sm;0;ON;;;;;N;WHITE RIGHT POINTING TRIANGLE;;;; 25B8;BLACK RIGHT-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;BLACK RIGHT POINTING SMALL TRIANGLE;;;; 25B9;WHITE RIGHT-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;WHITE RIGHT POINTING SMALL TRIANGLE;;;; 25BA;BLACK RIGHT-POINTING POINTER;So;0;ON;;;;;N;BLACK RIGHT POINTING POINTER;;;; 25BB;WHITE RIGHT-POINTING POINTER;So;0;ON;;;;;N;WHITE RIGHT POINTING POINTER;;;; 25BC;BLACK DOWN-POINTING TRIANGLE;So;0;ON;;;;;N;BLACK DOWN POINTING TRIANGLE;;;; 25BD;WHITE DOWN-POINTING TRIANGLE;So;0;ON;;;;;N;WHITE DOWN POINTING TRIANGLE;;;; 25BE;BLACK DOWN-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;BLACK DOWN POINTING SMALL TRIANGLE;;;; 25BF;WHITE DOWN-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;WHITE DOWN POINTING SMALL TRIANGLE;;;; 25C0;BLACK LEFT-POINTING TRIANGLE;So;0;ON;;;;;N;BLACK LEFT POINTING TRIANGLE;;;; 25C1;WHITE LEFT-POINTING TRIANGLE;Sm;0;ON;;;;;N;WHITE LEFT POINTING TRIANGLE;;;; 25C2;BLACK LEFT-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;BLACK LEFT POINTING SMALL TRIANGLE;;;; 25C3;WHITE LEFT-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;WHITE LEFT POINTING SMALL TRIANGLE;;;; 25C4;BLACK LEFT-POINTING POINTER;So;0;ON;;;;;N;BLACK LEFT POINTING POINTER;;;; 25C5;WHITE LEFT-POINTING POINTER;So;0;ON;;;;;N;WHITE LEFT POINTING POINTER;;;; 25C6;BLACK DIAMOND;So;0;ON;;;;;N;;;;; 25C7;WHITE DIAMOND;So;0;ON;;;;;N;;;;; 25C8;WHITE DIAMOND CONTAINING BLACK SMALL DIAMOND;So;0;ON;;;;;N;;;;; 25C9;FISHEYE;So;0;ON;;;;;N;;;;; 25CA;LOZENGE;So;0;ON;;;;;N;;;;; 25CB;WHITE CIRCLE;So;0;ON;;;;;N;;;;; 25CC;DOTTED CIRCLE;So;0;ON;;;;;N;;;;; 25CD;CIRCLE WITH VERTICAL FILL;So;0;ON;;;;;N;;;;; 25CE;BULLSEYE;So;0;ON;;;;;N;;;;; 25CF;BLACK CIRCLE;So;0;ON;;;;;N;;;;; 25D0;CIRCLE WITH LEFT HALF BLACK;So;0;ON;;;;;N;;;;; 25D1;CIRCLE WITH RIGHT HALF BLACK;So;0;ON;;;;;N;;;;; 25D2;CIRCLE WITH LOWER HALF BLACK;So;0;ON;;;;;N;;;;; 25D3;CIRCLE WITH UPPER HALF BLACK;So;0;ON;;;;;N;;;;; 25D4;CIRCLE WITH UPPER RIGHT QUADRANT BLACK;So;0;ON;;;;;N;;;;; 25D5;CIRCLE WITH ALL BUT UPPER LEFT QUADRANT BLACK;So;0;ON;;;;;N;;;;; 25D6;LEFT HALF BLACK CIRCLE;So;0;ON;;;;;N;;;;; 25D7;RIGHT HALF BLACK CIRCLE;So;0;ON;;;;;N;;;;; 25D8;INVERSE BULLET;So;0;ON;;;;;N;;;;; 25D9;INVERSE WHITE CIRCLE;So;0;ON;;;;;N;;;;; 25DA;UPPER HALF INVERSE WHITE CIRCLE;So;0;ON;;;;;N;;;;; 25DB;LOWER HALF INVERSE WHITE CIRCLE;So;0;ON;;;;;N;;;;; 25DC;UPPER LEFT QUADRANT CIRCULAR ARC;So;0;ON;;;;;N;;;;; 25DD;UPPER RIGHT QUADRANT CIRCULAR ARC;So;0;ON;;;;;N;;;;; 25DE;LOWER RIGHT QUADRANT CIRCULAR ARC;So;0;ON;;;;;N;;;;; 25DF;LOWER LEFT QUADRANT CIRCULAR ARC;So;0;ON;;;;;N;;;;; 25E0;UPPER HALF CIRCLE;So;0;ON;;;;;N;;;;; 25E1;LOWER HALF CIRCLE;So;0;ON;;;;;N;;;;; 25E2;BLACK LOWER RIGHT TRIANGLE;So;0;ON;;;;;N;;;;; 25E3;BLACK LOWER LEFT TRIANGLE;So;0;ON;;;;;N;;;;; 25E4;BLACK UPPER LEFT TRIANGLE;So;0;ON;;;;;N;;;;; 25E5;BLACK UPPER RIGHT TRIANGLE;So;0;ON;;;;;N;;;;; 25E6;WHITE BULLET;So;0;ON;;;;;N;;;;; 25E7;SQUARE WITH LEFT HALF BLACK;So;0;ON;;;;;N;;;;; 25E8;SQUARE WITH RIGHT HALF BLACK;So;0;ON;;;;;N;;;;; 25E9;SQUARE WITH UPPER LEFT DIAGONAL HALF BLACK;So;0;ON;;;;;N;;;;; 25EA;SQUARE WITH LOWER RIGHT DIAGONAL HALF BLACK;So;0;ON;;;;;N;;;;; 25EB;WHITE SQUARE WITH VERTICAL BISECTING LINE;So;0;ON;;;;;N;;;;; 25EC;WHITE UP-POINTING TRIANGLE WITH DOT;So;0;ON;;;;;N;WHITE UP POINTING TRIANGLE WITH DOT;;;; 25ED;UP-POINTING TRIANGLE WITH LEFT HALF BLACK;So;0;ON;;;;;N;UP POINTING TRIANGLE WITH LEFT HALF BLACK;;;; 25EE;UP-POINTING TRIANGLE WITH RIGHT HALF BLACK;So;0;ON;;;;;N;UP POINTING TRIANGLE WITH RIGHT HALF BLACK;;;; 25EF;LARGE CIRCLE;So;0;ON;;;;;N;;;;; 25F0;WHITE SQUARE WITH UPPER LEFT QUADRANT;So;0;ON;;;;;N;;;;; 25F1;WHITE SQUARE WITH LOWER LEFT QUADRANT;So;0;ON;;;;;N;;;;; 25F2;WHITE SQUARE WITH LOWER RIGHT QUADRANT;So;0;ON;;;;;N;;;;; 25F3;WHITE SQUARE WITH UPPER RIGHT QUADRANT;So;0;ON;;;;;N;;;;; 25F4;WHITE CIRCLE WITH UPPER LEFT QUADRANT;So;0;ON;;;;;N;;;;; 25F5;WHITE CIRCLE WITH LOWER LEFT QUADRANT;So;0;ON;;;;;N;;;;; 25F6;WHITE CIRCLE WITH LOWER RIGHT QUADRANT;So;0;ON;;;;;N;;;;; 25F7;WHITE CIRCLE WITH UPPER RIGHT QUADRANT;So;0;ON;;;;;N;;;;; 25F8;UPPER LEFT TRIANGLE;Sm;0;ON;;;;;N;;;;; 25F9;UPPER RIGHT TRIANGLE;Sm;0;ON;;;;;N;;;;; 25FA;LOWER LEFT TRIANGLE;Sm;0;ON;;;;;N;;;;; 25FB;WHITE MEDIUM SQUARE;Sm;0;ON;;;;;N;;;;; 25FC;BLACK MEDIUM SQUARE;Sm;0;ON;;;;;N;;;;; 25FD;WHITE MEDIUM SMALL SQUARE;Sm;0;ON;;;;;N;;;;; 25FE;BLACK MEDIUM SMALL SQUARE;Sm;0;ON;;;;;N;;;;; 25FF;LOWER RIGHT TRIANGLE;Sm;0;ON;;;;;N;;;;; 2600;BLACK SUN WITH RAYS;So;0;ON;;;;;N;;;;; 2601;CLOUD;So;0;ON;;;;;N;;;;; 2602;UMBRELLA;So;0;ON;;;;;N;;;;; 2603;SNOWMAN;So;0;ON;;;;;N;;;;; 2604;COMET;So;0;ON;;;;;N;;;;; 2605;BLACK STAR;So;0;ON;;;;;N;;;;; 2606;WHITE STAR;So;0;ON;;;;;N;;;;; 2607;LIGHTNING;So;0;ON;;;;;N;;;;; 2608;THUNDERSTORM;So;0;ON;;;;;N;;;;; 2609;SUN;So;0;ON;;;;;N;;;;; 260A;ASCENDING NODE;So;0;ON;;;;;N;;;;; 260B;DESCENDING NODE;So;0;ON;;;;;N;;;;; 260C;CONJUNCTION;So;0;ON;;;;;N;;;;; 260D;OPPOSITION;So;0;ON;;;;;N;;;;; 260E;BLACK TELEPHONE;So;0;ON;;;;;N;;;;; 260F;WHITE TELEPHONE;So;0;ON;;;;;N;;;;; 2610;BALLOT BOX;So;0;ON;;;;;N;;;;; 2611;BALLOT BOX WITH CHECK;So;0;ON;;;;;N;;;;; 2612;BALLOT BOX WITH X;So;0;ON;;;;;N;;;;; 2613;SALTIRE;So;0;ON;;;;;N;;;;; 2616;WHITE SHOGI PIECE;So;0;ON;;;;;N;;;;; 2617;BLACK SHOGI PIECE;So;0;ON;;;;;N;;;;; 2619;REVERSED ROTATED FLORAL HEART BULLET;So;0;ON;;;;;N;;;;; 261A;BLACK LEFT POINTING INDEX;So;0;ON;;;;;N;;;;; 261B;BLACK RIGHT POINTING INDEX;So;0;ON;;;;;N;;;;; 261C;WHITE LEFT POINTING INDEX;So;0;ON;;;;;N;;;;; 261D;WHITE UP POINTING INDEX;So;0;ON;;;;;N;;;;; 261E;WHITE RIGHT POINTING INDEX;So;0;ON;;;;;N;;;;; 261F;WHITE DOWN POINTING INDEX;So;0;ON;;;;;N;;;;; 2620;SKULL AND CROSSBONES;So;0;ON;;;;;N;;;;; 2621;CAUTION SIGN;So;0;ON;;;;;N;;;;; 2622;RADIOACTIVE SIGN;So;0;ON;;;;;N;;;;; 2623;BIOHAZARD SIGN;So;0;ON;;;;;N;;;;; 2624;CADUCEUS;So;0;ON;;;;;N;;;;; 2625;ANKH;So;0;ON;;;;;N;;;;; 2626;ORTHODOX CROSS;So;0;ON;;;;;N;;;;; 2627;CHI RHO;So;0;ON;;;;;N;;;;; 2628;CROSS OF LORRAINE;So;0;ON;;;;;N;;;;; 2629;CROSS OF JERUSALEM;So;0;ON;;;;;N;;;;; 262A;STAR AND CRESCENT;So;0;ON;;;;;N;;;;; 262B;FARSI SYMBOL;So;0;ON;;;;;N;SYMBOL OF IRAN;;;; 262C;ADI SHAKTI;So;0;ON;;;;;N;;;;; 262D;HAMMER AND SICKLE;So;0;ON;;;;;N;;;;; 262E;PEACE SYMBOL;So;0;ON;;;;;N;;;;; 262F;YIN YANG;So;0;ON;;;;;N;;;;; 2630;TRIGRAM FOR HEAVEN;So;0;ON;;;;;N;;;;; 2631;TRIGRAM FOR LAKE;So;0;ON;;;;;N;;;;; 2632;TRIGRAM FOR FIRE;So;0;ON;;;;;N;;;;; 2633;TRIGRAM FOR THUNDER;So;0;ON;;;;;N;;;;; 2634;TRIGRAM FOR WIND;So;0;ON;;;;;N;;;;; 2635;TRIGRAM FOR WATER;So;0;ON;;;;;N;;;;; 2636;TRIGRAM FOR MOUNTAIN;So;0;ON;;;;;N;;;;; 2637;TRIGRAM FOR EARTH;So;0;ON;;;;;N;;;;; 2638;WHEEL OF DHARMA;So;0;ON;;;;;N;;;;; 2639;WHITE FROWNING FACE;So;0;ON;;;;;N;;;;; 263A;WHITE SMILING FACE;So;0;ON;;;;;N;;;;; 263B;BLACK SMILING FACE;So;0;ON;;;;;N;;;;; 263C;WHITE SUN WITH RAYS;So;0;ON;;;;;N;;;;; 263D;FIRST QUARTER MOON;So;0;ON;;;;;N;;;;; 263E;LAST QUARTER MOON;So;0;ON;;;;;N;;;;; 263F;MERCURY;So;0;ON;;;;;N;;;;; 2640;FEMALE SIGN;So;0;ON;;;;;N;;;;; 2641;EARTH;So;0;ON;;;;;N;;;;; 2642;MALE SIGN;So;0;ON;;;;;N;;;;; 2643;JUPITER;So;0;ON;;;;;N;;;;; 2644;SATURN;So;0;ON;;;;;N;;;;; 2645;URANUS;So;0;ON;;;;;N;;;;; 2646;NEPTUNE;So;0;ON;;;;;N;;;;; 2647;PLUTO;So;0;ON;;;;;N;;;;; 2648;ARIES;So;0;ON;;;;;N;;;;; 2649;TAURUS;So;0;ON;;;;;N;;;;; 264A;GEMINI;So;0;ON;;;;;N;;;;; 264B;CANCER;So;0;ON;;;;;N;;;;; 264C;LEO;So;0;ON;;;;;N;;;;; 264D;VIRGO;So;0;ON;;;;;N;;;;; 264E;LIBRA;So;0;ON;;;;;N;;;;; 264F;SCORPIUS;So;0;ON;;;;;N;;;;; 2650;SAGITTARIUS;So;0;ON;;;;;N;;;;; 2651;CAPRICORN;So;0;ON;;;;;N;;;;; 2652;AQUARIUS;So;0;ON;;;;;N;;;;; 2653;PISCES;So;0;ON;;;;;N;;;;; 2654;WHITE CHESS KING;So;0;ON;;;;;N;;;;; 2655;WHITE CHESS QUEEN;So;0;ON;;;;;N;;;;; 2656;WHITE CHESS ROOK;So;0;ON;;;;;N;;;;; 2657;WHITE CHESS BISHOP;So;0;ON;;;;;N;;;;; 2658;WHITE CHESS KNIGHT;So;0;ON;;;;;N;;;;; 2659;WHITE CHESS PAWN;So;0;ON;;;;;N;;;;; 265A;BLACK CHESS KING;So;0;ON;;;;;N;;;;; 265B;BLACK CHESS QUEEN;So;0;ON;;;;;N;;;;; 265C;BLACK CHESS ROOK;So;0;ON;;;;;N;;;;; 265D;BLACK CHESS BISHOP;So;0;ON;;;;;N;;;;; 265E;BLACK CHESS KNIGHT;So;0;ON;;;;;N;;;;; 265F;BLACK CHESS PAWN;So;0;ON;;;;;N;;;;; 2660;BLACK SPADE SUIT;So;0;ON;;;;;N;;;;; 2661;WHITE HEART SUIT;So;0;ON;;;;;N;;;;; 2662;WHITE DIAMOND SUIT;So;0;ON;;;;;N;;;;; 2663;BLACK CLUB SUIT;So;0;ON;;;;;N;;;;; 2664;WHITE SPADE SUIT;So;0;ON;;;;;N;;;;; 2665;BLACK HEART SUIT;So;0;ON;;;;;N;;;;; 2666;BLACK DIAMOND SUIT;So;0;ON;;;;;N;;;;; 2667;WHITE CLUB SUIT;So;0;ON;;;;;N;;;;; 2668;HOT SPRINGS;So;0;ON;;;;;N;;;;; 2669;QUARTER NOTE;So;0;ON;;;;;N;;;;; 266A;EIGHTH NOTE;So;0;ON;;;;;N;;;;; 266B;BEAMED EIGHTH NOTES;So;0;ON;;;;;N;BARRED EIGHTH NOTES;;;; 266C;BEAMED SIXTEENTH NOTES;So;0;ON;;;;;N;BARRED SIXTEENTH NOTES;;;; 266D;MUSIC FLAT SIGN;So;0;ON;;;;;N;FLAT;;;; 266E;MUSIC NATURAL SIGN;So;0;ON;;;;;N;NATURAL;;;; 266F;MUSIC SHARP SIGN;Sm;0;ON;;;;;N;SHARP;;;; 2670;WEST SYRIAC CROSS;So;0;ON;;;;;N;;;;; 2671;EAST SYRIAC CROSS;So;0;ON;;;;;N;;;;; 2672;UNIVERSAL RECYCLING SYMBOL;So;0;ON;;;;;N;;;;; 2673;RECYCLING SYMBOL FOR TYPE-1 PLASTICS;So;0;ON;;;;;N;;pete;;; 2674;RECYCLING SYMBOL FOR TYPE-2 PLASTICS;So;0;ON;;;;;N;;hdpe;;; 2675;RECYCLING SYMBOL FOR TYPE-3 PLASTICS;So;0;ON;;;;;N;;pvc;;; 2676;RECYCLING SYMBOL FOR TYPE-4 PLASTICS;So;0;ON;;;;;N;;ldpe;;; 2677;RECYCLING SYMBOL FOR TYPE-5 PLASTICS;So;0;ON;;;;;N;;pp;;; 2678;RECYCLING SYMBOL FOR TYPE-6 PLASTICS;So;0;ON;;;;;N;;ps;;; 2679;RECYCLING SYMBOL FOR TYPE-7 PLASTICS;So;0;ON;;;;;N;;other;;; 267A;RECYCLING SYMBOL FOR GENERIC MATERIALS;So;0;ON;;;;;N;;;;; 267B;BLACK UNIVERSAL RECYCLING SYMBOL;So;0;ON;;;;;N;;;;; 267C;RECYCLED PAPER SYMBOL;So;0;ON;;;;;N;;;;; 267D;PARTIALLY-RECYCLED PAPER SYMBOL;So;0;ON;;;;;N;;;;; 2680;DIE FACE-1;So;0;ON;;;;;N;;;;; 2681;DIE FACE-2;So;0;ON;;;;;N;;;;; 2682;DIE FACE-3;So;0;ON;;;;;N;;;;; 2683;DIE FACE-4;So;0;ON;;;;;N;;;;; 2684;DIE FACE-5;So;0;ON;;;;;N;;;;; 2685;DIE FACE-6;So;0;ON;;;;;N;;;;; 2686;WHITE CIRCLE WITH DOT RIGHT;So;0;ON;;;;;N;;;;; 2687;WHITE CIRCLE WITH TWO DOTS;So;0;ON;;;;;N;;;;; 2688;BLACK CIRCLE WITH WHITE DOT RIGHT;So;0;ON;;;;;N;;;;; 2689;BLACK CIRCLE WITH TWO WHITE DOTS;So;0;ON;;;;;N;;;;; 2701;UPPER BLADE SCISSORS;So;0;ON;;;;;N;;;;; 2702;BLACK SCISSORS;So;0;ON;;;;;N;;;;; 2703;LOWER BLADE SCISSORS;So;0;ON;;;;;N;;;;; 2704;WHITE SCISSORS;So;0;ON;;;;;N;;;;; 2706;TELEPHONE LOCATION SIGN;So;0;ON;;;;;N;;;;; 2707;TAPE DRIVE;So;0;ON;;;;;N;;;;; 2708;AIRPLANE;So;0;ON;;;;;N;;;;; 2709;ENVELOPE;So;0;ON;;;;;N;;;;; 270C;VICTORY HAND;So;0;ON;;;;;N;;;;; 270D;WRITING HAND;So;0;ON;;;;;N;;;;; 270E;LOWER RIGHT PENCIL;So;0;ON;;;;;N;;;;; 270F;PENCIL;So;0;ON;;;;;N;;;;; 2710;UPPER RIGHT PENCIL;So;0;ON;;;;;N;;;;; 2711;WHITE NIB;So;0;ON;;;;;N;;;;; 2712;BLACK NIB;So;0;ON;;;;;N;;;;; 2713;CHECK MARK;So;0;ON;;;;;N;;;;; 2714;HEAVY CHECK MARK;So;0;ON;;;;;N;;;;; 2715;MULTIPLICATION X;So;0;ON;;;;;N;;;;; 2716;HEAVY MULTIPLICATION X;So;0;ON;;;;;N;;;;; 2717;BALLOT X;So;0;ON;;;;;N;;;;; 2718;HEAVY BALLOT X;So;0;ON;;;;;N;;;;; 2719;OUTLINED GREEK CROSS;So;0;ON;;;;;N;;;;; 271A;HEAVY GREEK CROSS;So;0;ON;;;;;N;;;;; 271B;OPEN CENTRE CROSS;So;0;ON;;;;;N;OPEN CENTER CROSS;;;; 271C;HEAVY OPEN CENTRE CROSS;So;0;ON;;;;;N;HEAVY OPEN CENTER CROSS;;;; 271D;LATIN CROSS;So;0;ON;;;;;N;;;;; 271E;SHADOWED WHITE LATIN CROSS;So;0;ON;;;;;N;;;;; 271F;OUTLINED LATIN CROSS;So;0;ON;;;;;N;;;;; 2720;MALTESE CROSS;So;0;ON;;;;;N;;;;; 2721;STAR OF DAVID;So;0;ON;;;;;N;;;;; 2722;FOUR TEARDROP-SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 2723;FOUR BALLOON-SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 2724;HEAVY FOUR BALLOON-SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 2725;FOUR CLUB-SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 2726;BLACK FOUR POINTED STAR;So;0;ON;;;;;N;;;;; 2727;WHITE FOUR POINTED STAR;So;0;ON;;;;;N;;;;; 2729;STRESS OUTLINED WHITE STAR;So;0;ON;;;;;N;;;;; 272A;CIRCLED WHITE STAR;So;0;ON;;;;;N;;;;; 272B;OPEN CENTRE BLACK STAR;So;0;ON;;;;;N;OPEN CENTER BLACK STAR;;;; 272C;BLACK CENTRE WHITE STAR;So;0;ON;;;;;N;BLACK CENTER WHITE STAR;;;; 272D;OUTLINED BLACK STAR;So;0;ON;;;;;N;;;;; 272E;HEAVY OUTLINED BLACK STAR;So;0;ON;;;;;N;;;;; 272F;PINWHEEL STAR;So;0;ON;;;;;N;;;;; 2730;SHADOWED WHITE STAR;So;0;ON;;;;;N;;;;; 2731;HEAVY ASTERISK;So;0;ON;;;;;N;;;;; 2732;OPEN CENTRE ASTERISK;So;0;ON;;;;;N;OPEN CENTER ASTERISK;;;; 2733;EIGHT SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 2734;EIGHT POINTED BLACK STAR;So;0;ON;;;;;N;;;;; 2735;EIGHT POINTED PINWHEEL STAR;So;0;ON;;;;;N;;;;; 2736;SIX POINTED BLACK STAR;So;0;ON;;;;;N;;;;; 2737;EIGHT POINTED RECTILINEAR BLACK STAR;So;0;ON;;;;;N;;;;; 2738;HEAVY EIGHT POINTED RECTILINEAR BLACK STAR;So;0;ON;;;;;N;;;;; 2739;TWELVE POINTED BLACK STAR;So;0;ON;;;;;N;;;;; 273A;SIXTEEN POINTED ASTERISK;So;0;ON;;;;;N;;;;; 273B;TEARDROP-SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 273C;OPEN CENTRE TEARDROP-SPOKED ASTERISK;So;0;ON;;;;;N;OPEN CENTER TEARDROP-SPOKED ASTERISK;;;; 273D;HEAVY TEARDROP-SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 273E;SIX PETALLED BLACK AND WHITE FLORETTE;So;0;ON;;;;;N;;;;; 273F;BLACK FLORETTE;So;0;ON;;;;;N;;;;; 2740;WHITE FLORETTE;So;0;ON;;;;;N;;;;; 2741;EIGHT PETALLED OUTLINED BLACK FLORETTE;So;0;ON;;;;;N;;;;; 2742;CIRCLED OPEN CENTRE EIGHT POINTED STAR;So;0;ON;;;;;N;CIRCLED OPEN CENTER EIGHT POINTED STAR;;;; 2743;HEAVY TEARDROP-SPOKED PINWHEEL ASTERISK;So;0;ON;;;;;N;;;;; 2744;SNOWFLAKE;So;0;ON;;;;;N;;;;; 2745;TIGHT TRIFOLIATE SNOWFLAKE;So;0;ON;;;;;N;;;;; 2746;HEAVY CHEVRON SNOWFLAKE;So;0;ON;;;;;N;;;;; 2747;SPARKLE;So;0;ON;;;;;N;;;;; 2748;HEAVY SPARKLE;So;0;ON;;;;;N;;;;; 2749;BALLOON-SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 274A;EIGHT TEARDROP-SPOKED PROPELLER ASTERISK;So;0;ON;;;;;N;;;;; 274B;HEAVY EIGHT TEARDROP-SPOKED PROPELLER ASTERISK;So;0;ON;;;;;N;;;;; 274D;SHADOWED WHITE CIRCLE;So;0;ON;;;;;N;;;;; 274F;LOWER RIGHT DROP-SHADOWED WHITE SQUARE;So;0;ON;;;;;N;;;;; 2750;UPPER RIGHT DROP-SHADOWED WHITE SQUARE;So;0;ON;;;;;N;;;;; 2751;LOWER RIGHT SHADOWED WHITE SQUARE;So;0;ON;;;;;N;;;;; 2752;UPPER RIGHT SHADOWED WHITE SQUARE;So;0;ON;;;;;N;;;;; 2756;BLACK DIAMOND MINUS WHITE X;So;0;ON;;;;;N;;;;; 2758;LIGHT VERTICAL BAR;So;0;ON;;;;;N;;;;; 2759;MEDIUM VERTICAL BAR;So;0;ON;;;;;N;;;;; 275A;HEAVY VERTICAL BAR;So;0;ON;;;;;N;;;;; 275B;HEAVY SINGLE TURNED COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; 275C;HEAVY SINGLE COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; 275D;HEAVY DOUBLE TURNED COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; 275E;HEAVY DOUBLE COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; 2761;CURVED STEM PARAGRAPH SIGN ORNAMENT;So;0;ON;;;;;N;;;;; 2762;HEAVY EXCLAMATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; 2763;HEAVY HEART EXCLAMATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; 2764;HEAVY BLACK HEART;So;0;ON;;;;;N;;;;; 2765;ROTATED HEAVY BLACK HEART BULLET;So;0;ON;;;;;N;;;;; 2766;FLORAL HEART;So;0;ON;;;;;N;;;;; 2767;ROTATED FLORAL HEART BULLET;So;0;ON;;;;;N;;;;; 2768;MEDIUM LEFT PARENTHESIS ORNAMENT;Ps;0;ON;;;;;Y;;;;; 2769;MEDIUM RIGHT PARENTHESIS ORNAMENT;Pe;0;ON;;;;;Y;;;;; 276A;MEDIUM FLATTENED LEFT PARENTHESIS ORNAMENT;Ps;0;ON;;;;;Y;;;;; 276B;MEDIUM FLATTENED RIGHT PARENTHESIS ORNAMENT;Pe;0;ON;;;;;Y;;;;; 276C;MEDIUM LEFT-POINTING ANGLE BRACKET ORNAMENT;Ps;0;ON;;;;;Y;;;;; 276D;MEDIUM RIGHT-POINTING ANGLE BRACKET ORNAMENT;Pe;0;ON;;;;;Y;;;;; 276E;HEAVY LEFT-POINTING ANGLE QUOTATION MARK ORNAMENT;Ps;0;ON;;;;;Y;;;;; 276F;HEAVY RIGHT-POINTING ANGLE QUOTATION MARK ORNAMENT;Pe;0;ON;;;;;Y;;;;; 2770;HEAVY LEFT-POINTING ANGLE BRACKET ORNAMENT;Ps;0;ON;;;;;Y;;;;; 2771;HEAVY RIGHT-POINTING ANGLE BRACKET ORNAMENT;Pe;0;ON;;;;;Y;;;;; 2772;LIGHT LEFT TORTOISE SHELL BRACKET ORNAMENT;Ps;0;ON;;;;;Y;;;;; 2773;LIGHT RIGHT TORTOISE SHELL BRACKET ORNAMENT;Pe;0;ON;;;;;Y;;;;; 2774;MEDIUM LEFT CURLY BRACKET ORNAMENT;Ps;0;ON;;;;;Y;;;;; 2775;MEDIUM RIGHT CURLY BRACKET ORNAMENT;Pe;0;ON;;;;;Y;;;;; 2776;DINGBAT NEGATIVE CIRCLED DIGIT ONE;No;0;ON;;;1;1;N;INVERSE CIRCLED DIGIT ONE;;;; 2777;DINGBAT NEGATIVE CIRCLED DIGIT TWO;No;0;ON;;;2;2;N;INVERSE CIRCLED DIGIT TWO;;;; 2778;DINGBAT NEGATIVE CIRCLED DIGIT THREE;No;0;ON;;;3;3;N;INVERSE CIRCLED DIGIT THREE;;;; 2779;DINGBAT NEGATIVE CIRCLED DIGIT FOUR;No;0;ON;;;4;4;N;INVERSE CIRCLED DIGIT FOUR;;;; 277A;DINGBAT NEGATIVE CIRCLED DIGIT FIVE;No;0;ON;;;5;5;N;INVERSE CIRCLED DIGIT FIVE;;;; 277B;DINGBAT NEGATIVE CIRCLED DIGIT SIX;No;0;ON;;;6;6;N;INVERSE CIRCLED DIGIT SIX;;;; 277C;DINGBAT NEGATIVE CIRCLED DIGIT SEVEN;No;0;ON;;;7;7;N;INVERSE CIRCLED DIGIT SEVEN;;;; 277D;DINGBAT NEGATIVE CIRCLED DIGIT EIGHT;No;0;ON;;;8;8;N;INVERSE CIRCLED DIGIT EIGHT;;;; 277E;DINGBAT NEGATIVE CIRCLED DIGIT NINE;No;0;ON;;;9;9;N;INVERSE CIRCLED DIGIT NINE;;;; 277F;DINGBAT NEGATIVE CIRCLED NUMBER TEN;No;0;ON;;;;10;N;INVERSE CIRCLED NUMBER TEN;;;; 2780;DINGBAT CIRCLED SANS-SERIF DIGIT ONE;No;0;ON;;;1;1;N;CIRCLED SANS-SERIF DIGIT ONE;;;; 2781;DINGBAT CIRCLED SANS-SERIF DIGIT TWO;No;0;ON;;;2;2;N;CIRCLED SANS-SERIF DIGIT TWO;;;; 2782;DINGBAT CIRCLED SANS-SERIF DIGIT THREE;No;0;ON;;;3;3;N;CIRCLED SANS-SERIF DIGIT THREE;;;; 2783;DINGBAT CIRCLED SANS-SERIF DIGIT FOUR;No;0;ON;;;4;4;N;CIRCLED SANS-SERIF DIGIT FOUR;;;; 2784;DINGBAT CIRCLED SANS-SERIF DIGIT FIVE;No;0;ON;;;5;5;N;CIRCLED SANS-SERIF DIGIT FIVE;;;; 2785;DINGBAT CIRCLED SANS-SERIF DIGIT SIX;No;0;ON;;;6;6;N;CIRCLED SANS-SERIF DIGIT SIX;;;; 2786;DINGBAT CIRCLED SANS-SERIF DIGIT SEVEN;No;0;ON;;;7;7;N;CIRCLED SANS-SERIF DIGIT SEVEN;;;; 2787;DINGBAT CIRCLED SANS-SERIF DIGIT EIGHT;No;0;ON;;;8;8;N;CIRCLED SANS-SERIF DIGIT EIGHT;;;; 2788;DINGBAT CIRCLED SANS-SERIF DIGIT NINE;No;0;ON;;;9;9;N;CIRCLED SANS-SERIF DIGIT NINE;;;; 2789;DINGBAT CIRCLED SANS-SERIF NUMBER TEN;No;0;ON;;;;10;N;CIRCLED SANS-SERIF NUMBER TEN;;;; 278A;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT ONE;No;0;ON;;;1;1;N;INVERSE CIRCLED SANS-SERIF DIGIT ONE;;;; 278B;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT TWO;No;0;ON;;;2;2;N;INVERSE CIRCLED SANS-SERIF DIGIT TWO;;;; 278C;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT THREE;No;0;ON;;;3;3;N;INVERSE CIRCLED SANS-SERIF DIGIT THREE;;;; 278D;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT FOUR;No;0;ON;;;4;4;N;INVERSE CIRCLED SANS-SERIF DIGIT FOUR;;;; 278E;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT FIVE;No;0;ON;;;5;5;N;INVERSE CIRCLED SANS-SERIF DIGIT FIVE;;;; 278F;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SIX;No;0;ON;;;6;6;N;INVERSE CIRCLED SANS-SERIF DIGIT SIX;;;; 2790;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SEVEN;No;0;ON;;;7;7;N;INVERSE CIRCLED SANS-SERIF DIGIT SEVEN;;;; 2791;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT EIGHT;No;0;ON;;;8;8;N;INVERSE CIRCLED SANS-SERIF DIGIT EIGHT;;;; 2792;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT NINE;No;0;ON;;;9;9;N;INVERSE CIRCLED SANS-SERIF DIGIT NINE;;;; 2793;DINGBAT NEGATIVE CIRCLED SANS-SERIF NUMBER TEN;No;0;ON;;;;10;N;INVERSE CIRCLED SANS-SERIF NUMBER TEN;;;; 2794;HEAVY WIDE-HEADED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY WIDE-HEADED RIGHT ARROW;;;; 2798;HEAVY SOUTH EAST ARROW;So;0;ON;;;;;N;HEAVY LOWER RIGHT ARROW;;;; 2799;HEAVY RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY RIGHT ARROW;;;; 279A;HEAVY NORTH EAST ARROW;So;0;ON;;;;;N;HEAVY UPPER RIGHT ARROW;;;; 279B;DRAFTING POINT RIGHTWARDS ARROW;So;0;ON;;;;;N;DRAFTING POINT RIGHT ARROW;;;; 279C;HEAVY ROUND-TIPPED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY ROUND-TIPPED RIGHT ARROW;;;; 279D;TRIANGLE-HEADED RIGHTWARDS ARROW;So;0;ON;;;;;N;TRIANGLE-HEADED RIGHT ARROW;;;; 279E;HEAVY TRIANGLE-HEADED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY TRIANGLE-HEADED RIGHT ARROW;;;; 279F;DASHED TRIANGLE-HEADED RIGHTWARDS ARROW;So;0;ON;;;;;N;DASHED TRIANGLE-HEADED RIGHT ARROW;;;; 27A0;HEAVY DASHED TRIANGLE-HEADED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY DASHED TRIANGLE-HEADED RIGHT ARROW;;;; 27A1;BLACK RIGHTWARDS ARROW;So;0;ON;;;;;N;BLACK RIGHT ARROW;;;; 27A2;THREE-D TOP-LIGHTED RIGHTWARDS ARROWHEAD;So;0;ON;;;;;N;THREE-D TOP-LIGHTED RIGHT ARROWHEAD;;;; 27A3;THREE-D BOTTOM-LIGHTED RIGHTWARDS ARROWHEAD;So;0;ON;;;;;N;THREE-D BOTTOM-LIGHTED RIGHT ARROWHEAD;;;; 27A4;BLACK RIGHTWARDS ARROWHEAD;So;0;ON;;;;;N;BLACK RIGHT ARROWHEAD;;;; 27A5;HEAVY BLACK CURVED DOWNWARDS AND RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY BLACK CURVED DOWN AND RIGHT ARROW;;;; 27A6;HEAVY BLACK CURVED UPWARDS AND RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY BLACK CURVED UP AND RIGHT ARROW;;;; 27A7;SQUAT BLACK RIGHTWARDS ARROW;So;0;ON;;;;;N;SQUAT BLACK RIGHT ARROW;;;; 27A8;HEAVY CONCAVE-POINTED BLACK RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY CONCAVE-POINTED BLACK RIGHT ARROW;;;; 27A9;RIGHT-SHADED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;RIGHT-SHADED WHITE RIGHT ARROW;;;; 27AA;LEFT-SHADED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;LEFT-SHADED WHITE RIGHT ARROW;;;; 27AB;BACK-TILTED SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;BACK-TILTED SHADOWED WHITE RIGHT ARROW;;;; 27AC;FRONT-TILTED SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;FRONT-TILTED SHADOWED WHITE RIGHT ARROW;;;; 27AD;HEAVY LOWER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY LOWER RIGHT-SHADOWED WHITE RIGHT ARROW;;;; 27AE;HEAVY UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY UPPER RIGHT-SHADOWED WHITE RIGHT ARROW;;;; 27AF;NOTCHED LOWER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;NOTCHED LOWER RIGHT-SHADOWED WHITE RIGHT ARROW;;;; 27B1;NOTCHED UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;NOTCHED UPPER RIGHT-SHADOWED WHITE RIGHT ARROW;;;; 27B2;CIRCLED HEAVY WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;CIRCLED HEAVY WHITE RIGHT ARROW;;;; 27B3;WHITE-FEATHERED RIGHTWARDS ARROW;So;0;ON;;;;;N;WHITE-FEATHERED RIGHT ARROW;;;; 27B4;BLACK-FEATHERED SOUTH EAST ARROW;So;0;ON;;;;;N;BLACK-FEATHERED LOWER RIGHT ARROW;;;; 27B5;BLACK-FEATHERED RIGHTWARDS ARROW;So;0;ON;;;;;N;BLACK-FEATHERED RIGHT ARROW;;;; 27B6;BLACK-FEATHERED NORTH EAST ARROW;So;0;ON;;;;;N;BLACK-FEATHERED UPPER RIGHT ARROW;;;; 27B7;HEAVY BLACK-FEATHERED SOUTH EAST ARROW;So;0;ON;;;;;N;HEAVY BLACK-FEATHERED LOWER RIGHT ARROW;;;; 27B8;HEAVY BLACK-FEATHERED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY BLACK-FEATHERED RIGHT ARROW;;;; 27B9;HEAVY BLACK-FEATHERED NORTH EAST ARROW;So;0;ON;;;;;N;HEAVY BLACK-FEATHERED UPPER RIGHT ARROW;;;; 27BA;TEARDROP-BARBED RIGHTWARDS ARROW;So;0;ON;;;;;N;TEARDROP-BARBED RIGHT ARROW;;;; 27BB;HEAVY TEARDROP-SHANKED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY TEARDROP-SHANKED RIGHT ARROW;;;; 27BC;WEDGE-TAILED RIGHTWARDS ARROW;So;0;ON;;;;;N;WEDGE-TAILED RIGHT ARROW;;;; 27BD;HEAVY WEDGE-TAILED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY WEDGE-TAILED RIGHT ARROW;;;; 27BE;OPEN-OUTLINED RIGHTWARDS ARROW;So;0;ON;;;;;N;OPEN-OUTLINED RIGHT ARROW;;;; 27D0;WHITE DIAMOND WITH CENTRED DOT;Sm;0;ON;;;;;N;;;;; 27D1;AND WITH DOT;Sm;0;ON;;;;;N;;;;; 27D2;ELEMENT OF OPENING UPWARDS;Sm;0;ON;;;;;N;;;;; 27D3;LOWER RIGHT CORNER WITH DOT;Sm;0;ON;;;;;Y;;;;; 27D4;UPPER LEFT CORNER WITH DOT;Sm;0;ON;;;;;Y;;;;; 27D5;LEFT OUTER JOIN;Sm;0;ON;;;;;Y;;;;; 27D6;RIGHT OUTER JOIN;Sm;0;ON;;;;;Y;;;;; 27D7;FULL OUTER JOIN;Sm;0;ON;;;;;N;;;;; 27D8;LARGE UP TACK;Sm;0;ON;;;;;N;;;;; 27D9;LARGE DOWN TACK;Sm;0;ON;;;;;N;;;;; 27DA;LEFT AND RIGHT DOUBLE TURNSTILE;Sm;0;ON;;;;;N;;;;; 27DB;LEFT AND RIGHT TACK;Sm;0;ON;;;;;N;;;;; 27DC;LEFT MULTIMAP;Sm;0;ON;;;;;Y;;;;; 27DD;LONG RIGHT TACK;Sm;0;ON;;;;;Y;;;;; 27DE;LONG LEFT TACK;Sm;0;ON;;;;;Y;;;;; 27DF;UP TACK WITH CIRCLE ABOVE;Sm;0;ON;;;;;N;;;;; 27E0;LOZENGE DIVIDED BY HORIZONTAL RULE;Sm;0;ON;;;;;N;;;;; 27E1;WHITE CONCAVE-SIDED DIAMOND;Sm;0;ON;;;;;N;;;;; 27E2;WHITE CONCAVE-SIDED DIAMOND WITH LEFTWARDS TICK;Sm;0;ON;;;;;Y;;;;; 27E3;WHITE CONCAVE-SIDED DIAMOND WITH RIGHTWARDS TICK;Sm;0;ON;;;;;Y;;;;; 27E4;WHITE SQUARE WITH LEFTWARDS TICK;Sm;0;ON;;;;;Y;;;;; 27E5;WHITE SQUARE WITH RIGHTWARDS TICK;Sm;0;ON;;;;;Y;;;;; 27E6;MATHEMATICAL LEFT WHITE SQUARE BRACKET;Ps;0;ON;;;;;Y;;;;; 27E7;MATHEMATICAL RIGHT WHITE SQUARE BRACKET;Pe;0;ON;;;;;Y;;;;; 27E8;MATHEMATICAL LEFT ANGLE BRACKET;Ps;0;ON;;;;;Y;;;;; 27E9;MATHEMATICAL RIGHT ANGLE BRACKET;Pe;0;ON;;;;;Y;;;;; 27EA;MATHEMATICAL LEFT DOUBLE ANGLE BRACKET;Ps;0;ON;;;;;Y;;;;; 27EB;MATHEMATICAL RIGHT DOUBLE ANGLE BRACKET;Pe;0;ON;;;;;Y;;;;; 27F0;UPWARDS QUADRUPLE ARROW;Sm;0;ON;;;;;N;;;;; 27F1;DOWNWARDS QUADRUPLE ARROW;Sm;0;ON;;;;;N;;;;; 27F2;ANTICLOCKWISE GAPPED CIRCLE ARROW;Sm;0;ON;;;;;N;;;;; 27F3;CLOCKWISE GAPPED CIRCLE ARROW;Sm;0;ON;;;;;N;;;;; 27F4;RIGHT ARROW WITH CIRCLED PLUS;Sm;0;ON;;;;;N;;;;; 27F5;LONG LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 27F6;LONG RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 27F7;LONG LEFT RIGHT ARROW;Sm;0;ON;;;;;N;;;;; 27F8;LONG LEFTWARDS DOUBLE ARROW;Sm;0;ON;;;;;N;;;;; 27F9;LONG RIGHTWARDS DOUBLE ARROW;Sm;0;ON;;;;;N;;;;; 27FA;LONG LEFT RIGHT DOUBLE ARROW;Sm;0;ON;;;;;N;;;;; 27FB;LONG LEFTWARDS ARROW FROM BAR;Sm;0;ON;;;;;N;;;;; 27FC;LONG RIGHTWARDS ARROW FROM BAR;Sm;0;ON;;;;;N;;;;; 27FD;LONG LEFTWARDS DOUBLE ARROW FROM BAR;Sm;0;ON;;;;;N;;;;; 27FE;LONG RIGHTWARDS DOUBLE ARROW FROM BAR;Sm;0;ON;;;;;N;;;;; 27FF;LONG RIGHTWARDS SQUIGGLE ARROW;Sm;0;ON;;;;;N;;;;; 2800;BRAILLE PATTERN BLANK;So;0;ON;;;;;N;;;;; 2801;BRAILLE PATTERN DOTS-1;So;0;ON;;;;;N;;;;; 2802;BRAILLE PATTERN DOTS-2;So;0;ON;;;;;N;;;;; 2803;BRAILLE PATTERN DOTS-12;So;0;ON;;;;;N;;;;; 2804;BRAILLE PATTERN DOTS-3;So;0;ON;;;;;N;;;;; 2805;BRAILLE PATTERN DOTS-13;So;0;ON;;;;;N;;;;; 2806;BRAILLE PATTERN DOTS-23;So;0;ON;;;;;N;;;;; 2807;BRAILLE PATTERN DOTS-123;So;0;ON;;;;;N;;;;; 2808;BRAILLE PATTERN DOTS-4;So;0;ON;;;;;N;;;;; 2809;BRAILLE PATTERN DOTS-14;So;0;ON;;;;;N;;;;; 280A;BRAILLE PATTERN DOTS-24;So;0;ON;;;;;N;;;;; 280B;BRAILLE PATTERN DOTS-124;So;0;ON;;;;;N;;;;; 280C;BRAILLE PATTERN DOTS-34;So;0;ON;;;;;N;;;;; 280D;BRAILLE PATTERN DOTS-134;So;0;ON;;;;;N;;;;; 280E;BRAILLE PATTERN DOTS-234;So;0;ON;;;;;N;;;;; 280F;BRAILLE PATTERN DOTS-1234;So;0;ON;;;;;N;;;;; 2810;BRAILLE PATTERN DOTS-5;So;0;ON;;;;;N;;;;; 2811;BRAILLE PATTERN DOTS-15;So;0;ON;;;;;N;;;;; 2812;BRAILLE PATTERN DOTS-25;So;0;ON;;;;;N;;;;; 2813;BRAILLE PATTERN DOTS-125;So;0;ON;;;;;N;;;;; 2814;BRAILLE PATTERN DOTS-35;So;0;ON;;;;;N;;;;; 2815;BRAILLE PATTERN DOTS-135;So;0;ON;;;;;N;;;;; 2816;BRAILLE PATTERN DOTS-235;So;0;ON;;;;;N;;;;; 2817;BRAILLE PATTERN DOTS-1235;So;0;ON;;;;;N;;;;; 2818;BRAILLE PATTERN DOTS-45;So;0;ON;;;;;N;;;;; 2819;BRAILLE PATTERN DOTS-145;So;0;ON;;;;;N;;;;; 281A;BRAILLE PATTERN DOTS-245;So;0;ON;;;;;N;;;;; 281B;BRAILLE PATTERN DOTS-1245;So;0;ON;;;;;N;;;;; 281C;BRAILLE PATTERN DOTS-345;So;0;ON;;;;;N;;;;; 281D;BRAILLE PATTERN DOTS-1345;So;0;ON;;;;;N;;;;; 281E;BRAILLE PATTERN DOTS-2345;So;0;ON;;;;;N;;;;; 281F;BRAILLE PATTERN DOTS-12345;So;0;ON;;;;;N;;;;; 2820;BRAILLE PATTERN DOTS-6;So;0;ON;;;;;N;;;;; 2821;BRAILLE PATTERN DOTS-16;So;0;ON;;;;;N;;;;; 2822;BRAILLE PATTERN DOTS-26;So;0;ON;;;;;N;;;;; 2823;BRAILLE PATTERN DOTS-126;So;0;ON;;;;;N;;;;; 2824;BRAILLE PATTERN DOTS-36;So;0;ON;;;;;N;;;;; 2825;BRAILLE PATTERN DOTS-136;So;0;ON;;;;;N;;;;; 2826;BRAILLE PATTERN DOTS-236;So;0;ON;;;;;N;;;;; 2827;BRAILLE PATTERN DOTS-1236;So;0;ON;;;;;N;;;;; 2828;BRAILLE PATTERN DOTS-46;So;0;ON;;;;;N;;;;; 2829;BRAILLE PATTERN DOTS-146;So;0;ON;;;;;N;;;;; 282A;BRAILLE PATTERN DOTS-246;So;0;ON;;;;;N;;;;; 282B;BRAILLE PATTERN DOTS-1246;So;0;ON;;;;;N;;;;; 282C;BRAILLE PATTERN DOTS-346;So;0;ON;;;;;N;;;;; 282D;BRAILLE PATTERN DOTS-1346;So;0;ON;;;;;N;;;;; 282E;BRAILLE PATTERN DOTS-2346;So;0;ON;;;;;N;;;;; 282F;BRAILLE PATTERN DOTS-12346;So;0;ON;;;;;N;;;;; 2830;BRAILLE PATTERN DOTS-56;So;0;ON;;;;;N;;;;; 2831;BRAILLE PATTERN DOTS-156;So;0;ON;;;;;N;;;;; 2832;BRAILLE PATTERN DOTS-256;So;0;ON;;;;;N;;;;; 2833;BRAILLE PATTERN DOTS-1256;So;0;ON;;;;;N;;;;; 2834;BRAILLE PATTERN DOTS-356;So;0;ON;;;;;N;;;;; 2835;BRAILLE PATTERN DOTS-1356;So;0;ON;;;;;N;;;;; 2836;BRAILLE PATTERN DOTS-2356;So;0;ON;;;;;N;;;;; 2837;BRAILLE PATTERN DOTS-12356;So;0;ON;;;;;N;;;;; 2838;BRAILLE PATTERN DOTS-456;So;0;ON;;;;;N;;;;; 2839;BRAILLE PATTERN DOTS-1456;So;0;ON;;;;;N;;;;; 283A;BRAILLE PATTERN DOTS-2456;So;0;ON;;;;;N;;;;; 283B;BRAILLE PATTERN DOTS-12456;So;0;ON;;;;;N;;;;; 283C;BRAILLE PATTERN DOTS-3456;So;0;ON;;;;;N;;;;; 283D;BRAILLE PATTERN DOTS-13456;So;0;ON;;;;;N;;;;; 283E;BRAILLE PATTERN DOTS-23456;So;0;ON;;;;;N;;;;; 283F;BRAILLE PATTERN DOTS-123456;So;0;ON;;;;;N;;;;; 2840;BRAILLE PATTERN DOTS-7;So;0;ON;;;;;N;;;;; 2841;BRAILLE PATTERN DOTS-17;So;0;ON;;;;;N;;;;; 2842;BRAILLE PATTERN DOTS-27;So;0;ON;;;;;N;;;;; 2843;BRAILLE PATTERN DOTS-127;So;0;ON;;;;;N;;;;; 2844;BRAILLE PATTERN DOTS-37;So;0;ON;;;;;N;;;;; 2845;BRAILLE PATTERN DOTS-137;So;0;ON;;;;;N;;;;; 2846;BRAILLE PATTERN DOTS-237;So;0;ON;;;;;N;;;;; 2847;BRAILLE PATTERN DOTS-1237;So;0;ON;;;;;N;;;;; 2848;BRAILLE PATTERN DOTS-47;So;0;ON;;;;;N;;;;; 2849;BRAILLE PATTERN DOTS-147;So;0;ON;;;;;N;;;;; 284A;BRAILLE PATTERN DOTS-247;So;0;ON;;;;;N;;;;; 284B;BRAILLE PATTERN DOTS-1247;So;0;ON;;;;;N;;;;; 284C;BRAILLE PATTERN DOTS-347;So;0;ON;;;;;N;;;;; 284D;BRAILLE PATTERN DOTS-1347;So;0;ON;;;;;N;;;;; 284E;BRAILLE PATTERN DOTS-2347;So;0;ON;;;;;N;;;;; 284F;BRAILLE PATTERN DOTS-12347;So;0;ON;;;;;N;;;;; 2850;BRAILLE PATTERN DOTS-57;So;0;ON;;;;;N;;;;; 2851;BRAILLE PATTERN DOTS-157;So;0;ON;;;;;N;;;;; 2852;BRAILLE PATTERN DOTS-257;So;0;ON;;;;;N;;;;; 2853;BRAILLE PATTERN DOTS-1257;So;0;ON;;;;;N;;;;; 2854;BRAILLE PATTERN DOTS-357;So;0;ON;;;;;N;;;;; 2855;BRAILLE PATTERN DOTS-1357;So;0;ON;;;;;N;;;;; 2856;BRAILLE PATTERN DOTS-2357;So;0;ON;;;;;N;;;;; 2857;BRAILLE PATTERN DOTS-12357;So;0;ON;;;;;N;;;;; 2858;BRAILLE PATTERN DOTS-457;So;0;ON;;;;;N;;;;; 2859;BRAILLE PATTERN DOTS-1457;So;0;ON;;;;;N;;;;; 285A;BRAILLE PATTERN DOTS-2457;So;0;ON;;;;;N;;;;; 285B;BRAILLE PATTERN DOTS-12457;So;0;ON;;;;;N;;;;; 285C;BRAILLE PATTERN DOTS-3457;So;0;ON;;;;;N;;;;; 285D;BRAILLE PATTERN DOTS-13457;So;0;ON;;;;;N;;;;; 285E;BRAILLE PATTERN DOTS-23457;So;0;ON;;;;;N;;;;; 285F;BRAILLE PATTERN DOTS-123457;So;0;ON;;;;;N;;;;; 2860;BRAILLE PATTERN DOTS-67;So;0;ON;;;;;N;;;;; 2861;BRAILLE PATTERN DOTS-167;So;0;ON;;;;;N;;;;; 2862;BRAILLE PATTERN DOTS-267;So;0;ON;;;;;N;;;;; 2863;BRAILLE PATTERN DOTS-1267;So;0;ON;;;;;N;;;;; 2864;BRAILLE PATTERN DOTS-367;So;0;ON;;;;;N;;;;; 2865;BRAILLE PATTERN DOTS-1367;So;0;ON;;;;;N;;;;; 2866;BRAILLE PATTERN DOTS-2367;So;0;ON;;;;;N;;;;; 2867;BRAILLE PATTERN DOTS-12367;So;0;ON;;;;;N;;;;; 2868;BRAILLE PATTERN DOTS-467;So;0;ON;;;;;N;;;;; 2869;BRAILLE PATTERN DOTS-1467;So;0;ON;;;;;N;;;;; 286A;BRAILLE PATTERN DOTS-2467;So;0;ON;;;;;N;;;;; 286B;BRAILLE PATTERN DOTS-12467;So;0;ON;;;;;N;;;;; 286C;BRAILLE PATTERN DOTS-3467;So;0;ON;;;;;N;;;;; 286D;BRAILLE PATTERN DOTS-13467;So;0;ON;;;;;N;;;;; 286E;BRAILLE PATTERN DOTS-23467;So;0;ON;;;;;N;;;;; 286F;BRAILLE PATTERN DOTS-123467;So;0;ON;;;;;N;;;;; 2870;BRAILLE PATTERN DOTS-567;So;0;ON;;;;;N;;;;; 2871;BRAILLE PATTERN DOTS-1567;So;0;ON;;;;;N;;;;; 2872;BRAILLE PATTERN DOTS-2567;So;0;ON;;;;;N;;;;; 2873;BRAILLE PATTERN DOTS-12567;So;0;ON;;;;;N;;;;; 2874;BRAILLE PATTERN DOTS-3567;So;0;ON;;;;;N;;;;; 2875;BRAILLE PATTERN DOTS-13567;So;0;ON;;;;;N;;;;; 2876;BRAILLE PATTERN DOTS-23567;So;0;ON;;;;;N;;;;; 2877;BRAILLE PATTERN DOTS-123567;So;0;ON;;;;;N;;;;; 2878;BRAILLE PATTERN DOTS-4567;So;0;ON;;;;;N;;;;; 2879;BRAILLE PATTERN DOTS-14567;So;0;ON;;;;;N;;;;; 287A;BRAILLE PATTERN DOTS-24567;So;0;ON;;;;;N;;;;; 287B;BRAILLE PATTERN DOTS-124567;So;0;ON;;;;;N;;;;; 287C;BRAILLE PATTERN DOTS-34567;So;0;ON;;;;;N;;;;; 287D;BRAILLE PATTERN DOTS-134567;So;0;ON;;;;;N;;;;; 287E;BRAILLE PATTERN DOTS-234567;So;0;ON;;;;;N;;;;; 287F;BRAILLE PATTERN DOTS-1234567;So;0;ON;;;;;N;;;;; 2880;BRAILLE PATTERN DOTS-8;So;0;ON;;;;;N;;;;; 2881;BRAILLE PATTERN DOTS-18;So;0;ON;;;;;N;;;;; 2882;BRAILLE PATTERN DOTS-28;So;0;ON;;;;;N;;;;; 2883;BRAILLE PATTERN DOTS-128;So;0;ON;;;;;N;;;;; 2884;BRAILLE PATTERN DOTS-38;So;0;ON;;;;;N;;;;; 2885;BRAILLE PATTERN DOTS-138;So;0;ON;;;;;N;;;;; 2886;BRAILLE PATTERN DOTS-238;So;0;ON;;;;;N;;;;; 2887;BRAILLE PATTERN DOTS-1238;So;0;ON;;;;;N;;;;; 2888;BRAILLE PATTERN DOTS-48;So;0;ON;;;;;N;;;;; 2889;BRAILLE PATTERN DOTS-148;So;0;ON;;;;;N;;;;; 288A;BRAILLE PATTERN DOTS-248;So;0;ON;;;;;N;;;;; 288B;BRAILLE PATTERN DOTS-1248;So;0;ON;;;;;N;;;;; 288C;BRAILLE PATTERN DOTS-348;So;0;ON;;;;;N;;;;; 288D;BRAILLE PATTERN DOTS-1348;So;0;ON;;;;;N;;;;; 288E;BRAILLE PATTERN DOTS-2348;So;0;ON;;;;;N;;;;; 288F;BRAILLE PATTERN DOTS-12348;So;0;ON;;;;;N;;;;; 2890;BRAILLE PATTERN DOTS-58;So;0;ON;;;;;N;;;;; 2891;BRAILLE PATTERN DOTS-158;So;0;ON;;;;;N;;;;; 2892;BRAILLE PATTERN DOTS-258;So;0;ON;;;;;N;;;;; 2893;BRAILLE PATTERN DOTS-1258;So;0;ON;;;;;N;;;;; 2894;BRAILLE PATTERN DOTS-358;So;0;ON;;;;;N;;;;; 2895;BRAILLE PATTERN DOTS-1358;So;0;ON;;;;;N;;;;; 2896;BRAILLE PATTERN DOTS-2358;So;0;ON;;;;;N;;;;; 2897;BRAILLE PATTERN DOTS-12358;So;0;ON;;;;;N;;;;; 2898;BRAILLE PATTERN DOTS-458;So;0;ON;;;;;N;;;;; 2899;BRAILLE PATTERN DOTS-1458;So;0;ON;;;;;N;;;;; 289A;BRAILLE PATTERN DOTS-2458;So;0;ON;;;;;N;;;;; 289B;BRAILLE PATTERN DOTS-12458;So;0;ON;;;;;N;;;;; 289C;BRAILLE PATTERN DOTS-3458;So;0;ON;;;;;N;;;;; 289D;BRAILLE PATTERN DOTS-13458;So;0;ON;;;;;N;;;;; 289E;BRAILLE PATTERN DOTS-23458;So;0;ON;;;;;N;;;;; 289F;BRAILLE PATTERN DOTS-123458;So;0;ON;;;;;N;;;;; 28A0;BRAILLE PATTERN DOTS-68;So;0;ON;;;;;N;;;;; 28A1;BRAILLE PATTERN DOTS-168;So;0;ON;;;;;N;;;;; 28A2;BRAILLE PATTERN DOTS-268;So;0;ON;;;;;N;;;;; 28A3;BRAILLE PATTERN DOTS-1268;So;0;ON;;;;;N;;;;; 28A4;BRAILLE PATTERN DOTS-368;So;0;ON;;;;;N;;;;; 28A5;BRAILLE PATTERN DOTS-1368;So;0;ON;;;;;N;;;;; 28A6;BRAILLE PATTERN DOTS-2368;So;0;ON;;;;;N;;;;; 28A7;BRAILLE PATTERN DOTS-12368;So;0;ON;;;;;N;;;;; 28A8;BRAILLE PATTERN DOTS-468;So;0;ON;;;;;N;;;;; 28A9;BRAILLE PATTERN DOTS-1468;So;0;ON;;;;;N;;;;; 28AA;BRAILLE PATTERN DOTS-2468;So;0;ON;;;;;N;;;;; 28AB;BRAILLE PATTERN DOTS-12468;So;0;ON;;;;;N;;;;; 28AC;BRAILLE PATTERN DOTS-3468;So;0;ON;;;;;N;;;;; 28AD;BRAILLE PATTERN DOTS-13468;So;0;ON;;;;;N;;;;; 28AE;BRAILLE PATTERN DOTS-23468;So;0;ON;;;;;N;;;;; 28AF;BRAILLE PATTERN DOTS-123468;So;0;ON;;;;;N;;;;; 28B0;BRAILLE PATTERN DOTS-568;So;0;ON;;;;;N;;;;; 28B1;BRAILLE PATTERN DOTS-1568;So;0;ON;;;;;N;;;;; 28B2;BRAILLE PATTERN DOTS-2568;So;0;ON;;;;;N;;;;; 28B3;BRAILLE PATTERN DOTS-12568;So;0;ON;;;;;N;;;;; 28B4;BRAILLE PATTERN DOTS-3568;So;0;ON;;;;;N;;;;; 28B5;BRAILLE PATTERN DOTS-13568;So;0;ON;;;;;N;;;;; 28B6;BRAILLE PATTERN DOTS-23568;So;0;ON;;;;;N;;;;; 28B7;BRAILLE PATTERN DOTS-123568;So;0;ON;;;;;N;;;;; 28B8;BRAILLE PATTERN DOTS-4568;So;0;ON;;;;;N;;;;; 28B9;BRAILLE PATTERN DOTS-14568;So;0;ON;;;;;N;;;;; 28BA;BRAILLE PATTERN DOTS-24568;So;0;ON;;;;;N;;;;; 28BB;BRAILLE PATTERN DOTS-124568;So;0;ON;;;;;N;;;;; 28BC;BRAILLE PATTERN DOTS-34568;So;0;ON;;;;;N;;;;; 28BD;BRAILLE PATTERN DOTS-134568;So;0;ON;;;;;N;;;;; 28BE;BRAILLE PATTERN DOTS-234568;So;0;ON;;;;;N;;;;; 28BF;BRAILLE PATTERN DOTS-1234568;So;0;ON;;;;;N;;;;; 28C0;BRAILLE PATTERN DOTS-78;So;0;ON;;;;;N;;;;; 28C1;BRAILLE PATTERN DOTS-178;So;0;ON;;;;;N;;;;; 28C2;BRAILLE PATTERN DOTS-278;So;0;ON;;;;;N;;;;; 28C3;BRAILLE PATTERN DOTS-1278;So;0;ON;;;;;N;;;;; 28C4;BRAILLE PATTERN DOTS-378;So;0;ON;;;;;N;;;;; 28C5;BRAILLE PATTERN DOTS-1378;So;0;ON;;;;;N;;;;; 28C6;BRAILLE PATTERN DOTS-2378;So;0;ON;;;;;N;;;;; 28C7;BRAILLE PATTERN DOTS-12378;So;0;ON;;;;;N;;;;; 28C8;BRAILLE PATTERN DOTS-478;So;0;ON;;;;;N;;;;; 28C9;BRAILLE PATTERN DOTS-1478;So;0;ON;;;;;N;;;;; 28CA;BRAILLE PATTERN DOTS-2478;So;0;ON;;;;;N;;;;; 28CB;BRAILLE PATTERN DOTS-12478;So;0;ON;;;;;N;;;;; 28CC;BRAILLE PATTERN DOTS-3478;So;0;ON;;;;;N;;;;; 28CD;BRAILLE PATTERN DOTS-13478;So;0;ON;;;;;N;;;;; 28CE;BRAILLE PATTERN DOTS-23478;So;0;ON;;;;;N;;;;; 28CF;BRAILLE PATTERN DOTS-123478;So;0;ON;;;;;N;;;;; 28D0;BRAILLE PATTERN DOTS-578;So;0;ON;;;;;N;;;;; 28D1;BRAILLE PATTERN DOTS-1578;So;0;ON;;;;;N;;;;; 28D2;BRAILLE PATTERN DOTS-2578;So;0;ON;;;;;N;;;;; 28D3;BRAILLE PATTERN DOTS-12578;So;0;ON;;;;;N;;;;; 28D4;BRAILLE PATTERN DOTS-3578;So;0;ON;;;;;N;;;;; 28D5;BRAILLE PATTERN DOTS-13578;So;0;ON;;;;;N;;;;; 28D6;BRAILLE PATTERN DOTS-23578;So;0;ON;;;;;N;;;;; 28D7;BRAILLE PATTERN DOTS-123578;So;0;ON;;;;;N;;;;; 28D8;BRAILLE PATTERN DOTS-4578;So;0;ON;;;;;N;;;;; 28D9;BRAILLE PATTERN DOTS-14578;So;0;ON;;;;;N;;;;; 28DA;BRAILLE PATTERN DOTS-24578;So;0;ON;;;;;N;;;;; 28DB;BRAILLE PATTERN DOTS-124578;So;0;ON;;;;;N;;;;; 28DC;BRAILLE PATTERN DOTS-34578;So;0;ON;;;;;N;;;;; 28DD;BRAILLE PATTERN DOTS-134578;So;0;ON;;;;;N;;;;; 28DE;BRAILLE PATTERN DOTS-234578;So;0;ON;;;;;N;;;;; 28DF;BRAILLE PATTERN DOTS-1234578;So;0;ON;;;;;N;;;;; 28E0;BRAILLE PATTERN DOTS-678;So;0;ON;;;;;N;;;;; 28E1;BRAILLE PATTERN DOTS-1678;So;0;ON;;;;;N;;;;; 28E2;BRAILLE PATTERN DOTS-2678;So;0;ON;;;;;N;;;;; 28E3;BRAILLE PATTERN DOTS-12678;So;0;ON;;;;;N;;;;; 28E4;BRAILLE PATTERN DOTS-3678;So;0;ON;;;;;N;;;;; 28E5;BRAILLE PATTERN DOTS-13678;So;0;ON;;;;;N;;;;; 28E6;BRAILLE PATTERN DOTS-23678;So;0;ON;;;;;N;;;;; 28E7;BRAILLE PATTERN DOTS-123678;So;0;ON;;;;;N;;;;; 28E8;BRAILLE PATTERN DOTS-4678;So;0;ON;;;;;N;;;;; 28E9;BRAILLE PATTERN DOTS-14678;So;0;ON;;;;;N;;;;; 28EA;BRAILLE PATTERN DOTS-24678;So;0;ON;;;;;N;;;;; 28EB;BRAILLE PATTERN DOTS-124678;So;0;ON;;;;;N;;;;; 28EC;BRAILLE PATTERN DOTS-34678;So;0;ON;;;;;N;;;;; 28ED;BRAILLE PATTERN DOTS-134678;So;0;ON;;;;;N;;;;; 28EE;BRAILLE PATTERN DOTS-234678;So;0;ON;;;;;N;;;;; 28EF;BRAILLE PATTERN DOTS-1234678;So;0;ON;;;;;N;;;;; 28F0;BRAILLE PATTERN DOTS-5678;So;0;ON;;;;;N;;;;; 28F1;BRAILLE PATTERN DOTS-15678;So;0;ON;;;;;N;;;;; 28F2;BRAILLE PATTERN DOTS-25678;So;0;ON;;;;;N;;;;; 28F3;BRAILLE PATTERN DOTS-125678;So;0;ON;;;;;N;;;;; 28F4;BRAILLE PATTERN DOTS-35678;So;0;ON;;;;;N;;;;; 28F5;BRAILLE PATTERN DOTS-135678;So;0;ON;;;;;N;;;;; 28F6;BRAILLE PATTERN DOTS-235678;So;0;ON;;;;;N;;;;; 28F7;BRAILLE PATTERN DOTS-1235678;So;0;ON;;;;;N;;;;; 28F8;BRAILLE PATTERN DOTS-45678;So;0;ON;;;;;N;;;;; 28F9;BRAILLE PATTERN DOTS-145678;So;0;ON;;;;;N;;;;; 28FA;BRAILLE PATTERN DOTS-245678;So;0;ON;;;;;N;;;;; 28FB;BRAILLE PATTERN DOTS-1245678;So;0;ON;;;;;N;;;;; 28FC;BRAILLE PATTERN DOTS-345678;So;0;ON;;;;;N;;;;; 28FD;BRAILLE PATTERN DOTS-1345678;So;0;ON;;;;;N;;;;; 28FE;BRAILLE PATTERN DOTS-2345678;So;0;ON;;;;;N;;;;; 28FF;BRAILLE PATTERN DOTS-12345678;So;0;ON;;;;;N;;;;; 2900;RIGHTWARDS TWO-HEADED ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2901;RIGHTWARDS TWO-HEADED ARROW WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2902;LEFTWARDS DOUBLE ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2903;RIGHTWARDS DOUBLE ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2904;LEFT RIGHT DOUBLE ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2905;RIGHTWARDS TWO-HEADED ARROW FROM BAR;Sm;0;ON;;;;;N;;;;; 2906;LEFTWARDS DOUBLE ARROW FROM BAR;Sm;0;ON;;;;;N;;;;; 2907;RIGHTWARDS DOUBLE ARROW FROM BAR;Sm;0;ON;;;;;N;;;;; 2908;DOWNWARDS ARROW WITH HORIZONTAL STROKE;Sm;0;ON;;;;;N;;;;; 2909;UPWARDS ARROW WITH HORIZONTAL STROKE;Sm;0;ON;;;;;N;;;;; 290A;UPWARDS TRIPLE ARROW;Sm;0;ON;;;;;N;;;;; 290B;DOWNWARDS TRIPLE ARROW;Sm;0;ON;;;;;N;;;;; 290C;LEFTWARDS DOUBLE DASH ARROW;Sm;0;ON;;;;;N;;;;; 290D;RIGHTWARDS DOUBLE DASH ARROW;Sm;0;ON;;;;;N;;;;; 290E;LEFTWARDS TRIPLE DASH ARROW;Sm;0;ON;;;;;N;;;;; 290F;RIGHTWARDS TRIPLE DASH ARROW;Sm;0;ON;;;;;N;;;;; 2910;RIGHTWARDS TWO-HEADED TRIPLE DASH ARROW;Sm;0;ON;;;;;N;;;;; 2911;RIGHTWARDS ARROW WITH DOTTED STEM;Sm;0;ON;;;;;N;;;;; 2912;UPWARDS ARROW TO BAR;Sm;0;ON;;;;;N;;;;; 2913;DOWNWARDS ARROW TO BAR;Sm;0;ON;;;;;N;;;;; 2914;RIGHTWARDS ARROW WITH TAIL WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2915;RIGHTWARDS ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2916;RIGHTWARDS TWO-HEADED ARROW WITH TAIL;Sm;0;ON;;;;;N;;;;; 2917;RIGHTWARDS TWO-HEADED ARROW WITH TAIL WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2918;RIGHTWARDS TWO-HEADED ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2919;LEFTWARDS ARROW-TAIL;Sm;0;ON;;;;;N;;;;; 291A;RIGHTWARDS ARROW-TAIL;Sm;0;ON;;;;;N;;;;; 291B;LEFTWARDS DOUBLE ARROW-TAIL;Sm;0;ON;;;;;N;;;;; 291C;RIGHTWARDS DOUBLE ARROW-TAIL;Sm;0;ON;;;;;N;;;;; 291D;LEFTWARDS ARROW TO BLACK DIAMOND;Sm;0;ON;;;;;N;;;;; 291E;RIGHTWARDS ARROW TO BLACK DIAMOND;Sm;0;ON;;;;;N;;;;; 291F;LEFTWARDS ARROW FROM BAR TO BLACK DIAMOND;Sm;0;ON;;;;;N;;;;; 2920;RIGHTWARDS ARROW FROM BAR TO BLACK DIAMOND;Sm;0;ON;;;;;N;;;;; 2921;NORTH WEST AND SOUTH EAST ARROW;Sm;0;ON;;;;;N;;;;; 2922;NORTH EAST AND SOUTH WEST ARROW;Sm;0;ON;;;;;N;;;;; 2923;NORTH WEST ARROW WITH HOOK;Sm;0;ON;;;;;N;;;;; 2924;NORTH EAST ARROW WITH HOOK;Sm;0;ON;;;;;N;;;;; 2925;SOUTH EAST ARROW WITH HOOK;Sm;0;ON;;;;;N;;;;; 2926;SOUTH WEST ARROW WITH HOOK;Sm;0;ON;;;;;N;;;;; 2927;NORTH WEST ARROW AND NORTH EAST ARROW;Sm;0;ON;;;;;N;;;;; 2928;NORTH EAST ARROW AND SOUTH EAST ARROW;Sm;0;ON;;;;;N;;;;; 2929;SOUTH EAST ARROW AND SOUTH WEST ARROW;Sm;0;ON;;;;;N;;;;; 292A;SOUTH WEST ARROW AND NORTH WEST ARROW;Sm;0;ON;;;;;N;;;;; 292B;RISING DIAGONAL CROSSING FALLING DIAGONAL;Sm;0;ON;;;;;N;;;;; 292C;FALLING DIAGONAL CROSSING RISING DIAGONAL;Sm;0;ON;;;;;N;;;;; 292D;SOUTH EAST ARROW CROSSING NORTH EAST ARROW;Sm;0;ON;;;;;N;;;;; 292E;NORTH EAST ARROW CROSSING SOUTH EAST ARROW;Sm;0;ON;;;;;N;;;;; 292F;FALLING DIAGONAL CROSSING NORTH EAST ARROW;Sm;0;ON;;;;;N;;;;; 2930;RISING DIAGONAL CROSSING SOUTH EAST ARROW;Sm;0;ON;;;;;N;;;;; 2931;NORTH EAST ARROW CROSSING NORTH WEST ARROW;Sm;0;ON;;;;;N;;;;; 2932;NORTH WEST ARROW CROSSING NORTH EAST ARROW;Sm;0;ON;;;;;N;;;;; 2933;WAVE ARROW POINTING DIRECTLY RIGHT;Sm;0;ON;;;;;N;;;;; 2934;ARROW POINTING RIGHTWARDS THEN CURVING UPWARDS;Sm;0;ON;;;;;N;;;;; 2935;ARROW POINTING RIGHTWARDS THEN CURVING DOWNWARDS;Sm;0;ON;;;;;N;;;;; 2936;ARROW POINTING DOWNWARDS THEN CURVING LEFTWARDS;Sm;0;ON;;;;;N;;;;; 2937;ARROW POINTING DOWNWARDS THEN CURVING RIGHTWARDS;Sm;0;ON;;;;;N;;;;; 2938;RIGHT-SIDE ARC CLOCKWISE ARROW;Sm;0;ON;;;;;N;;;;; 2939;LEFT-SIDE ARC ANTICLOCKWISE ARROW;Sm;0;ON;;;;;N;;;;; 293A;TOP ARC ANTICLOCKWISE ARROW;Sm;0;ON;;;;;N;;;;; 293B;BOTTOM ARC ANTICLOCKWISE ARROW;Sm;0;ON;;;;;N;;;;; 293C;TOP ARC CLOCKWISE ARROW WITH MINUS;Sm;0;ON;;;;;N;;;;; 293D;TOP ARC ANTICLOCKWISE ARROW WITH PLUS;Sm;0;ON;;;;;N;;;;; 293E;LOWER RIGHT SEMICIRCULAR CLOCKWISE ARROW;Sm;0;ON;;;;;N;;;;; 293F;LOWER LEFT SEMICIRCULAR ANTICLOCKWISE ARROW;Sm;0;ON;;;;;N;;;;; 2940;ANTICLOCKWISE CLOSED CIRCLE ARROW;Sm;0;ON;;;;;N;;;;; 2941;CLOCKWISE CLOSED CIRCLE ARROW;Sm;0;ON;;;;;N;;;;; 2942;RIGHTWARDS ARROW ABOVE SHORT LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 2943;LEFTWARDS ARROW ABOVE SHORT RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 2944;SHORT RIGHTWARDS ARROW ABOVE LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 2945;RIGHTWARDS ARROW WITH PLUS BELOW;Sm;0;ON;;;;;N;;;;; 2946;LEFTWARDS ARROW WITH PLUS BELOW;Sm;0;ON;;;;;N;;;;; 2947;RIGHTWARDS ARROW THROUGH X;Sm;0;ON;;;;;N;;;;; 2948;LEFT RIGHT ARROW THROUGH SMALL CIRCLE;Sm;0;ON;;;;;N;;;;; 2949;UPWARDS TWO-HEADED ARROW FROM SMALL CIRCLE;Sm;0;ON;;;;;N;;;;; 294A;LEFT BARB UP RIGHT BARB DOWN HARPOON;Sm;0;ON;;;;;N;;;;; 294B;LEFT BARB DOWN RIGHT BARB UP HARPOON;Sm;0;ON;;;;;N;;;;; 294C;UP BARB RIGHT DOWN BARB LEFT HARPOON;Sm;0;ON;;;;;N;;;;; 294D;UP BARB LEFT DOWN BARB RIGHT HARPOON;Sm;0;ON;;;;;N;;;;; 294E;LEFT BARB UP RIGHT BARB UP HARPOON;Sm;0;ON;;;;;N;;;;; 294F;UP BARB RIGHT DOWN BARB RIGHT HARPOON;Sm;0;ON;;;;;N;;;;; 2950;LEFT BARB DOWN RIGHT BARB DOWN HARPOON;Sm;0;ON;;;;;N;;;;; 2951;UP BARB LEFT DOWN BARB LEFT HARPOON;Sm;0;ON;;;;;N;;;;; 2952;LEFTWARDS HARPOON WITH BARB UP TO BAR;Sm;0;ON;;;;;N;;;;; 2953;RIGHTWARDS HARPOON WITH BARB UP TO BAR;Sm;0;ON;;;;;N;;;;; 2954;UPWARDS HARPOON WITH BARB RIGHT TO BAR;Sm;0;ON;;;;;N;;;;; 2955;DOWNWARDS HARPOON WITH BARB RIGHT TO BAR;Sm;0;ON;;;;;N;;;;; 2956;LEFTWARDS HARPOON WITH BARB DOWN TO BAR;Sm;0;ON;;;;;N;;;;; 2957;RIGHTWARDS HARPOON WITH BARB DOWN TO BAR;Sm;0;ON;;;;;N;;;;; 2958;UPWARDS HARPOON WITH BARB LEFT TO BAR;Sm;0;ON;;;;;N;;;;; 2959;DOWNWARDS HARPOON WITH BARB LEFT TO BAR;Sm;0;ON;;;;;N;;;;; 295A;LEFTWARDS HARPOON WITH BARB UP FROM BAR;Sm;0;ON;;;;;N;;;;; 295B;RIGHTWARDS HARPOON WITH BARB UP FROM BAR;Sm;0;ON;;;;;N;;;;; 295C;UPWARDS HARPOON WITH BARB RIGHT FROM BAR;Sm;0;ON;;;;;N;;;;; 295D;DOWNWARDS HARPOON WITH BARB RIGHT FROM BAR;Sm;0;ON;;;;;N;;;;; 295E;LEFTWARDS HARPOON WITH BARB DOWN FROM BAR;Sm;0;ON;;;;;N;;;;; 295F;RIGHTWARDS HARPOON WITH BARB DOWN FROM BAR;Sm;0;ON;;;;;N;;;;; 2960;UPWARDS HARPOON WITH BARB LEFT FROM BAR;Sm;0;ON;;;;;N;;;;; 2961;DOWNWARDS HARPOON WITH BARB LEFT FROM BAR;Sm;0;ON;;;;;N;;;;; 2962;LEFTWARDS HARPOON WITH BARB UP ABOVE LEFTWARDS HARPOON WITH BARB DOWN;Sm;0;ON;;;;;N;;;;; 2963;UPWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT;Sm;0;ON;;;;;N;;;;; 2964;RIGHTWARDS HARPOON WITH BARB UP ABOVE RIGHTWARDS HARPOON WITH BARB DOWN;Sm;0;ON;;;;;N;;;;; 2965;DOWNWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT;Sm;0;ON;;;;;N;;;;; 2966;LEFTWARDS HARPOON WITH BARB UP ABOVE RIGHTWARDS HARPOON WITH BARB UP;Sm;0;ON;;;;;N;;;;; 2967;LEFTWARDS HARPOON WITH BARB DOWN ABOVE RIGHTWARDS HARPOON WITH BARB DOWN;Sm;0;ON;;;;;N;;;;; 2968;RIGHTWARDS HARPOON WITH BARB UP ABOVE LEFTWARDS HARPOON WITH BARB UP;Sm;0;ON;;;;;N;;;;; 2969;RIGHTWARDS HARPOON WITH BARB DOWN ABOVE LEFTWARDS HARPOON WITH BARB DOWN;Sm;0;ON;;;;;N;;;;; 296A;LEFTWARDS HARPOON WITH BARB UP ABOVE LONG DASH;Sm;0;ON;;;;;N;;;;; 296B;LEFTWARDS HARPOON WITH BARB DOWN BELOW LONG DASH;Sm;0;ON;;;;;N;;;;; 296C;RIGHTWARDS HARPOON WITH BARB UP ABOVE LONG DASH;Sm;0;ON;;;;;N;;;;; 296D;RIGHTWARDS HARPOON WITH BARB DOWN BELOW LONG DASH;Sm;0;ON;;;;;N;;;;; 296E;UPWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT;Sm;0;ON;;;;;N;;;;; 296F;DOWNWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT;Sm;0;ON;;;;;N;;;;; 2970;RIGHT DOUBLE ARROW WITH ROUNDED HEAD;Sm;0;ON;;;;;N;;;;; 2971;EQUALS SIGN ABOVE RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 2972;TILDE OPERATOR ABOVE RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 2973;LEFTWARDS ARROW ABOVE TILDE OPERATOR;Sm;0;ON;;;;;N;;;;; 2974;RIGHTWARDS ARROW ABOVE TILDE OPERATOR;Sm;0;ON;;;;;N;;;;; 2975;RIGHTWARDS ARROW ABOVE ALMOST EQUAL TO;Sm;0;ON;;;;;N;;;;; 2976;LESS-THAN ABOVE LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 2977;LEFTWARDS ARROW THROUGH LESS-THAN;Sm;0;ON;;;;;N;;;;; 2978;GREATER-THAN ABOVE RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 2979;SUBSET ABOVE RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 297A;LEFTWARDS ARROW THROUGH SUBSET;Sm;0;ON;;;;;N;;;;; 297B;SUPERSET ABOVE LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 297C;LEFT FISH TAIL;Sm;0;ON;;;;;N;;;;; 297D;RIGHT FISH TAIL;Sm;0;ON;;;;;N;;;;; 297E;UP FISH TAIL;Sm;0;ON;;;;;N;;;;; 297F;DOWN FISH TAIL;Sm;0;ON;;;;;N;;;;; 2980;TRIPLE VERTICAL BAR DELIMITER;Sm;0;ON;;;;;N;;;;; 2981;Z NOTATION SPOT;Sm;0;ON;;;;;N;;;;; 2982;Z NOTATION TYPE COLON;Sm;0;ON;;;;;N;;;;; 2983;LEFT WHITE CURLY BRACKET;Ps;0;ON;;;;;Y;;;;; 2984;RIGHT WHITE CURLY BRACKET;Pe;0;ON;;;;;Y;;;;; 2985;LEFT WHITE PARENTHESIS;Ps;0;ON;;;;;Y;;;;; 2986;RIGHT WHITE PARENTHESIS;Pe;0;ON;;;;;Y;;;;; 2987;Z NOTATION LEFT IMAGE BRACKET;Ps;0;ON;;;;;Y;;;;; 2988;Z NOTATION RIGHT IMAGE BRACKET;Pe;0;ON;;;;;Y;;;;; 2989;Z NOTATION LEFT BINDING BRACKET;Ps;0;ON;;;;;Y;;;;; 298A;Z NOTATION RIGHT BINDING BRACKET;Pe;0;ON;;;;;Y;;;;; 298B;LEFT SQUARE BRACKET WITH UNDERBAR;Ps;0;ON;;;;;Y;;;;; 298C;RIGHT SQUARE BRACKET WITH UNDERBAR;Pe;0;ON;;;;;Y;;;;; 298D;LEFT SQUARE BRACKET WITH TICK IN TOP CORNER;Ps;0;ON;;;;;Y;;;;; 298E;RIGHT SQUARE BRACKET WITH TICK IN BOTTOM CORNER;Pe;0;ON;;;;;Y;;;;; 298F;LEFT SQUARE BRACKET WITH TICK IN BOTTOM CORNER;Ps;0;ON;;;;;Y;;;;; 2990;RIGHT SQUARE BRACKET WITH TICK IN TOP CORNER;Pe;0;ON;;;;;Y;;;;; 2991;LEFT ANGLE BRACKET WITH DOT;Ps;0;ON;;;;;Y;;;;; 2992;RIGHT ANGLE BRACKET WITH DOT;Pe;0;ON;;;;;Y;;;;; 2993;LEFT ARC LESS-THAN BRACKET;Ps;0;ON;;;;;Y;;;;; 2994;RIGHT ARC GREATER-THAN BRACKET;Pe;0;ON;;;;;Y;;;;; 2995;DOUBLE LEFT ARC GREATER-THAN BRACKET;Ps;0;ON;;;;;Y;;;;; 2996;DOUBLE RIGHT ARC LESS-THAN BRACKET;Pe;0;ON;;;;;Y;;;;; 2997;LEFT BLACK TORTOISE SHELL BRACKET;Ps;0;ON;;;;;Y;;;;; 2998;RIGHT BLACK TORTOISE SHELL BRACKET;Pe;0;ON;;;;;Y;;;;; 2999;DOTTED FENCE;Sm;0;ON;;;;;N;;;;; 299A;VERTICAL ZIGZAG LINE;Sm;0;ON;;;;;N;;;;; 299B;MEASURED ANGLE OPENING LEFT;Sm;0;ON;;;;;Y;;;;; 299C;RIGHT ANGLE VARIANT WITH SQUARE;Sm;0;ON;;;;;Y;;;;; 299D;MEASURED RIGHT ANGLE WITH DOT;Sm;0;ON;;;;;Y;;;;; 299E;ANGLE WITH S INSIDE;Sm;0;ON;;;;;Y;;;;; 299F;ACUTE ANGLE;Sm;0;ON;;;;;Y;;;;; 29A0;SPHERICAL ANGLE OPENING LEFT;Sm;0;ON;;;;;Y;;;;; 29A1;SPHERICAL ANGLE OPENING UP;Sm;0;ON;;;;;Y;;;;; 29A2;TURNED ANGLE;Sm;0;ON;;;;;Y;;;;; 29A3;REVERSED ANGLE;Sm;0;ON;;;;;Y;;;;; 29A4;ANGLE WITH UNDERBAR;Sm;0;ON;;;;;Y;;;;; 29A5;REVERSED ANGLE WITH UNDERBAR;Sm;0;ON;;;;;Y;;;;; 29A6;OBLIQUE ANGLE OPENING UP;Sm;0;ON;;;;;Y;;;;; 29A7;OBLIQUE ANGLE OPENING DOWN;Sm;0;ON;;;;;Y;;;;; 29A8;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING UP AND RIGHT;Sm;0;ON;;;;;Y;;;;; 29A9;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING UP AND LEFT;Sm;0;ON;;;;;Y;;;;; 29AA;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING DOWN AND RIGHT;Sm;0;ON;;;;;Y;;;;; 29AB;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING DOWN AND LEFT;Sm;0;ON;;;;;Y;;;;; 29AC;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING RIGHT AND UP;Sm;0;ON;;;;;Y;;;;; 29AD;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING LEFT AND UP;Sm;0;ON;;;;;Y;;;;; 29AE;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING RIGHT AND DOWN;Sm;0;ON;;;;;Y;;;;; 29AF;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING LEFT AND DOWN;Sm;0;ON;;;;;Y;;;;; 29B0;REVERSED EMPTY SET;Sm;0;ON;;;;;N;;;;; 29B1;EMPTY SET WITH OVERBAR;Sm;0;ON;;;;;N;;;;; 29B2;EMPTY SET WITH SMALL CIRCLE ABOVE;Sm;0;ON;;;;;N;;;;; 29B3;EMPTY SET WITH RIGHT ARROW ABOVE;Sm;0;ON;;;;;N;;;;; 29B4;EMPTY SET WITH LEFT ARROW ABOVE;Sm;0;ON;;;;;N;;;;; 29B5;CIRCLE WITH HORIZONTAL BAR;Sm;0;ON;;;;;N;;;;; 29B6;CIRCLED VERTICAL BAR;Sm;0;ON;;;;;N;;;;; 29B7;CIRCLED PARALLEL;Sm;0;ON;;;;;N;;;;; 29B8;CIRCLED REVERSE SOLIDUS;Sm;0;ON;;;;;Y;;;;; 29B9;CIRCLED PERPENDICULAR;Sm;0;ON;;;;;N;;;;; 29BA;CIRCLE DIVIDED BY HORIZONTAL BAR AND TOP HALF DIVIDED BY VERTICAL BAR;Sm;0;ON;;;;;N;;;;; 29BB;CIRCLE WITH SUPERIMPOSED X;Sm;0;ON;;;;;N;;;;; 29BC;CIRCLED ANTICLOCKWISE-ROTATED DIVISION SIGN;Sm;0;ON;;;;;N;;;;; 29BD;UP ARROW THROUGH CIRCLE;Sm;0;ON;;;;;N;;;;; 29BE;CIRCLED WHITE BULLET;Sm;0;ON;;;;;N;;;;; 29BF;CIRCLED BULLET;Sm;0;ON;;;;;N;;;;; 29C0;CIRCLED LESS-THAN;Sm;0;ON;;;;;Y;;;;; 29C1;CIRCLED GREATER-THAN;Sm;0;ON;;;;;Y;;;;; 29C2;CIRCLE WITH SMALL CIRCLE TO THE RIGHT;Sm;0;ON;;;;;Y;;;;; 29C3;CIRCLE WITH TWO HORIZONTAL STROKES TO THE RIGHT;Sm;0;ON;;;;;Y;;;;; 29C4;SQUARED RISING DIAGONAL SLASH;Sm;0;ON;;;;;Y;;;;; 29C5;SQUARED FALLING DIAGONAL SLASH;Sm;0;ON;;;;;Y;;;;; 29C6;SQUARED ASTERISK;Sm;0;ON;;;;;N;;;;; 29C7;SQUARED SMALL CIRCLE;Sm;0;ON;;;;;N;;;;; 29C8;SQUARED SQUARE;Sm;0;ON;;;;;N;;;;; 29C9;TWO JOINED SQUARES;Sm;0;ON;;;;;Y;;;;; 29CA;TRIANGLE WITH DOT ABOVE;Sm;0;ON;;;;;N;;;;; 29CB;TRIANGLE WITH UNDERBAR;Sm;0;ON;;;;;N;;;;; 29CC;S IN TRIANGLE;Sm;0;ON;;;;;N;;;;; 29CD;TRIANGLE WITH SERIFS AT BOTTOM;Sm;0;ON;;;;;N;;;;; 29CE;RIGHT TRIANGLE ABOVE LEFT TRIANGLE;Sm;0;ON;;;;;Y;;;;; 29CF;LEFT TRIANGLE BESIDE VERTICAL BAR;Sm;0;ON;;;;;Y;;;;; 29D0;VERTICAL BAR BESIDE RIGHT TRIANGLE;Sm;0;ON;;;;;Y;;;;; 29D1;BOWTIE WITH LEFT HALF BLACK;Sm;0;ON;;;;;Y;;;;; 29D2;BOWTIE WITH RIGHT HALF BLACK;Sm;0;ON;;;;;Y;;;;; 29D3;BLACK BOWTIE;Sm;0;ON;;;;;N;;;;; 29D4;TIMES WITH LEFT HALF BLACK;Sm;0;ON;;;;;Y;;;;; 29D5;TIMES WITH RIGHT HALF BLACK;Sm;0;ON;;;;;Y;;;;; 29D6;WHITE HOURGLASS;Sm;0;ON;;;;;N;;;;; 29D7;BLACK HOURGLASS;Sm;0;ON;;;;;N;;;;; 29D8;LEFT WIGGLY FENCE;Ps;0;ON;;;;;Y;;;;; 29D9;RIGHT WIGGLY FENCE;Pe;0;ON;;;;;Y;;;;; 29DA;LEFT DOUBLE WIGGLY FENCE;Ps;0;ON;;;;;Y;;;;; 29DB;RIGHT DOUBLE WIGGLY FENCE;Pe;0;ON;;;;;Y;;;;; 29DC;INCOMPLETE INFINITY;Sm;0;ON;;;;;Y;;;;; 29DD;TIE OVER INFINITY;Sm;0;ON;;;;;N;;;;; 29DE;INFINITY NEGATED WITH VERTICAL BAR;Sm;0;ON;;;;;N;;;;; 29DF;DOUBLE-ENDED MULTIMAP;Sm;0;ON;;;;;N;;;;; 29E0;SQUARE WITH CONTOURED OUTLINE;Sm;0;ON;;;;;N;;;;; 29E1;INCREASES AS;Sm;0;ON;;;;;Y;;;;; 29E2;SHUFFLE PRODUCT;Sm;0;ON;;;;;N;;;;; 29E3;EQUALS SIGN AND SLANTED PARALLEL;Sm;0;ON;;;;;Y;;;;; 29E4;EQUALS SIGN AND SLANTED PARALLEL WITH TILDE ABOVE;Sm;0;ON;;;;;Y;;;;; 29E5;IDENTICAL TO AND SLANTED PARALLEL;Sm;0;ON;;;;;Y;;;;; 29E6;GLEICH STARK;Sm;0;ON;;;;;N;;;;; 29E7;THERMODYNAMIC;Sm;0;ON;;;;;N;;;;; 29E8;DOWN-POINTING TRIANGLE WITH LEFT HALF BLACK;Sm;0;ON;;;;;Y;;;;; 29E9;DOWN-POINTING TRIANGLE WITH RIGHT HALF BLACK;Sm;0;ON;;;;;Y;;;;; 29EA;BLACK DIAMOND WITH DOWN ARROW;Sm;0;ON;;;;;N;;;;; 29EB;BLACK LOZENGE;Sm;0;ON;;;;;N;;;;; 29EC;WHITE CIRCLE WITH DOWN ARROW;Sm;0;ON;;;;;N;;;;; 29ED;BLACK CIRCLE WITH DOWN ARROW;Sm;0;ON;;;;;N;;;;; 29EE;ERROR-BARRED WHITE SQUARE;Sm;0;ON;;;;;N;;;;; 29EF;ERROR-BARRED BLACK SQUARE;Sm;0;ON;;;;;N;;;;; 29F0;ERROR-BARRED WHITE DIAMOND;Sm;0;ON;;;;;N;;;;; 29F1;ERROR-BARRED BLACK DIAMOND;Sm;0;ON;;;;;N;;;;; 29F2;ERROR-BARRED WHITE CIRCLE;Sm;0;ON;;;;;N;;;;; 29F3;ERROR-BARRED BLACK CIRCLE;Sm;0;ON;;;;;N;;;;; 29F4;RULE-DELAYED;Sm;0;ON;;;;;Y;;;;; 29F5;REVERSE SOLIDUS OPERATOR;Sm;0;ON;;;;;Y;;;;; 29F6;SOLIDUS WITH OVERBAR;Sm;0;ON;;;;;Y;;;;; 29F7;REVERSE SOLIDUS WITH HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;; 29F8;BIG SOLIDUS;Sm;0;ON;;;;;Y;;;;; 29F9;BIG REVERSE SOLIDUS;Sm;0;ON;;;;;Y;;;;; 29FA;DOUBLE PLUS;Sm;0;ON;;;;;N;;;;; 29FB;TRIPLE PLUS;Sm;0;ON;;;;;N;;;;; 29FC;LEFT-POINTING CURVED ANGLE BRACKET;Ps;0;ON;;;;;Y;;;;; 29FD;RIGHT-POINTING CURVED ANGLE BRACKET;Pe;0;ON;;;;;Y;;;;; 29FE;TINY;Sm;0;ON;;;;;N;;;;; 29FF;MINY;Sm;0;ON;;;;;N;;;;; 2A00;N-ARY CIRCLED DOT OPERATOR;Sm;0;ON;;;;;N;;;;; 2A01;N-ARY CIRCLED PLUS OPERATOR;Sm;0;ON;;;;;N;;;;; 2A02;N-ARY CIRCLED TIMES OPERATOR;Sm;0;ON;;;;;N;;;;; 2A03;N-ARY UNION OPERATOR WITH DOT;Sm;0;ON;;;;;N;;;;; 2A04;N-ARY UNION OPERATOR WITH PLUS;Sm;0;ON;;;;;N;;;;; 2A05;N-ARY SQUARE INTERSECTION OPERATOR;Sm;0;ON;;;;;N;;;;; 2A06;N-ARY SQUARE UNION OPERATOR;Sm;0;ON;;;;;N;;;;; 2A07;TWO LOGICAL AND OPERATOR;Sm;0;ON;;;;;N;;;;; 2A08;TWO LOGICAL OR OPERATOR;Sm;0;ON;;;;;N;;;;; 2A09;N-ARY TIMES OPERATOR;Sm;0;ON;;;;;N;;;;; 2A0A;MODULO TWO SUM;Sm;0;ON;;;;;Y;;;;; 2A0B;SUMMATION WITH INTEGRAL;Sm;0;ON;;;;;Y;;;;; 2A0C;QUADRUPLE INTEGRAL OPERATOR;Sm;0;ON; 222B 222B 222B 222B;;;;Y;;;;; 2A0D;FINITE PART INTEGRAL;Sm;0;ON;;;;;Y;;;;; 2A0E;INTEGRAL WITH DOUBLE STROKE;Sm;0;ON;;;;;Y;;;;; 2A0F;INTEGRAL AVERAGE WITH SLASH;Sm;0;ON;;;;;Y;;;;; 2A10;CIRCULATION FUNCTION;Sm;0;ON;;;;;Y;;;;; 2A11;ANTICLOCKWISE INTEGRATION;Sm;0;ON;;;;;Y;;;;; 2A12;LINE INTEGRATION WITH RECTANGULAR PATH AROUND POLE;Sm;0;ON;;;;;Y;;;;; 2A13;LINE INTEGRATION WITH SEMICIRCULAR PATH AROUND POLE;Sm;0;ON;;;;;Y;;;;; 2A14;LINE INTEGRATION NOT INCLUDING THE POLE;Sm;0;ON;;;;;Y;;;;; 2A15;INTEGRAL AROUND A POINT OPERATOR;Sm;0;ON;;;;;Y;;;;; 2A16;QUATERNION INTEGRAL OPERATOR;Sm;0;ON;;;;;Y;;;;; 2A17;INTEGRAL WITH LEFTWARDS ARROW WITH HOOK;Sm;0;ON;;;;;Y;;;;; 2A18;INTEGRAL WITH TIMES SIGN;Sm;0;ON;;;;;Y;;;;; 2A19;INTEGRAL WITH INTERSECTION;Sm;0;ON;;;;;Y;;;;; 2A1A;INTEGRAL WITH UNION;Sm;0;ON;;;;;Y;;;;; 2A1B;INTEGRAL WITH OVERBAR;Sm;0;ON;;;;;Y;;;;; 2A1C;INTEGRAL WITH UNDERBAR;Sm;0;ON;;;;;Y;;;;; 2A1D;JOIN;Sm;0;ON;;;;;N;;;;; 2A1E;LARGE LEFT TRIANGLE OPERATOR;Sm;0;ON;;;;;Y;;;;; 2A1F;Z NOTATION SCHEMA COMPOSITION;Sm;0;ON;;;;;Y;;;;; 2A20;Z NOTATION SCHEMA PIPING;Sm;0;ON;;;;;Y;;;;; 2A21;Z NOTATION SCHEMA PROJECTION;Sm;0;ON;;;;;Y;;;;; 2A22;PLUS SIGN WITH SMALL CIRCLE ABOVE;Sm;0;ON;;;;;N;;;;; 2A23;PLUS SIGN WITH CIRCUMFLEX ACCENT ABOVE;Sm;0;ON;;;;;N;;;;; 2A24;PLUS SIGN WITH TILDE ABOVE;Sm;0;ON;;;;;Y;;;;; 2A25;PLUS SIGN WITH DOT BELOW;Sm;0;ON;;;;;N;;;;; 2A26;PLUS SIGN WITH TILDE BELOW;Sm;0;ON;;;;;Y;;;;; 2A27;PLUS SIGN WITH SUBSCRIPT TWO;Sm;0;ON;;;;;N;;;;; 2A28;PLUS SIGN WITH BLACK TRIANGLE;Sm;0;ON;;;;;N;;;;; 2A29;MINUS SIGN WITH COMMA ABOVE;Sm;0;ON;;;;;Y;;;;; 2A2A;MINUS SIGN WITH DOT BELOW;Sm;0;ON;;;;;N;;;;; 2A2B;MINUS SIGN WITH FALLING DOTS;Sm;0;ON;;;;;Y;;;;; 2A2C;MINUS SIGN WITH RISING DOTS;Sm;0;ON;;;;;Y;;;;; 2A2D;PLUS SIGN IN LEFT HALF CIRCLE;Sm;0;ON;;;;;Y;;;;; 2A2E;PLUS SIGN IN RIGHT HALF CIRCLE;Sm;0;ON;;;;;Y;;;;; 2A2F;VECTOR OR CROSS PRODUCT;Sm;0;ON;;;;;N;;;;; 2A30;MULTIPLICATION SIGN WITH DOT ABOVE;Sm;0;ON;;;;;N;;;;; 2A31;MULTIPLICATION SIGN WITH UNDERBAR;Sm;0;ON;;;;;N;;;;; 2A32;SEMIDIRECT PRODUCT WITH BOTTOM CLOSED;Sm;0;ON;;;;;N;;;;; 2A33;SMASH PRODUCT;Sm;0;ON;;;;;N;;;;; 2A34;MULTIPLICATION SIGN IN LEFT HALF CIRCLE;Sm;0;ON;;;;;Y;;;;; 2A35;MULTIPLICATION SIGN IN RIGHT HALF CIRCLE;Sm;0;ON;;;;;Y;;;;; 2A36;CIRCLED MULTIPLICATION SIGN WITH CIRCUMFLEX ACCENT;Sm;0;ON;;;;;N;;;;; 2A37;MULTIPLICATION SIGN IN DOUBLE CIRCLE;Sm;0;ON;;;;;N;;;;; 2A38;CIRCLED DIVISION SIGN;Sm;0;ON;;;;;N;;;;; 2A39;PLUS SIGN IN TRIANGLE;Sm;0;ON;;;;;N;;;;; 2A3A;MINUS SIGN IN TRIANGLE;Sm;0;ON;;;;;N;;;;; 2A3B;MULTIPLICATION SIGN IN TRIANGLE;Sm;0;ON;;;;;N;;;;; 2A3C;INTERIOR PRODUCT;Sm;0;ON;;;;;Y;;;;; 2A3D;RIGHTHAND INTERIOR PRODUCT;Sm;0;ON;;;;;Y;;;;; 2A3E;Z NOTATION RELATIONAL COMPOSITION;Sm;0;ON;;;;;Y;;;;; 2A3F;AMALGAMATION OR COPRODUCT;Sm;0;ON;;;;;N;;;;; 2A40;INTERSECTION WITH DOT;Sm;0;ON;;;;;N;;;;; 2A41;UNION WITH MINUS SIGN;Sm;0;ON;;;;;N;;;;; 2A42;UNION WITH OVERBAR;Sm;0;ON;;;;;N;;;;; 2A43;INTERSECTION WITH OVERBAR;Sm;0;ON;;;;;N;;;;; 2A44;INTERSECTION WITH LOGICAL AND;Sm;0;ON;;;;;N;;;;; 2A45;UNION WITH LOGICAL OR;Sm;0;ON;;;;;N;;;;; 2A46;UNION ABOVE INTERSECTION;Sm;0;ON;;;;;N;;;;; 2A47;INTERSECTION ABOVE UNION;Sm;0;ON;;;;;N;;;;; 2A48;UNION ABOVE BAR ABOVE INTERSECTION;Sm;0;ON;;;;;N;;;;; 2A49;INTERSECTION ABOVE BAR ABOVE UNION;Sm;0;ON;;;;;N;;;;; 2A4A;UNION BESIDE AND JOINED WITH UNION;Sm;0;ON;;;;;N;;;;; 2A4B;INTERSECTION BESIDE AND JOINED WITH INTERSECTION;Sm;0;ON;;;;;N;;;;; 2A4C;CLOSED UNION WITH SERIFS;Sm;0;ON;;;;;N;;;;; 2A4D;CLOSED INTERSECTION WITH SERIFS;Sm;0;ON;;;;;N;;;;; 2A4E;DOUBLE SQUARE INTERSECTION;Sm;0;ON;;;;;N;;;;; 2A4F;DOUBLE SQUARE UNION;Sm;0;ON;;;;;N;;;;; 2A50;CLOSED UNION WITH SERIFS AND SMASH PRODUCT;Sm;0;ON;;;;;N;;;;; 2A51;LOGICAL AND WITH DOT ABOVE;Sm;0;ON;;;;;N;;;;; 2A52;LOGICAL OR WITH DOT ABOVE;Sm;0;ON;;;;;N;;;;; 2A53;DOUBLE LOGICAL AND;Sm;0;ON;;;;;N;;;;; 2A54;DOUBLE LOGICAL OR;Sm;0;ON;;;;;N;;;;; 2A55;TWO INTERSECTING LOGICAL AND;Sm;0;ON;;;;;N;;;;; 2A56;TWO INTERSECTING LOGICAL OR;Sm;0;ON;;;;;N;;;;; 2A57;SLOPING LARGE OR;Sm;0;ON;;;;;Y;;;;; 2A58;SLOPING LARGE AND;Sm;0;ON;;;;;Y;;;;; 2A59;LOGICAL OR OVERLAPPING LOGICAL AND;Sm;0;ON;;;;;N;;;;; 2A5A;LOGICAL AND WITH MIDDLE STEM;Sm;0;ON;;;;;N;;;;; 2A5B;LOGICAL OR WITH MIDDLE STEM;Sm;0;ON;;;;;N;;;;; 2A5C;LOGICAL AND WITH HORIZONTAL DASH;Sm;0;ON;;;;;N;;;;; 2A5D;LOGICAL OR WITH HORIZONTAL DASH;Sm;0;ON;;;;;N;;;;; 2A5E;LOGICAL AND WITH DOUBLE OVERBAR;Sm;0;ON;;;;;N;;;;; 2A5F;LOGICAL AND WITH UNDERBAR;Sm;0;ON;;;;;N;;;;; 2A60;LOGICAL AND WITH DOUBLE UNDERBAR;Sm;0;ON;;;;;N;;;;; 2A61;SMALL VEE WITH UNDERBAR;Sm;0;ON;;;;;N;;;;; 2A62;LOGICAL OR WITH DOUBLE OVERBAR;Sm;0;ON;;;;;N;;;;; 2A63;LOGICAL OR WITH DOUBLE UNDERBAR;Sm;0;ON;;;;;N;;;;; 2A64;Z NOTATION DOMAIN ANTIRESTRICTION;Sm;0;ON;;;;;Y;;;;; 2A65;Z NOTATION RANGE ANTIRESTRICTION;Sm;0;ON;;;;;Y;;;;; 2A66;EQUALS SIGN WITH DOT BELOW;Sm;0;ON;;;;;N;;;;; 2A67;IDENTICAL WITH DOT ABOVE;Sm;0;ON;;;;;N;;;;; 2A68;TRIPLE HORIZONTAL BAR WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2A69;TRIPLE HORIZONTAL BAR WITH TRIPLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2A6A;TILDE OPERATOR WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;; 2A6B;TILDE OPERATOR WITH RISING DOTS;Sm;0;ON;;;;;Y;;;;; 2A6C;SIMILAR MINUS SIMILAR;Sm;0;ON;;;;;Y;;;;; 2A6D;CONGRUENT WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;; 2A6E;EQUALS WITH ASTERISK;Sm;0;ON;;;;;N;;;;; 2A6F;ALMOST EQUAL TO WITH CIRCUMFLEX ACCENT;Sm;0;ON;;;;;Y;;;;; 2A70;APPROXIMATELY EQUAL OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2A71;EQUALS SIGN ABOVE PLUS SIGN;Sm;0;ON;;;;;N;;;;; 2A72;PLUS SIGN ABOVE EQUALS SIGN;Sm;0;ON;;;;;N;;;;; 2A73;EQUALS SIGN ABOVE TILDE OPERATOR;Sm;0;ON;;;;;Y;;;;; 2A74;DOUBLE COLON EQUAL;Sm;0;ON; 003A 003A 003D;;;;Y;;;;; 2A75;TWO CONSECUTIVE EQUALS SIGNS;Sm;0;ON; 003D 003D;;;;N;;;;; 2A76;THREE CONSECUTIVE EQUALS SIGNS;Sm;0;ON; 003D 003D 003D;;;;N;;;;; 2A77;EQUALS SIGN WITH TWO DOTS ABOVE AND TWO DOTS BELOW;Sm;0;ON;;;;;N;;;;; 2A78;EQUIVALENT WITH FOUR DOTS ABOVE;Sm;0;ON;;;;;N;;;;; 2A79;LESS-THAN WITH CIRCLE INSIDE;Sm;0;ON;;;;;Y;;;;; 2A7A;GREATER-THAN WITH CIRCLE INSIDE;Sm;0;ON;;;;;Y;;;;; 2A7B;LESS-THAN WITH QUESTION MARK ABOVE;Sm;0;ON;;;;;Y;;;;; 2A7C;GREATER-THAN WITH QUESTION MARK ABOVE;Sm;0;ON;;;;;Y;;;;; 2A7D;LESS-THAN OR SLANTED EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2A7E;GREATER-THAN OR SLANTED EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2A7F;LESS-THAN OR SLANTED EQUAL TO WITH DOT INSIDE;Sm;0;ON;;;;;Y;;;;; 2A80;GREATER-THAN OR SLANTED EQUAL TO WITH DOT INSIDE;Sm;0;ON;;;;;Y;;;;; 2A81;LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;; 2A82;GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;; 2A83;LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE RIGHT;Sm;0;ON;;;;;Y;;;;; 2A84;GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE LEFT;Sm;0;ON;;;;;Y;;;;; 2A85;LESS-THAN OR APPROXIMATE;Sm;0;ON;;;;;Y;;;;; 2A86;GREATER-THAN OR APPROXIMATE;Sm;0;ON;;;;;Y;;;;; 2A87;LESS-THAN AND SINGLE-LINE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2A88;GREATER-THAN AND SINGLE-LINE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2A89;LESS-THAN AND NOT APPROXIMATE;Sm;0;ON;;;;;Y;;;;; 2A8A;GREATER-THAN AND NOT APPROXIMATE;Sm;0;ON;;;;;Y;;;;; 2A8B;LESS-THAN ABOVE DOUBLE-LINE EQUAL ABOVE GREATER-THAN;Sm;0;ON;;;;;Y;;;;; 2A8C;GREATER-THAN ABOVE DOUBLE-LINE EQUAL ABOVE LESS-THAN;Sm;0;ON;;;;;Y;;;;; 2A8D;LESS-THAN ABOVE SIMILAR OR EQUAL;Sm;0;ON;;;;;Y;;;;; 2A8E;GREATER-THAN ABOVE SIMILAR OR EQUAL;Sm;0;ON;;;;;Y;;;;; 2A8F;LESS-THAN ABOVE SIMILAR ABOVE GREATER-THAN;Sm;0;ON;;;;;Y;;;;; 2A90;GREATER-THAN ABOVE SIMILAR ABOVE LESS-THAN;Sm;0;ON;;;;;Y;;;;; 2A91;LESS-THAN ABOVE GREATER-THAN ABOVE DOUBLE-LINE EQUAL;Sm;0;ON;;;;;Y;;;;; 2A92;GREATER-THAN ABOVE LESS-THAN ABOVE DOUBLE-LINE EQUAL;Sm;0;ON;;;;;Y;;;;; 2A93;LESS-THAN ABOVE SLANTED EQUAL ABOVE GREATER-THAN ABOVE SLANTED EQUAL;Sm;0;ON;;;;;Y;;;;; 2A94;GREATER-THAN ABOVE SLANTED EQUAL ABOVE LESS-THAN ABOVE SLANTED EQUAL;Sm;0;ON;;;;;Y;;;;; 2A95;SLANTED EQUAL TO OR LESS-THAN;Sm;0;ON;;;;;Y;;;;; 2A96;SLANTED EQUAL TO OR GREATER-THAN;Sm;0;ON;;;;;Y;;;;; 2A97;SLANTED EQUAL TO OR LESS-THAN WITH DOT INSIDE;Sm;0;ON;;;;;Y;;;;; 2A98;SLANTED EQUAL TO OR GREATER-THAN WITH DOT INSIDE;Sm;0;ON;;;;;Y;;;;; 2A99;DOUBLE-LINE EQUAL TO OR LESS-THAN;Sm;0;ON;;;;;Y;;;;; 2A9A;DOUBLE-LINE EQUAL TO OR GREATER-THAN;Sm;0;ON;;;;;Y;;;;; 2A9B;DOUBLE-LINE SLANTED EQUAL TO OR LESS-THAN;Sm;0;ON;;;;;Y;;;;; 2A9C;DOUBLE-LINE SLANTED EQUAL TO OR GREATER-THAN;Sm;0;ON;;;;;Y;;;;; 2A9D;SIMILAR OR LESS-THAN;Sm;0;ON;;;;;Y;;;;; 2A9E;SIMILAR OR GREATER-THAN;Sm;0;ON;;;;;Y;;;;; 2A9F;SIMILAR ABOVE LESS-THAN ABOVE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;; 2AA0;SIMILAR ABOVE GREATER-THAN ABOVE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;; 2AA1;DOUBLE NESTED LESS-THAN;Sm;0;ON;;;;;Y;;;;; 2AA2;DOUBLE NESTED GREATER-THAN;Sm;0;ON;;;;;Y;;;;; 2AA3;DOUBLE NESTED LESS-THAN WITH UNDERBAR;Sm;0;ON;;;;;Y;;;;; 2AA4;GREATER-THAN OVERLAPPING LESS-THAN;Sm;0;ON;;;;;N;;;;; 2AA5;GREATER-THAN BESIDE LESS-THAN;Sm;0;ON;;;;;N;;;;; 2AA6;LESS-THAN CLOSED BY CURVE;Sm;0;ON;;;;;Y;;;;; 2AA7;GREATER-THAN CLOSED BY CURVE;Sm;0;ON;;;;;Y;;;;; 2AA8;LESS-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL;Sm;0;ON;;;;;Y;;;;; 2AA9;GREATER-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL;Sm;0;ON;;;;;Y;;;;; 2AAA;SMALLER THAN;Sm;0;ON;;;;;Y;;;;; 2AAB;LARGER THAN;Sm;0;ON;;;;;Y;;;;; 2AAC;SMALLER THAN OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2AAD;LARGER THAN OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2AAE;EQUALS SIGN WITH BUMPY ABOVE;Sm;0;ON;;;;;N;;;;; 2AAF;PRECEDES ABOVE SINGLE-LINE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;; 2AB0;SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;; 2AB1;PRECEDES ABOVE SINGLE-LINE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2AB2;SUCCEEDS ABOVE SINGLE-LINE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2AB3;PRECEDES ABOVE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;; 2AB4;SUCCEEDS ABOVE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;; 2AB5;PRECEDES ABOVE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2AB6;SUCCEEDS ABOVE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2AB7;PRECEDES ABOVE ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2AB8;SUCCEEDS ABOVE ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2AB9;PRECEDES ABOVE NOT ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2ABA;SUCCEEDS ABOVE NOT ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2ABB;DOUBLE PRECEDES;Sm;0;ON;;;;;Y;;;;; 2ABC;DOUBLE SUCCEEDS;Sm;0;ON;;;;;Y;;;;; 2ABD;SUBSET WITH DOT;Sm;0;ON;;;;;Y;;;;; 2ABE;SUPERSET WITH DOT;Sm;0;ON;;;;;Y;;;;; 2ABF;SUBSET WITH PLUS SIGN BELOW;Sm;0;ON;;;;;Y;;;;; 2AC0;SUPERSET WITH PLUS SIGN BELOW;Sm;0;ON;;;;;Y;;;;; 2AC1;SUBSET WITH MULTIPLICATION SIGN BELOW;Sm;0;ON;;;;;Y;;;;; 2AC2;SUPERSET WITH MULTIPLICATION SIGN BELOW;Sm;0;ON;;;;;Y;;;;; 2AC3;SUBSET OF OR EQUAL TO WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;; 2AC4;SUPERSET OF OR EQUAL TO WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;; 2AC5;SUBSET OF ABOVE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;; 2AC6;SUPERSET OF ABOVE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;; 2AC7;SUBSET OF ABOVE TILDE OPERATOR;Sm;0;ON;;;;;Y;;;;; 2AC8;SUPERSET OF ABOVE TILDE OPERATOR;Sm;0;ON;;;;;Y;;;;; 2AC9;SUBSET OF ABOVE ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2ACA;SUPERSET OF ABOVE ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2ACB;SUBSET OF ABOVE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2ACC;SUPERSET OF ABOVE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2ACD;SQUARE LEFT OPEN BOX OPERATOR;Sm;0;ON;;;;;Y;;;;; 2ACE;SQUARE RIGHT OPEN BOX OPERATOR;Sm;0;ON;;;;;Y;;;;; 2ACF;CLOSED SUBSET;Sm;0;ON;;;;;Y;;;;; 2AD0;CLOSED SUPERSET;Sm;0;ON;;;;;Y;;;;; 2AD1;CLOSED SUBSET OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2AD2;CLOSED SUPERSET OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2AD3;SUBSET ABOVE SUPERSET;Sm;0;ON;;;;;Y;;;;; 2AD4;SUPERSET ABOVE SUBSET;Sm;0;ON;;;;;Y;;;;; 2AD5;SUBSET ABOVE SUBSET;Sm;0;ON;;;;;Y;;;;; 2AD6;SUPERSET ABOVE SUPERSET;Sm;0;ON;;;;;Y;;;;; 2AD7;SUPERSET BESIDE SUBSET;Sm;0;ON;;;;;N;;;;; 2AD8;SUPERSET BESIDE AND JOINED BY DASH WITH SUBSET;Sm;0;ON;;;;;N;;;;; 2AD9;ELEMENT OF OPENING DOWNWARDS;Sm;0;ON;;;;;N;;;;; 2ADA;PITCHFORK WITH TEE TOP;Sm;0;ON;;;;;N;;;;; 2ADB;TRANSVERSAL INTERSECTION;Sm;0;ON;;;;;N;;;;; 2ADC;FORKING;Sm;0;ON;2ADD 0338;;;;Y;;not independent;;; 2ADD;NONFORKING;Sm;0;ON;;;;;N;;independent;;; 2ADE;SHORT LEFT TACK;Sm;0;ON;;;;;Y;;;;; 2ADF;SHORT DOWN TACK;Sm;0;ON;;;;;N;;;;; 2AE0;SHORT UP TACK;Sm;0;ON;;;;;N;;;;; 2AE1;PERPENDICULAR WITH S;Sm;0;ON;;;;;N;;;;; 2AE2;VERTICAL BAR TRIPLE RIGHT TURNSTILE;Sm;0;ON;;;;;Y;;;;; 2AE3;DOUBLE VERTICAL BAR LEFT TURNSTILE;Sm;0;ON;;;;;Y;;;;; 2AE4;VERTICAL BAR DOUBLE LEFT TURNSTILE;Sm;0;ON;;;;;Y;;;;; 2AE5;DOUBLE VERTICAL BAR DOUBLE LEFT TURNSTILE;Sm;0;ON;;;;;Y;;;;; 2AE6;LONG DASH FROM LEFT MEMBER OF DOUBLE VERTICAL;Sm;0;ON;;;;;Y;;;;; 2AE7;SHORT DOWN TACK WITH OVERBAR;Sm;0;ON;;;;;N;;;;; 2AE8;SHORT UP TACK WITH UNDERBAR;Sm;0;ON;;;;;N;;;;; 2AE9;SHORT UP TACK ABOVE SHORT DOWN TACK;Sm;0;ON;;;;;N;;;;; 2AEA;DOUBLE DOWN TACK;Sm;0;ON;;;;;N;;;;; 2AEB;DOUBLE UP TACK;Sm;0;ON;;;;;N;;;;; 2AEC;DOUBLE STROKE NOT SIGN;Sm;0;ON;;;;;Y;;;;; 2AED;REVERSED DOUBLE STROKE NOT SIGN;Sm;0;ON;;;;;Y;;;;; 2AEE;DOES NOT DIVIDE WITH REVERSED NEGATION SLASH;Sm;0;ON;;;;;Y;;;;; 2AEF;VERTICAL LINE WITH CIRCLE ABOVE;Sm;0;ON;;;;;N;;;;; 2AF0;VERTICAL LINE WITH CIRCLE BELOW;Sm;0;ON;;;;;N;;;;; 2AF1;DOWN TACK WITH CIRCLE BELOW;Sm;0;ON;;;;;N;;;;; 2AF2;PARALLEL WITH HORIZONTAL STROKE;Sm;0;ON;;;;;N;;;;; 2AF3;PARALLEL WITH TILDE OPERATOR;Sm;0;ON;;;;;Y;;;;; 2AF4;TRIPLE VERTICAL BAR BINARY RELATION;Sm;0;ON;;;;;N;;;;; 2AF5;TRIPLE VERTICAL BAR WITH HORIZONTAL STROKE;Sm;0;ON;;;;;N;;;;; 2AF6;TRIPLE COLON OPERATOR;Sm;0;ON;;;;;N;;;;; 2AF7;TRIPLE NESTED LESS-THAN;Sm;0;ON;;;;;Y;;;;; 2AF8;TRIPLE NESTED GREATER-THAN;Sm;0;ON;;;;;Y;;;;; 2AF9;DOUBLE-LINE SLANTED LESS-THAN OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2AFA;DOUBLE-LINE SLANTED GREATER-THAN OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2AFB;TRIPLE SOLIDUS BINARY RELATION;Sm;0;ON;;;;;Y;;;;; 2AFC;LARGE TRIPLE VERTICAL BAR OPERATOR;Sm;0;ON;;;;;N;;;;; 2AFD;DOUBLE SOLIDUS OPERATOR;Sm;0;ON;;;;;Y;;;;; 2AFE;WHITE VERTICAL BAR;Sm;0;ON;;;;;N;;;;; 2AFF;N-ARY WHITE VERTICAL BAR;Sm;0;ON;;;;;N;;;;; 2E80;CJK RADICAL REPEAT;So;0;ON;;;;;N;;;;; 2E81;CJK RADICAL CLIFF;So;0;ON;;;;;N;;;;; 2E82;CJK RADICAL SECOND ONE;So;0;ON;;;;;N;;;;; 2E83;CJK RADICAL SECOND TWO;So;0;ON;;;;;N;;;;; 2E84;CJK RADICAL SECOND THREE;So;0;ON;;;;;N;;;;; 2E85;CJK RADICAL PERSON;So;0;ON;;;;;N;;;;; 2E86;CJK RADICAL BOX;So;0;ON;;;;;N;;;;; 2E87;CJK RADICAL TABLE;So;0;ON;;;;;N;;;;; 2E88;CJK RADICAL KNIFE ONE;So;0;ON;;;;;N;;;;; 2E89;CJK RADICAL KNIFE TWO;So;0;ON;;;;;N;;;;; 2E8A;CJK RADICAL DIVINATION;So;0;ON;;;;;N;;;;; 2E8B;CJK RADICAL SEAL;So;0;ON;;;;;N;;;;; 2E8C;CJK RADICAL SMALL ONE;So;0;ON;;;;;N;;;;; 2E8D;CJK RADICAL SMALL TWO;So;0;ON;;;;;N;;;;; 2E8E;CJK RADICAL LAME ONE;So;0;ON;;;;;N;;;;; 2E8F;CJK RADICAL LAME TWO;So;0;ON;;;;;N;;;;; 2E90;CJK RADICAL LAME THREE;So;0;ON;;;;;N;;;;; 2E91;CJK RADICAL LAME FOUR;So;0;ON;;;;;N;;;;; 2E92;CJK RADICAL SNAKE;So;0;ON;;;;;N;;;;; 2E93;CJK RADICAL THREAD;So;0;ON;;;;;N;;;;; 2E94;CJK RADICAL SNOUT ONE;So;0;ON;;;;;N;;;;; 2E95;CJK RADICAL SNOUT TWO;So;0;ON;;;;;N;;;;; 2E96;CJK RADICAL HEART ONE;So;0;ON;;;;;N;;;;; 2E97;CJK RADICAL HEART TWO;So;0;ON;;;;;N;;;;; 2E98;CJK RADICAL HAND;So;0;ON;;;;;N;;;;; 2E99;CJK RADICAL RAP;So;0;ON;;;;;N;;;;; 2E9B;CJK RADICAL CHOKE;So;0;ON;;;;;N;;;;; 2E9C;CJK RADICAL SUN;So;0;ON;;;;;N;;;;; 2E9D;CJK RADICAL MOON;So;0;ON;;;;;N;;;;; 2E9E;CJK RADICAL DEATH;So;0;ON;;;;;N;;;;; 2E9F;CJK RADICAL MOTHER;So;0;ON; 6BCD;;;;N;;;;; 2EA0;CJK RADICAL CIVILIAN;So;0;ON;;;;;N;;;;; 2EA1;CJK RADICAL WATER ONE;So;0;ON;;;;;N;;;;; 2EA2;CJK RADICAL WATER TWO;So;0;ON;;;;;N;;;;; 2EA3;CJK RADICAL FIRE;So;0;ON;;;;;N;;;;; 2EA4;CJK RADICAL PAW ONE;So;0;ON;;;;;N;;;;; 2EA5;CJK RADICAL PAW TWO;So;0;ON;;;;;N;;;;; 2EA6;CJK RADICAL SIMPLIFIED HALF TREE TRUNK;So;0;ON;;;;;N;;;;; 2EA7;CJK RADICAL COW;So;0;ON;;;;;N;;;;; 2EA8;CJK RADICAL DOG;So;0;ON;;;;;N;;;;; 2EA9;CJK RADICAL JADE;So;0;ON;;;;;N;;;;; 2EAA;CJK RADICAL BOLT OF CLOTH;So;0;ON;;;;;N;;;;; 2EAB;CJK RADICAL EYE;So;0;ON;;;;;N;;;;; 2EAC;CJK RADICAL SPIRIT ONE;So;0;ON;;;;;N;;;;; 2EAD;CJK RADICAL SPIRIT TWO;So;0;ON;;;;;N;;;;; 2EAE;CJK RADICAL BAMBOO;So;0;ON;;;;;N;;;;; 2EAF;CJK RADICAL SILK;So;0;ON;;;;;N;;;;; 2EB0;CJK RADICAL C-SIMPLIFIED SILK;So;0;ON;;;;;N;;;;; 2EB1;CJK RADICAL NET ONE;So;0;ON;;;;;N;;;;; 2EB2;CJK RADICAL NET TWO;So;0;ON;;;;;N;;;;; 2EB3;CJK RADICAL NET THREE;So;0;ON;;;;;N;;;;; 2EB4;CJK RADICAL NET FOUR;So;0;ON;;;;;N;;;;; 2EB5;CJK RADICAL MESH;So;0;ON;;;;;N;;;;; 2EB6;CJK RADICAL SHEEP;So;0;ON;;;;;N;;;;; 2EB7;CJK RADICAL RAM;So;0;ON;;;;;N;;;;; 2EB8;CJK RADICAL EWE;So;0;ON;;;;;N;;;;; 2EB9;CJK RADICAL OLD;So;0;ON;;;;;N;;;;; 2EBA;CJK RADICAL BRUSH ONE;So;0;ON;;;;;N;;;;; 2EBB;CJK RADICAL BRUSH TWO;So;0;ON;;;;;N;;;;; 2EBC;CJK RADICAL MEAT;So;0;ON;;;;;N;;;;; 2EBD;CJK RADICAL MORTAR;So;0;ON;;;;;N;;;;; 2EBE;CJK RADICAL GRASS ONE;So;0;ON;;;;;N;;;;; 2EBF;CJK RADICAL GRASS TWO;So;0;ON;;;;;N;;;;; 2EC0;CJK RADICAL GRASS THREE;So;0;ON;;;;;N;;;;; 2EC1;CJK RADICAL TIGER;So;0;ON;;;;;N;;;;; 2EC2;CJK RADICAL CLOTHES;So;0;ON;;;;;N;;;;; 2EC3;CJK RADICAL WEST ONE;So;0;ON;;;;;N;;;;; 2EC4;CJK RADICAL WEST TWO;So;0;ON;;;;;N;;;;; 2EC5;CJK RADICAL C-SIMPLIFIED SEE;So;0;ON;;;;;N;;;;; 2EC6;CJK RADICAL SIMPLIFIED HORN;So;0;ON;;;;;N;;;;; 2EC7;CJK RADICAL HORN;So;0;ON;;;;;N;;;;; 2EC8;CJK RADICAL C-SIMPLIFIED SPEECH;So;0;ON;;;;;N;;;;; 2EC9;CJK RADICAL C-SIMPLIFIED SHELL;So;0;ON;;;;;N;;;;; 2ECA;CJK RADICAL FOOT;So;0;ON;;;;;N;;;;; 2ECB;CJK RADICAL C-SIMPLIFIED CART;So;0;ON;;;;;N;;;;; 2ECC;CJK RADICAL SIMPLIFIED WALK;So;0;ON;;;;;N;;;;; 2ECD;CJK RADICAL WALK ONE;So;0;ON;;;;;N;;;;; 2ECE;CJK RADICAL WALK TWO;So;0;ON;;;;;N;;;;; 2ECF;CJK RADICAL CITY;So;0;ON;;;;;N;;;;; 2ED0;CJK RADICAL C-SIMPLIFIED GOLD;So;0;ON;;;;;N;;;;; 2ED1;CJK RADICAL LONG ONE;So;0;ON;;;;;N;;;;; 2ED2;CJK RADICAL LONG TWO;So;0;ON;;;;;N;;;;; 2ED3;CJK RADICAL C-SIMPLIFIED LONG;So;0;ON;;;;;N;;;;; 2ED4;CJK RADICAL C-SIMPLIFIED GATE;So;0;ON;;;;;N;;;;; 2ED5;CJK RADICAL MOUND ONE;So;0;ON;;;;;N;;;;; 2ED6;CJK RADICAL MOUND TWO;So;0;ON;;;;;N;;;;; 2ED7;CJK RADICAL RAIN;So;0;ON;;;;;N;;;;; 2ED8;CJK RADICAL BLUE;So;0;ON;;;;;N;;;;; 2ED9;CJK RADICAL C-SIMPLIFIED TANNED LEATHER;So;0;ON;;;;;N;;;;; 2EDA;CJK RADICAL C-SIMPLIFIED LEAF;So;0;ON;;;;;N;;;;; 2EDB;CJK RADICAL C-SIMPLIFIED WIND;So;0;ON;;;;;N;;;;; 2EDC;CJK RADICAL C-SIMPLIFIED FLY;So;0;ON;;;;;N;;;;; 2EDD;CJK RADICAL EAT ONE;So;0;ON;;;;;N;;;;; 2EDE;CJK RADICAL EAT TWO;So;0;ON;;;;;N;;;;; 2EDF;CJK RADICAL EAT THREE;So;0;ON;;;;;N;;;;; 2EE0;CJK RADICAL C-SIMPLIFIED EAT;So;0;ON;;;;;N;;;;; 2EE1;CJK RADICAL HEAD;So;0;ON;;;;;N;;;;; 2EE2;CJK RADICAL C-SIMPLIFIED HORSE;So;0;ON;;;;;N;;;;; 2EE3;CJK RADICAL BONE;So;0;ON;;;;;N;;;;; 2EE4;CJK RADICAL GHOST;So;0;ON;;;;;N;;;;; 2EE5;CJK RADICAL C-SIMPLIFIED FISH;So;0;ON;;;;;N;;;;; 2EE6;CJK RADICAL C-SIMPLIFIED BIRD;So;0;ON;;;;;N;;;;; 2EE7;CJK RADICAL C-SIMPLIFIED SALT;So;0;ON;;;;;N;;;;; 2EE8;CJK RADICAL SIMPLIFIED WHEAT;So;0;ON;;;;;N;;;;; 2EE9;CJK RADICAL SIMPLIFIED YELLOW;So;0;ON;;;;;N;;;;; 2EEA;CJK RADICAL C-SIMPLIFIED FROG;So;0;ON;;;;;N;;;;; 2EEB;CJK RADICAL J-SIMPLIFIED EVEN;So;0;ON;;;;;N;;;;; 2EEC;CJK RADICAL C-SIMPLIFIED EVEN;So;0;ON;;;;;N;;;;; 2EED;CJK RADICAL J-SIMPLIFIED TOOTH;So;0;ON;;;;;N;;;;; 2EEE;CJK RADICAL C-SIMPLIFIED TOOTH;So;0;ON;;;;;N;;;;; 2EEF;CJK RADICAL J-SIMPLIFIED DRAGON;So;0;ON;;;;;N;;;;; 2EF0;CJK RADICAL C-SIMPLIFIED DRAGON;So;0;ON;;;;;N;;;;; 2EF1;CJK RADICAL TURTLE;So;0;ON;;;;;N;;;;; 2EF2;CJK RADICAL J-SIMPLIFIED TURTLE;So;0;ON;;;;;N;;;;; 2EF3;CJK RADICAL C-SIMPLIFIED TURTLE;So;0;ON; 9F9F;;;;N;;;;; 2F00;KANGXI RADICAL ONE;So;0;ON; 4E00;;;;N;;;;; 2F01;KANGXI RADICAL LINE;So;0;ON; 4E28;;;;N;;;;; 2F02;KANGXI RADICAL DOT;So;0;ON; 4E36;;;;N;;;;; 2F03;KANGXI RADICAL SLASH;So;0;ON; 4E3F;;;;N;;;;; 2F04;KANGXI RADICAL SECOND;So;0;ON; 4E59;;;;N;;;;; 2F05;KANGXI RADICAL HOOK;So;0;ON; 4E85;;;;N;;;;; 2F06;KANGXI RADICAL TWO;So;0;ON; 4E8C;;;;N;;;;; 2F07;KANGXI RADICAL LID;So;0;ON; 4EA0;;;;N;;;;; 2F08;KANGXI RADICAL MAN;So;0;ON; 4EBA;;;;N;;;;; 2F09;KANGXI RADICAL LEGS;So;0;ON; 513F;;;;N;;;;; 2F0A;KANGXI RADICAL ENTER;So;0;ON; 5165;;;;N;;;;; 2F0B;KANGXI RADICAL EIGHT;So;0;ON; 516B;;;;N;;;;; 2F0C;KANGXI RADICAL DOWN BOX;So;0;ON; 5182;;;;N;;;;; 2F0D;KANGXI RADICAL COVER;So;0;ON; 5196;;;;N;;;;; 2F0E;KANGXI RADICAL ICE;So;0;ON; 51AB;;;;N;;;;; 2F0F;KANGXI RADICAL TABLE;So;0;ON; 51E0;;;;N;;;;; 2F10;KANGXI RADICAL OPEN BOX;So;0;ON; 51F5;;;;N;;;;; 2F11;KANGXI RADICAL KNIFE;So;0;ON; 5200;;;;N;;;;; 2F12;KANGXI RADICAL POWER;So;0;ON; 529B;;;;N;;;;; 2F13;KANGXI RADICAL WRAP;So;0;ON; 52F9;;;;N;;;;; 2F14;KANGXI RADICAL SPOON;So;0;ON; 5315;;;;N;;;;; 2F15;KANGXI RADICAL RIGHT OPEN BOX;So;0;ON; 531A;;;;N;;;;; 2F16;KANGXI RADICAL HIDING ENCLOSURE;So;0;ON; 5338;;;;N;;;;; 2F17;KANGXI RADICAL TEN;So;0;ON; 5341;;;;N;;;;; 2F18;KANGXI RADICAL DIVINATION;So;0;ON; 535C;;;;N;;;;; 2F19;KANGXI RADICAL SEAL;So;0;ON; 5369;;;;N;;;;; 2F1A;KANGXI RADICAL CLIFF;So;0;ON; 5382;;;;N;;;;; 2F1B;KANGXI RADICAL PRIVATE;So;0;ON; 53B6;;;;N;;;;; 2F1C;KANGXI RADICAL AGAIN;So;0;ON; 53C8;;;;N;;;;; 2F1D;KANGXI RADICAL MOUTH;So;0;ON; 53E3;;;;N;;;;; 2F1E;KANGXI RADICAL ENCLOSURE;So;0;ON; 56D7;;;;N;;;;; 2F1F;KANGXI RADICAL EARTH;So;0;ON; 571F;;;;N;;;;; 2F20;KANGXI RADICAL SCHOLAR;So;0;ON; 58EB;;;;N;;;;; 2F21;KANGXI RADICAL GO;So;0;ON; 5902;;;;N;;;;; 2F22;KANGXI RADICAL GO SLOWLY;So;0;ON; 590A;;;;N;;;;; 2F23;KANGXI RADICAL EVENING;So;0;ON; 5915;;;;N;;;;; 2F24;KANGXI RADICAL BIG;So;0;ON; 5927;;;;N;;;;; 2F25;KANGXI RADICAL WOMAN;So;0;ON; 5973;;;;N;;;;; 2F26;KANGXI RADICAL CHILD;So;0;ON; 5B50;;;;N;;;;; 2F27;KANGXI RADICAL ROOF;So;0;ON; 5B80;;;;N;;;;; 2F28;KANGXI RADICAL INCH;So;0;ON; 5BF8;;;;N;;;;; 2F29;KANGXI RADICAL SMALL;So;0;ON; 5C0F;;;;N;;;;; 2F2A;KANGXI RADICAL LAME;So;0;ON; 5C22;;;;N;;;;; 2F2B;KANGXI RADICAL CORPSE;So;0;ON; 5C38;;;;N;;;;; 2F2C;KANGXI RADICAL SPROUT;So;0;ON; 5C6E;;;;N;;;;; 2F2D;KANGXI RADICAL MOUNTAIN;So;0;ON; 5C71;;;;N;;;;; 2F2E;KANGXI RADICAL RIVER;So;0;ON; 5DDB;;;;N;;;;; 2F2F;KANGXI RADICAL WORK;So;0;ON; 5DE5;;;;N;;;;; 2F30;KANGXI RADICAL ONESELF;So;0;ON; 5DF1;;;;N;;;;; 2F31;KANGXI RADICAL TURBAN;So;0;ON; 5DFE;;;;N;;;;; 2F32;KANGXI RADICAL DRY;So;0;ON; 5E72;;;;N;;;;; 2F33;KANGXI RADICAL SHORT THREAD;So;0;ON; 5E7A;;;;N;;;;; 2F34;KANGXI RADICAL DOTTED CLIFF;So;0;ON; 5E7F;;;;N;;;;; 2F35;KANGXI RADICAL LONG STRIDE;So;0;ON; 5EF4;;;;N;;;;; 2F36;KANGXI RADICAL TWO HANDS;So;0;ON; 5EFE;;;;N;;;;; 2F37;KANGXI RADICAL SHOOT;So;0;ON; 5F0B;;;;N;;;;; 2F38;KANGXI RADICAL BOW;So;0;ON; 5F13;;;;N;;;;; 2F39;KANGXI RADICAL SNOUT;So;0;ON; 5F50;;;;N;;;;; 2F3A;KANGXI RADICAL BRISTLE;So;0;ON; 5F61;;;;N;;;;; 2F3B;KANGXI RADICAL STEP;So;0;ON; 5F73;;;;N;;;;; 2F3C;KANGXI RADICAL HEART;So;0;ON; 5FC3;;;;N;;;;; 2F3D;KANGXI RADICAL HALBERD;So;0;ON; 6208;;;;N;;;;; 2F3E;KANGXI RADICAL DOOR;So;0;ON; 6236;;;;N;;;;; 2F3F;KANGXI RADICAL HAND;So;0;ON; 624B;;;;N;;;;; 2F40;KANGXI RADICAL BRANCH;So;0;ON; 652F;;;;N;;;;; 2F41;KANGXI RADICAL RAP;So;0;ON; 6534;;;;N;;;;; 2F42;KANGXI RADICAL SCRIPT;So;0;ON; 6587;;;;N;;;;; 2F43;KANGXI RADICAL DIPPER;So;0;ON; 6597;;;;N;;;;; 2F44;KANGXI RADICAL AXE;So;0;ON; 65A4;;;;N;;;;; 2F45;KANGXI RADICAL SQUARE;So;0;ON; 65B9;;;;N;;;;; 2F46;KANGXI RADICAL NOT;So;0;ON; 65E0;;;;N;;;;; 2F47;KANGXI RADICAL SUN;So;0;ON; 65E5;;;;N;;;;; 2F48;KANGXI RADICAL SAY;So;0;ON; 66F0;;;;N;;;;; 2F49;KANGXI RADICAL MOON;So;0;ON; 6708;;;;N;;;;; 2F4A;KANGXI RADICAL TREE;So;0;ON; 6728;;;;N;;;;; 2F4B;KANGXI RADICAL LACK;So;0;ON; 6B20;;;;N;;;;; 2F4C;KANGXI RADICAL STOP;So;0;ON; 6B62;;;;N;;;;; 2F4D;KANGXI RADICAL DEATH;So;0;ON; 6B79;;;;N;;;;; 2F4E;KANGXI RADICAL WEAPON;So;0;ON; 6BB3;;;;N;;;;; 2F4F;KANGXI RADICAL DO NOT;So;0;ON; 6BCB;;;;N;;;;; 2F50;KANGXI RADICAL COMPARE;So;0;ON; 6BD4;;;;N;;;;; 2F51;KANGXI RADICAL FUR;So;0;ON; 6BDB;;;;N;;;;; 2F52;KANGXI RADICAL CLAN;So;0;ON; 6C0F;;;;N;;;;; 2F53;KANGXI RADICAL STEAM;So;0;ON; 6C14;;;;N;;;;; 2F54;KANGXI RADICAL WATER;So;0;ON; 6C34;;;;N;;;;; 2F55;KANGXI RADICAL FIRE;So;0;ON; 706B;;;;N;;;;; 2F56;KANGXI RADICAL CLAW;So;0;ON; 722A;;;;N;;;;; 2F57;KANGXI RADICAL FATHER;So;0;ON; 7236;;;;N;;;;; 2F58;KANGXI RADICAL DOUBLE X;So;0;ON; 723B;;;;N;;;;; 2F59;KANGXI RADICAL HALF TREE TRUNK;So;0;ON; 723F;;;;N;;;;; 2F5A;KANGXI RADICAL SLICE;So;0;ON; 7247;;;;N;;;;; 2F5B;KANGXI RADICAL FANG;So;0;ON; 7259;;;;N;;;;; 2F5C;KANGXI RADICAL COW;So;0;ON; 725B;;;;N;;;;; 2F5D;KANGXI RADICAL DOG;So;0;ON; 72AC;;;;N;;;;; 2F5E;KANGXI RADICAL PROFOUND;So;0;ON; 7384;;;;N;;;;; 2F5F;KANGXI RADICAL JADE;So;0;ON; 7389;;;;N;;;;; 2F60;KANGXI RADICAL MELON;So;0;ON; 74DC;;;;N;;;;; 2F61;KANGXI RADICAL TILE;So;0;ON; 74E6;;;;N;;;;; 2F62;KANGXI RADICAL SWEET;So;0;ON; 7518;;;;N;;;;; 2F63;KANGXI RADICAL LIFE;So;0;ON; 751F;;;;N;;;;; 2F64;KANGXI RADICAL USE;So;0;ON; 7528;;;;N;;;;; 2F65;KANGXI RADICAL FIELD;So;0;ON; 7530;;;;N;;;;; 2F66;KANGXI RADICAL BOLT OF CLOTH;So;0;ON; 758B;;;;N;;;;; 2F67;KANGXI RADICAL SICKNESS;So;0;ON; 7592;;;;N;;;;; 2F68;KANGXI RADICAL DOTTED TENT;So;0;ON; 7676;;;;N;;;;; 2F69;KANGXI RADICAL WHITE;So;0;ON; 767D;;;;N;;;;; 2F6A;KANGXI RADICAL SKIN;So;0;ON; 76AE;;;;N;;;;; 2F6B;KANGXI RADICAL DISH;So;0;ON; 76BF;;;;N;;;;; 2F6C;KANGXI RADICAL EYE;So;0;ON; 76EE;;;;N;;;;; 2F6D;KANGXI RADICAL SPEAR;So;0;ON; 77DB;;;;N;;;;; 2F6E;KANGXI RADICAL ARROW;So;0;ON; 77E2;;;;N;;;;; 2F6F;KANGXI RADICAL STONE;So;0;ON; 77F3;;;;N;;;;; 2F70;KANGXI RADICAL SPIRIT;So;0;ON; 793A;;;;N;;;;; 2F71;KANGXI RADICAL TRACK;So;0;ON; 79B8;;;;N;;;;; 2F72;KANGXI RADICAL GRAIN;So;0;ON; 79BE;;;;N;;;;; 2F73;KANGXI RADICAL CAVE;So;0;ON; 7A74;;;;N;;;;; 2F74;KANGXI RADICAL STAND;So;0;ON; 7ACB;;;;N;;;;; 2F75;KANGXI RADICAL BAMBOO;So;0;ON; 7AF9;;;;N;;;;; 2F76;KANGXI RADICAL RICE;So;0;ON; 7C73;;;;N;;;;; 2F77;KANGXI RADICAL SILK;So;0;ON; 7CF8;;;;N;;;;; 2F78;KANGXI RADICAL JAR;So;0;ON; 7F36;;;;N;;;;; 2F79;KANGXI RADICAL NET;So;0;ON; 7F51;;;;N;;;;; 2F7A;KANGXI RADICAL SHEEP;So;0;ON; 7F8A;;;;N;;;;; 2F7B;KANGXI RADICAL FEATHER;So;0;ON; 7FBD;;;;N;;;;; 2F7C;KANGXI RADICAL OLD;So;0;ON; 8001;;;;N;;;;; 2F7D;KANGXI RADICAL AND;So;0;ON; 800C;;;;N;;;;; 2F7E;KANGXI RADICAL PLOW;So;0;ON; 8012;;;;N;;;;; 2F7F;KANGXI RADICAL EAR;So;0;ON; 8033;;;;N;;;;; 2F80;KANGXI RADICAL BRUSH;So;0;ON; 807F;;;;N;;;;; 2F81;KANGXI RADICAL MEAT;So;0;ON; 8089;;;;N;;;;; 2F82;KANGXI RADICAL MINISTER;So;0;ON; 81E3;;;;N;;;;; 2F83;KANGXI RADICAL SELF;So;0;ON; 81EA;;;;N;;;;; 2F84;KANGXI RADICAL ARRIVE;So;0;ON; 81F3;;;;N;;;;; 2F85;KANGXI RADICAL MORTAR;So;0;ON; 81FC;;;;N;;;;; 2F86;KANGXI RADICAL TONGUE;So;0;ON; 820C;;;;N;;;;; 2F87;KANGXI RADICAL OPPOSE;So;0;ON; 821B;;;;N;;;;; 2F88;KANGXI RADICAL BOAT;So;0;ON; 821F;;;;N;;;;; 2F89;KANGXI RADICAL STOPPING;So;0;ON; 826E;;;;N;;;;; 2F8A;KANGXI RADICAL COLOR;So;0;ON; 8272;;;;N;;;;; 2F8B;KANGXI RADICAL GRASS;So;0;ON; 8278;;;;N;;;;; 2F8C;KANGXI RADICAL TIGER;So;0;ON; 864D;;;;N;;;;; 2F8D;KANGXI RADICAL INSECT;So;0;ON; 866B;;;;N;;;;; 2F8E;KANGXI RADICAL BLOOD;So;0;ON; 8840;;;;N;;;;; 2F8F;KANGXI RADICAL WALK ENCLOSURE;So;0;ON; 884C;;;;N;;;;; 2F90;KANGXI RADICAL CLOTHES;So;0;ON; 8863;;;;N;;;;; 2F91;KANGXI RADICAL WEST;So;0;ON; 897E;;;;N;;;;; 2F92;KANGXI RADICAL SEE;So;0;ON; 898B;;;;N;;;;; 2F93;KANGXI RADICAL HORN;So;0;ON; 89D2;;;;N;;;;; 2F94;KANGXI RADICAL SPEECH;So;0;ON; 8A00;;;;N;;;;; 2F95;KANGXI RADICAL VALLEY;So;0;ON; 8C37;;;;N;;;;; 2F96;KANGXI RADICAL BEAN;So;0;ON; 8C46;;;;N;;;;; 2F97;KANGXI RADICAL PIG;So;0;ON; 8C55;;;;N;;;;; 2F98;KANGXI RADICAL BADGER;So;0;ON; 8C78;;;;N;;;;; 2F99;KANGXI RADICAL SHELL;So;0;ON; 8C9D;;;;N;;;;; 2F9A;KANGXI RADICAL RED;So;0;ON; 8D64;;;;N;;;;; 2F9B;KANGXI RADICAL RUN;So;0;ON; 8D70;;;;N;;;;; 2F9C;KANGXI RADICAL FOOT;So;0;ON; 8DB3;;;;N;;;;; 2F9D;KANGXI RADICAL BODY;So;0;ON; 8EAB;;;;N;;;;; 2F9E;KANGXI RADICAL CART;So;0;ON; 8ECA;;;;N;;;;; 2F9F;KANGXI RADICAL BITTER;So;0;ON; 8F9B;;;;N;;;;; 2FA0;KANGXI RADICAL MORNING;So;0;ON; 8FB0;;;;N;;;;; 2FA1;KANGXI RADICAL WALK;So;0;ON; 8FB5;;;;N;;;;; 2FA2;KANGXI RADICAL CITY;So;0;ON; 9091;;;;N;;;;; 2FA3;KANGXI RADICAL WINE;So;0;ON; 9149;;;;N;;;;; 2FA4;KANGXI RADICAL DISTINGUISH;So;0;ON; 91C6;;;;N;;;;; 2FA5;KANGXI RADICAL VILLAGE;So;0;ON; 91CC;;;;N;;;;; 2FA6;KANGXI RADICAL GOLD;So;0;ON; 91D1;;;;N;;;;; 2FA7;KANGXI RADICAL LONG;So;0;ON; 9577;;;;N;;;;; 2FA8;KANGXI RADICAL GATE;So;0;ON; 9580;;;;N;;;;; 2FA9;KANGXI RADICAL MOUND;So;0;ON; 961C;;;;N;;;;; 2FAA;KANGXI RADICAL SLAVE;So;0;ON; 96B6;;;;N;;;;; 2FAB;KANGXI RADICAL SHORT TAILED BIRD;So;0;ON; 96B9;;;;N;;;;; 2FAC;KANGXI RADICAL RAIN;So;0;ON; 96E8;;;;N;;;;; 2FAD;KANGXI RADICAL BLUE;So;0;ON; 9751;;;;N;;;;; 2FAE;KANGXI RADICAL WRONG;So;0;ON; 975E;;;;N;;;;; 2FAF;KANGXI RADICAL FACE;So;0;ON; 9762;;;;N;;;;; 2FB0;KANGXI RADICAL LEATHER;So;0;ON; 9769;;;;N;;;;; 2FB1;KANGXI RADICAL TANNED LEATHER;So;0;ON; 97CB;;;;N;;;;; 2FB2;KANGXI RADICAL LEEK;So;0;ON; 97ED;;;;N;;;;; 2FB3;KANGXI RADICAL SOUND;So;0;ON; 97F3;;;;N;;;;; 2FB4;KANGXI RADICAL LEAF;So;0;ON; 9801;;;;N;;;;; 2FB5;KANGXI RADICAL WIND;So;0;ON; 98A8;;;;N;;;;; 2FB6;KANGXI RADICAL FLY;So;0;ON; 98DB;;;;N;;;;; 2FB7;KANGXI RADICAL EAT;So;0;ON; 98DF;;;;N;;;;; 2FB8;KANGXI RADICAL HEAD;So;0;ON; 9996;;;;N;;;;; 2FB9;KANGXI RADICAL FRAGRANT;So;0;ON; 9999;;;;N;;;;; 2FBA;KANGXI RADICAL HORSE;So;0;ON; 99AC;;;;N;;;;; 2FBB;KANGXI RADICAL BONE;So;0;ON; 9AA8;;;;N;;;;; 2FBC;KANGXI RADICAL TALL;So;0;ON; 9AD8;;;;N;;;;; 2FBD;KANGXI RADICAL HAIR;So;0;ON; 9ADF;;;;N;;;;; 2FBE;KANGXI RADICAL FIGHT;So;0;ON; 9B25;;;;N;;;;; 2FBF;KANGXI RADICAL SACRIFICIAL WINE;So;0;ON; 9B2F;;;;N;;;;; 2FC0;KANGXI RADICAL CAULDRON;So;0;ON; 9B32;;;;N;;;;; 2FC1;KANGXI RADICAL GHOST;So;0;ON; 9B3C;;;;N;;;;; 2FC2;KANGXI RADICAL FISH;So;0;ON; 9B5A;;;;N;;;;; 2FC3;KANGXI RADICAL BIRD;So;0;ON; 9CE5;;;;N;;;;; 2FC4;KANGXI RADICAL SALT;So;0;ON; 9E75;;;;N;;;;; 2FC5;KANGXI RADICAL DEER;So;0;ON; 9E7F;;;;N;;;;; 2FC6;KANGXI RADICAL WHEAT;So;0;ON; 9EA5;;;;N;;;;; 2FC7;KANGXI RADICAL HEMP;So;0;ON; 9EBB;;;;N;;;;; 2FC8;KANGXI RADICAL YELLOW;So;0;ON; 9EC3;;;;N;;;;; 2FC9;KANGXI RADICAL MILLET;So;0;ON; 9ECD;;;;N;;;;; 2FCA;KANGXI RADICAL BLACK;So;0;ON; 9ED1;;;;N;;;;; 2FCB;KANGXI RADICAL EMBROIDERY;So;0;ON; 9EF9;;;;N;;;;; 2FCC;KANGXI RADICAL FROG;So;0;ON; 9EFD;;;;N;;;;; 2FCD;KANGXI RADICAL TRIPOD;So;0;ON; 9F0E;;;;N;;;;; 2FCE;KANGXI RADICAL DRUM;So;0;ON; 9F13;;;;N;;;;; 2FCF;KANGXI RADICAL RAT;So;0;ON; 9F20;;;;N;;;;; 2FD0;KANGXI RADICAL NOSE;So;0;ON; 9F3B;;;;N;;;;; 2FD1;KANGXI RADICAL EVEN;So;0;ON; 9F4A;;;;N;;;;; 2FD2;KANGXI RADICAL TOOTH;So;0;ON; 9F52;;;;N;;;;; 2FD3;KANGXI RADICAL DRAGON;So;0;ON; 9F8D;;;;N;;;;; 2FD4;KANGXI RADICAL TURTLE;So;0;ON; 9F9C;;;;N;;;;; 2FD5;KANGXI RADICAL FLUTE;So;0;ON; 9FA0;;;;N;;;;; 2FF0;IDEOGRAPHIC DESCRIPTION CHARACTER LEFT TO RIGHT;So;0;ON;;;;;N;;;;; 2FF1;IDEOGRAPHIC DESCRIPTION CHARACTER ABOVE TO BELOW;So;0;ON;;;;;N;;;;; 2FF2;IDEOGRAPHIC DESCRIPTION CHARACTER LEFT TO MIDDLE AND RIGHT;So;0;ON;;;;;N;;;;; 2FF3;IDEOGRAPHIC DESCRIPTION CHARACTER ABOVE TO MIDDLE AND BELOW;So;0;ON;;;;;N;;;;; 2FF4;IDEOGRAPHIC DESCRIPTION CHARACTER FULL SURROUND;So;0;ON;;;;;N;;;;; 2FF5;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM ABOVE;So;0;ON;;;;;N;;;;; 2FF6;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM BELOW;So;0;ON;;;;;N;;;;; 2FF7;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM LEFT;So;0;ON;;;;;N;;;;; 2FF8;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM UPPER LEFT;So;0;ON;;;;;N;;;;; 2FF9;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM UPPER RIGHT;So;0;ON;;;;;N;;;;; 2FFA;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM LOWER LEFT;So;0;ON;;;;;N;;;;; 2FFB;IDEOGRAPHIC DESCRIPTION CHARACTER OVERLAID;So;0;ON;;;;;N;;;;; 3000;IDEOGRAPHIC SPACE;Zs;0;WS; 0020;;;;N;;;;; 3001;IDEOGRAPHIC COMMA;Po;0;ON;;;;;N;;;;; 3002;IDEOGRAPHIC FULL STOP;Po;0;ON;;;;;N;IDEOGRAPHIC PERIOD;;;; 3003;DITTO MARK;Po;0;ON;;;;;N;;;;; 3004;JAPANESE INDUSTRIAL STANDARD SYMBOL;So;0;ON;;;;;N;;;;; 3005;IDEOGRAPHIC ITERATION MARK;Lm;0;L;;;;;N;;;;; 3006;IDEOGRAPHIC CLOSING MARK;Lo;0;L;;;;;N;;;;; 3007;IDEOGRAPHIC NUMBER ZERO;Nl;0;L;;;;0;N;;;;; 3008;LEFT ANGLE BRACKET;Ps;0;ON;;;;;Y;OPENING ANGLE BRACKET;;;; 3009;RIGHT ANGLE BRACKET;Pe;0;ON;;;;;Y;CLOSING ANGLE BRACKET;;;; 300A;LEFT DOUBLE ANGLE BRACKET;Ps;0;ON;;;;;Y;OPENING DOUBLE ANGLE BRACKET;;;; 300B;RIGHT DOUBLE ANGLE BRACKET;Pe;0;ON;;;;;Y;CLOSING DOUBLE ANGLE BRACKET;;;; 300C;LEFT CORNER BRACKET;Ps;0;ON;;;;;Y;OPENING CORNER BRACKET;;;; 300D;RIGHT CORNER BRACKET;Pe;0;ON;;;;;Y;CLOSING CORNER BRACKET;;;; 300E;LEFT WHITE CORNER BRACKET;Ps;0;ON;;;;;Y;OPENING WHITE CORNER BRACKET;;;; 300F;RIGHT WHITE CORNER BRACKET;Pe;0;ON;;;;;Y;CLOSING WHITE CORNER BRACKET;;;; 3010;LEFT BLACK LENTICULAR BRACKET;Ps;0;ON;;;;;Y;OPENING BLACK LENTICULAR BRACKET;;;; 3011;RIGHT BLACK LENTICULAR BRACKET;Pe;0;ON;;;;;Y;CLOSING BLACK LENTICULAR BRACKET;;;; 3012;POSTAL MARK;So;0;ON;;;;;N;;;;; 3013;GETA MARK;So;0;ON;;;;;N;;;;; 3014;LEFT TORTOISE SHELL BRACKET;Ps;0;ON;;;;;Y;OPENING TORTOISE SHELL BRACKET;;;; 3015;RIGHT TORTOISE SHELL BRACKET;Pe;0;ON;;;;;Y;CLOSING TORTOISE SHELL BRACKET;;;; 3016;LEFT WHITE LENTICULAR BRACKET;Ps;0;ON;;;;;Y;OPENING WHITE LENTICULAR BRACKET;;;; 3017;RIGHT WHITE LENTICULAR BRACKET;Pe;0;ON;;;;;Y;CLOSING WHITE LENTICULAR BRACKET;;;; 3018;LEFT WHITE TORTOISE SHELL BRACKET;Ps;0;ON;;;;;Y;OPENING WHITE TORTOISE SHELL BRACKET;;;; 3019;RIGHT WHITE TORTOISE SHELL BRACKET;Pe;0;ON;;;;;Y;CLOSING WHITE TORTOISE SHELL BRACKET;;;; 301A;LEFT WHITE SQUARE BRACKET;Ps;0;ON;;;;;Y;OPENING WHITE SQUARE BRACKET;;;; 301B;RIGHT WHITE SQUARE BRACKET;Pe;0;ON;;;;;Y;CLOSING WHITE SQUARE BRACKET;;;; 301C;WAVE DASH;Pd;0;ON;;;;;N;;;;; 301D;REVERSED DOUBLE PRIME QUOTATION MARK;Ps;0;ON;;;;;N;;;;; 301E;DOUBLE PRIME QUOTATION MARK;Pe;0;ON;;;;;N;;;;; 301F;LOW DOUBLE PRIME QUOTATION MARK;Pe;0;ON;;;;;N;;;;; 3020;POSTAL MARK FACE;So;0;ON;;;;;N;;;;; 3021;HANGZHOU NUMERAL ONE;Nl;0;L;;;;1;N;;;;; 3022;HANGZHOU NUMERAL TWO;Nl;0;L;;;;2;N;;;;; 3023;HANGZHOU NUMERAL THREE;Nl;0;L;;;;3;N;;;;; 3024;HANGZHOU NUMERAL FOUR;Nl;0;L;;;;4;N;;;;; 3025;HANGZHOU NUMERAL FIVE;Nl;0;L;;;;5;N;;;;; 3026;HANGZHOU NUMERAL SIX;Nl;0;L;;;;6;N;;;;; 3027;HANGZHOU NUMERAL SEVEN;Nl;0;L;;;;7;N;;;;; 3028;HANGZHOU NUMERAL EIGHT;Nl;0;L;;;;8;N;;;;; 3029;HANGZHOU NUMERAL NINE;Nl;0;L;;;;9;N;;;;; 302A;IDEOGRAPHIC LEVEL TONE MARK;Mn;218;NSM;;;;;N;;;;; 302B;IDEOGRAPHIC RISING TONE MARK;Mn;228;NSM;;;;;N;;;;; 302C;IDEOGRAPHIC DEPARTING TONE MARK;Mn;232;NSM;;;;;N;;;;; 302D;IDEOGRAPHIC ENTERING TONE MARK;Mn;222;NSM;;;;;N;;;;; 302E;HANGUL SINGLE DOT TONE MARK;Mn;224;NSM;;;;;N;;;;; 302F;HANGUL DOUBLE DOT TONE MARK;Mn;224;NSM;;;;;N;;;;; 3030;WAVY DASH;Pd;0;ON;;;;;N;;;;; 3031;VERTICAL KANA REPEAT MARK;Lm;0;L;;;;;N;;;;; 3032;VERTICAL KANA REPEAT WITH VOICED SOUND MARK;Lm;0;L;;;;;N;;;;; 3033;VERTICAL KANA REPEAT MARK UPPER HALF;Lm;0;L;;;;;N;;;;; 3034;VERTICAL KANA REPEAT WITH VOICED SOUND MARK UPPER HALF;Lm;0;L;;;;;N;;;;; 3035;VERTICAL KANA REPEAT MARK LOWER HALF;Lm;0;L;;;;;N;;;;; 3036;CIRCLED POSTAL MARK;So;0;ON; 3012;;;;N;;;;; 3037;IDEOGRAPHIC TELEGRAPH LINE FEED SEPARATOR SYMBOL;So;0;ON;;;;;N;;;;; 3038;HANGZHOU NUMERAL TEN;Nl;0;L; 5341;;;10;N;;;;; 3039;HANGZHOU NUMERAL TWENTY;Nl;0;L; 5344;;;20;N;;;;; 303A;HANGZHOU NUMERAL THIRTY;Nl;0;L; 5345;;;30;N;;;;; 303B;VERTICAL IDEOGRAPHIC ITERATION MARK;Lm;0;L;;;;;N;;;;; 303C;MASU MARK;Lo;0;L;;;;;N;;;;; 303D;PART ALTERNATION MARK;Po;0;ON;;;;;N;;;;; 303E;IDEOGRAPHIC VARIATION INDICATOR;So;0;ON;;;;;N;;;;; 303F;IDEOGRAPHIC HALF FILL SPACE;So;0;ON;;;;;N;;;;; 3041;HIRAGANA LETTER SMALL A;Lo;0;L;;;;;N;;;;; 3042;HIRAGANA LETTER A;Lo;0;L;;;;;N;;;;; 3043;HIRAGANA LETTER SMALL I;Lo;0;L;;;;;N;;;;; 3044;HIRAGANA LETTER I;Lo;0;L;;;;;N;;;;; 3045;HIRAGANA LETTER SMALL U;Lo;0;L;;;;;N;;;;; 3046;HIRAGANA LETTER U;Lo;0;L;;;;;N;;;;; 3047;HIRAGANA LETTER SMALL E;Lo;0;L;;;;;N;;;;; 3048;HIRAGANA LETTER E;Lo;0;L;;;;;N;;;;; 3049;HIRAGANA LETTER SMALL O;Lo;0;L;;;;;N;;;;; 304A;HIRAGANA LETTER O;Lo;0;L;;;;;N;;;;; 304B;HIRAGANA LETTER KA;Lo;0;L;;;;;N;;;;; 304C;HIRAGANA LETTER GA;Lo;0;L;304B 3099;;;;N;;;;; 304D;HIRAGANA LETTER KI;Lo;0;L;;;;;N;;;;; 304E;HIRAGANA LETTER GI;Lo;0;L;304D 3099;;;;N;;;;; 304F;HIRAGANA LETTER KU;Lo;0;L;;;;;N;;;;; 3050;HIRAGANA LETTER GU;Lo;0;L;304F 3099;;;;N;;;;; 3051;HIRAGANA LETTER KE;Lo;0;L;;;;;N;;;;; 3052;HIRAGANA LETTER GE;Lo;0;L;3051 3099;;;;N;;;;; 3053;HIRAGANA LETTER KO;Lo;0;L;;;;;N;;;;; 3054;HIRAGANA LETTER GO;Lo;0;L;3053 3099;;;;N;;;;; 3055;HIRAGANA LETTER SA;Lo;0;L;;;;;N;;;;; 3056;HIRAGANA LETTER ZA;Lo;0;L;3055 3099;;;;N;;;;; 3057;HIRAGANA LETTER SI;Lo;0;L;;;;;N;;;;; 3058;HIRAGANA LETTER ZI;Lo;0;L;3057 3099;;;;N;;;;; 3059;HIRAGANA LETTER SU;Lo;0;L;;;;;N;;;;; 305A;HIRAGANA LETTER ZU;Lo;0;L;3059 3099;;;;N;;;;; 305B;HIRAGANA LETTER SE;Lo;0;L;;;;;N;;;;; 305C;HIRAGANA LETTER ZE;Lo;0;L;305B 3099;;;;N;;;;; 305D;HIRAGANA LETTER SO;Lo;0;L;;;;;N;;;;; 305E;HIRAGANA LETTER ZO;Lo;0;L;305D 3099;;;;N;;;;; 305F;HIRAGANA LETTER TA;Lo;0;L;;;;;N;;;;; 3060;HIRAGANA LETTER DA;Lo;0;L;305F 3099;;;;N;;;;; 3061;HIRAGANA LETTER TI;Lo;0;L;;;;;N;;;;; 3062;HIRAGANA LETTER DI;Lo;0;L;3061 3099;;;;N;;;;; 3063;HIRAGANA LETTER SMALL TU;Lo;0;L;;;;;N;;;;; 3064;HIRAGANA LETTER TU;Lo;0;L;;;;;N;;;;; 3065;HIRAGANA LETTER DU;Lo;0;L;3064 3099;;;;N;;;;; 3066;HIRAGANA LETTER TE;Lo;0;L;;;;;N;;;;; 3067;HIRAGANA LETTER DE;Lo;0;L;3066 3099;;;;N;;;;; 3068;HIRAGANA LETTER TO;Lo;0;L;;;;;N;;;;; 3069;HIRAGANA LETTER DO;Lo;0;L;3068 3099;;;;N;;;;; 306A;HIRAGANA LETTER NA;Lo;0;L;;;;;N;;;;; 306B;HIRAGANA LETTER NI;Lo;0;L;;;;;N;;;;; 306C;HIRAGANA LETTER NU;Lo;0;L;;;;;N;;;;; 306D;HIRAGANA LETTER NE;Lo;0;L;;;;;N;;;;; 306E;HIRAGANA LETTER NO;Lo;0;L;;;;;N;;;;; 306F;HIRAGANA LETTER HA;Lo;0;L;;;;;N;;;;; 3070;HIRAGANA LETTER BA;Lo;0;L;306F 3099;;;;N;;;;; 3071;HIRAGANA LETTER PA;Lo;0;L;306F 309A;;;;N;;;;; 3072;HIRAGANA LETTER HI;Lo;0;L;;;;;N;;;;; 3073;HIRAGANA LETTER BI;Lo;0;L;3072 3099;;;;N;;;;; 3074;HIRAGANA LETTER PI;Lo;0;L;3072 309A;;;;N;;;;; 3075;HIRAGANA LETTER HU;Lo;0;L;;;;;N;;;;; 3076;HIRAGANA LETTER BU;Lo;0;L;3075 3099;;;;N;;;;; 3077;HIRAGANA LETTER PU;Lo;0;L;3075 309A;;;;N;;;;; 3078;HIRAGANA LETTER HE;Lo;0;L;;;;;N;;;;; 3079;HIRAGANA LETTER BE;Lo;0;L;3078 3099;;;;N;;;;; 307A;HIRAGANA LETTER PE;Lo;0;L;3078 309A;;;;N;;;;; 307B;HIRAGANA LETTER HO;Lo;0;L;;;;;N;;;;; 307C;HIRAGANA LETTER BO;Lo;0;L;307B 3099;;;;N;;;;; 307D;HIRAGANA LETTER PO;Lo;0;L;307B 309A;;;;N;;;;; 307E;HIRAGANA LETTER MA;Lo;0;L;;;;;N;;;;; 307F;HIRAGANA LETTER MI;Lo;0;L;;;;;N;;;;; 3080;HIRAGANA LETTER MU;Lo;0;L;;;;;N;;;;; 3081;HIRAGANA LETTER ME;Lo;0;L;;;;;N;;;;; 3082;HIRAGANA LETTER MO;Lo;0;L;;;;;N;;;;; 3083;HIRAGANA LETTER SMALL YA;Lo;0;L;;;;;N;;;;; 3084;HIRAGANA LETTER YA;Lo;0;L;;;;;N;;;;; 3085;HIRAGANA LETTER SMALL YU;Lo;0;L;;;;;N;;;;; 3086;HIRAGANA LETTER YU;Lo;0;L;;;;;N;;;;; 3087;HIRAGANA LETTER SMALL YO;Lo;0;L;;;;;N;;;;; 3088;HIRAGANA LETTER YO;Lo;0;L;;;;;N;;;;; 3089;HIRAGANA LETTER RA;Lo;0;L;;;;;N;;;;; 308A;HIRAGANA LETTER RI;Lo;0;L;;;;;N;;;;; 308B;HIRAGANA LETTER RU;Lo;0;L;;;;;N;;;;; 308C;HIRAGANA LETTER RE;Lo;0;L;;;;;N;;;;; 308D;HIRAGANA LETTER RO;Lo;0;L;;;;;N;;;;; 308E;HIRAGANA LETTER SMALL WA;Lo;0;L;;;;;N;;;;; 308F;HIRAGANA LETTER WA;Lo;0;L;;;;;N;;;;; 3090;HIRAGANA LETTER WI;Lo;0;L;;;;;N;;;;; 3091;HIRAGANA LETTER WE;Lo;0;L;;;;;N;;;;; 3092;HIRAGANA LETTER WO;Lo;0;L;;;;;N;;;;; 3093;HIRAGANA LETTER N;Lo;0;L;;;;;N;;;;; 3094;HIRAGANA LETTER VU;Lo;0;L;3046 3099;;;;N;;;;; 3095;HIRAGANA LETTER SMALL KA;Lo;0;L;;;;;N;;;;; 3096;HIRAGANA LETTER SMALL KE;Lo;0;L;;;;;N;;;;; 3099;COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK;Mn;8;NSM;;;;;N;NON-SPACING KATAKANA-HIRAGANA VOICED SOUND MARK;;;; 309A;COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK;Mn;8;NSM;;;;;N;NON-SPACING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK;;;; 309B;KATAKANA-HIRAGANA VOICED SOUND MARK;Sk;0;ON; 0020 3099;;;;N;;;;; 309C;KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK;Sk;0;ON; 0020 309A;;;;N;;;;; 309D;HIRAGANA ITERATION MARK;Lm;0;L;;;;;N;;;;; 309E;HIRAGANA VOICED ITERATION MARK;Lm;0;L;309D 3099;;;;N;;;;; 309F;HIRAGANA DIGRAPH YORI;Lo;0;L; 3088 308A;;;;N;;;;; 30A0;KATAKANA-HIRAGANA DOUBLE HYPHEN;Pd;0;ON;;;;;N;;;;; 30A1;KATAKANA LETTER SMALL A;Lo;0;L;;;;;N;;;;; 30A2;KATAKANA LETTER A;Lo;0;L;;;;;N;;;;; 30A3;KATAKANA LETTER SMALL I;Lo;0;L;;;;;N;;;;; 30A4;KATAKANA LETTER I;Lo;0;L;;;;;N;;;;; 30A5;KATAKANA LETTER SMALL U;Lo;0;L;;;;;N;;;;; 30A6;KATAKANA LETTER U;Lo;0;L;;;;;N;;;;; 30A7;KATAKANA LETTER SMALL E;Lo;0;L;;;;;N;;;;; 30A8;KATAKANA LETTER E;Lo;0;L;;;;;N;;;;; 30A9;KATAKANA LETTER SMALL O;Lo;0;L;;;;;N;;;;; 30AA;KATAKANA LETTER O;Lo;0;L;;;;;N;;;;; 30AB;KATAKANA LETTER KA;Lo;0;L;;;;;N;;;;; 30AC;KATAKANA LETTER GA;Lo;0;L;30AB 3099;;;;N;;;;; 30AD;KATAKANA LETTER KI;Lo;0;L;;;;;N;;;;; 30AE;KATAKANA LETTER GI;Lo;0;L;30AD 3099;;;;N;;;;; 30AF;KATAKANA LETTER KU;Lo;0;L;;;;;N;;;;; 30B0;KATAKANA LETTER GU;Lo;0;L;30AF 3099;;;;N;;;;; 30B1;KATAKANA LETTER KE;Lo;0;L;;;;;N;;;;; 30B2;KATAKANA LETTER GE;Lo;0;L;30B1 3099;;;;N;;;;; 30B3;KATAKANA LETTER KO;Lo;0;L;;;;;N;;;;; 30B4;KATAKANA LETTER GO;Lo;0;L;30B3 3099;;;;N;;;;; 30B5;KATAKANA LETTER SA;Lo;0;L;;;;;N;;;;; 30B6;KATAKANA LETTER ZA;Lo;0;L;30B5 3099;;;;N;;;;; 30B7;KATAKANA LETTER SI;Lo;0;L;;;;;N;;;;; 30B8;KATAKANA LETTER ZI;Lo;0;L;30B7 3099;;;;N;;;;; 30B9;KATAKANA LETTER SU;Lo;0;L;;;;;N;;;;; 30BA;KATAKANA LETTER ZU;Lo;0;L;30B9 3099;;;;N;;;;; 30BB;KATAKANA LETTER SE;Lo;0;L;;;;;N;;;;; 30BC;KATAKANA LETTER ZE;Lo;0;L;30BB 3099;;;;N;;;;; 30BD;KATAKANA LETTER SO;Lo;0;L;;;;;N;;;;; 30BE;KATAKANA LETTER ZO;Lo;0;L;30BD 3099;;;;N;;;;; 30BF;KATAKANA LETTER TA;Lo;0;L;;;;;N;;;;; 30C0;KATAKANA LETTER DA;Lo;0;L;30BF 3099;;;;N;;;;; 30C1;KATAKANA LETTER TI;Lo;0;L;;;;;N;;;;; 30C2;KATAKANA LETTER DI;Lo;0;L;30C1 3099;;;;N;;;;; 30C3;KATAKANA LETTER SMALL TU;Lo;0;L;;;;;N;;;;; 30C4;KATAKANA LETTER TU;Lo;0;L;;;;;N;;;;; 30C5;KATAKANA LETTER DU;Lo;0;L;30C4 3099;;;;N;;;;; 30C6;KATAKANA LETTER TE;Lo;0;L;;;;;N;;;;; 30C7;KATAKANA LETTER DE;Lo;0;L;30C6 3099;;;;N;;;;; 30C8;KATAKANA LETTER TO;Lo;0;L;;;;;N;;;;; 30C9;KATAKANA LETTER DO;Lo;0;L;30C8 3099;;;;N;;;;; 30CA;KATAKANA LETTER NA;Lo;0;L;;;;;N;;;;; 30CB;KATAKANA LETTER NI;Lo;0;L;;;;;N;;;;; 30CC;KATAKANA LETTER NU;Lo;0;L;;;;;N;;;;; 30CD;KATAKANA LETTER NE;Lo;0;L;;;;;N;;;;; 30CE;KATAKANA LETTER NO;Lo;0;L;;;;;N;;;;; 30CF;KATAKANA LETTER HA;Lo;0;L;;;;;N;;;;; 30D0;KATAKANA LETTER BA;Lo;0;L;30CF 3099;;;;N;;;;; 30D1;KATAKANA LETTER PA;Lo;0;L;30CF 309A;;;;N;;;;; 30D2;KATAKANA LETTER HI;Lo;0;L;;;;;N;;;;; 30D3;KATAKANA LETTER BI;Lo;0;L;30D2 3099;;;;N;;;;; 30D4;KATAKANA LETTER PI;Lo;0;L;30D2 309A;;;;N;;;;; 30D5;KATAKANA LETTER HU;Lo;0;L;;;;;N;;;;; 30D6;KATAKANA LETTER BU;Lo;0;L;30D5 3099;;;;N;;;;; 30D7;KATAKANA LETTER PU;Lo;0;L;30D5 309A;;;;N;;;;; 30D8;KATAKANA LETTER HE;Lo;0;L;;;;;N;;;;; 30D9;KATAKANA LETTER BE;Lo;0;L;30D8 3099;;;;N;;;;; 30DA;KATAKANA LETTER PE;Lo;0;L;30D8 309A;;;;N;;;;; 30DB;KATAKANA LETTER HO;Lo;0;L;;;;;N;;;;; 30DC;KATAKANA LETTER BO;Lo;0;L;30DB 3099;;;;N;;;;; 30DD;KATAKANA LETTER PO;Lo;0;L;30DB 309A;;;;N;;;;; 30DE;KATAKANA LETTER MA;Lo;0;L;;;;;N;;;;; 30DF;KATAKANA LETTER MI;Lo;0;L;;;;;N;;;;; 30E0;KATAKANA LETTER MU;Lo;0;L;;;;;N;;;;; 30E1;KATAKANA LETTER ME;Lo;0;L;;;;;N;;;;; 30E2;KATAKANA LETTER MO;Lo;0;L;;;;;N;;;;; 30E3;KATAKANA LETTER SMALL YA;Lo;0;L;;;;;N;;;;; 30E4;KATAKANA LETTER YA;Lo;0;L;;;;;N;;;;; 30E5;KATAKANA LETTER SMALL YU;Lo;0;L;;;;;N;;;;; 30E6;KATAKANA LETTER YU;Lo;0;L;;;;;N;;;;; 30E7;KATAKANA LETTER SMALL YO;Lo;0;L;;;;;N;;;;; 30E8;KATAKANA LETTER YO;Lo;0;L;;;;;N;;;;; 30E9;KATAKANA LETTER RA;Lo;0;L;;;;;N;;;;; 30EA;KATAKANA LETTER RI;Lo;0;L;;;;;N;;;;; 30EB;KATAKANA LETTER RU;Lo;0;L;;;;;N;;;;; 30EC;KATAKANA LETTER RE;Lo;0;L;;;;;N;;;;; 30ED;KATAKANA LETTER RO;Lo;0;L;;;;;N;;;;; 30EE;KATAKANA LETTER SMALL WA;Lo;0;L;;;;;N;;;;; 30EF;KATAKANA LETTER WA;Lo;0;L;;;;;N;;;;; 30F0;KATAKANA LETTER WI;Lo;0;L;;;;;N;;;;; 30F1;KATAKANA LETTER WE;Lo;0;L;;;;;N;;;;; 30F2;KATAKANA LETTER WO;Lo;0;L;;;;;N;;;;; 30F3;KATAKANA LETTER N;Lo;0;L;;;;;N;;;;; 30F4;KATAKANA LETTER VU;Lo;0;L;30A6 3099;;;;N;;;;; 30F5;KATAKANA LETTER SMALL KA;Lo;0;L;;;;;N;;;;; 30F6;KATAKANA LETTER SMALL KE;Lo;0;L;;;;;N;;;;; 30F7;KATAKANA LETTER VA;Lo;0;L;30EF 3099;;;;N;;;;; 30F8;KATAKANA LETTER VI;Lo;0;L;30F0 3099;;;;N;;;;; 30F9;KATAKANA LETTER VE;Lo;0;L;30F1 3099;;;;N;;;;; 30FA;KATAKANA LETTER VO;Lo;0;L;30F2 3099;;;;N;;;;; 30FB;KATAKANA MIDDLE DOT;Pc;0;ON;;;;;N;;;;; 30FC;KATAKANA-HIRAGANA PROLONGED SOUND MARK;Lm;0;L;;;;;N;;;;; 30FD;KATAKANA ITERATION MARK;Lm;0;L;;;;;N;;;;; 30FE;KATAKANA VOICED ITERATION MARK;Lm;0;L;30FD 3099;;;;N;;;;; 30FF;KATAKANA DIGRAPH KOTO;Lo;0;L; 30B3 30C8;;;;N;;;;; 3105;BOPOMOFO LETTER B;Lo;0;L;;;;;N;;;;; 3106;BOPOMOFO LETTER P;Lo;0;L;;;;;N;;;;; 3107;BOPOMOFO LETTER M;Lo;0;L;;;;;N;;;;; 3108;BOPOMOFO LETTER F;Lo;0;L;;;;;N;;;;; 3109;BOPOMOFO LETTER D;Lo;0;L;;;;;N;;;;; 310A;BOPOMOFO LETTER T;Lo;0;L;;;;;N;;;;; 310B;BOPOMOFO LETTER N;Lo;0;L;;;;;N;;;;; 310C;BOPOMOFO LETTER L;Lo;0;L;;;;;N;;;;; 310D;BOPOMOFO LETTER G;Lo;0;L;;;;;N;;;;; 310E;BOPOMOFO LETTER K;Lo;0;L;;;;;N;;;;; 310F;BOPOMOFO LETTER H;Lo;0;L;;;;;N;;;;; 3110;BOPOMOFO LETTER J;Lo;0;L;;;;;N;;;;; 3111;BOPOMOFO LETTER Q;Lo;0;L;;;;;N;;;;; 3112;BOPOMOFO LETTER X;Lo;0;L;;;;;N;;;;; 3113;BOPOMOFO LETTER ZH;Lo;0;L;;;;;N;;;;; 3114;BOPOMOFO LETTER CH;Lo;0;L;;;;;N;;;;; 3115;BOPOMOFO LETTER SH;Lo;0;L;;;;;N;;;;; 3116;BOPOMOFO LETTER R;Lo;0;L;;;;;N;;;;; 3117;BOPOMOFO LETTER Z;Lo;0;L;;;;;N;;;;; 3118;BOPOMOFO LETTER C;Lo;0;L;;;;;N;;;;; 3119;BOPOMOFO LETTER S;Lo;0;L;;;;;N;;;;; 311A;BOPOMOFO LETTER A;Lo;0;L;;;;;N;;;;; 311B;BOPOMOFO LETTER O;Lo;0;L;;;;;N;;;;; 311C;BOPOMOFO LETTER E;Lo;0;L;;;;;N;;;;; 311D;BOPOMOFO LETTER EH;Lo;0;L;;;;;N;;;;; 311E;BOPOMOFO LETTER AI;Lo;0;L;;;;;N;;;;; 311F;BOPOMOFO LETTER EI;Lo;0;L;;;;;N;;;;; 3120;BOPOMOFO LETTER AU;Lo;0;L;;;;;N;;;;; 3121;BOPOMOFO LETTER OU;Lo;0;L;;;;;N;;;;; 3122;BOPOMOFO LETTER AN;Lo;0;L;;;;;N;;;;; 3123;BOPOMOFO LETTER EN;Lo;0;L;;;;;N;;;;; 3124;BOPOMOFO LETTER ANG;Lo;0;L;;;;;N;;;;; 3125;BOPOMOFO LETTER ENG;Lo;0;L;;;;;N;;;;; 3126;BOPOMOFO LETTER ER;Lo;0;L;;;;;N;;;;; 3127;BOPOMOFO LETTER I;Lo;0;L;;;;;N;;;;; 3128;BOPOMOFO LETTER U;Lo;0;L;;;;;N;;;;; 3129;BOPOMOFO LETTER IU;Lo;0;L;;;;;N;;;;; 312A;BOPOMOFO LETTER V;Lo;0;L;;;;;N;;;;; 312B;BOPOMOFO LETTER NG;Lo;0;L;;;;;N;;;;; 312C;BOPOMOFO LETTER GN;Lo;0;L;;;;;N;;;;; 3131;HANGUL LETTER KIYEOK;Lo;0;L; 1100;;;;N;HANGUL LETTER GIYEOG;;;; 3132;HANGUL LETTER SSANGKIYEOK;Lo;0;L; 1101;;;;N;HANGUL LETTER SSANG GIYEOG;;;; 3133;HANGUL LETTER KIYEOK-SIOS;Lo;0;L; 11AA;;;;N;HANGUL LETTER GIYEOG SIOS;;;; 3134;HANGUL LETTER NIEUN;Lo;0;L; 1102;;;;N;;;;; 3135;HANGUL LETTER NIEUN-CIEUC;Lo;0;L; 11AC;;;;N;HANGUL LETTER NIEUN JIEUJ;;;; 3136;HANGUL LETTER NIEUN-HIEUH;Lo;0;L; 11AD;;;;N;HANGUL LETTER NIEUN HIEUH;;;; 3137;HANGUL LETTER TIKEUT;Lo;0;L; 1103;;;;N;HANGUL LETTER DIGEUD;;;; 3138;HANGUL LETTER SSANGTIKEUT;Lo;0;L; 1104;;;;N;HANGUL LETTER SSANG DIGEUD;;;; 3139;HANGUL LETTER RIEUL;Lo;0;L; 1105;;;;N;HANGUL LETTER LIEUL;;;; 313A;HANGUL LETTER RIEUL-KIYEOK;Lo;0;L; 11B0;;;;N;HANGUL LETTER LIEUL GIYEOG;;;; 313B;HANGUL LETTER RIEUL-MIEUM;Lo;0;L; 11B1;;;;N;HANGUL LETTER LIEUL MIEUM;;;; 313C;HANGUL LETTER RIEUL-PIEUP;Lo;0;L; 11B2;;;;N;HANGUL LETTER LIEUL BIEUB;;;; 313D;HANGUL LETTER RIEUL-SIOS;Lo;0;L; 11B3;;;;N;HANGUL LETTER LIEUL SIOS;;;; 313E;HANGUL LETTER RIEUL-THIEUTH;Lo;0;L; 11B4;;;;N;HANGUL LETTER LIEUL TIEUT;;;; 313F;HANGUL LETTER RIEUL-PHIEUPH;Lo;0;L; 11B5;;;;N;HANGUL LETTER LIEUL PIEUP;;;; 3140;HANGUL LETTER RIEUL-HIEUH;Lo;0;L; 111A;;;;N;HANGUL LETTER LIEUL HIEUH;;;; 3141;HANGUL LETTER MIEUM;Lo;0;L; 1106;;;;N;;;;; 3142;HANGUL LETTER PIEUP;Lo;0;L; 1107;;;;N;HANGUL LETTER BIEUB;;;; 3143;HANGUL LETTER SSANGPIEUP;Lo;0;L; 1108;;;;N;HANGUL LETTER SSANG BIEUB;;;; 3144;HANGUL LETTER PIEUP-SIOS;Lo;0;L; 1121;;;;N;HANGUL LETTER BIEUB SIOS;;;; 3145;HANGUL LETTER SIOS;Lo;0;L; 1109;;;;N;;;;; 3146;HANGUL LETTER SSANGSIOS;Lo;0;L; 110A;;;;N;HANGUL LETTER SSANG SIOS;;;; 3147;HANGUL LETTER IEUNG;Lo;0;L; 110B;;;;N;;;;; 3148;HANGUL LETTER CIEUC;Lo;0;L; 110C;;;;N;HANGUL LETTER JIEUJ;;;; 3149;HANGUL LETTER SSANGCIEUC;Lo;0;L; 110D;;;;N;HANGUL LETTER SSANG JIEUJ;;;; 314A;HANGUL LETTER CHIEUCH;Lo;0;L; 110E;;;;N;HANGUL LETTER CIEUC;;;; 314B;HANGUL LETTER KHIEUKH;Lo;0;L; 110F;;;;N;HANGUL LETTER KIYEOK;;;; 314C;HANGUL LETTER THIEUTH;Lo;0;L; 1110;;;;N;HANGUL LETTER TIEUT;;;; 314D;HANGUL LETTER PHIEUPH;Lo;0;L; 1111;;;;N;HANGUL LETTER PIEUP;;;; 314E;HANGUL LETTER HIEUH;Lo;0;L; 1112;;;;N;;;;; 314F;HANGUL LETTER A;Lo;0;L; 1161;;;;N;;;;; 3150;HANGUL LETTER AE;Lo;0;L; 1162;;;;N;;;;; 3151;HANGUL LETTER YA;Lo;0;L; 1163;;;;N;;;;; 3152;HANGUL LETTER YAE;Lo;0;L; 1164;;;;N;;;;; 3153;HANGUL LETTER EO;Lo;0;L; 1165;;;;N;;;;; 3154;HANGUL LETTER E;Lo;0;L; 1166;;;;N;;;;; 3155;HANGUL LETTER YEO;Lo;0;L; 1167;;;;N;;;;; 3156;HANGUL LETTER YE;Lo;0;L; 1168;;;;N;;;;; 3157;HANGUL LETTER O;Lo;0;L; 1169;;;;N;;;;; 3158;HANGUL LETTER WA;Lo;0;L; 116A;;;;N;;;;; 3159;HANGUL LETTER WAE;Lo;0;L; 116B;;;;N;;;;; 315A;HANGUL LETTER OE;Lo;0;L; 116C;;;;N;;;;; 315B;HANGUL LETTER YO;Lo;0;L; 116D;;;;N;;;;; 315C;HANGUL LETTER U;Lo;0;L; 116E;;;;N;;;;; 315D;HANGUL LETTER WEO;Lo;0;L; 116F;;;;N;;;;; 315E;HANGUL LETTER WE;Lo;0;L; 1170;;;;N;;;;; 315F;HANGUL LETTER WI;Lo;0;L; 1171;;;;N;;;;; 3160;HANGUL LETTER YU;Lo;0;L; 1172;;;;N;;;;; 3161;HANGUL LETTER EU;Lo;0;L; 1173;;;;N;;;;; 3162;HANGUL LETTER YI;Lo;0;L; 1174;;;;N;;;;; 3163;HANGUL LETTER I;Lo;0;L; 1175;;;;N;;;;; 3164;HANGUL FILLER;Lo;0;L; 1160;;;;N;HANGUL CAE OM;;;; 3165;HANGUL LETTER SSANGNIEUN;Lo;0;L; 1114;;;;N;HANGUL LETTER SSANG NIEUN;;;; 3166;HANGUL LETTER NIEUN-TIKEUT;Lo;0;L; 1115;;;;N;HANGUL LETTER NIEUN DIGEUD;;;; 3167;HANGUL LETTER NIEUN-SIOS;Lo;0;L; 11C7;;;;N;HANGUL LETTER NIEUN SIOS;;;; 3168;HANGUL LETTER NIEUN-PANSIOS;Lo;0;L; 11C8;;;;N;HANGUL LETTER NIEUN BAN CHI EUM;;;; 3169;HANGUL LETTER RIEUL-KIYEOK-SIOS;Lo;0;L; 11CC;;;;N;HANGUL LETTER LIEUL GIYEOG SIOS;;;; 316A;HANGUL LETTER RIEUL-TIKEUT;Lo;0;L; 11CE;;;;N;HANGUL LETTER LIEUL DIGEUD;;;; 316B;HANGUL LETTER RIEUL-PIEUP-SIOS;Lo;0;L; 11D3;;;;N;HANGUL LETTER LIEUL BIEUB SIOS;;;; 316C;HANGUL LETTER RIEUL-PANSIOS;Lo;0;L; 11D7;;;;N;HANGUL LETTER LIEUL BAN CHI EUM;;;; 316D;HANGUL LETTER RIEUL-YEORINHIEUH;Lo;0;L; 11D9;;;;N;HANGUL LETTER LIEUL YEOLIN HIEUH;;;; 316E;HANGUL LETTER MIEUM-PIEUP;Lo;0;L; 111C;;;;N;HANGUL LETTER MIEUM BIEUB;;;; 316F;HANGUL LETTER MIEUM-SIOS;Lo;0;L; 11DD;;;;N;HANGUL LETTER MIEUM SIOS;;;; 3170;HANGUL LETTER MIEUM-PANSIOS;Lo;0;L; 11DF;;;;N;HANGUL LETTER BIEUB BAN CHI EUM;;;; 3171;HANGUL LETTER KAPYEOUNMIEUM;Lo;0;L; 111D;;;;N;HANGUL LETTER MIEUM SUN GYEONG EUM;;;; 3172;HANGUL LETTER PIEUP-KIYEOK;Lo;0;L; 111E;;;;N;HANGUL LETTER BIEUB GIYEOG;;;; 3173;HANGUL LETTER PIEUP-TIKEUT;Lo;0;L; 1120;;;;N;HANGUL LETTER BIEUB DIGEUD;;;; 3174;HANGUL LETTER PIEUP-SIOS-KIYEOK;Lo;0;L; 1122;;;;N;HANGUL LETTER BIEUB SIOS GIYEOG;;;; 3175;HANGUL LETTER PIEUP-SIOS-TIKEUT;Lo;0;L; 1123;;;;N;HANGUL LETTER BIEUB SIOS DIGEUD;;;; 3176;HANGUL LETTER PIEUP-CIEUC;Lo;0;L; 1127;;;;N;HANGUL LETTER BIEUB JIEUJ;;;; 3177;HANGUL LETTER PIEUP-THIEUTH;Lo;0;L; 1129;;;;N;HANGUL LETTER BIEUB TIEUT;;;; 3178;HANGUL LETTER KAPYEOUNPIEUP;Lo;0;L; 112B;;;;N;HANGUL LETTER BIEUB SUN GYEONG EUM;;;; 3179;HANGUL LETTER KAPYEOUNSSANGPIEUP;Lo;0;L; 112C;;;;N;HANGUL LETTER SSANG BIEUB SUN GYEONG EUM;;;; 317A;HANGUL LETTER SIOS-KIYEOK;Lo;0;L; 112D;;;;N;HANGUL LETTER SIOS GIYEOG;;;; 317B;HANGUL LETTER SIOS-NIEUN;Lo;0;L; 112E;;;;N;HANGUL LETTER SIOS NIEUN;;;; 317C;HANGUL LETTER SIOS-TIKEUT;Lo;0;L; 112F;;;;N;HANGUL LETTER SIOS DIGEUD;;;; 317D;HANGUL LETTER SIOS-PIEUP;Lo;0;L; 1132;;;;N;HANGUL LETTER SIOS BIEUB;;;; 317E;HANGUL LETTER SIOS-CIEUC;Lo;0;L; 1136;;;;N;HANGUL LETTER SIOS JIEUJ;;;; 317F;HANGUL LETTER PANSIOS;Lo;0;L; 1140;;;;N;HANGUL LETTER BAN CHI EUM;;;; 3180;HANGUL LETTER SSANGIEUNG;Lo;0;L; 1147;;;;N;HANGUL LETTER SSANG IEUNG;;;; 3181;HANGUL LETTER YESIEUNG;Lo;0;L; 114C;;;;N;HANGUL LETTER NGIEUNG;;;; 3182;HANGUL LETTER YESIEUNG-SIOS;Lo;0;L; 11F1;;;;N;HANGUL LETTER NGIEUNG SIOS;;;; 3183;HANGUL LETTER YESIEUNG-PANSIOS;Lo;0;L; 11F2;;;;N;HANGUL LETTER NGIEUNG BAN CHI EUM;;;; 3184;HANGUL LETTER KAPYEOUNPHIEUPH;Lo;0;L; 1157;;;;N;HANGUL LETTER PIEUP SUN GYEONG EUM;;;; 3185;HANGUL LETTER SSANGHIEUH;Lo;0;L; 1158;;;;N;HANGUL LETTER SSANG HIEUH;;;; 3186;HANGUL LETTER YEORINHIEUH;Lo;0;L; 1159;;;;N;HANGUL LETTER YEOLIN HIEUH;;;; 3187;HANGUL LETTER YO-YA;Lo;0;L; 1184;;;;N;HANGUL LETTER YOYA;;;; 3188;HANGUL LETTER YO-YAE;Lo;0;L; 1185;;;;N;HANGUL LETTER YOYAE;;;; 3189;HANGUL LETTER YO-I;Lo;0;L; 1188;;;;N;HANGUL LETTER YOI;;;; 318A;HANGUL LETTER YU-YEO;Lo;0;L; 1191;;;;N;HANGUL LETTER YUYEO;;;; 318B;HANGUL LETTER YU-YE;Lo;0;L; 1192;;;;N;HANGUL LETTER YUYE;;;; 318C;HANGUL LETTER YU-I;Lo;0;L; 1194;;;;N;HANGUL LETTER YUI;;;; 318D;HANGUL LETTER ARAEA;Lo;0;L; 119E;;;;N;HANGUL LETTER ALAE A;;;; 318E;HANGUL LETTER ARAEAE;Lo;0;L; 11A1;;;;N;HANGUL LETTER ALAE AE;;;; 3190;IDEOGRAPHIC ANNOTATION LINKING MARK;So;0;L;;;;;N;KANBUN TATETEN;Kanbun Tateten;;; 3191;IDEOGRAPHIC ANNOTATION REVERSE MARK;So;0;L;;;;;N;KAERITEN RE;Kaeriten;;; 3192;IDEOGRAPHIC ANNOTATION ONE MARK;No;0;L; 4E00;;;1;N;KAERITEN ITI;Kaeriten;;; 3193;IDEOGRAPHIC ANNOTATION TWO MARK;No;0;L; 4E8C;;;2;N;KAERITEN NI;Kaeriten;;; 3194;IDEOGRAPHIC ANNOTATION THREE MARK;No;0;L; 4E09;;;3;N;KAERITEN SAN;Kaeriten;;; 3195;IDEOGRAPHIC ANNOTATION FOUR MARK;No;0;L; 56DB;;;4;N;KAERITEN SI;Kaeriten;;; 3196;IDEOGRAPHIC ANNOTATION TOP MARK;So;0;L; 4E0A;;;;N;KAERITEN ZYOU;Kaeriten;;; 3197;IDEOGRAPHIC ANNOTATION MIDDLE MARK;So;0;L; 4E2D;;;;N;KAERITEN TYUU;Kaeriten;;; 3198;IDEOGRAPHIC ANNOTATION BOTTOM MARK;So;0;L; 4E0B;;;;N;KAERITEN GE;Kaeriten;;; 3199;IDEOGRAPHIC ANNOTATION FIRST MARK;So;0;L; 7532;;;;N;KAERITEN KOU;Kaeriten;;; 319A;IDEOGRAPHIC ANNOTATION SECOND MARK;So;0;L; 4E59;;;;N;KAERITEN OTU;Kaeriten;;; 319B;IDEOGRAPHIC ANNOTATION THIRD MARK;So;0;L; 4E19;;;;N;KAERITEN HEI;Kaeriten;;; 319C;IDEOGRAPHIC ANNOTATION FOURTH MARK;So;0;L; 4E01;;;;N;KAERITEN TEI;Kaeriten;;; 319D;IDEOGRAPHIC ANNOTATION HEAVEN MARK;So;0;L; 5929;;;;N;KAERITEN TEN;Kaeriten;;; 319E;IDEOGRAPHIC ANNOTATION EARTH MARK;So;0;L; 5730;;;;N;KAERITEN TI;Kaeriten;;; 319F;IDEOGRAPHIC ANNOTATION MAN MARK;So;0;L; 4EBA;;;;N;KAERITEN ZIN;Kaeriten;;; 31A0;BOPOMOFO LETTER BU;Lo;0;L;;;;;N;;;;; 31A1;BOPOMOFO LETTER ZI;Lo;0;L;;;;;N;;;;; 31A2;BOPOMOFO LETTER JI;Lo;0;L;;;;;N;;;;; 31A3;BOPOMOFO LETTER GU;Lo;0;L;;;;;N;;;;; 31A4;BOPOMOFO LETTER EE;Lo;0;L;;;;;N;;;;; 31A5;BOPOMOFO LETTER ENN;Lo;0;L;;;;;N;;;;; 31A6;BOPOMOFO LETTER OO;Lo;0;L;;;;;N;;;;; 31A7;BOPOMOFO LETTER ONN;Lo;0;L;;;;;N;;;;; 31A8;BOPOMOFO LETTER IR;Lo;0;L;;;;;N;;;;; 31A9;BOPOMOFO LETTER ANN;Lo;0;L;;;;;N;;;;; 31AA;BOPOMOFO LETTER INN;Lo;0;L;;;;;N;;;;; 31AB;BOPOMOFO LETTER UNN;Lo;0;L;;;;;N;;;;; 31AC;BOPOMOFO LETTER IM;Lo;0;L;;;;;N;;;;; 31AD;BOPOMOFO LETTER NGG;Lo;0;L;;;;;N;;;;; 31AE;BOPOMOFO LETTER AINN;Lo;0;L;;;;;N;;;;; 31AF;BOPOMOFO LETTER AUNN;Lo;0;L;;;;;N;;;;; 31B0;BOPOMOFO LETTER AM;Lo;0;L;;;;;N;;;;; 31B1;BOPOMOFO LETTER OM;Lo;0;L;;;;;N;;;;; 31B2;BOPOMOFO LETTER ONG;Lo;0;L;;;;;N;;;;; 31B3;BOPOMOFO LETTER INNN;Lo;0;L;;;;;N;;;;; 31B4;BOPOMOFO FINAL LETTER P;Lo;0;L;;;;;N;;;;; 31B5;BOPOMOFO FINAL LETTER T;Lo;0;L;;;;;N;;;;; 31B6;BOPOMOFO FINAL LETTER K;Lo;0;L;;;;;N;;;;; 31B7;BOPOMOFO FINAL LETTER H;Lo;0;L;;;;;N;;;;; 31F0;KATAKANA LETTER SMALL KU;Lo;0;L;;;;;N;;;;; 31F1;KATAKANA LETTER SMALL SI;Lo;0;L;;;;;N;;;;; 31F2;KATAKANA LETTER SMALL SU;Lo;0;L;;;;;N;;;;; 31F3;KATAKANA LETTER SMALL TO;Lo;0;L;;;;;N;;;;; 31F4;KATAKANA LETTER SMALL NU;Lo;0;L;;;;;N;;;;; 31F5;KATAKANA LETTER SMALL HA;Lo;0;L;;;;;N;;;;; 31F6;KATAKANA LETTER SMALL HI;Lo;0;L;;;;;N;;;;; 31F7;KATAKANA LETTER SMALL HU;Lo;0;L;;;;;N;;;;; 31F8;KATAKANA LETTER SMALL HE;Lo;0;L;;;;;N;;;;; 31F9;KATAKANA LETTER SMALL HO;Lo;0;L;;;;;N;;;;; 31FA;KATAKANA LETTER SMALL MU;Lo;0;L;;;;;N;;;;; 31FB;KATAKANA LETTER SMALL RA;Lo;0;L;;;;;N;;;;; 31FC;KATAKANA LETTER SMALL RI;Lo;0;L;;;;;N;;;;; 31FD;KATAKANA LETTER SMALL RU;Lo;0;L;;;;;N;;;;; 31FE;KATAKANA LETTER SMALL RE;Lo;0;L;;;;;N;;;;; 31FF;KATAKANA LETTER SMALL RO;Lo;0;L;;;;;N;;;;; 3200;PARENTHESIZED HANGUL KIYEOK;So;0;L; 0028 1100 0029;;;;N;PARENTHESIZED HANGUL GIYEOG;;;; 3201;PARENTHESIZED HANGUL NIEUN;So;0;L; 0028 1102 0029;;;;N;;;;; 3202;PARENTHESIZED HANGUL TIKEUT;So;0;L; 0028 1103 0029;;;;N;PARENTHESIZED HANGUL DIGEUD;;;; 3203;PARENTHESIZED HANGUL RIEUL;So;0;L; 0028 1105 0029;;;;N;PARENTHESIZED HANGUL LIEUL;;;; 3204;PARENTHESIZED HANGUL MIEUM;So;0;L; 0028 1106 0029;;;;N;;;;; 3205;PARENTHESIZED HANGUL PIEUP;So;0;L; 0028 1107 0029;;;;N;PARENTHESIZED HANGUL BIEUB;;;; 3206;PARENTHESIZED HANGUL SIOS;So;0;L; 0028 1109 0029;;;;N;;;;; 3207;PARENTHESIZED HANGUL IEUNG;So;0;L; 0028 110B 0029;;;;N;;;;; 3208;PARENTHESIZED HANGUL CIEUC;So;0;L; 0028 110C 0029;;;;N;PARENTHESIZED HANGUL JIEUJ;;;; 3209;PARENTHESIZED HANGUL CHIEUCH;So;0;L; 0028 110E 0029;;;;N;PARENTHESIZED HANGUL CIEUC;;;; 320A;PARENTHESIZED HANGUL KHIEUKH;So;0;L; 0028 110F 0029;;;;N;PARENTHESIZED HANGUL KIYEOK;;;; 320B;PARENTHESIZED HANGUL THIEUTH;So;0;L; 0028 1110 0029;;;;N;PARENTHESIZED HANGUL TIEUT;;;; 320C;PARENTHESIZED HANGUL PHIEUPH;So;0;L; 0028 1111 0029;;;;N;PARENTHESIZED HANGUL PIEUP;;;; 320D;PARENTHESIZED HANGUL HIEUH;So;0;L; 0028 1112 0029;;;;N;;;;; 320E;PARENTHESIZED HANGUL KIYEOK A;So;0;L; 0028 1100 1161 0029;;;;N;PARENTHESIZED HANGUL GA;;;; 320F;PARENTHESIZED HANGUL NIEUN A;So;0;L; 0028 1102 1161 0029;;;;N;PARENTHESIZED HANGUL NA;;;; 3210;PARENTHESIZED HANGUL TIKEUT A;So;0;L; 0028 1103 1161 0029;;;;N;PARENTHESIZED HANGUL DA;;;; 3211;PARENTHESIZED HANGUL RIEUL A;So;0;L; 0028 1105 1161 0029;;;;N;PARENTHESIZED HANGUL LA;;;; 3212;PARENTHESIZED HANGUL MIEUM A;So;0;L; 0028 1106 1161 0029;;;;N;PARENTHESIZED HANGUL MA;;;; 3213;PARENTHESIZED HANGUL PIEUP A;So;0;L; 0028 1107 1161 0029;;;;N;PARENTHESIZED HANGUL BA;;;; 3214;PARENTHESIZED HANGUL SIOS A;So;0;L; 0028 1109 1161 0029;;;;N;PARENTHESIZED HANGUL SA;;;; 3215;PARENTHESIZED HANGUL IEUNG A;So;0;L; 0028 110B 1161 0029;;;;N;PARENTHESIZED HANGUL A;;;; 3216;PARENTHESIZED HANGUL CIEUC A;So;0;L; 0028 110C 1161 0029;;;;N;PARENTHESIZED HANGUL JA;;;; 3217;PARENTHESIZED HANGUL CHIEUCH A;So;0;L; 0028 110E 1161 0029;;;;N;PARENTHESIZED HANGUL CA;;;; 3218;PARENTHESIZED HANGUL KHIEUKH A;So;0;L; 0028 110F 1161 0029;;;;N;PARENTHESIZED HANGUL KA;;;; 3219;PARENTHESIZED HANGUL THIEUTH A;So;0;L; 0028 1110 1161 0029;;;;N;PARENTHESIZED HANGUL TA;;;; 321A;PARENTHESIZED HANGUL PHIEUPH A;So;0;L; 0028 1111 1161 0029;;;;N;PARENTHESIZED HANGUL PA;;;; 321B;PARENTHESIZED HANGUL HIEUH A;So;0;L; 0028 1112 1161 0029;;;;N;PARENTHESIZED HANGUL HA;;;; 321C;PARENTHESIZED HANGUL CIEUC U;So;0;L; 0028 110C 116E 0029;;;;N;PARENTHESIZED HANGUL JU;;;; 3220;PARENTHESIZED IDEOGRAPH ONE;No;0;L; 0028 4E00 0029;;;1;N;;;;; 3221;PARENTHESIZED IDEOGRAPH TWO;No;0;L; 0028 4E8C 0029;;;2;N;;;;; 3222;PARENTHESIZED IDEOGRAPH THREE;No;0;L; 0028 4E09 0029;;;3;N;;;;; 3223;PARENTHESIZED IDEOGRAPH FOUR;No;0;L; 0028 56DB 0029;;;4;N;;;;; 3224;PARENTHESIZED IDEOGRAPH FIVE;No;0;L; 0028 4E94 0029;;;5;N;;;;; 3225;PARENTHESIZED IDEOGRAPH SIX;No;0;L; 0028 516D 0029;;;6;N;;;;; 3226;PARENTHESIZED IDEOGRAPH SEVEN;No;0;L; 0028 4E03 0029;;;7;N;;;;; 3227;PARENTHESIZED IDEOGRAPH EIGHT;No;0;L; 0028 516B 0029;;;8;N;;;;; 3228;PARENTHESIZED IDEOGRAPH NINE;No;0;L; 0028 4E5D 0029;;;9;N;;;;; 3229;PARENTHESIZED IDEOGRAPH TEN;No;0;L; 0028 5341 0029;;;10;N;;;;; 322A;PARENTHESIZED IDEOGRAPH MOON;So;0;L; 0028 6708 0029;;;;N;;;;; 322B;PARENTHESIZED IDEOGRAPH FIRE;So;0;L; 0028 706B 0029;;;;N;;;;; 322C;PARENTHESIZED IDEOGRAPH WATER;So;0;L; 0028 6C34 0029;;;;N;;;;; 322D;PARENTHESIZED IDEOGRAPH WOOD;So;0;L; 0028 6728 0029;;;;N;;;;; 322E;PARENTHESIZED IDEOGRAPH METAL;So;0;L; 0028 91D1 0029;;;;N;;;;; 322F;PARENTHESIZED IDEOGRAPH EARTH;So;0;L; 0028 571F 0029;;;;N;;;;; 3230;PARENTHESIZED IDEOGRAPH SUN;So;0;L; 0028 65E5 0029;;;;N;;;;; 3231;PARENTHESIZED IDEOGRAPH STOCK;So;0;L; 0028 682A 0029;;;;N;;;;; 3232;PARENTHESIZED IDEOGRAPH HAVE;So;0;L; 0028 6709 0029;;;;N;;;;; 3233;PARENTHESIZED IDEOGRAPH SOCIETY;So;0;L; 0028 793E 0029;;;;N;;;;; 3234;PARENTHESIZED IDEOGRAPH NAME;So;0;L; 0028 540D 0029;;;;N;;;;; 3235;PARENTHESIZED IDEOGRAPH SPECIAL;So;0;L; 0028 7279 0029;;;;N;;;;; 3236;PARENTHESIZED IDEOGRAPH FINANCIAL;So;0;L; 0028 8CA1 0029;;;;N;;;;; 3237;PARENTHESIZED IDEOGRAPH CONGRATULATION;So;0;L; 0028 795D 0029;;;;N;;;;; 3238;PARENTHESIZED IDEOGRAPH LABOR;So;0;L; 0028 52B4 0029;;;;N;;;;; 3239;PARENTHESIZED IDEOGRAPH REPRESENT;So;0;L; 0028 4EE3 0029;;;;N;;;;; 323A;PARENTHESIZED IDEOGRAPH CALL;So;0;L; 0028 547C 0029;;;;N;;;;; 323B;PARENTHESIZED IDEOGRAPH STUDY;So;0;L; 0028 5B66 0029;;;;N;;;;; 323C;PARENTHESIZED IDEOGRAPH SUPERVISE;So;0;L; 0028 76E3 0029;;;;N;;;;; 323D;PARENTHESIZED IDEOGRAPH ENTERPRISE;So;0;L; 0028 4F01 0029;;;;N;;;;; 323E;PARENTHESIZED IDEOGRAPH RESOURCE;So;0;L; 0028 8CC7 0029;;;;N;;;;; 323F;PARENTHESIZED IDEOGRAPH ALLIANCE;So;0;L; 0028 5354 0029;;;;N;;;;; 3240;PARENTHESIZED IDEOGRAPH FESTIVAL;So;0;L; 0028 796D 0029;;;;N;;;;; 3241;PARENTHESIZED IDEOGRAPH REST;So;0;L; 0028 4F11 0029;;;;N;;;;; 3242;PARENTHESIZED IDEOGRAPH SELF;So;0;L; 0028 81EA 0029;;;;N;;;;; 3243;PARENTHESIZED IDEOGRAPH REACH;So;0;L; 0028 81F3 0029;;;;N;;;;; 3251;CIRCLED NUMBER TWENTY ONE;No;0;ON; 0032 0031;;;21;N;;;;; 3252;CIRCLED NUMBER TWENTY TWO;No;0;ON; 0032 0032;;;22;N;;;;; 3253;CIRCLED NUMBER TWENTY THREE;No;0;ON; 0032 0033;;;23;N;;;;; 3254;CIRCLED NUMBER TWENTY FOUR;No;0;ON; 0032 0034;;;24;N;;;;; 3255;CIRCLED NUMBER TWENTY FIVE;No;0;ON; 0032 0035;;;25;N;;;;; 3256;CIRCLED NUMBER TWENTY SIX;No;0;ON; 0032 0036;;;26;N;;;;; 3257;CIRCLED NUMBER TWENTY SEVEN;No;0;ON; 0032 0037;;;27;N;;;;; 3258;CIRCLED NUMBER TWENTY EIGHT;No;0;ON; 0032 0038;;;28;N;;;;; 3259;CIRCLED NUMBER TWENTY NINE;No;0;ON; 0032 0039;;;29;N;;;;; 325A;CIRCLED NUMBER THIRTY;No;0;ON; 0033 0030;;;30;N;;;;; 325B;CIRCLED NUMBER THIRTY ONE;No;0;ON; 0033 0031;;;31;N;;;;; 325C;CIRCLED NUMBER THIRTY TWO;No;0;ON; 0033 0032;;;32;N;;;;; 325D;CIRCLED NUMBER THIRTY THREE;No;0;ON; 0033 0033;;;33;N;;;;; 325E;CIRCLED NUMBER THIRTY FOUR;No;0;ON; 0033 0034;;;34;N;;;;; 325F;CIRCLED NUMBER THIRTY FIVE;No;0;ON; 0033 0035;;;35;N;;;;; 3260;CIRCLED HANGUL KIYEOK;So;0;L; 1100;;;;N;CIRCLED HANGUL GIYEOG;;;; 3261;CIRCLED HANGUL NIEUN;So;0;L; 1102;;;;N;;;;; 3262;CIRCLED HANGUL TIKEUT;So;0;L; 1103;;;;N;CIRCLED HANGUL DIGEUD;;;; 3263;CIRCLED HANGUL RIEUL;So;0;L; 1105;;;;N;CIRCLED HANGUL LIEUL;;;; 3264;CIRCLED HANGUL MIEUM;So;0;L; 1106;;;;N;;;;; 3265;CIRCLED HANGUL PIEUP;So;0;L; 1107;;;;N;CIRCLED HANGUL BIEUB;;;; 3266;CIRCLED HANGUL SIOS;So;0;L; 1109;;;;N;;;;; 3267;CIRCLED HANGUL IEUNG;So;0;L; 110B;;;;N;;;;; 3268;CIRCLED HANGUL CIEUC;So;0;L; 110C;;;;N;CIRCLED HANGUL JIEUJ;;;; 3269;CIRCLED HANGUL CHIEUCH;So;0;L; 110E;;;;N;CIRCLED HANGUL CIEUC;;;; 326A;CIRCLED HANGUL KHIEUKH;So;0;L; 110F;;;;N;CIRCLED HANGUL KIYEOK;;;; 326B;CIRCLED HANGUL THIEUTH;So;0;L; 1110;;;;N;CIRCLED HANGUL TIEUT;;;; 326C;CIRCLED HANGUL PHIEUPH;So;0;L; 1111;;;;N;CIRCLED HANGUL PIEUP;;;; 326D;CIRCLED HANGUL HIEUH;So;0;L; 1112;;;;N;;;;; 326E;CIRCLED HANGUL KIYEOK A;So;0;L; 1100 1161;;;;N;CIRCLED HANGUL GA;;;; 326F;CIRCLED HANGUL NIEUN A;So;0;L; 1102 1161;;;;N;CIRCLED HANGUL NA;;;; 3270;CIRCLED HANGUL TIKEUT A;So;0;L; 1103 1161;;;;N;CIRCLED HANGUL DA;;;; 3271;CIRCLED HANGUL RIEUL A;So;0;L; 1105 1161;;;;N;CIRCLED HANGUL LA;;;; 3272;CIRCLED HANGUL MIEUM A;So;0;L; 1106 1161;;;;N;CIRCLED HANGUL MA;;;; 3273;CIRCLED HANGUL PIEUP A;So;0;L; 1107 1161;;;;N;CIRCLED HANGUL BA;;;; 3274;CIRCLED HANGUL SIOS A;So;0;L; 1109 1161;;;;N;CIRCLED HANGUL SA;;;; 3275;CIRCLED HANGUL IEUNG A;So;0;L; 110B 1161;;;;N;CIRCLED HANGUL A;;;; 3276;CIRCLED HANGUL CIEUC A;So;0;L; 110C 1161;;;;N;CIRCLED HANGUL JA;;;; 3277;CIRCLED HANGUL CHIEUCH A;So;0;L; 110E 1161;;;;N;CIRCLED HANGUL CA;;;; 3278;CIRCLED HANGUL KHIEUKH A;So;0;L; 110F 1161;;;;N;CIRCLED HANGUL KA;;;; 3279;CIRCLED HANGUL THIEUTH A;So;0;L; 1110 1161;;;;N;CIRCLED HANGUL TA;;;; 327A;CIRCLED HANGUL PHIEUPH A;So;0;L; 1111 1161;;;;N;CIRCLED HANGUL PA;;;; 327B;CIRCLED HANGUL HIEUH A;So;0;L; 1112 1161;;;;N;CIRCLED HANGUL HA;;;; 327F;KOREAN STANDARD SYMBOL;So;0;L;;;;;N;;;;; 3280;CIRCLED IDEOGRAPH ONE;No;0;L; 4E00;;;1;N;;;;; 3281;CIRCLED IDEOGRAPH TWO;No;0;L; 4E8C;;;2;N;;;;; 3282;CIRCLED IDEOGRAPH THREE;No;0;L; 4E09;;;3;N;;;;; 3283;CIRCLED IDEOGRAPH FOUR;No;0;L; 56DB;;;4;N;;;;; 3284;CIRCLED IDEOGRAPH FIVE;No;0;L; 4E94;;;5;N;;;;; 3285;CIRCLED IDEOGRAPH SIX;No;0;L; 516D;;;6;N;;;;; 3286;CIRCLED IDEOGRAPH SEVEN;No;0;L; 4E03;;;7;N;;;;; 3287;CIRCLED IDEOGRAPH EIGHT;No;0;L; 516B;;;8;N;;;;; 3288;CIRCLED IDEOGRAPH NINE;No;0;L; 4E5D;;;9;N;;;;; 3289;CIRCLED IDEOGRAPH TEN;No;0;L; 5341;;;10;N;;;;; 328A;CIRCLED IDEOGRAPH MOON;So;0;L; 6708;;;;N;;;;; 328B;CIRCLED IDEOGRAPH FIRE;So;0;L; 706B;;;;N;;;;; 328C;CIRCLED IDEOGRAPH WATER;So;0;L; 6C34;;;;N;;;;; 328D;CIRCLED IDEOGRAPH WOOD;So;0;L; 6728;;;;N;;;;; 328E;CIRCLED IDEOGRAPH METAL;So;0;L; 91D1;;;;N;;;;; 328F;CIRCLED IDEOGRAPH EARTH;So;0;L; 571F;;;;N;;;;; 3290;CIRCLED IDEOGRAPH SUN;So;0;L; 65E5;;;;N;;;;; 3291;CIRCLED IDEOGRAPH STOCK;So;0;L; 682A;;;;N;;;;; 3292;CIRCLED IDEOGRAPH HAVE;So;0;L; 6709;;;;N;;;;; 3293;CIRCLED IDEOGRAPH SOCIETY;So;0;L; 793E;;;;N;;;;; 3294;CIRCLED IDEOGRAPH NAME;So;0;L; 540D;;;;N;;;;; 3295;CIRCLED IDEOGRAPH SPECIAL;So;0;L; 7279;;;;N;;;;; 3296;CIRCLED IDEOGRAPH FINANCIAL;So;0;L; 8CA1;;;;N;;;;; 3297;CIRCLED IDEOGRAPH CONGRATULATION;So;0;L; 795D;;;;N;;;;; 3298;CIRCLED IDEOGRAPH LABOR;So;0;L; 52B4;;;;N;;;;; 3299;CIRCLED IDEOGRAPH SECRET;So;0;L; 79D8;;;;N;;;;; 329A;CIRCLED IDEOGRAPH MALE;So;0;L; 7537;;;;N;;;;; 329B;CIRCLED IDEOGRAPH FEMALE;So;0;L; 5973;;;;N;;;;; 329C;CIRCLED IDEOGRAPH SUITABLE;So;0;L; 9069;;;;N;;;;; 329D;CIRCLED IDEOGRAPH EXCELLENT;So;0;L; 512A;;;;N;;;;; 329E;CIRCLED IDEOGRAPH PRINT;So;0;L; 5370;;;;N;;;;; 329F;CIRCLED IDEOGRAPH ATTENTION;So;0;L; 6CE8;;;;N;;;;; 32A0;CIRCLED IDEOGRAPH ITEM;So;0;L; 9805;;;;N;;;;; 32A1;CIRCLED IDEOGRAPH REST;So;0;L; 4F11;;;;N;;;;; 32A2;CIRCLED IDEOGRAPH COPY;So;0;L; 5199;;;;N;;;;; 32A3;CIRCLED IDEOGRAPH CORRECT;So;0;L; 6B63;;;;N;;;;; 32A4;CIRCLED IDEOGRAPH HIGH;So;0;L; 4E0A;;;;N;;;;; 32A5;CIRCLED IDEOGRAPH CENTRE;So;0;L; 4E2D;;;;N;CIRCLED IDEOGRAPH CENTER;;;; 32A6;CIRCLED IDEOGRAPH LOW;So;0;L; 4E0B;;;;N;;;;; 32A7;CIRCLED IDEOGRAPH LEFT;So;0;L; 5DE6;;;;N;;;;; 32A8;CIRCLED IDEOGRAPH RIGHT;So;0;L; 53F3;;;;N;;;;; 32A9;CIRCLED IDEOGRAPH MEDICINE;So;0;L; 533B;;;;N;;;;; 32AA;CIRCLED IDEOGRAPH RELIGION;So;0;L; 5B97;;;;N;;;;; 32AB;CIRCLED IDEOGRAPH STUDY;So;0;L; 5B66;;;;N;;;;; 32AC;CIRCLED IDEOGRAPH SUPERVISE;So;0;L; 76E3;;;;N;;;;; 32AD;CIRCLED IDEOGRAPH ENTERPRISE;So;0;L; 4F01;;;;N;;;;; 32AE;CIRCLED IDEOGRAPH RESOURCE;So;0;L; 8CC7;;;;N;;;;; 32AF;CIRCLED IDEOGRAPH ALLIANCE;So;0;L; 5354;;;;N;;;;; 32B0;CIRCLED IDEOGRAPH NIGHT;So;0;L; 591C;;;;N;;;;; 32B1;CIRCLED NUMBER THIRTY SIX;No;0;ON; 0033 0036;;;36;N;;;;; 32B2;CIRCLED NUMBER THIRTY SEVEN;No;0;ON; 0033 0037;;;37;N;;;;; 32B3;CIRCLED NUMBER THIRTY EIGHT;No;0;ON; 0033 0038;;;38;N;;;;; 32B4;CIRCLED NUMBER THIRTY NINE;No;0;ON; 0033 0039;;;39;N;;;;; 32B5;CIRCLED NUMBER FORTY;No;0;ON; 0034 0030;;;40;N;;;;; 32B6;CIRCLED NUMBER FORTY ONE;No;0;ON; 0034 0031;;;41;N;;;;; 32B7;CIRCLED NUMBER FORTY TWO;No;0;ON; 0034 0032;;;42;N;;;;; 32B8;CIRCLED NUMBER FORTY THREE;No;0;ON; 0034 0033;;;43;N;;;;; 32B9;CIRCLED NUMBER FORTY FOUR;No;0;ON; 0034 0034;;;44;N;;;;; 32BA;CIRCLED NUMBER FORTY FIVE;No;0;ON; 0034 0035;;;45;N;;;;; 32BB;CIRCLED NUMBER FORTY SIX;No;0;ON; 0034 0036;;;46;N;;;;; 32BC;CIRCLED NUMBER FORTY SEVEN;No;0;ON; 0034 0037;;;47;N;;;;; 32BD;CIRCLED NUMBER FORTY EIGHT;No;0;ON; 0034 0038;;;48;N;;;;; 32BE;CIRCLED NUMBER FORTY NINE;No;0;ON; 0034 0039;;;49;N;;;;; 32BF;CIRCLED NUMBER FIFTY;No;0;ON; 0035 0030;;;50;N;;;;; 32C0;IDEOGRAPHIC TELEGRAPH SYMBOL FOR JANUARY;So;0;L; 0031 6708;;;;N;;;;; 32C1;IDEOGRAPHIC TELEGRAPH SYMBOL FOR FEBRUARY;So;0;L; 0032 6708;;;;N;;;;; 32C2;IDEOGRAPHIC TELEGRAPH SYMBOL FOR MARCH;So;0;L; 0033 6708;;;;N;;;;; 32C3;IDEOGRAPHIC TELEGRAPH SYMBOL FOR APRIL;So;0;L; 0034 6708;;;;N;;;;; 32C4;IDEOGRAPHIC TELEGRAPH SYMBOL FOR MAY;So;0;L; 0035 6708;;;;N;;;;; 32C5;IDEOGRAPHIC TELEGRAPH SYMBOL FOR JUNE;So;0;L; 0036 6708;;;;N;;;;; 32C6;IDEOGRAPHIC TELEGRAPH SYMBOL FOR JULY;So;0;L; 0037 6708;;;;N;;;;; 32C7;IDEOGRAPHIC TELEGRAPH SYMBOL FOR AUGUST;So;0;L; 0038 6708;;;;N;;;;; 32C8;IDEOGRAPHIC TELEGRAPH SYMBOL FOR SEPTEMBER;So;0;L; 0039 6708;;;;N;;;;; 32C9;IDEOGRAPHIC TELEGRAPH SYMBOL FOR OCTOBER;So;0;L; 0031 0030 6708;;;;N;;;;; 32CA;IDEOGRAPHIC TELEGRAPH SYMBOL FOR NOVEMBER;So;0;L; 0031 0031 6708;;;;N;;;;; 32CB;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DECEMBER;So;0;L; 0031 0032 6708;;;;N;;;;; 32D0;CIRCLED KATAKANA A;So;0;L; 30A2;;;;N;;;;; 32D1;CIRCLED KATAKANA I;So;0;L; 30A4;;;;N;;;;; 32D2;CIRCLED KATAKANA U;So;0;L; 30A6;;;;N;;;;; 32D3;CIRCLED KATAKANA E;So;0;L; 30A8;;;;N;;;;; 32D4;CIRCLED KATAKANA O;So;0;L; 30AA;;;;N;;;;; 32D5;CIRCLED KATAKANA KA;So;0;L; 30AB;;;;N;;;;; 32D6;CIRCLED KATAKANA KI;So;0;L; 30AD;;;;N;;;;; 32D7;CIRCLED KATAKANA KU;So;0;L; 30AF;;;;N;;;;; 32D8;CIRCLED KATAKANA KE;So;0;L; 30B1;;;;N;;;;; 32D9;CIRCLED KATAKANA KO;So;0;L; 30B3;;;;N;;;;; 32DA;CIRCLED KATAKANA SA;So;0;L; 30B5;;;;N;;;;; 32DB;CIRCLED KATAKANA SI;So;0;L; 30B7;;;;N;;;;; 32DC;CIRCLED KATAKANA SU;So;0;L; 30B9;;;;N;;;;; 32DD;CIRCLED KATAKANA SE;So;0;L; 30BB;;;;N;;;;; 32DE;CIRCLED KATAKANA SO;So;0;L; 30BD;;;;N;;;;; 32DF;CIRCLED KATAKANA TA;So;0;L; 30BF;;;;N;;;;; 32E0;CIRCLED KATAKANA TI;So;0;L; 30C1;;;;N;;;;; 32E1;CIRCLED KATAKANA TU;So;0;L; 30C4;;;;N;;;;; 32E2;CIRCLED KATAKANA TE;So;0;L; 30C6;;;;N;;;;; 32E3;CIRCLED KATAKANA TO;So;0;L; 30C8;;;;N;;;;; 32E4;CIRCLED KATAKANA NA;So;0;L; 30CA;;;;N;;;;; 32E5;CIRCLED KATAKANA NI;So;0;L; 30CB;;;;N;;;;; 32E6;CIRCLED KATAKANA NU;So;0;L; 30CC;;;;N;;;;; 32E7;CIRCLED KATAKANA NE;So;0;L; 30CD;;;;N;;;;; 32E8;CIRCLED KATAKANA NO;So;0;L; 30CE;;;;N;;;;; 32E9;CIRCLED KATAKANA HA;So;0;L; 30CF;;;;N;;;;; 32EA;CIRCLED KATAKANA HI;So;0;L; 30D2;;;;N;;;;; 32EB;CIRCLED KATAKANA HU;So;0;L; 30D5;;;;N;;;;; 32EC;CIRCLED KATAKANA HE;So;0;L; 30D8;;;;N;;;;; 32ED;CIRCLED KATAKANA HO;So;0;L; 30DB;;;;N;;;;; 32EE;CIRCLED KATAKANA MA;So;0;L; 30DE;;;;N;;;;; 32EF;CIRCLED KATAKANA MI;So;0;L; 30DF;;;;N;;;;; 32F0;CIRCLED KATAKANA MU;So;0;L; 30E0;;;;N;;;;; 32F1;CIRCLED KATAKANA ME;So;0;L; 30E1;;;;N;;;;; 32F2;CIRCLED KATAKANA MO;So;0;L; 30E2;;;;N;;;;; 32F3;CIRCLED KATAKANA YA;So;0;L; 30E4;;;;N;;;;; 32F4;CIRCLED KATAKANA YU;So;0;L; 30E6;;;;N;;;;; 32F5;CIRCLED KATAKANA YO;So;0;L; 30E8;;;;N;;;;; 32F6;CIRCLED KATAKANA RA;So;0;L; 30E9;;;;N;;;;; 32F7;CIRCLED KATAKANA RI;So;0;L; 30EA;;;;N;;;;; 32F8;CIRCLED KATAKANA RU;So;0;L; 30EB;;;;N;;;;; 32F9;CIRCLED KATAKANA RE;So;0;L; 30EC;;;;N;;;;; 32FA;CIRCLED KATAKANA RO;So;0;L; 30ED;;;;N;;;;; 32FB;CIRCLED KATAKANA WA;So;0;L; 30EF;;;;N;;;;; 32FC;CIRCLED KATAKANA WI;So;0;L; 30F0;;;;N;;;;; 32FD;CIRCLED KATAKANA WE;So;0;L; 30F1;;;;N;;;;; 32FE;CIRCLED KATAKANA WO;So;0;L; 30F2;;;;N;;;;; 3300;SQUARE APAATO;So;0;L; 30A2 30D1 30FC 30C8;;;;N;SQUARED APAATO;;;; 3301;SQUARE ARUHUA;So;0;L; 30A2 30EB 30D5 30A1;;;;N;SQUARED ARUHUA;;;; 3302;SQUARE ANPEA;So;0;L; 30A2 30F3 30DA 30A2;;;;N;SQUARED ANPEA;;;; 3303;SQUARE AARU;So;0;L; 30A2 30FC 30EB;;;;N;SQUARED AARU;;;; 3304;SQUARE ININGU;So;0;L; 30A4 30CB 30F3 30B0;;;;N;SQUARED ININGU;;;; 3305;SQUARE INTI;So;0;L; 30A4 30F3 30C1;;;;N;SQUARED INTI;;;; 3306;SQUARE UON;So;0;L; 30A6 30A9 30F3;;;;N;SQUARED UON;;;; 3307;SQUARE ESUKUUDO;So;0;L; 30A8 30B9 30AF 30FC 30C9;;;;N;SQUARED ESUKUUDO;;;; 3308;SQUARE EEKAA;So;0;L; 30A8 30FC 30AB 30FC;;;;N;SQUARED EEKAA;;;; 3309;SQUARE ONSU;So;0;L; 30AA 30F3 30B9;;;;N;SQUARED ONSU;;;; 330A;SQUARE OOMU;So;0;L; 30AA 30FC 30E0;;;;N;SQUARED OOMU;;;; 330B;SQUARE KAIRI;So;0;L; 30AB 30A4 30EA;;;;N;SQUARED KAIRI;;;; 330C;SQUARE KARATTO;So;0;L; 30AB 30E9 30C3 30C8;;;;N;SQUARED KARATTO;;;; 330D;SQUARE KARORII;So;0;L; 30AB 30ED 30EA 30FC;;;;N;SQUARED KARORII;;;; 330E;SQUARE GARON;So;0;L; 30AC 30ED 30F3;;;;N;SQUARED GARON;;;; 330F;SQUARE GANMA;So;0;L; 30AC 30F3 30DE;;;;N;SQUARED GANMA;;;; 3310;SQUARE GIGA;So;0;L; 30AE 30AC;;;;N;SQUARED GIGA;;;; 3311;SQUARE GINII;So;0;L; 30AE 30CB 30FC;;;;N;SQUARED GINII;;;; 3312;SQUARE KYURII;So;0;L; 30AD 30E5 30EA 30FC;;;;N;SQUARED KYURII;;;; 3313;SQUARE GIRUDAA;So;0;L; 30AE 30EB 30C0 30FC;;;;N;SQUARED GIRUDAA;;;; 3314;SQUARE KIRO;So;0;L; 30AD 30ED;;;;N;SQUARED KIRO;;;; 3315;SQUARE KIROGURAMU;So;0;L; 30AD 30ED 30B0 30E9 30E0;;;;N;SQUARED KIROGURAMU;;;; 3316;SQUARE KIROMEETORU;So;0;L; 30AD 30ED 30E1 30FC 30C8 30EB;;;;N;SQUARED KIROMEETORU;;;; 3317;SQUARE KIROWATTO;So;0;L; 30AD 30ED 30EF 30C3 30C8;;;;N;SQUARED KIROWATTO;;;; 3318;SQUARE GURAMU;So;0;L; 30B0 30E9 30E0;;;;N;SQUARED GURAMU;;;; 3319;SQUARE GURAMUTON;So;0;L; 30B0 30E9 30E0 30C8 30F3;;;;N;SQUARED GURAMUTON;;;; 331A;SQUARE KURUZEIRO;So;0;L; 30AF 30EB 30BC 30A4 30ED;;;;N;SQUARED KURUZEIRO;;;; 331B;SQUARE KUROONE;So;0;L; 30AF 30ED 30FC 30CD;;;;N;SQUARED KUROONE;;;; 331C;SQUARE KEESU;So;0;L; 30B1 30FC 30B9;;;;N;SQUARED KEESU;;;; 331D;SQUARE KORUNA;So;0;L; 30B3 30EB 30CA;;;;N;SQUARED KORUNA;;;; 331E;SQUARE KOOPO;So;0;L; 30B3 30FC 30DD;;;;N;SQUARED KOOPO;;;; 331F;SQUARE SAIKURU;So;0;L; 30B5 30A4 30AF 30EB;;;;N;SQUARED SAIKURU;;;; 3320;SQUARE SANTIIMU;So;0;L; 30B5 30F3 30C1 30FC 30E0;;;;N;SQUARED SANTIIMU;;;; 3321;SQUARE SIRINGU;So;0;L; 30B7 30EA 30F3 30B0;;;;N;SQUARED SIRINGU;;;; 3322;SQUARE SENTI;So;0;L; 30BB 30F3 30C1;;;;N;SQUARED SENTI;;;; 3323;SQUARE SENTO;So;0;L; 30BB 30F3 30C8;;;;N;SQUARED SENTO;;;; 3324;SQUARE DAASU;So;0;L; 30C0 30FC 30B9;;;;N;SQUARED DAASU;;;; 3325;SQUARE DESI;So;0;L; 30C7 30B7;;;;N;SQUARED DESI;;;; 3326;SQUARE DORU;So;0;L; 30C9 30EB;;;;N;SQUARED DORU;;;; 3327;SQUARE TON;So;0;L; 30C8 30F3;;;;N;SQUARED TON;;;; 3328;SQUARE NANO;So;0;L; 30CA 30CE;;;;N;SQUARED NANO;;;; 3329;SQUARE NOTTO;So;0;L; 30CE 30C3 30C8;;;;N;SQUARED NOTTO;;;; 332A;SQUARE HAITU;So;0;L; 30CF 30A4 30C4;;;;N;SQUARED HAITU;;;; 332B;SQUARE PAASENTO;So;0;L; 30D1 30FC 30BB 30F3 30C8;;;;N;SQUARED PAASENTO;;;; 332C;SQUARE PAATU;So;0;L; 30D1 30FC 30C4;;;;N;SQUARED PAATU;;;; 332D;SQUARE BAARERU;So;0;L; 30D0 30FC 30EC 30EB;;;;N;SQUARED BAARERU;;;; 332E;SQUARE PIASUTORU;So;0;L; 30D4 30A2 30B9 30C8 30EB;;;;N;SQUARED PIASUTORU;;;; 332F;SQUARE PIKURU;So;0;L; 30D4 30AF 30EB;;;;N;SQUARED PIKURU;;;; 3330;SQUARE PIKO;So;0;L; 30D4 30B3;;;;N;SQUARED PIKO;;;; 3331;SQUARE BIRU;So;0;L; 30D3 30EB;;;;N;SQUARED BIRU;;;; 3332;SQUARE HUARADDO;So;0;L; 30D5 30A1 30E9 30C3 30C9;;;;N;SQUARED HUARADDO;;;; 3333;SQUARE HUIITO;So;0;L; 30D5 30A3 30FC 30C8;;;;N;SQUARED HUIITO;;;; 3334;SQUARE BUSSYERU;So;0;L; 30D6 30C3 30B7 30A7 30EB;;;;N;SQUARED BUSSYERU;;;; 3335;SQUARE HURAN;So;0;L; 30D5 30E9 30F3;;;;N;SQUARED HURAN;;;; 3336;SQUARE HEKUTAARU;So;0;L; 30D8 30AF 30BF 30FC 30EB;;;;N;SQUARED HEKUTAARU;;;; 3337;SQUARE PESO;So;0;L; 30DA 30BD;;;;N;SQUARED PESO;;;; 3338;SQUARE PENIHI;So;0;L; 30DA 30CB 30D2;;;;N;SQUARED PENIHI;;;; 3339;SQUARE HERUTU;So;0;L; 30D8 30EB 30C4;;;;N;SQUARED HERUTU;;;; 333A;SQUARE PENSU;So;0;L; 30DA 30F3 30B9;;;;N;SQUARED PENSU;;;; 333B;SQUARE PEEZI;So;0;L; 30DA 30FC 30B8;;;;N;SQUARED PEEZI;;;; 333C;SQUARE BEETA;So;0;L; 30D9 30FC 30BF;;;;N;SQUARED BEETA;;;; 333D;SQUARE POINTO;So;0;L; 30DD 30A4 30F3 30C8;;;;N;SQUARED POINTO;;;; 333E;SQUARE BORUTO;So;0;L; 30DC 30EB 30C8;;;;N;SQUARED BORUTO;;;; 333F;SQUARE HON;So;0;L; 30DB 30F3;;;;N;SQUARED HON;;;; 3340;SQUARE PONDO;So;0;L; 30DD 30F3 30C9;;;;N;SQUARED PONDO;;;; 3341;SQUARE HOORU;So;0;L; 30DB 30FC 30EB;;;;N;SQUARED HOORU;;;; 3342;SQUARE HOON;So;0;L; 30DB 30FC 30F3;;;;N;SQUARED HOON;;;; 3343;SQUARE MAIKURO;So;0;L; 30DE 30A4 30AF 30ED;;;;N;SQUARED MAIKURO;;;; 3344;SQUARE MAIRU;So;0;L; 30DE 30A4 30EB;;;;N;SQUARED MAIRU;;;; 3345;SQUARE MAHHA;So;0;L; 30DE 30C3 30CF;;;;N;SQUARED MAHHA;;;; 3346;SQUARE MARUKU;So;0;L; 30DE 30EB 30AF;;;;N;SQUARED MARUKU;;;; 3347;SQUARE MANSYON;So;0;L; 30DE 30F3 30B7 30E7 30F3;;;;N;SQUARED MANSYON;;;; 3348;SQUARE MIKURON;So;0;L; 30DF 30AF 30ED 30F3;;;;N;SQUARED MIKURON;;;; 3349;SQUARE MIRI;So;0;L; 30DF 30EA;;;;N;SQUARED MIRI;;;; 334A;SQUARE MIRIBAARU;So;0;L; 30DF 30EA 30D0 30FC 30EB;;;;N;SQUARED MIRIBAARU;;;; 334B;SQUARE MEGA;So;0;L; 30E1 30AC;;;;N;SQUARED MEGA;;;; 334C;SQUARE MEGATON;So;0;L; 30E1 30AC 30C8 30F3;;;;N;SQUARED MEGATON;;;; 334D;SQUARE MEETORU;So;0;L; 30E1 30FC 30C8 30EB;;;;N;SQUARED MEETORU;;;; 334E;SQUARE YAADO;So;0;L; 30E4 30FC 30C9;;;;N;SQUARED YAADO;;;; 334F;SQUARE YAARU;So;0;L; 30E4 30FC 30EB;;;;N;SQUARED YAARU;;;; 3350;SQUARE YUAN;So;0;L; 30E6 30A2 30F3;;;;N;SQUARED YUAN;;;; 3351;SQUARE RITTORU;So;0;L; 30EA 30C3 30C8 30EB;;;;N;SQUARED RITTORU;;;; 3352;SQUARE RIRA;So;0;L; 30EA 30E9;;;;N;SQUARED RIRA;;;; 3353;SQUARE RUPII;So;0;L; 30EB 30D4 30FC;;;;N;SQUARED RUPII;;;; 3354;SQUARE RUUBURU;So;0;L; 30EB 30FC 30D6 30EB;;;;N;SQUARED RUUBURU;;;; 3355;SQUARE REMU;So;0;L; 30EC 30E0;;;;N;SQUARED REMU;;;; 3356;SQUARE RENTOGEN;So;0;L; 30EC 30F3 30C8 30B2 30F3;;;;N;SQUARED RENTOGEN;;;; 3357;SQUARE WATTO;So;0;L; 30EF 30C3 30C8;;;;N;SQUARED WATTO;;;; 3358;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR ZERO;So;0;L; 0030 70B9;;;;N;;;;; 3359;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR ONE;So;0;L; 0031 70B9;;;;N;;;;; 335A;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWO;So;0;L; 0032 70B9;;;;N;;;;; 335B;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR THREE;So;0;L; 0033 70B9;;;;N;;;;; 335C;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FOUR;So;0;L; 0034 70B9;;;;N;;;;; 335D;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FIVE;So;0;L; 0035 70B9;;;;N;;;;; 335E;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SIX;So;0;L; 0036 70B9;;;;N;;;;; 335F;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SEVEN;So;0;L; 0037 70B9;;;;N;;;;; 3360;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR EIGHT;So;0;L; 0038 70B9;;;;N;;;;; 3361;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR NINE;So;0;L; 0039 70B9;;;;N;;;;; 3362;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TEN;So;0;L; 0031 0030 70B9;;;;N;;;;; 3363;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR ELEVEN;So;0;L; 0031 0031 70B9;;;;N;;;;; 3364;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWELVE;So;0;L; 0031 0032 70B9;;;;N;;;;; 3365;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR THIRTEEN;So;0;L; 0031 0033 70B9;;;;N;;;;; 3366;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FOURTEEN;So;0;L; 0031 0034 70B9;;;;N;;;;; 3367;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FIFTEEN;So;0;L; 0031 0035 70B9;;;;N;;;;; 3368;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SIXTEEN;So;0;L; 0031 0036 70B9;;;;N;;;;; 3369;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SEVENTEEN;So;0;L; 0031 0037 70B9;;;;N;;;;; 336A;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR EIGHTEEN;So;0;L; 0031 0038 70B9;;;;N;;;;; 336B;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR NINETEEN;So;0;L; 0031 0039 70B9;;;;N;;;;; 336C;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY;So;0;L; 0032 0030 70B9;;;;N;;;;; 336D;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-ONE;So;0;L; 0032 0031 70B9;;;;N;;;;; 336E;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-TWO;So;0;L; 0032 0032 70B9;;;;N;;;;; 336F;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-THREE;So;0;L; 0032 0033 70B9;;;;N;;;;; 3370;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-FOUR;So;0;L; 0032 0034 70B9;;;;N;;;;; 3371;SQUARE HPA;So;0;L; 0068 0050 0061;;;;N;;;;; 3372;SQUARE DA;So;0;L; 0064 0061;;;;N;;;;; 3373;SQUARE AU;So;0;L; 0041 0055;;;;N;;;;; 3374;SQUARE BAR;So;0;L; 0062 0061 0072;;;;N;;;;; 3375;SQUARE OV;So;0;L; 006F 0056;;;;N;;;;; 3376;SQUARE PC;So;0;L; 0070 0063;;;;N;;;;; 337B;SQUARE ERA NAME HEISEI;So;0;L; 5E73 6210;;;;N;SQUARED TWO IDEOGRAPHS ERA NAME HEISEI;;;; 337C;SQUARE ERA NAME SYOUWA;So;0;L; 662D 548C;;;;N;SQUARED TWO IDEOGRAPHS ERA NAME SYOUWA;;;; 337D;SQUARE ERA NAME TAISYOU;So;0;L; 5927 6B63;;;;N;SQUARED TWO IDEOGRAPHS ERA NAME TAISYOU;;;; 337E;SQUARE ERA NAME MEIZI;So;0;L; 660E 6CBB;;;;N;SQUARED TWO IDEOGRAPHS ERA NAME MEIZI;;;; 337F;SQUARE CORPORATION;So;0;L; 682A 5F0F 4F1A 793E;;;;N;SQUARED FOUR IDEOGRAPHS CORPORATION;;;; 3380;SQUARE PA AMPS;So;0;L; 0070 0041;;;;N;SQUARED PA AMPS;;;; 3381;SQUARE NA;So;0;L; 006E 0041;;;;N;SQUARED NA;;;; 3382;SQUARE MU A;So;0;L; 03BC 0041;;;;N;SQUARED MU A;;;; 3383;SQUARE MA;So;0;L; 006D 0041;;;;N;SQUARED MA;;;; 3384;SQUARE KA;So;0;L; 006B 0041;;;;N;SQUARED KA;;;; 3385;SQUARE KB;So;0;L; 004B 0042;;;;N;SQUARED KB;;;; 3386;SQUARE MB;So;0;L; 004D 0042;;;;N;SQUARED MB;;;; 3387;SQUARE GB;So;0;L; 0047 0042;;;;N;SQUARED GB;;;; 3388;SQUARE CAL;So;0;L; 0063 0061 006C;;;;N;SQUARED CAL;;;; 3389;SQUARE KCAL;So;0;L; 006B 0063 0061 006C;;;;N;SQUARED KCAL;;;; 338A;SQUARE PF;So;0;L; 0070 0046;;;;N;SQUARED PF;;;; 338B;SQUARE NF;So;0;L; 006E 0046;;;;N;SQUARED NF;;;; 338C;SQUARE MU F;So;0;L; 03BC 0046;;;;N;SQUARED MU F;;;; 338D;SQUARE MU G;So;0;L; 03BC 0067;;;;N;SQUARED MU G;;;; 338E;SQUARE MG;So;0;L; 006D 0067;;;;N;SQUARED MG;;;; 338F;SQUARE KG;So;0;L; 006B 0067;;;;N;SQUARED KG;;;; 3390;SQUARE HZ;So;0;L; 0048 007A;;;;N;SQUARED HZ;;;; 3391;SQUARE KHZ;So;0;L; 006B 0048 007A;;;;N;SQUARED KHZ;;;; 3392;SQUARE MHZ;So;0;L; 004D 0048 007A;;;;N;SQUARED MHZ;;;; 3393;SQUARE GHZ;So;0;L; 0047 0048 007A;;;;N;SQUARED GHZ;;;; 3394;SQUARE THZ;So;0;L; 0054 0048 007A;;;;N;SQUARED THZ;;;; 3395;SQUARE MU L;So;0;L; 03BC 2113;;;;N;SQUARED MU L;;;; 3396;SQUARE ML;So;0;L; 006D 2113;;;;N;SQUARED ML;;;; 3397;SQUARE DL;So;0;L; 0064 2113;;;;N;SQUARED DL;;;; 3398;SQUARE KL;So;0;L; 006B 2113;;;;N;SQUARED KL;;;; 3399;SQUARE FM;So;0;L; 0066 006D;;;;N;SQUARED FM;;;; 339A;SQUARE NM;So;0;L; 006E 006D;;;;N;SQUARED NM;;;; 339B;SQUARE MU M;So;0;L; 03BC 006D;;;;N;SQUARED MU M;;;; 339C;SQUARE MM;So;0;L; 006D 006D;;;;N;SQUARED MM;;;; 339D;SQUARE CM;So;0;L; 0063 006D;;;;N;SQUARED CM;;;; 339E;SQUARE KM;So;0;L; 006B 006D;;;;N;SQUARED KM;;;; 339F;SQUARE MM SQUARED;So;0;L; 006D 006D 00B2;;;;N;SQUARED MM SQUARED;;;; 33A0;SQUARE CM SQUARED;So;0;L; 0063 006D 00B2;;;;N;SQUARED CM SQUARED;;;; 33A1;SQUARE M SQUARED;So;0;L; 006D 00B2;;;;N;SQUARED M SQUARED;;;; 33A2;SQUARE KM SQUARED;So;0;L; 006B 006D 00B2;;;;N;SQUARED KM SQUARED;;;; 33A3;SQUARE MM CUBED;So;0;L; 006D 006D 00B3;;;;N;SQUARED MM CUBED;;;; 33A4;SQUARE CM CUBED;So;0;L; 0063 006D 00B3;;;;N;SQUARED CM CUBED;;;; 33A5;SQUARE M CUBED;So;0;L; 006D 00B3;;;;N;SQUARED M CUBED;;;; 33A6;SQUARE KM CUBED;So;0;L; 006B 006D 00B3;;;;N;SQUARED KM CUBED;;;; 33A7;SQUARE M OVER S;So;0;L; 006D 2215 0073;;;;N;SQUARED M OVER S;;;; 33A8;SQUARE M OVER S SQUARED;So;0;L; 006D 2215 0073 00B2;;;;N;SQUARED M OVER S SQUARED;;;; 33A9;SQUARE PA;So;0;L; 0050 0061;;;;N;SQUARED PA;;;; 33AA;SQUARE KPA;So;0;L; 006B 0050 0061;;;;N;SQUARED KPA;;;; 33AB;SQUARE MPA;So;0;L; 004D 0050 0061;;;;N;SQUARED MPA;;;; 33AC;SQUARE GPA;So;0;L; 0047 0050 0061;;;;N;SQUARED GPA;;;; 33AD;SQUARE RAD;So;0;L; 0072 0061 0064;;;;N;SQUARED RAD;;;; 33AE;SQUARE RAD OVER S;So;0;L; 0072 0061 0064 2215 0073;;;;N;SQUARED RAD OVER S;;;; 33AF;SQUARE RAD OVER S SQUARED;So;0;L; 0072 0061 0064 2215 0073 00B2;;;;N;SQUARED RAD OVER S SQUARED;;;; 33B0;SQUARE PS;So;0;L; 0070 0073;;;;N;SQUARED PS;;;; 33B1;SQUARE NS;So;0;L; 006E 0073;;;;N;SQUARED NS;;;; 33B2;SQUARE MU S;So;0;L; 03BC 0073;;;;N;SQUARED MU S;;;; 33B3;SQUARE MS;So;0;L; 006D 0073;;;;N;SQUARED MS;;;; 33B4;SQUARE PV;So;0;L; 0070 0056;;;;N;SQUARED PV;;;; 33B5;SQUARE NV;So;0;L; 006E 0056;;;;N;SQUARED NV;;;; 33B6;SQUARE MU V;So;0;L; 03BC 0056;;;;N;SQUARED MU V;;;; 33B7;SQUARE MV;So;0;L; 006D 0056;;;;N;SQUARED MV;;;; 33B8;SQUARE KV;So;0;L; 006B 0056;;;;N;SQUARED KV;;;; 33B9;SQUARE MV MEGA;So;0;L; 004D 0056;;;;N;SQUARED MV MEGA;;;; 33BA;SQUARE PW;So;0;L; 0070 0057;;;;N;SQUARED PW;;;; 33BB;SQUARE NW;So;0;L; 006E 0057;;;;N;SQUARED NW;;;; 33BC;SQUARE MU W;So;0;L; 03BC 0057;;;;N;SQUARED MU W;;;; 33BD;SQUARE MW;So;0;L; 006D 0057;;;;N;SQUARED MW;;;; 33BE;SQUARE KW;So;0;L; 006B 0057;;;;N;SQUARED KW;;;; 33BF;SQUARE MW MEGA;So;0;L; 004D 0057;;;;N;SQUARED MW MEGA;;;; 33C0;SQUARE K OHM;So;0;L; 006B 03A9;;;;N;SQUARED K OHM;;;; 33C1;SQUARE M OHM;So;0;L; 004D 03A9;;;;N;SQUARED M OHM;;;; 33C2;SQUARE AM;So;0;L; 0061 002E 006D 002E;;;;N;SQUARED AM;;;; 33C3;SQUARE BQ;So;0;L; 0042 0071;;;;N;SQUARED BQ;;;; 33C4;SQUARE CC;So;0;L; 0063 0063;;;;N;SQUARED CC;;;; 33C5;SQUARE CD;So;0;L; 0063 0064;;;;N;SQUARED CD;;;; 33C6;SQUARE C OVER KG;So;0;L; 0043 2215 006B 0067;;;;N;SQUARED C OVER KG;;;; 33C7;SQUARE CO;So;0;L; 0043 006F 002E;;;;N;SQUARED CO;;;; 33C8;SQUARE DB;So;0;L; 0064 0042;;;;N;SQUARED DB;;;; 33C9;SQUARE GY;So;0;L; 0047 0079;;;;N;SQUARED GY;;;; 33CA;SQUARE HA;So;0;L; 0068 0061;;;;N;SQUARED HA;;;; 33CB;SQUARE HP;So;0;L; 0048 0050;;;;N;SQUARED HP;;;; 33CC;SQUARE IN;So;0;L; 0069 006E;;;;N;SQUARED IN;;;; 33CD;SQUARE KK;So;0;L; 004B 004B;;;;N;SQUARED KK;;;; 33CE;SQUARE KM CAPITAL;So;0;L; 004B 004D;;;;N;SQUARED KM CAPITAL;;;; 33CF;SQUARE KT;So;0;L; 006B 0074;;;;N;SQUARED KT;;;; 33D0;SQUARE LM;So;0;L; 006C 006D;;;;N;SQUARED LM;;;; 33D1;SQUARE LN;So;0;L; 006C 006E;;;;N;SQUARED LN;;;; 33D2;SQUARE LOG;So;0;L; 006C 006F 0067;;;;N;SQUARED LOG;;;; 33D3;SQUARE LX;So;0;L; 006C 0078;;;;N;SQUARED LX;;;; 33D4;SQUARE MB SMALL;So;0;L; 006D 0062;;;;N;SQUARED MB SMALL;;;; 33D5;SQUARE MIL;So;0;L; 006D 0069 006C;;;;N;SQUARED MIL;;;; 33D6;SQUARE MOL;So;0;L; 006D 006F 006C;;;;N;SQUARED MOL;;;; 33D7;SQUARE PH;So;0;L; 0050 0048;;;;N;SQUARED PH;;;; 33D8;SQUARE PM;So;0;L; 0070 002E 006D 002E;;;;N;SQUARED PM;;;; 33D9;SQUARE PPM;So;0;L; 0050 0050 004D;;;;N;SQUARED PPM;;;; 33DA;SQUARE PR;So;0;L; 0050 0052;;;;N;SQUARED PR;;;; 33DB;SQUARE SR;So;0;L; 0073 0072;;;;N;SQUARED SR;;;; 33DC;SQUARE SV;So;0;L; 0053 0076;;;;N;SQUARED SV;;;; 33DD;SQUARE WB;So;0;L; 0057 0062;;;;N;SQUARED WB;;;; 33E0;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY ONE;So;0;L; 0031 65E5;;;;N;;;;; 33E1;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWO;So;0;L; 0032 65E5;;;;N;;;;; 33E2;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THREE;So;0;L; 0033 65E5;;;;N;;;;; 33E3;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FOUR;So;0;L; 0034 65E5;;;;N;;;;; 33E4;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FIVE;So;0;L; 0035 65E5;;;;N;;;;; 33E5;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SIX;So;0;L; 0036 65E5;;;;N;;;;; 33E6;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SEVEN;So;0;L; 0037 65E5;;;;N;;;;; 33E7;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY EIGHT;So;0;L; 0038 65E5;;;;N;;;;; 33E8;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY NINE;So;0;L; 0039 65E5;;;;N;;;;; 33E9;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TEN;So;0;L; 0031 0030 65E5;;;;N;;;;; 33EA;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY ELEVEN;So;0;L; 0031 0031 65E5;;;;N;;;;; 33EB;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWELVE;So;0;L; 0031 0032 65E5;;;;N;;;;; 33EC;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTEEN;So;0;L; 0031 0033 65E5;;;;N;;;;; 33ED;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FOURTEEN;So;0;L; 0031 0034 65E5;;;;N;;;;; 33EE;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FIFTEEN;So;0;L; 0031 0035 65E5;;;;N;;;;; 33EF;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SIXTEEN;So;0;L; 0031 0036 65E5;;;;N;;;;; 33F0;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SEVENTEEN;So;0;L; 0031 0037 65E5;;;;N;;;;; 33F1;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY EIGHTEEN;So;0;L; 0031 0038 65E5;;;;N;;;;; 33F2;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY NINETEEN;So;0;L; 0031 0039 65E5;;;;N;;;;; 33F3;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY;So;0;L; 0032 0030 65E5;;;;N;;;;; 33F4;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-ONE;So;0;L; 0032 0031 65E5;;;;N;;;;; 33F5;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-TWO;So;0;L; 0032 0032 65E5;;;;N;;;;; 33F6;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-THREE;So;0;L; 0032 0033 65E5;;;;N;;;;; 33F7;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-FOUR;So;0;L; 0032 0034 65E5;;;;N;;;;; 33F8;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-FIVE;So;0;L; 0032 0035 65E5;;;;N;;;;; 33F9;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-SIX;So;0;L; 0032 0036 65E5;;;;N;;;;; 33FA;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-SEVEN;So;0;L; 0032 0037 65E5;;;;N;;;;; 33FB;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-EIGHT;So;0;L; 0032 0038 65E5;;;;N;;;;; 33FC;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-NINE;So;0;L; 0032 0039 65E5;;;;N;;;;; 33FD;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTY;So;0;L; 0033 0030 65E5;;;;N;;;;; 33FE;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTY-ONE;So;0;L; 0033 0031 65E5;;;;N;;;;; 3400;;Lo;0;L;;;;;N;;;;; 4DB5;;Lo;0;L;;;;;N;;;;; 4E00;;Lo;0;L;;;;;N;;;;; 9FA5;;Lo;0;L;;;;;N;;;;; A000;YI SYLLABLE IT;Lo;0;L;;;;;N;;;;; A001;YI SYLLABLE IX;Lo;0;L;;;;;N;;;;; A002;YI SYLLABLE I;Lo;0;L;;;;;N;;;;; A003;YI SYLLABLE IP;Lo;0;L;;;;;N;;;;; A004;YI SYLLABLE IET;Lo;0;L;;;;;N;;;;; A005;YI SYLLABLE IEX;Lo;0;L;;;;;N;;;;; A006;YI SYLLABLE IE;Lo;0;L;;;;;N;;;;; A007;YI SYLLABLE IEP;Lo;0;L;;;;;N;;;;; A008;YI SYLLABLE AT;Lo;0;L;;;;;N;;;;; A009;YI SYLLABLE AX;Lo;0;L;;;;;N;;;;; A00A;YI SYLLABLE A;Lo;0;L;;;;;N;;;;; A00B;YI SYLLABLE AP;Lo;0;L;;;;;N;;;;; A00C;YI SYLLABLE UOX;Lo;0;L;;;;;N;;;;; A00D;YI SYLLABLE UO;Lo;0;L;;;;;N;;;;; A00E;YI SYLLABLE UOP;Lo;0;L;;;;;N;;;;; A00F;YI SYLLABLE OT;Lo;0;L;;;;;N;;;;; A010;YI SYLLABLE OX;Lo;0;L;;;;;N;;;;; A011;YI SYLLABLE O;Lo;0;L;;;;;N;;;;; A012;YI SYLLABLE OP;Lo;0;L;;;;;N;;;;; A013;YI SYLLABLE EX;Lo;0;L;;;;;N;;;;; A014;YI SYLLABLE E;Lo;0;L;;;;;N;;;;; A015;YI SYLLABLE WU;Lo;0;L;;;;;N;;;;; A016;YI SYLLABLE BIT;Lo;0;L;;;;;N;;;;; A017;YI SYLLABLE BIX;Lo;0;L;;;;;N;;;;; A018;YI SYLLABLE BI;Lo;0;L;;;;;N;;;;; A019;YI SYLLABLE BIP;Lo;0;L;;;;;N;;;;; A01A;YI SYLLABLE BIET;Lo;0;L;;;;;N;;;;; A01B;YI SYLLABLE BIEX;Lo;0;L;;;;;N;;;;; A01C;YI SYLLABLE BIE;Lo;0;L;;;;;N;;;;; A01D;YI SYLLABLE BIEP;Lo;0;L;;;;;N;;;;; A01E;YI SYLLABLE BAT;Lo;0;L;;;;;N;;;;; A01F;YI SYLLABLE BAX;Lo;0;L;;;;;N;;;;; A020;YI SYLLABLE BA;Lo;0;L;;;;;N;;;;; A021;YI SYLLABLE BAP;Lo;0;L;;;;;N;;;;; A022;YI SYLLABLE BUOX;Lo;0;L;;;;;N;;;;; A023;YI SYLLABLE BUO;Lo;0;L;;;;;N;;;;; A024;YI SYLLABLE BUOP;Lo;0;L;;;;;N;;;;; A025;YI SYLLABLE BOT;Lo;0;L;;;;;N;;;;; A026;YI SYLLABLE BOX;Lo;0;L;;;;;N;;;;; A027;YI SYLLABLE BO;Lo;0;L;;;;;N;;;;; A028;YI SYLLABLE BOP;Lo;0;L;;;;;N;;;;; A029;YI SYLLABLE BEX;Lo;0;L;;;;;N;;;;; A02A;YI SYLLABLE BE;Lo;0;L;;;;;N;;;;; A02B;YI SYLLABLE BEP;Lo;0;L;;;;;N;;;;; A02C;YI SYLLABLE BUT;Lo;0;L;;;;;N;;;;; A02D;YI SYLLABLE BUX;Lo;0;L;;;;;N;;;;; A02E;YI SYLLABLE BU;Lo;0;L;;;;;N;;;;; A02F;YI SYLLABLE BUP;Lo;0;L;;;;;N;;;;; A030;YI SYLLABLE BURX;Lo;0;L;;;;;N;;;;; A031;YI SYLLABLE BUR;Lo;0;L;;;;;N;;;;; A032;YI SYLLABLE BYT;Lo;0;L;;;;;N;;;;; A033;YI SYLLABLE BYX;Lo;0;L;;;;;N;;;;; A034;YI SYLLABLE BY;Lo;0;L;;;;;N;;;;; A035;YI SYLLABLE BYP;Lo;0;L;;;;;N;;;;; A036;YI SYLLABLE BYRX;Lo;0;L;;;;;N;;;;; A037;YI SYLLABLE BYR;Lo;0;L;;;;;N;;;;; A038;YI SYLLABLE PIT;Lo;0;L;;;;;N;;;;; A039;YI SYLLABLE PIX;Lo;0;L;;;;;N;;;;; A03A;YI SYLLABLE PI;Lo;0;L;;;;;N;;;;; A03B;YI SYLLABLE PIP;Lo;0;L;;;;;N;;;;; A03C;YI SYLLABLE PIEX;Lo;0;L;;;;;N;;;;; A03D;YI SYLLABLE PIE;Lo;0;L;;;;;N;;;;; A03E;YI SYLLABLE PIEP;Lo;0;L;;;;;N;;;;; A03F;YI SYLLABLE PAT;Lo;0;L;;;;;N;;;;; A040;YI SYLLABLE PAX;Lo;0;L;;;;;N;;;;; A041;YI SYLLABLE PA;Lo;0;L;;;;;N;;;;; A042;YI SYLLABLE PAP;Lo;0;L;;;;;N;;;;; A043;YI SYLLABLE PUOX;Lo;0;L;;;;;N;;;;; A044;YI SYLLABLE PUO;Lo;0;L;;;;;N;;;;; A045;YI SYLLABLE PUOP;Lo;0;L;;;;;N;;;;; A046;YI SYLLABLE POT;Lo;0;L;;;;;N;;;;; A047;YI SYLLABLE POX;Lo;0;L;;;;;N;;;;; A048;YI SYLLABLE PO;Lo;0;L;;;;;N;;;;; A049;YI SYLLABLE POP;Lo;0;L;;;;;N;;;;; A04A;YI SYLLABLE PUT;Lo;0;L;;;;;N;;;;; A04B;YI SYLLABLE PUX;Lo;0;L;;;;;N;;;;; A04C;YI SYLLABLE PU;Lo;0;L;;;;;N;;;;; A04D;YI SYLLABLE PUP;Lo;0;L;;;;;N;;;;; A04E;YI SYLLABLE PURX;Lo;0;L;;;;;N;;;;; A04F;YI SYLLABLE PUR;Lo;0;L;;;;;N;;;;; A050;YI SYLLABLE PYT;Lo;0;L;;;;;N;;;;; A051;YI SYLLABLE PYX;Lo;0;L;;;;;N;;;;; A052;YI SYLLABLE PY;Lo;0;L;;;;;N;;;;; A053;YI SYLLABLE PYP;Lo;0;L;;;;;N;;;;; A054;YI SYLLABLE PYRX;Lo;0;L;;;;;N;;;;; A055;YI SYLLABLE PYR;Lo;0;L;;;;;N;;;;; A056;YI SYLLABLE BBIT;Lo;0;L;;;;;N;;;;; A057;YI SYLLABLE BBIX;Lo;0;L;;;;;N;;;;; A058;YI SYLLABLE BBI;Lo;0;L;;;;;N;;;;; A059;YI SYLLABLE BBIP;Lo;0;L;;;;;N;;;;; A05A;YI SYLLABLE BBIET;Lo;0;L;;;;;N;;;;; A05B;YI SYLLABLE BBIEX;Lo;0;L;;;;;N;;;;; A05C;YI SYLLABLE BBIE;Lo;0;L;;;;;N;;;;; A05D;YI SYLLABLE BBIEP;Lo;0;L;;;;;N;;;;; A05E;YI SYLLABLE BBAT;Lo;0;L;;;;;N;;;;; A05F;YI SYLLABLE BBAX;Lo;0;L;;;;;N;;;;; A060;YI SYLLABLE BBA;Lo;0;L;;;;;N;;;;; A061;YI SYLLABLE BBAP;Lo;0;L;;;;;N;;;;; A062;YI SYLLABLE BBUOX;Lo;0;L;;;;;N;;;;; A063;YI SYLLABLE BBUO;Lo;0;L;;;;;N;;;;; A064;YI SYLLABLE BBUOP;Lo;0;L;;;;;N;;;;; A065;YI SYLLABLE BBOT;Lo;0;L;;;;;N;;;;; A066;YI SYLLABLE BBOX;Lo;0;L;;;;;N;;;;; A067;YI SYLLABLE BBO;Lo;0;L;;;;;N;;;;; A068;YI SYLLABLE BBOP;Lo;0;L;;;;;N;;;;; A069;YI SYLLABLE BBEX;Lo;0;L;;;;;N;;;;; A06A;YI SYLLABLE BBE;Lo;0;L;;;;;N;;;;; A06B;YI SYLLABLE BBEP;Lo;0;L;;;;;N;;;;; A06C;YI SYLLABLE BBUT;Lo;0;L;;;;;N;;;;; A06D;YI SYLLABLE BBUX;Lo;0;L;;;;;N;;;;; A06E;YI SYLLABLE BBU;Lo;0;L;;;;;N;;;;; A06F;YI SYLLABLE BBUP;Lo;0;L;;;;;N;;;;; A070;YI SYLLABLE BBURX;Lo;0;L;;;;;N;;;;; A071;YI SYLLABLE BBUR;Lo;0;L;;;;;N;;;;; A072;YI SYLLABLE BBYT;Lo;0;L;;;;;N;;;;; A073;YI SYLLABLE BBYX;Lo;0;L;;;;;N;;;;; A074;YI SYLLABLE BBY;Lo;0;L;;;;;N;;;;; A075;YI SYLLABLE BBYP;Lo;0;L;;;;;N;;;;; A076;YI SYLLABLE NBIT;Lo;0;L;;;;;N;;;;; A077;YI SYLLABLE NBIX;Lo;0;L;;;;;N;;;;; A078;YI SYLLABLE NBI;Lo;0;L;;;;;N;;;;; A079;YI SYLLABLE NBIP;Lo;0;L;;;;;N;;;;; A07A;YI SYLLABLE NBIEX;Lo;0;L;;;;;N;;;;; A07B;YI SYLLABLE NBIE;Lo;0;L;;;;;N;;;;; A07C;YI SYLLABLE NBIEP;Lo;0;L;;;;;N;;;;; A07D;YI SYLLABLE NBAT;Lo;0;L;;;;;N;;;;; A07E;YI SYLLABLE NBAX;Lo;0;L;;;;;N;;;;; A07F;YI SYLLABLE NBA;Lo;0;L;;;;;N;;;;; A080;YI SYLLABLE NBAP;Lo;0;L;;;;;N;;;;; A081;YI SYLLABLE NBOT;Lo;0;L;;;;;N;;;;; A082;YI SYLLABLE NBOX;Lo;0;L;;;;;N;;;;; A083;YI SYLLABLE NBO;Lo;0;L;;;;;N;;;;; A084;YI SYLLABLE NBOP;Lo;0;L;;;;;N;;;;; A085;YI SYLLABLE NBUT;Lo;0;L;;;;;N;;;;; A086;YI SYLLABLE NBUX;Lo;0;L;;;;;N;;;;; A087;YI SYLLABLE NBU;Lo;0;L;;;;;N;;;;; A088;YI SYLLABLE NBUP;Lo;0;L;;;;;N;;;;; A089;YI SYLLABLE NBURX;Lo;0;L;;;;;N;;;;; A08A;YI SYLLABLE NBUR;Lo;0;L;;;;;N;;;;; A08B;YI SYLLABLE NBYT;Lo;0;L;;;;;N;;;;; A08C;YI SYLLABLE NBYX;Lo;0;L;;;;;N;;;;; A08D;YI SYLLABLE NBY;Lo;0;L;;;;;N;;;;; A08E;YI SYLLABLE NBYP;Lo;0;L;;;;;N;;;;; A08F;YI SYLLABLE NBYRX;Lo;0;L;;;;;N;;;;; A090;YI SYLLABLE NBYR;Lo;0;L;;;;;N;;;;; A091;YI SYLLABLE HMIT;Lo;0;L;;;;;N;;;;; A092;YI SYLLABLE HMIX;Lo;0;L;;;;;N;;;;; A093;YI SYLLABLE HMI;Lo;0;L;;;;;N;;;;; A094;YI SYLLABLE HMIP;Lo;0;L;;;;;N;;;;; A095;YI SYLLABLE HMIEX;Lo;0;L;;;;;N;;;;; A096;YI SYLLABLE HMIE;Lo;0;L;;;;;N;;;;; A097;YI SYLLABLE HMIEP;Lo;0;L;;;;;N;;;;; A098;YI SYLLABLE HMAT;Lo;0;L;;;;;N;;;;; A099;YI SYLLABLE HMAX;Lo;0;L;;;;;N;;;;; A09A;YI SYLLABLE HMA;Lo;0;L;;;;;N;;;;; A09B;YI SYLLABLE HMAP;Lo;0;L;;;;;N;;;;; A09C;YI SYLLABLE HMUOX;Lo;0;L;;;;;N;;;;; A09D;YI SYLLABLE HMUO;Lo;0;L;;;;;N;;;;; A09E;YI SYLLABLE HMUOP;Lo;0;L;;;;;N;;;;; A09F;YI SYLLABLE HMOT;Lo;0;L;;;;;N;;;;; A0A0;YI SYLLABLE HMOX;Lo;0;L;;;;;N;;;;; A0A1;YI SYLLABLE HMO;Lo;0;L;;;;;N;;;;; A0A2;YI SYLLABLE HMOP;Lo;0;L;;;;;N;;;;; A0A3;YI SYLLABLE HMUT;Lo;0;L;;;;;N;;;;; A0A4;YI SYLLABLE HMUX;Lo;0;L;;;;;N;;;;; A0A5;YI SYLLABLE HMU;Lo;0;L;;;;;N;;;;; A0A6;YI SYLLABLE HMUP;Lo;0;L;;;;;N;;;;; A0A7;YI SYLLABLE HMURX;Lo;0;L;;;;;N;;;;; A0A8;YI SYLLABLE HMUR;Lo;0;L;;;;;N;;;;; A0A9;YI SYLLABLE HMYX;Lo;0;L;;;;;N;;;;; A0AA;YI SYLLABLE HMY;Lo;0;L;;;;;N;;;;; A0AB;YI SYLLABLE HMYP;Lo;0;L;;;;;N;;;;; A0AC;YI SYLLABLE HMYRX;Lo;0;L;;;;;N;;;;; A0AD;YI SYLLABLE HMYR;Lo;0;L;;;;;N;;;;; A0AE;YI SYLLABLE MIT;Lo;0;L;;;;;N;;;;; A0AF;YI SYLLABLE MIX;Lo;0;L;;;;;N;;;;; A0B0;YI SYLLABLE MI;Lo;0;L;;;;;N;;;;; A0B1;YI SYLLABLE MIP;Lo;0;L;;;;;N;;;;; A0B2;YI SYLLABLE MIEX;Lo;0;L;;;;;N;;;;; A0B3;YI SYLLABLE MIE;Lo;0;L;;;;;N;;;;; A0B4;YI SYLLABLE MIEP;Lo;0;L;;;;;N;;;;; A0B5;YI SYLLABLE MAT;Lo;0;L;;;;;N;;;;; A0B6;YI SYLLABLE MAX;Lo;0;L;;;;;N;;;;; A0B7;YI SYLLABLE MA;Lo;0;L;;;;;N;;;;; A0B8;YI SYLLABLE MAP;Lo;0;L;;;;;N;;;;; A0B9;YI SYLLABLE MUOT;Lo;0;L;;;;;N;;;;; A0BA;YI SYLLABLE MUOX;Lo;0;L;;;;;N;;;;; A0BB;YI SYLLABLE MUO;Lo;0;L;;;;;N;;;;; A0BC;YI SYLLABLE MUOP;Lo;0;L;;;;;N;;;;; A0BD;YI SYLLABLE MOT;Lo;0;L;;;;;N;;;;; A0BE;YI SYLLABLE MOX;Lo;0;L;;;;;N;;;;; A0BF;YI SYLLABLE MO;Lo;0;L;;;;;N;;;;; A0C0;YI SYLLABLE MOP;Lo;0;L;;;;;N;;;;; A0C1;YI SYLLABLE MEX;Lo;0;L;;;;;N;;;;; A0C2;YI SYLLABLE ME;Lo;0;L;;;;;N;;;;; A0C3;YI SYLLABLE MUT;Lo;0;L;;;;;N;;;;; A0C4;YI SYLLABLE MUX;Lo;0;L;;;;;N;;;;; A0C5;YI SYLLABLE MU;Lo;0;L;;;;;N;;;;; A0C6;YI SYLLABLE MUP;Lo;0;L;;;;;N;;;;; A0C7;YI SYLLABLE MURX;Lo;0;L;;;;;N;;;;; A0C8;YI SYLLABLE MUR;Lo;0;L;;;;;N;;;;; A0C9;YI SYLLABLE MYT;Lo;0;L;;;;;N;;;;; A0CA;YI SYLLABLE MYX;Lo;0;L;;;;;N;;;;; A0CB;YI SYLLABLE MY;Lo;0;L;;;;;N;;;;; A0CC;YI SYLLABLE MYP;Lo;0;L;;;;;N;;;;; A0CD;YI SYLLABLE FIT;Lo;0;L;;;;;N;;;;; A0CE;YI SYLLABLE FIX;Lo;0;L;;;;;N;;;;; A0CF;YI SYLLABLE FI;Lo;0;L;;;;;N;;;;; A0D0;YI SYLLABLE FIP;Lo;0;L;;;;;N;;;;; A0D1;YI SYLLABLE FAT;Lo;0;L;;;;;N;;;;; A0D2;YI SYLLABLE FAX;Lo;0;L;;;;;N;;;;; A0D3;YI SYLLABLE FA;Lo;0;L;;;;;N;;;;; A0D4;YI SYLLABLE FAP;Lo;0;L;;;;;N;;;;; A0D5;YI SYLLABLE FOX;Lo;0;L;;;;;N;;;;; A0D6;YI SYLLABLE FO;Lo;0;L;;;;;N;;;;; A0D7;YI SYLLABLE FOP;Lo;0;L;;;;;N;;;;; A0D8;YI SYLLABLE FUT;Lo;0;L;;;;;N;;;;; A0D9;YI SYLLABLE FUX;Lo;0;L;;;;;N;;;;; A0DA;YI SYLLABLE FU;Lo;0;L;;;;;N;;;;; A0DB;YI SYLLABLE FUP;Lo;0;L;;;;;N;;;;; A0DC;YI SYLLABLE FURX;Lo;0;L;;;;;N;;;;; A0DD;YI SYLLABLE FUR;Lo;0;L;;;;;N;;;;; A0DE;YI SYLLABLE FYT;Lo;0;L;;;;;N;;;;; A0DF;YI SYLLABLE FYX;Lo;0;L;;;;;N;;;;; A0E0;YI SYLLABLE FY;Lo;0;L;;;;;N;;;;; A0E1;YI SYLLABLE FYP;Lo;0;L;;;;;N;;;;; A0E2;YI SYLLABLE VIT;Lo;0;L;;;;;N;;;;; A0E3;YI SYLLABLE VIX;Lo;0;L;;;;;N;;;;; A0E4;YI SYLLABLE VI;Lo;0;L;;;;;N;;;;; A0E5;YI SYLLABLE VIP;Lo;0;L;;;;;N;;;;; A0E6;YI SYLLABLE VIET;Lo;0;L;;;;;N;;;;; A0E7;YI SYLLABLE VIEX;Lo;0;L;;;;;N;;;;; A0E8;YI SYLLABLE VIE;Lo;0;L;;;;;N;;;;; A0E9;YI SYLLABLE VIEP;Lo;0;L;;;;;N;;;;; A0EA;YI SYLLABLE VAT;Lo;0;L;;;;;N;;;;; A0EB;YI SYLLABLE VAX;Lo;0;L;;;;;N;;;;; A0EC;YI SYLLABLE VA;Lo;0;L;;;;;N;;;;; A0ED;YI SYLLABLE VAP;Lo;0;L;;;;;N;;;;; A0EE;YI SYLLABLE VOT;Lo;0;L;;;;;N;;;;; A0EF;YI SYLLABLE VOX;Lo;0;L;;;;;N;;;;; A0F0;YI SYLLABLE VO;Lo;0;L;;;;;N;;;;; A0F1;YI SYLLABLE VOP;Lo;0;L;;;;;N;;;;; A0F2;YI SYLLABLE VEX;Lo;0;L;;;;;N;;;;; A0F3;YI SYLLABLE VEP;Lo;0;L;;;;;N;;;;; A0F4;YI SYLLABLE VUT;Lo;0;L;;;;;N;;;;; A0F5;YI SYLLABLE VUX;Lo;0;L;;;;;N;;;;; A0F6;YI SYLLABLE VU;Lo;0;L;;;;;N;;;;; A0F7;YI SYLLABLE VUP;Lo;0;L;;;;;N;;;;; A0F8;YI SYLLABLE VURX;Lo;0;L;;;;;N;;;;; A0F9;YI SYLLABLE VUR;Lo;0;L;;;;;N;;;;; A0FA;YI SYLLABLE VYT;Lo;0;L;;;;;N;;;;; A0FB;YI SYLLABLE VYX;Lo;0;L;;;;;N;;;;; A0FC;YI SYLLABLE VY;Lo;0;L;;;;;N;;;;; A0FD;YI SYLLABLE VYP;Lo;0;L;;;;;N;;;;; A0FE;YI SYLLABLE VYRX;Lo;0;L;;;;;N;;;;; A0FF;YI SYLLABLE VYR;Lo;0;L;;;;;N;;;;; A100;YI SYLLABLE DIT;Lo;0;L;;;;;N;;;;; A101;YI SYLLABLE DIX;Lo;0;L;;;;;N;;;;; A102;YI SYLLABLE DI;Lo;0;L;;;;;N;;;;; A103;YI SYLLABLE DIP;Lo;0;L;;;;;N;;;;; A104;YI SYLLABLE DIEX;Lo;0;L;;;;;N;;;;; A105;YI SYLLABLE DIE;Lo;0;L;;;;;N;;;;; A106;YI SYLLABLE DIEP;Lo;0;L;;;;;N;;;;; A107;YI SYLLABLE DAT;Lo;0;L;;;;;N;;;;; A108;YI SYLLABLE DAX;Lo;0;L;;;;;N;;;;; A109;YI SYLLABLE DA;Lo;0;L;;;;;N;;;;; A10A;YI SYLLABLE DAP;Lo;0;L;;;;;N;;;;; A10B;YI SYLLABLE DUOX;Lo;0;L;;;;;N;;;;; A10C;YI SYLLABLE DUO;Lo;0;L;;;;;N;;;;; A10D;YI SYLLABLE DOT;Lo;0;L;;;;;N;;;;; A10E;YI SYLLABLE DOX;Lo;0;L;;;;;N;;;;; A10F;YI SYLLABLE DO;Lo;0;L;;;;;N;;;;; A110;YI SYLLABLE DOP;Lo;0;L;;;;;N;;;;; A111;YI SYLLABLE DEX;Lo;0;L;;;;;N;;;;; A112;YI SYLLABLE DE;Lo;0;L;;;;;N;;;;; A113;YI SYLLABLE DEP;Lo;0;L;;;;;N;;;;; A114;YI SYLLABLE DUT;Lo;0;L;;;;;N;;;;; A115;YI SYLLABLE DUX;Lo;0;L;;;;;N;;;;; A116;YI SYLLABLE DU;Lo;0;L;;;;;N;;;;; A117;YI SYLLABLE DUP;Lo;0;L;;;;;N;;;;; A118;YI SYLLABLE DURX;Lo;0;L;;;;;N;;;;; A119;YI SYLLABLE DUR;Lo;0;L;;;;;N;;;;; A11A;YI SYLLABLE TIT;Lo;0;L;;;;;N;;;;; A11B;YI SYLLABLE TIX;Lo;0;L;;;;;N;;;;; A11C;YI SYLLABLE TI;Lo;0;L;;;;;N;;;;; A11D;YI SYLLABLE TIP;Lo;0;L;;;;;N;;;;; A11E;YI SYLLABLE TIEX;Lo;0;L;;;;;N;;;;; A11F;YI SYLLABLE TIE;Lo;0;L;;;;;N;;;;; A120;YI SYLLABLE TIEP;Lo;0;L;;;;;N;;;;; A121;YI SYLLABLE TAT;Lo;0;L;;;;;N;;;;; A122;YI SYLLABLE TAX;Lo;0;L;;;;;N;;;;; A123;YI SYLLABLE TA;Lo;0;L;;;;;N;;;;; A124;YI SYLLABLE TAP;Lo;0;L;;;;;N;;;;; A125;YI SYLLABLE TUOT;Lo;0;L;;;;;N;;;;; A126;YI SYLLABLE TUOX;Lo;0;L;;;;;N;;;;; A127;YI SYLLABLE TUO;Lo;0;L;;;;;N;;;;; A128;YI SYLLABLE TUOP;Lo;0;L;;;;;N;;;;; A129;YI SYLLABLE TOT;Lo;0;L;;;;;N;;;;; A12A;YI SYLLABLE TOX;Lo;0;L;;;;;N;;;;; A12B;YI SYLLABLE TO;Lo;0;L;;;;;N;;;;; A12C;YI SYLLABLE TOP;Lo;0;L;;;;;N;;;;; A12D;YI SYLLABLE TEX;Lo;0;L;;;;;N;;;;; A12E;YI SYLLABLE TE;Lo;0;L;;;;;N;;;;; A12F;YI SYLLABLE TEP;Lo;0;L;;;;;N;;;;; A130;YI SYLLABLE TUT;Lo;0;L;;;;;N;;;;; A131;YI SYLLABLE TUX;Lo;0;L;;;;;N;;;;; A132;YI SYLLABLE TU;Lo;0;L;;;;;N;;;;; A133;YI SYLLABLE TUP;Lo;0;L;;;;;N;;;;; A134;YI SYLLABLE TURX;Lo;0;L;;;;;N;;;;; A135;YI SYLLABLE TUR;Lo;0;L;;;;;N;;;;; A136;YI SYLLABLE DDIT;Lo;0;L;;;;;N;;;;; A137;YI SYLLABLE DDIX;Lo;0;L;;;;;N;;;;; A138;YI SYLLABLE DDI;Lo;0;L;;;;;N;;;;; A139;YI SYLLABLE DDIP;Lo;0;L;;;;;N;;;;; A13A;YI SYLLABLE DDIEX;Lo;0;L;;;;;N;;;;; A13B;YI SYLLABLE DDIE;Lo;0;L;;;;;N;;;;; A13C;YI SYLLABLE DDIEP;Lo;0;L;;;;;N;;;;; A13D;YI SYLLABLE DDAT;Lo;0;L;;;;;N;;;;; A13E;YI SYLLABLE DDAX;Lo;0;L;;;;;N;;;;; A13F;YI SYLLABLE DDA;Lo;0;L;;;;;N;;;;; A140;YI SYLLABLE DDAP;Lo;0;L;;;;;N;;;;; A141;YI SYLLABLE DDUOX;Lo;0;L;;;;;N;;;;; A142;YI SYLLABLE DDUO;Lo;0;L;;;;;N;;;;; A143;YI SYLLABLE DDUOP;Lo;0;L;;;;;N;;;;; A144;YI SYLLABLE DDOT;Lo;0;L;;;;;N;;;;; A145;YI SYLLABLE DDOX;Lo;0;L;;;;;N;;;;; A146;YI SYLLABLE DDO;Lo;0;L;;;;;N;;;;; A147;YI SYLLABLE DDOP;Lo;0;L;;;;;N;;;;; A148;YI SYLLABLE DDEX;Lo;0;L;;;;;N;;;;; A149;YI SYLLABLE DDE;Lo;0;L;;;;;N;;;;; A14A;YI SYLLABLE DDEP;Lo;0;L;;;;;N;;;;; A14B;YI SYLLABLE DDUT;Lo;0;L;;;;;N;;;;; A14C;YI SYLLABLE DDUX;Lo;0;L;;;;;N;;;;; A14D;YI SYLLABLE DDU;Lo;0;L;;;;;N;;;;; A14E;YI SYLLABLE DDUP;Lo;0;L;;;;;N;;;;; A14F;YI SYLLABLE DDURX;Lo;0;L;;;;;N;;;;; A150;YI SYLLABLE DDUR;Lo;0;L;;;;;N;;;;; A151;YI SYLLABLE NDIT;Lo;0;L;;;;;N;;;;; A152;YI SYLLABLE NDIX;Lo;0;L;;;;;N;;;;; A153;YI SYLLABLE NDI;Lo;0;L;;;;;N;;;;; A154;YI SYLLABLE NDIP;Lo;0;L;;;;;N;;;;; A155;YI SYLLABLE NDIEX;Lo;0;L;;;;;N;;;;; A156;YI SYLLABLE NDIE;Lo;0;L;;;;;N;;;;; A157;YI SYLLABLE NDAT;Lo;0;L;;;;;N;;;;; A158;YI SYLLABLE NDAX;Lo;0;L;;;;;N;;;;; A159;YI SYLLABLE NDA;Lo;0;L;;;;;N;;;;; A15A;YI SYLLABLE NDAP;Lo;0;L;;;;;N;;;;; A15B;YI SYLLABLE NDOT;Lo;0;L;;;;;N;;;;; A15C;YI SYLLABLE NDOX;Lo;0;L;;;;;N;;;;; A15D;YI SYLLABLE NDO;Lo;0;L;;;;;N;;;;; A15E;YI SYLLABLE NDOP;Lo;0;L;;;;;N;;;;; A15F;YI SYLLABLE NDEX;Lo;0;L;;;;;N;;;;; A160;YI SYLLABLE NDE;Lo;0;L;;;;;N;;;;; A161;YI SYLLABLE NDEP;Lo;0;L;;;;;N;;;;; A162;YI SYLLABLE NDUT;Lo;0;L;;;;;N;;;;; A163;YI SYLLABLE NDUX;Lo;0;L;;;;;N;;;;; A164;YI SYLLABLE NDU;Lo;0;L;;;;;N;;;;; A165;YI SYLLABLE NDUP;Lo;0;L;;;;;N;;;;; A166;YI SYLLABLE NDURX;Lo;0;L;;;;;N;;;;; A167;YI SYLLABLE NDUR;Lo;0;L;;;;;N;;;;; A168;YI SYLLABLE HNIT;Lo;0;L;;;;;N;;;;; A169;YI SYLLABLE HNIX;Lo;0;L;;;;;N;;;;; A16A;YI SYLLABLE HNI;Lo;0;L;;;;;N;;;;; A16B;YI SYLLABLE HNIP;Lo;0;L;;;;;N;;;;; A16C;YI SYLLABLE HNIET;Lo;0;L;;;;;N;;;;; A16D;YI SYLLABLE HNIEX;Lo;0;L;;;;;N;;;;; A16E;YI SYLLABLE HNIE;Lo;0;L;;;;;N;;;;; A16F;YI SYLLABLE HNIEP;Lo;0;L;;;;;N;;;;; A170;YI SYLLABLE HNAT;Lo;0;L;;;;;N;;;;; A171;YI SYLLABLE HNAX;Lo;0;L;;;;;N;;;;; A172;YI SYLLABLE HNA;Lo;0;L;;;;;N;;;;; A173;YI SYLLABLE HNAP;Lo;0;L;;;;;N;;;;; A174;YI SYLLABLE HNUOX;Lo;0;L;;;;;N;;;;; A175;YI SYLLABLE HNUO;Lo;0;L;;;;;N;;;;; A176;YI SYLLABLE HNOT;Lo;0;L;;;;;N;;;;; A177;YI SYLLABLE HNOX;Lo;0;L;;;;;N;;;;; A178;YI SYLLABLE HNOP;Lo;0;L;;;;;N;;;;; A179;YI SYLLABLE HNEX;Lo;0;L;;;;;N;;;;; A17A;YI SYLLABLE HNE;Lo;0;L;;;;;N;;;;; A17B;YI SYLLABLE HNEP;Lo;0;L;;;;;N;;;;; A17C;YI SYLLABLE HNUT;Lo;0;L;;;;;N;;;;; A17D;YI SYLLABLE NIT;Lo;0;L;;;;;N;;;;; A17E;YI SYLLABLE NIX;Lo;0;L;;;;;N;;;;; A17F;YI SYLLABLE NI;Lo;0;L;;;;;N;;;;; A180;YI SYLLABLE NIP;Lo;0;L;;;;;N;;;;; A181;YI SYLLABLE NIEX;Lo;0;L;;;;;N;;;;; A182;YI SYLLABLE NIE;Lo;0;L;;;;;N;;;;; A183;YI SYLLABLE NIEP;Lo;0;L;;;;;N;;;;; A184;YI SYLLABLE NAX;Lo;0;L;;;;;N;;;;; A185;YI SYLLABLE NA;Lo;0;L;;;;;N;;;;; A186;YI SYLLABLE NAP;Lo;0;L;;;;;N;;;;; A187;YI SYLLABLE NUOX;Lo;0;L;;;;;N;;;;; A188;YI SYLLABLE NUO;Lo;0;L;;;;;N;;;;; A189;YI SYLLABLE NUOP;Lo;0;L;;;;;N;;;;; A18A;YI SYLLABLE NOT;Lo;0;L;;;;;N;;;;; A18B;YI SYLLABLE NOX;Lo;0;L;;;;;N;;;;; A18C;YI SYLLABLE NO;Lo;0;L;;;;;N;;;;; A18D;YI SYLLABLE NOP;Lo;0;L;;;;;N;;;;; A18E;YI SYLLABLE NEX;Lo;0;L;;;;;N;;;;; A18F;YI SYLLABLE NE;Lo;0;L;;;;;N;;;;; A190;YI SYLLABLE NEP;Lo;0;L;;;;;N;;;;; A191;YI SYLLABLE NUT;Lo;0;L;;;;;N;;;;; A192;YI SYLLABLE NUX;Lo;0;L;;;;;N;;;;; A193;YI SYLLABLE NU;Lo;0;L;;;;;N;;;;; A194;YI SYLLABLE NUP;Lo;0;L;;;;;N;;;;; A195;YI SYLLABLE NURX;Lo;0;L;;;;;N;;;;; A196;YI SYLLABLE NUR;Lo;0;L;;;;;N;;;;; A197;YI SYLLABLE HLIT;Lo;0;L;;;;;N;;;;; A198;YI SYLLABLE HLIX;Lo;0;L;;;;;N;;;;; A199;YI SYLLABLE HLI;Lo;0;L;;;;;N;;;;; A19A;YI SYLLABLE HLIP;Lo;0;L;;;;;N;;;;; A19B;YI SYLLABLE HLIEX;Lo;0;L;;;;;N;;;;; A19C;YI SYLLABLE HLIE;Lo;0;L;;;;;N;;;;; A19D;YI SYLLABLE HLIEP;Lo;0;L;;;;;N;;;;; A19E;YI SYLLABLE HLAT;Lo;0;L;;;;;N;;;;; A19F;YI SYLLABLE HLAX;Lo;0;L;;;;;N;;;;; A1A0;YI SYLLABLE HLA;Lo;0;L;;;;;N;;;;; A1A1;YI SYLLABLE HLAP;Lo;0;L;;;;;N;;;;; A1A2;YI SYLLABLE HLUOX;Lo;0;L;;;;;N;;;;; A1A3;YI SYLLABLE HLUO;Lo;0;L;;;;;N;;;;; A1A4;YI SYLLABLE HLUOP;Lo;0;L;;;;;N;;;;; A1A5;YI SYLLABLE HLOX;Lo;0;L;;;;;N;;;;; A1A6;YI SYLLABLE HLO;Lo;0;L;;;;;N;;;;; A1A7;YI SYLLABLE HLOP;Lo;0;L;;;;;N;;;;; A1A8;YI SYLLABLE HLEX;Lo;0;L;;;;;N;;;;; A1A9;YI SYLLABLE HLE;Lo;0;L;;;;;N;;;;; A1AA;YI SYLLABLE HLEP;Lo;0;L;;;;;N;;;;; A1AB;YI SYLLABLE HLUT;Lo;0;L;;;;;N;;;;; A1AC;YI SYLLABLE HLUX;Lo;0;L;;;;;N;;;;; A1AD;YI SYLLABLE HLU;Lo;0;L;;;;;N;;;;; A1AE;YI SYLLABLE HLUP;Lo;0;L;;;;;N;;;;; A1AF;YI SYLLABLE HLURX;Lo;0;L;;;;;N;;;;; A1B0;YI SYLLABLE HLUR;Lo;0;L;;;;;N;;;;; A1B1;YI SYLLABLE HLYT;Lo;0;L;;;;;N;;;;; A1B2;YI SYLLABLE HLYX;Lo;0;L;;;;;N;;;;; A1B3;YI SYLLABLE HLY;Lo;0;L;;;;;N;;;;; A1B4;YI SYLLABLE HLYP;Lo;0;L;;;;;N;;;;; A1B5;YI SYLLABLE HLYRX;Lo;0;L;;;;;N;;;;; A1B6;YI SYLLABLE HLYR;Lo;0;L;;;;;N;;;;; A1B7;YI SYLLABLE LIT;Lo;0;L;;;;;N;;;;; A1B8;YI SYLLABLE LIX;Lo;0;L;;;;;N;;;;; A1B9;YI SYLLABLE LI;Lo;0;L;;;;;N;;;;; A1BA;YI SYLLABLE LIP;Lo;0;L;;;;;N;;;;; A1BB;YI SYLLABLE LIET;Lo;0;L;;;;;N;;;;; A1BC;YI SYLLABLE LIEX;Lo;0;L;;;;;N;;;;; A1BD;YI SYLLABLE LIE;Lo;0;L;;;;;N;;;;; A1BE;YI SYLLABLE LIEP;Lo;0;L;;;;;N;;;;; A1BF;YI SYLLABLE LAT;Lo;0;L;;;;;N;;;;; A1C0;YI SYLLABLE LAX;Lo;0;L;;;;;N;;;;; A1C1;YI SYLLABLE LA;Lo;0;L;;;;;N;;;;; A1C2;YI SYLLABLE LAP;Lo;0;L;;;;;N;;;;; A1C3;YI SYLLABLE LUOT;Lo;0;L;;;;;N;;;;; A1C4;YI SYLLABLE LUOX;Lo;0;L;;;;;N;;;;; A1C5;YI SYLLABLE LUO;Lo;0;L;;;;;N;;;;; A1C6;YI SYLLABLE LUOP;Lo;0;L;;;;;N;;;;; A1C7;YI SYLLABLE LOT;Lo;0;L;;;;;N;;;;; A1C8;YI SYLLABLE LOX;Lo;0;L;;;;;N;;;;; A1C9;YI SYLLABLE LO;Lo;0;L;;;;;N;;;;; A1CA;YI SYLLABLE LOP;Lo;0;L;;;;;N;;;;; A1CB;YI SYLLABLE LEX;Lo;0;L;;;;;N;;;;; A1CC;YI SYLLABLE LE;Lo;0;L;;;;;N;;;;; A1CD;YI SYLLABLE LEP;Lo;0;L;;;;;N;;;;; A1CE;YI SYLLABLE LUT;Lo;0;L;;;;;N;;;;; A1CF;YI SYLLABLE LUX;Lo;0;L;;;;;N;;;;; A1D0;YI SYLLABLE LU;Lo;0;L;;;;;N;;;;; A1D1;YI SYLLABLE LUP;Lo;0;L;;;;;N;;;;; A1D2;YI SYLLABLE LURX;Lo;0;L;;;;;N;;;;; A1D3;YI SYLLABLE LUR;Lo;0;L;;;;;N;;;;; A1D4;YI SYLLABLE LYT;Lo;0;L;;;;;N;;;;; A1D5;YI SYLLABLE LYX;Lo;0;L;;;;;N;;;;; A1D6;YI SYLLABLE LY;Lo;0;L;;;;;N;;;;; A1D7;YI SYLLABLE LYP;Lo;0;L;;;;;N;;;;; A1D8;YI SYLLABLE LYRX;Lo;0;L;;;;;N;;;;; A1D9;YI SYLLABLE LYR;Lo;0;L;;;;;N;;;;; A1DA;YI SYLLABLE GIT;Lo;0;L;;;;;N;;;;; A1DB;YI SYLLABLE GIX;Lo;0;L;;;;;N;;;;; A1DC;YI SYLLABLE GI;Lo;0;L;;;;;N;;;;; A1DD;YI SYLLABLE GIP;Lo;0;L;;;;;N;;;;; A1DE;YI SYLLABLE GIET;Lo;0;L;;;;;N;;;;; A1DF;YI SYLLABLE GIEX;Lo;0;L;;;;;N;;;;; A1E0;YI SYLLABLE GIE;Lo;0;L;;;;;N;;;;; A1E1;YI SYLLABLE GIEP;Lo;0;L;;;;;N;;;;; A1E2;YI SYLLABLE GAT;Lo;0;L;;;;;N;;;;; A1E3;YI SYLLABLE GAX;Lo;0;L;;;;;N;;;;; A1E4;YI SYLLABLE GA;Lo;0;L;;;;;N;;;;; A1E5;YI SYLLABLE GAP;Lo;0;L;;;;;N;;;;; A1E6;YI SYLLABLE GUOT;Lo;0;L;;;;;N;;;;; A1E7;YI SYLLABLE GUOX;Lo;0;L;;;;;N;;;;; A1E8;YI SYLLABLE GUO;Lo;0;L;;;;;N;;;;; A1E9;YI SYLLABLE GUOP;Lo;0;L;;;;;N;;;;; A1EA;YI SYLLABLE GOT;Lo;0;L;;;;;N;;;;; A1EB;YI SYLLABLE GOX;Lo;0;L;;;;;N;;;;; A1EC;YI SYLLABLE GO;Lo;0;L;;;;;N;;;;; A1ED;YI SYLLABLE GOP;Lo;0;L;;;;;N;;;;; A1EE;YI SYLLABLE GET;Lo;0;L;;;;;N;;;;; A1EF;YI SYLLABLE GEX;Lo;0;L;;;;;N;;;;; A1F0;YI SYLLABLE GE;Lo;0;L;;;;;N;;;;; A1F1;YI SYLLABLE GEP;Lo;0;L;;;;;N;;;;; A1F2;YI SYLLABLE GUT;Lo;0;L;;;;;N;;;;; A1F3;YI SYLLABLE GUX;Lo;0;L;;;;;N;;;;; A1F4;YI SYLLABLE GU;Lo;0;L;;;;;N;;;;; A1F5;YI SYLLABLE GUP;Lo;0;L;;;;;N;;;;; A1F6;YI SYLLABLE GURX;Lo;0;L;;;;;N;;;;; A1F7;YI SYLLABLE GUR;Lo;0;L;;;;;N;;;;; A1F8;YI SYLLABLE KIT;Lo;0;L;;;;;N;;;;; A1F9;YI SYLLABLE KIX;Lo;0;L;;;;;N;;;;; A1FA;YI SYLLABLE KI;Lo;0;L;;;;;N;;;;; A1FB;YI SYLLABLE KIP;Lo;0;L;;;;;N;;;;; A1FC;YI SYLLABLE KIEX;Lo;0;L;;;;;N;;;;; A1FD;YI SYLLABLE KIE;Lo;0;L;;;;;N;;;;; A1FE;YI SYLLABLE KIEP;Lo;0;L;;;;;N;;;;; A1FF;YI SYLLABLE KAT;Lo;0;L;;;;;N;;;;; A200;YI SYLLABLE KAX;Lo;0;L;;;;;N;;;;; A201;YI SYLLABLE KA;Lo;0;L;;;;;N;;;;; A202;YI SYLLABLE KAP;Lo;0;L;;;;;N;;;;; A203;YI SYLLABLE KUOX;Lo;0;L;;;;;N;;;;; A204;YI SYLLABLE KUO;Lo;0;L;;;;;N;;;;; A205;YI SYLLABLE KUOP;Lo;0;L;;;;;N;;;;; A206;YI SYLLABLE KOT;Lo;0;L;;;;;N;;;;; A207;YI SYLLABLE KOX;Lo;0;L;;;;;N;;;;; A208;YI SYLLABLE KO;Lo;0;L;;;;;N;;;;; A209;YI SYLLABLE KOP;Lo;0;L;;;;;N;;;;; A20A;YI SYLLABLE KET;Lo;0;L;;;;;N;;;;; A20B;YI SYLLABLE KEX;Lo;0;L;;;;;N;;;;; A20C;YI SYLLABLE KE;Lo;0;L;;;;;N;;;;; A20D;YI SYLLABLE KEP;Lo;0;L;;;;;N;;;;; A20E;YI SYLLABLE KUT;Lo;0;L;;;;;N;;;;; A20F;YI SYLLABLE KUX;Lo;0;L;;;;;N;;;;; A210;YI SYLLABLE KU;Lo;0;L;;;;;N;;;;; A211;YI SYLLABLE KUP;Lo;0;L;;;;;N;;;;; A212;YI SYLLABLE KURX;Lo;0;L;;;;;N;;;;; A213;YI SYLLABLE KUR;Lo;0;L;;;;;N;;;;; A214;YI SYLLABLE GGIT;Lo;0;L;;;;;N;;;;; A215;YI SYLLABLE GGIX;Lo;0;L;;;;;N;;;;; A216;YI SYLLABLE GGI;Lo;0;L;;;;;N;;;;; A217;YI SYLLABLE GGIEX;Lo;0;L;;;;;N;;;;; A218;YI SYLLABLE GGIE;Lo;0;L;;;;;N;;;;; A219;YI SYLLABLE GGIEP;Lo;0;L;;;;;N;;;;; A21A;YI SYLLABLE GGAT;Lo;0;L;;;;;N;;;;; A21B;YI SYLLABLE GGAX;Lo;0;L;;;;;N;;;;; A21C;YI SYLLABLE GGA;Lo;0;L;;;;;N;;;;; A21D;YI SYLLABLE GGAP;Lo;0;L;;;;;N;;;;; A21E;YI SYLLABLE GGUOT;Lo;0;L;;;;;N;;;;; A21F;YI SYLLABLE GGUOX;Lo;0;L;;;;;N;;;;; A220;YI SYLLABLE GGUO;Lo;0;L;;;;;N;;;;; A221;YI SYLLABLE GGUOP;Lo;0;L;;;;;N;;;;; A222;YI SYLLABLE GGOT;Lo;0;L;;;;;N;;;;; A223;YI SYLLABLE GGOX;Lo;0;L;;;;;N;;;;; A224;YI SYLLABLE GGO;Lo;0;L;;;;;N;;;;; A225;YI SYLLABLE GGOP;Lo;0;L;;;;;N;;;;; A226;YI SYLLABLE GGET;Lo;0;L;;;;;N;;;;; A227;YI SYLLABLE GGEX;Lo;0;L;;;;;N;;;;; A228;YI SYLLABLE GGE;Lo;0;L;;;;;N;;;;; A229;YI SYLLABLE GGEP;Lo;0;L;;;;;N;;;;; A22A;YI SYLLABLE GGUT;Lo;0;L;;;;;N;;;;; A22B;YI SYLLABLE GGUX;Lo;0;L;;;;;N;;;;; A22C;YI SYLLABLE GGU;Lo;0;L;;;;;N;;;;; A22D;YI SYLLABLE GGUP;Lo;0;L;;;;;N;;;;; A22E;YI SYLLABLE GGURX;Lo;0;L;;;;;N;;;;; A22F;YI SYLLABLE GGUR;Lo;0;L;;;;;N;;;;; A230;YI SYLLABLE MGIEX;Lo;0;L;;;;;N;;;;; A231;YI SYLLABLE MGIE;Lo;0;L;;;;;N;;;;; A232;YI SYLLABLE MGAT;Lo;0;L;;;;;N;;;;; A233;YI SYLLABLE MGAX;Lo;0;L;;;;;N;;;;; A234;YI SYLLABLE MGA;Lo;0;L;;;;;N;;;;; A235;YI SYLLABLE MGAP;Lo;0;L;;;;;N;;;;; A236;YI SYLLABLE MGUOX;Lo;0;L;;;;;N;;;;; A237;YI SYLLABLE MGUO;Lo;0;L;;;;;N;;;;; A238;YI SYLLABLE MGUOP;Lo;0;L;;;;;N;;;;; A239;YI SYLLABLE MGOT;Lo;0;L;;;;;N;;;;; A23A;YI SYLLABLE MGOX;Lo;0;L;;;;;N;;;;; A23B;YI SYLLABLE MGO;Lo;0;L;;;;;N;;;;; A23C;YI SYLLABLE MGOP;Lo;0;L;;;;;N;;;;; A23D;YI SYLLABLE MGEX;Lo;0;L;;;;;N;;;;; A23E;YI SYLLABLE MGE;Lo;0;L;;;;;N;;;;; A23F;YI SYLLABLE MGEP;Lo;0;L;;;;;N;;;;; A240;YI SYLLABLE MGUT;Lo;0;L;;;;;N;;;;; A241;YI SYLLABLE MGUX;Lo;0;L;;;;;N;;;;; A242;YI SYLLABLE MGU;Lo;0;L;;;;;N;;;;; A243;YI SYLLABLE MGUP;Lo;0;L;;;;;N;;;;; A244;YI SYLLABLE MGURX;Lo;0;L;;;;;N;;;;; A245;YI SYLLABLE MGUR;Lo;0;L;;;;;N;;;;; A246;YI SYLLABLE HXIT;Lo;0;L;;;;;N;;;;; A247;YI SYLLABLE HXIX;Lo;0;L;;;;;N;;;;; A248;YI SYLLABLE HXI;Lo;0;L;;;;;N;;;;; A249;YI SYLLABLE HXIP;Lo;0;L;;;;;N;;;;; A24A;YI SYLLABLE HXIET;Lo;0;L;;;;;N;;;;; A24B;YI SYLLABLE HXIEX;Lo;0;L;;;;;N;;;;; A24C;YI SYLLABLE HXIE;Lo;0;L;;;;;N;;;;; A24D;YI SYLLABLE HXIEP;Lo;0;L;;;;;N;;;;; A24E;YI SYLLABLE HXAT;Lo;0;L;;;;;N;;;;; A24F;YI SYLLABLE HXAX;Lo;0;L;;;;;N;;;;; A250;YI SYLLABLE HXA;Lo;0;L;;;;;N;;;;; A251;YI SYLLABLE HXAP;Lo;0;L;;;;;N;;;;; A252;YI SYLLABLE HXUOT;Lo;0;L;;;;;N;;;;; A253;YI SYLLABLE HXUOX;Lo;0;L;;;;;N;;;;; A254;YI SYLLABLE HXUO;Lo;0;L;;;;;N;;;;; A255;YI SYLLABLE HXUOP;Lo;0;L;;;;;N;;;;; A256;YI SYLLABLE HXOT;Lo;0;L;;;;;N;;;;; A257;YI SYLLABLE HXOX;Lo;0;L;;;;;N;;;;; A258;YI SYLLABLE HXO;Lo;0;L;;;;;N;;;;; A259;YI SYLLABLE HXOP;Lo;0;L;;;;;N;;;;; A25A;YI SYLLABLE HXEX;Lo;0;L;;;;;N;;;;; A25B;YI SYLLABLE HXE;Lo;0;L;;;;;N;;;;; A25C;YI SYLLABLE HXEP;Lo;0;L;;;;;N;;;;; A25D;YI SYLLABLE NGIEX;Lo;0;L;;;;;N;;;;; A25E;YI SYLLABLE NGIE;Lo;0;L;;;;;N;;;;; A25F;YI SYLLABLE NGIEP;Lo;0;L;;;;;N;;;;; A260;YI SYLLABLE NGAT;Lo;0;L;;;;;N;;;;; A261;YI SYLLABLE NGAX;Lo;0;L;;;;;N;;;;; A262;YI SYLLABLE NGA;Lo;0;L;;;;;N;;;;; A263;YI SYLLABLE NGAP;Lo;0;L;;;;;N;;;;; A264;YI SYLLABLE NGUOT;Lo;0;L;;;;;N;;;;; A265;YI SYLLABLE NGUOX;Lo;0;L;;;;;N;;;;; A266;YI SYLLABLE NGUO;Lo;0;L;;;;;N;;;;; A267;YI SYLLABLE NGOT;Lo;0;L;;;;;N;;;;; A268;YI SYLLABLE NGOX;Lo;0;L;;;;;N;;;;; A269;YI SYLLABLE NGO;Lo;0;L;;;;;N;;;;; A26A;YI SYLLABLE NGOP;Lo;0;L;;;;;N;;;;; A26B;YI SYLLABLE NGEX;Lo;0;L;;;;;N;;;;; A26C;YI SYLLABLE NGE;Lo;0;L;;;;;N;;;;; A26D;YI SYLLABLE NGEP;Lo;0;L;;;;;N;;;;; A26E;YI SYLLABLE HIT;Lo;0;L;;;;;N;;;;; A26F;YI SYLLABLE HIEX;Lo;0;L;;;;;N;;;;; A270;YI SYLLABLE HIE;Lo;0;L;;;;;N;;;;; A271;YI SYLLABLE HAT;Lo;0;L;;;;;N;;;;; A272;YI SYLLABLE HAX;Lo;0;L;;;;;N;;;;; A273;YI SYLLABLE HA;Lo;0;L;;;;;N;;;;; A274;YI SYLLABLE HAP;Lo;0;L;;;;;N;;;;; A275;YI SYLLABLE HUOT;Lo;0;L;;;;;N;;;;; A276;YI SYLLABLE HUOX;Lo;0;L;;;;;N;;;;; A277;YI SYLLABLE HUO;Lo;0;L;;;;;N;;;;; A278;YI SYLLABLE HUOP;Lo;0;L;;;;;N;;;;; A279;YI SYLLABLE HOT;Lo;0;L;;;;;N;;;;; A27A;YI SYLLABLE HOX;Lo;0;L;;;;;N;;;;; A27B;YI SYLLABLE HO;Lo;0;L;;;;;N;;;;; A27C;YI SYLLABLE HOP;Lo;0;L;;;;;N;;;;; A27D;YI SYLLABLE HEX;Lo;0;L;;;;;N;;;;; A27E;YI SYLLABLE HE;Lo;0;L;;;;;N;;;;; A27F;YI SYLLABLE HEP;Lo;0;L;;;;;N;;;;; A280;YI SYLLABLE WAT;Lo;0;L;;;;;N;;;;; A281;YI SYLLABLE WAX;Lo;0;L;;;;;N;;;;; A282;YI SYLLABLE WA;Lo;0;L;;;;;N;;;;; A283;YI SYLLABLE WAP;Lo;0;L;;;;;N;;;;; A284;YI SYLLABLE WUOX;Lo;0;L;;;;;N;;;;; A285;YI SYLLABLE WUO;Lo;0;L;;;;;N;;;;; A286;YI SYLLABLE WUOP;Lo;0;L;;;;;N;;;;; A287;YI SYLLABLE WOX;Lo;0;L;;;;;N;;;;; A288;YI SYLLABLE WO;Lo;0;L;;;;;N;;;;; A289;YI SYLLABLE WOP;Lo;0;L;;;;;N;;;;; A28A;YI SYLLABLE WEX;Lo;0;L;;;;;N;;;;; A28B;YI SYLLABLE WE;Lo;0;L;;;;;N;;;;; A28C;YI SYLLABLE WEP;Lo;0;L;;;;;N;;;;; A28D;YI SYLLABLE ZIT;Lo;0;L;;;;;N;;;;; A28E;YI SYLLABLE ZIX;Lo;0;L;;;;;N;;;;; A28F;YI SYLLABLE ZI;Lo;0;L;;;;;N;;;;; A290;YI SYLLABLE ZIP;Lo;0;L;;;;;N;;;;; A291;YI SYLLABLE ZIEX;Lo;0;L;;;;;N;;;;; A292;YI SYLLABLE ZIE;Lo;0;L;;;;;N;;;;; A293;YI SYLLABLE ZIEP;Lo;0;L;;;;;N;;;;; A294;YI SYLLABLE ZAT;Lo;0;L;;;;;N;;;;; A295;YI SYLLABLE ZAX;Lo;0;L;;;;;N;;;;; A296;YI SYLLABLE ZA;Lo;0;L;;;;;N;;;;; A297;YI SYLLABLE ZAP;Lo;0;L;;;;;N;;;;; A298;YI SYLLABLE ZUOX;Lo;0;L;;;;;N;;;;; A299;YI SYLLABLE ZUO;Lo;0;L;;;;;N;;;;; A29A;YI SYLLABLE ZUOP;Lo;0;L;;;;;N;;;;; A29B;YI SYLLABLE ZOT;Lo;0;L;;;;;N;;;;; A29C;YI SYLLABLE ZOX;Lo;0;L;;;;;N;;;;; A29D;YI SYLLABLE ZO;Lo;0;L;;;;;N;;;;; A29E;YI SYLLABLE ZOP;Lo;0;L;;;;;N;;;;; A29F;YI SYLLABLE ZEX;Lo;0;L;;;;;N;;;;; A2A0;YI SYLLABLE ZE;Lo;0;L;;;;;N;;;;; A2A1;YI SYLLABLE ZEP;Lo;0;L;;;;;N;;;;; A2A2;YI SYLLABLE ZUT;Lo;0;L;;;;;N;;;;; A2A3;YI SYLLABLE ZUX;Lo;0;L;;;;;N;;;;; A2A4;YI SYLLABLE ZU;Lo;0;L;;;;;N;;;;; A2A5;YI SYLLABLE ZUP;Lo;0;L;;;;;N;;;;; A2A6;YI SYLLABLE ZURX;Lo;0;L;;;;;N;;;;; A2A7;YI SYLLABLE ZUR;Lo;0;L;;;;;N;;;;; A2A8;YI SYLLABLE ZYT;Lo;0;L;;;;;N;;;;; A2A9;YI SYLLABLE ZYX;Lo;0;L;;;;;N;;;;; A2AA;YI SYLLABLE ZY;Lo;0;L;;;;;N;;;;; A2AB;YI SYLLABLE ZYP;Lo;0;L;;;;;N;;;;; A2AC;YI SYLLABLE ZYRX;Lo;0;L;;;;;N;;;;; A2AD;YI SYLLABLE ZYR;Lo;0;L;;;;;N;;;;; A2AE;YI SYLLABLE CIT;Lo;0;L;;;;;N;;;;; A2AF;YI SYLLABLE CIX;Lo;0;L;;;;;N;;;;; A2B0;YI SYLLABLE CI;Lo;0;L;;;;;N;;;;; A2B1;YI SYLLABLE CIP;Lo;0;L;;;;;N;;;;; A2B2;YI SYLLABLE CIET;Lo;0;L;;;;;N;;;;; A2B3;YI SYLLABLE CIEX;Lo;0;L;;;;;N;;;;; A2B4;YI SYLLABLE CIE;Lo;0;L;;;;;N;;;;; A2B5;YI SYLLABLE CIEP;Lo;0;L;;;;;N;;;;; A2B6;YI SYLLABLE CAT;Lo;0;L;;;;;N;;;;; A2B7;YI SYLLABLE CAX;Lo;0;L;;;;;N;;;;; A2B8;YI SYLLABLE CA;Lo;0;L;;;;;N;;;;; A2B9;YI SYLLABLE CAP;Lo;0;L;;;;;N;;;;; A2BA;YI SYLLABLE CUOX;Lo;0;L;;;;;N;;;;; A2BB;YI SYLLABLE CUO;Lo;0;L;;;;;N;;;;; A2BC;YI SYLLABLE CUOP;Lo;0;L;;;;;N;;;;; A2BD;YI SYLLABLE COT;Lo;0;L;;;;;N;;;;; A2BE;YI SYLLABLE COX;Lo;0;L;;;;;N;;;;; A2BF;YI SYLLABLE CO;Lo;0;L;;;;;N;;;;; A2C0;YI SYLLABLE COP;Lo;0;L;;;;;N;;;;; A2C1;YI SYLLABLE CEX;Lo;0;L;;;;;N;;;;; A2C2;YI SYLLABLE CE;Lo;0;L;;;;;N;;;;; A2C3;YI SYLLABLE CEP;Lo;0;L;;;;;N;;;;; A2C4;YI SYLLABLE CUT;Lo;0;L;;;;;N;;;;; A2C5;YI SYLLABLE CUX;Lo;0;L;;;;;N;;;;; A2C6;YI SYLLABLE CU;Lo;0;L;;;;;N;;;;; A2C7;YI SYLLABLE CUP;Lo;0;L;;;;;N;;;;; A2C8;YI SYLLABLE CURX;Lo;0;L;;;;;N;;;;; A2C9;YI SYLLABLE CUR;Lo;0;L;;;;;N;;;;; A2CA;YI SYLLABLE CYT;Lo;0;L;;;;;N;;;;; A2CB;YI SYLLABLE CYX;Lo;0;L;;;;;N;;;;; A2CC;YI SYLLABLE CY;Lo;0;L;;;;;N;;;;; A2CD;YI SYLLABLE CYP;Lo;0;L;;;;;N;;;;; A2CE;YI SYLLABLE CYRX;Lo;0;L;;;;;N;;;;; A2CF;YI SYLLABLE CYR;Lo;0;L;;;;;N;;;;; A2D0;YI SYLLABLE ZZIT;Lo;0;L;;;;;N;;;;; A2D1;YI SYLLABLE ZZIX;Lo;0;L;;;;;N;;;;; A2D2;YI SYLLABLE ZZI;Lo;0;L;;;;;N;;;;; A2D3;YI SYLLABLE ZZIP;Lo;0;L;;;;;N;;;;; A2D4;YI SYLLABLE ZZIET;Lo;0;L;;;;;N;;;;; A2D5;YI SYLLABLE ZZIEX;Lo;0;L;;;;;N;;;;; A2D6;YI SYLLABLE ZZIE;Lo;0;L;;;;;N;;;;; A2D7;YI SYLLABLE ZZIEP;Lo;0;L;;;;;N;;;;; A2D8;YI SYLLABLE ZZAT;Lo;0;L;;;;;N;;;;; A2D9;YI SYLLABLE ZZAX;Lo;0;L;;;;;N;;;;; A2DA;YI SYLLABLE ZZA;Lo;0;L;;;;;N;;;;; A2DB;YI SYLLABLE ZZAP;Lo;0;L;;;;;N;;;;; A2DC;YI SYLLABLE ZZOX;Lo;0;L;;;;;N;;;;; A2DD;YI SYLLABLE ZZO;Lo;0;L;;;;;N;;;;; A2DE;YI SYLLABLE ZZOP;Lo;0;L;;;;;N;;;;; A2DF;YI SYLLABLE ZZEX;Lo;0;L;;;;;N;;;;; A2E0;YI SYLLABLE ZZE;Lo;0;L;;;;;N;;;;; A2E1;YI SYLLABLE ZZEP;Lo;0;L;;;;;N;;;;; A2E2;YI SYLLABLE ZZUX;Lo;0;L;;;;;N;;;;; A2E3;YI SYLLABLE ZZU;Lo;0;L;;;;;N;;;;; A2E4;YI SYLLABLE ZZUP;Lo;0;L;;;;;N;;;;; A2E5;YI SYLLABLE ZZURX;Lo;0;L;;;;;N;;;;; A2E6;YI SYLLABLE ZZUR;Lo;0;L;;;;;N;;;;; A2E7;YI SYLLABLE ZZYT;Lo;0;L;;;;;N;;;;; A2E8;YI SYLLABLE ZZYX;Lo;0;L;;;;;N;;;;; A2E9;YI SYLLABLE ZZY;Lo;0;L;;;;;N;;;;; A2EA;YI SYLLABLE ZZYP;Lo;0;L;;;;;N;;;;; A2EB;YI SYLLABLE ZZYRX;Lo;0;L;;;;;N;;;;; A2EC;YI SYLLABLE ZZYR;Lo;0;L;;;;;N;;;;; A2ED;YI SYLLABLE NZIT;Lo;0;L;;;;;N;;;;; A2EE;YI SYLLABLE NZIX;Lo;0;L;;;;;N;;;;; A2EF;YI SYLLABLE NZI;Lo;0;L;;;;;N;;;;; A2F0;YI SYLLABLE NZIP;Lo;0;L;;;;;N;;;;; A2F1;YI SYLLABLE NZIEX;Lo;0;L;;;;;N;;;;; A2F2;YI SYLLABLE NZIE;Lo;0;L;;;;;N;;;;; A2F3;YI SYLLABLE NZIEP;Lo;0;L;;;;;N;;;;; A2F4;YI SYLLABLE NZAT;Lo;0;L;;;;;N;;;;; A2F5;YI SYLLABLE NZAX;Lo;0;L;;;;;N;;;;; A2F6;YI SYLLABLE NZA;Lo;0;L;;;;;N;;;;; A2F7;YI SYLLABLE NZAP;Lo;0;L;;;;;N;;;;; A2F8;YI SYLLABLE NZUOX;Lo;0;L;;;;;N;;;;; A2F9;YI SYLLABLE NZUO;Lo;0;L;;;;;N;;;;; A2FA;YI SYLLABLE NZOX;Lo;0;L;;;;;N;;;;; A2FB;YI SYLLABLE NZOP;Lo;0;L;;;;;N;;;;; A2FC;YI SYLLABLE NZEX;Lo;0;L;;;;;N;;;;; A2FD;YI SYLLABLE NZE;Lo;0;L;;;;;N;;;;; A2FE;YI SYLLABLE NZUX;Lo;0;L;;;;;N;;;;; A2FF;YI SYLLABLE NZU;Lo;0;L;;;;;N;;;;; A300;YI SYLLABLE NZUP;Lo;0;L;;;;;N;;;;; A301;YI SYLLABLE NZURX;Lo;0;L;;;;;N;;;;; A302;YI SYLLABLE NZUR;Lo;0;L;;;;;N;;;;; A303;YI SYLLABLE NZYT;Lo;0;L;;;;;N;;;;; A304;YI SYLLABLE NZYX;Lo;0;L;;;;;N;;;;; A305;YI SYLLABLE NZY;Lo;0;L;;;;;N;;;;; A306;YI SYLLABLE NZYP;Lo;0;L;;;;;N;;;;; A307;YI SYLLABLE NZYRX;Lo;0;L;;;;;N;;;;; A308;YI SYLLABLE NZYR;Lo;0;L;;;;;N;;;;; A309;YI SYLLABLE SIT;Lo;0;L;;;;;N;;;;; A30A;YI SYLLABLE SIX;Lo;0;L;;;;;N;;;;; A30B;YI SYLLABLE SI;Lo;0;L;;;;;N;;;;; A30C;YI SYLLABLE SIP;Lo;0;L;;;;;N;;;;; A30D;YI SYLLABLE SIEX;Lo;0;L;;;;;N;;;;; A30E;YI SYLLABLE SIE;Lo;0;L;;;;;N;;;;; A30F;YI SYLLABLE SIEP;Lo;0;L;;;;;N;;;;; A310;YI SYLLABLE SAT;Lo;0;L;;;;;N;;;;; A311;YI SYLLABLE SAX;Lo;0;L;;;;;N;;;;; A312;YI SYLLABLE SA;Lo;0;L;;;;;N;;;;; A313;YI SYLLABLE SAP;Lo;0;L;;;;;N;;;;; A314;YI SYLLABLE SUOX;Lo;0;L;;;;;N;;;;; A315;YI SYLLABLE SUO;Lo;0;L;;;;;N;;;;; A316;YI SYLLABLE SUOP;Lo;0;L;;;;;N;;;;; A317;YI SYLLABLE SOT;Lo;0;L;;;;;N;;;;; A318;YI SYLLABLE SOX;Lo;0;L;;;;;N;;;;; A319;YI SYLLABLE SO;Lo;0;L;;;;;N;;;;; A31A;YI SYLLABLE SOP;Lo;0;L;;;;;N;;;;; A31B;YI SYLLABLE SEX;Lo;0;L;;;;;N;;;;; A31C;YI SYLLABLE SE;Lo;0;L;;;;;N;;;;; A31D;YI SYLLABLE SEP;Lo;0;L;;;;;N;;;;; A31E;YI SYLLABLE SUT;Lo;0;L;;;;;N;;;;; A31F;YI SYLLABLE SUX;Lo;0;L;;;;;N;;;;; A320;YI SYLLABLE SU;Lo;0;L;;;;;N;;;;; A321;YI SYLLABLE SUP;Lo;0;L;;;;;N;;;;; A322;YI SYLLABLE SURX;Lo;0;L;;;;;N;;;;; A323;YI SYLLABLE SUR;Lo;0;L;;;;;N;;;;; A324;YI SYLLABLE SYT;Lo;0;L;;;;;N;;;;; A325;YI SYLLABLE SYX;Lo;0;L;;;;;N;;;;; A326;YI SYLLABLE SY;Lo;0;L;;;;;N;;;;; A327;YI SYLLABLE SYP;Lo;0;L;;;;;N;;;;; A328;YI SYLLABLE SYRX;Lo;0;L;;;;;N;;;;; A329;YI SYLLABLE SYR;Lo;0;L;;;;;N;;;;; A32A;YI SYLLABLE SSIT;Lo;0;L;;;;;N;;;;; A32B;YI SYLLABLE SSIX;Lo;0;L;;;;;N;;;;; A32C;YI SYLLABLE SSI;Lo;0;L;;;;;N;;;;; A32D;YI SYLLABLE SSIP;Lo;0;L;;;;;N;;;;; A32E;YI SYLLABLE SSIEX;Lo;0;L;;;;;N;;;;; A32F;YI SYLLABLE SSIE;Lo;0;L;;;;;N;;;;; A330;YI SYLLABLE SSIEP;Lo;0;L;;;;;N;;;;; A331;YI SYLLABLE SSAT;Lo;0;L;;;;;N;;;;; A332;YI SYLLABLE SSAX;Lo;0;L;;;;;N;;;;; A333;YI SYLLABLE SSA;Lo;0;L;;;;;N;;;;; A334;YI SYLLABLE SSAP;Lo;0;L;;;;;N;;;;; A335;YI SYLLABLE SSOT;Lo;0;L;;;;;N;;;;; A336;YI SYLLABLE SSOX;Lo;0;L;;;;;N;;;;; A337;YI SYLLABLE SSO;Lo;0;L;;;;;N;;;;; A338;YI SYLLABLE SSOP;Lo;0;L;;;;;N;;;;; A339;YI SYLLABLE SSEX;Lo;0;L;;;;;N;;;;; A33A;YI SYLLABLE SSE;Lo;0;L;;;;;N;;;;; A33B;YI SYLLABLE SSEP;Lo;0;L;;;;;N;;;;; A33C;YI SYLLABLE SSUT;Lo;0;L;;;;;N;;;;; A33D;YI SYLLABLE SSUX;Lo;0;L;;;;;N;;;;; A33E;YI SYLLABLE SSU;Lo;0;L;;;;;N;;;;; A33F;YI SYLLABLE SSUP;Lo;0;L;;;;;N;;;;; A340;YI SYLLABLE SSYT;Lo;0;L;;;;;N;;;;; A341;YI SYLLABLE SSYX;Lo;0;L;;;;;N;;;;; A342;YI SYLLABLE SSY;Lo;0;L;;;;;N;;;;; A343;YI SYLLABLE SSYP;Lo;0;L;;;;;N;;;;; A344;YI SYLLABLE SSYRX;Lo;0;L;;;;;N;;;;; A345;YI SYLLABLE SSYR;Lo;0;L;;;;;N;;;;; A346;YI SYLLABLE ZHAT;Lo;0;L;;;;;N;;;;; A347;YI SYLLABLE ZHAX;Lo;0;L;;;;;N;;;;; A348;YI SYLLABLE ZHA;Lo;0;L;;;;;N;;;;; A349;YI SYLLABLE ZHAP;Lo;0;L;;;;;N;;;;; A34A;YI SYLLABLE ZHUOX;Lo;0;L;;;;;N;;;;; A34B;YI SYLLABLE ZHUO;Lo;0;L;;;;;N;;;;; A34C;YI SYLLABLE ZHUOP;Lo;0;L;;;;;N;;;;; A34D;YI SYLLABLE ZHOT;Lo;0;L;;;;;N;;;;; A34E;YI SYLLABLE ZHOX;Lo;0;L;;;;;N;;;;; A34F;YI SYLLABLE ZHO;Lo;0;L;;;;;N;;;;; A350;YI SYLLABLE ZHOP;Lo;0;L;;;;;N;;;;; A351;YI SYLLABLE ZHET;Lo;0;L;;;;;N;;;;; A352;YI SYLLABLE ZHEX;Lo;0;L;;;;;N;;;;; A353;YI SYLLABLE ZHE;Lo;0;L;;;;;N;;;;; A354;YI SYLLABLE ZHEP;Lo;0;L;;;;;N;;;;; A355;YI SYLLABLE ZHUT;Lo;0;L;;;;;N;;;;; A356;YI SYLLABLE ZHUX;Lo;0;L;;;;;N;;;;; A357;YI SYLLABLE ZHU;Lo;0;L;;;;;N;;;;; A358;YI SYLLABLE ZHUP;Lo;0;L;;;;;N;;;;; A359;YI SYLLABLE ZHURX;Lo;0;L;;;;;N;;;;; A35A;YI SYLLABLE ZHUR;Lo;0;L;;;;;N;;;;; A35B;YI SYLLABLE ZHYT;Lo;0;L;;;;;N;;;;; A35C;YI SYLLABLE ZHYX;Lo;0;L;;;;;N;;;;; A35D;YI SYLLABLE ZHY;Lo;0;L;;;;;N;;;;; A35E;YI SYLLABLE ZHYP;Lo;0;L;;;;;N;;;;; A35F;YI SYLLABLE ZHYRX;Lo;0;L;;;;;N;;;;; A360;YI SYLLABLE ZHYR;Lo;0;L;;;;;N;;;;; A361;YI SYLLABLE CHAT;Lo;0;L;;;;;N;;;;; A362;YI SYLLABLE CHAX;Lo;0;L;;;;;N;;;;; A363;YI SYLLABLE CHA;Lo;0;L;;;;;N;;;;; A364;YI SYLLABLE CHAP;Lo;0;L;;;;;N;;;;; A365;YI SYLLABLE CHUOT;Lo;0;L;;;;;N;;;;; A366;YI SYLLABLE CHUOX;Lo;0;L;;;;;N;;;;; A367;YI SYLLABLE CHUO;Lo;0;L;;;;;N;;;;; A368;YI SYLLABLE CHUOP;Lo;0;L;;;;;N;;;;; A369;YI SYLLABLE CHOT;Lo;0;L;;;;;N;;;;; A36A;YI SYLLABLE CHOX;Lo;0;L;;;;;N;;;;; A36B;YI SYLLABLE CHO;Lo;0;L;;;;;N;;;;; A36C;YI SYLLABLE CHOP;Lo;0;L;;;;;N;;;;; A36D;YI SYLLABLE CHET;Lo;0;L;;;;;N;;;;; A36E;YI SYLLABLE CHEX;Lo;0;L;;;;;N;;;;; A36F;YI SYLLABLE CHE;Lo;0;L;;;;;N;;;;; A370;YI SYLLABLE CHEP;Lo;0;L;;;;;N;;;;; A371;YI SYLLABLE CHUX;Lo;0;L;;;;;N;;;;; A372;YI SYLLABLE CHU;Lo;0;L;;;;;N;;;;; A373;YI SYLLABLE CHUP;Lo;0;L;;;;;N;;;;; A374;YI SYLLABLE CHURX;Lo;0;L;;;;;N;;;;; A375;YI SYLLABLE CHUR;Lo;0;L;;;;;N;;;;; A376;YI SYLLABLE CHYT;Lo;0;L;;;;;N;;;;; A377;YI SYLLABLE CHYX;Lo;0;L;;;;;N;;;;; A378;YI SYLLABLE CHY;Lo;0;L;;;;;N;;;;; A379;YI SYLLABLE CHYP;Lo;0;L;;;;;N;;;;; A37A;YI SYLLABLE CHYRX;Lo;0;L;;;;;N;;;;; A37B;YI SYLLABLE CHYR;Lo;0;L;;;;;N;;;;; A37C;YI SYLLABLE RRAX;Lo;0;L;;;;;N;;;;; A37D;YI SYLLABLE RRA;Lo;0;L;;;;;N;;;;; A37E;YI SYLLABLE RRUOX;Lo;0;L;;;;;N;;;;; A37F;YI SYLLABLE RRUO;Lo;0;L;;;;;N;;;;; A380;YI SYLLABLE RROT;Lo;0;L;;;;;N;;;;; A381;YI SYLLABLE RROX;Lo;0;L;;;;;N;;;;; A382;YI SYLLABLE RRO;Lo;0;L;;;;;N;;;;; A383;YI SYLLABLE RROP;Lo;0;L;;;;;N;;;;; A384;YI SYLLABLE RRET;Lo;0;L;;;;;N;;;;; A385;YI SYLLABLE RREX;Lo;0;L;;;;;N;;;;; A386;YI SYLLABLE RRE;Lo;0;L;;;;;N;;;;; A387;YI SYLLABLE RREP;Lo;0;L;;;;;N;;;;; A388;YI SYLLABLE RRUT;Lo;0;L;;;;;N;;;;; A389;YI SYLLABLE RRUX;Lo;0;L;;;;;N;;;;; A38A;YI SYLLABLE RRU;Lo;0;L;;;;;N;;;;; A38B;YI SYLLABLE RRUP;Lo;0;L;;;;;N;;;;; A38C;YI SYLLABLE RRURX;Lo;0;L;;;;;N;;;;; A38D;YI SYLLABLE RRUR;Lo;0;L;;;;;N;;;;; A38E;YI SYLLABLE RRYT;Lo;0;L;;;;;N;;;;; A38F;YI SYLLABLE RRYX;Lo;0;L;;;;;N;;;;; A390;YI SYLLABLE RRY;Lo;0;L;;;;;N;;;;; A391;YI SYLLABLE RRYP;Lo;0;L;;;;;N;;;;; A392;YI SYLLABLE RRYRX;Lo;0;L;;;;;N;;;;; A393;YI SYLLABLE RRYR;Lo;0;L;;;;;N;;;;; A394;YI SYLLABLE NRAT;Lo;0;L;;;;;N;;;;; A395;YI SYLLABLE NRAX;Lo;0;L;;;;;N;;;;; A396;YI SYLLABLE NRA;Lo;0;L;;;;;N;;;;; A397;YI SYLLABLE NRAP;Lo;0;L;;;;;N;;;;; A398;YI SYLLABLE NROX;Lo;0;L;;;;;N;;;;; A399;YI SYLLABLE NRO;Lo;0;L;;;;;N;;;;; A39A;YI SYLLABLE NROP;Lo;0;L;;;;;N;;;;; A39B;YI SYLLABLE NRET;Lo;0;L;;;;;N;;;;; A39C;YI SYLLABLE NREX;Lo;0;L;;;;;N;;;;; A39D;YI SYLLABLE NRE;Lo;0;L;;;;;N;;;;; A39E;YI SYLLABLE NREP;Lo;0;L;;;;;N;;;;; A39F;YI SYLLABLE NRUT;Lo;0;L;;;;;N;;;;; A3A0;YI SYLLABLE NRUX;Lo;0;L;;;;;N;;;;; A3A1;YI SYLLABLE NRU;Lo;0;L;;;;;N;;;;; A3A2;YI SYLLABLE NRUP;Lo;0;L;;;;;N;;;;; A3A3;YI SYLLABLE NRURX;Lo;0;L;;;;;N;;;;; A3A4;YI SYLLABLE NRUR;Lo;0;L;;;;;N;;;;; A3A5;YI SYLLABLE NRYT;Lo;0;L;;;;;N;;;;; A3A6;YI SYLLABLE NRYX;Lo;0;L;;;;;N;;;;; A3A7;YI SYLLABLE NRY;Lo;0;L;;;;;N;;;;; A3A8;YI SYLLABLE NRYP;Lo;0;L;;;;;N;;;;; A3A9;YI SYLLABLE NRYRX;Lo;0;L;;;;;N;;;;; A3AA;YI SYLLABLE NRYR;Lo;0;L;;;;;N;;;;; A3AB;YI SYLLABLE SHAT;Lo;0;L;;;;;N;;;;; A3AC;YI SYLLABLE SHAX;Lo;0;L;;;;;N;;;;; A3AD;YI SYLLABLE SHA;Lo;0;L;;;;;N;;;;; A3AE;YI SYLLABLE SHAP;Lo;0;L;;;;;N;;;;; A3AF;YI SYLLABLE SHUOX;Lo;0;L;;;;;N;;;;; A3B0;YI SYLLABLE SHUO;Lo;0;L;;;;;N;;;;; A3B1;YI SYLLABLE SHUOP;Lo;0;L;;;;;N;;;;; A3B2;YI SYLLABLE SHOT;Lo;0;L;;;;;N;;;;; A3B3;YI SYLLABLE SHOX;Lo;0;L;;;;;N;;;;; A3B4;YI SYLLABLE SHO;Lo;0;L;;;;;N;;;;; A3B5;YI SYLLABLE SHOP;Lo;0;L;;;;;N;;;;; A3B6;YI SYLLABLE SHET;Lo;0;L;;;;;N;;;;; A3B7;YI SYLLABLE SHEX;Lo;0;L;;;;;N;;;;; A3B8;YI SYLLABLE SHE;Lo;0;L;;;;;N;;;;; A3B9;YI SYLLABLE SHEP;Lo;0;L;;;;;N;;;;; A3BA;YI SYLLABLE SHUT;Lo;0;L;;;;;N;;;;; A3BB;YI SYLLABLE SHUX;Lo;0;L;;;;;N;;;;; A3BC;YI SYLLABLE SHU;Lo;0;L;;;;;N;;;;; A3BD;YI SYLLABLE SHUP;Lo;0;L;;;;;N;;;;; A3BE;YI SYLLABLE SHURX;Lo;0;L;;;;;N;;;;; A3BF;YI SYLLABLE SHUR;Lo;0;L;;;;;N;;;;; A3C0;YI SYLLABLE SHYT;Lo;0;L;;;;;N;;;;; A3C1;YI SYLLABLE SHYX;Lo;0;L;;;;;N;;;;; A3C2;YI SYLLABLE SHY;Lo;0;L;;;;;N;;;;; A3C3;YI SYLLABLE SHYP;Lo;0;L;;;;;N;;;;; A3C4;YI SYLLABLE SHYRX;Lo;0;L;;;;;N;;;;; A3C5;YI SYLLABLE SHYR;Lo;0;L;;;;;N;;;;; A3C6;YI SYLLABLE RAT;Lo;0;L;;;;;N;;;;; A3C7;YI SYLLABLE RAX;Lo;0;L;;;;;N;;;;; A3C8;YI SYLLABLE RA;Lo;0;L;;;;;N;;;;; A3C9;YI SYLLABLE RAP;Lo;0;L;;;;;N;;;;; A3CA;YI SYLLABLE RUOX;Lo;0;L;;;;;N;;;;; A3CB;YI SYLLABLE RUO;Lo;0;L;;;;;N;;;;; A3CC;YI SYLLABLE RUOP;Lo;0;L;;;;;N;;;;; A3CD;YI SYLLABLE ROT;Lo;0;L;;;;;N;;;;; A3CE;YI SYLLABLE ROX;Lo;0;L;;;;;N;;;;; A3CF;YI SYLLABLE RO;Lo;0;L;;;;;N;;;;; A3D0;YI SYLLABLE ROP;Lo;0;L;;;;;N;;;;; A3D1;YI SYLLABLE REX;Lo;0;L;;;;;N;;;;; A3D2;YI SYLLABLE RE;Lo;0;L;;;;;N;;;;; A3D3;YI SYLLABLE REP;Lo;0;L;;;;;N;;;;; A3D4;YI SYLLABLE RUT;Lo;0;L;;;;;N;;;;; A3D5;YI SYLLABLE RUX;Lo;0;L;;;;;N;;;;; A3D6;YI SYLLABLE RU;Lo;0;L;;;;;N;;;;; A3D7;YI SYLLABLE RUP;Lo;0;L;;;;;N;;;;; A3D8;YI SYLLABLE RURX;Lo;0;L;;;;;N;;;;; A3D9;YI SYLLABLE RUR;Lo;0;L;;;;;N;;;;; A3DA;YI SYLLABLE RYT;Lo;0;L;;;;;N;;;;; A3DB;YI SYLLABLE RYX;Lo;0;L;;;;;N;;;;; A3DC;YI SYLLABLE RY;Lo;0;L;;;;;N;;;;; A3DD;YI SYLLABLE RYP;Lo;0;L;;;;;N;;;;; A3DE;YI SYLLABLE RYRX;Lo;0;L;;;;;N;;;;; A3DF;YI SYLLABLE RYR;Lo;0;L;;;;;N;;;;; A3E0;YI SYLLABLE JIT;Lo;0;L;;;;;N;;;;; A3E1;YI SYLLABLE JIX;Lo;0;L;;;;;N;;;;; A3E2;YI SYLLABLE JI;Lo;0;L;;;;;N;;;;; A3E3;YI SYLLABLE JIP;Lo;0;L;;;;;N;;;;; A3E4;YI SYLLABLE JIET;Lo;0;L;;;;;N;;;;; A3E5;YI SYLLABLE JIEX;Lo;0;L;;;;;N;;;;; A3E6;YI SYLLABLE JIE;Lo;0;L;;;;;N;;;;; A3E7;YI SYLLABLE JIEP;Lo;0;L;;;;;N;;;;; A3E8;YI SYLLABLE JUOT;Lo;0;L;;;;;N;;;;; A3E9;YI SYLLABLE JUOX;Lo;0;L;;;;;N;;;;; A3EA;YI SYLLABLE JUO;Lo;0;L;;;;;N;;;;; A3EB;YI SYLLABLE JUOP;Lo;0;L;;;;;N;;;;; A3EC;YI SYLLABLE JOT;Lo;0;L;;;;;N;;;;; A3ED;YI SYLLABLE JOX;Lo;0;L;;;;;N;;;;; A3EE;YI SYLLABLE JO;Lo;0;L;;;;;N;;;;; A3EF;YI SYLLABLE JOP;Lo;0;L;;;;;N;;;;; A3F0;YI SYLLABLE JUT;Lo;0;L;;;;;N;;;;; A3F1;YI SYLLABLE JUX;Lo;0;L;;;;;N;;;;; A3F2;YI SYLLABLE JU;Lo;0;L;;;;;N;;;;; A3F3;YI SYLLABLE JUP;Lo;0;L;;;;;N;;;;; A3F4;YI SYLLABLE JURX;Lo;0;L;;;;;N;;;;; A3F5;YI SYLLABLE JUR;Lo;0;L;;;;;N;;;;; A3F6;YI SYLLABLE JYT;Lo;0;L;;;;;N;;;;; A3F7;YI SYLLABLE JYX;Lo;0;L;;;;;N;;;;; A3F8;YI SYLLABLE JY;Lo;0;L;;;;;N;;;;; A3F9;YI SYLLABLE JYP;Lo;0;L;;;;;N;;;;; A3FA;YI SYLLABLE JYRX;Lo;0;L;;;;;N;;;;; A3FB;YI SYLLABLE JYR;Lo;0;L;;;;;N;;;;; A3FC;YI SYLLABLE QIT;Lo;0;L;;;;;N;;;;; A3FD;YI SYLLABLE QIX;Lo;0;L;;;;;N;;;;; A3FE;YI SYLLABLE QI;Lo;0;L;;;;;N;;;;; A3FF;YI SYLLABLE QIP;Lo;0;L;;;;;N;;;;; A400;YI SYLLABLE QIET;Lo;0;L;;;;;N;;;;; A401;YI SYLLABLE QIEX;Lo;0;L;;;;;N;;;;; A402;YI SYLLABLE QIE;Lo;0;L;;;;;N;;;;; A403;YI SYLLABLE QIEP;Lo;0;L;;;;;N;;;;; A404;YI SYLLABLE QUOT;Lo;0;L;;;;;N;;;;; A405;YI SYLLABLE QUOX;Lo;0;L;;;;;N;;;;; A406;YI SYLLABLE QUO;Lo;0;L;;;;;N;;;;; A407;YI SYLLABLE QUOP;Lo;0;L;;;;;N;;;;; A408;YI SYLLABLE QOT;Lo;0;L;;;;;N;;;;; A409;YI SYLLABLE QOX;Lo;0;L;;;;;N;;;;; A40A;YI SYLLABLE QO;Lo;0;L;;;;;N;;;;; A40B;YI SYLLABLE QOP;Lo;0;L;;;;;N;;;;; A40C;YI SYLLABLE QUT;Lo;0;L;;;;;N;;;;; A40D;YI SYLLABLE QUX;Lo;0;L;;;;;N;;;;; A40E;YI SYLLABLE QU;Lo;0;L;;;;;N;;;;; A40F;YI SYLLABLE QUP;Lo;0;L;;;;;N;;;;; A410;YI SYLLABLE QURX;Lo;0;L;;;;;N;;;;; A411;YI SYLLABLE QUR;Lo;0;L;;;;;N;;;;; A412;YI SYLLABLE QYT;Lo;0;L;;;;;N;;;;; A413;YI SYLLABLE QYX;Lo;0;L;;;;;N;;;;; A414;YI SYLLABLE QY;Lo;0;L;;;;;N;;;;; A415;YI SYLLABLE QYP;Lo;0;L;;;;;N;;;;; A416;YI SYLLABLE QYRX;Lo;0;L;;;;;N;;;;; A417;YI SYLLABLE QYR;Lo;0;L;;;;;N;;;;; A418;YI SYLLABLE JJIT;Lo;0;L;;;;;N;;;;; A419;YI SYLLABLE JJIX;Lo;0;L;;;;;N;;;;; A41A;YI SYLLABLE JJI;Lo;0;L;;;;;N;;;;; A41B;YI SYLLABLE JJIP;Lo;0;L;;;;;N;;;;; A41C;YI SYLLABLE JJIET;Lo;0;L;;;;;N;;;;; A41D;YI SYLLABLE JJIEX;Lo;0;L;;;;;N;;;;; A41E;YI SYLLABLE JJIE;Lo;0;L;;;;;N;;;;; A41F;YI SYLLABLE JJIEP;Lo;0;L;;;;;N;;;;; A420;YI SYLLABLE JJUOX;Lo;0;L;;;;;N;;;;; A421;YI SYLLABLE JJUO;Lo;0;L;;;;;N;;;;; A422;YI SYLLABLE JJUOP;Lo;0;L;;;;;N;;;;; A423;YI SYLLABLE JJOT;Lo;0;L;;;;;N;;;;; A424;YI SYLLABLE JJOX;Lo;0;L;;;;;N;;;;; A425;YI SYLLABLE JJO;Lo;0;L;;;;;N;;;;; A426;YI SYLLABLE JJOP;Lo;0;L;;;;;N;;;;; A427;YI SYLLABLE JJUT;Lo;0;L;;;;;N;;;;; A428;YI SYLLABLE JJUX;Lo;0;L;;;;;N;;;;; A429;YI SYLLABLE JJU;Lo;0;L;;;;;N;;;;; A42A;YI SYLLABLE JJUP;Lo;0;L;;;;;N;;;;; A42B;YI SYLLABLE JJURX;Lo;0;L;;;;;N;;;;; A42C;YI SYLLABLE JJUR;Lo;0;L;;;;;N;;;;; A42D;YI SYLLABLE JJYT;Lo;0;L;;;;;N;;;;; A42E;YI SYLLABLE JJYX;Lo;0;L;;;;;N;;;;; A42F;YI SYLLABLE JJY;Lo;0;L;;;;;N;;;;; A430;YI SYLLABLE JJYP;Lo;0;L;;;;;N;;;;; A431;YI SYLLABLE NJIT;Lo;0;L;;;;;N;;;;; A432;YI SYLLABLE NJIX;Lo;0;L;;;;;N;;;;; A433;YI SYLLABLE NJI;Lo;0;L;;;;;N;;;;; A434;YI SYLLABLE NJIP;Lo;0;L;;;;;N;;;;; A435;YI SYLLABLE NJIET;Lo;0;L;;;;;N;;;;; A436;YI SYLLABLE NJIEX;Lo;0;L;;;;;N;;;;; A437;YI SYLLABLE NJIE;Lo;0;L;;;;;N;;;;; A438;YI SYLLABLE NJIEP;Lo;0;L;;;;;N;;;;; A439;YI SYLLABLE NJUOX;Lo;0;L;;;;;N;;;;; A43A;YI SYLLABLE NJUO;Lo;0;L;;;;;N;;;;; A43B;YI SYLLABLE NJOT;Lo;0;L;;;;;N;;;;; A43C;YI SYLLABLE NJOX;Lo;0;L;;;;;N;;;;; A43D;YI SYLLABLE NJO;Lo;0;L;;;;;N;;;;; A43E;YI SYLLABLE NJOP;Lo;0;L;;;;;N;;;;; A43F;YI SYLLABLE NJUX;Lo;0;L;;;;;N;;;;; A440;YI SYLLABLE NJU;Lo;0;L;;;;;N;;;;; A441;YI SYLLABLE NJUP;Lo;0;L;;;;;N;;;;; A442;YI SYLLABLE NJURX;Lo;0;L;;;;;N;;;;; A443;YI SYLLABLE NJUR;Lo;0;L;;;;;N;;;;; A444;YI SYLLABLE NJYT;Lo;0;L;;;;;N;;;;; A445;YI SYLLABLE NJYX;Lo;0;L;;;;;N;;;;; A446;YI SYLLABLE NJY;Lo;0;L;;;;;N;;;;; A447;YI SYLLABLE NJYP;Lo;0;L;;;;;N;;;;; A448;YI SYLLABLE NJYRX;Lo;0;L;;;;;N;;;;; A449;YI SYLLABLE NJYR;Lo;0;L;;;;;N;;;;; A44A;YI SYLLABLE NYIT;Lo;0;L;;;;;N;;;;; A44B;YI SYLLABLE NYIX;Lo;0;L;;;;;N;;;;; A44C;YI SYLLABLE NYI;Lo;0;L;;;;;N;;;;; A44D;YI SYLLABLE NYIP;Lo;0;L;;;;;N;;;;; A44E;YI SYLLABLE NYIET;Lo;0;L;;;;;N;;;;; A44F;YI SYLLABLE NYIEX;Lo;0;L;;;;;N;;;;; A450;YI SYLLABLE NYIE;Lo;0;L;;;;;N;;;;; A451;YI SYLLABLE NYIEP;Lo;0;L;;;;;N;;;;; A452;YI SYLLABLE NYUOX;Lo;0;L;;;;;N;;;;; A453;YI SYLLABLE NYUO;Lo;0;L;;;;;N;;;;; A454;YI SYLLABLE NYUOP;Lo;0;L;;;;;N;;;;; A455;YI SYLLABLE NYOT;Lo;0;L;;;;;N;;;;; A456;YI SYLLABLE NYOX;Lo;0;L;;;;;N;;;;; A457;YI SYLLABLE NYO;Lo;0;L;;;;;N;;;;; A458;YI SYLLABLE NYOP;Lo;0;L;;;;;N;;;;; A459;YI SYLLABLE NYUT;Lo;0;L;;;;;N;;;;; A45A;YI SYLLABLE NYUX;Lo;0;L;;;;;N;;;;; A45B;YI SYLLABLE NYU;Lo;0;L;;;;;N;;;;; A45C;YI SYLLABLE NYUP;Lo;0;L;;;;;N;;;;; A45D;YI SYLLABLE XIT;Lo;0;L;;;;;N;;;;; A45E;YI SYLLABLE XIX;Lo;0;L;;;;;N;;;;; A45F;YI SYLLABLE XI;Lo;0;L;;;;;N;;;;; A460;YI SYLLABLE XIP;Lo;0;L;;;;;N;;;;; A461;YI SYLLABLE XIET;Lo;0;L;;;;;N;;;;; A462;YI SYLLABLE XIEX;Lo;0;L;;;;;N;;;;; A463;YI SYLLABLE XIE;Lo;0;L;;;;;N;;;;; A464;YI SYLLABLE XIEP;Lo;0;L;;;;;N;;;;; A465;YI SYLLABLE XUOX;Lo;0;L;;;;;N;;;;; A466;YI SYLLABLE XUO;Lo;0;L;;;;;N;;;;; A467;YI SYLLABLE XOT;Lo;0;L;;;;;N;;;;; A468;YI SYLLABLE XOX;Lo;0;L;;;;;N;;;;; A469;YI SYLLABLE XO;Lo;0;L;;;;;N;;;;; A46A;YI SYLLABLE XOP;Lo;0;L;;;;;N;;;;; A46B;YI SYLLABLE XYT;Lo;0;L;;;;;N;;;;; A46C;YI SYLLABLE XYX;Lo;0;L;;;;;N;;;;; A46D;YI SYLLABLE XY;Lo;0;L;;;;;N;;;;; A46E;YI SYLLABLE XYP;Lo;0;L;;;;;N;;;;; A46F;YI SYLLABLE XYRX;Lo;0;L;;;;;N;;;;; A470;YI SYLLABLE XYR;Lo;0;L;;;;;N;;;;; A471;YI SYLLABLE YIT;Lo;0;L;;;;;N;;;;; A472;YI SYLLABLE YIX;Lo;0;L;;;;;N;;;;; A473;YI SYLLABLE YI;Lo;0;L;;;;;N;;;;; A474;YI SYLLABLE YIP;Lo;0;L;;;;;N;;;;; A475;YI SYLLABLE YIET;Lo;0;L;;;;;N;;;;; A476;YI SYLLABLE YIEX;Lo;0;L;;;;;N;;;;; A477;YI SYLLABLE YIE;Lo;0;L;;;;;N;;;;; A478;YI SYLLABLE YIEP;Lo;0;L;;;;;N;;;;; A479;YI SYLLABLE YUOT;Lo;0;L;;;;;N;;;;; A47A;YI SYLLABLE YUOX;Lo;0;L;;;;;N;;;;; A47B;YI SYLLABLE YUO;Lo;0;L;;;;;N;;;;; A47C;YI SYLLABLE YUOP;Lo;0;L;;;;;N;;;;; A47D;YI SYLLABLE YOT;Lo;0;L;;;;;N;;;;; A47E;YI SYLLABLE YOX;Lo;0;L;;;;;N;;;;; A47F;YI SYLLABLE YO;Lo;0;L;;;;;N;;;;; A480;YI SYLLABLE YOP;Lo;0;L;;;;;N;;;;; A481;YI SYLLABLE YUT;Lo;0;L;;;;;N;;;;; A482;YI SYLLABLE YUX;Lo;0;L;;;;;N;;;;; A483;YI SYLLABLE YU;Lo;0;L;;;;;N;;;;; A484;YI SYLLABLE YUP;Lo;0;L;;;;;N;;;;; A485;YI SYLLABLE YURX;Lo;0;L;;;;;N;;;;; A486;YI SYLLABLE YUR;Lo;0;L;;;;;N;;;;; A487;YI SYLLABLE YYT;Lo;0;L;;;;;N;;;;; A488;YI SYLLABLE YYX;Lo;0;L;;;;;N;;;;; A489;YI SYLLABLE YY;Lo;0;L;;;;;N;;;;; A48A;YI SYLLABLE YYP;Lo;0;L;;;;;N;;;;; A48B;YI SYLLABLE YYRX;Lo;0;L;;;;;N;;;;; A48C;YI SYLLABLE YYR;Lo;0;L;;;;;N;;;;; A490;YI RADICAL QOT;So;0;ON;;;;;N;;;;; A491;YI RADICAL LI;So;0;ON;;;;;N;;;;; A492;YI RADICAL KIT;So;0;ON;;;;;N;;;;; A493;YI RADICAL NYIP;So;0;ON;;;;;N;;;;; A494;YI RADICAL CYP;So;0;ON;;;;;N;;;;; A495;YI RADICAL SSI;So;0;ON;;;;;N;;;;; A496;YI RADICAL GGOP;So;0;ON;;;;;N;;;;; A497;YI RADICAL GEP;So;0;ON;;;;;N;;;;; A498;YI RADICAL MI;So;0;ON;;;;;N;;;;; A499;YI RADICAL HXIT;So;0;ON;;;;;N;;;;; A49A;YI RADICAL LYR;So;0;ON;;;;;N;;;;; A49B;YI RADICAL BBUT;So;0;ON;;;;;N;;;;; A49C;YI RADICAL MOP;So;0;ON;;;;;N;;;;; A49D;YI RADICAL YO;So;0;ON;;;;;N;;;;; A49E;YI RADICAL PUT;So;0;ON;;;;;N;;;;; A49F;YI RADICAL HXUO;So;0;ON;;;;;N;;;;; A4A0;YI RADICAL TAT;So;0;ON;;;;;N;;;;; A4A1;YI RADICAL GA;So;0;ON;;;;;N;;;;; A4A2;YI RADICAL ZUP;So;0;ON;;;;;N;;;;; A4A3;YI RADICAL CYT;So;0;ON;;;;;N;;;;; A4A4;YI RADICAL DDUR;So;0;ON;;;;;N;;;;; A4A5;YI RADICAL BUR;So;0;ON;;;;;N;;;;; A4A6;YI RADICAL GGUO;So;0;ON;;;;;N;;;;; A4A7;YI RADICAL NYOP;So;0;ON;;;;;N;;;;; A4A8;YI RADICAL TU;So;0;ON;;;;;N;;;;; A4A9;YI RADICAL OP;So;0;ON;;;;;N;;;;; A4AA;YI RADICAL JJUT;So;0;ON;;;;;N;;;;; A4AB;YI RADICAL ZOT;So;0;ON;;;;;N;;;;; A4AC;YI RADICAL PYT;So;0;ON;;;;;N;;;;; A4AD;YI RADICAL HMO;So;0;ON;;;;;N;;;;; A4AE;YI RADICAL YIT;So;0;ON;;;;;N;;;;; A4AF;YI RADICAL VUR;So;0;ON;;;;;N;;;;; A4B0;YI RADICAL SHY;So;0;ON;;;;;N;;;;; A4B1;YI RADICAL VEP;So;0;ON;;;;;N;;;;; A4B2;YI RADICAL ZA;So;0;ON;;;;;N;;;;; A4B3;YI RADICAL JO;So;0;ON;;;;;N;;;;; A4B4;YI RADICAL NZUP;So;0;ON;;;;;N;;;;; A4B5;YI RADICAL JJY;So;0;ON;;;;;N;;;;; A4B6;YI RADICAL GOT;So;0;ON;;;;;N;;;;; A4B7;YI RADICAL JJIE;So;0;ON;;;;;N;;;;; A4B8;YI RADICAL WO;So;0;ON;;;;;N;;;;; A4B9;YI RADICAL DU;So;0;ON;;;;;N;;;;; A4BA;YI RADICAL SHUR;So;0;ON;;;;;N;;;;; A4BB;YI RADICAL LIE;So;0;ON;;;;;N;;;;; A4BC;YI RADICAL CY;So;0;ON;;;;;N;;;;; A4BD;YI RADICAL CUOP;So;0;ON;;;;;N;;;;; A4BE;YI RADICAL CIP;So;0;ON;;;;;N;;;;; A4BF;YI RADICAL HXOP;So;0;ON;;;;;N;;;;; A4C0;YI RADICAL SHAT;So;0;ON;;;;;N;;;;; A4C1;YI RADICAL ZUR;So;0;ON;;;;;N;;;;; A4C2;YI RADICAL SHOP;So;0;ON;;;;;N;;;;; A4C3;YI RADICAL CHE;So;0;ON;;;;;N;;;;; A4C4;YI RADICAL ZZIET;So;0;ON;;;;;N;;;;; A4C5;YI RADICAL NBIE;So;0;ON;;;;;N;;;;; A4C6;YI RADICAL KE;So;0;ON;;;;;N;;;;; AC00;;Lo;0;L;;;;;N;;;;; D7A3;;Lo;0;L;;;;;N;;;;; D800;;Cs;0;L;;;;;N;;;;; DB7F;;Cs;0;L;;;;;N;;;;; DB80;;Cs;0;L;;;;;N;;;;; DBFF;;Cs;0;L;;;;;N;;;;; DC00;;Cs;0;L;;;;;N;;;;; DFFF;;Cs;0;L;;;;;N;;;;; E000;;Co;0;L;;;;;N;;;;; F8FF;;Co;0;L;;;;;N;;;;; F900;CJK COMPATIBILITY IDEOGRAPH-F900;Lo;0;L;8C48;;;;N;;;;; F901;CJK COMPATIBILITY IDEOGRAPH-F901;Lo;0;L;66F4;;;;N;;;;; F902;CJK COMPATIBILITY IDEOGRAPH-F902;Lo;0;L;8ECA;;;;N;;;;; F903;CJK COMPATIBILITY IDEOGRAPH-F903;Lo;0;L;8CC8;;;;N;;;;; F904;CJK COMPATIBILITY IDEOGRAPH-F904;Lo;0;L;6ED1;;;;N;;;;; F905;CJK COMPATIBILITY IDEOGRAPH-F905;Lo;0;L;4E32;;;;N;;;;; F906;CJK COMPATIBILITY IDEOGRAPH-F906;Lo;0;L;53E5;;;;N;;;;; F907;CJK COMPATIBILITY IDEOGRAPH-F907;Lo;0;L;9F9C;;;;N;;;;; F908;CJK COMPATIBILITY IDEOGRAPH-F908;Lo;0;L;9F9C;;;;N;;;;; F909;CJK COMPATIBILITY IDEOGRAPH-F909;Lo;0;L;5951;;;;N;;;;; F90A;CJK COMPATIBILITY IDEOGRAPH-F90A;Lo;0;L;91D1;;;;N;;;;; F90B;CJK COMPATIBILITY IDEOGRAPH-F90B;Lo;0;L;5587;;;;N;;;;; F90C;CJK COMPATIBILITY IDEOGRAPH-F90C;Lo;0;L;5948;;;;N;;;;; F90D;CJK COMPATIBILITY IDEOGRAPH-F90D;Lo;0;L;61F6;;;;N;;;;; F90E;CJK COMPATIBILITY IDEOGRAPH-F90E;Lo;0;L;7669;;;;N;;;;; F90F;CJK COMPATIBILITY IDEOGRAPH-F90F;Lo;0;L;7F85;;;;N;;;;; F910;CJK COMPATIBILITY IDEOGRAPH-F910;Lo;0;L;863F;;;;N;;;;; F911;CJK COMPATIBILITY IDEOGRAPH-F911;Lo;0;L;87BA;;;;N;;;;; F912;CJK COMPATIBILITY IDEOGRAPH-F912;Lo;0;L;88F8;;;;N;;;;; F913;CJK COMPATIBILITY IDEOGRAPH-F913;Lo;0;L;908F;;;;N;;;;; F914;CJK COMPATIBILITY IDEOGRAPH-F914;Lo;0;L;6A02;;;;N;;;;; F915;CJK COMPATIBILITY IDEOGRAPH-F915;Lo;0;L;6D1B;;;;N;;;;; F916;CJK COMPATIBILITY IDEOGRAPH-F916;Lo;0;L;70D9;;;;N;;;;; F917;CJK COMPATIBILITY IDEOGRAPH-F917;Lo;0;L;73DE;;;;N;;;;; F918;CJK COMPATIBILITY IDEOGRAPH-F918;Lo;0;L;843D;;;;N;;;;; F919;CJK COMPATIBILITY IDEOGRAPH-F919;Lo;0;L;916A;;;;N;;;;; F91A;CJK COMPATIBILITY IDEOGRAPH-F91A;Lo;0;L;99F1;;;;N;;;;; F91B;CJK COMPATIBILITY IDEOGRAPH-F91B;Lo;0;L;4E82;;;;N;;;;; F91C;CJK COMPATIBILITY IDEOGRAPH-F91C;Lo;0;L;5375;;;;N;;;;; F91D;CJK COMPATIBILITY IDEOGRAPH-F91D;Lo;0;L;6B04;;;;N;;;;; F91E;CJK COMPATIBILITY IDEOGRAPH-F91E;Lo;0;L;721B;;;;N;;;;; F91F;CJK COMPATIBILITY IDEOGRAPH-F91F;Lo;0;L;862D;;;;N;;;;; F920;CJK COMPATIBILITY IDEOGRAPH-F920;Lo;0;L;9E1E;;;;N;;;;; F921;CJK COMPATIBILITY IDEOGRAPH-F921;Lo;0;L;5D50;;;;N;;;;; F922;CJK COMPATIBILITY IDEOGRAPH-F922;Lo;0;L;6FEB;;;;N;;;;; F923;CJK COMPATIBILITY IDEOGRAPH-F923;Lo;0;L;85CD;;;;N;;;;; F924;CJK COMPATIBILITY IDEOGRAPH-F924;Lo;0;L;8964;;;;N;;;;; F925;CJK COMPATIBILITY IDEOGRAPH-F925;Lo;0;L;62C9;;;;N;;;;; F926;CJK COMPATIBILITY IDEOGRAPH-F926;Lo;0;L;81D8;;;;N;;;;; F927;CJK COMPATIBILITY IDEOGRAPH-F927;Lo;0;L;881F;;;;N;;;;; F928;CJK COMPATIBILITY IDEOGRAPH-F928;Lo;0;L;5ECA;;;;N;;;;; F929;CJK COMPATIBILITY IDEOGRAPH-F929;Lo;0;L;6717;;;;N;;;;; F92A;CJK COMPATIBILITY IDEOGRAPH-F92A;Lo;0;L;6D6A;;;;N;;;;; F92B;CJK COMPATIBILITY IDEOGRAPH-F92B;Lo;0;L;72FC;;;;N;;;;; F92C;CJK COMPATIBILITY IDEOGRAPH-F92C;Lo;0;L;90CE;;;;N;;;;; F92D;CJK COMPATIBILITY IDEOGRAPH-F92D;Lo;0;L;4F86;;;;N;;;;; F92E;CJK COMPATIBILITY IDEOGRAPH-F92E;Lo;0;L;51B7;;;;N;;;;; F92F;CJK COMPATIBILITY IDEOGRAPH-F92F;Lo;0;L;52DE;;;;N;;;;; F930;CJK COMPATIBILITY IDEOGRAPH-F930;Lo;0;L;64C4;;;;N;;;;; F931;CJK COMPATIBILITY IDEOGRAPH-F931;Lo;0;L;6AD3;;;;N;;;;; F932;CJK COMPATIBILITY IDEOGRAPH-F932;Lo;0;L;7210;;;;N;;;;; F933;CJK COMPATIBILITY IDEOGRAPH-F933;Lo;0;L;76E7;;;;N;;;;; F934;CJK COMPATIBILITY IDEOGRAPH-F934;Lo;0;L;8001;;;;N;;;;; F935;CJK COMPATIBILITY IDEOGRAPH-F935;Lo;0;L;8606;;;;N;;;;; F936;CJK COMPATIBILITY IDEOGRAPH-F936;Lo;0;L;865C;;;;N;;;;; F937;CJK COMPATIBILITY IDEOGRAPH-F937;Lo;0;L;8DEF;;;;N;;;;; F938;CJK COMPATIBILITY IDEOGRAPH-F938;Lo;0;L;9732;;;;N;;;;; F939;CJK COMPATIBILITY IDEOGRAPH-F939;Lo;0;L;9B6F;;;;N;;;;; F93A;CJK COMPATIBILITY IDEOGRAPH-F93A;Lo;0;L;9DFA;;;;N;;;;; F93B;CJK COMPATIBILITY IDEOGRAPH-F93B;Lo;0;L;788C;;;;N;;;;; F93C;CJK COMPATIBILITY IDEOGRAPH-F93C;Lo;0;L;797F;;;;N;;;;; F93D;CJK COMPATIBILITY IDEOGRAPH-F93D;Lo;0;L;7DA0;;;;N;;;;; F93E;CJK COMPATIBILITY IDEOGRAPH-F93E;Lo;0;L;83C9;;;;N;;;;; F93F;CJK COMPATIBILITY IDEOGRAPH-F93F;Lo;0;L;9304;;;;N;;;;; F940;CJK COMPATIBILITY IDEOGRAPH-F940;Lo;0;L;9E7F;;;;N;;;;; F941;CJK COMPATIBILITY IDEOGRAPH-F941;Lo;0;L;8AD6;;;;N;;;;; F942;CJK COMPATIBILITY IDEOGRAPH-F942;Lo;0;L;58DF;;;;N;;;;; F943;CJK COMPATIBILITY IDEOGRAPH-F943;Lo;0;L;5F04;;;;N;;;;; F944;CJK COMPATIBILITY IDEOGRAPH-F944;Lo;0;L;7C60;;;;N;;;;; F945;CJK COMPATIBILITY IDEOGRAPH-F945;Lo;0;L;807E;;;;N;;;;; F946;CJK COMPATIBILITY IDEOGRAPH-F946;Lo;0;L;7262;;;;N;;;;; F947;CJK COMPATIBILITY IDEOGRAPH-F947;Lo;0;L;78CA;;;;N;;;;; F948;CJK COMPATIBILITY IDEOGRAPH-F948;Lo;0;L;8CC2;;;;N;;;;; F949;CJK COMPATIBILITY IDEOGRAPH-F949;Lo;0;L;96F7;;;;N;;;;; F94A;CJK COMPATIBILITY IDEOGRAPH-F94A;Lo;0;L;58D8;;;;N;;;;; F94B;CJK COMPATIBILITY IDEOGRAPH-F94B;Lo;0;L;5C62;;;;N;;;;; F94C;CJK COMPATIBILITY IDEOGRAPH-F94C;Lo;0;L;6A13;;;;N;;;;; F94D;CJK COMPATIBILITY IDEOGRAPH-F94D;Lo;0;L;6DDA;;;;N;;;;; F94E;CJK COMPATIBILITY IDEOGRAPH-F94E;Lo;0;L;6F0F;;;;N;;;;; F94F;CJK COMPATIBILITY IDEOGRAPH-F94F;Lo;0;L;7D2F;;;;N;;;;; F950;CJK COMPATIBILITY IDEOGRAPH-F950;Lo;0;L;7E37;;;;N;;;;; F951;CJK COMPATIBILITY IDEOGRAPH-F951;Lo;0;L;964B;;;;N;;;;; F952;CJK COMPATIBILITY IDEOGRAPH-F952;Lo;0;L;52D2;;;;N;;;;; F953;CJK COMPATIBILITY IDEOGRAPH-F953;Lo;0;L;808B;;;;N;;;;; F954;CJK COMPATIBILITY IDEOGRAPH-F954;Lo;0;L;51DC;;;;N;;;;; F955;CJK COMPATIBILITY IDEOGRAPH-F955;Lo;0;L;51CC;;;;N;;;;; F956;CJK COMPATIBILITY IDEOGRAPH-F956;Lo;0;L;7A1C;;;;N;;;;; F957;CJK COMPATIBILITY IDEOGRAPH-F957;Lo;0;L;7DBE;;;;N;;;;; F958;CJK COMPATIBILITY IDEOGRAPH-F958;Lo;0;L;83F1;;;;N;;;;; F959;CJK COMPATIBILITY IDEOGRAPH-F959;Lo;0;L;9675;;;;N;;;;; F95A;CJK COMPATIBILITY IDEOGRAPH-F95A;Lo;0;L;8B80;;;;N;;;;; F95B;CJK COMPATIBILITY IDEOGRAPH-F95B;Lo;0;L;62CF;;;;N;;;;; F95C;CJK COMPATIBILITY IDEOGRAPH-F95C;Lo;0;L;6A02;;;;N;;;;; F95D;CJK COMPATIBILITY IDEOGRAPH-F95D;Lo;0;L;8AFE;;;;N;;;;; F95E;CJK COMPATIBILITY IDEOGRAPH-F95E;Lo;0;L;4E39;;;;N;;;;; F95F;CJK COMPATIBILITY IDEOGRAPH-F95F;Lo;0;L;5BE7;;;;N;;;;; F960;CJK COMPATIBILITY IDEOGRAPH-F960;Lo;0;L;6012;;;;N;;;;; F961;CJK COMPATIBILITY IDEOGRAPH-F961;Lo;0;L;7387;;;;N;;;;; F962;CJK COMPATIBILITY IDEOGRAPH-F962;Lo;0;L;7570;;;;N;;;;; F963;CJK COMPATIBILITY IDEOGRAPH-F963;Lo;0;L;5317;;;;N;;;;; F964;CJK COMPATIBILITY IDEOGRAPH-F964;Lo;0;L;78FB;;;;N;;;;; F965;CJK COMPATIBILITY IDEOGRAPH-F965;Lo;0;L;4FBF;;;;N;;;;; F966;CJK COMPATIBILITY IDEOGRAPH-F966;Lo;0;L;5FA9;;;;N;;;;; F967;CJK COMPATIBILITY IDEOGRAPH-F967;Lo;0;L;4E0D;;;;N;;;;; F968;CJK COMPATIBILITY IDEOGRAPH-F968;Lo;0;L;6CCC;;;;N;;;;; F969;CJK COMPATIBILITY IDEOGRAPH-F969;Lo;0;L;6578;;;;N;;;;; F96A;CJK COMPATIBILITY IDEOGRAPH-F96A;Lo;0;L;7D22;;;;N;;;;; F96B;CJK COMPATIBILITY IDEOGRAPH-F96B;Lo;0;L;53C3;;;;N;;;;; F96C;CJK COMPATIBILITY IDEOGRAPH-F96C;Lo;0;L;585E;;;;N;;;;; F96D;CJK COMPATIBILITY IDEOGRAPH-F96D;Lo;0;L;7701;;;;N;;;;; F96E;CJK COMPATIBILITY IDEOGRAPH-F96E;Lo;0;L;8449;;;;N;;;;; F96F;CJK COMPATIBILITY IDEOGRAPH-F96F;Lo;0;L;8AAA;;;;N;;;;; F970;CJK COMPATIBILITY IDEOGRAPH-F970;Lo;0;L;6BBA;;;;N;;;;; F971;CJK COMPATIBILITY IDEOGRAPH-F971;Lo;0;L;8FB0;;;;N;;;;; F972;CJK COMPATIBILITY IDEOGRAPH-F972;Lo;0;L;6C88;;;;N;;;;; F973;CJK COMPATIBILITY IDEOGRAPH-F973;Lo;0;L;62FE;;;;N;;;;; F974;CJK COMPATIBILITY IDEOGRAPH-F974;Lo;0;L;82E5;;;;N;;;;; F975;CJK COMPATIBILITY IDEOGRAPH-F975;Lo;0;L;63A0;;;;N;;;;; F976;CJK COMPATIBILITY IDEOGRAPH-F976;Lo;0;L;7565;;;;N;;;;; F977;CJK COMPATIBILITY IDEOGRAPH-F977;Lo;0;L;4EAE;;;;N;;;;; F978;CJK COMPATIBILITY IDEOGRAPH-F978;Lo;0;L;5169;;;;N;;;;; F979;CJK COMPATIBILITY IDEOGRAPH-F979;Lo;0;L;51C9;;;;N;;;;; F97A;CJK COMPATIBILITY IDEOGRAPH-F97A;Lo;0;L;6881;;;;N;;;;; F97B;CJK COMPATIBILITY IDEOGRAPH-F97B;Lo;0;L;7CE7;;;;N;;;;; F97C;CJK COMPATIBILITY IDEOGRAPH-F97C;Lo;0;L;826F;;;;N;;;;; F97D;CJK COMPATIBILITY IDEOGRAPH-F97D;Lo;0;L;8AD2;;;;N;;;;; F97E;CJK COMPATIBILITY IDEOGRAPH-F97E;Lo;0;L;91CF;;;;N;;;;; F97F;CJK COMPATIBILITY IDEOGRAPH-F97F;Lo;0;L;52F5;;;;N;;;;; F980;CJK COMPATIBILITY IDEOGRAPH-F980;Lo;0;L;5442;;;;N;;;;; F981;CJK COMPATIBILITY IDEOGRAPH-F981;Lo;0;L;5973;;;;N;;;;; F982;CJK COMPATIBILITY IDEOGRAPH-F982;Lo;0;L;5EEC;;;;N;;;;; F983;CJK COMPATIBILITY IDEOGRAPH-F983;Lo;0;L;65C5;;;;N;;;;; F984;CJK COMPATIBILITY IDEOGRAPH-F984;Lo;0;L;6FFE;;;;N;;;;; F985;CJK COMPATIBILITY IDEOGRAPH-F985;Lo;0;L;792A;;;;N;;;;; F986;CJK COMPATIBILITY IDEOGRAPH-F986;Lo;0;L;95AD;;;;N;;;;; F987;CJK COMPATIBILITY IDEOGRAPH-F987;Lo;0;L;9A6A;;;;N;;;;; F988;CJK COMPATIBILITY IDEOGRAPH-F988;Lo;0;L;9E97;;;;N;;;;; F989;CJK COMPATIBILITY IDEOGRAPH-F989;Lo;0;L;9ECE;;;;N;;;;; F98A;CJK COMPATIBILITY IDEOGRAPH-F98A;Lo;0;L;529B;;;;N;;;;; F98B;CJK COMPATIBILITY IDEOGRAPH-F98B;Lo;0;L;66C6;;;;N;;;;; F98C;CJK COMPATIBILITY IDEOGRAPH-F98C;Lo;0;L;6B77;;;;N;;;;; F98D;CJK COMPATIBILITY IDEOGRAPH-F98D;Lo;0;L;8F62;;;;N;;;;; F98E;CJK COMPATIBILITY IDEOGRAPH-F98E;Lo;0;L;5E74;;;;N;;;;; F98F;CJK COMPATIBILITY IDEOGRAPH-F98F;Lo;0;L;6190;;;;N;;;;; F990;CJK COMPATIBILITY IDEOGRAPH-F990;Lo;0;L;6200;;;;N;;;;; F991;CJK COMPATIBILITY IDEOGRAPH-F991;Lo;0;L;649A;;;;N;;;;; F992;CJK COMPATIBILITY IDEOGRAPH-F992;Lo;0;L;6F23;;;;N;;;;; F993;CJK COMPATIBILITY IDEOGRAPH-F993;Lo;0;L;7149;;;;N;;;;; F994;CJK COMPATIBILITY IDEOGRAPH-F994;Lo;0;L;7489;;;;N;;;;; F995;CJK COMPATIBILITY IDEOGRAPH-F995;Lo;0;L;79CA;;;;N;;;;; F996;CJK COMPATIBILITY IDEOGRAPH-F996;Lo;0;L;7DF4;;;;N;;;;; F997;CJK COMPATIBILITY IDEOGRAPH-F997;Lo;0;L;806F;;;;N;;;;; F998;CJK COMPATIBILITY IDEOGRAPH-F998;Lo;0;L;8F26;;;;N;;;;; F999;CJK COMPATIBILITY IDEOGRAPH-F999;Lo;0;L;84EE;;;;N;;;;; F99A;CJK COMPATIBILITY IDEOGRAPH-F99A;Lo;0;L;9023;;;;N;;;;; F99B;CJK COMPATIBILITY IDEOGRAPH-F99B;Lo;0;L;934A;;;;N;;;;; F99C;CJK COMPATIBILITY IDEOGRAPH-F99C;Lo;0;L;5217;;;;N;;;;; F99D;CJK COMPATIBILITY IDEOGRAPH-F99D;Lo;0;L;52A3;;;;N;;;;; F99E;CJK COMPATIBILITY IDEOGRAPH-F99E;Lo;0;L;54BD;;;;N;;;;; F99F;CJK COMPATIBILITY IDEOGRAPH-F99F;Lo;0;L;70C8;;;;N;;;;; F9A0;CJK COMPATIBILITY IDEOGRAPH-F9A0;Lo;0;L;88C2;;;;N;;;;; F9A1;CJK COMPATIBILITY IDEOGRAPH-F9A1;Lo;0;L;8AAA;;;;N;;;;; F9A2;CJK COMPATIBILITY IDEOGRAPH-F9A2;Lo;0;L;5EC9;;;;N;;;;; F9A3;CJK COMPATIBILITY IDEOGRAPH-F9A3;Lo;0;L;5FF5;;;;N;;;;; F9A4;CJK COMPATIBILITY IDEOGRAPH-F9A4;Lo;0;L;637B;;;;N;;;;; F9A5;CJK COMPATIBILITY IDEOGRAPH-F9A5;Lo;0;L;6BAE;;;;N;;;;; F9A6;CJK COMPATIBILITY IDEOGRAPH-F9A6;Lo;0;L;7C3E;;;;N;;;;; F9A7;CJK COMPATIBILITY IDEOGRAPH-F9A7;Lo;0;L;7375;;;;N;;;;; F9A8;CJK COMPATIBILITY IDEOGRAPH-F9A8;Lo;0;L;4EE4;;;;N;;;;; F9A9;CJK COMPATIBILITY IDEOGRAPH-F9A9;Lo;0;L;56F9;;;;N;;;;; F9AA;CJK COMPATIBILITY IDEOGRAPH-F9AA;Lo;0;L;5BE7;;;;N;;;;; F9AB;CJK COMPATIBILITY IDEOGRAPH-F9AB;Lo;0;L;5DBA;;;;N;;;;; F9AC;CJK COMPATIBILITY IDEOGRAPH-F9AC;Lo;0;L;601C;;;;N;;;;; F9AD;CJK COMPATIBILITY IDEOGRAPH-F9AD;Lo;0;L;73B2;;;;N;;;;; F9AE;CJK COMPATIBILITY IDEOGRAPH-F9AE;Lo;0;L;7469;;;;N;;;;; F9AF;CJK COMPATIBILITY IDEOGRAPH-F9AF;Lo;0;L;7F9A;;;;N;;;;; F9B0;CJK COMPATIBILITY IDEOGRAPH-F9B0;Lo;0;L;8046;;;;N;;;;; F9B1;CJK COMPATIBILITY IDEOGRAPH-F9B1;Lo;0;L;9234;;;;N;;;;; F9B2;CJK COMPATIBILITY IDEOGRAPH-F9B2;Lo;0;L;96F6;;;;N;;;;; F9B3;CJK COMPATIBILITY IDEOGRAPH-F9B3;Lo;0;L;9748;;;;N;;;;; F9B4;CJK COMPATIBILITY IDEOGRAPH-F9B4;Lo;0;L;9818;;;;N;;;;; F9B5;CJK COMPATIBILITY IDEOGRAPH-F9B5;Lo;0;L;4F8B;;;;N;;;;; F9B6;CJK COMPATIBILITY IDEOGRAPH-F9B6;Lo;0;L;79AE;;;;N;;;;; F9B7;CJK COMPATIBILITY IDEOGRAPH-F9B7;Lo;0;L;91B4;;;;N;;;;; F9B8;CJK COMPATIBILITY IDEOGRAPH-F9B8;Lo;0;L;96B8;;;;N;;;;; F9B9;CJK COMPATIBILITY IDEOGRAPH-F9B9;Lo;0;L;60E1;;;;N;;;;; F9BA;CJK COMPATIBILITY IDEOGRAPH-F9BA;Lo;0;L;4E86;;;;N;;;;; F9BB;CJK COMPATIBILITY IDEOGRAPH-F9BB;Lo;0;L;50DA;;;;N;;;;; F9BC;CJK COMPATIBILITY IDEOGRAPH-F9BC;Lo;0;L;5BEE;;;;N;;;;; F9BD;CJK COMPATIBILITY IDEOGRAPH-F9BD;Lo;0;L;5C3F;;;;N;;;;; F9BE;CJK COMPATIBILITY IDEOGRAPH-F9BE;Lo;0;L;6599;;;;N;;;;; F9BF;CJK COMPATIBILITY IDEOGRAPH-F9BF;Lo;0;L;6A02;;;;N;;;;; F9C0;CJK COMPATIBILITY IDEOGRAPH-F9C0;Lo;0;L;71CE;;;;N;;;;; F9C1;CJK COMPATIBILITY IDEOGRAPH-F9C1;Lo;0;L;7642;;;;N;;;;; F9C2;CJK COMPATIBILITY IDEOGRAPH-F9C2;Lo;0;L;84FC;;;;N;;;;; F9C3;CJK COMPATIBILITY IDEOGRAPH-F9C3;Lo;0;L;907C;;;;N;;;;; F9C4;CJK COMPATIBILITY IDEOGRAPH-F9C4;Lo;0;L;9F8D;;;;N;;;;; F9C5;CJK COMPATIBILITY IDEOGRAPH-F9C5;Lo;0;L;6688;;;;N;;;;; F9C6;CJK COMPATIBILITY IDEOGRAPH-F9C6;Lo;0;L;962E;;;;N;;;;; F9C7;CJK COMPATIBILITY IDEOGRAPH-F9C7;Lo;0;L;5289;;;;N;;;;; F9C8;CJK COMPATIBILITY IDEOGRAPH-F9C8;Lo;0;L;677B;;;;N;;;;; F9C9;CJK COMPATIBILITY IDEOGRAPH-F9C9;Lo;0;L;67F3;;;;N;;;;; F9CA;CJK COMPATIBILITY IDEOGRAPH-F9CA;Lo;0;L;6D41;;;;N;;;;; F9CB;CJK COMPATIBILITY IDEOGRAPH-F9CB;Lo;0;L;6E9C;;;;N;;;;; F9CC;CJK COMPATIBILITY IDEOGRAPH-F9CC;Lo;0;L;7409;;;;N;;;;; F9CD;CJK COMPATIBILITY IDEOGRAPH-F9CD;Lo;0;L;7559;;;;N;;;;; F9CE;CJK COMPATIBILITY IDEOGRAPH-F9CE;Lo;0;L;786B;;;;N;;;;; F9CF;CJK COMPATIBILITY IDEOGRAPH-F9CF;Lo;0;L;7D10;;;;N;;;;; F9D0;CJK COMPATIBILITY IDEOGRAPH-F9D0;Lo;0;L;985E;;;;N;;;;; F9D1;CJK COMPATIBILITY IDEOGRAPH-F9D1;Lo;0;L;516D;;;;N;;;;; F9D2;CJK COMPATIBILITY IDEOGRAPH-F9D2;Lo;0;L;622E;;;;N;;;;; F9D3;CJK COMPATIBILITY IDEOGRAPH-F9D3;Lo;0;L;9678;;;;N;;;;; F9D4;CJK COMPATIBILITY IDEOGRAPH-F9D4;Lo;0;L;502B;;;;N;;;;; F9D5;CJK COMPATIBILITY IDEOGRAPH-F9D5;Lo;0;L;5D19;;;;N;;;;; F9D6;CJK COMPATIBILITY IDEOGRAPH-F9D6;Lo;0;L;6DEA;;;;N;;;;; F9D7;CJK COMPATIBILITY IDEOGRAPH-F9D7;Lo;0;L;8F2A;;;;N;;;;; F9D8;CJK COMPATIBILITY IDEOGRAPH-F9D8;Lo;0;L;5F8B;;;;N;;;;; F9D9;CJK COMPATIBILITY IDEOGRAPH-F9D9;Lo;0;L;6144;;;;N;;;;; F9DA;CJK COMPATIBILITY IDEOGRAPH-F9DA;Lo;0;L;6817;;;;N;;;;; F9DB;CJK COMPATIBILITY IDEOGRAPH-F9DB;Lo;0;L;7387;;;;N;;;;; F9DC;CJK COMPATIBILITY IDEOGRAPH-F9DC;Lo;0;L;9686;;;;N;;;;; F9DD;CJK COMPATIBILITY IDEOGRAPH-F9DD;Lo;0;L;5229;;;;N;;;;; F9DE;CJK COMPATIBILITY IDEOGRAPH-F9DE;Lo;0;L;540F;;;;N;;;;; F9DF;CJK COMPATIBILITY IDEOGRAPH-F9DF;Lo;0;L;5C65;;;;N;;;;; F9E0;CJK COMPATIBILITY IDEOGRAPH-F9E0;Lo;0;L;6613;;;;N;;;;; F9E1;CJK COMPATIBILITY IDEOGRAPH-F9E1;Lo;0;L;674E;;;;N;;;;; F9E2;CJK COMPATIBILITY IDEOGRAPH-F9E2;Lo;0;L;68A8;;;;N;;;;; F9E3;CJK COMPATIBILITY IDEOGRAPH-F9E3;Lo;0;L;6CE5;;;;N;;;;; F9E4;CJK COMPATIBILITY IDEOGRAPH-F9E4;Lo;0;L;7406;;;;N;;;;; F9E5;CJK COMPATIBILITY IDEOGRAPH-F9E5;Lo;0;L;75E2;;;;N;;;;; F9E6;CJK COMPATIBILITY IDEOGRAPH-F9E6;Lo;0;L;7F79;;;;N;;;;; F9E7;CJK COMPATIBILITY IDEOGRAPH-F9E7;Lo;0;L;88CF;;;;N;;;;; F9E8;CJK COMPATIBILITY IDEOGRAPH-F9E8;Lo;0;L;88E1;;;;N;;;;; F9E9;CJK COMPATIBILITY IDEOGRAPH-F9E9;Lo;0;L;91CC;;;;N;;;;; F9EA;CJK COMPATIBILITY IDEOGRAPH-F9EA;Lo;0;L;96E2;;;;N;;;;; F9EB;CJK COMPATIBILITY IDEOGRAPH-F9EB;Lo;0;L;533F;;;;N;;;;; F9EC;CJK COMPATIBILITY IDEOGRAPH-F9EC;Lo;0;L;6EBA;;;;N;;;;; F9ED;CJK COMPATIBILITY IDEOGRAPH-F9ED;Lo;0;L;541D;;;;N;;;;; F9EE;CJK COMPATIBILITY IDEOGRAPH-F9EE;Lo;0;L;71D0;;;;N;;;;; F9EF;CJK COMPATIBILITY IDEOGRAPH-F9EF;Lo;0;L;7498;;;;N;;;;; F9F0;CJK COMPATIBILITY IDEOGRAPH-F9F0;Lo;0;L;85FA;;;;N;;;;; F9F1;CJK COMPATIBILITY IDEOGRAPH-F9F1;Lo;0;L;96A3;;;;N;;;;; F9F2;CJK COMPATIBILITY IDEOGRAPH-F9F2;Lo;0;L;9C57;;;;N;;;;; F9F3;CJK COMPATIBILITY IDEOGRAPH-F9F3;Lo;0;L;9E9F;;;;N;;;;; F9F4;CJK COMPATIBILITY IDEOGRAPH-F9F4;Lo;0;L;6797;;;;N;;;;; F9F5;CJK COMPATIBILITY IDEOGRAPH-F9F5;Lo;0;L;6DCB;;;;N;;;;; F9F6;CJK COMPATIBILITY IDEOGRAPH-F9F6;Lo;0;L;81E8;;;;N;;;;; F9F7;CJK COMPATIBILITY IDEOGRAPH-F9F7;Lo;0;L;7ACB;;;;N;;;;; F9F8;CJK COMPATIBILITY IDEOGRAPH-F9F8;Lo;0;L;7B20;;;;N;;;;; F9F9;CJK COMPATIBILITY IDEOGRAPH-F9F9;Lo;0;L;7C92;;;;N;;;;; F9FA;CJK COMPATIBILITY IDEOGRAPH-F9FA;Lo;0;L;72C0;;;;N;;;;; F9FB;CJK COMPATIBILITY IDEOGRAPH-F9FB;Lo;0;L;7099;;;;N;;;;; F9FC;CJK COMPATIBILITY IDEOGRAPH-F9FC;Lo;0;L;8B58;;;;N;;;;; F9FD;CJK COMPATIBILITY IDEOGRAPH-F9FD;Lo;0;L;4EC0;;;;N;;;;; F9FE;CJK COMPATIBILITY IDEOGRAPH-F9FE;Lo;0;L;8336;;;;N;;;;; F9FF;CJK COMPATIBILITY IDEOGRAPH-F9FF;Lo;0;L;523A;;;;N;;;;; FA00;CJK COMPATIBILITY IDEOGRAPH-FA00;Lo;0;L;5207;;;;N;;;;; FA01;CJK COMPATIBILITY IDEOGRAPH-FA01;Lo;0;L;5EA6;;;;N;;;;; FA02;CJK COMPATIBILITY IDEOGRAPH-FA02;Lo;0;L;62D3;;;;N;;;;; FA03;CJK COMPATIBILITY IDEOGRAPH-FA03;Lo;0;L;7CD6;;;;N;;;;; FA04;CJK COMPATIBILITY IDEOGRAPH-FA04;Lo;0;L;5B85;;;;N;;;;; FA05;CJK COMPATIBILITY IDEOGRAPH-FA05;Lo;0;L;6D1E;;;;N;;;;; FA06;CJK COMPATIBILITY IDEOGRAPH-FA06;Lo;0;L;66B4;;;;N;;;;; FA07;CJK COMPATIBILITY IDEOGRAPH-FA07;Lo;0;L;8F3B;;;;N;;;;; FA08;CJK COMPATIBILITY IDEOGRAPH-FA08;Lo;0;L;884C;;;;N;;;;; FA09;CJK COMPATIBILITY IDEOGRAPH-FA09;Lo;0;L;964D;;;;N;;;;; FA0A;CJK COMPATIBILITY IDEOGRAPH-FA0A;Lo;0;L;898B;;;;N;;;;; FA0B;CJK COMPATIBILITY IDEOGRAPH-FA0B;Lo;0;L;5ED3;;;;N;;;;; FA0C;CJK COMPATIBILITY IDEOGRAPH-FA0C;Lo;0;L;5140;;;;N;;;;; FA0D;CJK COMPATIBILITY IDEOGRAPH-FA0D;Lo;0;L;55C0;;;;N;;;;; FA0E;CJK COMPATIBILITY IDEOGRAPH-FA0E;Lo;0;L;;;;;N;;;;; FA0F;CJK COMPATIBILITY IDEOGRAPH-FA0F;Lo;0;L;;;;;N;;;;; FA10;CJK COMPATIBILITY IDEOGRAPH-FA10;Lo;0;L;585A;;;;N;;;;; FA11;CJK COMPATIBILITY IDEOGRAPH-FA11;Lo;0;L;;;;;N;;;;; FA12;CJK COMPATIBILITY IDEOGRAPH-FA12;Lo;0;L;6674;;;;N;;;;; FA13;CJK COMPATIBILITY IDEOGRAPH-FA13;Lo;0;L;;;;;N;;;;; FA14;CJK COMPATIBILITY IDEOGRAPH-FA14;Lo;0;L;;;;;N;;;;; FA15;CJK COMPATIBILITY IDEOGRAPH-FA15;Lo;0;L;51DE;;;;N;;;;; FA16;CJK COMPATIBILITY IDEOGRAPH-FA16;Lo;0;L;732A;;;;N;;;;; FA17;CJK COMPATIBILITY IDEOGRAPH-FA17;Lo;0;L;76CA;;;;N;;;;; FA18;CJK COMPATIBILITY IDEOGRAPH-FA18;Lo;0;L;793C;;;;N;;;;; FA19;CJK COMPATIBILITY IDEOGRAPH-FA19;Lo;0;L;795E;;;;N;;;;; FA1A;CJK COMPATIBILITY IDEOGRAPH-FA1A;Lo;0;L;7965;;;;N;;;;; FA1B;CJK COMPATIBILITY IDEOGRAPH-FA1B;Lo;0;L;798F;;;;N;;;;; FA1C;CJK COMPATIBILITY IDEOGRAPH-FA1C;Lo;0;L;9756;;;;N;;;;; FA1D;CJK COMPATIBILITY IDEOGRAPH-FA1D;Lo;0;L;7CBE;;;;N;;;;; FA1E;CJK COMPATIBILITY IDEOGRAPH-FA1E;Lo;0;L;7FBD;;;;N;;;;; FA1F;CJK COMPATIBILITY IDEOGRAPH-FA1F;Lo;0;L;;;;;N;;*;;; FA20;CJK COMPATIBILITY IDEOGRAPH-FA20;Lo;0;L;8612;;;;N;;;;; FA21;CJK COMPATIBILITY IDEOGRAPH-FA21;Lo;0;L;;;;;N;;;;; FA22;CJK COMPATIBILITY IDEOGRAPH-FA22;Lo;0;L;8AF8;;;;N;;;;; FA23;CJK COMPATIBILITY IDEOGRAPH-FA23;Lo;0;L;;;;;N;;*;;; FA24;CJK COMPATIBILITY IDEOGRAPH-FA24;Lo;0;L;;;;;N;;;;; FA25;CJK COMPATIBILITY IDEOGRAPH-FA25;Lo;0;L;9038;;;;N;;;;; FA26;CJK COMPATIBILITY IDEOGRAPH-FA26;Lo;0;L;90FD;;;;N;;;;; FA27;CJK COMPATIBILITY IDEOGRAPH-FA27;Lo;0;L;;;;;N;;;;; FA28;CJK COMPATIBILITY IDEOGRAPH-FA28;Lo;0;L;;;;;N;;;;; FA29;CJK COMPATIBILITY IDEOGRAPH-FA29;Lo;0;L;;;;;N;;;;; FA2A;CJK COMPATIBILITY IDEOGRAPH-FA2A;Lo;0;L;98EF;;;;N;;;;; FA2B;CJK COMPATIBILITY IDEOGRAPH-FA2B;Lo;0;L;98FC;;;;N;;;;; FA2C;CJK COMPATIBILITY IDEOGRAPH-FA2C;Lo;0;L;9928;;;;N;;;;; FA2D;CJK COMPATIBILITY IDEOGRAPH-FA2D;Lo;0;L;9DB4;;;;N;;;;; FA30;CJK COMPATIBILITY IDEOGRAPH-FA30;Lo;0;L;4FAE;;;;N;;;;; FA31;CJK COMPATIBILITY IDEOGRAPH-FA31;Lo;0;L;50E7;;;;N;;;;; FA32;CJK COMPATIBILITY IDEOGRAPH-FA32;Lo;0;L;514D;;;;N;;;;; FA33;CJK COMPATIBILITY IDEOGRAPH-FA33;Lo;0;L;52C9;;;;N;;;;; FA34;CJK COMPATIBILITY IDEOGRAPH-FA34;Lo;0;L;52E4;;;;N;;;;; FA35;CJK COMPATIBILITY IDEOGRAPH-FA35;Lo;0;L;5351;;;;N;;;;; FA36;CJK COMPATIBILITY IDEOGRAPH-FA36;Lo;0;L;559D;;;;N;;;;; FA37;CJK COMPATIBILITY IDEOGRAPH-FA37;Lo;0;L;5606;;;;N;;;;; FA38;CJK COMPATIBILITY IDEOGRAPH-FA38;Lo;0;L;5668;;;;N;;;;; FA39;CJK COMPATIBILITY IDEOGRAPH-FA39;Lo;0;L;5840;;;;N;;;;; FA3A;CJK COMPATIBILITY IDEOGRAPH-FA3A;Lo;0;L;58A8;;;;N;;;;; FA3B;CJK COMPATIBILITY IDEOGRAPH-FA3B;Lo;0;L;5C64;;;;N;;;;; FA3C;CJK COMPATIBILITY IDEOGRAPH-FA3C;Lo;0;L;5C6E;;;;N;;;;; FA3D;CJK COMPATIBILITY IDEOGRAPH-FA3D;Lo;0;L;6094;;;;N;;;;; FA3E;CJK COMPATIBILITY IDEOGRAPH-FA3E;Lo;0;L;6168;;;;N;;;;; FA3F;CJK COMPATIBILITY IDEOGRAPH-FA3F;Lo;0;L;618E;;;;N;;;;; FA40;CJK COMPATIBILITY IDEOGRAPH-FA40;Lo;0;L;61F2;;;;N;;;;; FA41;CJK COMPATIBILITY IDEOGRAPH-FA41;Lo;0;L;654F;;;;N;;;;; FA42;CJK COMPATIBILITY IDEOGRAPH-FA42;Lo;0;L;65E2;;;;N;;;;; FA43;CJK COMPATIBILITY IDEOGRAPH-FA43;Lo;0;L;6691;;;;N;;;;; FA44;CJK COMPATIBILITY IDEOGRAPH-FA44;Lo;0;L;6885;;;;N;;;;; FA45;CJK COMPATIBILITY IDEOGRAPH-FA45;Lo;0;L;6D77;;;;N;;;;; FA46;CJK COMPATIBILITY IDEOGRAPH-FA46;Lo;0;L;6E1A;;;;N;;;;; FA47;CJK COMPATIBILITY IDEOGRAPH-FA47;Lo;0;L;6F22;;;;N;;;;; FA48;CJK COMPATIBILITY IDEOGRAPH-FA48;Lo;0;L;716E;;;;N;;;;; FA49;CJK COMPATIBILITY IDEOGRAPH-FA49;Lo;0;L;722B;;;;N;;;;; FA4A;CJK COMPATIBILITY IDEOGRAPH-FA4A;Lo;0;L;7422;;;;N;;;;; FA4B;CJK COMPATIBILITY IDEOGRAPH-FA4B;Lo;0;L;7891;;;;N;;;;; FA4C;CJK COMPATIBILITY IDEOGRAPH-FA4C;Lo;0;L;793E;;;;N;;;;; FA4D;CJK COMPATIBILITY IDEOGRAPH-FA4D;Lo;0;L;7949;;;;N;;;;; FA4E;CJK COMPATIBILITY IDEOGRAPH-FA4E;Lo;0;L;7948;;;;N;;;;; FA4F;CJK COMPATIBILITY IDEOGRAPH-FA4F;Lo;0;L;7950;;;;N;;;;; FA50;CJK COMPATIBILITY IDEOGRAPH-FA50;Lo;0;L;7956;;;;N;;;;; FA51;CJK COMPATIBILITY IDEOGRAPH-FA51;Lo;0;L;795D;;;;N;;;;; FA52;CJK COMPATIBILITY IDEOGRAPH-FA52;Lo;0;L;798D;;;;N;;;;; FA53;CJK COMPATIBILITY IDEOGRAPH-FA53;Lo;0;L;798E;;;;N;;;;; FA54;CJK COMPATIBILITY IDEOGRAPH-FA54;Lo;0;L;7A40;;;;N;;;;; FA55;CJK COMPATIBILITY IDEOGRAPH-FA55;Lo;0;L;7A81;;;;N;;;;; FA56;CJK COMPATIBILITY IDEOGRAPH-FA56;Lo;0;L;7BC0;;;;N;;;;; FA57;CJK COMPATIBILITY IDEOGRAPH-FA57;Lo;0;L;7DF4;;;;N;;;;; FA58;CJK COMPATIBILITY IDEOGRAPH-FA58;Lo;0;L;7E09;;;;N;;;;; FA59;CJK COMPATIBILITY IDEOGRAPH-FA59;Lo;0;L;7E41;;;;N;;;;; FA5A;CJK COMPATIBILITY IDEOGRAPH-FA5A;Lo;0;L;7F72;;;;N;;;;; FA5B;CJK COMPATIBILITY IDEOGRAPH-FA5B;Lo;0;L;8005;;;;N;;;;; FA5C;CJK COMPATIBILITY IDEOGRAPH-FA5C;Lo;0;L;81ED;;;;N;;;;; FA5D;CJK COMPATIBILITY IDEOGRAPH-FA5D;Lo;0;L;8279;;;;N;;;;; FA5E;CJK COMPATIBILITY IDEOGRAPH-FA5E;Lo;0;L;8279;;;;N;;;;; FA5F;CJK COMPATIBILITY IDEOGRAPH-FA5F;Lo;0;L;8457;;;;N;;;;; FA60;CJK COMPATIBILITY IDEOGRAPH-FA60;Lo;0;L;8910;;;;N;;;;; FA61;CJK COMPATIBILITY IDEOGRAPH-FA61;Lo;0;L;8996;;;;N;;;;; FA62;CJK COMPATIBILITY IDEOGRAPH-FA62;Lo;0;L;8B01;;;;N;;;;; FA63;CJK COMPATIBILITY IDEOGRAPH-FA63;Lo;0;L;8B39;;;;N;;;;; FA64;CJK COMPATIBILITY IDEOGRAPH-FA64;Lo;0;L;8CD3;;;;N;;;;; FA65;CJK COMPATIBILITY IDEOGRAPH-FA65;Lo;0;L;8D08;;;;N;;;;; FA66;CJK COMPATIBILITY IDEOGRAPH-FA66;Lo;0;L;8FB6;;;;N;;;;; FA67;CJK COMPATIBILITY IDEOGRAPH-FA67;Lo;0;L;9038;;;;N;;;;; FA68;CJK COMPATIBILITY IDEOGRAPH-FA68;Lo;0;L;96E3;;;;N;;;;; FA69;CJK COMPATIBILITY IDEOGRAPH-FA69;Lo;0;L;97FF;;;;N;;;;; FA6A;CJK COMPATIBILITY IDEOGRAPH-FA6A;Lo;0;L;983B;;;;N;;;;; FB00;LATIN SMALL LIGATURE FF;Ll;0;L; 0066 0066;;;;N;;;;; FB01;LATIN SMALL LIGATURE FI;Ll;0;L; 0066 0069;;;;N;;;;; FB02;LATIN SMALL LIGATURE FL;Ll;0;L; 0066 006C;;;;N;;;;; FB03;LATIN SMALL LIGATURE FFI;Ll;0;L; 0066 0066 0069;;;;N;;;;; FB04;LATIN SMALL LIGATURE FFL;Ll;0;L; 0066 0066 006C;;;;N;;;;; FB05;LATIN SMALL LIGATURE LONG S T;Ll;0;L; 017F 0074;;;;N;;;;; FB06;LATIN SMALL LIGATURE ST;Ll;0;L; 0073 0074;;;;N;;;;; FB13;ARMENIAN SMALL LIGATURE MEN NOW;Ll;0;L; 0574 0576;;;;N;;;;; FB14;ARMENIAN SMALL LIGATURE MEN ECH;Ll;0;L; 0574 0565;;;;N;;;;; FB15;ARMENIAN SMALL LIGATURE MEN INI;Ll;0;L; 0574 056B;;;;N;;;;; FB16;ARMENIAN SMALL LIGATURE VEW NOW;Ll;0;L; 057E 0576;;;;N;;;;; FB17;ARMENIAN SMALL LIGATURE MEN XEH;Ll;0;L; 0574 056D;;;;N;;;;; FB1D;HEBREW LETTER YOD WITH HIRIQ;Lo;0;R;05D9 05B4;;;;N;;;;; FB1E;HEBREW POINT JUDEO-SPANISH VARIKA;Mn;26;NSM;;;;;N;HEBREW POINT VARIKA;;;; FB1F;HEBREW LIGATURE YIDDISH YOD YOD PATAH;Lo;0;R;05F2 05B7;;;;N;;;;; FB20;HEBREW LETTER ALTERNATIVE AYIN;Lo;0;R; 05E2;;;;N;;;;; FB21;HEBREW LETTER WIDE ALEF;Lo;0;R; 05D0;;;;N;;;;; FB22;HEBREW LETTER WIDE DALET;Lo;0;R; 05D3;;;;N;;;;; FB23;HEBREW LETTER WIDE HE;Lo;0;R; 05D4;;;;N;;;;; FB24;HEBREW LETTER WIDE KAF;Lo;0;R; 05DB;;;;N;;;;; FB25;HEBREW LETTER WIDE LAMED;Lo;0;R; 05DC;;;;N;;;;; FB26;HEBREW LETTER WIDE FINAL MEM;Lo;0;R; 05DD;;;;N;;;;; FB27;HEBREW LETTER WIDE RESH;Lo;0;R; 05E8;;;;N;;;;; FB28;HEBREW LETTER WIDE TAV;Lo;0;R; 05EA;;;;N;;;;; FB29;HEBREW LETTER ALTERNATIVE PLUS SIGN;Sm;0;ET; 002B;;;;N;;;;; FB2A;HEBREW LETTER SHIN WITH SHIN DOT;Lo;0;R;05E9 05C1;;;;N;;;;; FB2B;HEBREW LETTER SHIN WITH SIN DOT;Lo;0;R;05E9 05C2;;;;N;;;;; FB2C;HEBREW LETTER SHIN WITH DAGESH AND SHIN DOT;Lo;0;R;FB49 05C1;;;;N;;;;; FB2D;HEBREW LETTER SHIN WITH DAGESH AND SIN DOT;Lo;0;R;FB49 05C2;;;;N;;;;; FB2E;HEBREW LETTER ALEF WITH PATAH;Lo;0;R;05D0 05B7;;;;N;;;;; FB2F;HEBREW LETTER ALEF WITH QAMATS;Lo;0;R;05D0 05B8;;;;N;;;;; FB30;HEBREW LETTER ALEF WITH MAPIQ;Lo;0;R;05D0 05BC;;;;N;;;;; FB31;HEBREW LETTER BET WITH DAGESH;Lo;0;R;05D1 05BC;;;;N;;;;; FB32;HEBREW LETTER GIMEL WITH DAGESH;Lo;0;R;05D2 05BC;;;;N;;;;; FB33;HEBREW LETTER DALET WITH DAGESH;Lo;0;R;05D3 05BC;;;;N;;;;; FB34;HEBREW LETTER HE WITH MAPIQ;Lo;0;R;05D4 05BC;;;;N;;;;; FB35;HEBREW LETTER VAV WITH DAGESH;Lo;0;R;05D5 05BC;;;;N;;;;; FB36;HEBREW LETTER ZAYIN WITH DAGESH;Lo;0;R;05D6 05BC;;;;N;;;;; FB38;HEBREW LETTER TET WITH DAGESH;Lo;0;R;05D8 05BC;;;;N;;;;; FB39;HEBREW LETTER YOD WITH DAGESH;Lo;0;R;05D9 05BC;;;;N;;;;; FB3A;HEBREW LETTER FINAL KAF WITH DAGESH;Lo;0;R;05DA 05BC;;;;N;;;;; FB3B;HEBREW LETTER KAF WITH DAGESH;Lo;0;R;05DB 05BC;;;;N;;;;; FB3C;HEBREW LETTER LAMED WITH DAGESH;Lo;0;R;05DC 05BC;;;;N;;;;; FB3E;HEBREW LETTER MEM WITH DAGESH;Lo;0;R;05DE 05BC;;;;N;;;;; FB40;HEBREW LETTER NUN WITH DAGESH;Lo;0;R;05E0 05BC;;;;N;;;;; FB41;HEBREW LETTER SAMEKH WITH DAGESH;Lo;0;R;05E1 05BC;;;;N;;;;; FB43;HEBREW LETTER FINAL PE WITH DAGESH;Lo;0;R;05E3 05BC;;;;N;;;;; FB44;HEBREW LETTER PE WITH DAGESH;Lo;0;R;05E4 05BC;;;;N;;;;; FB46;HEBREW LETTER TSADI WITH DAGESH;Lo;0;R;05E6 05BC;;;;N;;;;; FB47;HEBREW LETTER QOF WITH DAGESH;Lo;0;R;05E7 05BC;;;;N;;;;; FB48;HEBREW LETTER RESH WITH DAGESH;Lo;0;R;05E8 05BC;;;;N;;;;; FB49;HEBREW LETTER SHIN WITH DAGESH;Lo;0;R;05E9 05BC;;;;N;;;;; FB4A;HEBREW LETTER TAV WITH DAGESH;Lo;0;R;05EA 05BC;;;;N;;;;; FB4B;HEBREW LETTER VAV WITH HOLAM;Lo;0;R;05D5 05B9;;;;N;;;;; FB4C;HEBREW LETTER BET WITH RAFE;Lo;0;R;05D1 05BF;;;;N;;;;; FB4D;HEBREW LETTER KAF WITH RAFE;Lo;0;R;05DB 05BF;;;;N;;;;; FB4E;HEBREW LETTER PE WITH RAFE;Lo;0;R;05E4 05BF;;;;N;;;;; FB4F;HEBREW LIGATURE ALEF LAMED;Lo;0;R; 05D0 05DC;;;;N;;;;; FB50;ARABIC LETTER ALEF WASLA ISOLATED FORM;Lo;0;AL; 0671;;;;N;;;;; FB51;ARABIC LETTER ALEF WASLA FINAL FORM;Lo;0;AL; 0671;;;;N;;;;; FB52;ARABIC LETTER BEEH ISOLATED FORM;Lo;0;AL; 067B;;;;N;;;;; FB53;ARABIC LETTER BEEH FINAL FORM;Lo;0;AL; 067B;;;;N;;;;; FB54;ARABIC LETTER BEEH INITIAL FORM;Lo;0;AL; 067B;;;;N;;;;; FB55;ARABIC LETTER BEEH MEDIAL FORM;Lo;0;AL; 067B;;;;N;;;;; FB56;ARABIC LETTER PEH ISOLATED FORM;Lo;0;AL; 067E;;;;N;;;;; FB57;ARABIC LETTER PEH FINAL FORM;Lo;0;AL; 067E;;;;N;;;;; FB58;ARABIC LETTER PEH INITIAL FORM;Lo;0;AL; 067E;;;;N;;;;; FB59;ARABIC LETTER PEH MEDIAL FORM;Lo;0;AL; 067E;;;;N;;;;; FB5A;ARABIC LETTER BEHEH ISOLATED FORM;Lo;0;AL; 0680;;;;N;;;;; FB5B;ARABIC LETTER BEHEH FINAL FORM;Lo;0;AL; 0680;;;;N;;;;; FB5C;ARABIC LETTER BEHEH INITIAL FORM;Lo;0;AL; 0680;;;;N;;;;; FB5D;ARABIC LETTER BEHEH MEDIAL FORM;Lo;0;AL; 0680;;;;N;;;;; FB5E;ARABIC LETTER TTEHEH ISOLATED FORM;Lo;0;AL; 067A;;;;N;;;;; FB5F;ARABIC LETTER TTEHEH FINAL FORM;Lo;0;AL; 067A;;;;N;;;;; FB60;ARABIC LETTER TTEHEH INITIAL FORM;Lo;0;AL; 067A;;;;N;;;;; FB61;ARABIC LETTER TTEHEH MEDIAL FORM;Lo;0;AL; 067A;;;;N;;;;; FB62;ARABIC LETTER TEHEH ISOLATED FORM;Lo;0;AL; 067F;;;;N;;;;; FB63;ARABIC LETTER TEHEH FINAL FORM;Lo;0;AL; 067F;;;;N;;;;; FB64;ARABIC LETTER TEHEH INITIAL FORM;Lo;0;AL; 067F;;;;N;;;;; FB65;ARABIC LETTER TEHEH MEDIAL FORM;Lo;0;AL; 067F;;;;N;;;;; FB66;ARABIC LETTER TTEH ISOLATED FORM;Lo;0;AL; 0679;;;;N;;;;; FB67;ARABIC LETTER TTEH FINAL FORM;Lo;0;AL; 0679;;;;N;;;;; FB68;ARABIC LETTER TTEH INITIAL FORM;Lo;0;AL; 0679;;;;N;;;;; FB69;ARABIC LETTER TTEH MEDIAL FORM;Lo;0;AL; 0679;;;;N;;;;; FB6A;ARABIC LETTER VEH ISOLATED FORM;Lo;0;AL; 06A4;;;;N;;;;; FB6B;ARABIC LETTER VEH FINAL FORM;Lo;0;AL; 06A4;;;;N;;;;; FB6C;ARABIC LETTER VEH INITIAL FORM;Lo;0;AL; 06A4;;;;N;;;;; FB6D;ARABIC LETTER VEH MEDIAL FORM;Lo;0;AL; 06A4;;;;N;;;;; FB6E;ARABIC LETTER PEHEH ISOLATED FORM;Lo;0;AL; 06A6;;;;N;;;;; FB6F;ARABIC LETTER PEHEH FINAL FORM;Lo;0;AL; 06A6;;;;N;;;;; FB70;ARABIC LETTER PEHEH INITIAL FORM;Lo;0;AL; 06A6;;;;N;;;;; FB71;ARABIC LETTER PEHEH MEDIAL FORM;Lo;0;AL; 06A6;;;;N;;;;; FB72;ARABIC LETTER DYEH ISOLATED FORM;Lo;0;AL; 0684;;;;N;;;;; FB73;ARABIC LETTER DYEH FINAL FORM;Lo;0;AL; 0684;;;;N;;;;; FB74;ARABIC LETTER DYEH INITIAL FORM;Lo;0;AL; 0684;;;;N;;;;; FB75;ARABIC LETTER DYEH MEDIAL FORM;Lo;0;AL; 0684;;;;N;;;;; FB76;ARABIC LETTER NYEH ISOLATED FORM;Lo;0;AL; 0683;;;;N;;;;; FB77;ARABIC LETTER NYEH FINAL FORM;Lo;0;AL; 0683;;;;N;;;;; FB78;ARABIC LETTER NYEH INITIAL FORM;Lo;0;AL; 0683;;;;N;;;;; FB79;ARABIC LETTER NYEH MEDIAL FORM;Lo;0;AL; 0683;;;;N;;;;; FB7A;ARABIC LETTER TCHEH ISOLATED FORM;Lo;0;AL; 0686;;;;N;;;;; FB7B;ARABIC LETTER TCHEH FINAL FORM;Lo;0;AL; 0686;;;;N;;;;; FB7C;ARABIC LETTER TCHEH INITIAL FORM;Lo;0;AL; 0686;;;;N;;;;; FB7D;ARABIC LETTER TCHEH MEDIAL FORM;Lo;0;AL; 0686;;;;N;;;;; FB7E;ARABIC LETTER TCHEHEH ISOLATED FORM;Lo;0;AL; 0687;;;;N;;;;; FB7F;ARABIC LETTER TCHEHEH FINAL FORM;Lo;0;AL; 0687;;;;N;;;;; FB80;ARABIC LETTER TCHEHEH INITIAL FORM;Lo;0;AL; 0687;;;;N;;;;; FB81;ARABIC LETTER TCHEHEH MEDIAL FORM;Lo;0;AL; 0687;;;;N;;;;; FB82;ARABIC LETTER DDAHAL ISOLATED FORM;Lo;0;AL; 068D;;;;N;;;;; FB83;ARABIC LETTER DDAHAL FINAL FORM;Lo;0;AL; 068D;;;;N;;;;; FB84;ARABIC LETTER DAHAL ISOLATED FORM;Lo;0;AL; 068C;;;;N;;;;; FB85;ARABIC LETTER DAHAL FINAL FORM;Lo;0;AL; 068C;;;;N;;;;; FB86;ARABIC LETTER DUL ISOLATED FORM;Lo;0;AL; 068E;;;;N;;;;; FB87;ARABIC LETTER DUL FINAL FORM;Lo;0;AL; 068E;;;;N;;;;; FB88;ARABIC LETTER DDAL ISOLATED FORM;Lo;0;AL; 0688;;;;N;;;;; FB89;ARABIC LETTER DDAL FINAL FORM;Lo;0;AL; 0688;;;;N;;;;; FB8A;ARABIC LETTER JEH ISOLATED FORM;Lo;0;AL; 0698;;;;N;;;;; FB8B;ARABIC LETTER JEH FINAL FORM;Lo;0;AL; 0698;;;;N;;;;; FB8C;ARABIC LETTER RREH ISOLATED FORM;Lo;0;AL; 0691;;;;N;;;;; FB8D;ARABIC LETTER RREH FINAL FORM;Lo;0;AL; 0691;;;;N;;;;; FB8E;ARABIC LETTER KEHEH ISOLATED FORM;Lo;0;AL; 06A9;;;;N;;;;; FB8F;ARABIC LETTER KEHEH FINAL FORM;Lo;0;AL; 06A9;;;;N;;;;; FB90;ARABIC LETTER KEHEH INITIAL FORM;Lo;0;AL; 06A9;;;;N;;;;; FB91;ARABIC LETTER KEHEH MEDIAL FORM;Lo;0;AL; 06A9;;;;N;;;;; FB92;ARABIC LETTER GAF ISOLATED FORM;Lo;0;AL; 06AF;;;;N;;;;; FB93;ARABIC LETTER GAF FINAL FORM;Lo;0;AL; 06AF;;;;N;;;;; FB94;ARABIC LETTER GAF INITIAL FORM;Lo;0;AL; 06AF;;;;N;;;;; FB95;ARABIC LETTER GAF MEDIAL FORM;Lo;0;AL; 06AF;;;;N;;;;; FB96;ARABIC LETTER GUEH ISOLATED FORM;Lo;0;AL; 06B3;;;;N;;;;; FB97;ARABIC LETTER GUEH FINAL FORM;Lo;0;AL; 06B3;;;;N;;;;; FB98;ARABIC LETTER GUEH INITIAL FORM;Lo;0;AL; 06B3;;;;N;;;;; FB99;ARABIC LETTER GUEH MEDIAL FORM;Lo;0;AL; 06B3;;;;N;;;;; FB9A;ARABIC LETTER NGOEH ISOLATED FORM;Lo;0;AL; 06B1;;;;N;;;;; FB9B;ARABIC LETTER NGOEH FINAL FORM;Lo;0;AL; 06B1;;;;N;;;;; FB9C;ARABIC LETTER NGOEH INITIAL FORM;Lo;0;AL; 06B1;;;;N;;;;; FB9D;ARABIC LETTER NGOEH MEDIAL FORM;Lo;0;AL; 06B1;;;;N;;;;; FB9E;ARABIC LETTER NOON GHUNNA ISOLATED FORM;Lo;0;AL; 06BA;;;;N;;;;; FB9F;ARABIC LETTER NOON GHUNNA FINAL FORM;Lo;0;AL; 06BA;;;;N;;;;; FBA0;ARABIC LETTER RNOON ISOLATED FORM;Lo;0;AL; 06BB;;;;N;;;;; FBA1;ARABIC LETTER RNOON FINAL FORM;Lo;0;AL; 06BB;;;;N;;;;; FBA2;ARABIC LETTER RNOON INITIAL FORM;Lo;0;AL; 06BB;;;;N;;;;; FBA3;ARABIC LETTER RNOON MEDIAL FORM;Lo;0;AL; 06BB;;;;N;;;;; FBA4;ARABIC LETTER HEH WITH YEH ABOVE ISOLATED FORM;Lo;0;AL; 06C0;;;;N;;;;; FBA5;ARABIC LETTER HEH WITH YEH ABOVE FINAL FORM;Lo;0;AL; 06C0;;;;N;;;;; FBA6;ARABIC LETTER HEH GOAL ISOLATED FORM;Lo;0;AL; 06C1;;;;N;;;;; FBA7;ARABIC LETTER HEH GOAL FINAL FORM;Lo;0;AL; 06C1;;;;N;;;;; FBA8;ARABIC LETTER HEH GOAL INITIAL FORM;Lo;0;AL; 06C1;;;;N;;;;; FBA9;ARABIC LETTER HEH GOAL MEDIAL FORM;Lo;0;AL; 06C1;;;;N;;;;; FBAA;ARABIC LETTER HEH DOACHASHMEE ISOLATED FORM;Lo;0;AL; 06BE;;;;N;;;;; FBAB;ARABIC LETTER HEH DOACHASHMEE FINAL FORM;Lo;0;AL; 06BE;;;;N;;;;; FBAC;ARABIC LETTER HEH DOACHASHMEE INITIAL FORM;Lo;0;AL; 06BE;;;;N;;;;; FBAD;ARABIC LETTER HEH DOACHASHMEE MEDIAL FORM;Lo;0;AL; 06BE;;;;N;;;;; FBAE;ARABIC LETTER YEH BARREE ISOLATED FORM;Lo;0;AL; 06D2;;;;N;;;;; FBAF;ARABIC LETTER YEH BARREE FINAL FORM;Lo;0;AL; 06D2;;;;N;;;;; FBB0;ARABIC LETTER YEH BARREE WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL; 06D3;;;;N;;;;; FBB1;ARABIC LETTER YEH BARREE WITH HAMZA ABOVE FINAL FORM;Lo;0;AL; 06D3;;;;N;;;;; FBD3;ARABIC LETTER NG ISOLATED FORM;Lo;0;AL; 06AD;;;;N;;;;; FBD4;ARABIC LETTER NG FINAL FORM;Lo;0;AL; 06AD;;;;N;;;;; FBD5;ARABIC LETTER NG INITIAL FORM;Lo;0;AL; 06AD;;;;N;;;;; FBD6;ARABIC LETTER NG MEDIAL FORM;Lo;0;AL; 06AD;;;;N;;;;; FBD7;ARABIC LETTER U ISOLATED FORM;Lo;0;AL; 06C7;;;;N;;;;; FBD8;ARABIC LETTER U FINAL FORM;Lo;0;AL; 06C7;;;;N;;;;; FBD9;ARABIC LETTER OE ISOLATED FORM;Lo;0;AL; 06C6;;;;N;;;;; FBDA;ARABIC LETTER OE FINAL FORM;Lo;0;AL; 06C6;;;;N;;;;; FBDB;ARABIC LETTER YU ISOLATED FORM;Lo;0;AL; 06C8;;;;N;;;;; FBDC;ARABIC LETTER YU FINAL FORM;Lo;0;AL; 06C8;;;;N;;;;; FBDD;ARABIC LETTER U WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL; 0677;;;;N;;;;; FBDE;ARABIC LETTER VE ISOLATED FORM;Lo;0;AL; 06CB;;;;N;;;;; FBDF;ARABIC LETTER VE FINAL FORM;Lo;0;AL; 06CB;;;;N;;;;; FBE0;ARABIC LETTER KIRGHIZ OE ISOLATED FORM;Lo;0;AL; 06C5;;;;N;;;;; FBE1;ARABIC LETTER KIRGHIZ OE FINAL FORM;Lo;0;AL; 06C5;;;;N;;;;; FBE2;ARABIC LETTER KIRGHIZ YU ISOLATED FORM;Lo;0;AL; 06C9;;;;N;;;;; FBE3;ARABIC LETTER KIRGHIZ YU FINAL FORM;Lo;0;AL; 06C9;;;;N;;;;; FBE4;ARABIC LETTER E ISOLATED FORM;Lo;0;AL; 06D0;;;;N;;;;; FBE5;ARABIC LETTER E FINAL FORM;Lo;0;AL; 06D0;;;;N;;;;; FBE6;ARABIC LETTER E INITIAL FORM;Lo;0;AL; 06D0;;;;N;;;;; FBE7;ARABIC LETTER E MEDIAL FORM;Lo;0;AL; 06D0;;;;N;;;;; FBE8;ARABIC LETTER UIGHUR KAZAKH KIRGHIZ ALEF MAKSURA INITIAL FORM;Lo;0;AL; 0649;;;;N;;;;; FBE9;ARABIC LETTER UIGHUR KAZAKH KIRGHIZ ALEF MAKSURA MEDIAL FORM;Lo;0;AL; 0649;;;;N;;;;; FBEA;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF ISOLATED FORM;Lo;0;AL; 0626 0627;;;;N;;;;; FBEB;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF FINAL FORM;Lo;0;AL; 0626 0627;;;;N;;;;; FBEC;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH AE ISOLATED FORM;Lo;0;AL; 0626 06D5;;;;N;;;;; FBED;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH AE FINAL FORM;Lo;0;AL; 0626 06D5;;;;N;;;;; FBEE;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH WAW ISOLATED FORM;Lo;0;AL; 0626 0648;;;;N;;;;; FBEF;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH WAW FINAL FORM;Lo;0;AL; 0626 0648;;;;N;;;;; FBF0;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH U ISOLATED FORM;Lo;0;AL; 0626 06C7;;;;N;;;;; FBF1;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH U FINAL FORM;Lo;0;AL; 0626 06C7;;;;N;;;;; FBF2;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH OE ISOLATED FORM;Lo;0;AL; 0626 06C6;;;;N;;;;; FBF3;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH OE FINAL FORM;Lo;0;AL; 0626 06C6;;;;N;;;;; FBF4;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YU ISOLATED FORM;Lo;0;AL; 0626 06C8;;;;N;;;;; FBF5;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YU FINAL FORM;Lo;0;AL; 0626 06C8;;;;N;;;;; FBF6;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH E ISOLATED FORM;Lo;0;AL; 0626 06D0;;;;N;;;;; FBF7;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH E FINAL FORM;Lo;0;AL; 0626 06D0;;;;N;;;;; FBF8;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH E INITIAL FORM;Lo;0;AL; 0626 06D0;;;;N;;;;; FBF9;ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0626 0649;;;;N;;;;; FBFA;ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0626 0649;;;;N;;;;; FBFB;ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA INITIAL FORM;Lo;0;AL; 0626 0649;;;;N;;;;; FBFC;ARABIC LETTER FARSI YEH ISOLATED FORM;Lo;0;AL; 06CC;;;;N;;;;; FBFD;ARABIC LETTER FARSI YEH FINAL FORM;Lo;0;AL; 06CC;;;;N;;;;; FBFE;ARABIC LETTER FARSI YEH INITIAL FORM;Lo;0;AL; 06CC;;;;N;;;;; FBFF;ARABIC LETTER FARSI YEH MEDIAL FORM;Lo;0;AL; 06CC;;;;N;;;;; FC00;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH JEEM ISOLATED FORM;Lo;0;AL; 0626 062C;;;;N;;;;; FC01;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HAH ISOLATED FORM;Lo;0;AL; 0626 062D;;;;N;;;;; FC02;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM ISOLATED FORM;Lo;0;AL; 0626 0645;;;;N;;;;; FC03;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0626 0649;;;;N;;;;; FC04;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YEH ISOLATED FORM;Lo;0;AL; 0626 064A;;;;N;;;;; FC05;ARABIC LIGATURE BEH WITH JEEM ISOLATED FORM;Lo;0;AL; 0628 062C;;;;N;;;;; FC06;ARABIC LIGATURE BEH WITH HAH ISOLATED FORM;Lo;0;AL; 0628 062D;;;;N;;;;; FC07;ARABIC LIGATURE BEH WITH KHAH ISOLATED FORM;Lo;0;AL; 0628 062E;;;;N;;;;; FC08;ARABIC LIGATURE BEH WITH MEEM ISOLATED FORM;Lo;0;AL; 0628 0645;;;;N;;;;; FC09;ARABIC LIGATURE BEH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0628 0649;;;;N;;;;; FC0A;ARABIC LIGATURE BEH WITH YEH ISOLATED FORM;Lo;0;AL; 0628 064A;;;;N;;;;; FC0B;ARABIC LIGATURE TEH WITH JEEM ISOLATED FORM;Lo;0;AL; 062A 062C;;;;N;;;;; FC0C;ARABIC LIGATURE TEH WITH HAH ISOLATED FORM;Lo;0;AL; 062A 062D;;;;N;;;;; FC0D;ARABIC LIGATURE TEH WITH KHAH ISOLATED FORM;Lo;0;AL; 062A 062E;;;;N;;;;; FC0E;ARABIC LIGATURE TEH WITH MEEM ISOLATED FORM;Lo;0;AL; 062A 0645;;;;N;;;;; FC0F;ARABIC LIGATURE TEH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 062A 0649;;;;N;;;;; FC10;ARABIC LIGATURE TEH WITH YEH ISOLATED FORM;Lo;0;AL; 062A 064A;;;;N;;;;; FC11;ARABIC LIGATURE THEH WITH JEEM ISOLATED FORM;Lo;0;AL; 062B 062C;;;;N;;;;; FC12;ARABIC LIGATURE THEH WITH MEEM ISOLATED FORM;Lo;0;AL; 062B 0645;;;;N;;;;; FC13;ARABIC LIGATURE THEH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 062B 0649;;;;N;;;;; FC14;ARABIC LIGATURE THEH WITH YEH ISOLATED FORM;Lo;0;AL; 062B 064A;;;;N;;;;; FC15;ARABIC LIGATURE JEEM WITH HAH ISOLATED FORM;Lo;0;AL; 062C 062D;;;;N;;;;; FC16;ARABIC LIGATURE JEEM WITH MEEM ISOLATED FORM;Lo;0;AL; 062C 0645;;;;N;;;;; FC17;ARABIC LIGATURE HAH WITH JEEM ISOLATED FORM;Lo;0;AL; 062D 062C;;;;N;;;;; FC18;ARABIC LIGATURE HAH WITH MEEM ISOLATED FORM;Lo;0;AL; 062D 0645;;;;N;;;;; FC19;ARABIC LIGATURE KHAH WITH JEEM ISOLATED FORM;Lo;0;AL; 062E 062C;;;;N;;;;; FC1A;ARABIC LIGATURE KHAH WITH HAH ISOLATED FORM;Lo;0;AL; 062E 062D;;;;N;;;;; FC1B;ARABIC LIGATURE KHAH WITH MEEM ISOLATED FORM;Lo;0;AL; 062E 0645;;;;N;;;;; FC1C;ARABIC LIGATURE SEEN WITH JEEM ISOLATED FORM;Lo;0;AL; 0633 062C;;;;N;;;;; FC1D;ARABIC LIGATURE SEEN WITH HAH ISOLATED FORM;Lo;0;AL; 0633 062D;;;;N;;;;; FC1E;ARABIC LIGATURE SEEN WITH KHAH ISOLATED FORM;Lo;0;AL; 0633 062E;;;;N;;;;; FC1F;ARABIC LIGATURE SEEN WITH MEEM ISOLATED FORM;Lo;0;AL; 0633 0645;;;;N;;;;; FC20;ARABIC LIGATURE SAD WITH HAH ISOLATED FORM;Lo;0;AL; 0635 062D;;;;N;;;;; FC21;ARABIC LIGATURE SAD WITH MEEM ISOLATED FORM;Lo;0;AL; 0635 0645;;;;N;;;;; FC22;ARABIC LIGATURE DAD WITH JEEM ISOLATED FORM;Lo;0;AL; 0636 062C;;;;N;;;;; FC23;ARABIC LIGATURE DAD WITH HAH ISOLATED FORM;Lo;0;AL; 0636 062D;;;;N;;;;; FC24;ARABIC LIGATURE DAD WITH KHAH ISOLATED FORM;Lo;0;AL; 0636 062E;;;;N;;;;; FC25;ARABIC LIGATURE DAD WITH MEEM ISOLATED FORM;Lo;0;AL; 0636 0645;;;;N;;;;; FC26;ARABIC LIGATURE TAH WITH HAH ISOLATED FORM;Lo;0;AL; 0637 062D;;;;N;;;;; FC27;ARABIC LIGATURE TAH WITH MEEM ISOLATED FORM;Lo;0;AL; 0637 0645;;;;N;;;;; FC28;ARABIC LIGATURE ZAH WITH MEEM ISOLATED FORM;Lo;0;AL; 0638 0645;;;;N;;;;; FC29;ARABIC LIGATURE AIN WITH JEEM ISOLATED FORM;Lo;0;AL; 0639 062C;;;;N;;;;; FC2A;ARABIC LIGATURE AIN WITH MEEM ISOLATED FORM;Lo;0;AL; 0639 0645;;;;N;;;;; FC2B;ARABIC LIGATURE GHAIN WITH JEEM ISOLATED FORM;Lo;0;AL; 063A 062C;;;;N;;;;; FC2C;ARABIC LIGATURE GHAIN WITH MEEM ISOLATED FORM;Lo;0;AL; 063A 0645;;;;N;;;;; FC2D;ARABIC LIGATURE FEH WITH JEEM ISOLATED FORM;Lo;0;AL; 0641 062C;;;;N;;;;; FC2E;ARABIC LIGATURE FEH WITH HAH ISOLATED FORM;Lo;0;AL; 0641 062D;;;;N;;;;; FC2F;ARABIC LIGATURE FEH WITH KHAH ISOLATED FORM;Lo;0;AL; 0641 062E;;;;N;;;;; FC30;ARABIC LIGATURE FEH WITH MEEM ISOLATED FORM;Lo;0;AL; 0641 0645;;;;N;;;;; FC31;ARABIC LIGATURE FEH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0641 0649;;;;N;;;;; FC32;ARABIC LIGATURE FEH WITH YEH ISOLATED FORM;Lo;0;AL; 0641 064A;;;;N;;;;; FC33;ARABIC LIGATURE QAF WITH HAH ISOLATED FORM;Lo;0;AL; 0642 062D;;;;N;;;;; FC34;ARABIC LIGATURE QAF WITH MEEM ISOLATED FORM;Lo;0;AL; 0642 0645;;;;N;;;;; FC35;ARABIC LIGATURE QAF WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0642 0649;;;;N;;;;; FC36;ARABIC LIGATURE QAF WITH YEH ISOLATED FORM;Lo;0;AL; 0642 064A;;;;N;;;;; FC37;ARABIC LIGATURE KAF WITH ALEF ISOLATED FORM;Lo;0;AL; 0643 0627;;;;N;;;;; FC38;ARABIC LIGATURE KAF WITH JEEM ISOLATED FORM;Lo;0;AL; 0643 062C;;;;N;;;;; FC39;ARABIC LIGATURE KAF WITH HAH ISOLATED FORM;Lo;0;AL; 0643 062D;;;;N;;;;; FC3A;ARABIC LIGATURE KAF WITH KHAH ISOLATED FORM;Lo;0;AL; 0643 062E;;;;N;;;;; FC3B;ARABIC LIGATURE KAF WITH LAM ISOLATED FORM;Lo;0;AL; 0643 0644;;;;N;;;;; FC3C;ARABIC LIGATURE KAF WITH MEEM ISOLATED FORM;Lo;0;AL; 0643 0645;;;;N;;;;; FC3D;ARABIC LIGATURE KAF WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0643 0649;;;;N;;;;; FC3E;ARABIC LIGATURE KAF WITH YEH ISOLATED FORM;Lo;0;AL; 0643 064A;;;;N;;;;; FC3F;ARABIC LIGATURE LAM WITH JEEM ISOLATED FORM;Lo;0;AL; 0644 062C;;;;N;;;;; FC40;ARABIC LIGATURE LAM WITH HAH ISOLATED FORM;Lo;0;AL; 0644 062D;;;;N;;;;; FC41;ARABIC LIGATURE LAM WITH KHAH ISOLATED FORM;Lo;0;AL; 0644 062E;;;;N;;;;; FC42;ARABIC LIGATURE LAM WITH MEEM ISOLATED FORM;Lo;0;AL; 0644 0645;;;;N;;;;; FC43;ARABIC LIGATURE LAM WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0644 0649;;;;N;;;;; FC44;ARABIC LIGATURE LAM WITH YEH ISOLATED FORM;Lo;0;AL; 0644 064A;;;;N;;;;; FC45;ARABIC LIGATURE MEEM WITH JEEM ISOLATED FORM;Lo;0;AL; 0645 062C;;;;N;;;;; FC46;ARABIC LIGATURE MEEM WITH HAH ISOLATED FORM;Lo;0;AL; 0645 062D;;;;N;;;;; FC47;ARABIC LIGATURE MEEM WITH KHAH ISOLATED FORM;Lo;0;AL; 0645 062E;;;;N;;;;; FC48;ARABIC LIGATURE MEEM WITH MEEM ISOLATED FORM;Lo;0;AL; 0645 0645;;;;N;;;;; FC49;ARABIC LIGATURE MEEM WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0645 0649;;;;N;;;;; FC4A;ARABIC LIGATURE MEEM WITH YEH ISOLATED FORM;Lo;0;AL; 0645 064A;;;;N;;;;; FC4B;ARABIC LIGATURE NOON WITH JEEM ISOLATED FORM;Lo;0;AL; 0646 062C;;;;N;;;;; FC4C;ARABIC LIGATURE NOON WITH HAH ISOLATED FORM;Lo;0;AL; 0646 062D;;;;N;;;;; FC4D;ARABIC LIGATURE NOON WITH KHAH ISOLATED FORM;Lo;0;AL; 0646 062E;;;;N;;;;; FC4E;ARABIC LIGATURE NOON WITH MEEM ISOLATED FORM;Lo;0;AL; 0646 0645;;;;N;;;;; FC4F;ARABIC LIGATURE NOON WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0646 0649;;;;N;;;;; FC50;ARABIC LIGATURE NOON WITH YEH ISOLATED FORM;Lo;0;AL; 0646 064A;;;;N;;;;; FC51;ARABIC LIGATURE HEH WITH JEEM ISOLATED FORM;Lo;0;AL; 0647 062C;;;;N;;;;; FC52;ARABIC LIGATURE HEH WITH MEEM ISOLATED FORM;Lo;0;AL; 0647 0645;;;;N;;;;; FC53;ARABIC LIGATURE HEH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0647 0649;;;;N;;;;; FC54;ARABIC LIGATURE HEH WITH YEH ISOLATED FORM;Lo;0;AL; 0647 064A;;;;N;;;;; FC55;ARABIC LIGATURE YEH WITH JEEM ISOLATED FORM;Lo;0;AL; 064A 062C;;;;N;;;;; FC56;ARABIC LIGATURE YEH WITH HAH ISOLATED FORM;Lo;0;AL; 064A 062D;;;;N;;;;; FC57;ARABIC LIGATURE YEH WITH KHAH ISOLATED FORM;Lo;0;AL; 064A 062E;;;;N;;;;; FC58;ARABIC LIGATURE YEH WITH MEEM ISOLATED FORM;Lo;0;AL; 064A 0645;;;;N;;;;; FC59;ARABIC LIGATURE YEH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 064A 0649;;;;N;;;;; FC5A;ARABIC LIGATURE YEH WITH YEH ISOLATED FORM;Lo;0;AL; 064A 064A;;;;N;;;;; FC5B;ARABIC LIGATURE THAL WITH SUPERSCRIPT ALEF ISOLATED FORM;Lo;0;AL; 0630 0670;;;;N;;;;; FC5C;ARABIC LIGATURE REH WITH SUPERSCRIPT ALEF ISOLATED FORM;Lo;0;AL; 0631 0670;;;;N;;;;; FC5D;ARABIC LIGATURE ALEF MAKSURA WITH SUPERSCRIPT ALEF ISOLATED FORM;Lo;0;AL; 0649 0670;;;;N;;;;; FC5E;ARABIC LIGATURE SHADDA WITH DAMMATAN ISOLATED FORM;Lo;0;AL; 0020 064C 0651;;;;N;;;;; FC5F;ARABIC LIGATURE SHADDA WITH KASRATAN ISOLATED FORM;Lo;0;AL; 0020 064D 0651;;;;N;;;;; FC60;ARABIC LIGATURE SHADDA WITH FATHA ISOLATED FORM;Lo;0;AL; 0020 064E 0651;;;;N;;;;; FC61;ARABIC LIGATURE SHADDA WITH DAMMA ISOLATED FORM;Lo;0;AL; 0020 064F 0651;;;;N;;;;; FC62;ARABIC LIGATURE SHADDA WITH KASRA ISOLATED FORM;Lo;0;AL; 0020 0650 0651;;;;N;;;;; FC63;ARABIC LIGATURE SHADDA WITH SUPERSCRIPT ALEF ISOLATED FORM;Lo;0;AL; 0020 0651 0670;;;;N;;;;; FC64;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH REH FINAL FORM;Lo;0;AL; 0626 0631;;;;N;;;;; FC65;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ZAIN FINAL FORM;Lo;0;AL; 0626 0632;;;;N;;;;; FC66;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM FINAL FORM;Lo;0;AL; 0626 0645;;;;N;;;;; FC67;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH NOON FINAL FORM;Lo;0;AL; 0626 0646;;;;N;;;;; FC68;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0626 0649;;;;N;;;;; FC69;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YEH FINAL FORM;Lo;0;AL; 0626 064A;;;;N;;;;; FC6A;ARABIC LIGATURE BEH WITH REH FINAL FORM;Lo;0;AL; 0628 0631;;;;N;;;;; FC6B;ARABIC LIGATURE BEH WITH ZAIN FINAL FORM;Lo;0;AL; 0628 0632;;;;N;;;;; FC6C;ARABIC LIGATURE BEH WITH MEEM FINAL FORM;Lo;0;AL; 0628 0645;;;;N;;;;; FC6D;ARABIC LIGATURE BEH WITH NOON FINAL FORM;Lo;0;AL; 0628 0646;;;;N;;;;; FC6E;ARABIC LIGATURE BEH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0628 0649;;;;N;;;;; FC6F;ARABIC LIGATURE BEH WITH YEH FINAL FORM;Lo;0;AL; 0628 064A;;;;N;;;;; FC70;ARABIC LIGATURE TEH WITH REH FINAL FORM;Lo;0;AL; 062A 0631;;;;N;;;;; FC71;ARABIC LIGATURE TEH WITH ZAIN FINAL FORM;Lo;0;AL; 062A 0632;;;;N;;;;; FC72;ARABIC LIGATURE TEH WITH MEEM FINAL FORM;Lo;0;AL; 062A 0645;;;;N;;;;; FC73;ARABIC LIGATURE TEH WITH NOON FINAL FORM;Lo;0;AL; 062A 0646;;;;N;;;;; FC74;ARABIC LIGATURE TEH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 062A 0649;;;;N;;;;; FC75;ARABIC LIGATURE TEH WITH YEH FINAL FORM;Lo;0;AL; 062A 064A;;;;N;;;;; FC76;ARABIC LIGATURE THEH WITH REH FINAL FORM;Lo;0;AL; 062B 0631;;;;N;;;;; FC77;ARABIC LIGATURE THEH WITH ZAIN FINAL FORM;Lo;0;AL; 062B 0632;;;;N;;;;; FC78;ARABIC LIGATURE THEH WITH MEEM FINAL FORM;Lo;0;AL; 062B 0645;;;;N;;;;; FC79;ARABIC LIGATURE THEH WITH NOON FINAL FORM;Lo;0;AL; 062B 0646;;;;N;;;;; FC7A;ARABIC LIGATURE THEH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 062B 0649;;;;N;;;;; FC7B;ARABIC LIGATURE THEH WITH YEH FINAL FORM;Lo;0;AL; 062B 064A;;;;N;;;;; FC7C;ARABIC LIGATURE FEH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0641 0649;;;;N;;;;; FC7D;ARABIC LIGATURE FEH WITH YEH FINAL FORM;Lo;0;AL; 0641 064A;;;;N;;;;; FC7E;ARABIC LIGATURE QAF WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0642 0649;;;;N;;;;; FC7F;ARABIC LIGATURE QAF WITH YEH FINAL FORM;Lo;0;AL; 0642 064A;;;;N;;;;; FC80;ARABIC LIGATURE KAF WITH ALEF FINAL FORM;Lo;0;AL; 0643 0627;;;;N;;;;; FC81;ARABIC LIGATURE KAF WITH LAM FINAL FORM;Lo;0;AL; 0643 0644;;;;N;;;;; FC82;ARABIC LIGATURE KAF WITH MEEM FINAL FORM;Lo;0;AL; 0643 0645;;;;N;;;;; FC83;ARABIC LIGATURE KAF WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0643 0649;;;;N;;;;; FC84;ARABIC LIGATURE KAF WITH YEH FINAL FORM;Lo;0;AL; 0643 064A;;;;N;;;;; FC85;ARABIC LIGATURE LAM WITH MEEM FINAL FORM;Lo;0;AL; 0644 0645;;;;N;;;;; FC86;ARABIC LIGATURE LAM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0644 0649;;;;N;;;;; FC87;ARABIC LIGATURE LAM WITH YEH FINAL FORM;Lo;0;AL; 0644 064A;;;;N;;;;; FC88;ARABIC LIGATURE MEEM WITH ALEF FINAL FORM;Lo;0;AL; 0645 0627;;;;N;;;;; FC89;ARABIC LIGATURE MEEM WITH MEEM FINAL FORM;Lo;0;AL; 0645 0645;;;;N;;;;; FC8A;ARABIC LIGATURE NOON WITH REH FINAL FORM;Lo;0;AL; 0646 0631;;;;N;;;;; FC8B;ARABIC LIGATURE NOON WITH ZAIN FINAL FORM;Lo;0;AL; 0646 0632;;;;N;;;;; FC8C;ARABIC LIGATURE NOON WITH MEEM FINAL FORM;Lo;0;AL; 0646 0645;;;;N;;;;; FC8D;ARABIC LIGATURE NOON WITH NOON FINAL FORM;Lo;0;AL; 0646 0646;;;;N;;;;; FC8E;ARABIC LIGATURE NOON WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0646 0649;;;;N;;;;; FC8F;ARABIC LIGATURE NOON WITH YEH FINAL FORM;Lo;0;AL; 0646 064A;;;;N;;;;; FC90;ARABIC LIGATURE ALEF MAKSURA WITH SUPERSCRIPT ALEF FINAL FORM;Lo;0;AL; 0649 0670;;;;N;;;;; FC91;ARABIC LIGATURE YEH WITH REH FINAL FORM;Lo;0;AL; 064A 0631;;;;N;;;;; FC92;ARABIC LIGATURE YEH WITH ZAIN FINAL FORM;Lo;0;AL; 064A 0632;;;;N;;;;; FC93;ARABIC LIGATURE YEH WITH MEEM FINAL FORM;Lo;0;AL; 064A 0645;;;;N;;;;; FC94;ARABIC LIGATURE YEH WITH NOON FINAL FORM;Lo;0;AL; 064A 0646;;;;N;;;;; FC95;ARABIC LIGATURE YEH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 064A 0649;;;;N;;;;; FC96;ARABIC LIGATURE YEH WITH YEH FINAL FORM;Lo;0;AL; 064A 064A;;;;N;;;;; FC97;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH JEEM INITIAL FORM;Lo;0;AL; 0626 062C;;;;N;;;;; FC98;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HAH INITIAL FORM;Lo;0;AL; 0626 062D;;;;N;;;;; FC99;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH KHAH INITIAL FORM;Lo;0;AL; 0626 062E;;;;N;;;;; FC9A;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM INITIAL FORM;Lo;0;AL; 0626 0645;;;;N;;;;; FC9B;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HEH INITIAL FORM;Lo;0;AL; 0626 0647;;;;N;;;;; FC9C;ARABIC LIGATURE BEH WITH JEEM INITIAL FORM;Lo;0;AL; 0628 062C;;;;N;;;;; FC9D;ARABIC LIGATURE BEH WITH HAH INITIAL FORM;Lo;0;AL; 0628 062D;;;;N;;;;; FC9E;ARABIC LIGATURE BEH WITH KHAH INITIAL FORM;Lo;0;AL; 0628 062E;;;;N;;;;; FC9F;ARABIC LIGATURE BEH WITH MEEM INITIAL FORM;Lo;0;AL; 0628 0645;;;;N;;;;; FCA0;ARABIC LIGATURE BEH WITH HEH INITIAL FORM;Lo;0;AL; 0628 0647;;;;N;;;;; FCA1;ARABIC LIGATURE TEH WITH JEEM INITIAL FORM;Lo;0;AL; 062A 062C;;;;N;;;;; FCA2;ARABIC LIGATURE TEH WITH HAH INITIAL FORM;Lo;0;AL; 062A 062D;;;;N;;;;; FCA3;ARABIC LIGATURE TEH WITH KHAH INITIAL FORM;Lo;0;AL; 062A 062E;;;;N;;;;; FCA4;ARABIC LIGATURE TEH WITH MEEM INITIAL FORM;Lo;0;AL; 062A 0645;;;;N;;;;; FCA5;ARABIC LIGATURE TEH WITH HEH INITIAL FORM;Lo;0;AL; 062A 0647;;;;N;;;;; FCA6;ARABIC LIGATURE THEH WITH MEEM INITIAL FORM;Lo;0;AL; 062B 0645;;;;N;;;;; FCA7;ARABIC LIGATURE JEEM WITH HAH INITIAL FORM;Lo;0;AL; 062C 062D;;;;N;;;;; FCA8;ARABIC LIGATURE JEEM WITH MEEM INITIAL FORM;Lo;0;AL; 062C 0645;;;;N;;;;; FCA9;ARABIC LIGATURE HAH WITH JEEM INITIAL FORM;Lo;0;AL; 062D 062C;;;;N;;;;; FCAA;ARABIC LIGATURE HAH WITH MEEM INITIAL FORM;Lo;0;AL; 062D 0645;;;;N;;;;; FCAB;ARABIC LIGATURE KHAH WITH JEEM INITIAL FORM;Lo;0;AL; 062E 062C;;;;N;;;;; FCAC;ARABIC LIGATURE KHAH WITH MEEM INITIAL FORM;Lo;0;AL; 062E 0645;;;;N;;;;; FCAD;ARABIC LIGATURE SEEN WITH JEEM INITIAL FORM;Lo;0;AL; 0633 062C;;;;N;;;;; FCAE;ARABIC LIGATURE SEEN WITH HAH INITIAL FORM;Lo;0;AL; 0633 062D;;;;N;;;;; FCAF;ARABIC LIGATURE SEEN WITH KHAH INITIAL FORM;Lo;0;AL; 0633 062E;;;;N;;;;; FCB0;ARABIC LIGATURE SEEN WITH MEEM INITIAL FORM;Lo;0;AL; 0633 0645;;;;N;;;;; FCB1;ARABIC LIGATURE SAD WITH HAH INITIAL FORM;Lo;0;AL; 0635 062D;;;;N;;;;; FCB2;ARABIC LIGATURE SAD WITH KHAH INITIAL FORM;Lo;0;AL; 0635 062E;;;;N;;;;; FCB3;ARABIC LIGATURE SAD WITH MEEM INITIAL FORM;Lo;0;AL; 0635 0645;;;;N;;;;; FCB4;ARABIC LIGATURE DAD WITH JEEM INITIAL FORM;Lo;0;AL; 0636 062C;;;;N;;;;; FCB5;ARABIC LIGATURE DAD WITH HAH INITIAL FORM;Lo;0;AL; 0636 062D;;;;N;;;;; FCB6;ARABIC LIGATURE DAD WITH KHAH INITIAL FORM;Lo;0;AL; 0636 062E;;;;N;;;;; FCB7;ARABIC LIGATURE DAD WITH MEEM INITIAL FORM;Lo;0;AL; 0636 0645;;;;N;;;;; FCB8;ARABIC LIGATURE TAH WITH HAH INITIAL FORM;Lo;0;AL; 0637 062D;;;;N;;;;; FCB9;ARABIC LIGATURE ZAH WITH MEEM INITIAL FORM;Lo;0;AL; 0638 0645;;;;N;;;;; FCBA;ARABIC LIGATURE AIN WITH JEEM INITIAL FORM;Lo;0;AL; 0639 062C;;;;N;;;;; FCBB;ARABIC LIGATURE AIN WITH MEEM INITIAL FORM;Lo;0;AL; 0639 0645;;;;N;;;;; FCBC;ARABIC LIGATURE GHAIN WITH JEEM INITIAL FORM;Lo;0;AL; 063A 062C;;;;N;;;;; FCBD;ARABIC LIGATURE GHAIN WITH MEEM INITIAL FORM;Lo;0;AL; 063A 0645;;;;N;;;;; FCBE;ARABIC LIGATURE FEH WITH JEEM INITIAL FORM;Lo;0;AL; 0641 062C;;;;N;;;;; FCBF;ARABIC LIGATURE FEH WITH HAH INITIAL FORM;Lo;0;AL; 0641 062D;;;;N;;;;; FCC0;ARABIC LIGATURE FEH WITH KHAH INITIAL FORM;Lo;0;AL; 0641 062E;;;;N;;;;; FCC1;ARABIC LIGATURE FEH WITH MEEM INITIAL FORM;Lo;0;AL; 0641 0645;;;;N;;;;; FCC2;ARABIC LIGATURE QAF WITH HAH INITIAL FORM;Lo;0;AL; 0642 062D;;;;N;;;;; FCC3;ARABIC LIGATURE QAF WITH MEEM INITIAL FORM;Lo;0;AL; 0642 0645;;;;N;;;;; FCC4;ARABIC LIGATURE KAF WITH JEEM INITIAL FORM;Lo;0;AL; 0643 062C;;;;N;;;;; FCC5;ARABIC LIGATURE KAF WITH HAH INITIAL FORM;Lo;0;AL; 0643 062D;;;;N;;;;; FCC6;ARABIC LIGATURE KAF WITH KHAH INITIAL FORM;Lo;0;AL; 0643 062E;;;;N;;;;; FCC7;ARABIC LIGATURE KAF WITH LAM INITIAL FORM;Lo;0;AL; 0643 0644;;;;N;;;;; FCC8;ARABIC LIGATURE KAF WITH MEEM INITIAL FORM;Lo;0;AL; 0643 0645;;;;N;;;;; FCC9;ARABIC LIGATURE LAM WITH JEEM INITIAL FORM;Lo;0;AL; 0644 062C;;;;N;;;;; FCCA;ARABIC LIGATURE LAM WITH HAH INITIAL FORM;Lo;0;AL; 0644 062D;;;;N;;;;; FCCB;ARABIC LIGATURE LAM WITH KHAH INITIAL FORM;Lo;0;AL; 0644 062E;;;;N;;;;; FCCC;ARABIC LIGATURE LAM WITH MEEM INITIAL FORM;Lo;0;AL; 0644 0645;;;;N;;;;; FCCD;ARABIC LIGATURE LAM WITH HEH INITIAL FORM;Lo;0;AL; 0644 0647;;;;N;;;;; FCCE;ARABIC LIGATURE MEEM WITH JEEM INITIAL FORM;Lo;0;AL; 0645 062C;;;;N;;;;; FCCF;ARABIC LIGATURE MEEM WITH HAH INITIAL FORM;Lo;0;AL; 0645 062D;;;;N;;;;; FCD0;ARABIC LIGATURE MEEM WITH KHAH INITIAL FORM;Lo;0;AL; 0645 062E;;;;N;;;;; FCD1;ARABIC LIGATURE MEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0645 0645;;;;N;;;;; FCD2;ARABIC LIGATURE NOON WITH JEEM INITIAL FORM;Lo;0;AL; 0646 062C;;;;N;;;;; FCD3;ARABIC LIGATURE NOON WITH HAH INITIAL FORM;Lo;0;AL; 0646 062D;;;;N;;;;; FCD4;ARABIC LIGATURE NOON WITH KHAH INITIAL FORM;Lo;0;AL; 0646 062E;;;;N;;;;; FCD5;ARABIC LIGATURE NOON WITH MEEM INITIAL FORM;Lo;0;AL; 0646 0645;;;;N;;;;; FCD6;ARABIC LIGATURE NOON WITH HEH INITIAL FORM;Lo;0;AL; 0646 0647;;;;N;;;;; FCD7;ARABIC LIGATURE HEH WITH JEEM INITIAL FORM;Lo;0;AL; 0647 062C;;;;N;;;;; FCD8;ARABIC LIGATURE HEH WITH MEEM INITIAL FORM;Lo;0;AL; 0647 0645;;;;N;;;;; FCD9;ARABIC LIGATURE HEH WITH SUPERSCRIPT ALEF INITIAL FORM;Lo;0;AL; 0647 0670;;;;N;;;;; FCDA;ARABIC LIGATURE YEH WITH JEEM INITIAL FORM;Lo;0;AL; 064A 062C;;;;N;;;;; FCDB;ARABIC LIGATURE YEH WITH HAH INITIAL FORM;Lo;0;AL; 064A 062D;;;;N;;;;; FCDC;ARABIC LIGATURE YEH WITH KHAH INITIAL FORM;Lo;0;AL; 064A 062E;;;;N;;;;; FCDD;ARABIC LIGATURE YEH WITH MEEM INITIAL FORM;Lo;0;AL; 064A 0645;;;;N;;;;; FCDE;ARABIC LIGATURE YEH WITH HEH INITIAL FORM;Lo;0;AL; 064A 0647;;;;N;;;;; FCDF;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM MEDIAL FORM;Lo;0;AL; 0626 0645;;;;N;;;;; FCE0;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HEH MEDIAL FORM;Lo;0;AL; 0626 0647;;;;N;;;;; FCE1;ARABIC LIGATURE BEH WITH MEEM MEDIAL FORM;Lo;0;AL; 0628 0645;;;;N;;;;; FCE2;ARABIC LIGATURE BEH WITH HEH MEDIAL FORM;Lo;0;AL; 0628 0647;;;;N;;;;; FCE3;ARABIC LIGATURE TEH WITH MEEM MEDIAL FORM;Lo;0;AL; 062A 0645;;;;N;;;;; FCE4;ARABIC LIGATURE TEH WITH HEH MEDIAL FORM;Lo;0;AL; 062A 0647;;;;N;;;;; FCE5;ARABIC LIGATURE THEH WITH MEEM MEDIAL FORM;Lo;0;AL; 062B 0645;;;;N;;;;; FCE6;ARABIC LIGATURE THEH WITH HEH MEDIAL FORM;Lo;0;AL; 062B 0647;;;;N;;;;; FCE7;ARABIC LIGATURE SEEN WITH MEEM MEDIAL FORM;Lo;0;AL; 0633 0645;;;;N;;;;; FCE8;ARABIC LIGATURE SEEN WITH HEH MEDIAL FORM;Lo;0;AL; 0633 0647;;;;N;;;;; FCE9;ARABIC LIGATURE SHEEN WITH MEEM MEDIAL FORM;Lo;0;AL; 0634 0645;;;;N;;;;; FCEA;ARABIC LIGATURE SHEEN WITH HEH MEDIAL FORM;Lo;0;AL; 0634 0647;;;;N;;;;; FCEB;ARABIC LIGATURE KAF WITH LAM MEDIAL FORM;Lo;0;AL; 0643 0644;;;;N;;;;; FCEC;ARABIC LIGATURE KAF WITH MEEM MEDIAL FORM;Lo;0;AL; 0643 0645;;;;N;;;;; FCED;ARABIC LIGATURE LAM WITH MEEM MEDIAL FORM;Lo;0;AL; 0644 0645;;;;N;;;;; FCEE;ARABIC LIGATURE NOON WITH MEEM MEDIAL FORM;Lo;0;AL; 0646 0645;;;;N;;;;; FCEF;ARABIC LIGATURE NOON WITH HEH MEDIAL FORM;Lo;0;AL; 0646 0647;;;;N;;;;; FCF0;ARABIC LIGATURE YEH WITH MEEM MEDIAL FORM;Lo;0;AL; 064A 0645;;;;N;;;;; FCF1;ARABIC LIGATURE YEH WITH HEH MEDIAL FORM;Lo;0;AL; 064A 0647;;;;N;;;;; FCF2;ARABIC LIGATURE SHADDA WITH FATHA MEDIAL FORM;Lo;0;AL; 0640 064E 0651;;;;N;;;;; FCF3;ARABIC LIGATURE SHADDA WITH DAMMA MEDIAL FORM;Lo;0;AL; 0640 064F 0651;;;;N;;;;; FCF4;ARABIC LIGATURE SHADDA WITH KASRA MEDIAL FORM;Lo;0;AL; 0640 0650 0651;;;;N;;;;; FCF5;ARABIC LIGATURE TAH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0637 0649;;;;N;;;;; FCF6;ARABIC LIGATURE TAH WITH YEH ISOLATED FORM;Lo;0;AL; 0637 064A;;;;N;;;;; FCF7;ARABIC LIGATURE AIN WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0639 0649;;;;N;;;;; FCF8;ARABIC LIGATURE AIN WITH YEH ISOLATED FORM;Lo;0;AL; 0639 064A;;;;N;;;;; FCF9;ARABIC LIGATURE GHAIN WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 063A 0649;;;;N;;;;; FCFA;ARABIC LIGATURE GHAIN WITH YEH ISOLATED FORM;Lo;0;AL; 063A 064A;;;;N;;;;; FCFB;ARABIC LIGATURE SEEN WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0633 0649;;;;N;;;;; FCFC;ARABIC LIGATURE SEEN WITH YEH ISOLATED FORM;Lo;0;AL; 0633 064A;;;;N;;;;; FCFD;ARABIC LIGATURE SHEEN WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0634 0649;;;;N;;;;; FCFE;ARABIC LIGATURE SHEEN WITH YEH ISOLATED FORM;Lo;0;AL; 0634 064A;;;;N;;;;; FCFF;ARABIC LIGATURE HAH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 062D 0649;;;;N;;;;; FD00;ARABIC LIGATURE HAH WITH YEH ISOLATED FORM;Lo;0;AL; 062D 064A;;;;N;;;;; FD01;ARABIC LIGATURE JEEM WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 062C 0649;;;;N;;;;; FD02;ARABIC LIGATURE JEEM WITH YEH ISOLATED FORM;Lo;0;AL; 062C 064A;;;;N;;;;; FD03;ARABIC LIGATURE KHAH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 062E 0649;;;;N;;;;; FD04;ARABIC LIGATURE KHAH WITH YEH ISOLATED FORM;Lo;0;AL; 062E 064A;;;;N;;;;; FD05;ARABIC LIGATURE SAD WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0635 0649;;;;N;;;;; FD06;ARABIC LIGATURE SAD WITH YEH ISOLATED FORM;Lo;0;AL; 0635 064A;;;;N;;;;; FD07;ARABIC LIGATURE DAD WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0636 0649;;;;N;;;;; FD08;ARABIC LIGATURE DAD WITH YEH ISOLATED FORM;Lo;0;AL; 0636 064A;;;;N;;;;; FD09;ARABIC LIGATURE SHEEN WITH JEEM ISOLATED FORM;Lo;0;AL; 0634 062C;;;;N;;;;; FD0A;ARABIC LIGATURE SHEEN WITH HAH ISOLATED FORM;Lo;0;AL; 0634 062D;;;;N;;;;; FD0B;ARABIC LIGATURE SHEEN WITH KHAH ISOLATED FORM;Lo;0;AL; 0634 062E;;;;N;;;;; FD0C;ARABIC LIGATURE SHEEN WITH MEEM ISOLATED FORM;Lo;0;AL; 0634 0645;;;;N;;;;; FD0D;ARABIC LIGATURE SHEEN WITH REH ISOLATED FORM;Lo;0;AL; 0634 0631;;;;N;;;;; FD0E;ARABIC LIGATURE SEEN WITH REH ISOLATED FORM;Lo;0;AL; 0633 0631;;;;N;;;;; FD0F;ARABIC LIGATURE SAD WITH REH ISOLATED FORM;Lo;0;AL; 0635 0631;;;;N;;;;; FD10;ARABIC LIGATURE DAD WITH REH ISOLATED FORM;Lo;0;AL; 0636 0631;;;;N;;;;; FD11;ARABIC LIGATURE TAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0637 0649;;;;N;;;;; FD12;ARABIC LIGATURE TAH WITH YEH FINAL FORM;Lo;0;AL; 0637 064A;;;;N;;;;; FD13;ARABIC LIGATURE AIN WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0639 0649;;;;N;;;;; FD14;ARABIC LIGATURE AIN WITH YEH FINAL FORM;Lo;0;AL; 0639 064A;;;;N;;;;; FD15;ARABIC LIGATURE GHAIN WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 063A 0649;;;;N;;;;; FD16;ARABIC LIGATURE GHAIN WITH YEH FINAL FORM;Lo;0;AL; 063A 064A;;;;N;;;;; FD17;ARABIC LIGATURE SEEN WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0633 0649;;;;N;;;;; FD18;ARABIC LIGATURE SEEN WITH YEH FINAL FORM;Lo;0;AL; 0633 064A;;;;N;;;;; FD19;ARABIC LIGATURE SHEEN WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0634 0649;;;;N;;;;; FD1A;ARABIC LIGATURE SHEEN WITH YEH FINAL FORM;Lo;0;AL; 0634 064A;;;;N;;;;; FD1B;ARABIC LIGATURE HAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 062D 0649;;;;N;;;;; FD1C;ARABIC LIGATURE HAH WITH YEH FINAL FORM;Lo;0;AL; 062D 064A;;;;N;;;;; FD1D;ARABIC LIGATURE JEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 062C 0649;;;;N;;;;; FD1E;ARABIC LIGATURE JEEM WITH YEH FINAL FORM;Lo;0;AL; 062C 064A;;;;N;;;;; FD1F;ARABIC LIGATURE KHAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 062E 0649;;;;N;;;;; FD20;ARABIC LIGATURE KHAH WITH YEH FINAL FORM;Lo;0;AL; 062E 064A;;;;N;;;;; FD21;ARABIC LIGATURE SAD WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0635 0649;;;;N;;;;; FD22;ARABIC LIGATURE SAD WITH YEH FINAL FORM;Lo;0;AL; 0635 064A;;;;N;;;;; FD23;ARABIC LIGATURE DAD WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0636 0649;;;;N;;;;; FD24;ARABIC LIGATURE DAD WITH YEH FINAL FORM;Lo;0;AL; 0636 064A;;;;N;;;;; FD25;ARABIC LIGATURE SHEEN WITH JEEM FINAL FORM;Lo;0;AL; 0634 062C;;;;N;;;;; FD26;ARABIC LIGATURE SHEEN WITH HAH FINAL FORM;Lo;0;AL; 0634 062D;;;;N;;;;; FD27;ARABIC LIGATURE SHEEN WITH KHAH FINAL FORM;Lo;0;AL; 0634 062E;;;;N;;;;; FD28;ARABIC LIGATURE SHEEN WITH MEEM FINAL FORM;Lo;0;AL; 0634 0645;;;;N;;;;; FD29;ARABIC LIGATURE SHEEN WITH REH FINAL FORM;Lo;0;AL; 0634 0631;;;;N;;;;; FD2A;ARABIC LIGATURE SEEN WITH REH FINAL FORM;Lo;0;AL; 0633 0631;;;;N;;;;; FD2B;ARABIC LIGATURE SAD WITH REH FINAL FORM;Lo;0;AL; 0635 0631;;;;N;;;;; FD2C;ARABIC LIGATURE DAD WITH REH FINAL FORM;Lo;0;AL; 0636 0631;;;;N;;;;; FD2D;ARABIC LIGATURE SHEEN WITH JEEM INITIAL FORM;Lo;0;AL; 0634 062C;;;;N;;;;; FD2E;ARABIC LIGATURE SHEEN WITH HAH INITIAL FORM;Lo;0;AL; 0634 062D;;;;N;;;;; FD2F;ARABIC LIGATURE SHEEN WITH KHAH INITIAL FORM;Lo;0;AL; 0634 062E;;;;N;;;;; FD30;ARABIC LIGATURE SHEEN WITH MEEM INITIAL FORM;Lo;0;AL; 0634 0645;;;;N;;;;; FD31;ARABIC LIGATURE SEEN WITH HEH INITIAL FORM;Lo;0;AL; 0633 0647;;;;N;;;;; FD32;ARABIC LIGATURE SHEEN WITH HEH INITIAL FORM;Lo;0;AL; 0634 0647;;;;N;;;;; FD33;ARABIC LIGATURE TAH WITH MEEM INITIAL FORM;Lo;0;AL; 0637 0645;;;;N;;;;; FD34;ARABIC LIGATURE SEEN WITH JEEM MEDIAL FORM;Lo;0;AL; 0633 062C;;;;N;;;;; FD35;ARABIC LIGATURE SEEN WITH HAH MEDIAL FORM;Lo;0;AL; 0633 062D;;;;N;;;;; FD36;ARABIC LIGATURE SEEN WITH KHAH MEDIAL FORM;Lo;0;AL; 0633 062E;;;;N;;;;; FD37;ARABIC LIGATURE SHEEN WITH JEEM MEDIAL FORM;Lo;0;AL; 0634 062C;;;;N;;;;; FD38;ARABIC LIGATURE SHEEN WITH HAH MEDIAL FORM;Lo;0;AL; 0634 062D;;;;N;;;;; FD39;ARABIC LIGATURE SHEEN WITH KHAH MEDIAL FORM;Lo;0;AL; 0634 062E;;;;N;;;;; FD3A;ARABIC LIGATURE TAH WITH MEEM MEDIAL FORM;Lo;0;AL; 0637 0645;;;;N;;;;; FD3B;ARABIC LIGATURE ZAH WITH MEEM MEDIAL FORM;Lo;0;AL; 0638 0645;;;;N;;;;; FD3C;ARABIC LIGATURE ALEF WITH FATHATAN FINAL FORM;Lo;0;AL; 0627 064B;;;;N;;;;; FD3D;ARABIC LIGATURE ALEF WITH FATHATAN ISOLATED FORM;Lo;0;AL; 0627 064B;;;;N;;;;; FD3E;ORNATE LEFT PARENTHESIS;Ps;0;ON;;;;;N;;;;; FD3F;ORNATE RIGHT PARENTHESIS;Pe;0;ON;;;;;N;;;;; FD50;ARABIC LIGATURE TEH WITH JEEM WITH MEEM INITIAL FORM;Lo;0;AL; 062A 062C 0645;;;;N;;;;; FD51;ARABIC LIGATURE TEH WITH HAH WITH JEEM FINAL FORM;Lo;0;AL; 062A 062D 062C;;;;N;;;;; FD52;ARABIC LIGATURE TEH WITH HAH WITH JEEM INITIAL FORM;Lo;0;AL; 062A 062D 062C;;;;N;;;;; FD53;ARABIC LIGATURE TEH WITH HAH WITH MEEM INITIAL FORM;Lo;0;AL; 062A 062D 0645;;;;N;;;;; FD54;ARABIC LIGATURE TEH WITH KHAH WITH MEEM INITIAL FORM;Lo;0;AL; 062A 062E 0645;;;;N;;;;; FD55;ARABIC LIGATURE TEH WITH MEEM WITH JEEM INITIAL FORM;Lo;0;AL; 062A 0645 062C;;;;N;;;;; FD56;ARABIC LIGATURE TEH WITH MEEM WITH HAH INITIAL FORM;Lo;0;AL; 062A 0645 062D;;;;N;;;;; FD57;ARABIC LIGATURE TEH WITH MEEM WITH KHAH INITIAL FORM;Lo;0;AL; 062A 0645 062E;;;;N;;;;; FD58;ARABIC LIGATURE JEEM WITH MEEM WITH HAH FINAL FORM;Lo;0;AL; 062C 0645 062D;;;;N;;;;; FD59;ARABIC LIGATURE JEEM WITH MEEM WITH HAH INITIAL FORM;Lo;0;AL; 062C 0645 062D;;;;N;;;;; FD5A;ARABIC LIGATURE HAH WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 062D 0645 064A;;;;N;;;;; FD5B;ARABIC LIGATURE HAH WITH MEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 062D 0645 0649;;;;N;;;;; FD5C;ARABIC LIGATURE SEEN WITH HAH WITH JEEM INITIAL FORM;Lo;0;AL; 0633 062D 062C;;;;N;;;;; FD5D;ARABIC LIGATURE SEEN WITH JEEM WITH HAH INITIAL FORM;Lo;0;AL; 0633 062C 062D;;;;N;;;;; FD5E;ARABIC LIGATURE SEEN WITH JEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0633 062C 0649;;;;N;;;;; FD5F;ARABIC LIGATURE SEEN WITH MEEM WITH HAH FINAL FORM;Lo;0;AL; 0633 0645 062D;;;;N;;;;; FD60;ARABIC LIGATURE SEEN WITH MEEM WITH HAH INITIAL FORM;Lo;0;AL; 0633 0645 062D;;;;N;;;;; FD61;ARABIC LIGATURE SEEN WITH MEEM WITH JEEM INITIAL FORM;Lo;0;AL; 0633 0645 062C;;;;N;;;;; FD62;ARABIC LIGATURE SEEN WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL; 0633 0645 0645;;;;N;;;;; FD63;ARABIC LIGATURE SEEN WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0633 0645 0645;;;;N;;;;; FD64;ARABIC LIGATURE SAD WITH HAH WITH HAH FINAL FORM;Lo;0;AL; 0635 062D 062D;;;;N;;;;; FD65;ARABIC LIGATURE SAD WITH HAH WITH HAH INITIAL FORM;Lo;0;AL; 0635 062D 062D;;;;N;;;;; FD66;ARABIC LIGATURE SAD WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL; 0635 0645 0645;;;;N;;;;; FD67;ARABIC LIGATURE SHEEN WITH HAH WITH MEEM FINAL FORM;Lo;0;AL; 0634 062D 0645;;;;N;;;;; FD68;ARABIC LIGATURE SHEEN WITH HAH WITH MEEM INITIAL FORM;Lo;0;AL; 0634 062D 0645;;;;N;;;;; FD69;ARABIC LIGATURE SHEEN WITH JEEM WITH YEH FINAL FORM;Lo;0;AL; 0634 062C 064A;;;;N;;;;; FD6A;ARABIC LIGATURE SHEEN WITH MEEM WITH KHAH FINAL FORM;Lo;0;AL; 0634 0645 062E;;;;N;;;;; FD6B;ARABIC LIGATURE SHEEN WITH MEEM WITH KHAH INITIAL FORM;Lo;0;AL; 0634 0645 062E;;;;N;;;;; FD6C;ARABIC LIGATURE SHEEN WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL; 0634 0645 0645;;;;N;;;;; FD6D;ARABIC LIGATURE SHEEN WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0634 0645 0645;;;;N;;;;; FD6E;ARABIC LIGATURE DAD WITH HAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0636 062D 0649;;;;N;;;;; FD6F;ARABIC LIGATURE DAD WITH KHAH WITH MEEM FINAL FORM;Lo;0;AL; 0636 062E 0645;;;;N;;;;; FD70;ARABIC LIGATURE DAD WITH KHAH WITH MEEM INITIAL FORM;Lo;0;AL; 0636 062E 0645;;;;N;;;;; FD71;ARABIC LIGATURE TAH WITH MEEM WITH HAH FINAL FORM;Lo;0;AL; 0637 0645 062D;;;;N;;;;; FD72;ARABIC LIGATURE TAH WITH MEEM WITH HAH INITIAL FORM;Lo;0;AL; 0637 0645 062D;;;;N;;;;; FD73;ARABIC LIGATURE TAH WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0637 0645 0645;;;;N;;;;; FD74;ARABIC LIGATURE TAH WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 0637 0645 064A;;;;N;;;;; FD75;ARABIC LIGATURE AIN WITH JEEM WITH MEEM FINAL FORM;Lo;0;AL; 0639 062C 0645;;;;N;;;;; FD76;ARABIC LIGATURE AIN WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL; 0639 0645 0645;;;;N;;;;; FD77;ARABIC LIGATURE AIN WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0639 0645 0645;;;;N;;;;; FD78;ARABIC LIGATURE AIN WITH MEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0639 0645 0649;;;;N;;;;; FD79;ARABIC LIGATURE GHAIN WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL; 063A 0645 0645;;;;N;;;;; FD7A;ARABIC LIGATURE GHAIN WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 063A 0645 064A;;;;N;;;;; FD7B;ARABIC LIGATURE GHAIN WITH MEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 063A 0645 0649;;;;N;;;;; FD7C;ARABIC LIGATURE FEH WITH KHAH WITH MEEM FINAL FORM;Lo;0;AL; 0641 062E 0645;;;;N;;;;; FD7D;ARABIC LIGATURE FEH WITH KHAH WITH MEEM INITIAL FORM;Lo;0;AL; 0641 062E 0645;;;;N;;;;; FD7E;ARABIC LIGATURE QAF WITH MEEM WITH HAH FINAL FORM;Lo;0;AL; 0642 0645 062D;;;;N;;;;; FD7F;ARABIC LIGATURE QAF WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL; 0642 0645 0645;;;;N;;;;; FD80;ARABIC LIGATURE LAM WITH HAH WITH MEEM FINAL FORM;Lo;0;AL; 0644 062D 0645;;;;N;;;;; FD81;ARABIC LIGATURE LAM WITH HAH WITH YEH FINAL FORM;Lo;0;AL; 0644 062D 064A;;;;N;;;;; FD82;ARABIC LIGATURE LAM WITH HAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0644 062D 0649;;;;N;;;;; FD83;ARABIC LIGATURE LAM WITH JEEM WITH JEEM INITIAL FORM;Lo;0;AL; 0644 062C 062C;;;;N;;;;; FD84;ARABIC LIGATURE LAM WITH JEEM WITH JEEM FINAL FORM;Lo;0;AL; 0644 062C 062C;;;;N;;;;; FD85;ARABIC LIGATURE LAM WITH KHAH WITH MEEM FINAL FORM;Lo;0;AL; 0644 062E 0645;;;;N;;;;; FD86;ARABIC LIGATURE LAM WITH KHAH WITH MEEM INITIAL FORM;Lo;0;AL; 0644 062E 0645;;;;N;;;;; FD87;ARABIC LIGATURE LAM WITH MEEM WITH HAH FINAL FORM;Lo;0;AL; 0644 0645 062D;;;;N;;;;; FD88;ARABIC LIGATURE LAM WITH MEEM WITH HAH INITIAL FORM;Lo;0;AL; 0644 0645 062D;;;;N;;;;; FD89;ARABIC LIGATURE MEEM WITH HAH WITH JEEM INITIAL FORM;Lo;0;AL; 0645 062D 062C;;;;N;;;;; FD8A;ARABIC LIGATURE MEEM WITH HAH WITH MEEM INITIAL FORM;Lo;0;AL; 0645 062D 0645;;;;N;;;;; FD8B;ARABIC LIGATURE MEEM WITH HAH WITH YEH FINAL FORM;Lo;0;AL; 0645 062D 064A;;;;N;;;;; FD8C;ARABIC LIGATURE MEEM WITH JEEM WITH HAH INITIAL FORM;Lo;0;AL; 0645 062C 062D;;;;N;;;;; FD8D;ARABIC LIGATURE MEEM WITH JEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0645 062C 0645;;;;N;;;;; FD8E;ARABIC LIGATURE MEEM WITH KHAH WITH JEEM INITIAL FORM;Lo;0;AL; 0645 062E 062C;;;;N;;;;; FD8F;ARABIC LIGATURE MEEM WITH KHAH WITH MEEM INITIAL FORM;Lo;0;AL; 0645 062E 0645;;;;N;;;;; FD92;ARABIC LIGATURE MEEM WITH JEEM WITH KHAH INITIAL FORM;Lo;0;AL; 0645 062C 062E;;;;N;;;;; FD93;ARABIC LIGATURE HEH WITH MEEM WITH JEEM INITIAL FORM;Lo;0;AL; 0647 0645 062C;;;;N;;;;; FD94;ARABIC LIGATURE HEH WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0647 0645 0645;;;;N;;;;; FD95;ARABIC LIGATURE NOON WITH HAH WITH MEEM INITIAL FORM;Lo;0;AL; 0646 062D 0645;;;;N;;;;; FD96;ARABIC LIGATURE NOON WITH HAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0646 062D 0649;;;;N;;;;; FD97;ARABIC LIGATURE NOON WITH JEEM WITH MEEM FINAL FORM;Lo;0;AL; 0646 062C 0645;;;;N;;;;; FD98;ARABIC LIGATURE NOON WITH JEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0646 062C 0645;;;;N;;;;; FD99;ARABIC LIGATURE NOON WITH JEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0646 062C 0649;;;;N;;;;; FD9A;ARABIC LIGATURE NOON WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 0646 0645 064A;;;;N;;;;; FD9B;ARABIC LIGATURE NOON WITH MEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0646 0645 0649;;;;N;;;;; FD9C;ARABIC LIGATURE YEH WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL; 064A 0645 0645;;;;N;;;;; FD9D;ARABIC LIGATURE YEH WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL; 064A 0645 0645;;;;N;;;;; FD9E;ARABIC LIGATURE BEH WITH KHAH WITH YEH FINAL FORM;Lo;0;AL; 0628 062E 064A;;;;N;;;;; FD9F;ARABIC LIGATURE TEH WITH JEEM WITH YEH FINAL FORM;Lo;0;AL; 062A 062C 064A;;;;N;;;;; FDA0;ARABIC LIGATURE TEH WITH JEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 062A 062C 0649;;;;N;;;;; FDA1;ARABIC LIGATURE TEH WITH KHAH WITH YEH FINAL FORM;Lo;0;AL; 062A 062E 064A;;;;N;;;;; FDA2;ARABIC LIGATURE TEH WITH KHAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 062A 062E 0649;;;;N;;;;; FDA3;ARABIC LIGATURE TEH WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 062A 0645 064A;;;;N;;;;; FDA4;ARABIC LIGATURE TEH WITH MEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 062A 0645 0649;;;;N;;;;; FDA5;ARABIC LIGATURE JEEM WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 062C 0645 064A;;;;N;;;;; FDA6;ARABIC LIGATURE JEEM WITH HAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 062C 062D 0649;;;;N;;;;; FDA7;ARABIC LIGATURE JEEM WITH MEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 062C 0645 0649;;;;N;;;;; FDA8;ARABIC LIGATURE SEEN WITH KHAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0633 062E 0649;;;;N;;;;; FDA9;ARABIC LIGATURE SAD WITH HAH WITH YEH FINAL FORM;Lo;0;AL; 0635 062D 064A;;;;N;;;;; FDAA;ARABIC LIGATURE SHEEN WITH HAH WITH YEH FINAL FORM;Lo;0;AL; 0634 062D 064A;;;;N;;;;; FDAB;ARABIC LIGATURE DAD WITH HAH WITH YEH FINAL FORM;Lo;0;AL; 0636 062D 064A;;;;N;;;;; FDAC;ARABIC LIGATURE LAM WITH JEEM WITH YEH FINAL FORM;Lo;0;AL; 0644 062C 064A;;;;N;;;;; FDAD;ARABIC LIGATURE LAM WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 0644 0645 064A;;;;N;;;;; FDAE;ARABIC LIGATURE YEH WITH HAH WITH YEH FINAL FORM;Lo;0;AL; 064A 062D 064A;;;;N;;;;; FDAF;ARABIC LIGATURE YEH WITH JEEM WITH YEH FINAL FORM;Lo;0;AL; 064A 062C 064A;;;;N;;;;; FDB0;ARABIC LIGATURE YEH WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 064A 0645 064A;;;;N;;;;; FDB1;ARABIC LIGATURE MEEM WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 0645 0645 064A;;;;N;;;;; FDB2;ARABIC LIGATURE QAF WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 0642 0645 064A;;;;N;;;;; FDB3;ARABIC LIGATURE NOON WITH HAH WITH YEH FINAL FORM;Lo;0;AL; 0646 062D 064A;;;;N;;;;; FDB4;ARABIC LIGATURE QAF WITH MEEM WITH HAH INITIAL FORM;Lo;0;AL; 0642 0645 062D;;;;N;;;;; FDB5;ARABIC LIGATURE LAM WITH HAH WITH MEEM INITIAL FORM;Lo;0;AL; 0644 062D 0645;;;;N;;;;; FDB6;ARABIC LIGATURE AIN WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 0639 0645 064A;;;;N;;;;; FDB7;ARABIC LIGATURE KAF WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 0643 0645 064A;;;;N;;;;; FDB8;ARABIC LIGATURE NOON WITH JEEM WITH HAH INITIAL FORM;Lo;0;AL; 0646 062C 062D;;;;N;;;;; FDB9;ARABIC LIGATURE MEEM WITH KHAH WITH YEH FINAL FORM;Lo;0;AL; 0645 062E 064A;;;;N;;;;; FDBA;ARABIC LIGATURE LAM WITH JEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0644 062C 0645;;;;N;;;;; FDBB;ARABIC LIGATURE KAF WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL; 0643 0645 0645;;;;N;;;;; FDBC;ARABIC LIGATURE LAM WITH JEEM WITH MEEM FINAL FORM;Lo;0;AL; 0644 062C 0645;;;;N;;;;; FDBD;ARABIC LIGATURE NOON WITH JEEM WITH HAH FINAL FORM;Lo;0;AL; 0646 062C 062D;;;;N;;;;; FDBE;ARABIC LIGATURE JEEM WITH HAH WITH YEH FINAL FORM;Lo;0;AL; 062C 062D 064A;;;;N;;;;; FDBF;ARABIC LIGATURE HAH WITH JEEM WITH YEH FINAL FORM;Lo;0;AL; 062D 062C 064A;;;;N;;;;; FDC0;ARABIC LIGATURE MEEM WITH JEEM WITH YEH FINAL FORM;Lo;0;AL; 0645 062C 064A;;;;N;;;;; FDC1;ARABIC LIGATURE FEH WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 0641 0645 064A;;;;N;;;;; FDC2;ARABIC LIGATURE BEH WITH HAH WITH YEH FINAL FORM;Lo;0;AL; 0628 062D 064A;;;;N;;;;; FDC3;ARABIC LIGATURE KAF WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0643 0645 0645;;;;N;;;;; FDC4;ARABIC LIGATURE AIN WITH JEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0639 062C 0645;;;;N;;;;; FDC5;ARABIC LIGATURE SAD WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0635 0645 0645;;;;N;;;;; FDC6;ARABIC LIGATURE SEEN WITH KHAH WITH YEH FINAL FORM;Lo;0;AL; 0633 062E 064A;;;;N;;;;; FDC7;ARABIC LIGATURE NOON WITH JEEM WITH YEH FINAL FORM;Lo;0;AL; 0646 062C 064A;;;;N;;;;; FDF0;ARABIC LIGATURE SALLA USED AS KORANIC STOP SIGN ISOLATED FORM;Lo;0;AL; 0635 0644 06D2;;;;N;;;;; FDF1;ARABIC LIGATURE QALA USED AS KORANIC STOP SIGN ISOLATED FORM;Lo;0;AL; 0642 0644 06D2;;;;N;;;;; FDF2;ARABIC LIGATURE ALLAH ISOLATED FORM;Lo;0;AL; 0627 0644 0644 0647;;;;N;;;;; FDF3;ARABIC LIGATURE AKBAR ISOLATED FORM;Lo;0;AL; 0627 0643 0628 0631;;;;N;;;;; FDF4;ARABIC LIGATURE MOHAMMAD ISOLATED FORM;Lo;0;AL; 0645 062D 0645 062F;;;;N;;;;; FDF5;ARABIC LIGATURE SALAM ISOLATED FORM;Lo;0;AL; 0635 0644 0639 0645;;;;N;;;;; FDF6;ARABIC LIGATURE RASOUL ISOLATED FORM;Lo;0;AL; 0631 0633 0648 0644;;;;N;;;;; FDF7;ARABIC LIGATURE ALAYHE ISOLATED FORM;Lo;0;AL; 0639 0644 064A 0647;;;;N;;;;; FDF8;ARABIC LIGATURE WASALLAM ISOLATED FORM;Lo;0;AL; 0648 0633 0644 0645;;;;N;;;;; FDF9;ARABIC LIGATURE SALLA ISOLATED FORM;Lo;0;AL; 0635 0644 0649;;;;N;;;;; FDFA;ARABIC LIGATURE SALLALLAHOU ALAYHE WASALLAM;Lo;0;AL; 0635 0644 0649 0020 0627 0644 0644 0647 0020 0639 0644 064A 0647 0020 0648 0633 0644 0645;;;;N;ARABIC LETTER SALLALLAHOU ALAYHE WASALLAM;;;; FDFB;ARABIC LIGATURE JALLAJALALOUHOU;Lo;0;AL; 062C 0644 0020 062C 0644 0627 0644 0647;;;;N;ARABIC LETTER JALLAJALALOUHOU;;;; FDFC;RIAL SIGN;Sc;0;AL; 0631 06CC 0627 0644;;;;N;;;;; FE00;VARIATION SELECTOR-1;Mn;0;NSM;;;;;N;;;;; FE01;VARIATION SELECTOR-2;Mn;0;NSM;;;;;N;;;;; FE02;VARIATION SELECTOR-3;Mn;0;NSM;;;;;N;;;;; FE03;VARIATION SELECTOR-4;Mn;0;NSM;;;;;N;;;;; FE04;VARIATION SELECTOR-5;Mn;0;NSM;;;;;N;;;;; FE05;VARIATION SELECTOR-6;Mn;0;NSM;;;;;N;;;;; FE06;VARIATION SELECTOR-7;Mn;0;NSM;;;;;N;;;;; FE07;VARIATION SELECTOR-8;Mn;0;NSM;;;;;N;;;;; FE08;VARIATION SELECTOR-9;Mn;0;NSM;;;;;N;;;;; FE09;VARIATION SELECTOR-10;Mn;0;NSM;;;;;N;;;;; FE0A;VARIATION SELECTOR-11;Mn;0;NSM;;;;;N;;;;; FE0B;VARIATION SELECTOR-12;Mn;0;NSM;;;;;N;;;;; FE0C;VARIATION SELECTOR-13;Mn;0;NSM;;;;;N;;;;; FE0D;VARIATION SELECTOR-14;Mn;0;NSM;;;;;N;;;;; FE0E;VARIATION SELECTOR-15;Mn;0;NSM;;;;;N;;;;; FE0F;VARIATION SELECTOR-16;Mn;0;NSM;;;;;N;;;;; FE20;COMBINING LIGATURE LEFT HALF;Mn;230;NSM;;;;;N;;;;; FE21;COMBINING LIGATURE RIGHT HALF;Mn;230;NSM;;;;;N;;;;; FE22;COMBINING DOUBLE TILDE LEFT HALF;Mn;230;NSM;;;;;N;;;;; FE23;COMBINING DOUBLE TILDE RIGHT HALF;Mn;230;NSM;;;;;N;;;;; FE30;PRESENTATION FORM FOR VERTICAL TWO DOT LEADER;Po;0;ON; 2025;;;;N;GLYPH FOR VERTICAL TWO DOT LEADER;;;; FE31;PRESENTATION FORM FOR VERTICAL EM DASH;Pd;0;ON; 2014;;;;N;GLYPH FOR VERTICAL EM DASH;;;; FE32;PRESENTATION FORM FOR VERTICAL EN DASH;Pd;0;ON; 2013;;;;N;GLYPH FOR VERTICAL EN DASH;;;; FE33;PRESENTATION FORM FOR VERTICAL LOW LINE;Pc;0;ON; 005F;;;;N;GLYPH FOR VERTICAL SPACING UNDERSCORE;;;; FE34;PRESENTATION FORM FOR VERTICAL WAVY LOW LINE;Pc;0;ON; 005F;;;;N;GLYPH FOR VERTICAL SPACING WAVY UNDERSCORE;;;; FE35;PRESENTATION FORM FOR VERTICAL LEFT PARENTHESIS;Ps;0;ON; 0028;;;;N;GLYPH FOR VERTICAL OPENING PARENTHESIS;;;; FE36;PRESENTATION FORM FOR VERTICAL RIGHT PARENTHESIS;Pe;0;ON; 0029;;;;N;GLYPH FOR VERTICAL CLOSING PARENTHESIS;;;; FE37;PRESENTATION FORM FOR VERTICAL LEFT CURLY BRACKET;Ps;0;ON; 007B;;;;N;GLYPH FOR VERTICAL OPENING CURLY BRACKET;;;; FE38;PRESENTATION FORM FOR VERTICAL RIGHT CURLY BRACKET;Pe;0;ON; 007D;;;;N;GLYPH FOR VERTICAL CLOSING CURLY BRACKET;;;; FE39;PRESENTATION FORM FOR VERTICAL LEFT TORTOISE SHELL BRACKET;Ps;0;ON; 3014;;;;N;GLYPH FOR VERTICAL OPENING TORTOISE SHELL BRACKET;;;; FE3A;PRESENTATION FORM FOR VERTICAL RIGHT TORTOISE SHELL BRACKET;Pe;0;ON; 3015;;;;N;GLYPH FOR VERTICAL CLOSING TORTOISE SHELL BRACKET;;;; FE3B;PRESENTATION FORM FOR VERTICAL LEFT BLACK LENTICULAR BRACKET;Ps;0;ON; 3010;;;;N;GLYPH FOR VERTICAL OPENING BLACK LENTICULAR BRACKET;;;; FE3C;PRESENTATION FORM FOR VERTICAL RIGHT BLACK LENTICULAR BRACKET;Pe;0;ON; 3011;;;;N;GLYPH FOR VERTICAL CLOSING BLACK LENTICULAR BRACKET;;;; FE3D;PRESENTATION FORM FOR VERTICAL LEFT DOUBLE ANGLE BRACKET;Ps;0;ON; 300A;;;;N;GLYPH FOR VERTICAL OPENING DOUBLE ANGLE BRACKET;;;; FE3E;PRESENTATION FORM FOR VERTICAL RIGHT DOUBLE ANGLE BRACKET;Pe;0;ON; 300B;;;;N;GLYPH FOR VERTICAL CLOSING DOUBLE ANGLE BRACKET;;;; FE3F;PRESENTATION FORM FOR VERTICAL LEFT ANGLE BRACKET;Ps;0;ON; 3008;;;;N;GLYPH FOR VERTICAL OPENING ANGLE BRACKET;;;; FE40;PRESENTATION FORM FOR VERTICAL RIGHT ANGLE BRACKET;Pe;0;ON; 3009;;;;N;GLYPH FOR VERTICAL CLOSING ANGLE BRACKET;;;; FE41;PRESENTATION FORM FOR VERTICAL LEFT CORNER BRACKET;Ps;0;ON; 300C;;;;N;GLYPH FOR VERTICAL OPENING CORNER BRACKET;;;; FE42;PRESENTATION FORM FOR VERTICAL RIGHT CORNER BRACKET;Pe;0;ON; 300D;;;;N;GLYPH FOR VERTICAL CLOSING CORNER BRACKET;;;; FE43;PRESENTATION FORM FOR VERTICAL LEFT WHITE CORNER BRACKET;Ps;0;ON; 300E;;;;N;GLYPH FOR VERTICAL OPENING WHITE CORNER BRACKET;;;; FE44;PRESENTATION FORM FOR VERTICAL RIGHT WHITE CORNER BRACKET;Pe;0;ON; 300F;;;;N;GLYPH FOR VERTICAL CLOSING WHITE CORNER BRACKET;;;; FE45;SESAME DOT;Po;0;ON;;;;;N;;;;; FE46;WHITE SESAME DOT;Po;0;ON;;;;;N;;;;; FE49;DASHED OVERLINE;Po;0;ON; 203E;;;;N;SPACING DASHED OVERSCORE;;;; FE4A;CENTRELINE OVERLINE;Po;0;ON; 203E;;;;N;SPACING CENTERLINE OVERSCORE;;;; FE4B;WAVY OVERLINE;Po;0;ON; 203E;;;;N;SPACING WAVY OVERSCORE;;;; FE4C;DOUBLE WAVY OVERLINE;Po;0;ON; 203E;;;;N;SPACING DOUBLE WAVY OVERSCORE;;;; FE4D;DASHED LOW LINE;Pc;0;ON; 005F;;;;N;SPACING DASHED UNDERSCORE;;;; FE4E;CENTRELINE LOW LINE;Pc;0;ON; 005F;;;;N;SPACING CENTERLINE UNDERSCORE;;;; FE4F;WAVY LOW LINE;Pc;0;ON; 005F;;;;N;SPACING WAVY UNDERSCORE;;;; FE50;SMALL COMMA;Po;0;CS; 002C;;;;N;;;;; FE51;SMALL IDEOGRAPHIC COMMA;Po;0;ON; 3001;;;;N;;;;; FE52;SMALL FULL STOP;Po;0;CS; 002E;;;;N;SMALL PERIOD;;;; FE54;SMALL SEMICOLON;Po;0;ON; 003B;;;;N;;;;; FE55;SMALL COLON;Po;0;CS; 003A;;;;N;;;;; FE56;SMALL QUESTION MARK;Po;0;ON; 003F;;;;N;;;;; FE57;SMALL EXCLAMATION MARK;Po;0;ON; 0021;;;;N;;;;; FE58;SMALL EM DASH;Pd;0;ON; 2014;;;;N;;;;; FE59;SMALL LEFT PARENTHESIS;Ps;0;ON; 0028;;;;N;SMALL OPENING PARENTHESIS;;;; FE5A;SMALL RIGHT PARENTHESIS;Pe;0;ON; 0029;;;;N;SMALL CLOSING PARENTHESIS;;;; FE5B;SMALL LEFT CURLY BRACKET;Ps;0;ON; 007B;;;;N;SMALL OPENING CURLY BRACKET;;;; FE5C;SMALL RIGHT CURLY BRACKET;Pe;0;ON; 007D;;;;N;SMALL CLOSING CURLY BRACKET;;;; FE5D;SMALL LEFT TORTOISE SHELL BRACKET;Ps;0;ON; 3014;;;;N;SMALL OPENING TORTOISE SHELL BRACKET;;;; FE5E;SMALL RIGHT TORTOISE SHELL BRACKET;Pe;0;ON; 3015;;;;N;SMALL CLOSING TORTOISE SHELL BRACKET;;;; FE5F;SMALL NUMBER SIGN;Po;0;ET; 0023;;;;N;;;;; FE60;SMALL AMPERSAND;Po;0;ON; 0026;;;;N;;;;; FE61;SMALL ASTERISK;Po;0;ON; 002A;;;;N;;;;; FE62;SMALL PLUS SIGN;Sm;0;ET; 002B;;;;N;;;;; FE63;SMALL HYPHEN-MINUS;Pd;0;ET; 002D;;;;N;;;;; FE64;SMALL LESS-THAN SIGN;Sm;0;ON; 003C;;;;N;;;;; FE65;SMALL GREATER-THAN SIGN;Sm;0;ON; 003E;;;;N;;;;; FE66;SMALL EQUALS SIGN;Sm;0;ON; 003D;;;;N;;;;; FE68;SMALL REVERSE SOLIDUS;Po;0;ON; 005C;;;;N;SMALL BACKSLASH;;;; FE69;SMALL DOLLAR SIGN;Sc;0;ET; 0024;;;;N;;;;; FE6A;SMALL PERCENT SIGN;Po;0;ET; 0025;;;;N;;;;; FE6B;SMALL COMMERCIAL AT;Po;0;ON; 0040;;;;N;;;;; FE70;ARABIC FATHATAN ISOLATED FORM;Lo;0;AL; 0020 064B;;;;N;ARABIC SPACING FATHATAN;;;; FE71;ARABIC TATWEEL WITH FATHATAN ABOVE;Lo;0;AL; 0640 064B;;;;N;ARABIC FATHATAN ON TATWEEL;;;; FE72;ARABIC DAMMATAN ISOLATED FORM;Lo;0;AL; 0020 064C;;;;N;ARABIC SPACING DAMMATAN;;;; FE73;ARABIC TAIL FRAGMENT;Lo;0;AL;;;;;N;;;;; FE74;ARABIC KASRATAN ISOLATED FORM;Lo;0;AL; 0020 064D;;;;N;ARABIC SPACING KASRATAN;;;; FE76;ARABIC FATHA ISOLATED FORM;Lo;0;AL; 0020 064E;;;;N;ARABIC SPACING FATHAH;;;; FE77;ARABIC FATHA MEDIAL FORM;Lo;0;AL; 0640 064E;;;;N;ARABIC FATHAH ON TATWEEL;;;; FE78;ARABIC DAMMA ISOLATED FORM;Lo;0;AL; 0020 064F;;;;N;ARABIC SPACING DAMMAH;;;; FE79;ARABIC DAMMA MEDIAL FORM;Lo;0;AL; 0640 064F;;;;N;ARABIC DAMMAH ON TATWEEL;;;; FE7A;ARABIC KASRA ISOLATED FORM;Lo;0;AL; 0020 0650;;;;N;ARABIC SPACING KASRAH;;;; FE7B;ARABIC KASRA MEDIAL FORM;Lo;0;AL; 0640 0650;;;;N;ARABIC KASRAH ON TATWEEL;;;; FE7C;ARABIC SHADDA ISOLATED FORM;Lo;0;AL; 0020 0651;;;;N;ARABIC SPACING SHADDAH;;;; FE7D;ARABIC SHADDA MEDIAL FORM;Lo;0;AL; 0640 0651;;;;N;ARABIC SHADDAH ON TATWEEL;;;; FE7E;ARABIC SUKUN ISOLATED FORM;Lo;0;AL; 0020 0652;;;;N;ARABIC SPACING SUKUN;;;; FE7F;ARABIC SUKUN MEDIAL FORM;Lo;0;AL; 0640 0652;;;;N;ARABIC SUKUN ON TATWEEL;;;; FE80;ARABIC LETTER HAMZA ISOLATED FORM;Lo;0;AL; 0621;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH;;;; FE81;ARABIC LETTER ALEF WITH MADDA ABOVE ISOLATED FORM;Lo;0;AL; 0622;;;;N;GLYPH FOR ISOLATE ARABIC MADDAH ON ALEF;;;; FE82;ARABIC LETTER ALEF WITH MADDA ABOVE FINAL FORM;Lo;0;AL; 0622;;;;N;GLYPH FOR FINAL ARABIC MADDAH ON ALEF;;;; FE83;ARABIC LETTER ALEF WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL; 0623;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH ON ALEF;;;; FE84;ARABIC LETTER ALEF WITH HAMZA ABOVE FINAL FORM;Lo;0;AL; 0623;;;;N;GLYPH FOR FINAL ARABIC HAMZAH ON ALEF;;;; FE85;ARABIC LETTER WAW WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL; 0624;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH ON WAW;;;; FE86;ARABIC LETTER WAW WITH HAMZA ABOVE FINAL FORM;Lo;0;AL; 0624;;;;N;GLYPH FOR FINAL ARABIC HAMZAH ON WAW;;;; FE87;ARABIC LETTER ALEF WITH HAMZA BELOW ISOLATED FORM;Lo;0;AL; 0625;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH UNDER ALEF;;;; FE88;ARABIC LETTER ALEF WITH HAMZA BELOW FINAL FORM;Lo;0;AL; 0625;;;;N;GLYPH FOR FINAL ARABIC HAMZAH UNDER ALEF;;;; FE89;ARABIC LETTER YEH WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL; 0626;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH ON YA;;;; FE8A;ARABIC LETTER YEH WITH HAMZA ABOVE FINAL FORM;Lo;0;AL; 0626;;;;N;GLYPH FOR FINAL ARABIC HAMZAH ON YA;;;; FE8B;ARABIC LETTER YEH WITH HAMZA ABOVE INITIAL FORM;Lo;0;AL; 0626;;;;N;GLYPH FOR INITIAL ARABIC HAMZAH ON YA;;;; FE8C;ARABIC LETTER YEH WITH HAMZA ABOVE MEDIAL FORM;Lo;0;AL; 0626;;;;N;GLYPH FOR MEDIAL ARABIC HAMZAH ON YA;;;; FE8D;ARABIC LETTER ALEF ISOLATED FORM;Lo;0;AL; 0627;;;;N;GLYPH FOR ISOLATE ARABIC ALEF;;;; FE8E;ARABIC LETTER ALEF FINAL FORM;Lo;0;AL; 0627;;;;N;GLYPH FOR FINAL ARABIC ALEF;;;; FE8F;ARABIC LETTER BEH ISOLATED FORM;Lo;0;AL; 0628;;;;N;GLYPH FOR ISOLATE ARABIC BAA;;;; FE90;ARABIC LETTER BEH FINAL FORM;Lo;0;AL; 0628;;;;N;GLYPH FOR FINAL ARABIC BAA;;;; FE91;ARABIC LETTER BEH INITIAL FORM;Lo;0;AL; 0628;;;;N;GLYPH FOR INITIAL ARABIC BAA;;;; FE92;ARABIC LETTER BEH MEDIAL FORM;Lo;0;AL; 0628;;;;N;GLYPH FOR MEDIAL ARABIC BAA;;;; FE93;ARABIC LETTER TEH MARBUTA ISOLATED FORM;Lo;0;AL; 0629;;;;N;GLYPH FOR ISOLATE ARABIC TAA MARBUTAH;;;; FE94;ARABIC LETTER TEH MARBUTA FINAL FORM;Lo;0;AL; 0629;;;;N;GLYPH FOR FINAL ARABIC TAA MARBUTAH;;;; FE95;ARABIC LETTER TEH ISOLATED FORM;Lo;0;AL; 062A;;;;N;GLYPH FOR ISOLATE ARABIC TAA;;;; FE96;ARABIC LETTER TEH FINAL FORM;Lo;0;AL; 062A;;;;N;GLYPH FOR FINAL ARABIC TAA;;;; FE97;ARABIC LETTER TEH INITIAL FORM;Lo;0;AL; 062A;;;;N;GLYPH FOR INITIAL ARABIC TAA;;;; FE98;ARABIC LETTER TEH MEDIAL FORM;Lo;0;AL; 062A;;;;N;GLYPH FOR MEDIAL ARABIC TAA;;;; FE99;ARABIC LETTER THEH ISOLATED FORM;Lo;0;AL; 062B;;;;N;GLYPH FOR ISOLATE ARABIC THAA;;;; FE9A;ARABIC LETTER THEH FINAL FORM;Lo;0;AL; 062B;;;;N;GLYPH FOR FINAL ARABIC THAA;;;; FE9B;ARABIC LETTER THEH INITIAL FORM;Lo;0;AL; 062B;;;;N;GLYPH FOR INITIAL ARABIC THAA;;;; FE9C;ARABIC LETTER THEH MEDIAL FORM;Lo;0;AL; 062B;;;;N;GLYPH FOR MEDIAL ARABIC THAA;;;; FE9D;ARABIC LETTER JEEM ISOLATED FORM;Lo;0;AL; 062C;;;;N;GLYPH FOR ISOLATE ARABIC JEEM;;;; FE9E;ARABIC LETTER JEEM FINAL FORM;Lo;0;AL; 062C;;;;N;GLYPH FOR FINAL ARABIC JEEM;;;; FE9F;ARABIC LETTER JEEM INITIAL FORM;Lo;0;AL; 062C;;;;N;GLYPH FOR INITIAL ARABIC JEEM;;;; FEA0;ARABIC LETTER JEEM MEDIAL FORM;Lo;0;AL; 062C;;;;N;GLYPH FOR MEDIAL ARABIC JEEM;;;; FEA1;ARABIC LETTER HAH ISOLATED FORM;Lo;0;AL; 062D;;;;N;GLYPH FOR ISOLATE ARABIC HAA;;;; FEA2;ARABIC LETTER HAH FINAL FORM;Lo;0;AL; 062D;;;;N;GLYPH FOR FINAL ARABIC HAA;;;; FEA3;ARABIC LETTER HAH INITIAL FORM;Lo;0;AL; 062D;;;;N;GLYPH FOR INITIAL ARABIC HAA;;;; FEA4;ARABIC LETTER HAH MEDIAL FORM;Lo;0;AL; 062D;;;;N;GLYPH FOR MEDIAL ARABIC HAA;;;; FEA5;ARABIC LETTER KHAH ISOLATED FORM;Lo;0;AL; 062E;;;;N;GLYPH FOR ISOLATE ARABIC KHAA;;;; FEA6;ARABIC LETTER KHAH FINAL FORM;Lo;0;AL; 062E;;;;N;GLYPH FOR FINAL ARABIC KHAA;;;; FEA7;ARABIC LETTER KHAH INITIAL FORM;Lo;0;AL; 062E;;;;N;GLYPH FOR INITIAL ARABIC KHAA;;;; FEA8;ARABIC LETTER KHAH MEDIAL FORM;Lo;0;AL; 062E;;;;N;GLYPH FOR MEDIAL ARABIC KHAA;;;; FEA9;ARABIC LETTER DAL ISOLATED FORM;Lo;0;AL; 062F;;;;N;GLYPH FOR ISOLATE ARABIC DAL;;;; FEAA;ARABIC LETTER DAL FINAL FORM;Lo;0;AL; 062F;;;;N;GLYPH FOR FINAL ARABIC DAL;;;; FEAB;ARABIC LETTER THAL ISOLATED FORM;Lo;0;AL; 0630;;;;N;GLYPH FOR ISOLATE ARABIC THAL;;;; FEAC;ARABIC LETTER THAL FINAL FORM;Lo;0;AL; 0630;;;;N;GLYPH FOR FINAL ARABIC THAL;;;; FEAD;ARABIC LETTER REH ISOLATED FORM;Lo;0;AL; 0631;;;;N;GLYPH FOR ISOLATE ARABIC RA;;;; FEAE;ARABIC LETTER REH FINAL FORM;Lo;0;AL; 0631;;;;N;GLYPH FOR FINAL ARABIC RA;;;; FEAF;ARABIC LETTER ZAIN ISOLATED FORM;Lo;0;AL; 0632;;;;N;GLYPH FOR ISOLATE ARABIC ZAIN;;;; FEB0;ARABIC LETTER ZAIN FINAL FORM;Lo;0;AL; 0632;;;;N;GLYPH FOR FINAL ARABIC ZAIN;;;; FEB1;ARABIC LETTER SEEN ISOLATED FORM;Lo;0;AL; 0633;;;;N;GLYPH FOR ISOLATE ARABIC SEEN;;;; FEB2;ARABIC LETTER SEEN FINAL FORM;Lo;0;AL; 0633;;;;N;GLYPH FOR FINAL ARABIC SEEN;;;; FEB3;ARABIC LETTER SEEN INITIAL FORM;Lo;0;AL; 0633;;;;N;GLYPH FOR INITIAL ARABIC SEEN;;;; FEB4;ARABIC LETTER SEEN MEDIAL FORM;Lo;0;AL; 0633;;;;N;GLYPH FOR MEDIAL ARABIC SEEN;;;; FEB5;ARABIC LETTER SHEEN ISOLATED FORM;Lo;0;AL; 0634;;;;N;GLYPH FOR ISOLATE ARABIC SHEEN;;;; FEB6;ARABIC LETTER SHEEN FINAL FORM;Lo;0;AL; 0634;;;;N;GLYPH FOR FINAL ARABIC SHEEN;;;; FEB7;ARABIC LETTER SHEEN INITIAL FORM;Lo;0;AL; 0634;;;;N;GLYPH FOR INITIAL ARABIC SHEEN;;;; FEB8;ARABIC LETTER SHEEN MEDIAL FORM;Lo;0;AL; 0634;;;;N;GLYPH FOR MEDIAL ARABIC SHEEN;;;; FEB9;ARABIC LETTER SAD ISOLATED FORM;Lo;0;AL; 0635;;;;N;GLYPH FOR ISOLATE ARABIC SAD;;;; FEBA;ARABIC LETTER SAD FINAL FORM;Lo;0;AL; 0635;;;;N;GLYPH FOR FINAL ARABIC SAD;;;; FEBB;ARABIC LETTER SAD INITIAL FORM;Lo;0;AL; 0635;;;;N;GLYPH FOR INITIAL ARABIC SAD;;;; FEBC;ARABIC LETTER SAD MEDIAL FORM;Lo;0;AL; 0635;;;;N;GLYPH FOR MEDIAL ARABIC SAD;;;; FEBD;ARABIC LETTER DAD ISOLATED FORM;Lo;0;AL; 0636;;;;N;GLYPH FOR ISOLATE ARABIC DAD;;;; FEBE;ARABIC LETTER DAD FINAL FORM;Lo;0;AL; 0636;;;;N;GLYPH FOR FINAL ARABIC DAD;;;; FEBF;ARABIC LETTER DAD INITIAL FORM;Lo;0;AL; 0636;;;;N;GLYPH FOR INITIAL ARABIC DAD;;;; FEC0;ARABIC LETTER DAD MEDIAL FORM;Lo;0;AL; 0636;;;;N;GLYPH FOR MEDIAL ARABIC DAD;;;; FEC1;ARABIC LETTER TAH ISOLATED FORM;Lo;0;AL; 0637;;;;N;GLYPH FOR ISOLATE ARABIC TAH;;;; FEC2;ARABIC LETTER TAH FINAL FORM;Lo;0;AL; 0637;;;;N;GLYPH FOR FINAL ARABIC TAH;;;; FEC3;ARABIC LETTER TAH INITIAL FORM;Lo;0;AL; 0637;;;;N;GLYPH FOR INITIAL ARABIC TAH;;;; FEC4;ARABIC LETTER TAH MEDIAL FORM;Lo;0;AL; 0637;;;;N;GLYPH FOR MEDIAL ARABIC TAH;;;; FEC5;ARABIC LETTER ZAH ISOLATED FORM;Lo;0;AL; 0638;;;;N;GLYPH FOR ISOLATE ARABIC DHAH;;;; FEC6;ARABIC LETTER ZAH FINAL FORM;Lo;0;AL; 0638;;;;N;GLYPH FOR FINAL ARABIC DHAH;;;; FEC7;ARABIC LETTER ZAH INITIAL FORM;Lo;0;AL; 0638;;;;N;GLYPH FOR INITIAL ARABIC DHAH;;;; FEC8;ARABIC LETTER ZAH MEDIAL FORM;Lo;0;AL; 0638;;;;N;GLYPH FOR MEDIAL ARABIC DHAH;;;; FEC9;ARABIC LETTER AIN ISOLATED FORM;Lo;0;AL; 0639;;;;N;GLYPH FOR ISOLATE ARABIC AIN;;;; FECA;ARABIC LETTER AIN FINAL FORM;Lo;0;AL; 0639;;;;N;GLYPH FOR FINAL ARABIC AIN;;;; FECB;ARABIC LETTER AIN INITIAL FORM;Lo;0;AL; 0639;;;;N;GLYPH FOR INITIAL ARABIC AIN;;;; FECC;ARABIC LETTER AIN MEDIAL FORM;Lo;0;AL; 0639;;;;N;GLYPH FOR MEDIAL ARABIC AIN;;;; FECD;ARABIC LETTER GHAIN ISOLATED FORM;Lo;0;AL; 063A;;;;N;GLYPH FOR ISOLATE ARABIC GHAIN;;;; FECE;ARABIC LETTER GHAIN FINAL FORM;Lo;0;AL; 063A;;;;N;GLYPH FOR FINAL ARABIC GHAIN;;;; FECF;ARABIC LETTER GHAIN INITIAL FORM;Lo;0;AL; 063A;;;;N;GLYPH FOR INITIAL ARABIC GHAIN;;;; FED0;ARABIC LETTER GHAIN MEDIAL FORM;Lo;0;AL; 063A;;;;N;GLYPH FOR MEDIAL ARABIC GHAIN;;;; FED1;ARABIC LETTER FEH ISOLATED FORM;Lo;0;AL; 0641;;;;N;GLYPH FOR ISOLATE ARABIC FA;;;; FED2;ARABIC LETTER FEH FINAL FORM;Lo;0;AL; 0641;;;;N;GLYPH FOR FINAL ARABIC FA;;;; FED3;ARABIC LETTER FEH INITIAL FORM;Lo;0;AL; 0641;;;;N;GLYPH FOR INITIAL ARABIC FA;;;; FED4;ARABIC LETTER FEH MEDIAL FORM;Lo;0;AL; 0641;;;;N;GLYPH FOR MEDIAL ARABIC FA;;;; FED5;ARABIC LETTER QAF ISOLATED FORM;Lo;0;AL; 0642;;;;N;GLYPH FOR ISOLATE ARABIC QAF;;;; FED6;ARABIC LETTER QAF FINAL FORM;Lo;0;AL; 0642;;;;N;GLYPH FOR FINAL ARABIC QAF;;;; FED7;ARABIC LETTER QAF INITIAL FORM;Lo;0;AL; 0642;;;;N;GLYPH FOR INITIAL ARABIC QAF;;;; FED8;ARABIC LETTER QAF MEDIAL FORM;Lo;0;AL; 0642;;;;N;GLYPH FOR MEDIAL ARABIC QAF;;;; FED9;ARABIC LETTER KAF ISOLATED FORM;Lo;0;AL; 0643;;;;N;GLYPH FOR ISOLATE ARABIC CAF;;;; FEDA;ARABIC LETTER KAF FINAL FORM;Lo;0;AL; 0643;;;;N;GLYPH FOR FINAL ARABIC CAF;;;; FEDB;ARABIC LETTER KAF INITIAL FORM;Lo;0;AL; 0643;;;;N;GLYPH FOR INITIAL ARABIC CAF;;;; FEDC;ARABIC LETTER KAF MEDIAL FORM;Lo;0;AL; 0643;;;;N;GLYPH FOR MEDIAL ARABIC CAF;;;; FEDD;ARABIC LETTER LAM ISOLATED FORM;Lo;0;AL; 0644;;;;N;GLYPH FOR ISOLATE ARABIC LAM;;;; FEDE;ARABIC LETTER LAM FINAL FORM;Lo;0;AL; 0644;;;;N;GLYPH FOR FINAL ARABIC LAM;;;; FEDF;ARABIC LETTER LAM INITIAL FORM;Lo;0;AL; 0644;;;;N;GLYPH FOR INITIAL ARABIC LAM;;;; FEE0;ARABIC LETTER LAM MEDIAL FORM;Lo;0;AL; 0644;;;;N;GLYPH FOR MEDIAL ARABIC LAM;;;; FEE1;ARABIC LETTER MEEM ISOLATED FORM;Lo;0;AL; 0645;;;;N;GLYPH FOR ISOLATE ARABIC MEEM;;;; FEE2;ARABIC LETTER MEEM FINAL FORM;Lo;0;AL; 0645;;;;N;GLYPH FOR FINAL ARABIC MEEM;;;; FEE3;ARABIC LETTER MEEM INITIAL FORM;Lo;0;AL; 0645;;;;N;GLYPH FOR INITIAL ARABIC MEEM;;;; FEE4;ARABIC LETTER MEEM MEDIAL FORM;Lo;0;AL; 0645;;;;N;GLYPH FOR MEDIAL ARABIC MEEM;;;; FEE5;ARABIC LETTER NOON ISOLATED FORM;Lo;0;AL; 0646;;;;N;GLYPH FOR ISOLATE ARABIC NOON;;;; FEE6;ARABIC LETTER NOON FINAL FORM;Lo;0;AL; 0646;;;;N;GLYPH FOR FINAL ARABIC NOON;;;; FEE7;ARABIC LETTER NOON INITIAL FORM;Lo;0;AL; 0646;;;;N;GLYPH FOR INITIAL ARABIC NOON;;;; FEE8;ARABIC LETTER NOON MEDIAL FORM;Lo;0;AL; 0646;;;;N;GLYPH FOR MEDIAL ARABIC NOON;;;; FEE9;ARABIC LETTER HEH ISOLATED FORM;Lo;0;AL; 0647;;;;N;GLYPH FOR ISOLATE ARABIC HA;;;; FEEA;ARABIC LETTER HEH FINAL FORM;Lo;0;AL; 0647;;;;N;GLYPH FOR FINAL ARABIC HA;;;; FEEB;ARABIC LETTER HEH INITIAL FORM;Lo;0;AL; 0647;;;;N;GLYPH FOR INITIAL ARABIC HA;;;; FEEC;ARABIC LETTER HEH MEDIAL FORM;Lo;0;AL; 0647;;;;N;GLYPH FOR MEDIAL ARABIC HA;;;; FEED;ARABIC LETTER WAW ISOLATED FORM;Lo;0;AL; 0648;;;;N;GLYPH FOR ISOLATE ARABIC WAW;;;; FEEE;ARABIC LETTER WAW FINAL FORM;Lo;0;AL; 0648;;;;N;GLYPH FOR FINAL ARABIC WAW;;;; FEEF;ARABIC LETTER ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0649;;;;N;GLYPH FOR ISOLATE ARABIC ALEF MAQSURAH;;;; FEF0;ARABIC LETTER ALEF MAKSURA FINAL FORM;Lo;0;AL; 0649;;;;N;GLYPH FOR FINAL ARABIC ALEF MAQSURAH;;;; FEF1;ARABIC LETTER YEH ISOLATED FORM;Lo;0;AL; 064A;;;;N;GLYPH FOR ISOLATE ARABIC YA;;;; FEF2;ARABIC LETTER YEH FINAL FORM;Lo;0;AL; 064A;;;;N;GLYPH FOR FINAL ARABIC YA;;;; FEF3;ARABIC LETTER YEH INITIAL FORM;Lo;0;AL; 064A;;;;N;GLYPH FOR INITIAL ARABIC YA;;;; FEF4;ARABIC LETTER YEH MEDIAL FORM;Lo;0;AL; 064A;;;;N;GLYPH FOR MEDIAL ARABIC YA;;;; FEF5;ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM;Lo;0;AL; 0644 0622;;;;N;GLYPH FOR ISOLATE ARABIC MADDAH ON LIGATURE LAM ALEF;;;; FEF6;ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM;Lo;0;AL; 0644 0622;;;;N;GLYPH FOR FINAL ARABIC MADDAH ON LIGATURE LAM ALEF;;;; FEF7;ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL; 0644 0623;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH ON LIGATURE LAM ALEF;;;; FEF8;ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM;Lo;0;AL; 0644 0623;;;;N;GLYPH FOR FINAL ARABIC HAMZAH ON LIGATURE LAM ALEF;;;; FEF9;ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM;Lo;0;AL; 0644 0625;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH UNDER LIGATURE LAM ALEF;;;; FEFA;ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW FINAL FORM;Lo;0;AL; 0644 0625;;;;N;GLYPH FOR FINAL ARABIC HAMZAH UNDER LIGATURE LAM ALEF;;;; FEFB;ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM;Lo;0;AL; 0644 0627;;;;N;GLYPH FOR ISOLATE ARABIC LIGATURE LAM ALEF;;;; FEFC;ARABIC LIGATURE LAM WITH ALEF FINAL FORM;Lo;0;AL; 0644 0627;;;;N;GLYPH FOR FINAL ARABIC LIGATURE LAM ALEF;;;; FEFF;ZERO WIDTH NO-BREAK SPACE;Cf;0;BN;;;;;N;BYTE ORDER MARK;;;; FF01;FULLWIDTH EXCLAMATION MARK;Po;0;ON; 0021;;;;N;;;;; FF02;FULLWIDTH QUOTATION MARK;Po;0;ON; 0022;;;;N;;;;; FF03;FULLWIDTH NUMBER SIGN;Po;0;ET; 0023;;;;N;;;;; FF04;FULLWIDTH DOLLAR SIGN;Sc;0;ET; 0024;;;;N;;;;; FF05;FULLWIDTH PERCENT SIGN;Po;0;ET; 0025;;;;N;;;;; FF06;FULLWIDTH AMPERSAND;Po;0;ON; 0026;;;;N;;;;; FF07;FULLWIDTH APOSTROPHE;Po;0;ON; 0027;;;;N;;;;; FF08;FULLWIDTH LEFT PARENTHESIS;Ps;0;ON; 0028;;;;Y;FULLWIDTH OPENING PARENTHESIS;;;; FF09;FULLWIDTH RIGHT PARENTHESIS;Pe;0;ON; 0029;;;;Y;FULLWIDTH CLOSING PARENTHESIS;;;; FF0A;FULLWIDTH ASTERISK;Po;0;ON; 002A;;;;N;;;;; FF0B;FULLWIDTH PLUS SIGN;Sm;0;ET; 002B;;;;N;;;;; FF0C;FULLWIDTH COMMA;Po;0;CS; 002C;;;;N;;;;; FF0D;FULLWIDTH HYPHEN-MINUS;Pd;0;ET; 002D;;;;N;;;;; FF0E;FULLWIDTH FULL STOP;Po;0;CS; 002E;;;;N;FULLWIDTH PERIOD;;;; FF0F;FULLWIDTH SOLIDUS;Po;0;ES; 002F;;;;N;FULLWIDTH SLASH;;;; FF10;FULLWIDTH DIGIT ZERO;Nd;0;EN; 0030;0;0;0;N;;;;; FF11;FULLWIDTH DIGIT ONE;Nd;0;EN; 0031;1;1;1;N;;;;; FF12;FULLWIDTH DIGIT TWO;Nd;0;EN; 0032;2;2;2;N;;;;; FF13;FULLWIDTH DIGIT THREE;Nd;0;EN; 0033;3;3;3;N;;;;; FF14;FULLWIDTH DIGIT FOUR;Nd;0;EN; 0034;4;4;4;N;;;;; FF15;FULLWIDTH DIGIT FIVE;Nd;0;EN; 0035;5;5;5;N;;;;; FF16;FULLWIDTH DIGIT SIX;Nd;0;EN; 0036;6;6;6;N;;;;; FF17;FULLWIDTH DIGIT SEVEN;Nd;0;EN; 0037;7;7;7;N;;;;; FF18;FULLWIDTH DIGIT EIGHT;Nd;0;EN; 0038;8;8;8;N;;;;; FF19;FULLWIDTH DIGIT NINE;Nd;0;EN; 0039;9;9;9;N;;;;; FF1A;FULLWIDTH COLON;Po;0;CS; 003A;;;;N;;;;; FF1B;FULLWIDTH SEMICOLON;Po;0;ON; 003B;;;;N;;;;; FF1C;FULLWIDTH LESS-THAN SIGN;Sm;0;ON; 003C;;;;Y;;;;; FF1D;FULLWIDTH EQUALS SIGN;Sm;0;ON; 003D;;;;N;;;;; FF1E;FULLWIDTH GREATER-THAN SIGN;Sm;0;ON; 003E;;;;Y;;;;; FF1F;FULLWIDTH QUESTION MARK;Po;0;ON; 003F;;;;N;;;;; FF20;FULLWIDTH COMMERCIAL AT;Po;0;ON; 0040;;;;N;;;;; FF21;FULLWIDTH LATIN CAPITAL LETTER A;Lu;0;L; 0041;;;;N;;;;FF41; FF22;FULLWIDTH LATIN CAPITAL LETTER B;Lu;0;L; 0042;;;;N;;;;FF42; FF23;FULLWIDTH LATIN CAPITAL LETTER C;Lu;0;L; 0043;;;;N;;;;FF43; FF24;FULLWIDTH LATIN CAPITAL LETTER D;Lu;0;L; 0044;;;;N;;;;FF44; FF25;FULLWIDTH LATIN CAPITAL LETTER E;Lu;0;L; 0045;;;;N;;;;FF45; FF26;FULLWIDTH LATIN CAPITAL LETTER F;Lu;0;L; 0046;;;;N;;;;FF46; FF27;FULLWIDTH LATIN CAPITAL LETTER G;Lu;0;L; 0047;;;;N;;;;FF47; FF28;FULLWIDTH LATIN CAPITAL LETTER H;Lu;0;L; 0048;;;;N;;;;FF48; FF29;FULLWIDTH LATIN CAPITAL LETTER I;Lu;0;L; 0049;;;;N;;;;FF49; FF2A;FULLWIDTH LATIN CAPITAL LETTER J;Lu;0;L; 004A;;;;N;;;;FF4A; FF2B;FULLWIDTH LATIN CAPITAL LETTER K;Lu;0;L; 004B;;;;N;;;;FF4B; FF2C;FULLWIDTH LATIN CAPITAL LETTER L;Lu;0;L; 004C;;;;N;;;;FF4C; FF2D;FULLWIDTH LATIN CAPITAL LETTER M;Lu;0;L; 004D;;;;N;;;;FF4D; FF2E;FULLWIDTH LATIN CAPITAL LETTER N;Lu;0;L; 004E;;;;N;;;;FF4E; FF2F;FULLWIDTH LATIN CAPITAL LETTER O;Lu;0;L; 004F;;;;N;;;;FF4F; FF30;FULLWIDTH LATIN CAPITAL LETTER P;Lu;0;L; 0050;;;;N;;;;FF50; FF31;FULLWIDTH LATIN CAPITAL LETTER Q;Lu;0;L; 0051;;;;N;;;;FF51; FF32;FULLWIDTH LATIN CAPITAL LETTER R;Lu;0;L; 0052;;;;N;;;;FF52; FF33;FULLWIDTH LATIN CAPITAL LETTER S;Lu;0;L; 0053;;;;N;;;;FF53; FF34;FULLWIDTH LATIN CAPITAL LETTER T;Lu;0;L; 0054;;;;N;;;;FF54; FF35;FULLWIDTH LATIN CAPITAL LETTER U;Lu;0;L; 0055;;;;N;;;;FF55; FF36;FULLWIDTH LATIN CAPITAL LETTER V;Lu;0;L; 0056;;;;N;;;;FF56; FF37;FULLWIDTH LATIN CAPITAL LETTER W;Lu;0;L; 0057;;;;N;;;;FF57; FF38;FULLWIDTH LATIN CAPITAL LETTER X;Lu;0;L; 0058;;;;N;;;;FF58; FF39;FULLWIDTH LATIN CAPITAL LETTER Y;Lu;0;L; 0059;;;;N;;;;FF59; FF3A;FULLWIDTH LATIN CAPITAL LETTER Z;Lu;0;L; 005A;;;;N;;;;FF5A; FF3B;FULLWIDTH LEFT SQUARE BRACKET;Ps;0;ON; 005B;;;;Y;FULLWIDTH OPENING SQUARE BRACKET;;;; FF3C;FULLWIDTH REVERSE SOLIDUS;Po;0;ON; 005C;;;;N;FULLWIDTH BACKSLASH;;;; FF3D;FULLWIDTH RIGHT SQUARE BRACKET;Pe;0;ON; 005D;;;;Y;FULLWIDTH CLOSING SQUARE BRACKET;;;; FF3E;FULLWIDTH CIRCUMFLEX ACCENT;Sk;0;ON; 005E;;;;N;FULLWIDTH SPACING CIRCUMFLEX;;;; FF3F;FULLWIDTH LOW LINE;Pc;0;ON; 005F;;;;N;FULLWIDTH SPACING UNDERSCORE;;;; FF40;FULLWIDTH GRAVE ACCENT;Sk;0;ON; 0060;;;;N;FULLWIDTH SPACING GRAVE;;;; FF41;FULLWIDTH LATIN SMALL LETTER A;Ll;0;L; 0061;;;;N;;;FF21;;FF21 FF42;FULLWIDTH LATIN SMALL LETTER B;Ll;0;L; 0062;;;;N;;;FF22;;FF22 FF43;FULLWIDTH LATIN SMALL LETTER C;Ll;0;L; 0063;;;;N;;;FF23;;FF23 FF44;FULLWIDTH LATIN SMALL LETTER D;Ll;0;L; 0064;;;;N;;;FF24;;FF24 FF45;FULLWIDTH LATIN SMALL LETTER E;Ll;0;L; 0065;;;;N;;;FF25;;FF25 FF46;FULLWIDTH LATIN SMALL LETTER F;Ll;0;L; 0066;;;;N;;;FF26;;FF26 FF47;FULLWIDTH LATIN SMALL LETTER G;Ll;0;L; 0067;;;;N;;;FF27;;FF27 FF48;FULLWIDTH LATIN SMALL LETTER H;Ll;0;L; 0068;;;;N;;;FF28;;FF28 FF49;FULLWIDTH LATIN SMALL LETTER I;Ll;0;L; 0069;;;;N;;;FF29;;FF29 FF4A;FULLWIDTH LATIN SMALL LETTER J;Ll;0;L; 006A;;;;N;;;FF2A;;FF2A FF4B;FULLWIDTH LATIN SMALL LETTER K;Ll;0;L; 006B;;;;N;;;FF2B;;FF2B FF4C;FULLWIDTH LATIN SMALL LETTER L;Ll;0;L; 006C;;;;N;;;FF2C;;FF2C FF4D;FULLWIDTH LATIN SMALL LETTER M;Ll;0;L; 006D;;;;N;;;FF2D;;FF2D FF4E;FULLWIDTH LATIN SMALL LETTER N;Ll;0;L; 006E;;;;N;;;FF2E;;FF2E FF4F;FULLWIDTH LATIN SMALL LETTER O;Ll;0;L; 006F;;;;N;;;FF2F;;FF2F FF50;FULLWIDTH LATIN SMALL LETTER P;Ll;0;L; 0070;;;;N;;;FF30;;FF30 FF51;FULLWIDTH LATIN SMALL LETTER Q;Ll;0;L; 0071;;;;N;;;FF31;;FF31 FF52;FULLWIDTH LATIN SMALL LETTER R;Ll;0;L; 0072;;;;N;;;FF32;;FF32 FF53;FULLWIDTH LATIN SMALL LETTER S;Ll;0;L; 0073;;;;N;;;FF33;;FF33 FF54;FULLWIDTH LATIN SMALL LETTER T;Ll;0;L; 0074;;;;N;;;FF34;;FF34 FF55;FULLWIDTH LATIN SMALL LETTER U;Ll;0;L; 0075;;;;N;;;FF35;;FF35 FF56;FULLWIDTH LATIN SMALL LETTER V;Ll;0;L; 0076;;;;N;;;FF36;;FF36 FF57;FULLWIDTH LATIN SMALL LETTER W;Ll;0;L; 0077;;;;N;;;FF37;;FF37 FF58;FULLWIDTH LATIN SMALL LETTER X;Ll;0;L; 0078;;;;N;;;FF38;;FF38 FF59;FULLWIDTH LATIN SMALL LETTER Y;Ll;0;L; 0079;;;;N;;;FF39;;FF39 FF5A;FULLWIDTH LATIN SMALL LETTER Z;Ll;0;L; 007A;;;;N;;;FF3A;;FF3A FF5B;FULLWIDTH LEFT CURLY BRACKET;Ps;0;ON; 007B;;;;Y;FULLWIDTH OPENING CURLY BRACKET;;;; FF5C;FULLWIDTH VERTICAL LINE;Sm;0;ON; 007C;;;;N;FULLWIDTH VERTICAL BAR;;;; FF5D;FULLWIDTH RIGHT CURLY BRACKET;Pe;0;ON; 007D;;;;Y;FULLWIDTH CLOSING CURLY BRACKET;;;; FF5E;FULLWIDTH TILDE;Sm;0;ON; 007E;;;;N;FULLWIDTH SPACING TILDE;;;; FF5F;FULLWIDTH LEFT WHITE PARENTHESIS;Ps;0;ON; 2985;;;;Y;;*;;; FF60;FULLWIDTH RIGHT WHITE PARENTHESIS;Pe;0;ON; 2986;;;;Y;;*;;; FF61;HALFWIDTH IDEOGRAPHIC FULL STOP;Po;0;ON; 3002;;;;N;HALFWIDTH IDEOGRAPHIC PERIOD;;;; FF62;HALFWIDTH LEFT CORNER BRACKET;Ps;0;ON; 300C;;;;Y;HALFWIDTH OPENING CORNER BRACKET;;;; FF63;HALFWIDTH RIGHT CORNER BRACKET;Pe;0;ON; 300D;;;;Y;HALFWIDTH CLOSING CORNER BRACKET;;;; FF64;HALFWIDTH IDEOGRAPHIC COMMA;Po;0;ON; 3001;;;;N;;;;; FF65;HALFWIDTH KATAKANA MIDDLE DOT;Pc;0;ON; 30FB;;;;N;;;;; FF66;HALFWIDTH KATAKANA LETTER WO;Lo;0;L; 30F2;;;;N;;;;; FF67;HALFWIDTH KATAKANA LETTER SMALL A;Lo;0;L; 30A1;;;;N;;;;; FF68;HALFWIDTH KATAKANA LETTER SMALL I;Lo;0;L; 30A3;;;;N;;;;; FF69;HALFWIDTH KATAKANA LETTER SMALL U;Lo;0;L; 30A5;;;;N;;;;; FF6A;HALFWIDTH KATAKANA LETTER SMALL E;Lo;0;L; 30A7;;;;N;;;;; FF6B;HALFWIDTH KATAKANA LETTER SMALL O;Lo;0;L; 30A9;;;;N;;;;; FF6C;HALFWIDTH KATAKANA LETTER SMALL YA;Lo;0;L; 30E3;;;;N;;;;; FF6D;HALFWIDTH KATAKANA LETTER SMALL YU;Lo;0;L; 30E5;;;;N;;;;; FF6E;HALFWIDTH KATAKANA LETTER SMALL YO;Lo;0;L; 30E7;;;;N;;;;; FF6F;HALFWIDTH KATAKANA LETTER SMALL TU;Lo;0;L; 30C3;;;;N;;;;; FF70;HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK;Lm;0;L; 30FC;;;;N;;;;; FF71;HALFWIDTH KATAKANA LETTER A;Lo;0;L; 30A2;;;;N;;;;; FF72;HALFWIDTH KATAKANA LETTER I;Lo;0;L; 30A4;;;;N;;;;; FF73;HALFWIDTH KATAKANA LETTER U;Lo;0;L; 30A6;;;;N;;;;; FF74;HALFWIDTH KATAKANA LETTER E;Lo;0;L; 30A8;;;;N;;;;; FF75;HALFWIDTH KATAKANA LETTER O;Lo;0;L; 30AA;;;;N;;;;; FF76;HALFWIDTH KATAKANA LETTER KA;Lo;0;L; 30AB;;;;N;;;;; FF77;HALFWIDTH KATAKANA LETTER KI;Lo;0;L; 30AD;;;;N;;;;; FF78;HALFWIDTH KATAKANA LETTER KU;Lo;0;L; 30AF;;;;N;;;;; FF79;HALFWIDTH KATAKANA LETTER KE;Lo;0;L; 30B1;;;;N;;;;; FF7A;HALFWIDTH KATAKANA LETTER KO;Lo;0;L; 30B3;;;;N;;;;; FF7B;HALFWIDTH KATAKANA LETTER SA;Lo;0;L; 30B5;;;;N;;;;; FF7C;HALFWIDTH KATAKANA LETTER SI;Lo;0;L; 30B7;;;;N;;;;; FF7D;HALFWIDTH KATAKANA LETTER SU;Lo;0;L; 30B9;;;;N;;;;; FF7E;HALFWIDTH KATAKANA LETTER SE;Lo;0;L; 30BB;;;;N;;;;; FF7F;HALFWIDTH KATAKANA LETTER SO;Lo;0;L; 30BD;;;;N;;;;; FF80;HALFWIDTH KATAKANA LETTER TA;Lo;0;L; 30BF;;;;N;;;;; FF81;HALFWIDTH KATAKANA LETTER TI;Lo;0;L; 30C1;;;;N;;;;; FF82;HALFWIDTH KATAKANA LETTER TU;Lo;0;L; 30C4;;;;N;;;;; FF83;HALFWIDTH KATAKANA LETTER TE;Lo;0;L; 30C6;;;;N;;;;; FF84;HALFWIDTH KATAKANA LETTER TO;Lo;0;L; 30C8;;;;N;;;;; FF85;HALFWIDTH KATAKANA LETTER NA;Lo;0;L; 30CA;;;;N;;;;; FF86;HALFWIDTH KATAKANA LETTER NI;Lo;0;L; 30CB;;;;N;;;;; FF87;HALFWIDTH KATAKANA LETTER NU;Lo;0;L; 30CC;;;;N;;;;; FF88;HALFWIDTH KATAKANA LETTER NE;Lo;0;L; 30CD;;;;N;;;;; FF89;HALFWIDTH KATAKANA LETTER NO;Lo;0;L; 30CE;;;;N;;;;; FF8A;HALFWIDTH KATAKANA LETTER HA;Lo;0;L; 30CF;;;;N;;;;; FF8B;HALFWIDTH KATAKANA LETTER HI;Lo;0;L; 30D2;;;;N;;;;; FF8C;HALFWIDTH KATAKANA LETTER HU;Lo;0;L; 30D5;;;;N;;;;; FF8D;HALFWIDTH KATAKANA LETTER HE;Lo;0;L; 30D8;;;;N;;;;; FF8E;HALFWIDTH KATAKANA LETTER HO;Lo;0;L; 30DB;;;;N;;;;; FF8F;HALFWIDTH KATAKANA LETTER MA;Lo;0;L; 30DE;;;;N;;;;; FF90;HALFWIDTH KATAKANA LETTER MI;Lo;0;L; 30DF;;;;N;;;;; FF91;HALFWIDTH KATAKANA LETTER MU;Lo;0;L; 30E0;;;;N;;;;; FF92;HALFWIDTH KATAKANA LETTER ME;Lo;0;L; 30E1;;;;N;;;;; FF93;HALFWIDTH KATAKANA LETTER MO;Lo;0;L; 30E2;;;;N;;;;; FF94;HALFWIDTH KATAKANA LETTER YA;Lo;0;L; 30E4;;;;N;;;;; FF95;HALFWIDTH KATAKANA LETTER YU;Lo;0;L; 30E6;;;;N;;;;; FF96;HALFWIDTH KATAKANA LETTER YO;Lo;0;L; 30E8;;;;N;;;;; FF97;HALFWIDTH KATAKANA LETTER RA;Lo;0;L; 30E9;;;;N;;;;; FF98;HALFWIDTH KATAKANA LETTER RI;Lo;0;L; 30EA;;;;N;;;;; FF99;HALFWIDTH KATAKANA LETTER RU;Lo;0;L; 30EB;;;;N;;;;; FF9A;HALFWIDTH KATAKANA LETTER RE;Lo;0;L; 30EC;;;;N;;;;; FF9B;HALFWIDTH KATAKANA LETTER RO;Lo;0;L; 30ED;;;;N;;;;; FF9C;HALFWIDTH KATAKANA LETTER WA;Lo;0;L; 30EF;;;;N;;;;; FF9D;HALFWIDTH KATAKANA LETTER N;Lo;0;L; 30F3;;;;N;;;;; FF9E;HALFWIDTH KATAKANA VOICED SOUND MARK;Lm;0;L; 3099;;;;N;;halfwidth katakana-hiragana voiced sound mark;;; FF9F;HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK;Lm;0;L; 309A;;;;N;;halfwidth katakana-hiragana semi-voiced sound mark;;; FFA0;HALFWIDTH HANGUL FILLER;Lo;0;L; 3164;;;;N;HALFWIDTH HANGUL CAE OM;;;; FFA1;HALFWIDTH HANGUL LETTER KIYEOK;Lo;0;L; 3131;;;;N;HALFWIDTH HANGUL LETTER GIYEOG;;;; FFA2;HALFWIDTH HANGUL LETTER SSANGKIYEOK;Lo;0;L; 3132;;;;N;HALFWIDTH HANGUL LETTER SSANG GIYEOG;;;; FFA3;HALFWIDTH HANGUL LETTER KIYEOK-SIOS;Lo;0;L; 3133;;;;N;HALFWIDTH HANGUL LETTER GIYEOG SIOS;;;; FFA4;HALFWIDTH HANGUL LETTER NIEUN;Lo;0;L; 3134;;;;N;;;;; FFA5;HALFWIDTH HANGUL LETTER NIEUN-CIEUC;Lo;0;L; 3135;;;;N;HALFWIDTH HANGUL LETTER NIEUN JIEUJ;;;; FFA6;HALFWIDTH HANGUL LETTER NIEUN-HIEUH;Lo;0;L; 3136;;;;N;HALFWIDTH HANGUL LETTER NIEUN HIEUH;;;; FFA7;HALFWIDTH HANGUL LETTER TIKEUT;Lo;0;L; 3137;;;;N;HALFWIDTH HANGUL LETTER DIGEUD;;;; FFA8;HALFWIDTH HANGUL LETTER SSANGTIKEUT;Lo;0;L; 3138;;;;N;HALFWIDTH HANGUL LETTER SSANG DIGEUD;;;; FFA9;HALFWIDTH HANGUL LETTER RIEUL;Lo;0;L; 3139;;;;N;HALFWIDTH HANGUL LETTER LIEUL;;;; FFAA;HALFWIDTH HANGUL LETTER RIEUL-KIYEOK;Lo;0;L; 313A;;;;N;HALFWIDTH HANGUL LETTER LIEUL GIYEOG;;;; FFAB;HALFWIDTH HANGUL LETTER RIEUL-MIEUM;Lo;0;L; 313B;;;;N;HALFWIDTH HANGUL LETTER LIEUL MIEUM;;;; FFAC;HALFWIDTH HANGUL LETTER RIEUL-PIEUP;Lo;0;L; 313C;;;;N;HALFWIDTH HANGUL LETTER LIEUL BIEUB;;;; FFAD;HALFWIDTH HANGUL LETTER RIEUL-SIOS;Lo;0;L; 313D;;;;N;HALFWIDTH HANGUL LETTER LIEUL SIOS;;;; FFAE;HALFWIDTH HANGUL LETTER RIEUL-THIEUTH;Lo;0;L; 313E;;;;N;HALFWIDTH HANGUL LETTER LIEUL TIEUT;;;; FFAF;HALFWIDTH HANGUL LETTER RIEUL-PHIEUPH;Lo;0;L; 313F;;;;N;HALFWIDTH HANGUL LETTER LIEUL PIEUP;;;; FFB0;HALFWIDTH HANGUL LETTER RIEUL-HIEUH;Lo;0;L; 3140;;;;N;HALFWIDTH HANGUL LETTER LIEUL HIEUH;;;; FFB1;HALFWIDTH HANGUL LETTER MIEUM;Lo;0;L; 3141;;;;N;;;;; FFB2;HALFWIDTH HANGUL LETTER PIEUP;Lo;0;L; 3142;;;;N;HALFWIDTH HANGUL LETTER BIEUB;;;; FFB3;HALFWIDTH HANGUL LETTER SSANGPIEUP;Lo;0;L; 3143;;;;N;HALFWIDTH HANGUL LETTER SSANG BIEUB;;;; FFB4;HALFWIDTH HANGUL LETTER PIEUP-SIOS;Lo;0;L; 3144;;;;N;HALFWIDTH HANGUL LETTER BIEUB SIOS;;;; FFB5;HALFWIDTH HANGUL LETTER SIOS;Lo;0;L; 3145;;;;N;;;;; FFB6;HALFWIDTH HANGUL LETTER SSANGSIOS;Lo;0;L; 3146;;;;N;HALFWIDTH HANGUL LETTER SSANG SIOS;;;; FFB7;HALFWIDTH HANGUL LETTER IEUNG;Lo;0;L; 3147;;;;N;;;;; FFB8;HALFWIDTH HANGUL LETTER CIEUC;Lo;0;L; 3148;;;;N;HALFWIDTH HANGUL LETTER JIEUJ;;;; FFB9;HALFWIDTH HANGUL LETTER SSANGCIEUC;Lo;0;L; 3149;;;;N;HALFWIDTH HANGUL LETTER SSANG JIEUJ;;;; FFBA;HALFWIDTH HANGUL LETTER CHIEUCH;Lo;0;L; 314A;;;;N;HALFWIDTH HANGUL LETTER CIEUC;;;; FFBB;HALFWIDTH HANGUL LETTER KHIEUKH;Lo;0;L; 314B;;;;N;HALFWIDTH HANGUL LETTER KIYEOK;;;; FFBC;HALFWIDTH HANGUL LETTER THIEUTH;Lo;0;L; 314C;;;;N;HALFWIDTH HANGUL LETTER TIEUT;;;; FFBD;HALFWIDTH HANGUL LETTER PHIEUPH;Lo;0;L; 314D;;;;N;HALFWIDTH HANGUL LETTER PIEUP;;;; FFBE;HALFWIDTH HANGUL LETTER HIEUH;Lo;0;L; 314E;;;;N;;;;; FFC2;HALFWIDTH HANGUL LETTER A;Lo;0;L; 314F;;;;N;;;;; FFC3;HALFWIDTH HANGUL LETTER AE;Lo;0;L; 3150;;;;N;;;;; FFC4;HALFWIDTH HANGUL LETTER YA;Lo;0;L; 3151;;;;N;;;;; FFC5;HALFWIDTH HANGUL LETTER YAE;Lo;0;L; 3152;;;;N;;;;; FFC6;HALFWIDTH HANGUL LETTER EO;Lo;0;L; 3153;;;;N;;;;; FFC7;HALFWIDTH HANGUL LETTER E;Lo;0;L; 3154;;;;N;;;;; FFCA;HALFWIDTH HANGUL LETTER YEO;Lo;0;L; 3155;;;;N;;;;; FFCB;HALFWIDTH HANGUL LETTER YE;Lo;0;L; 3156;;;;N;;;;; FFCC;HALFWIDTH HANGUL LETTER O;Lo;0;L; 3157;;;;N;;;;; FFCD;HALFWIDTH HANGUL LETTER WA;Lo;0;L; 3158;;;;N;;;;; FFCE;HALFWIDTH HANGUL LETTER WAE;Lo;0;L; 3159;;;;N;;;;; FFCF;HALFWIDTH HANGUL LETTER OE;Lo;0;L; 315A;;;;N;;;;; FFD2;HALFWIDTH HANGUL LETTER YO;Lo;0;L; 315B;;;;N;;;;; FFD3;HALFWIDTH HANGUL LETTER U;Lo;0;L; 315C;;;;N;;;;; FFD4;HALFWIDTH HANGUL LETTER WEO;Lo;0;L; 315D;;;;N;;;;; FFD5;HALFWIDTH HANGUL LETTER WE;Lo;0;L; 315E;;;;N;;;;; FFD6;HALFWIDTH HANGUL LETTER WI;Lo;0;L; 315F;;;;N;;;;; FFD7;HALFWIDTH HANGUL LETTER YU;Lo;0;L; 3160;;;;N;;;;; FFDA;HALFWIDTH HANGUL LETTER EU;Lo;0;L; 3161;;;;N;;;;; FFDB;HALFWIDTH HANGUL LETTER YI;Lo;0;L; 3162;;;;N;;;;; FFDC;HALFWIDTH HANGUL LETTER I;Lo;0;L; 3163;;;;N;;;;; FFE0;FULLWIDTH CENT SIGN;Sc;0;ET; 00A2;;;;N;;;;; FFE1;FULLWIDTH POUND SIGN;Sc;0;ET; 00A3;;;;N;;;;; FFE2;FULLWIDTH NOT SIGN;Sm;0;ON; 00AC;;;;N;;;;; FFE3;FULLWIDTH MACRON;Sk;0;ON; 00AF;;;;N;FULLWIDTH SPACING MACRON;*;;; FFE4;FULLWIDTH BROKEN BAR;So;0;ON; 00A6;;;;N;FULLWIDTH BROKEN VERTICAL BAR;;;; FFE5;FULLWIDTH YEN SIGN;Sc;0;ET; 00A5;;;;N;;;;; FFE6;FULLWIDTH WON SIGN;Sc;0;ET; 20A9;;;;N;;;;; FFE8;HALFWIDTH FORMS LIGHT VERTICAL;So;0;ON; 2502;;;;N;;;;; FFE9;HALFWIDTH LEFTWARDS ARROW;Sm;0;ON; 2190;;;;N;;;;; FFEA;HALFWIDTH UPWARDS ARROW;Sm;0;ON; 2191;;;;N;;;;; FFEB;HALFWIDTH RIGHTWARDS ARROW;Sm;0;ON; 2192;;;;N;;;;; FFEC;HALFWIDTH DOWNWARDS ARROW;Sm;0;ON; 2193;;;;N;;;;; FFED;HALFWIDTH BLACK SQUARE;So;0;ON; 25A0;;;;N;;;;; FFEE;HALFWIDTH WHITE CIRCLE;So;0;ON; 25CB;;;;N;;;;; FFF9;INTERLINEAR ANNOTATION ANCHOR;Cf;0;BN;;;;;N;;;;; FFFA;INTERLINEAR ANNOTATION SEPARATOR;Cf;0;BN;;;;;N;;;;; FFFB;INTERLINEAR ANNOTATION TERMINATOR;Cf;0;BN;;;;;N;;;;; FFFC;OBJECT REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 10300;OLD ITALIC LETTER A;Lo;0;L;;;;;N;;;;; 10301;OLD ITALIC LETTER BE;Lo;0;L;;;;;N;;;;; 10302;OLD ITALIC LETTER KE;Lo;0;L;;;;;N;;;;; 10303;OLD ITALIC LETTER DE;Lo;0;L;;;;;N;;;;; 10304;OLD ITALIC LETTER E;Lo;0;L;;;;;N;;;;; 10305;OLD ITALIC LETTER VE;Lo;0;L;;;;;N;;;;; 10306;OLD ITALIC LETTER ZE;Lo;0;L;;;;;N;;;;; 10307;OLD ITALIC LETTER HE;Lo;0;L;;;;;N;;;;; 10308;OLD ITALIC LETTER THE;Lo;0;L;;;;;N;;;;; 10309;OLD ITALIC LETTER I;Lo;0;L;;;;;N;;;;; 1030A;OLD ITALIC LETTER KA;Lo;0;L;;;;;N;;;;; 1030B;OLD ITALIC LETTER EL;Lo;0;L;;;;;N;;;;; 1030C;OLD ITALIC LETTER EM;Lo;0;L;;;;;N;;;;; 1030D;OLD ITALIC LETTER EN;Lo;0;L;;;;;N;;;;; 1030E;OLD ITALIC LETTER ESH;Lo;0;L;;;;;N;;;;; 1030F;OLD ITALIC LETTER O;Lo;0;L;;;;;N;;Faliscan;;; 10310;OLD ITALIC LETTER PE;Lo;0;L;;;;;N;;;;; 10311;OLD ITALIC LETTER SHE;Lo;0;L;;;;;N;;;;; 10312;OLD ITALIC LETTER KU;Lo;0;L;;;;;N;;;;; 10313;OLD ITALIC LETTER ER;Lo;0;L;;;;;N;;;;; 10314;OLD ITALIC LETTER ES;Lo;0;L;;;;;N;;;;; 10315;OLD ITALIC LETTER TE;Lo;0;L;;;;;N;;;;; 10316;OLD ITALIC LETTER U;Lo;0;L;;;;;N;;;;; 10317;OLD ITALIC LETTER EKS;Lo;0;L;;;;;N;;Faliscan;;; 10318;OLD ITALIC LETTER PHE;Lo;0;L;;;;;N;;;;; 10319;OLD ITALIC LETTER KHE;Lo;0;L;;;;;N;;;;; 1031A;OLD ITALIC LETTER EF;Lo;0;L;;;;;N;;;;; 1031B;OLD ITALIC LETTER ERS;Lo;0;L;;;;;N;;Umbrian;;; 1031C;OLD ITALIC LETTER CHE;Lo;0;L;;;;;N;;Umbrian;;; 1031D;OLD ITALIC LETTER II;Lo;0;L;;;;;N;;Oscan;;; 1031E;OLD ITALIC LETTER UU;Lo;0;L;;;;;N;;Oscan;;; 10320;OLD ITALIC NUMERAL ONE;No;0;L;;;;1;N;;;;; 10321;OLD ITALIC NUMERAL FIVE;No;0;L;;;;5;N;;;;; 10322;OLD ITALIC NUMERAL TEN;No;0;L;;;;10;N;;;;; 10323;OLD ITALIC NUMERAL FIFTY;No;0;L;;;;50;N;;;;; 10330;GOTHIC LETTER AHSA;Lo;0;L;;;;;N;;;;; 10331;GOTHIC LETTER BAIRKAN;Lo;0;L;;;;;N;;;;; 10332;GOTHIC LETTER GIBA;Lo;0;L;;;;;N;;;;; 10333;GOTHIC LETTER DAGS;Lo;0;L;;;;;N;;;;; 10334;GOTHIC LETTER AIHVUS;Lo;0;L;;;;;N;;;;; 10335;GOTHIC LETTER QAIRTHRA;Lo;0;L;;;;;N;;;;; 10336;GOTHIC LETTER IUJA;Lo;0;L;;;;;N;;;;; 10337;GOTHIC LETTER HAGL;Lo;0;L;;;;;N;;;;; 10338;GOTHIC LETTER THIUTH;Lo;0;L;;;;;N;;;;; 10339;GOTHIC LETTER EIS;Lo;0;L;;;;;N;;;;; 1033A;GOTHIC LETTER KUSMA;Lo;0;L;;;;;N;;;;; 1033B;GOTHIC LETTER LAGUS;Lo;0;L;;;;;N;;;;; 1033C;GOTHIC LETTER MANNA;Lo;0;L;;;;;N;;;;; 1033D;GOTHIC LETTER NAUTHS;Lo;0;L;;;;;N;;;;; 1033E;GOTHIC LETTER JER;Lo;0;L;;;;;N;;;;; 1033F;GOTHIC LETTER URUS;Lo;0;L;;;;;N;;;;; 10340;GOTHIC LETTER PAIRTHRA;Lo;0;L;;;;;N;;;;; 10341;GOTHIC LETTER NINETY;Lo;0;L;;;;;N;;;;; 10342;GOTHIC LETTER RAIDA;Lo;0;L;;;;;N;;;;; 10343;GOTHIC LETTER SAUIL;Lo;0;L;;;;;N;;;;; 10344;GOTHIC LETTER TEIWS;Lo;0;L;;;;;N;;;;; 10345;GOTHIC LETTER WINJA;Lo;0;L;;;;;N;;;;; 10346;GOTHIC LETTER FAIHU;Lo;0;L;;;;;N;;;;; 10347;GOTHIC LETTER IGGWS;Lo;0;L;;;;;N;;;;; 10348;GOTHIC LETTER HWAIR;Lo;0;L;;;;;N;;;;; 10349;GOTHIC LETTER OTHAL;Lo;0;L;;;;;N;;;;; 1034A;GOTHIC LETTER NINE HUNDRED;Nl;0;L;;;;;N;;;;; 10400;DESERET CAPITAL LETTER LONG I;Lu;0;L;;;;;N;;;;10428; 10401;DESERET CAPITAL LETTER LONG E;Lu;0;L;;;;;N;;;;10429; 10402;DESERET CAPITAL LETTER LONG A;Lu;0;L;;;;;N;;;;1042A; 10403;DESERET CAPITAL LETTER LONG AH;Lu;0;L;;;;;N;;;;1042B; 10404;DESERET CAPITAL LETTER LONG O;Lu;0;L;;;;;N;;;;1042C; 10405;DESERET CAPITAL LETTER LONG OO;Lu;0;L;;;;;N;;;;1042D; 10406;DESERET CAPITAL LETTER SHORT I;Lu;0;L;;;;;N;;;;1042E; 10407;DESERET CAPITAL LETTER SHORT E;Lu;0;L;;;;;N;;;;1042F; 10408;DESERET CAPITAL LETTER SHORT A;Lu;0;L;;;;;N;;;;10430; 10409;DESERET CAPITAL LETTER SHORT AH;Lu;0;L;;;;;N;;;;10431; 1040A;DESERET CAPITAL LETTER SHORT O;Lu;0;L;;;;;N;;;;10432; 1040B;DESERET CAPITAL LETTER SHORT OO;Lu;0;L;;;;;N;;;;10433; 1040C;DESERET CAPITAL LETTER AY;Lu;0;L;;;;;N;;;;10434; 1040D;DESERET CAPITAL LETTER OW;Lu;0;L;;;;;N;;;;10435; 1040E;DESERET CAPITAL LETTER WU;Lu;0;L;;;;;N;;;;10436; 1040F;DESERET CAPITAL LETTER YEE;Lu;0;L;;;;;N;;;;10437; 10410;DESERET CAPITAL LETTER H;Lu;0;L;;;;;N;;;;10438; 10411;DESERET CAPITAL LETTER PEE;Lu;0;L;;;;;N;;;;10439; 10412;DESERET CAPITAL LETTER BEE;Lu;0;L;;;;;N;;;;1043A; 10413;DESERET CAPITAL LETTER TEE;Lu;0;L;;;;;N;;;;1043B; 10414;DESERET CAPITAL LETTER DEE;Lu;0;L;;;;;N;;;;1043C; 10415;DESERET CAPITAL LETTER CHEE;Lu;0;L;;;;;N;;;;1043D; 10416;DESERET CAPITAL LETTER JEE;Lu;0;L;;;;;N;;;;1043E; 10417;DESERET CAPITAL LETTER KAY;Lu;0;L;;;;;N;;;;1043F; 10418;DESERET CAPITAL LETTER GAY;Lu;0;L;;;;;N;;;;10440; 10419;DESERET CAPITAL LETTER EF;Lu;0;L;;;;;N;;;;10441; 1041A;DESERET CAPITAL LETTER VEE;Lu;0;L;;;;;N;;;;10442; 1041B;DESERET CAPITAL LETTER ETH;Lu;0;L;;;;;N;;;;10443; 1041C;DESERET CAPITAL LETTER THEE;Lu;0;L;;;;;N;;;;10444; 1041D;DESERET CAPITAL LETTER ES;Lu;0;L;;;;;N;;;;10445; 1041E;DESERET CAPITAL LETTER ZEE;Lu;0;L;;;;;N;;;;10446; 1041F;DESERET CAPITAL LETTER ESH;Lu;0;L;;;;;N;;;;10447; 10420;DESERET CAPITAL LETTER ZHEE;Lu;0;L;;;;;N;;;;10448; 10421;DESERET CAPITAL LETTER ER;Lu;0;L;;;;;N;;;;10449; 10422;DESERET CAPITAL LETTER EL;Lu;0;L;;;;;N;;;;1044A; 10423;DESERET CAPITAL LETTER EM;Lu;0;L;;;;;N;;;;1044B; 10424;DESERET CAPITAL LETTER EN;Lu;0;L;;;;;N;;;;1044C; 10425;DESERET CAPITAL LETTER ENG;Lu;0;L;;;;;N;;;;1044D; 10428;DESERET SMALL LETTER LONG I;Ll;0;L;;;;;N;;;10400;;10400 10429;DESERET SMALL LETTER LONG E;Ll;0;L;;;;;N;;;10401;;10401 1042A;DESERET SMALL LETTER LONG A;Ll;0;L;;;;;N;;;10402;;10402 1042B;DESERET SMALL LETTER LONG AH;Ll;0;L;;;;;N;;;10403;;10403 1042C;DESERET SMALL LETTER LONG O;Ll;0;L;;;;;N;;;10404;;10404 1042D;DESERET SMALL LETTER LONG OO;Ll;0;L;;;;;N;;;10405;;10405 1042E;DESERET SMALL LETTER SHORT I;Ll;0;L;;;;;N;;;10406;;10406 1042F;DESERET SMALL LETTER SHORT E;Ll;0;L;;;;;N;;;10407;;10407 10430;DESERET SMALL LETTER SHORT A;Ll;0;L;;;;;N;;;10408;;10408 10431;DESERET SMALL LETTER SHORT AH;Ll;0;L;;;;;N;;;10409;;10409 10432;DESERET SMALL LETTER SHORT O;Ll;0;L;;;;;N;;;1040A;;1040A 10433;DESERET SMALL LETTER SHORT OO;Ll;0;L;;;;;N;;;1040B;;1040B 10434;DESERET SMALL LETTER AY;Ll;0;L;;;;;N;;;1040C;;1040C 10435;DESERET SMALL LETTER OW;Ll;0;L;;;;;N;;;1040D;;1040D 10436;DESERET SMALL LETTER WU;Ll;0;L;;;;;N;;;1040E;;1040E 10437;DESERET SMALL LETTER YEE;Ll;0;L;;;;;N;;;1040F;;1040F 10438;DESERET SMALL LETTER H;Ll;0;L;;;;;N;;;10410;;10410 10439;DESERET SMALL LETTER PEE;Ll;0;L;;;;;N;;;10411;;10411 1043A;DESERET SMALL LETTER BEE;Ll;0;L;;;;;N;;;10412;;10412 1043B;DESERET SMALL LETTER TEE;Ll;0;L;;;;;N;;;10413;;10413 1043C;DESERET SMALL LETTER DEE;Ll;0;L;;;;;N;;;10414;;10414 1043D;DESERET SMALL LETTER CHEE;Ll;0;L;;;;;N;;;10415;;10415 1043E;DESERET SMALL LETTER JEE;Ll;0;L;;;;;N;;;10416;;10416 1043F;DESERET SMALL LETTER KAY;Ll;0;L;;;;;N;;;10417;;10417 10440;DESERET SMALL LETTER GAY;Ll;0;L;;;;;N;;;10418;;10418 10441;DESERET SMALL LETTER EF;Ll;0;L;;;;;N;;;10419;;10419 10442;DESERET SMALL LETTER VEE;Ll;0;L;;;;;N;;;1041A;;1041A 10443;DESERET SMALL LETTER ETH;Ll;0;L;;;;;N;;;1041B;;1041B 10444;DESERET SMALL LETTER THEE;Ll;0;L;;;;;N;;;1041C;;1041C 10445;DESERET SMALL LETTER ES;Ll;0;L;;;;;N;;;1041D;;1041D 10446;DESERET SMALL LETTER ZEE;Ll;0;L;;;;;N;;;1041E;;1041E 10447;DESERET SMALL LETTER ESH;Ll;0;L;;;;;N;;;1041F;;1041F 10448;DESERET SMALL LETTER ZHEE;Ll;0;L;;;;;N;;;10420;;10420 10449;DESERET SMALL LETTER ER;Ll;0;L;;;;;N;;;10421;;10421 1044A;DESERET SMALL LETTER EL;Ll;0;L;;;;;N;;;10422;;10422 1044B;DESERET SMALL LETTER EM;Ll;0;L;;;;;N;;;10423;;10423 1044C;DESERET SMALL LETTER EN;Ll;0;L;;;;;N;;;10424;;10424 1044D;DESERET SMALL LETTER ENG;Ll;0;L;;;;;N;;;10425;;10425 1D000;BYZANTINE MUSICAL SYMBOL PSILI;So;0;L;;;;;N;;;;; 1D001;BYZANTINE MUSICAL SYMBOL DASEIA;So;0;L;;;;;N;;;;; 1D002;BYZANTINE MUSICAL SYMBOL PERISPOMENI;So;0;L;;;;;N;;;;; 1D003;BYZANTINE MUSICAL SYMBOL OXEIA EKFONITIKON;So;0;L;;;;;N;;;;; 1D004;BYZANTINE MUSICAL SYMBOL OXEIA DIPLI;So;0;L;;;;;N;;;;; 1D005;BYZANTINE MUSICAL SYMBOL VAREIA EKFONITIKON;So;0;L;;;;;N;;;;; 1D006;BYZANTINE MUSICAL SYMBOL VAREIA DIPLI;So;0;L;;;;;N;;;;; 1D007;BYZANTINE MUSICAL SYMBOL KATHISTI;So;0;L;;;;;N;;;;; 1D008;BYZANTINE MUSICAL SYMBOL SYRMATIKI;So;0;L;;;;;N;;;;; 1D009;BYZANTINE MUSICAL SYMBOL PARAKLITIKI;So;0;L;;;;;N;;;;; 1D00A;BYZANTINE MUSICAL SYMBOL YPOKRISIS;So;0;L;;;;;N;;;;; 1D00B;BYZANTINE MUSICAL SYMBOL YPOKRISIS DIPLI;So;0;L;;;;;N;;;;; 1D00C;BYZANTINE MUSICAL SYMBOL KREMASTI;So;0;L;;;;;N;;;;; 1D00D;BYZANTINE MUSICAL SYMBOL APESO EKFONITIKON;So;0;L;;;;;N;;;;; 1D00E;BYZANTINE MUSICAL SYMBOL EXO EKFONITIKON;So;0;L;;;;;N;;;;; 1D00F;BYZANTINE MUSICAL SYMBOL TELEIA;So;0;L;;;;;N;;;;; 1D010;BYZANTINE MUSICAL SYMBOL KENTIMATA;So;0;L;;;;;N;;;;; 1D011;BYZANTINE MUSICAL SYMBOL APOSTROFOS;So;0;L;;;;;N;;;;; 1D012;BYZANTINE MUSICAL SYMBOL APOSTROFOS DIPLI;So;0;L;;;;;N;;;;; 1D013;BYZANTINE MUSICAL SYMBOL SYNEVMA;So;0;L;;;;;N;;;;; 1D014;BYZANTINE MUSICAL SYMBOL THITA;So;0;L;;;;;N;;;;; 1D015;BYZANTINE MUSICAL SYMBOL OLIGON ARCHAION;So;0;L;;;;;N;;;;; 1D016;BYZANTINE MUSICAL SYMBOL GORGON ARCHAION;So;0;L;;;;;N;;;;; 1D017;BYZANTINE MUSICAL SYMBOL PSILON;So;0;L;;;;;N;;;;; 1D018;BYZANTINE MUSICAL SYMBOL CHAMILON;So;0;L;;;;;N;;;;; 1D019;BYZANTINE MUSICAL SYMBOL VATHY;So;0;L;;;;;N;;;;; 1D01A;BYZANTINE MUSICAL SYMBOL ISON ARCHAION;So;0;L;;;;;N;;;;; 1D01B;BYZANTINE MUSICAL SYMBOL KENTIMA ARCHAION;So;0;L;;;;;N;;;;; 1D01C;BYZANTINE MUSICAL SYMBOL KENTIMATA ARCHAION;So;0;L;;;;;N;;;;; 1D01D;BYZANTINE MUSICAL SYMBOL SAXIMATA;So;0;L;;;;;N;;;;; 1D01E;BYZANTINE MUSICAL SYMBOL PARICHON;So;0;L;;;;;N;;;;; 1D01F;BYZANTINE MUSICAL SYMBOL STAVROS APODEXIA;So;0;L;;;;;N;;;;; 1D020;BYZANTINE MUSICAL SYMBOL OXEIAI ARCHAION;So;0;L;;;;;N;;;;; 1D021;BYZANTINE MUSICAL SYMBOL VAREIAI ARCHAION;So;0;L;;;;;N;;;;; 1D022;BYZANTINE MUSICAL SYMBOL APODERMA ARCHAION;So;0;L;;;;;N;;;;; 1D023;BYZANTINE MUSICAL SYMBOL APOTHEMA;So;0;L;;;;;N;;;;; 1D024;BYZANTINE MUSICAL SYMBOL KLASMA;So;0;L;;;;;N;;;;; 1D025;BYZANTINE MUSICAL SYMBOL REVMA;So;0;L;;;;;N;;;;; 1D026;BYZANTINE MUSICAL SYMBOL PIASMA ARCHAION;So;0;L;;;;;N;;;;; 1D027;BYZANTINE MUSICAL SYMBOL TINAGMA;So;0;L;;;;;N;;;;; 1D028;BYZANTINE MUSICAL SYMBOL ANATRICHISMA;So;0;L;;;;;N;;;;; 1D029;BYZANTINE MUSICAL SYMBOL SEISMA;So;0;L;;;;;N;;;;; 1D02A;BYZANTINE MUSICAL SYMBOL SYNAGMA ARCHAION;So;0;L;;;;;N;;;;; 1D02B;BYZANTINE MUSICAL SYMBOL SYNAGMA META STAVROU;So;0;L;;;;;N;;;;; 1D02C;BYZANTINE MUSICAL SYMBOL OYRANISMA ARCHAION;So;0;L;;;;;N;;;;; 1D02D;BYZANTINE MUSICAL SYMBOL THEMA;So;0;L;;;;;N;;;;; 1D02E;BYZANTINE MUSICAL SYMBOL LEMOI;So;0;L;;;;;N;;;;; 1D02F;BYZANTINE MUSICAL SYMBOL DYO;So;0;L;;;;;N;;;;; 1D030;BYZANTINE MUSICAL SYMBOL TRIA;So;0;L;;;;;N;;;;; 1D031;BYZANTINE MUSICAL SYMBOL TESSERA;So;0;L;;;;;N;;;;; 1D032;BYZANTINE MUSICAL SYMBOL KRATIMATA;So;0;L;;;;;N;;;;; 1D033;BYZANTINE MUSICAL SYMBOL APESO EXO NEO;So;0;L;;;;;N;;;;; 1D034;BYZANTINE MUSICAL SYMBOL FTHORA ARCHAION;So;0;L;;;;;N;;;;; 1D035;BYZANTINE MUSICAL SYMBOL IMIFTHORA;So;0;L;;;;;N;;;;; 1D036;BYZANTINE MUSICAL SYMBOL TROMIKON ARCHAION;So;0;L;;;;;N;;;;; 1D037;BYZANTINE MUSICAL SYMBOL KATAVA TROMIKON;So;0;L;;;;;N;;;;; 1D038;BYZANTINE MUSICAL SYMBOL PELASTON;So;0;L;;;;;N;;;;; 1D039;BYZANTINE MUSICAL SYMBOL PSIFISTON;So;0;L;;;;;N;;;;; 1D03A;BYZANTINE MUSICAL SYMBOL KONTEVMA;So;0;L;;;;;N;;;;; 1D03B;BYZANTINE MUSICAL SYMBOL CHOREVMA ARCHAION;So;0;L;;;;;N;;;;; 1D03C;BYZANTINE MUSICAL SYMBOL RAPISMA;So;0;L;;;;;N;;;;; 1D03D;BYZANTINE MUSICAL SYMBOL PARAKALESMA ARCHAION;So;0;L;;;;;N;;;;; 1D03E;BYZANTINE MUSICAL SYMBOL PARAKLITIKI ARCHAION;So;0;L;;;;;N;;;;; 1D03F;BYZANTINE MUSICAL SYMBOL ICHADIN;So;0;L;;;;;N;;;;; 1D040;BYZANTINE MUSICAL SYMBOL NANA;So;0;L;;;;;N;;;;; 1D041;BYZANTINE MUSICAL SYMBOL PETASMA;So;0;L;;;;;N;;;;; 1D042;BYZANTINE MUSICAL SYMBOL KONTEVMA ALLO;So;0;L;;;;;N;;;;; 1D043;BYZANTINE MUSICAL SYMBOL TROMIKON ALLO;So;0;L;;;;;N;;;;; 1D044;BYZANTINE MUSICAL SYMBOL STRAGGISMATA;So;0;L;;;;;N;;;;; 1D045;BYZANTINE MUSICAL SYMBOL GRONTHISMATA;So;0;L;;;;;N;;;;; 1D046;BYZANTINE MUSICAL SYMBOL ISON NEO;So;0;L;;;;;N;;;;; 1D047;BYZANTINE MUSICAL SYMBOL OLIGON NEO;So;0;L;;;;;N;;;;; 1D048;BYZANTINE MUSICAL SYMBOL OXEIA NEO;So;0;L;;;;;N;;;;; 1D049;BYZANTINE MUSICAL SYMBOL PETASTI;So;0;L;;;;;N;;;;; 1D04A;BYZANTINE MUSICAL SYMBOL KOUFISMA;So;0;L;;;;;N;;;;; 1D04B;BYZANTINE MUSICAL SYMBOL PETASTOKOUFISMA;So;0;L;;;;;N;;;;; 1D04C;BYZANTINE MUSICAL SYMBOL KRATIMOKOUFISMA;So;0;L;;;;;N;;;;; 1D04D;BYZANTINE MUSICAL SYMBOL PELASTON NEO;So;0;L;;;;;N;;;;; 1D04E;BYZANTINE MUSICAL SYMBOL KENTIMATA NEO ANO;So;0;L;;;;;N;;;;; 1D04F;BYZANTINE MUSICAL SYMBOL KENTIMA NEO ANO;So;0;L;;;;;N;;;;; 1D050;BYZANTINE MUSICAL SYMBOL YPSILI;So;0;L;;;;;N;;;;; 1D051;BYZANTINE MUSICAL SYMBOL APOSTROFOS NEO;So;0;L;;;;;N;;;;; 1D052;BYZANTINE MUSICAL SYMBOL APOSTROFOI SYNDESMOS NEO;So;0;L;;;;;N;;;;; 1D053;BYZANTINE MUSICAL SYMBOL YPORROI;So;0;L;;;;;N;;;;; 1D054;BYZANTINE MUSICAL SYMBOL KRATIMOYPORROON;So;0;L;;;;;N;;;;; 1D055;BYZANTINE MUSICAL SYMBOL ELAFRON;So;0;L;;;;;N;;;;; 1D056;BYZANTINE MUSICAL SYMBOL CHAMILI;So;0;L;;;;;N;;;;; 1D057;BYZANTINE MUSICAL SYMBOL MIKRON ISON;So;0;L;;;;;N;;;;; 1D058;BYZANTINE MUSICAL SYMBOL VAREIA NEO;So;0;L;;;;;N;;;;; 1D059;BYZANTINE MUSICAL SYMBOL PIASMA NEO;So;0;L;;;;;N;;;;; 1D05A;BYZANTINE MUSICAL SYMBOL PSIFISTON NEO;So;0;L;;;;;N;;;;; 1D05B;BYZANTINE MUSICAL SYMBOL OMALON;So;0;L;;;;;N;;;;; 1D05C;BYZANTINE MUSICAL SYMBOL ANTIKENOMA;So;0;L;;;;;N;;;;; 1D05D;BYZANTINE MUSICAL SYMBOL LYGISMA;So;0;L;;;;;N;;;;; 1D05E;BYZANTINE MUSICAL SYMBOL PARAKLITIKI NEO;So;0;L;;;;;N;;;;; 1D05F;BYZANTINE MUSICAL SYMBOL PARAKALESMA NEO;So;0;L;;;;;N;;;;; 1D060;BYZANTINE MUSICAL SYMBOL ETERON PARAKALESMA;So;0;L;;;;;N;;;;; 1D061;BYZANTINE MUSICAL SYMBOL KYLISMA;So;0;L;;;;;N;;;;; 1D062;BYZANTINE MUSICAL SYMBOL ANTIKENOKYLISMA;So;0;L;;;;;N;;;;; 1D063;BYZANTINE MUSICAL SYMBOL TROMIKON NEO;So;0;L;;;;;N;;;;; 1D064;BYZANTINE MUSICAL SYMBOL EKSTREPTON;So;0;L;;;;;N;;;;; 1D065;BYZANTINE MUSICAL SYMBOL SYNAGMA NEO;So;0;L;;;;;N;;;;; 1D066;BYZANTINE MUSICAL SYMBOL SYRMA;So;0;L;;;;;N;;;;; 1D067;BYZANTINE MUSICAL SYMBOL CHOREVMA NEO;So;0;L;;;;;N;;;;; 1D068;BYZANTINE MUSICAL SYMBOL EPEGERMA;So;0;L;;;;;N;;;;; 1D069;BYZANTINE MUSICAL SYMBOL SEISMA NEO;So;0;L;;;;;N;;;;; 1D06A;BYZANTINE MUSICAL SYMBOL XIRON KLASMA;So;0;L;;;;;N;;;;; 1D06B;BYZANTINE MUSICAL SYMBOL TROMIKOPSIFISTON;So;0;L;;;;;N;;;;; 1D06C;BYZANTINE MUSICAL SYMBOL PSIFISTOLYGISMA;So;0;L;;;;;N;;;;; 1D06D;BYZANTINE MUSICAL SYMBOL TROMIKOLYGISMA;So;0;L;;;;;N;;;;; 1D06E;BYZANTINE MUSICAL SYMBOL TROMIKOPARAKALESMA;So;0;L;;;;;N;;;;; 1D06F;BYZANTINE MUSICAL SYMBOL PSIFISTOPARAKALESMA;So;0;L;;;;;N;;;;; 1D070;BYZANTINE MUSICAL SYMBOL TROMIKOSYNAGMA;So;0;L;;;;;N;;;;; 1D071;BYZANTINE MUSICAL SYMBOL PSIFISTOSYNAGMA;So;0;L;;;;;N;;;;; 1D072;BYZANTINE MUSICAL SYMBOL GORGOSYNTHETON;So;0;L;;;;;N;;;;; 1D073;BYZANTINE MUSICAL SYMBOL ARGOSYNTHETON;So;0;L;;;;;N;;;;; 1D074;BYZANTINE MUSICAL SYMBOL ETERON ARGOSYNTHETON;So;0;L;;;;;N;;;;; 1D075;BYZANTINE MUSICAL SYMBOL OYRANISMA NEO;So;0;L;;;;;N;;;;; 1D076;BYZANTINE MUSICAL SYMBOL THEMATISMOS ESO;So;0;L;;;;;N;;;;; 1D077;BYZANTINE MUSICAL SYMBOL THEMATISMOS EXO;So;0;L;;;;;N;;;;; 1D078;BYZANTINE MUSICAL SYMBOL THEMA APLOUN;So;0;L;;;;;N;;;;; 1D079;BYZANTINE MUSICAL SYMBOL THES KAI APOTHES;So;0;L;;;;;N;;;;; 1D07A;BYZANTINE MUSICAL SYMBOL KATAVASMA;So;0;L;;;;;N;;;;; 1D07B;BYZANTINE MUSICAL SYMBOL ENDOFONON;So;0;L;;;;;N;;;;; 1D07C;BYZANTINE MUSICAL SYMBOL YFEN KATO;So;0;L;;;;;N;;;;; 1D07D;BYZANTINE MUSICAL SYMBOL YFEN ANO;So;0;L;;;;;N;;;;; 1D07E;BYZANTINE MUSICAL SYMBOL STAVROS;So;0;L;;;;;N;;;;; 1D07F;BYZANTINE MUSICAL SYMBOL KLASMA ANO;So;0;L;;;;;N;;;;; 1D080;BYZANTINE MUSICAL SYMBOL DIPLI ARCHAION;So;0;L;;;;;N;;;;; 1D081;BYZANTINE MUSICAL SYMBOL KRATIMA ARCHAION;So;0;L;;;;;N;;;;; 1D082;BYZANTINE MUSICAL SYMBOL KRATIMA ALLO;So;0;L;;;;;N;;;;; 1D083;BYZANTINE MUSICAL SYMBOL KRATIMA NEO;So;0;L;;;;;N;;;;; 1D084;BYZANTINE MUSICAL SYMBOL APODERMA NEO;So;0;L;;;;;N;;;;; 1D085;BYZANTINE MUSICAL SYMBOL APLI;So;0;L;;;;;N;;;;; 1D086;BYZANTINE MUSICAL SYMBOL DIPLI;So;0;L;;;;;N;;;;; 1D087;BYZANTINE MUSICAL SYMBOL TRIPLI;So;0;L;;;;;N;;;;; 1D088;BYZANTINE MUSICAL SYMBOL TETRAPLI;So;0;L;;;;;N;;;;; 1D089;BYZANTINE MUSICAL SYMBOL KORONIS;So;0;L;;;;;N;;;;; 1D08A;BYZANTINE MUSICAL SYMBOL LEIMMA ENOS CHRONOU;So;0;L;;;;;N;;;;; 1D08B;BYZANTINE MUSICAL SYMBOL LEIMMA DYO CHRONON;So;0;L;;;;;N;;;;; 1D08C;BYZANTINE MUSICAL SYMBOL LEIMMA TRION CHRONON;So;0;L;;;;;N;;;;; 1D08D;BYZANTINE MUSICAL SYMBOL LEIMMA TESSARON CHRONON;So;0;L;;;;;N;;;;; 1D08E;BYZANTINE MUSICAL SYMBOL LEIMMA IMISEOS CHRONOU;So;0;L;;;;;N;;;;; 1D08F;BYZANTINE MUSICAL SYMBOL GORGON NEO ANO;So;0;L;;;;;N;;;;; 1D090;BYZANTINE MUSICAL SYMBOL GORGON PARESTIGMENON ARISTERA;So;0;L;;;;;N;;;;; 1D091;BYZANTINE MUSICAL SYMBOL GORGON PARESTIGMENON DEXIA;So;0;L;;;;;N;;;;; 1D092;BYZANTINE MUSICAL SYMBOL DIGORGON;So;0;L;;;;;N;;;;; 1D093;BYZANTINE MUSICAL SYMBOL DIGORGON PARESTIGMENON ARISTERA KATO;So;0;L;;;;;N;;;;; 1D094;BYZANTINE MUSICAL SYMBOL DIGORGON PARESTIGMENON ARISTERA ANO;So;0;L;;;;;N;;;;; 1D095;BYZANTINE MUSICAL SYMBOL DIGORGON PARESTIGMENON DEXIA;So;0;L;;;;;N;;;;; 1D096;BYZANTINE MUSICAL SYMBOL TRIGORGON;So;0;L;;;;;N;;;;; 1D097;BYZANTINE MUSICAL SYMBOL ARGON;So;0;L;;;;;N;;;;; 1D098;BYZANTINE MUSICAL SYMBOL IMIDIARGON;So;0;L;;;;;N;;;;; 1D099;BYZANTINE MUSICAL SYMBOL DIARGON;So;0;L;;;;;N;;;;; 1D09A;BYZANTINE MUSICAL SYMBOL AGOGI POLI ARGI;So;0;L;;;;;N;;;;; 1D09B;BYZANTINE MUSICAL SYMBOL AGOGI ARGOTERI;So;0;L;;;;;N;;;;; 1D09C;BYZANTINE MUSICAL SYMBOL AGOGI ARGI;So;0;L;;;;;N;;;;; 1D09D;BYZANTINE MUSICAL SYMBOL AGOGI METRIA;So;0;L;;;;;N;;;;; 1D09E;BYZANTINE MUSICAL SYMBOL AGOGI MESI;So;0;L;;;;;N;;;;; 1D09F;BYZANTINE MUSICAL SYMBOL AGOGI GORGI;So;0;L;;;;;N;;;;; 1D0A0;BYZANTINE MUSICAL SYMBOL AGOGI GORGOTERI;So;0;L;;;;;N;;;;; 1D0A1;BYZANTINE MUSICAL SYMBOL AGOGI POLI GORGI;So;0;L;;;;;N;;;;; 1D0A2;BYZANTINE MUSICAL SYMBOL MARTYRIA PROTOS ICHOS;So;0;L;;;;;N;;;;; 1D0A3;BYZANTINE MUSICAL SYMBOL MARTYRIA ALLI PROTOS ICHOS;So;0;L;;;;;N;;;;; 1D0A4;BYZANTINE MUSICAL SYMBOL MARTYRIA DEYTEROS ICHOS;So;0;L;;;;;N;;;;; 1D0A5;BYZANTINE MUSICAL SYMBOL MARTYRIA ALLI DEYTEROS ICHOS;So;0;L;;;;;N;;;;; 1D0A6;BYZANTINE MUSICAL SYMBOL MARTYRIA TRITOS ICHOS;So;0;L;;;;;N;;;;; 1D0A7;BYZANTINE MUSICAL SYMBOL MARTYRIA TRIFONIAS;So;0;L;;;;;N;;;;; 1D0A8;BYZANTINE MUSICAL SYMBOL MARTYRIA TETARTOS ICHOS;So;0;L;;;;;N;;;;; 1D0A9;BYZANTINE MUSICAL SYMBOL MARTYRIA TETARTOS LEGETOS ICHOS;So;0;L;;;;;N;;;;; 1D0AA;BYZANTINE MUSICAL SYMBOL MARTYRIA LEGETOS ICHOS;So;0;L;;;;;N;;;;; 1D0AB;BYZANTINE MUSICAL SYMBOL MARTYRIA PLAGIOS ICHOS;So;0;L;;;;;N;;;;; 1D0AC;BYZANTINE MUSICAL SYMBOL ISAKIA TELOUS ICHIMATOS;So;0;L;;;;;N;;;;; 1D0AD;BYZANTINE MUSICAL SYMBOL APOSTROFOI TELOUS ICHIMATOS;So;0;L;;;;;N;;;;; 1D0AE;BYZANTINE MUSICAL SYMBOL FANEROSIS TETRAFONIAS;So;0;L;;;;;N;;;;; 1D0AF;BYZANTINE MUSICAL SYMBOL FANEROSIS MONOFONIAS;So;0;L;;;;;N;;;;; 1D0B0;BYZANTINE MUSICAL SYMBOL FANEROSIS DIFONIAS;So;0;L;;;;;N;;;;; 1D0B1;BYZANTINE MUSICAL SYMBOL MARTYRIA VARYS ICHOS;So;0;L;;;;;N;;;;; 1D0B2;BYZANTINE MUSICAL SYMBOL MARTYRIA PROTOVARYS ICHOS;So;0;L;;;;;N;;;;; 1D0B3;BYZANTINE MUSICAL SYMBOL MARTYRIA PLAGIOS TETARTOS ICHOS;So;0;L;;;;;N;;;;; 1D0B4;BYZANTINE MUSICAL SYMBOL GORTHMIKON N APLOUN;So;0;L;;;;;N;;;;; 1D0B5;BYZANTINE MUSICAL SYMBOL GORTHMIKON N DIPLOUN;So;0;L;;;;;N;;;;; 1D0B6;BYZANTINE MUSICAL SYMBOL ENARXIS KAI FTHORA VOU;So;0;L;;;;;N;;;;; 1D0B7;BYZANTINE MUSICAL SYMBOL IMIFONON;So;0;L;;;;;N;;;;; 1D0B8;BYZANTINE MUSICAL SYMBOL IMIFTHORON;So;0;L;;;;;N;;;;; 1D0B9;BYZANTINE MUSICAL SYMBOL FTHORA ARCHAION DEYTEROU ICHOU;So;0;L;;;;;N;;;;; 1D0BA;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI PA;So;0;L;;;;;N;;;;; 1D0BB;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI NANA;So;0;L;;;;;N;;;;; 1D0BC;BYZANTINE MUSICAL SYMBOL FTHORA NAOS ICHOS;So;0;L;;;;;N;;;;; 1D0BD;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI DI;So;0;L;;;;;N;;;;; 1D0BE;BYZANTINE MUSICAL SYMBOL FTHORA SKLIRON DIATONON DI;So;0;L;;;;;N;;;;; 1D0BF;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI KE;So;0;L;;;;;N;;;;; 1D0C0;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI ZO;So;0;L;;;;;N;;;;; 1D0C1;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI NI KATO;So;0;L;;;;;N;;;;; 1D0C2;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI NI ANO;So;0;L;;;;;N;;;;; 1D0C3;BYZANTINE MUSICAL SYMBOL FTHORA MALAKON CHROMA DIFONIAS;So;0;L;;;;;N;;;;; 1D0C4;BYZANTINE MUSICAL SYMBOL FTHORA MALAKON CHROMA MONOFONIAS;So;0;L;;;;;N;;;;; 1D0C5;BYZANTINE MUSICAL SYMBOL FHTORA SKLIRON CHROMA VASIS;So;0;L;;;;;N;;;;; 1D0C6;BYZANTINE MUSICAL SYMBOL FTHORA SKLIRON CHROMA SYNAFI;So;0;L;;;;;N;;;;; 1D0C7;BYZANTINE MUSICAL SYMBOL FTHORA NENANO;So;0;L;;;;;N;;;;; 1D0C8;BYZANTINE MUSICAL SYMBOL CHROA ZYGOS;So;0;L;;;;;N;;;;; 1D0C9;BYZANTINE MUSICAL SYMBOL CHROA KLITON;So;0;L;;;;;N;;;;; 1D0CA;BYZANTINE MUSICAL SYMBOL CHROA SPATHI;So;0;L;;;;;N;;;;; 1D0CB;BYZANTINE MUSICAL SYMBOL FTHORA I YFESIS TETARTIMORION;So;0;L;;;;;N;;;;; 1D0CC;BYZANTINE MUSICAL SYMBOL FTHORA ENARMONIOS ANTIFONIA;So;0;L;;;;;N;;;;; 1D0CD;BYZANTINE MUSICAL SYMBOL YFESIS TRITIMORION;So;0;L;;;;;N;;;;; 1D0CE;BYZANTINE MUSICAL SYMBOL DIESIS TRITIMORION;So;0;L;;;;;N;;;;; 1D0CF;BYZANTINE MUSICAL SYMBOL DIESIS TETARTIMORION;So;0;L;;;;;N;;;;; 1D0D0;BYZANTINE MUSICAL SYMBOL DIESIS APLI DYO DODEKATA;So;0;L;;;;;N;;;;; 1D0D1;BYZANTINE MUSICAL SYMBOL DIESIS MONOGRAMMOS TESSERA DODEKATA;So;0;L;;;;;N;;;;; 1D0D2;BYZANTINE MUSICAL SYMBOL DIESIS DIGRAMMOS EX DODEKATA;So;0;L;;;;;N;;;;; 1D0D3;BYZANTINE MUSICAL SYMBOL DIESIS TRIGRAMMOS OKTO DODEKATA;So;0;L;;;;;N;;;;; 1D0D4;BYZANTINE MUSICAL SYMBOL YFESIS APLI DYO DODEKATA;So;0;L;;;;;N;;;;; 1D0D5;BYZANTINE MUSICAL SYMBOL YFESIS MONOGRAMMOS TESSERA DODEKATA;So;0;L;;;;;N;;;;; 1D0D6;BYZANTINE MUSICAL SYMBOL YFESIS DIGRAMMOS EX DODEKATA;So;0;L;;;;;N;;;;; 1D0D7;BYZANTINE MUSICAL SYMBOL YFESIS TRIGRAMMOS OKTO DODEKATA;So;0;L;;;;;N;;;;; 1D0D8;BYZANTINE MUSICAL SYMBOL GENIKI DIESIS;So;0;L;;;;;N;;;;; 1D0D9;BYZANTINE MUSICAL SYMBOL GENIKI YFESIS;So;0;L;;;;;N;;;;; 1D0DA;BYZANTINE MUSICAL SYMBOL DIASTOLI APLI MIKRI;So;0;L;;;;;N;;;;; 1D0DB;BYZANTINE MUSICAL SYMBOL DIASTOLI APLI MEGALI;So;0;L;;;;;N;;;;; 1D0DC;BYZANTINE MUSICAL SYMBOL DIASTOLI DIPLI;So;0;L;;;;;N;;;;; 1D0DD;BYZANTINE MUSICAL SYMBOL DIASTOLI THESEOS;So;0;L;;;;;N;;;;; 1D0DE;BYZANTINE MUSICAL SYMBOL SIMANSIS THESEOS;So;0;L;;;;;N;;;;; 1D0DF;BYZANTINE MUSICAL SYMBOL SIMANSIS THESEOS DISIMOU;So;0;L;;;;;N;;;;; 1D0E0;BYZANTINE MUSICAL SYMBOL SIMANSIS THESEOS TRISIMOU;So;0;L;;;;;N;;;;; 1D0E1;BYZANTINE MUSICAL SYMBOL SIMANSIS THESEOS TETRASIMOU;So;0;L;;;;;N;;;;; 1D0E2;BYZANTINE MUSICAL SYMBOL SIMANSIS ARSEOS;So;0;L;;;;;N;;;;; 1D0E3;BYZANTINE MUSICAL SYMBOL SIMANSIS ARSEOS DISIMOU;So;0;L;;;;;N;;;;; 1D0E4;BYZANTINE MUSICAL SYMBOL SIMANSIS ARSEOS TRISIMOU;So;0;L;;;;;N;;;;; 1D0E5;BYZANTINE MUSICAL SYMBOL SIMANSIS ARSEOS TETRASIMOU;So;0;L;;;;;N;;;;; 1D0E6;BYZANTINE MUSICAL SYMBOL DIGRAMMA GG;So;0;L;;;;;N;;;;; 1D0E7;BYZANTINE MUSICAL SYMBOL DIFTOGGOS OU;So;0;L;;;;;N;;;;; 1D0E8;BYZANTINE MUSICAL SYMBOL STIGMA;So;0;L;;;;;N;;;;; 1D0E9;BYZANTINE MUSICAL SYMBOL ARKTIKO PA;So;0;L;;;;;N;;;;; 1D0EA;BYZANTINE MUSICAL SYMBOL ARKTIKO VOU;So;0;L;;;;;N;;;;; 1D0EB;BYZANTINE MUSICAL SYMBOL ARKTIKO GA;So;0;L;;;;;N;;;;; 1D0EC;BYZANTINE MUSICAL SYMBOL ARKTIKO DI;So;0;L;;;;;N;;;;; 1D0ED;BYZANTINE MUSICAL SYMBOL ARKTIKO KE;So;0;L;;;;;N;;;;; 1D0EE;BYZANTINE MUSICAL SYMBOL ARKTIKO ZO;So;0;L;;;;;N;;;;; 1D0EF;BYZANTINE MUSICAL SYMBOL ARKTIKO NI;So;0;L;;;;;N;;;;; 1D0F0;BYZANTINE MUSICAL SYMBOL KENTIMATA NEO MESO;So;0;L;;;;;N;;;;; 1D0F1;BYZANTINE MUSICAL SYMBOL KENTIMA NEO MESO;So;0;L;;;;;N;;;;; 1D0F2;BYZANTINE MUSICAL SYMBOL KENTIMATA NEO KATO;So;0;L;;;;;N;;;;; 1D0F3;BYZANTINE MUSICAL SYMBOL KENTIMA NEO KATO;So;0;L;;;;;N;;;;; 1D0F4;BYZANTINE MUSICAL SYMBOL KLASMA KATO;So;0;L;;;;;N;;;;; 1D0F5;BYZANTINE MUSICAL SYMBOL GORGON NEO KATO;So;0;L;;;;;N;;;;; 1D100;MUSICAL SYMBOL SINGLE BARLINE;So;0;L;;;;;N;;;;; 1D101;MUSICAL SYMBOL DOUBLE BARLINE;So;0;L;;;;;N;;;;; 1D102;MUSICAL SYMBOL FINAL BARLINE;So;0;L;;;;;N;;;;; 1D103;MUSICAL SYMBOL REVERSE FINAL BARLINE;So;0;L;;;;;N;;;;; 1D104;MUSICAL SYMBOL DASHED BARLINE;So;0;L;;;;;N;;;;; 1D105;MUSICAL SYMBOL SHORT BARLINE;So;0;L;;;;;N;;;;; 1D106;MUSICAL SYMBOL LEFT REPEAT SIGN;So;0;L;;;;;N;;;;; 1D107;MUSICAL SYMBOL RIGHT REPEAT SIGN;So;0;L;;;;;N;;;;; 1D108;MUSICAL SYMBOL REPEAT DOTS;So;0;L;;;;;N;;;;; 1D109;MUSICAL SYMBOL DAL SEGNO;So;0;L;;;;;N;;;;; 1D10A;MUSICAL SYMBOL DA CAPO;So;0;L;;;;;N;;;;; 1D10B;MUSICAL SYMBOL SEGNO;So;0;L;;;;;N;;;;; 1D10C;MUSICAL SYMBOL CODA;So;0;L;;;;;N;;;;; 1D10D;MUSICAL SYMBOL REPEATED FIGURE-1;So;0;L;;;;;N;;;;; 1D10E;MUSICAL SYMBOL REPEATED FIGURE-2;So;0;L;;;;;N;;;;; 1D10F;MUSICAL SYMBOL REPEATED FIGURE-3;So;0;L;;;;;N;;;;; 1D110;MUSICAL SYMBOL FERMATA;So;0;L;;;;;N;;;;; 1D111;MUSICAL SYMBOL FERMATA BELOW;So;0;L;;;;;N;;;;; 1D112;MUSICAL SYMBOL BREATH MARK;So;0;L;;;;;N;;;;; 1D113;MUSICAL SYMBOL CAESURA;So;0;L;;;;;N;;;;; 1D114;MUSICAL SYMBOL BRACE;So;0;L;;;;;N;;;;; 1D115;MUSICAL SYMBOL BRACKET;So;0;L;;;;;N;;;;; 1D116;MUSICAL SYMBOL ONE-LINE STAFF;So;0;L;;;;;N;;;;; 1D117;MUSICAL SYMBOL TWO-LINE STAFF;So;0;L;;;;;N;;;;; 1D118;MUSICAL SYMBOL THREE-LINE STAFF;So;0;L;;;;;N;;;;; 1D119;MUSICAL SYMBOL FOUR-LINE STAFF;So;0;L;;;;;N;;;;; 1D11A;MUSICAL SYMBOL FIVE-LINE STAFF;So;0;L;;;;;N;;;;; 1D11B;MUSICAL SYMBOL SIX-LINE STAFF;So;0;L;;;;;N;;;;; 1D11C;MUSICAL SYMBOL SIX-STRING FRETBOARD;So;0;L;;;;;N;;;;; 1D11D;MUSICAL SYMBOL FOUR-STRING FRETBOARD;So;0;L;;;;;N;;;;; 1D11E;MUSICAL SYMBOL G CLEF;So;0;L;;;;;N;;;;; 1D11F;MUSICAL SYMBOL G CLEF OTTAVA ALTA;So;0;L;;;;;N;;;;; 1D120;MUSICAL SYMBOL G CLEF OTTAVA BASSA;So;0;L;;;;;N;;;;; 1D121;MUSICAL SYMBOL C CLEF;So;0;L;;;;;N;;;;; 1D122;MUSICAL SYMBOL F CLEF;So;0;L;;;;;N;;;;; 1D123;MUSICAL SYMBOL F CLEF OTTAVA ALTA;So;0;L;;;;;N;;;;; 1D124;MUSICAL SYMBOL F CLEF OTTAVA BASSA;So;0;L;;;;;N;;;;; 1D125;MUSICAL SYMBOL DRUM CLEF-1;So;0;L;;;;;N;;;;; 1D126;MUSICAL SYMBOL DRUM CLEF-2;So;0;L;;;;;N;;;;; 1D12A;MUSICAL SYMBOL DOUBLE SHARP;So;0;L;;;;;N;;;;; 1D12B;MUSICAL SYMBOL DOUBLE FLAT;So;0;L;;;;;N;;;;; 1D12C;MUSICAL SYMBOL FLAT UP;So;0;L;;;;;N;;;;; 1D12D;MUSICAL SYMBOL FLAT DOWN;So;0;L;;;;;N;;;;; 1D12E;MUSICAL SYMBOL NATURAL UP;So;0;L;;;;;N;;;;; 1D12F;MUSICAL SYMBOL NATURAL DOWN;So;0;L;;;;;N;;;;; 1D130;MUSICAL SYMBOL SHARP UP;So;0;L;;;;;N;;;;; 1D131;MUSICAL SYMBOL SHARP DOWN;So;0;L;;;;;N;;;;; 1D132;MUSICAL SYMBOL QUARTER TONE SHARP;So;0;L;;;;;N;;;;; 1D133;MUSICAL SYMBOL QUARTER TONE FLAT;So;0;L;;;;;N;;;;; 1D134;MUSICAL SYMBOL COMMON TIME;So;0;L;;;;;N;;;;; 1D135;MUSICAL SYMBOL CUT TIME;So;0;L;;;;;N;;;;; 1D136;MUSICAL SYMBOL OTTAVA ALTA;So;0;L;;;;;N;;;;; 1D137;MUSICAL SYMBOL OTTAVA BASSA;So;0;L;;;;;N;;;;; 1D138;MUSICAL SYMBOL QUINDICESIMA ALTA;So;0;L;;;;;N;;;;; 1D139;MUSICAL SYMBOL QUINDICESIMA BASSA;So;0;L;;;;;N;;;;; 1D13A;MUSICAL SYMBOL MULTI REST;So;0;L;;;;;N;;;;; 1D13B;MUSICAL SYMBOL WHOLE REST;So;0;L;;;;;N;;;;; 1D13C;MUSICAL SYMBOL HALF REST;So;0;L;;;;;N;;;;; 1D13D;MUSICAL SYMBOL QUARTER REST;So;0;L;;;;;N;;;;; 1D13E;MUSICAL SYMBOL EIGHTH REST;So;0;L;;;;;N;;;;; 1D13F;MUSICAL SYMBOL SIXTEENTH REST;So;0;L;;;;;N;;;;; 1D140;MUSICAL SYMBOL THIRTY-SECOND REST;So;0;L;;;;;N;;;;; 1D141;MUSICAL SYMBOL SIXTY-FOURTH REST;So;0;L;;;;;N;;;;; 1D142;MUSICAL SYMBOL ONE HUNDRED TWENTY-EIGHTH REST;So;0;L;;;;;N;;;;; 1D143;MUSICAL SYMBOL X NOTEHEAD;So;0;L;;;;;N;;;;; 1D144;MUSICAL SYMBOL PLUS NOTEHEAD;So;0;L;;;;;N;;;;; 1D145;MUSICAL SYMBOL CIRCLE X NOTEHEAD;So;0;L;;;;;N;;;;; 1D146;MUSICAL SYMBOL SQUARE NOTEHEAD WHITE;So;0;L;;;;;N;;;;; 1D147;MUSICAL SYMBOL SQUARE NOTEHEAD BLACK;So;0;L;;;;;N;;;;; 1D148;MUSICAL SYMBOL TRIANGLE NOTEHEAD UP WHITE;So;0;L;;;;;N;;;;; 1D149;MUSICAL SYMBOL TRIANGLE NOTEHEAD UP BLACK;So;0;L;;;;;N;;;;; 1D14A;MUSICAL SYMBOL TRIANGLE NOTEHEAD LEFT WHITE;So;0;L;;;;;N;;;;; 1D14B;MUSICAL SYMBOL TRIANGLE NOTEHEAD LEFT BLACK;So;0;L;;;;;N;;;;; 1D14C;MUSICAL SYMBOL TRIANGLE NOTEHEAD RIGHT WHITE;So;0;L;;;;;N;;;;; 1D14D;MUSICAL SYMBOL TRIANGLE NOTEHEAD RIGHT BLACK;So;0;L;;;;;N;;;;; 1D14E;MUSICAL SYMBOL TRIANGLE NOTEHEAD DOWN WHITE;So;0;L;;;;;N;;;;; 1D14F;MUSICAL SYMBOL TRIANGLE NOTEHEAD DOWN BLACK;So;0;L;;;;;N;;;;; 1D150;MUSICAL SYMBOL TRIANGLE NOTEHEAD UP RIGHT WHITE;So;0;L;;;;;N;;;;; 1D151;MUSICAL SYMBOL TRIANGLE NOTEHEAD UP RIGHT BLACK;So;0;L;;;;;N;;;;; 1D152;MUSICAL SYMBOL MOON NOTEHEAD WHITE;So;0;L;;;;;N;;;;; 1D153;MUSICAL SYMBOL MOON NOTEHEAD BLACK;So;0;L;;;;;N;;;;; 1D154;MUSICAL SYMBOL TRIANGLE-ROUND NOTEHEAD DOWN WHITE;So;0;L;;;;;N;;;;; 1D155;MUSICAL SYMBOL TRIANGLE-ROUND NOTEHEAD DOWN BLACK;So;0;L;;;;;N;;;;; 1D156;MUSICAL SYMBOL PARENTHESIS NOTEHEAD;So;0;L;;;;;N;;;;; 1D157;MUSICAL SYMBOL VOID NOTEHEAD;So;0;L;;;;;N;;;;; 1D158;MUSICAL SYMBOL NOTEHEAD BLACK;So;0;L;;;;;N;;;;; 1D159;MUSICAL SYMBOL NULL NOTEHEAD;So;0;L;;;;;N;;;;; 1D15A;MUSICAL SYMBOL CLUSTER NOTEHEAD WHITE;So;0;L;;;;;N;;;;; 1D15B;MUSICAL SYMBOL CLUSTER NOTEHEAD BLACK;So;0;L;;;;;N;;;;; 1D15C;MUSICAL SYMBOL BREVE;So;0;L;;;;;N;;;;; 1D15D;MUSICAL SYMBOL WHOLE NOTE;So;0;L;;;;;N;;;;; 1D15E;MUSICAL SYMBOL HALF NOTE;So;0;L;1D157 1D165;;;;N;;;;; 1D15F;MUSICAL SYMBOL QUARTER NOTE;So;0;L;1D158 1D165;;;;N;;;;; 1D160;MUSICAL SYMBOL EIGHTH NOTE;So;0;L;1D15F 1D16E;;;;N;;;;; 1D161;MUSICAL SYMBOL SIXTEENTH NOTE;So;0;L;1D15F 1D16F;;;;N;;;;; 1D162;MUSICAL SYMBOL THIRTY-SECOND NOTE;So;0;L;1D15F 1D170;;;;N;;;;; 1D163;MUSICAL SYMBOL SIXTY-FOURTH NOTE;So;0;L;1D15F 1D171;;;;N;;;;; 1D164;MUSICAL SYMBOL ONE HUNDRED TWENTY-EIGHTH NOTE;So;0;L;1D15F 1D172;;;;N;;;;; 1D165;MUSICAL SYMBOL COMBINING STEM;Mc;216;L;;;;;N;;;;; 1D166;MUSICAL SYMBOL COMBINING SPRECHGESANG STEM;Mc;216;L;;;;;N;;;;; 1D167;MUSICAL SYMBOL COMBINING TREMOLO-1;Mn;1;NSM;;;;;N;;;;; 1D168;MUSICAL SYMBOL COMBINING TREMOLO-2;Mn;1;NSM;;;;;N;;;;; 1D169;MUSICAL SYMBOL COMBINING TREMOLO-3;Mn;1;NSM;;;;;N;;;;; 1D16A;MUSICAL SYMBOL FINGERED TREMOLO-1;So;0;L;;;;;N;;;;; 1D16B;MUSICAL SYMBOL FINGERED TREMOLO-2;So;0;L;;;;;N;;;;; 1D16C;MUSICAL SYMBOL FINGERED TREMOLO-3;So;0;L;;;;;N;;;;; 1D16D;MUSICAL SYMBOL COMBINING AUGMENTATION DOT;Mc;226;L;;;;;N;;;;; 1D16E;MUSICAL SYMBOL COMBINING FLAG-1;Mc;216;L;;;;;N;;;;; 1D16F;MUSICAL SYMBOL COMBINING FLAG-2;Mc;216;L;;;;;N;;;;; 1D170;MUSICAL SYMBOL COMBINING FLAG-3;Mc;216;L;;;;;N;;;;; 1D171;MUSICAL SYMBOL COMBINING FLAG-4;Mc;216;L;;;;;N;;;;; 1D172;MUSICAL SYMBOL COMBINING FLAG-5;Mc;216;L;;;;;N;;;;; 1D173;MUSICAL SYMBOL BEGIN BEAM;Cf;0;BN;;;;;N;;;;; 1D174;MUSICAL SYMBOL END BEAM;Cf;0;BN;;;;;N;;;;; 1D175;MUSICAL SYMBOL BEGIN TIE;Cf;0;BN;;;;;N;;;;; 1D176;MUSICAL SYMBOL END TIE;Cf;0;BN;;;;;N;;;;; 1D177;MUSICAL SYMBOL BEGIN SLUR;Cf;0;BN;;;;;N;;;;; 1D178;MUSICAL SYMBOL END SLUR;Cf;0;BN;;;;;N;;;;; 1D179;MUSICAL SYMBOL BEGIN PHRASE;Cf;0;BN;;;;;N;;;;; 1D17A;MUSICAL SYMBOL END PHRASE;Cf;0;BN;;;;;N;;;;; 1D17B;MUSICAL SYMBOL COMBINING ACCENT;Mn;220;NSM;;;;;N;;;;; 1D17C;MUSICAL SYMBOL COMBINING STACCATO;Mn;220;NSM;;;;;N;;;;; 1D17D;MUSICAL SYMBOL COMBINING TENUTO;Mn;220;NSM;;;;;N;;;;; 1D17E;MUSICAL SYMBOL COMBINING STACCATISSIMO;Mn;220;NSM;;;;;N;;;;; 1D17F;MUSICAL SYMBOL COMBINING MARCATO;Mn;220;NSM;;;;;N;;;;; 1D180;MUSICAL SYMBOL COMBINING MARCATO-STACCATO;Mn;220;NSM;;;;;N;;;;; 1D181;MUSICAL SYMBOL COMBINING ACCENT-STACCATO;Mn;220;NSM;;;;;N;;;;; 1D182;MUSICAL SYMBOL COMBINING LOURE;Mn;220;NSM;;;;;N;;;;; 1D183;MUSICAL SYMBOL ARPEGGIATO UP;So;0;L;;;;;N;;;;; 1D184;MUSICAL SYMBOL ARPEGGIATO DOWN;So;0;L;;;;;N;;;;; 1D185;MUSICAL SYMBOL COMBINING DOIT;Mn;230;NSM;;;;;N;;;;; 1D186;MUSICAL SYMBOL COMBINING RIP;Mn;230;NSM;;;;;N;;;;; 1D187;MUSICAL SYMBOL COMBINING FLIP;Mn;230;NSM;;;;;N;;;;; 1D188;MUSICAL SYMBOL COMBINING SMEAR;Mn;230;NSM;;;;;N;;;;; 1D189;MUSICAL SYMBOL COMBINING BEND;Mn;230;NSM;;;;;N;;;;; 1D18A;MUSICAL SYMBOL COMBINING DOUBLE TONGUE;Mn;220;NSM;;;;;N;;;;; 1D18B;MUSICAL SYMBOL COMBINING TRIPLE TONGUE;Mn;220;NSM;;;;;N;;;;; 1D18C;MUSICAL SYMBOL RINFORZANDO;So;0;L;;;;;N;;;;; 1D18D;MUSICAL SYMBOL SUBITO;So;0;L;;;;;N;;;;; 1D18E;MUSICAL SYMBOL Z;So;0;L;;;;;N;;;;; 1D18F;MUSICAL SYMBOL PIANO;So;0;L;;;;;N;;;;; 1D190;MUSICAL SYMBOL MEZZO;So;0;L;;;;;N;;;;; 1D191;MUSICAL SYMBOL FORTE;So;0;L;;;;;N;;;;; 1D192;MUSICAL SYMBOL CRESCENDO;So;0;L;;;;;N;;;;; 1D193;MUSICAL SYMBOL DECRESCENDO;So;0;L;;;;;N;;;;; 1D194;MUSICAL SYMBOL GRACE NOTE SLASH;So;0;L;;;;;N;;;;; 1D195;MUSICAL SYMBOL GRACE NOTE NO SLASH;So;0;L;;;;;N;;;;; 1D196;MUSICAL SYMBOL TR;So;0;L;;;;;N;;;;; 1D197;MUSICAL SYMBOL TURN;So;0;L;;;;;N;;;;; 1D198;MUSICAL SYMBOL INVERTED TURN;So;0;L;;;;;N;;;;; 1D199;MUSICAL SYMBOL TURN SLASH;So;0;L;;;;;N;;;;; 1D19A;MUSICAL SYMBOL TURN UP;So;0;L;;;;;N;;;;; 1D19B;MUSICAL SYMBOL ORNAMENT STROKE-1;So;0;L;;;;;N;;;;; 1D19C;MUSICAL SYMBOL ORNAMENT STROKE-2;So;0;L;;;;;N;;;;; 1D19D;MUSICAL SYMBOL ORNAMENT STROKE-3;So;0;L;;;;;N;;;;; 1D19E;MUSICAL SYMBOL ORNAMENT STROKE-4;So;0;L;;;;;N;;;;; 1D19F;MUSICAL SYMBOL ORNAMENT STROKE-5;So;0;L;;;;;N;;;;; 1D1A0;MUSICAL SYMBOL ORNAMENT STROKE-6;So;0;L;;;;;N;;;;; 1D1A1;MUSICAL SYMBOL ORNAMENT STROKE-7;So;0;L;;;;;N;;;;; 1D1A2;MUSICAL SYMBOL ORNAMENT STROKE-8;So;0;L;;;;;N;;;;; 1D1A3;MUSICAL SYMBOL ORNAMENT STROKE-9;So;0;L;;;;;N;;;;; 1D1A4;MUSICAL SYMBOL ORNAMENT STROKE-10;So;0;L;;;;;N;;;;; 1D1A5;MUSICAL SYMBOL ORNAMENT STROKE-11;So;0;L;;;;;N;;;;; 1D1A6;MUSICAL SYMBOL HAUPTSTIMME;So;0;L;;;;;N;;;;; 1D1A7;MUSICAL SYMBOL NEBENSTIMME;So;0;L;;;;;N;;;;; 1D1A8;MUSICAL SYMBOL END OF STIMME;So;0;L;;;;;N;;;;; 1D1A9;MUSICAL SYMBOL DEGREE SLASH;So;0;L;;;;;N;;;;; 1D1AA;MUSICAL SYMBOL COMBINING DOWN BOW;Mn;230;NSM;;;;;N;;;;; 1D1AB;MUSICAL SYMBOL COMBINING UP BOW;Mn;230;NSM;;;;;N;;;;; 1D1AC;MUSICAL SYMBOL COMBINING HARMONIC;Mn;230;NSM;;;;;N;;;;; 1D1AD;MUSICAL SYMBOL COMBINING SNAP PIZZICATO;Mn;230;NSM;;;;;N;;;;; 1D1AE;MUSICAL SYMBOL PEDAL MARK;So;0;L;;;;;N;;;;; 1D1AF;MUSICAL SYMBOL PEDAL UP MARK;So;0;L;;;;;N;;;;; 1D1B0;MUSICAL SYMBOL HALF PEDAL MARK;So;0;L;;;;;N;;;;; 1D1B1;MUSICAL SYMBOL GLISSANDO UP;So;0;L;;;;;N;;;;; 1D1B2;MUSICAL SYMBOL GLISSANDO DOWN;So;0;L;;;;;N;;;;; 1D1B3;MUSICAL SYMBOL WITH FINGERNAILS;So;0;L;;;;;N;;;;; 1D1B4;MUSICAL SYMBOL DAMP;So;0;L;;;;;N;;;;; 1D1B5;MUSICAL SYMBOL DAMP ALL;So;0;L;;;;;N;;;;; 1D1B6;MUSICAL SYMBOL MAXIMA;So;0;L;;;;;N;;;;; 1D1B7;MUSICAL SYMBOL LONGA;So;0;L;;;;;N;;;;; 1D1B8;MUSICAL SYMBOL BREVIS;So;0;L;;;;;N;;;;; 1D1B9;MUSICAL SYMBOL SEMIBREVIS WHITE;So;0;L;;;;;N;;;;; 1D1BA;MUSICAL SYMBOL SEMIBREVIS BLACK;So;0;L;;;;;N;;;;; 1D1BB;MUSICAL SYMBOL MINIMA;So;0;L;1D1B9 1D165;;;;N;;;;; 1D1BC;MUSICAL SYMBOL MINIMA BLACK;So;0;L;1D1BA 1D165;;;;N;;;;; 1D1BD;MUSICAL SYMBOL SEMIMINIMA WHITE;So;0;L;1D1BB 1D16E;;;;N;;;;; 1D1BE;MUSICAL SYMBOL SEMIMINIMA BLACK;So;0;L;1D1BC 1D16E;;;;N;;;;; 1D1BF;MUSICAL SYMBOL FUSA WHITE;So;0;L;1D1BB 1D16F;;;;N;;;;; 1D1C0;MUSICAL SYMBOL FUSA BLACK;So;0;L;1D1BC 1D16F;;;;N;;;;; 1D1C1;MUSICAL SYMBOL LONGA PERFECTA REST;So;0;L;;;;;N;;;;; 1D1C2;MUSICAL SYMBOL LONGA IMPERFECTA REST;So;0;L;;;;;N;;;;; 1D1C3;MUSICAL SYMBOL BREVIS REST;So;0;L;;;;;N;;;;; 1D1C4;MUSICAL SYMBOL SEMIBREVIS REST;So;0;L;;;;;N;;;;; 1D1C5;MUSICAL SYMBOL MINIMA REST;So;0;L;;;;;N;;;;; 1D1C6;MUSICAL SYMBOL SEMIMINIMA REST;So;0;L;;;;;N;;;;; 1D1C7;MUSICAL SYMBOL TEMPUS PERFECTUM CUM PROLATIONE PERFECTA;So;0;L;;;;;N;;;;; 1D1C8;MUSICAL SYMBOL TEMPUS PERFECTUM CUM PROLATIONE IMPERFECTA;So;0;L;;;;;N;;;;; 1D1C9;MUSICAL SYMBOL TEMPUS PERFECTUM CUM PROLATIONE PERFECTA DIMINUTION-1;So;0;L;;;;;N;;;;; 1D1CA;MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE PERFECTA;So;0;L;;;;;N;;;;; 1D1CB;MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE IMPERFECTA;So;0;L;;;;;N;;;;; 1D1CC;MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE IMPERFECTA DIMINUTION-1;So;0;L;;;;;N;;;;; 1D1CD;MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE IMPERFECTA DIMINUTION-2;So;0;L;;;;;N;;;;; 1D1CE;MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE IMPERFECTA DIMINUTION-3;So;0;L;;;;;N;;;;; 1D1CF;MUSICAL SYMBOL CROIX;So;0;L;;;;;N;;;;; 1D1D0;MUSICAL SYMBOL GREGORIAN C CLEF;So;0;L;;;;;N;;;;; 1D1D1;MUSICAL SYMBOL GREGORIAN F CLEF;So;0;L;;;;;N;;;;; 1D1D2;MUSICAL SYMBOL SQUARE B;So;0;L;;;;;N;;;;; 1D1D3;MUSICAL SYMBOL VIRGA;So;0;L;;;;;N;;;;; 1D1D4;MUSICAL SYMBOL PODATUS;So;0;L;;;;;N;;;;; 1D1D5;MUSICAL SYMBOL CLIVIS;So;0;L;;;;;N;;;;; 1D1D6;MUSICAL SYMBOL SCANDICUS;So;0;L;;;;;N;;;;; 1D1D7;MUSICAL SYMBOL CLIMACUS;So;0;L;;;;;N;;;;; 1D1D8;MUSICAL SYMBOL TORCULUS;So;0;L;;;;;N;;;;; 1D1D9;MUSICAL SYMBOL PORRECTUS;So;0;L;;;;;N;;;;; 1D1DA;MUSICAL SYMBOL PORRECTUS FLEXUS;So;0;L;;;;;N;;;;; 1D1DB;MUSICAL SYMBOL SCANDICUS FLEXUS;So;0;L;;;;;N;;;;; 1D1DC;MUSICAL SYMBOL TORCULUS RESUPINUS;So;0;L;;;;;N;;;;; 1D1DD;MUSICAL SYMBOL PES SUBPUNCTIS;So;0;L;;;;;N;;;;; 1D400;MATHEMATICAL BOLD CAPITAL A;Lu;0;L; 0041;;;;N;;;;; 1D401;MATHEMATICAL BOLD CAPITAL B;Lu;0;L; 0042;;;;N;;;;; 1D402;MATHEMATICAL BOLD CAPITAL C;Lu;0;L; 0043;;;;N;;;;; 1D403;MATHEMATICAL BOLD CAPITAL D;Lu;0;L; 0044;;;;N;;;;; 1D404;MATHEMATICAL BOLD CAPITAL E;Lu;0;L; 0045;;;;N;;;;; 1D405;MATHEMATICAL BOLD CAPITAL F;Lu;0;L; 0046;;;;N;;;;; 1D406;MATHEMATICAL BOLD CAPITAL G;Lu;0;L; 0047;;;;N;;;;; 1D407;MATHEMATICAL BOLD CAPITAL H;Lu;0;L; 0048;;;;N;;;;; 1D408;MATHEMATICAL BOLD CAPITAL I;Lu;0;L; 0049;;;;N;;;;; 1D409;MATHEMATICAL BOLD CAPITAL J;Lu;0;L; 004A;;;;N;;;;; 1D40A;MATHEMATICAL BOLD CAPITAL K;Lu;0;L; 004B;;;;N;;;;; 1D40B;MATHEMATICAL BOLD CAPITAL L;Lu;0;L; 004C;;;;N;;;;; 1D40C;MATHEMATICAL BOLD CAPITAL M;Lu;0;L; 004D;;;;N;;;;; 1D40D;MATHEMATICAL BOLD CAPITAL N;Lu;0;L; 004E;;;;N;;;;; 1D40E;MATHEMATICAL BOLD CAPITAL O;Lu;0;L; 004F;;;;N;;;;; 1D40F;MATHEMATICAL BOLD CAPITAL P;Lu;0;L; 0050;;;;N;;;;; 1D410;MATHEMATICAL BOLD CAPITAL Q;Lu;0;L; 0051;;;;N;;;;; 1D411;MATHEMATICAL BOLD CAPITAL R;Lu;0;L; 0052;;;;N;;;;; 1D412;MATHEMATICAL BOLD CAPITAL S;Lu;0;L; 0053;;;;N;;;;; 1D413;MATHEMATICAL BOLD CAPITAL T;Lu;0;L; 0054;;;;N;;;;; 1D414;MATHEMATICAL BOLD CAPITAL U;Lu;0;L; 0055;;;;N;;;;; 1D415;MATHEMATICAL BOLD CAPITAL V;Lu;0;L; 0056;;;;N;;;;; 1D416;MATHEMATICAL BOLD CAPITAL W;Lu;0;L; 0057;;;;N;;;;; 1D417;MATHEMATICAL BOLD CAPITAL X;Lu;0;L; 0058;;;;N;;;;; 1D418;MATHEMATICAL BOLD CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; 1D419;MATHEMATICAL BOLD CAPITAL Z;Lu;0;L; 005A;;;;N;;;;; 1D41A;MATHEMATICAL BOLD SMALL A;Ll;0;L; 0061;;;;N;;;;; 1D41B;MATHEMATICAL BOLD SMALL B;Ll;0;L; 0062;;;;N;;;;; 1D41C;MATHEMATICAL BOLD SMALL C;Ll;0;L; 0063;;;;N;;;;; 1D41D;MATHEMATICAL BOLD SMALL D;Ll;0;L; 0064;;;;N;;;;; 1D41E;MATHEMATICAL BOLD SMALL E;Ll;0;L; 0065;;;;N;;;;; 1D41F;MATHEMATICAL BOLD SMALL F;Ll;0;L; 0066;;;;N;;;;; 1D420;MATHEMATICAL BOLD SMALL G;Ll;0;L; 0067;;;;N;;;;; 1D421;MATHEMATICAL BOLD SMALL H;Ll;0;L; 0068;;;;N;;;;; 1D422;MATHEMATICAL BOLD SMALL I;Ll;0;L; 0069;;;;N;;;;; 1D423;MATHEMATICAL BOLD SMALL J;Ll;0;L; 006A;;;;N;;;;; 1D424;MATHEMATICAL BOLD SMALL K;Ll;0;L; 006B;;;;N;;;;; 1D425;MATHEMATICAL BOLD SMALL L;Ll;0;L; 006C;;;;N;;;;; 1D426;MATHEMATICAL BOLD SMALL M;Ll;0;L; 006D;;;;N;;;;; 1D427;MATHEMATICAL BOLD SMALL N;Ll;0;L; 006E;;;;N;;;;; 1D428;MATHEMATICAL BOLD SMALL O;Ll;0;L; 006F;;;;N;;;;; 1D429;MATHEMATICAL BOLD SMALL P;Ll;0;L; 0070;;;;N;;;;; 1D42A;MATHEMATICAL BOLD SMALL Q;Ll;0;L; 0071;;;;N;;;;; 1D42B;MATHEMATICAL BOLD SMALL R;Ll;0;L; 0072;;;;N;;;;; 1D42C;MATHEMATICAL BOLD SMALL S;Ll;0;L; 0073;;;;N;;;;; 1D42D;MATHEMATICAL BOLD SMALL T;Ll;0;L; 0074;;;;N;;;;; 1D42E;MATHEMATICAL BOLD SMALL U;Ll;0;L; 0075;;;;N;;;;; 1D42F;MATHEMATICAL BOLD SMALL V;Ll;0;L; 0076;;;;N;;;;; 1D430;MATHEMATICAL BOLD SMALL W;Ll;0;L; 0077;;;;N;;;;; 1D431;MATHEMATICAL BOLD SMALL X;Ll;0;L; 0078;;;;N;;;;; 1D432;MATHEMATICAL BOLD SMALL Y;Ll;0;L; 0079;;;;N;;;;; 1D433;MATHEMATICAL BOLD SMALL Z;Ll;0;L; 007A;;;;N;;;;; 1D434;MATHEMATICAL ITALIC CAPITAL A;Lu;0;L; 0041;;;;N;;;;; 1D435;MATHEMATICAL ITALIC CAPITAL B;Lu;0;L; 0042;;;;N;;;;; 1D436;MATHEMATICAL ITALIC CAPITAL C;Lu;0;L; 0043;;;;N;;;;; 1D437;MATHEMATICAL ITALIC CAPITAL D;Lu;0;L; 0044;;;;N;;;;; 1D438;MATHEMATICAL ITALIC CAPITAL E;Lu;0;L; 0045;;;;N;;;;; 1D439;MATHEMATICAL ITALIC CAPITAL F;Lu;0;L; 0046;;;;N;;;;; 1D43A;MATHEMATICAL ITALIC CAPITAL G;Lu;0;L; 0047;;;;N;;;;; 1D43B;MATHEMATICAL ITALIC CAPITAL H;Lu;0;L; 0048;;;;N;;;;; 1D43C;MATHEMATICAL ITALIC CAPITAL I;Lu;0;L; 0049;;;;N;;;;; 1D43D;MATHEMATICAL ITALIC CAPITAL J;Lu;0;L; 004A;;;;N;;;;; 1D43E;MATHEMATICAL ITALIC CAPITAL K;Lu;0;L; 004B;;;;N;;;;; 1D43F;MATHEMATICAL ITALIC CAPITAL L;Lu;0;L; 004C;;;;N;;;;; 1D440;MATHEMATICAL ITALIC CAPITAL M;Lu;0;L; 004D;;;;N;;;;; 1D441;MATHEMATICAL ITALIC CAPITAL N;Lu;0;L; 004E;;;;N;;;;; 1D442;MATHEMATICAL ITALIC CAPITAL O;Lu;0;L; 004F;;;;N;;;;; 1D443;MATHEMATICAL ITALIC CAPITAL P;Lu;0;L; 0050;;;;N;;;;; 1D444;MATHEMATICAL ITALIC CAPITAL Q;Lu;0;L; 0051;;;;N;;;;; 1D445;MATHEMATICAL ITALIC CAPITAL R;Lu;0;L; 0052;;;;N;;;;; 1D446;MATHEMATICAL ITALIC CAPITAL S;Lu;0;L; 0053;;;;N;;;;; 1D447;MATHEMATICAL ITALIC CAPITAL T;Lu;0;L; 0054;;;;N;;;;; 1D448;MATHEMATICAL ITALIC CAPITAL U;Lu;0;L; 0055;;;;N;;;;; 1D449;MATHEMATICAL ITALIC CAPITAL V;Lu;0;L; 0056;;;;N;;;;; 1D44A;MATHEMATICAL ITALIC CAPITAL W;Lu;0;L; 0057;;;;N;;;;; 1D44B;MATHEMATICAL ITALIC CAPITAL X;Lu;0;L; 0058;;;;N;;;;; 1D44C;MATHEMATICAL ITALIC CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; 1D44D;MATHEMATICAL ITALIC CAPITAL Z;Lu;0;L; 005A;;;;N;;;;; 1D44E;MATHEMATICAL ITALIC SMALL A;Ll;0;L; 0061;;;;N;;;;; 1D44F;MATHEMATICAL ITALIC SMALL B;Ll;0;L; 0062;;;;N;;;;; 1D450;MATHEMATICAL ITALIC SMALL C;Ll;0;L; 0063;;;;N;;;;; 1D451;MATHEMATICAL ITALIC SMALL D;Ll;0;L; 0064;;;;N;;;;; 1D452;MATHEMATICAL ITALIC SMALL E;Ll;0;L; 0065;;;;N;;;;; 1D453;MATHEMATICAL ITALIC SMALL F;Ll;0;L; 0066;;;;N;;;;; 1D454;MATHEMATICAL ITALIC SMALL G;Ll;0;L; 0067;;;;N;;;;; 1D456;MATHEMATICAL ITALIC SMALL I;Ll;0;L; 0069;;;;N;;;;; 1D457;MATHEMATICAL ITALIC SMALL J;Ll;0;L; 006A;;;;N;;;;; 1D458;MATHEMATICAL ITALIC SMALL K;Ll;0;L; 006B;;;;N;;;;; 1D459;MATHEMATICAL ITALIC SMALL L;Ll;0;L; 006C;;;;N;;;;; 1D45A;MATHEMATICAL ITALIC SMALL M;Ll;0;L; 006D;;;;N;;;;; 1D45B;MATHEMATICAL ITALIC SMALL N;Ll;0;L; 006E;;;;N;;;;; 1D45C;MATHEMATICAL ITALIC SMALL O;Ll;0;L; 006F;;;;N;;;;; 1D45D;MATHEMATICAL ITALIC SMALL P;Ll;0;L; 0070;;;;N;;;;; 1D45E;MATHEMATICAL ITALIC SMALL Q;Ll;0;L; 0071;;;;N;;;;; 1D45F;MATHEMATICAL ITALIC SMALL R;Ll;0;L; 0072;;;;N;;;;; 1D460;MATHEMATICAL ITALIC SMALL S;Ll;0;L; 0073;;;;N;;;;; 1D461;MATHEMATICAL ITALIC SMALL T;Ll;0;L; 0074;;;;N;;;;; 1D462;MATHEMATICAL ITALIC SMALL U;Ll;0;L; 0075;;;;N;;;;; 1D463;MATHEMATICAL ITALIC SMALL V;Ll;0;L; 0076;;;;N;;;;; 1D464;MATHEMATICAL ITALIC SMALL W;Ll;0;L; 0077;;;;N;;;;; 1D465;MATHEMATICAL ITALIC SMALL X;Ll;0;L; 0078;;;;N;;;;; 1D466;MATHEMATICAL ITALIC SMALL Y;Ll;0;L; 0079;;;;N;;;;; 1D467;MATHEMATICAL ITALIC SMALL Z;Ll;0;L; 007A;;;;N;;;;; 1D468;MATHEMATICAL BOLD ITALIC CAPITAL A;Lu;0;L; 0041;;;;N;;;;; 1D469;MATHEMATICAL BOLD ITALIC CAPITAL B;Lu;0;L; 0042;;;;N;;;;; 1D46A;MATHEMATICAL BOLD ITALIC CAPITAL C;Lu;0;L; 0043;;;;N;;;;; 1D46B;MATHEMATICAL BOLD ITALIC CAPITAL D;Lu;0;L; 0044;;;;N;;;;; 1D46C;MATHEMATICAL BOLD ITALIC CAPITAL E;Lu;0;L; 0045;;;;N;;;;; 1D46D;MATHEMATICAL BOLD ITALIC CAPITAL F;Lu;0;L; 0046;;;;N;;;;; 1D46E;MATHEMATICAL BOLD ITALIC CAPITAL G;Lu;0;L; 0047;;;;N;;;;; 1D46F;MATHEMATICAL BOLD ITALIC CAPITAL H;Lu;0;L; 0048;;;;N;;;;; 1D470;MATHEMATICAL BOLD ITALIC CAPITAL I;Lu;0;L; 0049;;;;N;;;;; 1D471;MATHEMATICAL BOLD ITALIC CAPITAL J;Lu;0;L; 004A;;;;N;;;;; 1D472;MATHEMATICAL BOLD ITALIC CAPITAL K;Lu;0;L; 004B;;;;N;;;;; 1D473;MATHEMATICAL BOLD ITALIC CAPITAL L;Lu;0;L; 004C;;;;N;;;;; 1D474;MATHEMATICAL BOLD ITALIC CAPITAL M;Lu;0;L; 004D;;;;N;;;;; 1D475;MATHEMATICAL BOLD ITALIC CAPITAL N;Lu;0;L; 004E;;;;N;;;;; 1D476;MATHEMATICAL BOLD ITALIC CAPITAL O;Lu;0;L; 004F;;;;N;;;;; 1D477;MATHEMATICAL BOLD ITALIC CAPITAL P;Lu;0;L; 0050;;;;N;;;;; 1D478;MATHEMATICAL BOLD ITALIC CAPITAL Q;Lu;0;L; 0051;;;;N;;;;; 1D479;MATHEMATICAL BOLD ITALIC CAPITAL R;Lu;0;L; 0052;;;;N;;;;; 1D47A;MATHEMATICAL BOLD ITALIC CAPITAL S;Lu;0;L; 0053;;;;N;;;;; 1D47B;MATHEMATICAL BOLD ITALIC CAPITAL T;Lu;0;L; 0054;;;;N;;;;; 1D47C;MATHEMATICAL BOLD ITALIC CAPITAL U;Lu;0;L; 0055;;;;N;;;;; 1D47D;MATHEMATICAL BOLD ITALIC CAPITAL V;Lu;0;L; 0056;;;;N;;;;; 1D47E;MATHEMATICAL BOLD ITALIC CAPITAL W;Lu;0;L; 0057;;;;N;;;;; 1D47F;MATHEMATICAL BOLD ITALIC CAPITAL X;Lu;0;L; 0058;;;;N;;;;; 1D480;MATHEMATICAL BOLD ITALIC CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; 1D481;MATHEMATICAL BOLD ITALIC CAPITAL Z;Lu;0;L; 005A;;;;N;;;;; 1D482;MATHEMATICAL BOLD ITALIC SMALL A;Ll;0;L; 0061;;;;N;;;;; 1D483;MATHEMATICAL BOLD ITALIC SMALL B;Ll;0;L; 0062;;;;N;;;;; 1D484;MATHEMATICAL BOLD ITALIC SMALL C;Ll;0;L; 0063;;;;N;;;;; 1D485;MATHEMATICAL BOLD ITALIC SMALL D;Ll;0;L; 0064;;;;N;;;;; 1D486;MATHEMATICAL BOLD ITALIC SMALL E;Ll;0;L; 0065;;;;N;;;;; 1D487;MATHEMATICAL BOLD ITALIC SMALL F;Ll;0;L; 0066;;;;N;;;;; 1D488;MATHEMATICAL BOLD ITALIC SMALL G;Ll;0;L; 0067;;;;N;;;;; 1D489;MATHEMATICAL BOLD ITALIC SMALL H;Ll;0;L; 0068;;;;N;;;;; 1D48A;MATHEMATICAL BOLD ITALIC SMALL I;Ll;0;L; 0069;;;;N;;;;; 1D48B;MATHEMATICAL BOLD ITALIC SMALL J;Ll;0;L; 006A;;;;N;;;;; 1D48C;MATHEMATICAL BOLD ITALIC SMALL K;Ll;0;L; 006B;;;;N;;;;; 1D48D;MATHEMATICAL BOLD ITALIC SMALL L;Ll;0;L; 006C;;;;N;;;;; 1D48E;MATHEMATICAL BOLD ITALIC SMALL M;Ll;0;L; 006D;;;;N;;;;; 1D48F;MATHEMATICAL BOLD ITALIC SMALL N;Ll;0;L; 006E;;;;N;;;;; 1D490;MATHEMATICAL BOLD ITALIC SMALL O;Ll;0;L; 006F;;;;N;;;;; 1D491;MATHEMATICAL BOLD ITALIC SMALL P;Ll;0;L; 0070;;;;N;;;;; 1D492;MATHEMATICAL BOLD ITALIC SMALL Q;Ll;0;L; 0071;;;;N;;;;; 1D493;MATHEMATICAL BOLD ITALIC SMALL R;Ll;0;L; 0072;;;;N;;;;; 1D494;MATHEMATICAL BOLD ITALIC SMALL S;Ll;0;L; 0073;;;;N;;;;; 1D495;MATHEMATICAL BOLD ITALIC SMALL T;Ll;0;L; 0074;;;;N;;;;; 1D496;MATHEMATICAL BOLD ITALIC SMALL U;Ll;0;L; 0075;;;;N;;;;; 1D497;MATHEMATICAL BOLD ITALIC SMALL V;Ll;0;L; 0076;;;;N;;;;; 1D498;MATHEMATICAL BOLD ITALIC SMALL W;Ll;0;L; 0077;;;;N;;;;; 1D499;MATHEMATICAL BOLD ITALIC SMALL X;Ll;0;L; 0078;;;;N;;;;; 1D49A;MATHEMATICAL BOLD ITALIC SMALL Y;Ll;0;L; 0079;;;;N;;;;; 1D49B;MATHEMATICAL BOLD ITALIC SMALL Z;Ll;0;L; 007A;;;;N;;;;; 1D49C;MATHEMATICAL SCRIPT CAPITAL A;Lu;0;L; 0041;;;;N;;;;; 1D49E;MATHEMATICAL SCRIPT CAPITAL C;Lu;0;L; 0043;;;;N;;;;; 1D49F;MATHEMATICAL SCRIPT CAPITAL D;Lu;0;L; 0044;;;;N;;;;; 1D4A2;MATHEMATICAL SCRIPT CAPITAL G;Lu;0;L; 0047;;;;N;;;;; 1D4A5;MATHEMATICAL SCRIPT CAPITAL J;Lu;0;L; 004A;;;;N;;;;; 1D4A6;MATHEMATICAL SCRIPT CAPITAL K;Lu;0;L; 004B;;;;N;;;;; 1D4A9;MATHEMATICAL SCRIPT CAPITAL N;Lu;0;L; 004E;;;;N;;;;; 1D4AA;MATHEMATICAL SCRIPT CAPITAL O;Lu;0;L; 004F;;;;N;;;;; 1D4AB;MATHEMATICAL SCRIPT CAPITAL P;Lu;0;L; 0050;;;;N;;;;; 1D4AC;MATHEMATICAL SCRIPT CAPITAL Q;Lu;0;L; 0051;;;;N;;;;; 1D4AE;MATHEMATICAL SCRIPT CAPITAL S;Lu;0;L; 0053;;;;N;;;;; 1D4AF;MATHEMATICAL SCRIPT CAPITAL T;Lu;0;L; 0054;;;;N;;;;; 1D4B0;MATHEMATICAL SCRIPT CAPITAL U;Lu;0;L; 0055;;;;N;;;;; 1D4B1;MATHEMATICAL SCRIPT CAPITAL V;Lu;0;L; 0056;;;;N;;;;; 1D4B2;MATHEMATICAL SCRIPT CAPITAL W;Lu;0;L; 0057;;;;N;;;;; 1D4B3;MATHEMATICAL SCRIPT CAPITAL X;Lu;0;L; 0058;;;;N;;;;; 1D4B4;MATHEMATICAL SCRIPT CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; 1D4B5;MATHEMATICAL SCRIPT CAPITAL Z;Lu;0;L; 005A;;;;N;;;;; 1D4B6;MATHEMATICAL SCRIPT SMALL A;Ll;0;L; 0061;;;;N;;;;; 1D4B7;MATHEMATICAL SCRIPT SMALL B;Ll;0;L; 0062;;;;N;;;;; 1D4B8;MATHEMATICAL SCRIPT SMALL C;Ll;0;L; 0063;;;;N;;;;; 1D4B9;MATHEMATICAL SCRIPT SMALL D;Ll;0;L; 0064;;;;N;;;;; 1D4BB;MATHEMATICAL SCRIPT SMALL F;Ll;0;L; 0066;;;;N;;;;; 1D4BD;MATHEMATICAL SCRIPT SMALL H;Ll;0;L; 0068;;;;N;;;;; 1D4BE;MATHEMATICAL SCRIPT SMALL I;Ll;0;L; 0069;;;;N;;;;; 1D4BF;MATHEMATICAL SCRIPT SMALL J;Ll;0;L; 006A;;;;N;;;;; 1D4C0;MATHEMATICAL SCRIPT SMALL K;Ll;0;L; 006B;;;;N;;;;; 1D4C2;MATHEMATICAL SCRIPT SMALL M;Ll;0;L; 006D;;;;N;;;;; 1D4C3;MATHEMATICAL SCRIPT SMALL N;Ll;0;L; 006E;;;;N;;;;; 1D4C5;MATHEMATICAL SCRIPT SMALL P;Ll;0;L; 0070;;;;N;;;;; 1D4C6;MATHEMATICAL SCRIPT SMALL Q;Ll;0;L; 0071;;;;N;;;;; 1D4C7;MATHEMATICAL SCRIPT SMALL R;Ll;0;L; 0072;;;;N;;;;; 1D4C8;MATHEMATICAL SCRIPT SMALL S;Ll;0;L; 0073;;;;N;;;;; 1D4C9;MATHEMATICAL SCRIPT SMALL T;Ll;0;L; 0074;;;;N;;;;; 1D4CA;MATHEMATICAL SCRIPT SMALL U;Ll;0;L; 0075;;;;N;;;;; 1D4CB;MATHEMATICAL SCRIPT SMALL V;Ll;0;L; 0076;;;;N;;;;; 1D4CC;MATHEMATICAL SCRIPT SMALL W;Ll;0;L; 0077;;;;N;;;;; 1D4CD;MATHEMATICAL SCRIPT SMALL X;Ll;0;L; 0078;;;;N;;;;; 1D4CE;MATHEMATICAL SCRIPT SMALL Y;Ll;0;L; 0079;;;;N;;;;; 1D4CF;MATHEMATICAL SCRIPT SMALL Z;Ll;0;L; 007A;;;;N;;;;; 1D4D0;MATHEMATICAL BOLD SCRIPT CAPITAL A;Lu;0;L; 0041;;;;N;;;;; 1D4D1;MATHEMATICAL BOLD SCRIPT CAPITAL B;Lu;0;L; 0042;;;;N;;;;; 1D4D2;MATHEMATICAL BOLD SCRIPT CAPITAL C;Lu;0;L; 0043;;;;N;;;;; 1D4D3;MATHEMATICAL BOLD SCRIPT CAPITAL D;Lu;0;L; 0044;;;;N;;;;; 1D4D4;MATHEMATICAL BOLD SCRIPT CAPITAL E;Lu;0;L; 0045;;;;N;;;;; 1D4D5;MATHEMATICAL BOLD SCRIPT CAPITAL F;Lu;0;L; 0046;;;;N;;;;; 1D4D6;MATHEMATICAL BOLD SCRIPT CAPITAL G;Lu;0;L; 0047;;;;N;;;;; 1D4D7;MATHEMATICAL BOLD SCRIPT CAPITAL H;Lu;0;L; 0048;;;;N;;;;; 1D4D8;MATHEMATICAL BOLD SCRIPT CAPITAL I;Lu;0;L; 0049;;;;N;;;;; 1D4D9;MATHEMATICAL BOLD SCRIPT CAPITAL J;Lu;0;L; 004A;;;;N;;;;; 1D4DA;MATHEMATICAL BOLD SCRIPT CAPITAL K;Lu;0;L; 004B;;;;N;;;;; 1D4DB;MATHEMATICAL BOLD SCRIPT CAPITAL L;Lu;0;L; 004C;;;;N;;;;; 1D4DC;MATHEMATICAL BOLD SCRIPT CAPITAL M;Lu;0;L; 004D;;;;N;;;;; 1D4DD;MATHEMATICAL BOLD SCRIPT CAPITAL N;Lu;0;L; 004E;;;;N;;;;; 1D4DE;MATHEMATICAL BOLD SCRIPT CAPITAL O;Lu;0;L; 004F;;;;N;;;;; 1D4DF;MATHEMATICAL BOLD SCRIPT CAPITAL P;Lu;0;L; 0050;;;;N;;;;; 1D4E0;MATHEMATICAL BOLD SCRIPT CAPITAL Q;Lu;0;L; 0051;;;;N;;;;; 1D4E1;MATHEMATICAL BOLD SCRIPT CAPITAL R;Lu;0;L; 0052;;;;N;;;;; 1D4E2;MATHEMATICAL BOLD SCRIPT CAPITAL S;Lu;0;L; 0053;;;;N;;;;; 1D4E3;MATHEMATICAL BOLD SCRIPT CAPITAL T;Lu;0;L; 0054;;;;N;;;;; 1D4E4;MATHEMATICAL BOLD SCRIPT CAPITAL U;Lu;0;L; 0055;;;;N;;;;; 1D4E5;MATHEMATICAL BOLD SCRIPT CAPITAL V;Lu;0;L; 0056;;;;N;;;;; 1D4E6;MATHEMATICAL BOLD SCRIPT CAPITAL W;Lu;0;L; 0057;;;;N;;;;; 1D4E7;MATHEMATICAL BOLD SCRIPT CAPITAL X;Lu;0;L; 0058;;;;N;;;;; 1D4E8;MATHEMATICAL BOLD SCRIPT CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; 1D4E9;MATHEMATICAL BOLD SCRIPT CAPITAL Z;Lu;0;L; 005A;;;;N;;;;; 1D4EA;MATHEMATICAL BOLD SCRIPT SMALL A;Ll;0;L; 0061;;;;N;;;;; 1D4EB;MATHEMATICAL BOLD SCRIPT SMALL B;Ll;0;L; 0062;;;;N;;;;; 1D4EC;MATHEMATICAL BOLD SCRIPT SMALL C;Ll;0;L; 0063;;;;N;;;;; 1D4ED;MATHEMATICAL BOLD SCRIPT SMALL D;Ll;0;L; 0064;;;;N;;;;; 1D4EE;MATHEMATICAL BOLD SCRIPT SMALL E;Ll;0;L; 0065;;;;N;;;;; 1D4EF;MATHEMATICAL BOLD SCRIPT SMALL F;Ll;0;L; 0066;;;;N;;;;; 1D4F0;MATHEMATICAL BOLD SCRIPT SMALL G;Ll;0;L; 0067;;;;N;;;;; 1D4F1;MATHEMATICAL BOLD SCRIPT SMALL H;Ll;0;L; 0068;;;;N;;;;; 1D4F2;MATHEMATICAL BOLD SCRIPT SMALL I;Ll;0;L; 0069;;;;N;;;;; 1D4F3;MATHEMATICAL BOLD SCRIPT SMALL J;Ll;0;L; 006A;;;;N;;;;; 1D4F4;MATHEMATICAL BOLD SCRIPT SMALL K;Ll;0;L; 006B;;;;N;;;;; 1D4F5;MATHEMATICAL BOLD SCRIPT SMALL L;Ll;0;L; 006C;;;;N;;;;; 1D4F6;MATHEMATICAL BOLD SCRIPT SMALL M;Ll;0;L; 006D;;;;N;;;;; 1D4F7;MATHEMATICAL BOLD SCRIPT SMALL N;Ll;0;L; 006E;;;;N;;;;; 1D4F8;MATHEMATICAL BOLD SCRIPT SMALL O;Ll;0;L; 006F;;;;N;;;;; 1D4F9;MATHEMATICAL BOLD SCRIPT SMALL P;Ll;0;L; 0070;;;;N;;;;; 1D4FA;MATHEMATICAL BOLD SCRIPT SMALL Q;Ll;0;L; 0071;;;;N;;;;; 1D4FB;MATHEMATICAL BOLD SCRIPT SMALL R;Ll;0;L; 0072;;;;N;;;;; 1D4FC;MATHEMATICAL BOLD SCRIPT SMALL S;Ll;0;L; 0073;;;;N;;;;; 1D4FD;MATHEMATICAL BOLD SCRIPT SMALL T;Ll;0;L; 0074;;;;N;;;;; 1D4FE;MATHEMATICAL BOLD SCRIPT SMALL U;Ll;0;L; 0075;;;;N;;;;; 1D4FF;MATHEMATICAL BOLD SCRIPT SMALL V;Ll;0;L; 0076;;;;N;;;;; 1D500;MATHEMATICAL BOLD SCRIPT SMALL W;Ll;0;L; 0077;;;;N;;;;; 1D501;MATHEMATICAL BOLD SCRIPT SMALL X;Ll;0;L; 0078;;;;N;;;;; 1D502;MATHEMATICAL BOLD SCRIPT SMALL Y;Ll;0;L; 0079;;;;N;;;;; 1D503;MATHEMATICAL BOLD SCRIPT SMALL Z;Ll;0;L; 007A;;;;N;;;;; 1D504;MATHEMATICAL FRAKTUR CAPITAL A;Lu;0;L; 0041;;;;N;;;;; 1D505;MATHEMATICAL FRAKTUR CAPITAL B;Lu;0;L; 0042;;;;N;;;;; 1D507;MATHEMATICAL FRAKTUR CAPITAL D;Lu;0;L; 0044;;;;N;;;;; 1D508;MATHEMATICAL FRAKTUR CAPITAL E;Lu;0;L; 0045;;;;N;;;;; 1D509;MATHEMATICAL FRAKTUR CAPITAL F;Lu;0;L; 0046;;;;N;;;;; 1D50A;MATHEMATICAL FRAKTUR CAPITAL G;Lu;0;L; 0047;;;;N;;;;; 1D50D;MATHEMATICAL FRAKTUR CAPITAL J;Lu;0;L; 004A;;;;N;;;;; 1D50E;MATHEMATICAL FRAKTUR CAPITAL K;Lu;0;L; 004B;;;;N;;;;; 1D50F;MATHEMATICAL FRAKTUR CAPITAL L;Lu;0;L; 004C;;;;N;;;;; 1D510;MATHEMATICAL FRAKTUR CAPITAL M;Lu;0;L; 004D;;;;N;;;;; 1D511;MATHEMATICAL FRAKTUR CAPITAL N;Lu;0;L; 004E;;;;N;;;;; 1D512;MATHEMATICAL FRAKTUR CAPITAL O;Lu;0;L; 004F;;;;N;;;;; 1D513;MATHEMATICAL FRAKTUR CAPITAL P;Lu;0;L; 0050;;;;N;;;;; 1D514;MATHEMATICAL FRAKTUR CAPITAL Q;Lu;0;L; 0051;;;;N;;;;; 1D516;MATHEMATICAL FRAKTUR CAPITAL S;Lu;0;L; 0053;;;;N;;;;; 1D517;MATHEMATICAL FRAKTUR CAPITAL T;Lu;0;L; 0054;;;;N;;;;; 1D518;MATHEMATICAL FRAKTUR CAPITAL U;Lu;0;L; 0055;;;;N;;;;; 1D519;MATHEMATICAL FRAKTUR CAPITAL V;Lu;0;L; 0056;;;;N;;;;; 1D51A;MATHEMATICAL FRAKTUR CAPITAL W;Lu;0;L; 0057;;;;N;;;;; 1D51B;MATHEMATICAL FRAKTUR CAPITAL X;Lu;0;L; 0058;;;;N;;;;; 1D51C;MATHEMATICAL FRAKTUR CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; 1D51E;MATHEMATICAL FRAKTUR SMALL A;Ll;0;L; 0061;;;;N;;;;; 1D51F;MATHEMATICAL FRAKTUR SMALL B;Ll;0;L; 0062;;;;N;;;;; 1D520;MATHEMATICAL FRAKTUR SMALL C;Ll;0;L; 0063;;;;N;;;;; 1D521;MATHEMATICAL FRAKTUR SMALL D;Ll;0;L; 0064;;;;N;;;;; 1D522;MATHEMATICAL FRAKTUR SMALL E;Ll;0;L; 0065;;;;N;;;;; 1D523;MATHEMATICAL FRAKTUR SMALL F;Ll;0;L; 0066;;;;N;;;;; 1D524;MATHEMATICAL FRAKTUR SMALL G;Ll;0;L; 0067;;;;N;;;;; 1D525;MATHEMATICAL FRAKTUR SMALL H;Ll;0;L; 0068;;;;N;;;;; 1D526;MATHEMATICAL FRAKTUR SMALL I;Ll;0;L; 0069;;;;N;;;;; 1D527;MATHEMATICAL FRAKTUR SMALL J;Ll;0;L; 006A;;;;N;;;;; 1D528;MATHEMATICAL FRAKTUR SMALL K;Ll;0;L; 006B;;;;N;;;;; 1D529;MATHEMATICAL FRAKTUR SMALL L;Ll;0;L; 006C;;;;N;;;;; 1D52A;MATHEMATICAL FRAKTUR SMALL M;Ll;0;L; 006D;;;;N;;;;; 1D52B;MATHEMATICAL FRAKTUR SMALL N;Ll;0;L; 006E;;;;N;;;;; 1D52C;MATHEMATICAL FRAKTUR SMALL O;Ll;0;L; 006F;;;;N;;;;; 1D52D;MATHEMATICAL FRAKTUR SMALL P;Ll;0;L; 0070;;;;N;;;;; 1D52E;MATHEMATICAL FRAKTUR SMALL Q;Ll;0;L; 0071;;;;N;;;;; 1D52F;MATHEMATICAL FRAKTUR SMALL R;Ll;0;L; 0072;;;;N;;;;; 1D530;MATHEMATICAL FRAKTUR SMALL S;Ll;0;L; 0073;;;;N;;;;; 1D531;MATHEMATICAL FRAKTUR SMALL T;Ll;0;L; 0074;;;;N;;;;; 1D532;MATHEMATICAL FRAKTUR SMALL U;Ll;0;L; 0075;;;;N;;;;; 1D533;MATHEMATICAL FRAKTUR SMALL V;Ll;0;L; 0076;;;;N;;;;; 1D534;MATHEMATICAL FRAKTUR SMALL W;Ll;0;L; 0077;;;;N;;;;; 1D535;MATHEMATICAL FRAKTUR SMALL X;Ll;0;L; 0078;;;;N;;;;; 1D536;MATHEMATICAL FRAKTUR SMALL Y;Ll;0;L; 0079;;;;N;;;;; 1D537;MATHEMATICAL FRAKTUR SMALL Z;Ll;0;L; 007A;;;;N;;;;; 1D538;MATHEMATICAL DOUBLE-STRUCK CAPITAL A;Lu;0;L; 0041;;;;N;;;;; 1D539;MATHEMATICAL DOUBLE-STRUCK CAPITAL B;Lu;0;L; 0042;;;;N;;;;; 1D53B;MATHEMATICAL DOUBLE-STRUCK CAPITAL D;Lu;0;L; 0044;;;;N;;;;; 1D53C;MATHEMATICAL DOUBLE-STRUCK CAPITAL E;Lu;0;L; 0045;;;;N;;;;; 1D53D;MATHEMATICAL DOUBLE-STRUCK CAPITAL F;Lu;0;L; 0046;;;;N;;;;; 1D53E;MATHEMATICAL DOUBLE-STRUCK CAPITAL G;Lu;0;L; 0047;;;;N;;;;; 1D540;MATHEMATICAL DOUBLE-STRUCK CAPITAL I;Lu;0;L; 0049;;;;N;;;;; 1D541;MATHEMATICAL DOUBLE-STRUCK CAPITAL J;Lu;0;L; 004A;;;;N;;;;; 1D542;MATHEMATICAL DOUBLE-STRUCK CAPITAL K;Lu;0;L; 004B;;;;N;;;;; 1D543;MATHEMATICAL DOUBLE-STRUCK CAPITAL L;Lu;0;L; 004C;;;;N;;;;; 1D544;MATHEMATICAL DOUBLE-STRUCK CAPITAL M;Lu;0;L; 004D;;;;N;;;;; 1D546;MATHEMATICAL DOUBLE-STRUCK CAPITAL O;Lu;0;L; 004F;;;;N;;;;; 1D54A;MATHEMATICAL DOUBLE-STRUCK CAPITAL S;Lu;0;L; 0053;;;;N;;;;; 1D54B;MATHEMATICAL DOUBLE-STRUCK CAPITAL T;Lu;0;L; 0054;;;;N;;;;; 1D54C;MATHEMATICAL DOUBLE-STRUCK CAPITAL U;Lu;0;L; 0055;;;;N;;;;; 1D54D;MATHEMATICAL DOUBLE-STRUCK CAPITAL V;Lu;0;L; 0056;;;;N;;;;; 1D54E;MATHEMATICAL DOUBLE-STRUCK CAPITAL W;Lu;0;L; 0057;;;;N;;;;; 1D54F;MATHEMATICAL DOUBLE-STRUCK CAPITAL X;Lu;0;L; 0058;;;;N;;;;; 1D550;MATHEMATICAL DOUBLE-STRUCK CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; 1D552;MATHEMATICAL DOUBLE-STRUCK SMALL A;Ll;0;L; 0061;;;;N;;;;; 1D553;MATHEMATICAL DOUBLE-STRUCK SMALL B;Ll;0;L; 0062;;;;N;;;;; 1D554;MATHEMATICAL DOUBLE-STRUCK SMALL C;Ll;0;L; 0063;;;;N;;;;; 1D555;MATHEMATICAL DOUBLE-STRUCK SMALL D;Ll;0;L; 0064;;;;N;;;;; 1D556;MATHEMATICAL DOUBLE-STRUCK SMALL E;Ll;0;L; 0065;;;;N;;;;; 1D557;MATHEMATICAL DOUBLE-STRUCK SMALL F;Ll;0;L; 0066;;;;N;;;;; 1D558;MATHEMATICAL DOUBLE-STRUCK SMALL G;Ll;0;L; 0067;;;;N;;;;; 1D559;MATHEMATICAL DOUBLE-STRUCK SMALL H;Ll;0;L; 0068;;;;N;;;;; 1D55A;MATHEMATICAL DOUBLE-STRUCK SMALL I;Ll;0;L; 0069;;;;N;;;;; 1D55B;MATHEMATICAL DOUBLE-STRUCK SMALL J;Ll;0;L; 006A;;;;N;;;;; 1D55C;MATHEMATICAL DOUBLE-STRUCK SMALL K;Ll;0;L; 006B;;;;N;;;;; 1D55D;MATHEMATICAL DOUBLE-STRUCK SMALL L;Ll;0;L; 006C;;;;N;;;;; 1D55E;MATHEMATICAL DOUBLE-STRUCK SMALL M;Ll;0;L; 006D;;;;N;;;;; 1D55F;MATHEMATICAL DOUBLE-STRUCK SMALL N;Ll;0;L; 006E;;;;N;;;;; 1D560;MATHEMATICAL DOUBLE-STRUCK SMALL O;Ll;0;L; 006F;;;;N;;;;; 1D561;MATHEMATICAL DOUBLE-STRUCK SMALL P;Ll;0;L; 0070;;;;N;;;;; 1D562;MATHEMATICAL DOUBLE-STRUCK SMALL Q;Ll;0;L; 0071;;;;N;;;;; 1D563;MATHEMATICAL DOUBLE-STRUCK SMALL R;Ll;0;L; 0072;;;;N;;;;; 1D564;MATHEMATICAL DOUBLE-STRUCK SMALL S;Ll;0;L; 0073;;;;N;;;;; 1D565;MATHEMATICAL DOUBLE-STRUCK SMALL T;Ll;0;L; 0074;;;;N;;;;; 1D566;MATHEMATICAL DOUBLE-STRUCK SMALL U;Ll;0;L; 0075;;;;N;;;;; 1D567;MATHEMATICAL DOUBLE-STRUCK SMALL V;Ll;0;L; 0076;;;;N;;;;; 1D568;MATHEMATICAL DOUBLE-STRUCK SMALL W;Ll;0;L; 0077;;;;N;;;;; 1D569;MATHEMATICAL DOUBLE-STRUCK SMALL X;Ll;0;L; 0078;;;;N;;;;; 1D56A;MATHEMATICAL DOUBLE-STRUCK SMALL Y;Ll;0;L; 0079;;;;N;;;;; 1D56B;MATHEMATICAL DOUBLE-STRUCK SMALL Z;Ll;0;L; 007A;;;;N;;;;; 1D56C;MATHEMATICAL BOLD FRAKTUR CAPITAL A;Lu;0;L; 0041;;;;N;;;;; 1D56D;MATHEMATICAL BOLD FRAKTUR CAPITAL B;Lu;0;L; 0042;;;;N;;;;; 1D56E;MATHEMATICAL BOLD FRAKTUR CAPITAL C;Lu;0;L; 0043;;;;N;;;;; 1D56F;MATHEMATICAL BOLD FRAKTUR CAPITAL D;Lu;0;L; 0044;;;;N;;;;; 1D570;MATHEMATICAL BOLD FRAKTUR CAPITAL E;Lu;0;L; 0045;;;;N;;;;; 1D571;MATHEMATICAL BOLD FRAKTUR CAPITAL F;Lu;0;L; 0046;;;;N;;;;; 1D572;MATHEMATICAL BOLD FRAKTUR CAPITAL G;Lu;0;L; 0047;;;;N;;;;; 1D573;MATHEMATICAL BOLD FRAKTUR CAPITAL H;Lu;0;L; 0048;;;;N;;;;; 1D574;MATHEMATICAL BOLD FRAKTUR CAPITAL I;Lu;0;L; 0049;;;;N;;;;; 1D575;MATHEMATICAL BOLD FRAKTUR CAPITAL J;Lu;0;L; 004A;;;;N;;;;; 1D576;MATHEMATICAL BOLD FRAKTUR CAPITAL K;Lu;0;L; 004B;;;;N;;;;; 1D577;MATHEMATICAL BOLD FRAKTUR CAPITAL L;Lu;0;L; 004C;;;;N;;;;; 1D578;MATHEMATICAL BOLD FRAKTUR CAPITAL M;Lu;0;L; 004D;;;;N;;;;; 1D579;MATHEMATICAL BOLD FRAKTUR CAPITAL N;Lu;0;L; 004E;;;;N;;;;; 1D57A;MATHEMATICAL BOLD FRAKTUR CAPITAL O;Lu;0;L; 004F;;;;N;;;;; 1D57B;MATHEMATICAL BOLD FRAKTUR CAPITAL P;Lu;0;L; 0050;;;;N;;;;; 1D57C;MATHEMATICAL BOLD FRAKTUR CAPITAL Q;Lu;0;L; 0051;;;;N;;;;; 1D57D;MATHEMATICAL BOLD FRAKTUR CAPITAL R;Lu;0;L; 0052;;;;N;;;;; 1D57E;MATHEMATICAL BOLD FRAKTUR CAPITAL S;Lu;0;L; 0053;;;;N;;;;; 1D57F;MATHEMATICAL BOLD FRAKTUR CAPITAL T;Lu;0;L; 0054;;;;N;;;;; 1D580;MATHEMATICAL BOLD FRAKTUR CAPITAL U;Lu;0;L; 0055;;;;N;;;;; 1D581;MATHEMATICAL BOLD FRAKTUR CAPITAL V;Lu;0;L; 0056;;;;N;;;;; 1D582;MATHEMATICAL BOLD FRAKTUR CAPITAL W;Lu;0;L; 0057;;;;N;;;;; 1D583;MATHEMATICAL BOLD FRAKTUR CAPITAL X;Lu;0;L; 0058;;;;N;;;;; 1D584;MATHEMATICAL BOLD FRAKTUR CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; 1D585;MATHEMATICAL BOLD FRAKTUR CAPITAL Z;Lu;0;L; 005A;;;;N;;;;; 1D586;MATHEMATICAL BOLD FRAKTUR SMALL A;Ll;0;L; 0061;;;;N;;;;; 1D587;MATHEMATICAL BOLD FRAKTUR SMALL B;Ll;0;L; 0062;;;;N;;;;; 1D588;MATHEMATICAL BOLD FRAKTUR SMALL C;Ll;0;L; 0063;;;;N;;;;; 1D589;MATHEMATICAL BOLD FRAKTUR SMALL D;Ll;0;L; 0064;;;;N;;;;; 1D58A;MATHEMATICAL BOLD FRAKTUR SMALL E;Ll;0;L; 0065;;;;N;;;;; 1D58B;MATHEMATICAL BOLD FRAKTUR SMALL F;Ll;0;L; 0066;;;;N;;;;; 1D58C;MATHEMATICAL BOLD FRAKTUR SMALL G;Ll;0;L; 0067;;;;N;;;;; 1D58D;MATHEMATICAL BOLD FRAKTUR SMALL H;Ll;0;L; 0068;;;;N;;;;; 1D58E;MATHEMATICAL BOLD FRAKTUR SMALL I;Ll;0;L; 0069;;;;N;;;;; 1D58F;MATHEMATICAL BOLD FRAKTUR SMALL J;Ll;0;L; 006A;;;;N;;;;; 1D590;MATHEMATICAL BOLD FRAKTUR SMALL K;Ll;0;L; 006B;;;;N;;;;; 1D591;MATHEMATICAL BOLD FRAKTUR SMALL L;Ll;0;L; 006C;;;;N;;;;; 1D592;MATHEMATICAL BOLD FRAKTUR SMALL M;Ll;0;L; 006D;;;;N;;;;; 1D593;MATHEMATICAL BOLD FRAKTUR SMALL N;Ll;0;L; 006E;;;;N;;;;; 1D594;MATHEMATICAL BOLD FRAKTUR SMALL O;Ll;0;L; 006F;;;;N;;;;; 1D595;MATHEMATICAL BOLD FRAKTUR SMALL P;Ll;0;L; 0070;;;;N;;;;; 1D596;MATHEMATICAL BOLD FRAKTUR SMALL Q;Ll;0;L; 0071;;;;N;;;;; 1D597;MATHEMATICAL BOLD FRAKTUR SMALL R;Ll;0;L; 0072;;;;N;;;;; 1D598;MATHEMATICAL BOLD FRAKTUR SMALL S;Ll;0;L; 0073;;;;N;;;;; 1D599;MATHEMATICAL BOLD FRAKTUR SMALL T;Ll;0;L; 0074;;;;N;;;;; 1D59A;MATHEMATICAL BOLD FRAKTUR SMALL U;Ll;0;L; 0075;;;;N;;;;; 1D59B;MATHEMATICAL BOLD FRAKTUR SMALL V;Ll;0;L; 0076;;;;N;;;;; 1D59C;MATHEMATICAL BOLD FRAKTUR SMALL W;Ll;0;L; 0077;;;;N;;;;; 1D59D;MATHEMATICAL BOLD FRAKTUR SMALL X;Ll;0;L; 0078;;;;N;;;;; 1D59E;MATHEMATICAL BOLD FRAKTUR SMALL Y;Ll;0;L; 0079;;;;N;;;;; 1D59F;MATHEMATICAL BOLD FRAKTUR SMALL Z;Ll;0;L; 007A;;;;N;;;;; 1D5A0;MATHEMATICAL SANS-SERIF CAPITAL A;Lu;0;L; 0041;;;;N;;;;; 1D5A1;MATHEMATICAL SANS-SERIF CAPITAL B;Lu;0;L; 0042;;;;N;;;;; 1D5A2;MATHEMATICAL SANS-SERIF CAPITAL C;Lu;0;L; 0043;;;;N;;;;; 1D5A3;MATHEMATICAL SANS-SERIF CAPITAL D;Lu;0;L; 0044;;;;N;;;;; 1D5A4;MATHEMATICAL SANS-SERIF CAPITAL E;Lu;0;L; 0045;;;;N;;;;; 1D5A5;MATHEMATICAL SANS-SERIF CAPITAL F;Lu;0;L; 0046;;;;N;;;;; 1D5A6;MATHEMATICAL SANS-SERIF CAPITAL G;Lu;0;L; 0047;;;;N;;;;; 1D5A7;MATHEMATICAL SANS-SERIF CAPITAL H;Lu;0;L; 0048;;;;N;;;;; 1D5A8;MATHEMATICAL SANS-SERIF CAPITAL I;Lu;0;L; 0049;;;;N;;;;; 1D5A9;MATHEMATICAL SANS-SERIF CAPITAL J;Lu;0;L; 004A;;;;N;;;;; 1D5AA;MATHEMATICAL SANS-SERIF CAPITAL K;Lu;0;L; 004B;;;;N;;;;; 1D5AB;MATHEMATICAL SANS-SERIF CAPITAL L;Lu;0;L; 004C;;;;N;;;;; 1D5AC;MATHEMATICAL SANS-SERIF CAPITAL M;Lu;0;L; 004D;;;;N;;;;; 1D5AD;MATHEMATICAL SANS-SERIF CAPITAL N;Lu;0;L; 004E;;;;N;;;;; 1D5AE;MATHEMATICAL SANS-SERIF CAPITAL O;Lu;0;L; 004F;;;;N;;;;; 1D5AF;MATHEMATICAL SANS-SERIF CAPITAL P;Lu;0;L; 0050;;;;N;;;;; 1D5B0;MATHEMATICAL SANS-SERIF CAPITAL Q;Lu;0;L; 0051;;;;N;;;;; 1D5B1;MATHEMATICAL SANS-SERIF CAPITAL R;Lu;0;L; 0052;;;;N;;;;; 1D5B2;MATHEMATICAL SANS-SERIF CAPITAL S;Lu;0;L; 0053;;;;N;;;;; 1D5B3;MATHEMATICAL SANS-SERIF CAPITAL T;Lu;0;L; 0054;;;;N;;;;; 1D5B4;MATHEMATICAL SANS-SERIF CAPITAL U;Lu;0;L; 0055;;;;N;;;;; 1D5B5;MATHEMATICAL SANS-SERIF CAPITAL V;Lu;0;L; 0056;;;;N;;;;; 1D5B6;MATHEMATICAL SANS-SERIF CAPITAL W;Lu;0;L; 0057;;;;N;;;;; 1D5B7;MATHEMATICAL SANS-SERIF CAPITAL X;Lu;0;L; 0058;;;;N;;;;; 1D5B8;MATHEMATICAL SANS-SERIF CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; 1D5B9;MATHEMATICAL SANS-SERIF CAPITAL Z;Lu;0;L; 005A;;;;N;;;;; 1D5BA;MATHEMATICAL SANS-SERIF SMALL A;Ll;0;L; 0061;;;;N;;;;; 1D5BB;MATHEMATICAL SANS-SERIF SMALL B;Ll;0;L; 0062;;;;N;;;;; 1D5BC;MATHEMATICAL SANS-SERIF SMALL C;Ll;0;L; 0063;;;;N;;;;; 1D5BD;MATHEMATICAL SANS-SERIF SMALL D;Ll;0;L; 0064;;;;N;;;;; 1D5BE;MATHEMATICAL SANS-SERIF SMALL E;Ll;0;L; 0065;;;;N;;;;; 1D5BF;MATHEMATICAL SANS-SERIF SMALL F;Ll;0;L; 0066;;;;N;;;;; 1D5C0;MATHEMATICAL SANS-SERIF SMALL G;Ll;0;L; 0067;;;;N;;;;; 1D5C1;MATHEMATICAL SANS-SERIF SMALL H;Ll;0;L; 0068;;;;N;;;;; 1D5C2;MATHEMATICAL SANS-SERIF SMALL I;Ll;0;L; 0069;;;;N;;;;; 1D5C3;MATHEMATICAL SANS-SERIF SMALL J;Ll;0;L; 006A;;;;N;;;;; 1D5C4;MATHEMATICAL SANS-SERIF SMALL K;Ll;0;L; 006B;;;;N;;;;; 1D5C5;MATHEMATICAL SANS-SERIF SMALL L;Ll;0;L; 006C;;;;N;;;;; 1D5C6;MATHEMATICAL SANS-SERIF SMALL M;Ll;0;L; 006D;;;;N;;;;; 1D5C7;MATHEMATICAL SANS-SERIF SMALL N;Ll;0;L; 006E;;;;N;;;;; 1D5C8;MATHEMATICAL SANS-SERIF SMALL O;Ll;0;L; 006F;;;;N;;;;; 1D5C9;MATHEMATICAL SANS-SERIF SMALL P;Ll;0;L; 0070;;;;N;;;;; 1D5CA;MATHEMATICAL SANS-SERIF SMALL Q;Ll;0;L; 0071;;;;N;;;;; 1D5CB;MATHEMATICAL SANS-SERIF SMALL R;Ll;0;L; 0072;;;;N;;;;; 1D5CC;MATHEMATICAL SANS-SERIF SMALL S;Ll;0;L; 0073;;;;N;;;;; 1D5CD;MATHEMATICAL SANS-SERIF SMALL T;Ll;0;L; 0074;;;;N;;;;; 1D5CE;MATHEMATICAL SANS-SERIF SMALL U;Ll;0;L; 0075;;;;N;;;;; 1D5CF;MATHEMATICAL SANS-SERIF SMALL V;Ll;0;L; 0076;;;;N;;;;; 1D5D0;MATHEMATICAL SANS-SERIF SMALL W;Ll;0;L; 0077;;;;N;;;;; 1D5D1;MATHEMATICAL SANS-SERIF SMALL X;Ll;0;L; 0078;;;;N;;;;; 1D5D2;MATHEMATICAL SANS-SERIF SMALL Y;Ll;0;L; 0079;;;;N;;;;; 1D5D3;MATHEMATICAL SANS-SERIF SMALL Z;Ll;0;L; 007A;;;;N;;;;; 1D5D4;MATHEMATICAL SANS-SERIF BOLD CAPITAL A;Lu;0;L; 0041;;;;N;;;;; 1D5D5;MATHEMATICAL SANS-SERIF BOLD CAPITAL B;Lu;0;L; 0042;;;;N;;;;; 1D5D6;MATHEMATICAL SANS-SERIF BOLD CAPITAL C;Lu;0;L; 0043;;;;N;;;;; 1D5D7;MATHEMATICAL SANS-SERIF BOLD CAPITAL D;Lu;0;L; 0044;;;;N;;;;; 1D5D8;MATHEMATICAL SANS-SERIF BOLD CAPITAL E;Lu;0;L; 0045;;;;N;;;;; 1D5D9;MATHEMATICAL SANS-SERIF BOLD CAPITAL F;Lu;0;L; 0046;;;;N;;;;; 1D5DA;MATHEMATICAL SANS-SERIF BOLD CAPITAL G;Lu;0;L; 0047;;;;N;;;;; 1D5DB;MATHEMATICAL SANS-SERIF BOLD CAPITAL H;Lu;0;L; 0048;;;;N;;;;; 1D5DC;MATHEMATICAL SANS-SERIF BOLD CAPITAL I;Lu;0;L; 0049;;;;N;;;;; 1D5DD;MATHEMATICAL SANS-SERIF BOLD CAPITAL J;Lu;0;L; 004A;;;;N;;;;; 1D5DE;MATHEMATICAL SANS-SERIF BOLD CAPITAL K;Lu;0;L; 004B;;;;N;;;;; 1D5DF;MATHEMATICAL SANS-SERIF BOLD CAPITAL L;Lu;0;L; 004C;;;;N;;;;; 1D5E0;MATHEMATICAL SANS-SERIF BOLD CAPITAL M;Lu;0;L; 004D;;;;N;;;;; 1D5E1;MATHEMATICAL SANS-SERIF BOLD CAPITAL N;Lu;0;L; 004E;;;;N;;;;; 1D5E2;MATHEMATICAL SANS-SERIF BOLD CAPITAL O;Lu;0;L; 004F;;;;N;;;;; 1D5E3;MATHEMATICAL SANS-SERIF BOLD CAPITAL P;Lu;0;L; 0050;;;;N;;;;; 1D5E4;MATHEMATICAL SANS-SERIF BOLD CAPITAL Q;Lu;0;L; 0051;;;;N;;;;; 1D5E5;MATHEMATICAL SANS-SERIF BOLD CAPITAL R;Lu;0;L; 0052;;;;N;;;;; 1D5E6;MATHEMATICAL SANS-SERIF BOLD CAPITAL S;Lu;0;L; 0053;;;;N;;;;; 1D5E7;MATHEMATICAL SANS-SERIF BOLD CAPITAL T;Lu;0;L; 0054;;;;N;;;;; 1D5E8;MATHEMATICAL SANS-SERIF BOLD CAPITAL U;Lu;0;L; 0055;;;;N;;;;; 1D5E9;MATHEMATICAL SANS-SERIF BOLD CAPITAL V;Lu;0;L; 0056;;;;N;;;;; 1D5EA;MATHEMATICAL SANS-SERIF BOLD CAPITAL W;Lu;0;L; 0057;;;;N;;;;; 1D5EB;MATHEMATICAL SANS-SERIF BOLD CAPITAL X;Lu;0;L; 0058;;;;N;;;;; 1D5EC;MATHEMATICAL SANS-SERIF BOLD CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; 1D5ED;MATHEMATICAL SANS-SERIF BOLD CAPITAL Z;Lu;0;L; 005A;;;;N;;;;; 1D5EE;MATHEMATICAL SANS-SERIF BOLD SMALL A;Ll;0;L; 0061;;;;N;;;;; 1D5EF;MATHEMATICAL SANS-SERIF BOLD SMALL B;Ll;0;L; 0062;;;;N;;;;; 1D5F0;MATHEMATICAL SANS-SERIF BOLD SMALL C;Ll;0;L; 0063;;;;N;;;;; 1D5F1;MATHEMATICAL SANS-SERIF BOLD SMALL D;Ll;0;L; 0064;;;;N;;;;; 1D5F2;MATHEMATICAL SANS-SERIF BOLD SMALL E;Ll;0;L; 0065;;;;N;;;;; 1D5F3;MATHEMATICAL SANS-SERIF BOLD SMALL F;Ll;0;L; 0066;;;;N;;;;; 1D5F4;MATHEMATICAL SANS-SERIF BOLD SMALL G;Ll;0;L; 0067;;;;N;;;;; 1D5F5;MATHEMATICAL SANS-SERIF BOLD SMALL H;Ll;0;L; 0068;;;;N;;;;; 1D5F6;MATHEMATICAL SANS-SERIF BOLD SMALL I;Ll;0;L; 0069;;;;N;;;;; 1D5F7;MATHEMATICAL SANS-SERIF BOLD SMALL J;Ll;0;L; 006A;;;;N;;;;; 1D5F8;MATHEMATICAL SANS-SERIF BOLD SMALL K;Ll;0;L; 006B;;;;N;;;;; 1D5F9;MATHEMATICAL SANS-SERIF BOLD SMALL L;Ll;0;L; 006C;;;;N;;;;; 1D5FA;MATHEMATICAL SANS-SERIF BOLD SMALL M;Ll;0;L; 006D;;;;N;;;;; 1D5FB;MATHEMATICAL SANS-SERIF BOLD SMALL N;Ll;0;L; 006E;;;;N;;;;; 1D5FC;MATHEMATICAL SANS-SERIF BOLD SMALL O;Ll;0;L; 006F;;;;N;;;;; 1D5FD;MATHEMATICAL SANS-SERIF BOLD SMALL P;Ll;0;L; 0070;;;;N;;;;; 1D5FE;MATHEMATICAL SANS-SERIF BOLD SMALL Q;Ll;0;L; 0071;;;;N;;;;; 1D5FF;MATHEMATICAL SANS-SERIF BOLD SMALL R;Ll;0;L; 0072;;;;N;;;;; 1D600;MATHEMATICAL SANS-SERIF BOLD SMALL S;Ll;0;L; 0073;;;;N;;;;; 1D601;MATHEMATICAL SANS-SERIF BOLD SMALL T;Ll;0;L; 0074;;;;N;;;;; 1D602;MATHEMATICAL SANS-SERIF BOLD SMALL U;Ll;0;L; 0075;;;;N;;;;; 1D603;MATHEMATICAL SANS-SERIF BOLD SMALL V;Ll;0;L; 0076;;;;N;;;;; 1D604;MATHEMATICAL SANS-SERIF BOLD SMALL W;Ll;0;L; 0077;;;;N;;;;; 1D605;MATHEMATICAL SANS-SERIF BOLD SMALL X;Ll;0;L; 0078;;;;N;;;;; 1D606;MATHEMATICAL SANS-SERIF BOLD SMALL Y;Ll;0;L; 0079;;;;N;;;;; 1D607;MATHEMATICAL SANS-SERIF BOLD SMALL Z;Ll;0;L; 007A;;;;N;;;;; 1D608;MATHEMATICAL SANS-SERIF ITALIC CAPITAL A;Lu;0;L; 0041;;;;N;;;;; 1D609;MATHEMATICAL SANS-SERIF ITALIC CAPITAL B;Lu;0;L; 0042;;;;N;;;;; 1D60A;MATHEMATICAL SANS-SERIF ITALIC CAPITAL C;Lu;0;L; 0043;;;;N;;;;; 1D60B;MATHEMATICAL SANS-SERIF ITALIC CAPITAL D;Lu;0;L; 0044;;;;N;;;;; 1D60C;MATHEMATICAL SANS-SERIF ITALIC CAPITAL E;Lu;0;L; 0045;;;;N;;;;; 1D60D;MATHEMATICAL SANS-SERIF ITALIC CAPITAL F;Lu;0;L; 0046;;;;N;;;;; 1D60E;MATHEMATICAL SANS-SERIF ITALIC CAPITAL G;Lu;0;L; 0047;;;;N;;;;; 1D60F;MATHEMATICAL SANS-SERIF ITALIC CAPITAL H;Lu;0;L; 0048;;;;N;;;;; 1D610;MATHEMATICAL SANS-SERIF ITALIC CAPITAL I;Lu;0;L; 0049;;;;N;;;;; 1D611;MATHEMATICAL SANS-SERIF ITALIC CAPITAL J;Lu;0;L; 004A;;;;N;;;;; 1D612;MATHEMATICAL SANS-SERIF ITALIC CAPITAL K;Lu;0;L; 004B;;;;N;;;;; 1D613;MATHEMATICAL SANS-SERIF ITALIC CAPITAL L;Lu;0;L; 004C;;;;N;;;;; 1D614;MATHEMATICAL SANS-SERIF ITALIC CAPITAL M;Lu;0;L; 004D;;;;N;;;;; 1D615;MATHEMATICAL SANS-SERIF ITALIC CAPITAL N;Lu;0;L; 004E;;;;N;;;;; 1D616;MATHEMATICAL SANS-SERIF ITALIC CAPITAL O;Lu;0;L; 004F;;;;N;;;;; 1D617;MATHEMATICAL SANS-SERIF ITALIC CAPITAL P;Lu;0;L; 0050;;;;N;;;;; 1D618;MATHEMATICAL SANS-SERIF ITALIC CAPITAL Q;Lu;0;L; 0051;;;;N;;;;; 1D619;MATHEMATICAL SANS-SERIF ITALIC CAPITAL R;Lu;0;L; 0052;;;;N;;;;; 1D61A;MATHEMATICAL SANS-SERIF ITALIC CAPITAL S;Lu;0;L; 0053;;;;N;;;;; 1D61B;MATHEMATICAL SANS-SERIF ITALIC CAPITAL T;Lu;0;L; 0054;;;;N;;;;; 1D61C;MATHEMATICAL SANS-SERIF ITALIC CAPITAL U;Lu;0;L; 0055;;;;N;;;;; 1D61D;MATHEMATICAL SANS-SERIF ITALIC CAPITAL V;Lu;0;L; 0056;;;;N;;;;; 1D61E;MATHEMATICAL SANS-SERIF ITALIC CAPITAL W;Lu;0;L; 0057;;;;N;;;;; 1D61F;MATHEMATICAL SANS-SERIF ITALIC CAPITAL X;Lu;0;L; 0058;;;;N;;;;; 1D620;MATHEMATICAL SANS-SERIF ITALIC CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; 1D621;MATHEMATICAL SANS-SERIF ITALIC CAPITAL Z;Lu;0;L; 005A;;;;N;;;;; 1D622;MATHEMATICAL SANS-SERIF ITALIC SMALL A;Ll;0;L; 0061;;;;N;;;;; 1D623;MATHEMATICAL SANS-SERIF ITALIC SMALL B;Ll;0;L; 0062;;;;N;;;;; 1D624;MATHEMATICAL SANS-SERIF ITALIC SMALL C;Ll;0;L; 0063;;;;N;;;;; 1D625;MATHEMATICAL SANS-SERIF ITALIC SMALL D;Ll;0;L; 0064;;;;N;;;;; 1D626;MATHEMATICAL SANS-SERIF ITALIC SMALL E;Ll;0;L; 0065;;;;N;;;;; 1D627;MATHEMATICAL SANS-SERIF ITALIC SMALL F;Ll;0;L; 0066;;;;N;;;;; 1D628;MATHEMATICAL SANS-SERIF ITALIC SMALL G;Ll;0;L; 0067;;;;N;;;;; 1D629;MATHEMATICAL SANS-SERIF ITALIC SMALL H;Ll;0;L; 0068;;;;N;;;;; 1D62A;MATHEMATICAL SANS-SERIF ITALIC SMALL I;Ll;0;L; 0069;;;;N;;;;; 1D62B;MATHEMATICAL SANS-SERIF ITALIC SMALL J;Ll;0;L; 006A;;;;N;;;;; 1D62C;MATHEMATICAL SANS-SERIF ITALIC SMALL K;Ll;0;L; 006B;;;;N;;;;; 1D62D;MATHEMATICAL SANS-SERIF ITALIC SMALL L;Ll;0;L; 006C;;;;N;;;;; 1D62E;MATHEMATICAL SANS-SERIF ITALIC SMALL M;Ll;0;L; 006D;;;;N;;;;; 1D62F;MATHEMATICAL SANS-SERIF ITALIC SMALL N;Ll;0;L; 006E;;;;N;;;;; 1D630;MATHEMATICAL SANS-SERIF ITALIC SMALL O;Ll;0;L; 006F;;;;N;;;;; 1D631;MATHEMATICAL SANS-SERIF ITALIC SMALL P;Ll;0;L; 0070;;;;N;;;;; 1D632;MATHEMATICAL SANS-SERIF ITALIC SMALL Q;Ll;0;L; 0071;;;;N;;;;; 1D633;MATHEMATICAL SANS-SERIF ITALIC SMALL R;Ll;0;L; 0072;;;;N;;;;; 1D634;MATHEMATICAL SANS-SERIF ITALIC SMALL S;Ll;0;L; 0073;;;;N;;;;; 1D635;MATHEMATICAL SANS-SERIF ITALIC SMALL T;Ll;0;L; 0074;;;;N;;;;; 1D636;MATHEMATICAL SANS-SERIF ITALIC SMALL U;Ll;0;L; 0075;;;;N;;;;; 1D637;MATHEMATICAL SANS-SERIF ITALIC SMALL V;Ll;0;L; 0076;;;;N;;;;; 1D638;MATHEMATICAL SANS-SERIF ITALIC SMALL W;Ll;0;L; 0077;;;;N;;;;; 1D639;MATHEMATICAL SANS-SERIF ITALIC SMALL X;Ll;0;L; 0078;;;;N;;;;; 1D63A;MATHEMATICAL SANS-SERIF ITALIC SMALL Y;Ll;0;L; 0079;;;;N;;;;; 1D63B;MATHEMATICAL SANS-SERIF ITALIC SMALL Z;Ll;0;L; 007A;;;;N;;;;; 1D63C;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL A;Lu;0;L; 0041;;;;N;;;;; 1D63D;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL B;Lu;0;L; 0042;;;;N;;;;; 1D63E;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL C;Lu;0;L; 0043;;;;N;;;;; 1D63F;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL D;Lu;0;L; 0044;;;;N;;;;; 1D640;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL E;Lu;0;L; 0045;;;;N;;;;; 1D641;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL F;Lu;0;L; 0046;;;;N;;;;; 1D642;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL G;Lu;0;L; 0047;;;;N;;;;; 1D643;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL H;Lu;0;L; 0048;;;;N;;;;; 1D644;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL I;Lu;0;L; 0049;;;;N;;;;; 1D645;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL J;Lu;0;L; 004A;;;;N;;;;; 1D646;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL K;Lu;0;L; 004B;;;;N;;;;; 1D647;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL L;Lu;0;L; 004C;;;;N;;;;; 1D648;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL M;Lu;0;L; 004D;;;;N;;;;; 1D649;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL N;Lu;0;L; 004E;;;;N;;;;; 1D64A;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL O;Lu;0;L; 004F;;;;N;;;;; 1D64B;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL P;Lu;0;L; 0050;;;;N;;;;; 1D64C;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Q;Lu;0;L; 0051;;;;N;;;;; 1D64D;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL R;Lu;0;L; 0052;;;;N;;;;; 1D64E;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL S;Lu;0;L; 0053;;;;N;;;;; 1D64F;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL T;Lu;0;L; 0054;;;;N;;;;; 1D650;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL U;Lu;0;L; 0055;;;;N;;;;; 1D651;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL V;Lu;0;L; 0056;;;;N;;;;; 1D652;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL W;Lu;0;L; 0057;;;;N;;;;; 1D653;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL X;Lu;0;L; 0058;;;;N;;;;; 1D654;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; 1D655;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Z;Lu;0;L; 005A;;;;N;;;;; 1D656;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL A;Ll;0;L; 0061;;;;N;;;;; 1D657;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL B;Ll;0;L; 0062;;;;N;;;;; 1D658;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL C;Ll;0;L; 0063;;;;N;;;;; 1D659;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL D;Ll;0;L; 0064;;;;N;;;;; 1D65A;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL E;Ll;0;L; 0065;;;;N;;;;; 1D65B;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL F;Ll;0;L; 0066;;;;N;;;;; 1D65C;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL G;Ll;0;L; 0067;;;;N;;;;; 1D65D;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL H;Ll;0;L; 0068;;;;N;;;;; 1D65E;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL I;Ll;0;L; 0069;;;;N;;;;; 1D65F;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL J;Ll;0;L; 006A;;;;N;;;;; 1D660;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL K;Ll;0;L; 006B;;;;N;;;;; 1D661;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL L;Ll;0;L; 006C;;;;N;;;;; 1D662;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL M;Ll;0;L; 006D;;;;N;;;;; 1D663;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL N;Ll;0;L; 006E;;;;N;;;;; 1D664;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL O;Ll;0;L; 006F;;;;N;;;;; 1D665;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL P;Ll;0;L; 0070;;;;N;;;;; 1D666;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Q;Ll;0;L; 0071;;;;N;;;;; 1D667;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL R;Ll;0;L; 0072;;;;N;;;;; 1D668;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL S;Ll;0;L; 0073;;;;N;;;;; 1D669;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL T;Ll;0;L; 0074;;;;N;;;;; 1D66A;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL U;Ll;0;L; 0075;;;;N;;;;; 1D66B;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL V;Ll;0;L; 0076;;;;N;;;;; 1D66C;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL W;Ll;0;L; 0077;;;;N;;;;; 1D66D;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL X;Ll;0;L; 0078;;;;N;;;;; 1D66E;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Y;Ll;0;L; 0079;;;;N;;;;; 1D66F;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Z;Ll;0;L; 007A;;;;N;;;;; 1D670;MATHEMATICAL MONOSPACE CAPITAL A;Lu;0;L; 0041;;;;N;;;;; 1D671;MATHEMATICAL MONOSPACE CAPITAL B;Lu;0;L; 0042;;;;N;;;;; 1D672;MATHEMATICAL MONOSPACE CAPITAL C;Lu;0;L; 0043;;;;N;;;;; 1D673;MATHEMATICAL MONOSPACE CAPITAL D;Lu;0;L; 0044;;;;N;;;;; 1D674;MATHEMATICAL MONOSPACE CAPITAL E;Lu;0;L; 0045;;;;N;;;;; 1D675;MATHEMATICAL MONOSPACE CAPITAL F;Lu;0;L; 0046;;;;N;;;;; 1D676;MATHEMATICAL MONOSPACE CAPITAL G;Lu;0;L; 0047;;;;N;;;;; 1D677;MATHEMATICAL MONOSPACE CAPITAL H;Lu;0;L; 0048;;;;N;;;;; 1D678;MATHEMATICAL MONOSPACE CAPITAL I;Lu;0;L; 0049;;;;N;;;;; 1D679;MATHEMATICAL MONOSPACE CAPITAL J;Lu;0;L; 004A;;;;N;;;;; 1D67A;MATHEMATICAL MONOSPACE CAPITAL K;Lu;0;L; 004B;;;;N;;;;; 1D67B;MATHEMATICAL MONOSPACE CAPITAL L;Lu;0;L; 004C;;;;N;;;;; 1D67C;MATHEMATICAL MONOSPACE CAPITAL M;Lu;0;L; 004D;;;;N;;;;; 1D67D;MATHEMATICAL MONOSPACE CAPITAL N;Lu;0;L; 004E;;;;N;;;;; 1D67E;MATHEMATICAL MONOSPACE CAPITAL O;Lu;0;L; 004F;;;;N;;;;; 1D67F;MATHEMATICAL MONOSPACE CAPITAL P;Lu;0;L; 0050;;;;N;;;;; 1D680;MATHEMATICAL MONOSPACE CAPITAL Q;Lu;0;L; 0051;;;;N;;;;; 1D681;MATHEMATICAL MONOSPACE CAPITAL R;Lu;0;L; 0052;;;;N;;;;; 1D682;MATHEMATICAL MONOSPACE CAPITAL S;Lu;0;L; 0053;;;;N;;;;; 1D683;MATHEMATICAL MONOSPACE CAPITAL T;Lu;0;L; 0054;;;;N;;;;; 1D684;MATHEMATICAL MONOSPACE CAPITAL U;Lu;0;L; 0055;;;;N;;;;; 1D685;MATHEMATICAL MONOSPACE CAPITAL V;Lu;0;L; 0056;;;;N;;;;; 1D686;MATHEMATICAL MONOSPACE CAPITAL W;Lu;0;L; 0057;;;;N;;;;; 1D687;MATHEMATICAL MONOSPACE CAPITAL X;Lu;0;L; 0058;;;;N;;;;; 1D688;MATHEMATICAL MONOSPACE CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; 1D689;MATHEMATICAL MONOSPACE CAPITAL Z;Lu;0;L; 005A;;;;N;;;;; 1D68A;MATHEMATICAL MONOSPACE SMALL A;Ll;0;L; 0061;;;;N;;;;; 1D68B;MATHEMATICAL MONOSPACE SMALL B;Ll;0;L; 0062;;;;N;;;;; 1D68C;MATHEMATICAL MONOSPACE SMALL C;Ll;0;L; 0063;;;;N;;;;; 1D68D;MATHEMATICAL MONOSPACE SMALL D;Ll;0;L; 0064;;;;N;;;;; 1D68E;MATHEMATICAL MONOSPACE SMALL E;Ll;0;L; 0065;;;;N;;;;; 1D68F;MATHEMATICAL MONOSPACE SMALL F;Ll;0;L; 0066;;;;N;;;;; 1D690;MATHEMATICAL MONOSPACE SMALL G;Ll;0;L; 0067;;;;N;;;;; 1D691;MATHEMATICAL MONOSPACE SMALL H;Ll;0;L; 0068;;;;N;;;;; 1D692;MATHEMATICAL MONOSPACE SMALL I;Ll;0;L; 0069;;;;N;;;;; 1D693;MATHEMATICAL MONOSPACE SMALL J;Ll;0;L; 006A;;;;N;;;;; 1D694;MATHEMATICAL MONOSPACE SMALL K;Ll;0;L; 006B;;;;N;;;;; 1D695;MATHEMATICAL MONOSPACE SMALL L;Ll;0;L; 006C;;;;N;;;;; 1D696;MATHEMATICAL MONOSPACE SMALL M;Ll;0;L; 006D;;;;N;;;;; 1D697;MATHEMATICAL MONOSPACE SMALL N;Ll;0;L; 006E;;;;N;;;;; 1D698;MATHEMATICAL MONOSPACE SMALL O;Ll;0;L; 006F;;;;N;;;;; 1D699;MATHEMATICAL MONOSPACE SMALL P;Ll;0;L; 0070;;;;N;;;;; 1D69A;MATHEMATICAL MONOSPACE SMALL Q;Ll;0;L; 0071;;;;N;;;;; 1D69B;MATHEMATICAL MONOSPACE SMALL R;Ll;0;L; 0072;;;;N;;;;; 1D69C;MATHEMATICAL MONOSPACE SMALL S;Ll;0;L; 0073;;;;N;;;;; 1D69D;MATHEMATICAL MONOSPACE SMALL T;Ll;0;L; 0074;;;;N;;;;; 1D69E;MATHEMATICAL MONOSPACE SMALL U;Ll;0;L; 0075;;;;N;;;;; 1D69F;MATHEMATICAL MONOSPACE SMALL V;Ll;0;L; 0076;;;;N;;;;; 1D6A0;MATHEMATICAL MONOSPACE SMALL W;Ll;0;L; 0077;;;;N;;;;; 1D6A1;MATHEMATICAL MONOSPACE SMALL X;Ll;0;L; 0078;;;;N;;;;; 1D6A2;MATHEMATICAL MONOSPACE SMALL Y;Ll;0;L; 0079;;;;N;;;;; 1D6A3;MATHEMATICAL MONOSPACE SMALL Z;Ll;0;L; 007A;;;;N;;;;; 1D6A8;MATHEMATICAL BOLD CAPITAL ALPHA;Lu;0;L; 0391;;;;N;;;;; 1D6A9;MATHEMATICAL BOLD CAPITAL BETA;Lu;0;L; 0392;;;;N;;;;; 1D6AA;MATHEMATICAL BOLD CAPITAL GAMMA;Lu;0;L; 0393;;;;N;;;;; 1D6AB;MATHEMATICAL BOLD CAPITAL DELTA;Lu;0;L; 0394;;;;N;;;;; 1D6AC;MATHEMATICAL BOLD CAPITAL EPSILON;Lu;0;L; 0395;;;;N;;;;; 1D6AD;MATHEMATICAL BOLD CAPITAL ZETA;Lu;0;L; 0396;;;;N;;;;; 1D6AE;MATHEMATICAL BOLD CAPITAL ETA;Lu;0;L; 0397;;;;N;;;;; 1D6AF;MATHEMATICAL BOLD CAPITAL THETA;Lu;0;L; 0398;;;;N;;;;; 1D6B0;MATHEMATICAL BOLD CAPITAL IOTA;Lu;0;L; 0399;;;;N;;;;; 1D6B1;MATHEMATICAL BOLD CAPITAL KAPPA;Lu;0;L; 039A;;;;N;;;;; 1D6B2;MATHEMATICAL BOLD CAPITAL LAMDA;Lu;0;L; 039B;;;;N;;;;; 1D6B3;MATHEMATICAL BOLD CAPITAL MU;Lu;0;L; 039C;;;;N;;;;; 1D6B4;MATHEMATICAL BOLD CAPITAL NU;Lu;0;L; 039D;;;;N;;;;; 1D6B5;MATHEMATICAL BOLD CAPITAL XI;Lu;0;L; 039E;;;;N;;;;; 1D6B6;MATHEMATICAL BOLD CAPITAL OMICRON;Lu;0;L; 039F;;;;N;;;;; 1D6B7;MATHEMATICAL BOLD CAPITAL PI;Lu;0;L; 03A0;;;;N;;;;; 1D6B8;MATHEMATICAL BOLD CAPITAL RHO;Lu;0;L; 03A1;;;;N;;;;; 1D6B9;MATHEMATICAL BOLD CAPITAL THETA SYMBOL;Lu;0;L; 03F4;;;;N;;;;; 1D6BA;MATHEMATICAL BOLD CAPITAL SIGMA;Lu;0;L; 03A3;;;;N;;;;; 1D6BB;MATHEMATICAL BOLD CAPITAL TAU;Lu;0;L; 03A4;;;;N;;;;; 1D6BC;MATHEMATICAL BOLD CAPITAL UPSILON;Lu;0;L; 03A5;;;;N;;;;; 1D6BD;MATHEMATICAL BOLD CAPITAL PHI;Lu;0;L; 03A6;;;;N;;;;; 1D6BE;MATHEMATICAL BOLD CAPITAL CHI;Lu;0;L; 03A7;;;;N;;;;; 1D6BF;MATHEMATICAL BOLD CAPITAL PSI;Lu;0;L; 03A8;;;;N;;;;; 1D6C0;MATHEMATICAL BOLD CAPITAL OMEGA;Lu;0;L; 03A9;;;;N;;;;; 1D6C1;MATHEMATICAL BOLD NABLA;Sm;0;L; 2207;;;;N;;;;; 1D6C2;MATHEMATICAL BOLD SMALL ALPHA;Ll;0;L; 03B1;;;;N;;;;; 1D6C3;MATHEMATICAL BOLD SMALL BETA;Ll;0;L; 03B2;;;;N;;;;; 1D6C4;MATHEMATICAL BOLD SMALL GAMMA;Ll;0;L; 03B3;;;;N;;;;; 1D6C5;MATHEMATICAL BOLD SMALL DELTA;Ll;0;L; 03B4;;;;N;;;;; 1D6C6;MATHEMATICAL BOLD SMALL EPSILON;Ll;0;L; 03B5;;;;N;;;;; 1D6C7;MATHEMATICAL BOLD SMALL ZETA;Ll;0;L; 03B6;;;;N;;;;; 1D6C8;MATHEMATICAL BOLD SMALL ETA;Ll;0;L; 03B7;;;;N;;;;; 1D6C9;MATHEMATICAL BOLD SMALL THETA;Ll;0;L; 03B8;;;;N;;;;; 1D6CA;MATHEMATICAL BOLD SMALL IOTA;Ll;0;L; 03B9;;;;N;;;;; 1D6CB;MATHEMATICAL BOLD SMALL KAPPA;Ll;0;L; 03BA;;;;N;;;;; 1D6CC;MATHEMATICAL BOLD SMALL LAMDA;Ll;0;L; 03BB;;;;N;;;;; 1D6CD;MATHEMATICAL BOLD SMALL MU;Ll;0;L; 03BC;;;;N;;;;; 1D6CE;MATHEMATICAL BOLD SMALL NU;Ll;0;L; 03BD;;;;N;;;;; 1D6CF;MATHEMATICAL BOLD SMALL XI;Ll;0;L; 03BE;;;;N;;;;; 1D6D0;MATHEMATICAL BOLD SMALL OMICRON;Ll;0;L; 03BF;;;;N;;;;; 1D6D1;MATHEMATICAL BOLD SMALL PI;Ll;0;L; 03C0;;;;N;;;;; 1D6D2;MATHEMATICAL BOLD SMALL RHO;Ll;0;L; 03C1;;;;N;;;;; 1D6D3;MATHEMATICAL BOLD SMALL FINAL SIGMA;Ll;0;L; 03C2;;;;N;;;;; 1D6D4;MATHEMATICAL BOLD SMALL SIGMA;Ll;0;L; 03C3;;;;N;;;;; 1D6D5;MATHEMATICAL BOLD SMALL TAU;Ll;0;L; 03C4;;;;N;;;;; 1D6D6;MATHEMATICAL BOLD SMALL UPSILON;Ll;0;L; 03C5;;;;N;;;;; 1D6D7;MATHEMATICAL BOLD SMALL PHI;Ll;0;L; 03C6;;;;N;;;;; 1D6D8;MATHEMATICAL BOLD SMALL CHI;Ll;0;L; 03C7;;;;N;;;;; 1D6D9;MATHEMATICAL BOLD SMALL PSI;Ll;0;L; 03C8;;;;N;;;;; 1D6DA;MATHEMATICAL BOLD SMALL OMEGA;Ll;0;L; 03C9;;;;N;;;;; 1D6DB;MATHEMATICAL BOLD PARTIAL DIFFERENTIAL;Sm;0;L; 2202;;;;N;;;;; 1D6DC;MATHEMATICAL BOLD EPSILON SYMBOL;Ll;0;L; 03F5;;;;N;;;;; 1D6DD;MATHEMATICAL BOLD THETA SYMBOL;Ll;0;L; 03D1;;;;N;;;;; 1D6DE;MATHEMATICAL BOLD KAPPA SYMBOL;Ll;0;L; 03F0;;;;N;;;;; 1D6DF;MATHEMATICAL BOLD PHI SYMBOL;Ll;0;L; 03D5;;;;N;;;;; 1D6E0;MATHEMATICAL BOLD RHO SYMBOL;Ll;0;L; 03F1;;;;N;;;;; 1D6E1;MATHEMATICAL BOLD PI SYMBOL;Ll;0;L; 03D6;;;;N;;;;; 1D6E2;MATHEMATICAL ITALIC CAPITAL ALPHA;Lu;0;L; 0391;;;;N;;;;; 1D6E3;MATHEMATICAL ITALIC CAPITAL BETA;Lu;0;L; 0392;;;;N;;;;; 1D6E4;MATHEMATICAL ITALIC CAPITAL GAMMA;Lu;0;L; 0393;;;;N;;;;; 1D6E5;MATHEMATICAL ITALIC CAPITAL DELTA;Lu;0;L; 0394;;;;N;;;;; 1D6E6;MATHEMATICAL ITALIC CAPITAL EPSILON;Lu;0;L; 0395;;;;N;;;;; 1D6E7;MATHEMATICAL ITALIC CAPITAL ZETA;Lu;0;L; 0396;;;;N;;;;; 1D6E8;MATHEMATICAL ITALIC CAPITAL ETA;Lu;0;L; 0397;;;;N;;;;; 1D6E9;MATHEMATICAL ITALIC CAPITAL THETA;Lu;0;L; 0398;;;;N;;;;; 1D6EA;MATHEMATICAL ITALIC CAPITAL IOTA;Lu;0;L; 0399;;;;N;;;;; 1D6EB;MATHEMATICAL ITALIC CAPITAL KAPPA;Lu;0;L; 039A;;;;N;;;;; 1D6EC;MATHEMATICAL ITALIC CAPITAL LAMDA;Lu;0;L; 039B;;;;N;;;;; 1D6ED;MATHEMATICAL ITALIC CAPITAL MU;Lu;0;L; 039C;;;;N;;;;; 1D6EE;MATHEMATICAL ITALIC CAPITAL NU;Lu;0;L; 039D;;;;N;;;;; 1D6EF;MATHEMATICAL ITALIC CAPITAL XI;Lu;0;L; 039E;;;;N;;;;; 1D6F0;MATHEMATICAL ITALIC CAPITAL OMICRON;Lu;0;L; 039F;;;;N;;;;; 1D6F1;MATHEMATICAL ITALIC CAPITAL PI;Lu;0;L; 03A0;;;;N;;;;; 1D6F2;MATHEMATICAL ITALIC CAPITAL RHO;Lu;0;L; 03A1;;;;N;;;;; 1D6F3;MATHEMATICAL ITALIC CAPITAL THETA SYMBOL;Lu;0;L; 03F4;;;;N;;;;; 1D6F4;MATHEMATICAL ITALIC CAPITAL SIGMA;Lu;0;L; 03A3;;;;N;;;;; 1D6F5;MATHEMATICAL ITALIC CAPITAL TAU;Lu;0;L; 03A4;;;;N;;;;; 1D6F6;MATHEMATICAL ITALIC CAPITAL UPSILON;Lu;0;L; 03A5;;;;N;;;;; 1D6F7;MATHEMATICAL ITALIC CAPITAL PHI;Lu;0;L; 03A6;;;;N;;;;; 1D6F8;MATHEMATICAL ITALIC CAPITAL CHI;Lu;0;L; 03A7;;;;N;;;;; 1D6F9;MATHEMATICAL ITALIC CAPITAL PSI;Lu;0;L; 03A8;;;;N;;;;; 1D6FA;MATHEMATICAL ITALIC CAPITAL OMEGA;Lu;0;L; 03A9;;;;N;;;;; 1D6FB;MATHEMATICAL ITALIC NABLA;Sm;0;L; 2207;;;;N;;;;; 1D6FC;MATHEMATICAL ITALIC SMALL ALPHA;Ll;0;L; 03B1;;;;N;;;;; 1D6FD;MATHEMATICAL ITALIC SMALL BETA;Ll;0;L; 03B2;;;;N;;;;; 1D6FE;MATHEMATICAL ITALIC SMALL GAMMA;Ll;0;L; 03B3;;;;N;;;;; 1D6FF;MATHEMATICAL ITALIC SMALL DELTA;Ll;0;L; 03B4;;;;N;;;;; 1D700;MATHEMATICAL ITALIC SMALL EPSILON;Ll;0;L; 03B5;;;;N;;;;; 1D701;MATHEMATICAL ITALIC SMALL ZETA;Ll;0;L; 03B6;;;;N;;;;; 1D702;MATHEMATICAL ITALIC SMALL ETA;Ll;0;L; 03B7;;;;N;;;;; 1D703;MATHEMATICAL ITALIC SMALL THETA;Ll;0;L; 03B8;;;;N;;;;; 1D704;MATHEMATICAL ITALIC SMALL IOTA;Ll;0;L; 03B9;;;;N;;;;; 1D705;MATHEMATICAL ITALIC SMALL KAPPA;Ll;0;L; 03BA;;;;N;;;;; 1D706;MATHEMATICAL ITALIC SMALL LAMDA;Ll;0;L; 03BB;;;;N;;;;; 1D707;MATHEMATICAL ITALIC SMALL MU;Ll;0;L; 03BC;;;;N;;;;; 1D708;MATHEMATICAL ITALIC SMALL NU;Ll;0;L; 03BD;;;;N;;;;; 1D709;MATHEMATICAL ITALIC SMALL XI;Ll;0;L; 03BE;;;;N;;;;; 1D70A;MATHEMATICAL ITALIC SMALL OMICRON;Ll;0;L; 03BF;;;;N;;;;; 1D70B;MATHEMATICAL ITALIC SMALL PI;Ll;0;L; 03C0;;;;N;;;;; 1D70C;MATHEMATICAL ITALIC SMALL RHO;Ll;0;L; 03C1;;;;N;;;;; 1D70D;MATHEMATICAL ITALIC SMALL FINAL SIGMA;Ll;0;L; 03C2;;;;N;;;;; 1D70E;MATHEMATICAL ITALIC SMALL SIGMA;Ll;0;L; 03C3;;;;N;;;;; 1D70F;MATHEMATICAL ITALIC SMALL TAU;Ll;0;L; 03C4;;;;N;;;;; 1D710;MATHEMATICAL ITALIC SMALL UPSILON;Ll;0;L; 03C5;;;;N;;;;; 1D711;MATHEMATICAL ITALIC SMALL PHI;Ll;0;L; 03C6;;;;N;;;;; 1D712;MATHEMATICAL ITALIC SMALL CHI;Ll;0;L; 03C7;;;;N;;;;; 1D713;MATHEMATICAL ITALIC SMALL PSI;Ll;0;L; 03C8;;;;N;;;;; 1D714;MATHEMATICAL ITALIC SMALL OMEGA;Ll;0;L; 03C9;;;;N;;;;; 1D715;MATHEMATICAL ITALIC PARTIAL DIFFERENTIAL;Sm;0;L; 2202;;;;N;;;;; 1D716;MATHEMATICAL ITALIC EPSILON SYMBOL;Ll;0;L; 03F5;;;;N;;;;; 1D717;MATHEMATICAL ITALIC THETA SYMBOL;Ll;0;L; 03D1;;;;N;;;;; 1D718;MATHEMATICAL ITALIC KAPPA SYMBOL;Ll;0;L; 03F0;;;;N;;;;; 1D719;MATHEMATICAL ITALIC PHI SYMBOL;Ll;0;L; 03D5;;;;N;;;;; 1D71A;MATHEMATICAL ITALIC RHO SYMBOL;Ll;0;L; 03F1;;;;N;;;;; 1D71B;MATHEMATICAL ITALIC PI SYMBOL;Ll;0;L; 03D6;;;;N;;;;; 1D71C;MATHEMATICAL BOLD ITALIC CAPITAL ALPHA;Lu;0;L; 0391;;;;N;;;;; 1D71D;MATHEMATICAL BOLD ITALIC CAPITAL BETA;Lu;0;L; 0392;;;;N;;;;; 1D71E;MATHEMATICAL BOLD ITALIC CAPITAL GAMMA;Lu;0;L; 0393;;;;N;;;;; 1D71F;MATHEMATICAL BOLD ITALIC CAPITAL DELTA;Lu;0;L; 0394;;;;N;;;;; 1D720;MATHEMATICAL BOLD ITALIC CAPITAL EPSILON;Lu;0;L; 0395;;;;N;;;;; 1D721;MATHEMATICAL BOLD ITALIC CAPITAL ZETA;Lu;0;L; 0396;;;;N;;;;; 1D722;MATHEMATICAL BOLD ITALIC CAPITAL ETA;Lu;0;L; 0397;;;;N;;;;; 1D723;MATHEMATICAL BOLD ITALIC CAPITAL THETA;Lu;0;L; 0398;;;;N;;;;; 1D724;MATHEMATICAL BOLD ITALIC CAPITAL IOTA;Lu;0;L; 0399;;;;N;;;;; 1D725;MATHEMATICAL BOLD ITALIC CAPITAL KAPPA;Lu;0;L; 039A;;;;N;;;;; 1D726;MATHEMATICAL BOLD ITALIC CAPITAL LAMDA;Lu;0;L; 039B;;;;N;;;;; 1D727;MATHEMATICAL BOLD ITALIC CAPITAL MU;Lu;0;L; 039C;;;;N;;;;; 1D728;MATHEMATICAL BOLD ITALIC CAPITAL NU;Lu;0;L; 039D;;;;N;;;;; 1D729;MATHEMATICAL BOLD ITALIC CAPITAL XI;Lu;0;L; 039E;;;;N;;;;; 1D72A;MATHEMATICAL BOLD ITALIC CAPITAL OMICRON;Lu;0;L; 039F;;;;N;;;;; 1D72B;MATHEMATICAL BOLD ITALIC CAPITAL PI;Lu;0;L; 03A0;;;;N;;;;; 1D72C;MATHEMATICAL BOLD ITALIC CAPITAL RHO;Lu;0;L; 03A1;;;;N;;;;; 1D72D;MATHEMATICAL BOLD ITALIC CAPITAL THETA SYMBOL;Lu;0;L; 03F4;;;;N;;;;; 1D72E;MATHEMATICAL BOLD ITALIC CAPITAL SIGMA;Lu;0;L; 03A3;;;;N;;;;; 1D72F;MATHEMATICAL BOLD ITALIC CAPITAL TAU;Lu;0;L; 03A4;;;;N;;;;; 1D730;MATHEMATICAL BOLD ITALIC CAPITAL UPSILON;Lu;0;L; 03A5;;;;N;;;;; 1D731;MATHEMATICAL BOLD ITALIC CAPITAL PHI;Lu;0;L; 03A6;;;;N;;;;; 1D732;MATHEMATICAL BOLD ITALIC CAPITAL CHI;Lu;0;L; 03A7;;;;N;;;;; 1D733;MATHEMATICAL BOLD ITALIC CAPITAL PSI;Lu;0;L; 03A8;;;;N;;;;; 1D734;MATHEMATICAL BOLD ITALIC CAPITAL OMEGA;Lu;0;L; 03A9;;;;N;;;;; 1D735;MATHEMATICAL BOLD ITALIC NABLA;Sm;0;L; 2207;;;;N;;;;; 1D736;MATHEMATICAL BOLD ITALIC SMALL ALPHA;Ll;0;L; 03B1;;;;N;;;;; 1D737;MATHEMATICAL BOLD ITALIC SMALL BETA;Ll;0;L; 03B2;;;;N;;;;; 1D738;MATHEMATICAL BOLD ITALIC SMALL GAMMA;Ll;0;L; 03B3;;;;N;;;;; 1D739;MATHEMATICAL BOLD ITALIC SMALL DELTA;Ll;0;L; 03B4;;;;N;;;;; 1D73A;MATHEMATICAL BOLD ITALIC SMALL EPSILON;Ll;0;L; 03B5;;;;N;;;;; 1D73B;MATHEMATICAL BOLD ITALIC SMALL ZETA;Ll;0;L; 03B6;;;;N;;;;; 1D73C;MATHEMATICAL BOLD ITALIC SMALL ETA;Ll;0;L; 03B7;;;;N;;;;; 1D73D;MATHEMATICAL BOLD ITALIC SMALL THETA;Ll;0;L; 03B8;;;;N;;;;; 1D73E;MATHEMATICAL BOLD ITALIC SMALL IOTA;Ll;0;L; 03B9;;;;N;;;;; 1D73F;MATHEMATICAL BOLD ITALIC SMALL KAPPA;Ll;0;L; 03BA;;;;N;;;;; 1D740;MATHEMATICAL BOLD ITALIC SMALL LAMDA;Ll;0;L; 03BB;;;;N;;;;; 1D741;MATHEMATICAL BOLD ITALIC SMALL MU;Ll;0;L; 03BC;;;;N;;;;; 1D742;MATHEMATICAL BOLD ITALIC SMALL NU;Ll;0;L; 03BD;;;;N;;;;; 1D743;MATHEMATICAL BOLD ITALIC SMALL XI;Ll;0;L; 03BE;;;;N;;;;; 1D744;MATHEMATICAL BOLD ITALIC SMALL OMICRON;Ll;0;L; 03BF;;;;N;;;;; 1D745;MATHEMATICAL BOLD ITALIC SMALL PI;Ll;0;L; 03C0;;;;N;;;;; 1D746;MATHEMATICAL BOLD ITALIC SMALL RHO;Ll;0;L; 03C1;;;;N;;;;; 1D747;MATHEMATICAL BOLD ITALIC SMALL FINAL SIGMA;Ll;0;L; 03C2;;;;N;;;;; 1D748;MATHEMATICAL BOLD ITALIC SMALL SIGMA;Ll;0;L; 03C3;;;;N;;;;; 1D749;MATHEMATICAL BOLD ITALIC SMALL TAU;Ll;0;L; 03C4;;;;N;;;;; 1D74A;MATHEMATICAL BOLD ITALIC SMALL UPSILON;Ll;0;L; 03C5;;;;N;;;;; 1D74B;MATHEMATICAL BOLD ITALIC SMALL PHI;Ll;0;L; 03C6;;;;N;;;;; 1D74C;MATHEMATICAL BOLD ITALIC SMALL CHI;Ll;0;L; 03C7;;;;N;;;;; 1D74D;MATHEMATICAL BOLD ITALIC SMALL PSI;Ll;0;L; 03C8;;;;N;;;;; 1D74E;MATHEMATICAL BOLD ITALIC SMALL OMEGA;Ll;0;L; 03C9;;;;N;;;;; 1D74F;MATHEMATICAL BOLD ITALIC PARTIAL DIFFERENTIAL;Sm;0;L; 2202;;;;N;;;;; 1D750;MATHEMATICAL BOLD ITALIC EPSILON SYMBOL;Ll;0;L; 03F5;;;;N;;;;; 1D751;MATHEMATICAL BOLD ITALIC THETA SYMBOL;Ll;0;L; 03D1;;;;N;;;;; 1D752;MATHEMATICAL BOLD ITALIC KAPPA SYMBOL;Ll;0;L; 03F0;;;;N;;;;; 1D753;MATHEMATICAL BOLD ITALIC PHI SYMBOL;Ll;0;L; 03D5;;;;N;;;;; 1D754;MATHEMATICAL BOLD ITALIC RHO SYMBOL;Ll;0;L; 03F1;;;;N;;;;; 1D755;MATHEMATICAL BOLD ITALIC PI SYMBOL;Ll;0;L; 03D6;;;;N;;;;; 1D756;MATHEMATICAL SANS-SERIF BOLD CAPITAL ALPHA;Lu;0;L; 0391;;;;N;;;;; 1D757;MATHEMATICAL SANS-SERIF BOLD CAPITAL BETA;Lu;0;L; 0392;;;;N;;;;; 1D758;MATHEMATICAL SANS-SERIF BOLD CAPITAL GAMMA;Lu;0;L; 0393;;;;N;;;;; 1D759;MATHEMATICAL SANS-SERIF BOLD CAPITAL DELTA;Lu;0;L; 0394;;;;N;;;;; 1D75A;MATHEMATICAL SANS-SERIF BOLD CAPITAL EPSILON;Lu;0;L; 0395;;;;N;;;;; 1D75B;MATHEMATICAL SANS-SERIF BOLD CAPITAL ZETA;Lu;0;L; 0396;;;;N;;;;; 1D75C;MATHEMATICAL SANS-SERIF BOLD CAPITAL ETA;Lu;0;L; 0397;;;;N;;;;; 1D75D;MATHEMATICAL SANS-SERIF BOLD CAPITAL THETA;Lu;0;L; 0398;;;;N;;;;; 1D75E;MATHEMATICAL SANS-SERIF BOLD CAPITAL IOTA;Lu;0;L; 0399;;;;N;;;;; 1D75F;MATHEMATICAL SANS-SERIF BOLD CAPITAL KAPPA;Lu;0;L; 039A;;;;N;;;;; 1D760;MATHEMATICAL SANS-SERIF BOLD CAPITAL LAMDA;Lu;0;L; 039B;;;;N;;;;; 1D761;MATHEMATICAL SANS-SERIF BOLD CAPITAL MU;Lu;0;L; 039C;;;;N;;;;; 1D762;MATHEMATICAL SANS-SERIF BOLD CAPITAL NU;Lu;0;L; 039D;;;;N;;;;; 1D763;MATHEMATICAL SANS-SERIF BOLD CAPITAL XI;Lu;0;L; 039E;;;;N;;;;; 1D764;MATHEMATICAL SANS-SERIF BOLD CAPITAL OMICRON;Lu;0;L; 039F;;;;N;;;;; 1D765;MATHEMATICAL SANS-SERIF BOLD CAPITAL PI;Lu;0;L; 03A0;;;;N;;;;; 1D766;MATHEMATICAL SANS-SERIF BOLD CAPITAL RHO;Lu;0;L; 03A1;;;;N;;;;; 1D767;MATHEMATICAL SANS-SERIF BOLD CAPITAL THETA SYMBOL;Lu;0;L; 03F4;;;;N;;;;; 1D768;MATHEMATICAL SANS-SERIF BOLD CAPITAL SIGMA;Lu;0;L; 03A3;;;;N;;;;; 1D769;MATHEMATICAL SANS-SERIF BOLD CAPITAL TAU;Lu;0;L; 03A4;;;;N;;;;; 1D76A;MATHEMATICAL SANS-SERIF BOLD CAPITAL UPSILON;Lu;0;L; 03A5;;;;N;;;;; 1D76B;MATHEMATICAL SANS-SERIF BOLD CAPITAL PHI;Lu;0;L; 03A6;;;;N;;;;; 1D76C;MATHEMATICAL SANS-SERIF BOLD CAPITAL CHI;Lu;0;L; 03A7;;;;N;;;;; 1D76D;MATHEMATICAL SANS-SERIF BOLD CAPITAL PSI;Lu;0;L; 03A8;;;;N;;;;; 1D76E;MATHEMATICAL SANS-SERIF BOLD CAPITAL OMEGA;Lu;0;L; 03A9;;;;N;;;;; 1D76F;MATHEMATICAL SANS-SERIF BOLD NABLA;Sm;0;L; 2207;;;;N;;;;; 1D770;MATHEMATICAL SANS-SERIF BOLD SMALL ALPHA;Ll;0;L; 03B1;;;;N;;;;; 1D771;MATHEMATICAL SANS-SERIF BOLD SMALL BETA;Ll;0;L; 03B2;;;;N;;;;; 1D772;MATHEMATICAL SANS-SERIF BOLD SMALL GAMMA;Ll;0;L; 03B3;;;;N;;;;; 1D773;MATHEMATICAL SANS-SERIF BOLD SMALL DELTA;Ll;0;L; 03B4;;;;N;;;;; 1D774;MATHEMATICAL SANS-SERIF BOLD SMALL EPSILON;Ll;0;L; 03B5;;;;N;;;;; 1D775;MATHEMATICAL SANS-SERIF BOLD SMALL ZETA;Ll;0;L; 03B6;;;;N;;;;; 1D776;MATHEMATICAL SANS-SERIF BOLD SMALL ETA;Ll;0;L; 03B7;;;;N;;;;; 1D777;MATHEMATICAL SANS-SERIF BOLD SMALL THETA;Ll;0;L; 03B8;;;;N;;;;; 1D778;MATHEMATICAL SANS-SERIF BOLD SMALL IOTA;Ll;0;L; 03B9;;;;N;;;;; 1D779;MATHEMATICAL SANS-SERIF BOLD SMALL KAPPA;Ll;0;L; 03BA;;;;N;;;;; 1D77A;MATHEMATICAL SANS-SERIF BOLD SMALL LAMDA;Ll;0;L; 03BB;;;;N;;;;; 1D77B;MATHEMATICAL SANS-SERIF BOLD SMALL MU;Ll;0;L; 03BC;;;;N;;;;; 1D77C;MATHEMATICAL SANS-SERIF BOLD SMALL NU;Ll;0;L; 03BD;;;;N;;;;; 1D77D;MATHEMATICAL SANS-SERIF BOLD SMALL XI;Ll;0;L; 03BE;;;;N;;;;; 1D77E;MATHEMATICAL SANS-SERIF BOLD SMALL OMICRON;Ll;0;L; 03BF;;;;N;;;;; 1D77F;MATHEMATICAL SANS-SERIF BOLD SMALL PI;Ll;0;L; 03C0;;;;N;;;;; 1D780;MATHEMATICAL SANS-SERIF BOLD SMALL RHO;Ll;0;L; 03C1;;;;N;;;;; 1D781;MATHEMATICAL SANS-SERIF BOLD SMALL FINAL SIGMA;Ll;0;L; 03C2;;;;N;;;;; 1D782;MATHEMATICAL SANS-SERIF BOLD SMALL SIGMA;Ll;0;L; 03C3;;;;N;;;;; 1D783;MATHEMATICAL SANS-SERIF BOLD SMALL TAU;Ll;0;L; 03C4;;;;N;;;;; 1D784;MATHEMATICAL SANS-SERIF BOLD SMALL UPSILON;Ll;0;L; 03C5;;;;N;;;;; 1D785;MATHEMATICAL SANS-SERIF BOLD SMALL PHI;Ll;0;L; 03C6;;;;N;;;;; 1D786;MATHEMATICAL SANS-SERIF BOLD SMALL CHI;Ll;0;L; 03C7;;;;N;;;;; 1D787;MATHEMATICAL SANS-SERIF BOLD SMALL PSI;Ll;0;L; 03C8;;;;N;;;;; 1D788;MATHEMATICAL SANS-SERIF BOLD SMALL OMEGA;Ll;0;L; 03C9;;;;N;;;;; 1D789;MATHEMATICAL SANS-SERIF BOLD PARTIAL DIFFERENTIAL;Sm;0;L; 2202;;;;N;;;;; 1D78A;MATHEMATICAL SANS-SERIF BOLD EPSILON SYMBOL;Ll;0;L; 03F5;;;;N;;;;; 1D78B;MATHEMATICAL SANS-SERIF BOLD THETA SYMBOL;Ll;0;L; 03D1;;;;N;;;;; 1D78C;MATHEMATICAL SANS-SERIF BOLD KAPPA SYMBOL;Ll;0;L; 03F0;;;;N;;;;; 1D78D;MATHEMATICAL SANS-SERIF BOLD PHI SYMBOL;Ll;0;L; 03D5;;;;N;;;;; 1D78E;MATHEMATICAL SANS-SERIF BOLD RHO SYMBOL;Ll;0;L; 03F1;;;;N;;;;; 1D78F;MATHEMATICAL SANS-SERIF BOLD PI SYMBOL;Ll;0;L; 03D6;;;;N;;;;; 1D790;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ALPHA;Lu;0;L; 0391;;;;N;;;;; 1D791;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL BETA;Lu;0;L; 0392;;;;N;;;;; 1D792;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL GAMMA;Lu;0;L; 0393;;;;N;;;;; 1D793;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL DELTA;Lu;0;L; 0394;;;;N;;;;; 1D794;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL EPSILON;Lu;0;L; 0395;;;;N;;;;; 1D795;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ZETA;Lu;0;L; 0396;;;;N;;;;; 1D796;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ETA;Lu;0;L; 0397;;;;N;;;;; 1D797;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL THETA;Lu;0;L; 0398;;;;N;;;;; 1D798;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL IOTA;Lu;0;L; 0399;;;;N;;;;; 1D799;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL KAPPA;Lu;0;L; 039A;;;;N;;;;; 1D79A;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL LAMDA;Lu;0;L; 039B;;;;N;;;;; 1D79B;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL MU;Lu;0;L; 039C;;;;N;;;;; 1D79C;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL NU;Lu;0;L; 039D;;;;N;;;;; 1D79D;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL XI;Lu;0;L; 039E;;;;N;;;;; 1D79E;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMICRON;Lu;0;L; 039F;;;;N;;;;; 1D79F;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PI;Lu;0;L; 03A0;;;;N;;;;; 1D7A0;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL RHO;Lu;0;L; 03A1;;;;N;;;;; 1D7A1;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL THETA SYMBOL;Lu;0;L; 03F4;;;;N;;;;; 1D7A2;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL SIGMA;Lu;0;L; 03A3;;;;N;;;;; 1D7A3;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL TAU;Lu;0;L; 03A4;;;;N;;;;; 1D7A4;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL UPSILON;Lu;0;L; 03A5;;;;N;;;;; 1D7A5;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PHI;Lu;0;L; 03A6;;;;N;;;;; 1D7A6;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL CHI;Lu;0;L; 03A7;;;;N;;;;; 1D7A7;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PSI;Lu;0;L; 03A8;;;;N;;;;; 1D7A8;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMEGA;Lu;0;L; 03A9;;;;N;;;;; 1D7A9;MATHEMATICAL SANS-SERIF BOLD ITALIC NABLA;Sm;0;L; 2207;;;;N;;;;; 1D7AA;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ALPHA;Ll;0;L; 03B1;;;;N;;;;; 1D7AB;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL BETA;Ll;0;L; 03B2;;;;N;;;;; 1D7AC;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL GAMMA;Ll;0;L; 03B3;;;;N;;;;; 1D7AD;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL DELTA;Ll;0;L; 03B4;;;;N;;;;; 1D7AE;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL EPSILON;Ll;0;L; 03B5;;;;N;;;;; 1D7AF;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ZETA;Ll;0;L; 03B6;;;;N;;;;; 1D7B0;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ETA;Ll;0;L; 03B7;;;;N;;;;; 1D7B1;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL THETA;Ll;0;L; 03B8;;;;N;;;;; 1D7B2;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL IOTA;Ll;0;L; 03B9;;;;N;;;;; 1D7B3;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL KAPPA;Ll;0;L; 03BA;;;;N;;;;; 1D7B4;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL LAMDA;Ll;0;L; 03BB;;;;N;;;;; 1D7B5;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL MU;Ll;0;L; 03BC;;;;N;;;;; 1D7B6;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL NU;Ll;0;L; 03BD;;;;N;;;;; 1D7B7;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL XI;Ll;0;L; 03BE;;;;N;;;;; 1D7B8;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMICRON;Ll;0;L; 03BF;;;;N;;;;; 1D7B9;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PI;Ll;0;L; 03C0;;;;N;;;;; 1D7BA;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL RHO;Ll;0;L; 03C1;;;;N;;;;; 1D7BB;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL FINAL SIGMA;Ll;0;L; 03C2;;;;N;;;;; 1D7BC;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL SIGMA;Ll;0;L; 03C3;;;;N;;;;; 1D7BD;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL TAU;Ll;0;L; 03C4;;;;N;;;;; 1D7BE;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL UPSILON;Ll;0;L; 03C5;;;;N;;;;; 1D7BF;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PHI;Ll;0;L; 03C6;;;;N;;;;; 1D7C0;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL CHI;Ll;0;L; 03C7;;;;N;;;;; 1D7C1;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PSI;Ll;0;L; 03C8;;;;N;;;;; 1D7C2;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMEGA;Ll;0;L; 03C9;;;;N;;;;; 1D7C3;MATHEMATICAL SANS-SERIF BOLD ITALIC PARTIAL DIFFERENTIAL;Sm;0;L; 2202;;;;N;;;;; 1D7C4;MATHEMATICAL SANS-SERIF BOLD ITALIC EPSILON SYMBOL;Ll;0;L; 03F5;;;;N;;;;; 1D7C5;MATHEMATICAL SANS-SERIF BOLD ITALIC THETA SYMBOL;Ll;0;L; 03D1;;;;N;;;;; 1D7C6;MATHEMATICAL SANS-SERIF BOLD ITALIC KAPPA SYMBOL;Ll;0;L; 03F0;;;;N;;;;; 1D7C7;MATHEMATICAL SANS-SERIF BOLD ITALIC PHI SYMBOL;Ll;0;L; 03D5;;;;N;;;;; 1D7C8;MATHEMATICAL SANS-SERIF BOLD ITALIC RHO SYMBOL;Ll;0;L; 03F1;;;;N;;;;; 1D7C9;MATHEMATICAL SANS-SERIF BOLD ITALIC PI SYMBOL;Ll;0;L; 03D6;;;;N;;;;; 1D7CE;MATHEMATICAL BOLD DIGIT ZERO;Nd;0;EN; 0030;0;0;0;N;;;;; 1D7CF;MATHEMATICAL BOLD DIGIT ONE;Nd;0;EN; 0031;1;1;1;N;;;;; 1D7D0;MATHEMATICAL BOLD DIGIT TWO;Nd;0;EN; 0032;2;2;2;N;;;;; 1D7D1;MATHEMATICAL BOLD DIGIT THREE;Nd;0;EN; 0033;3;3;3;N;;;;; 1D7D2;MATHEMATICAL BOLD DIGIT FOUR;Nd;0;EN; 0034;4;4;4;N;;;;; 1D7D3;MATHEMATICAL BOLD DIGIT FIVE;Nd;0;EN; 0035;5;5;5;N;;;;; 1D7D4;MATHEMATICAL BOLD DIGIT SIX;Nd;0;EN; 0036;6;6;6;N;;;;; 1D7D5;MATHEMATICAL BOLD DIGIT SEVEN;Nd;0;EN; 0037;7;7;7;N;;;;; 1D7D6;MATHEMATICAL BOLD DIGIT EIGHT;Nd;0;EN; 0038;8;8;8;N;;;;; 1D7D7;MATHEMATICAL BOLD DIGIT NINE;Nd;0;EN; 0039;9;9;9;N;;;;; 1D7D8;MATHEMATICAL DOUBLE-STRUCK DIGIT ZERO;Nd;0;EN; 0030;0;0;0;N;;;;; 1D7D9;MATHEMATICAL DOUBLE-STRUCK DIGIT ONE;Nd;0;EN; 0031;1;1;1;N;;;;; 1D7DA;MATHEMATICAL DOUBLE-STRUCK DIGIT TWO;Nd;0;EN; 0032;2;2;2;N;;;;; 1D7DB;MATHEMATICAL DOUBLE-STRUCK DIGIT THREE;Nd;0;EN; 0033;3;3;3;N;;;;; 1D7DC;MATHEMATICAL DOUBLE-STRUCK DIGIT FOUR;Nd;0;EN; 0034;4;4;4;N;;;;; 1D7DD;MATHEMATICAL DOUBLE-STRUCK DIGIT FIVE;Nd;0;EN; 0035;5;5;5;N;;;;; 1D7DE;MATHEMATICAL DOUBLE-STRUCK DIGIT SIX;Nd;0;EN; 0036;6;6;6;N;;;;; 1D7DF;MATHEMATICAL DOUBLE-STRUCK DIGIT SEVEN;Nd;0;EN; 0037;7;7;7;N;;;;; 1D7E0;MATHEMATICAL DOUBLE-STRUCK DIGIT EIGHT;Nd;0;EN; 0038;8;8;8;N;;;;; 1D7E1;MATHEMATICAL DOUBLE-STRUCK DIGIT NINE;Nd;0;EN; 0039;9;9;9;N;;;;; 1D7E2;MATHEMATICAL SANS-SERIF DIGIT ZERO;Nd;0;EN; 0030;0;0;0;N;;;;; 1D7E3;MATHEMATICAL SANS-SERIF DIGIT ONE;Nd;0;EN; 0031;1;1;1;N;;;;; 1D7E4;MATHEMATICAL SANS-SERIF DIGIT TWO;Nd;0;EN; 0032;2;2;2;N;;;;; 1D7E5;MATHEMATICAL SANS-SERIF DIGIT THREE;Nd;0;EN; 0033;3;3;3;N;;;;; 1D7E6;MATHEMATICAL SANS-SERIF DIGIT FOUR;Nd;0;EN; 0034;4;4;4;N;;;;; 1D7E7;MATHEMATICAL SANS-SERIF DIGIT FIVE;Nd;0;EN; 0035;5;5;5;N;;;;; 1D7E8;MATHEMATICAL SANS-SERIF DIGIT SIX;Nd;0;EN; 0036;6;6;6;N;;;;; 1D7E9;MATHEMATICAL SANS-SERIF DIGIT SEVEN;Nd;0;EN; 0037;7;7;7;N;;;;; 1D7EA;MATHEMATICAL SANS-SERIF DIGIT EIGHT;Nd;0;EN; 0038;8;8;8;N;;;;; 1D7EB;MATHEMATICAL SANS-SERIF DIGIT NINE;Nd;0;EN; 0039;9;9;9;N;;;;; 1D7EC;MATHEMATICAL SANS-SERIF BOLD DIGIT ZERO;Nd;0;EN; 0030;0;0;0;N;;;;; 1D7ED;MATHEMATICAL SANS-SERIF BOLD DIGIT ONE;Nd;0;EN; 0031;1;1;1;N;;;;; 1D7EE;MATHEMATICAL SANS-SERIF BOLD DIGIT TWO;Nd;0;EN; 0032;2;2;2;N;;;;; 1D7EF;MATHEMATICAL SANS-SERIF BOLD DIGIT THREE;Nd;0;EN; 0033;3;3;3;N;;;;; 1D7F0;MATHEMATICAL SANS-SERIF BOLD DIGIT FOUR;Nd;0;EN; 0034;4;4;4;N;;;;; 1D7F1;MATHEMATICAL SANS-SERIF BOLD DIGIT FIVE;Nd;0;EN; 0035;5;5;5;N;;;;; 1D7F2;MATHEMATICAL SANS-SERIF BOLD DIGIT SIX;Nd;0;EN; 0036;6;6;6;N;;;;; 1D7F3;MATHEMATICAL SANS-SERIF BOLD DIGIT SEVEN;Nd;0;EN; 0037;7;7;7;N;;;;; 1D7F4;MATHEMATICAL SANS-SERIF BOLD DIGIT EIGHT;Nd;0;EN; 0038;8;8;8;N;;;;; 1D7F5;MATHEMATICAL SANS-SERIF BOLD DIGIT NINE;Nd;0;EN; 0039;9;9;9;N;;;;; 1D7F6;MATHEMATICAL MONOSPACE DIGIT ZERO;Nd;0;EN; 0030;0;0;0;N;;;;; 1D7F7;MATHEMATICAL MONOSPACE DIGIT ONE;Nd;0;EN; 0031;1;1;1;N;;;;; 1D7F8;MATHEMATICAL MONOSPACE DIGIT TWO;Nd;0;EN; 0032;2;2;2;N;;;;; 1D7F9;MATHEMATICAL MONOSPACE DIGIT THREE;Nd;0;EN; 0033;3;3;3;N;;;;; 1D7FA;MATHEMATICAL MONOSPACE DIGIT FOUR;Nd;0;EN; 0034;4;4;4;N;;;;; 1D7FB;MATHEMATICAL MONOSPACE DIGIT FIVE;Nd;0;EN; 0035;5;5;5;N;;;;; 1D7FC;MATHEMATICAL MONOSPACE DIGIT SIX;Nd;0;EN; 0036;6;6;6;N;;;;; 1D7FD;MATHEMATICAL MONOSPACE DIGIT SEVEN;Nd;0;EN; 0037;7;7;7;N;;;;; 1D7FE;MATHEMATICAL MONOSPACE DIGIT EIGHT;Nd;0;EN; 0038;8;8;8;N;;;;; 1D7FF;MATHEMATICAL MONOSPACE DIGIT NINE;Nd;0;EN; 0039;9;9;9;N;;;;; 20000;;Lo;0;L;;;;;N;;;;; 2A6D6;;Lo;0;L;;;;;N;;;;; 2F800;CJK COMPATIBILITY IDEOGRAPH-2F800;Lo;0;L;4E3D;;;;N;;;;; 2F801;CJK COMPATIBILITY IDEOGRAPH-2F801;Lo;0;L;4E38;;;;N;;;;; 2F802;CJK COMPATIBILITY IDEOGRAPH-2F802;Lo;0;L;4E41;;;;N;;;;; 2F803;CJK COMPATIBILITY IDEOGRAPH-2F803;Lo;0;L;20122;;;;N;;;;; 2F804;CJK COMPATIBILITY IDEOGRAPH-2F804;Lo;0;L;4F60;;;;N;;;;; 2F805;CJK COMPATIBILITY IDEOGRAPH-2F805;Lo;0;L;4FAE;;;;N;;;;; 2F806;CJK COMPATIBILITY IDEOGRAPH-2F806;Lo;0;L;4FBB;;;;N;;;;; 2F807;CJK COMPATIBILITY IDEOGRAPH-2F807;Lo;0;L;5002;;;;N;;;;; 2F808;CJK COMPATIBILITY IDEOGRAPH-2F808;Lo;0;L;507A;;;;N;;;;; 2F809;CJK COMPATIBILITY IDEOGRAPH-2F809;Lo;0;L;5099;;;;N;;;;; 2F80A;CJK COMPATIBILITY IDEOGRAPH-2F80A;Lo;0;L;50E7;;;;N;;;;; 2F80B;CJK COMPATIBILITY IDEOGRAPH-2F80B;Lo;0;L;50CF;;;;N;;;;; 2F80C;CJK COMPATIBILITY IDEOGRAPH-2F80C;Lo;0;L;349E;;;;N;;;;; 2F80D;CJK COMPATIBILITY IDEOGRAPH-2F80D;Lo;0;L;2063A;;;;N;;;;; 2F80E;CJK COMPATIBILITY IDEOGRAPH-2F80E;Lo;0;L;514D;;;;N;;;;; 2F80F;CJK COMPATIBILITY IDEOGRAPH-2F80F;Lo;0;L;5154;;;;N;;;;; 2F810;CJK COMPATIBILITY IDEOGRAPH-2F810;Lo;0;L;5164;;;;N;;;;; 2F811;CJK COMPATIBILITY IDEOGRAPH-2F811;Lo;0;L;5177;;;;N;;;;; 2F812;CJK COMPATIBILITY IDEOGRAPH-2F812;Lo;0;L;2051C;;;;N;;;;; 2F813;CJK COMPATIBILITY IDEOGRAPH-2F813;Lo;0;L;34B9;;;;N;;;;; 2F814;CJK COMPATIBILITY IDEOGRAPH-2F814;Lo;0;L;5167;;;;N;;;;; 2F815;CJK COMPATIBILITY IDEOGRAPH-2F815;Lo;0;L;518D;;;;N;;;;; 2F816;CJK COMPATIBILITY IDEOGRAPH-2F816;Lo;0;L;2054B;;;;N;;;;; 2F817;CJK COMPATIBILITY IDEOGRAPH-2F817;Lo;0;L;5197;;;;N;;;;; 2F818;CJK COMPATIBILITY IDEOGRAPH-2F818;Lo;0;L;51A4;;;;N;;;;; 2F819;CJK COMPATIBILITY IDEOGRAPH-2F819;Lo;0;L;4ECC;;;;N;;;;; 2F81A;CJK COMPATIBILITY IDEOGRAPH-2F81A;Lo;0;L;51AC;;;;N;;;;; 2F81B;CJK COMPATIBILITY IDEOGRAPH-2F81B;Lo;0;L;51B5;;;;N;;;;; 2F81C;CJK COMPATIBILITY IDEOGRAPH-2F81C;Lo;0;L;291DF;;;;N;;;;; 2F81D;CJK COMPATIBILITY IDEOGRAPH-2F81D;Lo;0;L;51F5;;;;N;;;;; 2F81E;CJK COMPATIBILITY IDEOGRAPH-2F81E;Lo;0;L;5203;;;;N;;;;; 2F81F;CJK COMPATIBILITY IDEOGRAPH-2F81F;Lo;0;L;34DF;;;;N;;;;; 2F820;CJK COMPATIBILITY IDEOGRAPH-2F820;Lo;0;L;523B;;;;N;;;;; 2F821;CJK COMPATIBILITY IDEOGRAPH-2F821;Lo;0;L;5246;;;;N;;;;; 2F822;CJK COMPATIBILITY IDEOGRAPH-2F822;Lo;0;L;5272;;;;N;;;;; 2F823;CJK COMPATIBILITY IDEOGRAPH-2F823;Lo;0;L;5277;;;;N;;;;; 2F824;CJK COMPATIBILITY IDEOGRAPH-2F824;Lo;0;L;3515;;;;N;;;;; 2F825;CJK COMPATIBILITY IDEOGRAPH-2F825;Lo;0;L;52C7;;;;N;;;;; 2F826;CJK COMPATIBILITY IDEOGRAPH-2F826;Lo;0;L;52C9;;;;N;;;;; 2F827;CJK COMPATIBILITY IDEOGRAPH-2F827;Lo;0;L;52E4;;;;N;;;;; 2F828;CJK COMPATIBILITY IDEOGRAPH-2F828;Lo;0;L;52FA;;;;N;;;;; 2F829;CJK COMPATIBILITY IDEOGRAPH-2F829;Lo;0;L;5305;;;;N;;;;; 2F82A;CJK COMPATIBILITY IDEOGRAPH-2F82A;Lo;0;L;5306;;;;N;;;;; 2F82B;CJK COMPATIBILITY IDEOGRAPH-2F82B;Lo;0;L;5317;;;;N;;;;; 2F82C;CJK COMPATIBILITY IDEOGRAPH-2F82C;Lo;0;L;5349;;;;N;;;;; 2F82D;CJK COMPATIBILITY IDEOGRAPH-2F82D;Lo;0;L;5351;;;;N;;;;; 2F82E;CJK COMPATIBILITY IDEOGRAPH-2F82E;Lo;0;L;535A;;;;N;;;;; 2F82F;CJK COMPATIBILITY IDEOGRAPH-2F82F;Lo;0;L;5373;;;;N;;;;; 2F830;CJK COMPATIBILITY IDEOGRAPH-2F830;Lo;0;L;537D;;;;N;;;;; 2F831;CJK COMPATIBILITY IDEOGRAPH-2F831;Lo;0;L;537F;;;;N;;;;; 2F832;CJK COMPATIBILITY IDEOGRAPH-2F832;Lo;0;L;537F;;;;N;;;;; 2F833;CJK COMPATIBILITY IDEOGRAPH-2F833;Lo;0;L;537F;;;;N;;;;; 2F834;CJK COMPATIBILITY IDEOGRAPH-2F834;Lo;0;L;20A2C;;;;N;;;;; 2F835;CJK COMPATIBILITY IDEOGRAPH-2F835;Lo;0;L;7070;;;;N;;;;; 2F836;CJK COMPATIBILITY IDEOGRAPH-2F836;Lo;0;L;53CA;;;;N;;;;; 2F837;CJK COMPATIBILITY IDEOGRAPH-2F837;Lo;0;L;53DF;;;;N;;;;; 2F838;CJK COMPATIBILITY IDEOGRAPH-2F838;Lo;0;L;20B63;;;;N;;;;; 2F839;CJK COMPATIBILITY IDEOGRAPH-2F839;Lo;0;L;53EB;;;;N;;;;; 2F83A;CJK COMPATIBILITY IDEOGRAPH-2F83A;Lo;0;L;53F1;;;;N;;;;; 2F83B;CJK COMPATIBILITY IDEOGRAPH-2F83B;Lo;0;L;5406;;;;N;;;;; 2F83C;CJK COMPATIBILITY IDEOGRAPH-2F83C;Lo;0;L;549E;;;;N;;;;; 2F83D;CJK COMPATIBILITY IDEOGRAPH-2F83D;Lo;0;L;5438;;;;N;;;;; 2F83E;CJK COMPATIBILITY IDEOGRAPH-2F83E;Lo;0;L;5448;;;;N;;;;; 2F83F;CJK COMPATIBILITY IDEOGRAPH-2F83F;Lo;0;L;5468;;;;N;;;;; 2F840;CJK COMPATIBILITY IDEOGRAPH-2F840;Lo;0;L;54A2;;;;N;;;;; 2F841;CJK COMPATIBILITY IDEOGRAPH-2F841;Lo;0;L;54F6;;;;N;;;;; 2F842;CJK COMPATIBILITY IDEOGRAPH-2F842;Lo;0;L;5510;;;;N;;;;; 2F843;CJK COMPATIBILITY IDEOGRAPH-2F843;Lo;0;L;5553;;;;N;;;;; 2F844;CJK COMPATIBILITY IDEOGRAPH-2F844;Lo;0;L;5563;;;;N;;;;; 2F845;CJK COMPATIBILITY IDEOGRAPH-2F845;Lo;0;L;5584;;;;N;;;;; 2F846;CJK COMPATIBILITY IDEOGRAPH-2F846;Lo;0;L;5584;;;;N;;;;; 2F847;CJK COMPATIBILITY IDEOGRAPH-2F847;Lo;0;L;5599;;;;N;;;;; 2F848;CJK COMPATIBILITY IDEOGRAPH-2F848;Lo;0;L;55AB;;;;N;;;;; 2F849;CJK COMPATIBILITY IDEOGRAPH-2F849;Lo;0;L;55B3;;;;N;;;;; 2F84A;CJK COMPATIBILITY IDEOGRAPH-2F84A;Lo;0;L;55C2;;;;N;;;;; 2F84B;CJK COMPATIBILITY IDEOGRAPH-2F84B;Lo;0;L;5716;;;;N;;;;; 2F84C;CJK COMPATIBILITY IDEOGRAPH-2F84C;Lo;0;L;5606;;;;N;;;;; 2F84D;CJK COMPATIBILITY IDEOGRAPH-2F84D;Lo;0;L;5717;;;;N;;;;; 2F84E;CJK COMPATIBILITY IDEOGRAPH-2F84E;Lo;0;L;5651;;;;N;;;;; 2F84F;CJK COMPATIBILITY IDEOGRAPH-2F84F;Lo;0;L;5674;;;;N;;;;; 2F850;CJK COMPATIBILITY IDEOGRAPH-2F850;Lo;0;L;5207;;;;N;;;;; 2F851;CJK COMPATIBILITY IDEOGRAPH-2F851;Lo;0;L;58EE;;;;N;;;;; 2F852;CJK COMPATIBILITY IDEOGRAPH-2F852;Lo;0;L;57CE;;;;N;;;;; 2F853;CJK COMPATIBILITY IDEOGRAPH-2F853;Lo;0;L;57F4;;;;N;;;;; 2F854;CJK COMPATIBILITY IDEOGRAPH-2F854;Lo;0;L;580D;;;;N;;;;; 2F855;CJK COMPATIBILITY IDEOGRAPH-2F855;Lo;0;L;578B;;;;N;;;;; 2F856;CJK COMPATIBILITY IDEOGRAPH-2F856;Lo;0;L;5832;;;;N;;;;; 2F857;CJK COMPATIBILITY IDEOGRAPH-2F857;Lo;0;L;5831;;;;N;;;;; 2F858;CJK COMPATIBILITY IDEOGRAPH-2F858;Lo;0;L;58AC;;;;N;;;;; 2F859;CJK COMPATIBILITY IDEOGRAPH-2F859;Lo;0;L;214E4;;;;N;;;;; 2F85A;CJK COMPATIBILITY IDEOGRAPH-2F85A;Lo;0;L;58F2;;;;N;;;;; 2F85B;CJK COMPATIBILITY IDEOGRAPH-2F85B;Lo;0;L;58F7;;;;N;;;;; 2F85C;CJK COMPATIBILITY IDEOGRAPH-2F85C;Lo;0;L;5906;;;;N;;;;; 2F85D;CJK COMPATIBILITY IDEOGRAPH-2F85D;Lo;0;L;591A;;;;N;;;;; 2F85E;CJK COMPATIBILITY IDEOGRAPH-2F85E;Lo;0;L;5922;;;;N;;;;; 2F85F;CJK COMPATIBILITY IDEOGRAPH-2F85F;Lo;0;L;5962;;;;N;;;;; 2F860;CJK COMPATIBILITY IDEOGRAPH-2F860;Lo;0;L;216A8;;;;N;;;;; 2F861;CJK COMPATIBILITY IDEOGRAPH-2F861;Lo;0;L;216EA;;;;N;;;;; 2F862;CJK COMPATIBILITY IDEOGRAPH-2F862;Lo;0;L;59EC;;;;N;;;;; 2F863;CJK COMPATIBILITY IDEOGRAPH-2F863;Lo;0;L;5A1B;;;;N;;;;; 2F864;CJK COMPATIBILITY IDEOGRAPH-2F864;Lo;0;L;5A27;;;;N;;;;; 2F865;CJK COMPATIBILITY IDEOGRAPH-2F865;Lo;0;L;59D8;;;;N;;;;; 2F866;CJK COMPATIBILITY IDEOGRAPH-2F866;Lo;0;L;5A66;;;;N;;;;; 2F867;CJK COMPATIBILITY IDEOGRAPH-2F867;Lo;0;L;36EE;;;;N;;;;; 2F868;CJK COMPATIBILITY IDEOGRAPH-2F868;Lo;0;L;2136A;;;;N;;;;; 2F869;CJK COMPATIBILITY IDEOGRAPH-2F869;Lo;0;L;5B08;;;;N;;;;; 2F86A;CJK COMPATIBILITY IDEOGRAPH-2F86A;Lo;0;L;5B3E;;;;N;;;;; 2F86B;CJK COMPATIBILITY IDEOGRAPH-2F86B;Lo;0;L;5B3E;;;;N;;;;; 2F86C;CJK COMPATIBILITY IDEOGRAPH-2F86C;Lo;0;L;219C8;;;;N;;;;; 2F86D;CJK COMPATIBILITY IDEOGRAPH-2F86D;Lo;0;L;5BC3;;;;N;;;;; 2F86E;CJK COMPATIBILITY IDEOGRAPH-2F86E;Lo;0;L;5BD8;;;;N;;;;; 2F86F;CJK COMPATIBILITY IDEOGRAPH-2F86F;Lo;0;L;5BE7;;;;N;;;;; 2F870;CJK COMPATIBILITY IDEOGRAPH-2F870;Lo;0;L;5BF3;;;;N;;;;; 2F871;CJK COMPATIBILITY IDEOGRAPH-2F871;Lo;0;L;21B18;;;;N;;;;; 2F872;CJK COMPATIBILITY IDEOGRAPH-2F872;Lo;0;L;5BFF;;;;N;;;;; 2F873;CJK COMPATIBILITY IDEOGRAPH-2F873;Lo;0;L;5C06;;;;N;;;;; 2F874;CJK COMPATIBILITY IDEOGRAPH-2F874;Lo;0;L;5F33;;;;N;;;;; 2F875;CJK COMPATIBILITY IDEOGRAPH-2F875;Lo;0;L;5C22;;;;N;;;;; 2F876;CJK COMPATIBILITY IDEOGRAPH-2F876;Lo;0;L;3781;;;;N;;;;; 2F877;CJK COMPATIBILITY IDEOGRAPH-2F877;Lo;0;L;5C60;;;;N;;;;; 2F878;CJK COMPATIBILITY IDEOGRAPH-2F878;Lo;0;L;5C6E;;;;N;;;;; 2F879;CJK COMPATIBILITY IDEOGRAPH-2F879;Lo;0;L;5CC0;;;;N;;;;; 2F87A;CJK COMPATIBILITY IDEOGRAPH-2F87A;Lo;0;L;5C8D;;;;N;;;;; 2F87B;CJK COMPATIBILITY IDEOGRAPH-2F87B;Lo;0;L;21DE4;;;;N;;;;; 2F87C;CJK COMPATIBILITY IDEOGRAPH-2F87C;Lo;0;L;5D43;;;;N;;;;; 2F87D;CJK COMPATIBILITY IDEOGRAPH-2F87D;Lo;0;L;21DE6;;;;N;;;;; 2F87E;CJK COMPATIBILITY IDEOGRAPH-2F87E;Lo;0;L;5D6E;;;;N;;;;; 2F87F;CJK COMPATIBILITY IDEOGRAPH-2F87F;Lo;0;L;5D6B;;;;N;;;;; 2F880;CJK COMPATIBILITY IDEOGRAPH-2F880;Lo;0;L;5D7C;;;;N;;;;; 2F881;CJK COMPATIBILITY IDEOGRAPH-2F881;Lo;0;L;5DE1;;;;N;;;;; 2F882;CJK COMPATIBILITY IDEOGRAPH-2F882;Lo;0;L;5DE2;;;;N;;;;; 2F883;CJK COMPATIBILITY IDEOGRAPH-2F883;Lo;0;L;382F;;;;N;;;;; 2F884;CJK COMPATIBILITY IDEOGRAPH-2F884;Lo;0;L;5DFD;;;;N;;;;; 2F885;CJK COMPATIBILITY IDEOGRAPH-2F885;Lo;0;L;5E28;;;;N;;;;; 2F886;CJK COMPATIBILITY IDEOGRAPH-2F886;Lo;0;L;5E3D;;;;N;;;;; 2F887;CJK COMPATIBILITY IDEOGRAPH-2F887;Lo;0;L;5E69;;;;N;;;;; 2F888;CJK COMPATIBILITY IDEOGRAPH-2F888;Lo;0;L;3862;;;;N;;;;; 2F889;CJK COMPATIBILITY IDEOGRAPH-2F889;Lo;0;L;22183;;;;N;;;;; 2F88A;CJK COMPATIBILITY IDEOGRAPH-2F88A;Lo;0;L;387C;;;;N;;;;; 2F88B;CJK COMPATIBILITY IDEOGRAPH-2F88B;Lo;0;L;5EB0;;;;N;;;;; 2F88C;CJK COMPATIBILITY IDEOGRAPH-2F88C;Lo;0;L;5EB3;;;;N;;;;; 2F88D;CJK COMPATIBILITY IDEOGRAPH-2F88D;Lo;0;L;5EB6;;;;N;;;;; 2F88E;CJK COMPATIBILITY IDEOGRAPH-2F88E;Lo;0;L;5ECA;;;;N;;;;; 2F88F;CJK COMPATIBILITY IDEOGRAPH-2F88F;Lo;0;L;2A392;;;;N;;;;; 2F890;CJK COMPATIBILITY IDEOGRAPH-2F890;Lo;0;L;5EFE;;;;N;;;;; 2F891;CJK COMPATIBILITY IDEOGRAPH-2F891;Lo;0;L;22331;;;;N;;;;; 2F892;CJK COMPATIBILITY IDEOGRAPH-2F892;Lo;0;L;22331;;;;N;;;;; 2F893;CJK COMPATIBILITY IDEOGRAPH-2F893;Lo;0;L;8201;;;;N;;;;; 2F894;CJK COMPATIBILITY IDEOGRAPH-2F894;Lo;0;L;5F22;;;;N;;;;; 2F895;CJK COMPATIBILITY IDEOGRAPH-2F895;Lo;0;L;5F22;;;;N;;;;; 2F896;CJK COMPATIBILITY IDEOGRAPH-2F896;Lo;0;L;38C7;;;;N;;;;; 2F897;CJK COMPATIBILITY IDEOGRAPH-2F897;Lo;0;L;232B8;;;;N;;;;; 2F898;CJK COMPATIBILITY IDEOGRAPH-2F898;Lo;0;L;261DA;;;;N;;;;; 2F899;CJK COMPATIBILITY IDEOGRAPH-2F899;Lo;0;L;5F62;;;;N;;;;; 2F89A;CJK COMPATIBILITY IDEOGRAPH-2F89A;Lo;0;L;5F6B;;;;N;;;;; 2F89B;CJK COMPATIBILITY IDEOGRAPH-2F89B;Lo;0;L;38E3;;;;N;;;;; 2F89C;CJK COMPATIBILITY IDEOGRAPH-2F89C;Lo;0;L;5F9A;;;;N;;;;; 2F89D;CJK COMPATIBILITY IDEOGRAPH-2F89D;Lo;0;L;5FCD;;;;N;;;;; 2F89E;CJK COMPATIBILITY IDEOGRAPH-2F89E;Lo;0;L;5FD7;;;;N;;;;; 2F89F;CJK COMPATIBILITY IDEOGRAPH-2F89F;Lo;0;L;5FF9;;;;N;;;;; 2F8A0;CJK COMPATIBILITY IDEOGRAPH-2F8A0;Lo;0;L;6081;;;;N;;;;; 2F8A1;CJK COMPATIBILITY IDEOGRAPH-2F8A1;Lo;0;L;393A;;;;N;;;;; 2F8A2;CJK COMPATIBILITY IDEOGRAPH-2F8A2;Lo;0;L;391C;;;;N;;;;; 2F8A3;CJK COMPATIBILITY IDEOGRAPH-2F8A3;Lo;0;L;6094;;;;N;;;;; 2F8A4;CJK COMPATIBILITY IDEOGRAPH-2F8A4;Lo;0;L;226D4;;;;N;;;;; 2F8A5;CJK COMPATIBILITY IDEOGRAPH-2F8A5;Lo;0;L;60C7;;;;N;;;;; 2F8A6;CJK COMPATIBILITY IDEOGRAPH-2F8A6;Lo;0;L;6148;;;;N;;;;; 2F8A7;CJK COMPATIBILITY IDEOGRAPH-2F8A7;Lo;0;L;614C;;;;N;;;;; 2F8A8;CJK COMPATIBILITY IDEOGRAPH-2F8A8;Lo;0;L;614E;;;;N;;;;; 2F8A9;CJK COMPATIBILITY IDEOGRAPH-2F8A9;Lo;0;L;614C;;;;N;;;;; 2F8AA;CJK COMPATIBILITY IDEOGRAPH-2F8AA;Lo;0;L;617A;;;;N;;;;; 2F8AB;CJK COMPATIBILITY IDEOGRAPH-2F8AB;Lo;0;L;618E;;;;N;;;;; 2F8AC;CJK COMPATIBILITY IDEOGRAPH-2F8AC;Lo;0;L;61B2;;;;N;;;;; 2F8AD;CJK COMPATIBILITY IDEOGRAPH-2F8AD;Lo;0;L;61A4;;;;N;;;;; 2F8AE;CJK COMPATIBILITY IDEOGRAPH-2F8AE;Lo;0;L;61AF;;;;N;;;;; 2F8AF;CJK COMPATIBILITY IDEOGRAPH-2F8AF;Lo;0;L;61DE;;;;N;;;;; 2F8B0;CJK COMPATIBILITY IDEOGRAPH-2F8B0;Lo;0;L;61F2;;;;N;;;;; 2F8B1;CJK COMPATIBILITY IDEOGRAPH-2F8B1;Lo;0;L;61F6;;;;N;;;;; 2F8B2;CJK COMPATIBILITY IDEOGRAPH-2F8B2;Lo;0;L;6210;;;;N;;;;; 2F8B3;CJK COMPATIBILITY IDEOGRAPH-2F8B3;Lo;0;L;621B;;;;N;;;;; 2F8B4;CJK COMPATIBILITY IDEOGRAPH-2F8B4;Lo;0;L;625D;;;;N;;;;; 2F8B5;CJK COMPATIBILITY IDEOGRAPH-2F8B5;Lo;0;L;62B1;;;;N;;;;; 2F8B6;CJK COMPATIBILITY IDEOGRAPH-2F8B6;Lo;0;L;62D4;;;;N;;;;; 2F8B7;CJK COMPATIBILITY IDEOGRAPH-2F8B7;Lo;0;L;6350;;;;N;;;;; 2F8B8;CJK COMPATIBILITY IDEOGRAPH-2F8B8;Lo;0;L;22B0C;;;;N;;;;; 2F8B9;CJK COMPATIBILITY IDEOGRAPH-2F8B9;Lo;0;L;633D;;;;N;;;;; 2F8BA;CJK COMPATIBILITY IDEOGRAPH-2F8BA;Lo;0;L;62FC;;;;N;;;;; 2F8BB;CJK COMPATIBILITY IDEOGRAPH-2F8BB;Lo;0;L;6368;;;;N;;;;; 2F8BC;CJK COMPATIBILITY IDEOGRAPH-2F8BC;Lo;0;L;6383;;;;N;;;;; 2F8BD;CJK COMPATIBILITY IDEOGRAPH-2F8BD;Lo;0;L;63E4;;;;N;;;;; 2F8BE;CJK COMPATIBILITY IDEOGRAPH-2F8BE;Lo;0;L;22BF1;;;;N;;;;; 2F8BF;CJK COMPATIBILITY IDEOGRAPH-2F8BF;Lo;0;L;6422;;;;N;;;;; 2F8C0;CJK COMPATIBILITY IDEOGRAPH-2F8C0;Lo;0;L;63C5;;;;N;;;;; 2F8C1;CJK COMPATIBILITY IDEOGRAPH-2F8C1;Lo;0;L;63A9;;;;N;;;;; 2F8C2;CJK COMPATIBILITY IDEOGRAPH-2F8C2;Lo;0;L;3A2E;;;;N;;;;; 2F8C3;CJK COMPATIBILITY IDEOGRAPH-2F8C3;Lo;0;L;6469;;;;N;;;;; 2F8C4;CJK COMPATIBILITY IDEOGRAPH-2F8C4;Lo;0;L;647E;;;;N;;;;; 2F8C5;CJK COMPATIBILITY IDEOGRAPH-2F8C5;Lo;0;L;649D;;;;N;;;;; 2F8C6;CJK COMPATIBILITY IDEOGRAPH-2F8C6;Lo;0;L;6477;;;;N;;;;; 2F8C7;CJK COMPATIBILITY IDEOGRAPH-2F8C7;Lo;0;L;3A6C;;;;N;;;;; 2F8C8;CJK COMPATIBILITY IDEOGRAPH-2F8C8;Lo;0;L;654F;;;;N;;;;; 2F8C9;CJK COMPATIBILITY IDEOGRAPH-2F8C9;Lo;0;L;656C;;;;N;;;;; 2F8CA;CJK COMPATIBILITY IDEOGRAPH-2F8CA;Lo;0;L;2300A;;;;N;;;;; 2F8CB;CJK COMPATIBILITY IDEOGRAPH-2F8CB;Lo;0;L;65E3;;;;N;;;;; 2F8CC;CJK COMPATIBILITY IDEOGRAPH-2F8CC;Lo;0;L;66F8;;;;N;;;;; 2F8CD;CJK COMPATIBILITY IDEOGRAPH-2F8CD;Lo;0;L;6649;;;;N;;;;; 2F8CE;CJK COMPATIBILITY IDEOGRAPH-2F8CE;Lo;0;L;3B19;;;;N;;;;; 2F8CF;CJK COMPATIBILITY IDEOGRAPH-2F8CF;Lo;0;L;6691;;;;N;;;;; 2F8D0;CJK COMPATIBILITY IDEOGRAPH-2F8D0;Lo;0;L;3B08;;;;N;;;;; 2F8D1;CJK COMPATIBILITY IDEOGRAPH-2F8D1;Lo;0;L;3AE4;;;;N;;;;; 2F8D2;CJK COMPATIBILITY IDEOGRAPH-2F8D2;Lo;0;L;5192;;;;N;;;;; 2F8D3;CJK COMPATIBILITY IDEOGRAPH-2F8D3;Lo;0;L;5195;;;;N;;;;; 2F8D4;CJK COMPATIBILITY IDEOGRAPH-2F8D4;Lo;0;L;6700;;;;N;;;;; 2F8D5;CJK COMPATIBILITY IDEOGRAPH-2F8D5;Lo;0;L;669C;;;;N;;;;; 2F8D6;CJK COMPATIBILITY IDEOGRAPH-2F8D6;Lo;0;L;80AD;;;;N;;;;; 2F8D7;CJK COMPATIBILITY IDEOGRAPH-2F8D7;Lo;0;L;43D9;;;;N;;;;; 2F8D8;CJK COMPATIBILITY IDEOGRAPH-2F8D8;Lo;0;L;6717;;;;N;;;;; 2F8D9;CJK COMPATIBILITY IDEOGRAPH-2F8D9;Lo;0;L;671B;;;;N;;;;; 2F8DA;CJK COMPATIBILITY IDEOGRAPH-2F8DA;Lo;0;L;6721;;;;N;;;;; 2F8DB;CJK COMPATIBILITY IDEOGRAPH-2F8DB;Lo;0;L;675E;;;;N;;;;; 2F8DC;CJK COMPATIBILITY IDEOGRAPH-2F8DC;Lo;0;L;6753;;;;N;;;;; 2F8DD;CJK COMPATIBILITY IDEOGRAPH-2F8DD;Lo;0;L;233C3;;;;N;;;;; 2F8DE;CJK COMPATIBILITY IDEOGRAPH-2F8DE;Lo;0;L;3B49;;;;N;;;;; 2F8DF;CJK COMPATIBILITY IDEOGRAPH-2F8DF;Lo;0;L;67FA;;;;N;;;;; 2F8E0;CJK COMPATIBILITY IDEOGRAPH-2F8E0;Lo;0;L;6785;;;;N;;;;; 2F8E1;CJK COMPATIBILITY IDEOGRAPH-2F8E1;Lo;0;L;6852;;;;N;;;;; 2F8E2;CJK COMPATIBILITY IDEOGRAPH-2F8E2;Lo;0;L;6885;;;;N;;;;; 2F8E3;CJK COMPATIBILITY IDEOGRAPH-2F8E3;Lo;0;L;2346D;;;;N;;;;; 2F8E4;CJK COMPATIBILITY IDEOGRAPH-2F8E4;Lo;0;L;688E;;;;N;;;;; 2F8E5;CJK COMPATIBILITY IDEOGRAPH-2F8E5;Lo;0;L;681F;;;;N;;;;; 2F8E6;CJK COMPATIBILITY IDEOGRAPH-2F8E6;Lo;0;L;6914;;;;N;;;;; 2F8E7;CJK COMPATIBILITY IDEOGRAPH-2F8E7;Lo;0;L;3B9D;;;;N;;;;; 2F8E8;CJK COMPATIBILITY IDEOGRAPH-2F8E8;Lo;0;L;6942;;;;N;;;;; 2F8E9;CJK COMPATIBILITY IDEOGRAPH-2F8E9;Lo;0;L;69A3;;;;N;;;;; 2F8EA;CJK COMPATIBILITY IDEOGRAPH-2F8EA;Lo;0;L;69EA;;;;N;;;;; 2F8EB;CJK COMPATIBILITY IDEOGRAPH-2F8EB;Lo;0;L;6AA8;;;;N;;;;; 2F8EC;CJK COMPATIBILITY IDEOGRAPH-2F8EC;Lo;0;L;236A3;;;;N;;;;; 2F8ED;CJK COMPATIBILITY IDEOGRAPH-2F8ED;Lo;0;L;6ADB;;;;N;;;;; 2F8EE;CJK COMPATIBILITY IDEOGRAPH-2F8EE;Lo;0;L;3C18;;;;N;;;;; 2F8EF;CJK COMPATIBILITY IDEOGRAPH-2F8EF;Lo;0;L;6B21;;;;N;;;;; 2F8F0;CJK COMPATIBILITY IDEOGRAPH-2F8F0;Lo;0;L;238A7;;;;N;;;;; 2F8F1;CJK COMPATIBILITY IDEOGRAPH-2F8F1;Lo;0;L;6B54;;;;N;;;;; 2F8F2;CJK COMPATIBILITY IDEOGRAPH-2F8F2;Lo;0;L;3C4E;;;;N;;;;; 2F8F3;CJK COMPATIBILITY IDEOGRAPH-2F8F3;Lo;0;L;6B72;;;;N;;;;; 2F8F4;CJK COMPATIBILITY IDEOGRAPH-2F8F4;Lo;0;L;6B9F;;;;N;;;;; 2F8F5;CJK COMPATIBILITY IDEOGRAPH-2F8F5;Lo;0;L;6BBA;;;;N;;;;; 2F8F6;CJK COMPATIBILITY IDEOGRAPH-2F8F6;Lo;0;L;6BBB;;;;N;;;;; 2F8F7;CJK COMPATIBILITY IDEOGRAPH-2F8F7;Lo;0;L;23A8D;;;;N;;;;; 2F8F8;CJK COMPATIBILITY IDEOGRAPH-2F8F8;Lo;0;L;21D0B;;;;N;;;;; 2F8F9;CJK COMPATIBILITY IDEOGRAPH-2F8F9;Lo;0;L;23AFA;;;;N;;;;; 2F8FA;CJK COMPATIBILITY IDEOGRAPH-2F8FA;Lo;0;L;6C4E;;;;N;;;;; 2F8FB;CJK COMPATIBILITY IDEOGRAPH-2F8FB;Lo;0;L;23CBC;;;;N;;;;; 2F8FC;CJK COMPATIBILITY IDEOGRAPH-2F8FC;Lo;0;L;6CBF;;;;N;;;;; 2F8FD;CJK COMPATIBILITY IDEOGRAPH-2F8FD;Lo;0;L;6CCD;;;;N;;;;; 2F8FE;CJK COMPATIBILITY IDEOGRAPH-2F8FE;Lo;0;L;6C67;;;;N;;;;; 2F8FF;CJK COMPATIBILITY IDEOGRAPH-2F8FF;Lo;0;L;6D16;;;;N;;;;; 2F900;CJK COMPATIBILITY IDEOGRAPH-2F900;Lo;0;L;6D3E;;;;N;;;;; 2F901;CJK COMPATIBILITY IDEOGRAPH-2F901;Lo;0;L;6D77;;;;N;;;;; 2F902;CJK COMPATIBILITY IDEOGRAPH-2F902;Lo;0;L;6D41;;;;N;;;;; 2F903;CJK COMPATIBILITY IDEOGRAPH-2F903;Lo;0;L;6D69;;;;N;;;;; 2F904;CJK COMPATIBILITY IDEOGRAPH-2F904;Lo;0;L;6D78;;;;N;;;;; 2F905;CJK COMPATIBILITY IDEOGRAPH-2F905;Lo;0;L;6D85;;;;N;;;;; 2F906;CJK COMPATIBILITY IDEOGRAPH-2F906;Lo;0;L;23D1E;;;;N;;;;; 2F907;CJK COMPATIBILITY IDEOGRAPH-2F907;Lo;0;L;6D34;;;;N;;;;; 2F908;CJK COMPATIBILITY IDEOGRAPH-2F908;Lo;0;L;6E2F;;;;N;;;;; 2F909;CJK COMPATIBILITY IDEOGRAPH-2F909;Lo;0;L;6E6E;;;;N;;;;; 2F90A;CJK COMPATIBILITY IDEOGRAPH-2F90A;Lo;0;L;3D33;;;;N;;;;; 2F90B;CJK COMPATIBILITY IDEOGRAPH-2F90B;Lo;0;L;6ECB;;;;N;;;;; 2F90C;CJK COMPATIBILITY IDEOGRAPH-2F90C;Lo;0;L;6EC7;;;;N;;;;; 2F90D;CJK COMPATIBILITY IDEOGRAPH-2F90D;Lo;0;L;23ED1;;;;N;;;;; 2F90E;CJK COMPATIBILITY IDEOGRAPH-2F90E;Lo;0;L;6DF9;;;;N;;;;; 2F90F;CJK COMPATIBILITY IDEOGRAPH-2F90F;Lo;0;L;6F6E;;;;N;;;;; 2F910;CJK COMPATIBILITY IDEOGRAPH-2F910;Lo;0;L;23F5E;;;;N;;;;; 2F911;CJK COMPATIBILITY IDEOGRAPH-2F911;Lo;0;L;23F8E;;;;N;;;;; 2F912;CJK COMPATIBILITY IDEOGRAPH-2F912;Lo;0;L;6FC6;;;;N;;;;; 2F913;CJK COMPATIBILITY IDEOGRAPH-2F913;Lo;0;L;7039;;;;N;;;;; 2F914;CJK COMPATIBILITY IDEOGRAPH-2F914;Lo;0;L;701E;;;;N;;;;; 2F915;CJK COMPATIBILITY IDEOGRAPH-2F915;Lo;0;L;701B;;;;N;;;;; 2F916;CJK COMPATIBILITY IDEOGRAPH-2F916;Lo;0;L;3D96;;;;N;;;;; 2F917;CJK COMPATIBILITY IDEOGRAPH-2F917;Lo;0;L;704A;;;;N;;;;; 2F918;CJK COMPATIBILITY IDEOGRAPH-2F918;Lo;0;L;707D;;;;N;;;;; 2F919;CJK COMPATIBILITY IDEOGRAPH-2F919;Lo;0;L;7077;;;;N;;;;; 2F91A;CJK COMPATIBILITY IDEOGRAPH-2F91A;Lo;0;L;70AD;;;;N;;;;; 2F91B;CJK COMPATIBILITY IDEOGRAPH-2F91B;Lo;0;L;20525;;;;N;;;;; 2F91C;CJK COMPATIBILITY IDEOGRAPH-2F91C;Lo;0;L;7145;;;;N;;;;; 2F91D;CJK COMPATIBILITY IDEOGRAPH-2F91D;Lo;0;L;24263;;;;N;;;;; 2F91E;CJK COMPATIBILITY IDEOGRAPH-2F91E;Lo;0;L;719C;;;;N;;;;; 2F91F;CJK COMPATIBILITY IDEOGRAPH-2F91F;Lo;0;L;43AB;;;;N;;;;; 2F920;CJK COMPATIBILITY IDEOGRAPH-2F920;Lo;0;L;7228;;;;N;;;;; 2F921;CJK COMPATIBILITY IDEOGRAPH-2F921;Lo;0;L;7235;;;;N;;;;; 2F922;CJK COMPATIBILITY IDEOGRAPH-2F922;Lo;0;L;7250;;;;N;;;;; 2F923;CJK COMPATIBILITY IDEOGRAPH-2F923;Lo;0;L;24608;;;;N;;;;; 2F924;CJK COMPATIBILITY IDEOGRAPH-2F924;Lo;0;L;7280;;;;N;;;;; 2F925;CJK COMPATIBILITY IDEOGRAPH-2F925;Lo;0;L;7295;;;;N;;;;; 2F926;CJK COMPATIBILITY IDEOGRAPH-2F926;Lo;0;L;24735;;;;N;;;;; 2F927;CJK COMPATIBILITY IDEOGRAPH-2F927;Lo;0;L;24814;;;;N;;;;; 2F928;CJK COMPATIBILITY IDEOGRAPH-2F928;Lo;0;L;737A;;;;N;;;;; 2F929;CJK COMPATIBILITY IDEOGRAPH-2F929;Lo;0;L;738B;;;;N;;;;; 2F92A;CJK COMPATIBILITY IDEOGRAPH-2F92A;Lo;0;L;3EAC;;;;N;;;;; 2F92B;CJK COMPATIBILITY IDEOGRAPH-2F92B;Lo;0;L;73A5;;;;N;;;;; 2F92C;CJK COMPATIBILITY IDEOGRAPH-2F92C;Lo;0;L;3EB8;;;;N;;;;; 2F92D;CJK COMPATIBILITY IDEOGRAPH-2F92D;Lo;0;L;3EB8;;;;N;;;;; 2F92E;CJK COMPATIBILITY IDEOGRAPH-2F92E;Lo;0;L;7447;;;;N;;;;; 2F92F;CJK COMPATIBILITY IDEOGRAPH-2F92F;Lo;0;L;745C;;;;N;;;;; 2F930;CJK COMPATIBILITY IDEOGRAPH-2F930;Lo;0;L;7471;;;;N;;;;; 2F931;CJK COMPATIBILITY IDEOGRAPH-2F931;Lo;0;L;7485;;;;N;;;;; 2F932;CJK COMPATIBILITY IDEOGRAPH-2F932;Lo;0;L;74CA;;;;N;;;;; 2F933;CJK COMPATIBILITY IDEOGRAPH-2F933;Lo;0;L;3F1B;;;;N;;;;; 2F934;CJK COMPATIBILITY IDEOGRAPH-2F934;Lo;0;L;7524;;;;N;;;;; 2F935;CJK COMPATIBILITY IDEOGRAPH-2F935;Lo;0;L;24C36;;;;N;;;;; 2F936;CJK COMPATIBILITY IDEOGRAPH-2F936;Lo;0;L;753E;;;;N;;;;; 2F937;CJK COMPATIBILITY IDEOGRAPH-2F937;Lo;0;L;24C92;;;;N;;;;; 2F938;CJK COMPATIBILITY IDEOGRAPH-2F938;Lo;0;L;7570;;;;N;;;;; 2F939;CJK COMPATIBILITY IDEOGRAPH-2F939;Lo;0;L;2219F;;;;N;;;;; 2F93A;CJK COMPATIBILITY IDEOGRAPH-2F93A;Lo;0;L;7610;;;;N;;;;; 2F93B;CJK COMPATIBILITY IDEOGRAPH-2F93B;Lo;0;L;24FA1;;;;N;;;;; 2F93C;CJK COMPATIBILITY IDEOGRAPH-2F93C;Lo;0;L;24FB8;;;;N;;;;; 2F93D;CJK COMPATIBILITY IDEOGRAPH-2F93D;Lo;0;L;25044;;;;N;;;;; 2F93E;CJK COMPATIBILITY IDEOGRAPH-2F93E;Lo;0;L;3FFC;;;;N;;;;; 2F93F;CJK COMPATIBILITY IDEOGRAPH-2F93F;Lo;0;L;4008;;;;N;;;;; 2F940;CJK COMPATIBILITY IDEOGRAPH-2F940;Lo;0;L;76F4;;;;N;;;;; 2F941;CJK COMPATIBILITY IDEOGRAPH-2F941;Lo;0;L;250F3;;;;N;;;;; 2F942;CJK COMPATIBILITY IDEOGRAPH-2F942;Lo;0;L;250F2;;;;N;;;;; 2F943;CJK COMPATIBILITY IDEOGRAPH-2F943;Lo;0;L;25119;;;;N;;;;; 2F944;CJK COMPATIBILITY IDEOGRAPH-2F944;Lo;0;L;25133;;;;N;;;;; 2F945;CJK COMPATIBILITY IDEOGRAPH-2F945;Lo;0;L;771E;;;;N;;;;; 2F946;CJK COMPATIBILITY IDEOGRAPH-2F946;Lo;0;L;771F;;;;N;;;;; 2F947;CJK COMPATIBILITY IDEOGRAPH-2F947;Lo;0;L;771F;;;;N;;;;; 2F948;CJK COMPATIBILITY IDEOGRAPH-2F948;Lo;0;L;774A;;;;N;;;;; 2F949;CJK COMPATIBILITY IDEOGRAPH-2F949;Lo;0;L;4039;;;;N;;;;; 2F94A;CJK COMPATIBILITY IDEOGRAPH-2F94A;Lo;0;L;778B;;;;N;;;;; 2F94B;CJK COMPATIBILITY IDEOGRAPH-2F94B;Lo;0;L;4046;;;;N;;;;; 2F94C;CJK COMPATIBILITY IDEOGRAPH-2F94C;Lo;0;L;4096;;;;N;;;;; 2F94D;CJK COMPATIBILITY IDEOGRAPH-2F94D;Lo;0;L;2541D;;;;N;;;;; 2F94E;CJK COMPATIBILITY IDEOGRAPH-2F94E;Lo;0;L;784E;;;;N;;;;; 2F94F;CJK COMPATIBILITY IDEOGRAPH-2F94F;Lo;0;L;788C;;;;N;;;;; 2F950;CJK COMPATIBILITY IDEOGRAPH-2F950;Lo;0;L;78CC;;;;N;;;;; 2F951;CJK COMPATIBILITY IDEOGRAPH-2F951;Lo;0;L;40E3;;;;N;;;;; 2F952;CJK COMPATIBILITY IDEOGRAPH-2F952;Lo;0;L;25626;;;;N;;;;; 2F953;CJK COMPATIBILITY IDEOGRAPH-2F953;Lo;0;L;7956;;;;N;;;;; 2F954;CJK COMPATIBILITY IDEOGRAPH-2F954;Lo;0;L;2569A;;;;N;;;;; 2F955;CJK COMPATIBILITY IDEOGRAPH-2F955;Lo;0;L;256C5;;;;N;;;;; 2F956;CJK COMPATIBILITY IDEOGRAPH-2F956;Lo;0;L;798F;;;;N;;;;; 2F957;CJK COMPATIBILITY IDEOGRAPH-2F957;Lo;0;L;79EB;;;;N;;;;; 2F958;CJK COMPATIBILITY IDEOGRAPH-2F958;Lo;0;L;412F;;;;N;;;;; 2F959;CJK COMPATIBILITY IDEOGRAPH-2F959;Lo;0;L;7A40;;;;N;;;;; 2F95A;CJK COMPATIBILITY IDEOGRAPH-2F95A;Lo;0;L;7A4A;;;;N;;;;; 2F95B;CJK COMPATIBILITY IDEOGRAPH-2F95B;Lo;0;L;7A4F;;;;N;;;;; 2F95C;CJK COMPATIBILITY IDEOGRAPH-2F95C;Lo;0;L;2597C;;;;N;;;;; 2F95D;CJK COMPATIBILITY IDEOGRAPH-2F95D;Lo;0;L;25AA7;;;;N;;;;; 2F95E;CJK COMPATIBILITY IDEOGRAPH-2F95E;Lo;0;L;25AA7;;;;N;;;;; 2F95F;CJK COMPATIBILITY IDEOGRAPH-2F95F;Lo;0;L;7AAE;;;;N;;;;; 2F960;CJK COMPATIBILITY IDEOGRAPH-2F960;Lo;0;L;4202;;;;N;;;;; 2F961;CJK COMPATIBILITY IDEOGRAPH-2F961;Lo;0;L;25BAB;;;;N;;;;; 2F962;CJK COMPATIBILITY IDEOGRAPH-2F962;Lo;0;L;7BC6;;;;N;;;;; 2F963;CJK COMPATIBILITY IDEOGRAPH-2F963;Lo;0;L;7BC9;;;;N;;;;; 2F964;CJK COMPATIBILITY IDEOGRAPH-2F964;Lo;0;L;4227;;;;N;;;;; 2F965;CJK COMPATIBILITY IDEOGRAPH-2F965;Lo;0;L;25C80;;;;N;;;;; 2F966;CJK COMPATIBILITY IDEOGRAPH-2F966;Lo;0;L;7CD2;;;;N;;;;; 2F967;CJK COMPATIBILITY IDEOGRAPH-2F967;Lo;0;L;42A0;;;;N;;;;; 2F968;CJK COMPATIBILITY IDEOGRAPH-2F968;Lo;0;L;7CE8;;;;N;;;;; 2F969;CJK COMPATIBILITY IDEOGRAPH-2F969;Lo;0;L;7CE3;;;;N;;;;; 2F96A;CJK COMPATIBILITY IDEOGRAPH-2F96A;Lo;0;L;7D00;;;;N;;;;; 2F96B;CJK COMPATIBILITY IDEOGRAPH-2F96B;Lo;0;L;25F86;;;;N;;;;; 2F96C;CJK COMPATIBILITY IDEOGRAPH-2F96C;Lo;0;L;7D63;;;;N;;;;; 2F96D;CJK COMPATIBILITY IDEOGRAPH-2F96D;Lo;0;L;4301;;;;N;;;;; 2F96E;CJK COMPATIBILITY IDEOGRAPH-2F96E;Lo;0;L;7DC7;;;;N;;;;; 2F96F;CJK COMPATIBILITY IDEOGRAPH-2F96F;Lo;0;L;7E02;;;;N;;;;; 2F970;CJK COMPATIBILITY IDEOGRAPH-2F970;Lo;0;L;7E45;;;;N;;;;; 2F971;CJK COMPATIBILITY IDEOGRAPH-2F971;Lo;0;L;4334;;;;N;;;;; 2F972;CJK COMPATIBILITY IDEOGRAPH-2F972;Lo;0;L;26228;;;;N;;;;; 2F973;CJK COMPATIBILITY IDEOGRAPH-2F973;Lo;0;L;26247;;;;N;;;;; 2F974;CJK COMPATIBILITY IDEOGRAPH-2F974;Lo;0;L;4359;;;;N;;;;; 2F975;CJK COMPATIBILITY IDEOGRAPH-2F975;Lo;0;L;262D9;;;;N;;;;; 2F976;CJK COMPATIBILITY IDEOGRAPH-2F976;Lo;0;L;7F7A;;;;N;;;;; 2F977;CJK COMPATIBILITY IDEOGRAPH-2F977;Lo;0;L;2633E;;;;N;;;;; 2F978;CJK COMPATIBILITY IDEOGRAPH-2F978;Lo;0;L;7F95;;;;N;;;;; 2F979;CJK COMPATIBILITY IDEOGRAPH-2F979;Lo;0;L;7FFA;;;;N;;;;; 2F97A;CJK COMPATIBILITY IDEOGRAPH-2F97A;Lo;0;L;8005;;;;N;;;;; 2F97B;CJK COMPATIBILITY IDEOGRAPH-2F97B;Lo;0;L;264DA;;;;N;;;;; 2F97C;CJK COMPATIBILITY IDEOGRAPH-2F97C;Lo;0;L;26523;;;;N;;;;; 2F97D;CJK COMPATIBILITY IDEOGRAPH-2F97D;Lo;0;L;8060;;;;N;;;;; 2F97E;CJK COMPATIBILITY IDEOGRAPH-2F97E;Lo;0;L;265A8;;;;N;;;;; 2F97F;CJK COMPATIBILITY IDEOGRAPH-2F97F;Lo;0;L;8070;;;;N;;;;; 2F980;CJK COMPATIBILITY IDEOGRAPH-2F980;Lo;0;L;2335F;;;;N;;;;; 2F981;CJK COMPATIBILITY IDEOGRAPH-2F981;Lo;0;L;43D5;;;;N;;;;; 2F982;CJK COMPATIBILITY IDEOGRAPH-2F982;Lo;0;L;80B2;;;;N;;;;; 2F983;CJK COMPATIBILITY IDEOGRAPH-2F983;Lo;0;L;8103;;;;N;;;;; 2F984;CJK COMPATIBILITY IDEOGRAPH-2F984;Lo;0;L;440B;;;;N;;;;; 2F985;CJK COMPATIBILITY IDEOGRAPH-2F985;Lo;0;L;813E;;;;N;;;;; 2F986;CJK COMPATIBILITY IDEOGRAPH-2F986;Lo;0;L;5AB5;;;;N;;;;; 2F987;CJK COMPATIBILITY IDEOGRAPH-2F987;Lo;0;L;267A7;;;;N;;;;; 2F988;CJK COMPATIBILITY IDEOGRAPH-2F988;Lo;0;L;267B5;;;;N;;;;; 2F989;CJK COMPATIBILITY IDEOGRAPH-2F989;Lo;0;L;23393;;;;N;;;;; 2F98A;CJK COMPATIBILITY IDEOGRAPH-2F98A;Lo;0;L;2339C;;;;N;;;;; 2F98B;CJK COMPATIBILITY IDEOGRAPH-2F98B;Lo;0;L;8201;;;;N;;;;; 2F98C;CJK COMPATIBILITY IDEOGRAPH-2F98C;Lo;0;L;8204;;;;N;;;;; 2F98D;CJK COMPATIBILITY IDEOGRAPH-2F98D;Lo;0;L;8F9E;;;;N;;;;; 2F98E;CJK COMPATIBILITY IDEOGRAPH-2F98E;Lo;0;L;446B;;;;N;;;;; 2F98F;CJK COMPATIBILITY IDEOGRAPH-2F98F;Lo;0;L;8291;;;;N;;;;; 2F990;CJK COMPATIBILITY IDEOGRAPH-2F990;Lo;0;L;828B;;;;N;;;;; 2F991;CJK COMPATIBILITY IDEOGRAPH-2F991;Lo;0;L;829D;;;;N;;;;; 2F992;CJK COMPATIBILITY IDEOGRAPH-2F992;Lo;0;L;52B3;;;;N;;;;; 2F993;CJK COMPATIBILITY IDEOGRAPH-2F993;Lo;0;L;82B1;;;;N;;;;; 2F994;CJK COMPATIBILITY IDEOGRAPH-2F994;Lo;0;L;82B3;;;;N;;;;; 2F995;CJK COMPATIBILITY IDEOGRAPH-2F995;Lo;0;L;82BD;;;;N;;;;; 2F996;CJK COMPATIBILITY IDEOGRAPH-2F996;Lo;0;L;82E6;;;;N;;;;; 2F997;CJK COMPATIBILITY IDEOGRAPH-2F997;Lo;0;L;26B3C;;;;N;;;;; 2F998;CJK COMPATIBILITY IDEOGRAPH-2F998;Lo;0;L;82E5;;;;N;;;;; 2F999;CJK COMPATIBILITY IDEOGRAPH-2F999;Lo;0;L;831D;;;;N;;;;; 2F99A;CJK COMPATIBILITY IDEOGRAPH-2F99A;Lo;0;L;8363;;;;N;;;;; 2F99B;CJK COMPATIBILITY IDEOGRAPH-2F99B;Lo;0;L;83AD;;;;N;;;;; 2F99C;CJK COMPATIBILITY IDEOGRAPH-2F99C;Lo;0;L;8323;;;;N;;;;; 2F99D;CJK COMPATIBILITY IDEOGRAPH-2F99D;Lo;0;L;83BD;;;;N;;;;; 2F99E;CJK COMPATIBILITY IDEOGRAPH-2F99E;Lo;0;L;83E7;;;;N;;;;; 2F99F;CJK COMPATIBILITY IDEOGRAPH-2F99F;Lo;0;L;8457;;;;N;;;;; 2F9A0;CJK COMPATIBILITY IDEOGRAPH-2F9A0;Lo;0;L;8353;;;;N;;;;; 2F9A1;CJK COMPATIBILITY IDEOGRAPH-2F9A1;Lo;0;L;83CA;;;;N;;;;; 2F9A2;CJK COMPATIBILITY IDEOGRAPH-2F9A2;Lo;0;L;83CC;;;;N;;;;; 2F9A3;CJK COMPATIBILITY IDEOGRAPH-2F9A3;Lo;0;L;83DC;;;;N;;;;; 2F9A4;CJK COMPATIBILITY IDEOGRAPH-2F9A4;Lo;0;L;26C36;;;;N;;;;; 2F9A5;CJK COMPATIBILITY IDEOGRAPH-2F9A5;Lo;0;L;26D6B;;;;N;;;;; 2F9A6;CJK COMPATIBILITY IDEOGRAPH-2F9A6;Lo;0;L;26CD5;;;;N;;;;; 2F9A7;CJK COMPATIBILITY IDEOGRAPH-2F9A7;Lo;0;L;452B;;;;N;;;;; 2F9A8;CJK COMPATIBILITY IDEOGRAPH-2F9A8;Lo;0;L;84F1;;;;N;;;;; 2F9A9;CJK COMPATIBILITY IDEOGRAPH-2F9A9;Lo;0;L;84F3;;;;N;;;;; 2F9AA;CJK COMPATIBILITY IDEOGRAPH-2F9AA;Lo;0;L;8516;;;;N;;;;; 2F9AB;CJK COMPATIBILITY IDEOGRAPH-2F9AB;Lo;0;L;273CA;;;;N;;;;; 2F9AC;CJK COMPATIBILITY IDEOGRAPH-2F9AC;Lo;0;L;8564;;;;N;;;;; 2F9AD;CJK COMPATIBILITY IDEOGRAPH-2F9AD;Lo;0;L;26F2C;;;;N;;;;; 2F9AE;CJK COMPATIBILITY IDEOGRAPH-2F9AE;Lo;0;L;455D;;;;N;;;;; 2F9AF;CJK COMPATIBILITY IDEOGRAPH-2F9AF;Lo;0;L;4561;;;;N;;;;; 2F9B0;CJK COMPATIBILITY IDEOGRAPH-2F9B0;Lo;0;L;26FB1;;;;N;;;;; 2F9B1;CJK COMPATIBILITY IDEOGRAPH-2F9B1;Lo;0;L;270D2;;;;N;;;;; 2F9B2;CJK COMPATIBILITY IDEOGRAPH-2F9B2;Lo;0;L;456B;;;;N;;;;; 2F9B3;CJK COMPATIBILITY IDEOGRAPH-2F9B3;Lo;0;L;8650;;;;N;;;;; 2F9B4;CJK COMPATIBILITY IDEOGRAPH-2F9B4;Lo;0;L;865C;;;;N;;;;; 2F9B5;CJK COMPATIBILITY IDEOGRAPH-2F9B5;Lo;0;L;8667;;;;N;;;;; 2F9B6;CJK COMPATIBILITY IDEOGRAPH-2F9B6;Lo;0;L;8669;;;;N;;;;; 2F9B7;CJK COMPATIBILITY IDEOGRAPH-2F9B7;Lo;0;L;86A9;;;;N;;;;; 2F9B8;CJK COMPATIBILITY IDEOGRAPH-2F9B8;Lo;0;L;8688;;;;N;;;;; 2F9B9;CJK COMPATIBILITY IDEOGRAPH-2F9B9;Lo;0;L;870E;;;;N;;;;; 2F9BA;CJK COMPATIBILITY IDEOGRAPH-2F9BA;Lo;0;L;86E2;;;;N;;;;; 2F9BB;CJK COMPATIBILITY IDEOGRAPH-2F9BB;Lo;0;L;8779;;;;N;;;;; 2F9BC;CJK COMPATIBILITY IDEOGRAPH-2F9BC;Lo;0;L;8728;;;;N;;;;; 2F9BD;CJK COMPATIBILITY IDEOGRAPH-2F9BD;Lo;0;L;876B;;;;N;;;;; 2F9BE;CJK COMPATIBILITY IDEOGRAPH-2F9BE;Lo;0;L;8786;;;;N;;;;; 2F9BF;CJK COMPATIBILITY IDEOGRAPH-2F9BF;Lo;0;L;4D57;;;;N;;;;; 2F9C0;CJK COMPATIBILITY IDEOGRAPH-2F9C0;Lo;0;L;87E1;;;;N;;;;; 2F9C1;CJK COMPATIBILITY IDEOGRAPH-2F9C1;Lo;0;L;8801;;;;N;;;;; 2F9C2;CJK COMPATIBILITY IDEOGRAPH-2F9C2;Lo;0;L;45F9;;;;N;;;;; 2F9C3;CJK COMPATIBILITY IDEOGRAPH-2F9C3;Lo;0;L;8860;;;;N;;;;; 2F9C4;CJK COMPATIBILITY IDEOGRAPH-2F9C4;Lo;0;L;8863;;;;N;;;;; 2F9C5;CJK COMPATIBILITY IDEOGRAPH-2F9C5;Lo;0;L;27667;;;;N;;;;; 2F9C6;CJK COMPATIBILITY IDEOGRAPH-2F9C6;Lo;0;L;88D7;;;;N;;;;; 2F9C7;CJK COMPATIBILITY IDEOGRAPH-2F9C7;Lo;0;L;88DE;;;;N;;;;; 2F9C8;CJK COMPATIBILITY IDEOGRAPH-2F9C8;Lo;0;L;4635;;;;N;;;;; 2F9C9;CJK COMPATIBILITY IDEOGRAPH-2F9C9;Lo;0;L;88FA;;;;N;;;;; 2F9CA;CJK COMPATIBILITY IDEOGRAPH-2F9CA;Lo;0;L;34BB;;;;N;;;;; 2F9CB;CJK COMPATIBILITY IDEOGRAPH-2F9CB;Lo;0;L;278AE;;;;N;;;;; 2F9CC;CJK COMPATIBILITY IDEOGRAPH-2F9CC;Lo;0;L;27966;;;;N;;;;; 2F9CD;CJK COMPATIBILITY IDEOGRAPH-2F9CD;Lo;0;L;46BE;;;;N;;;;; 2F9CE;CJK COMPATIBILITY IDEOGRAPH-2F9CE;Lo;0;L;46C7;;;;N;;;;; 2F9CF;CJK COMPATIBILITY IDEOGRAPH-2F9CF;Lo;0;L;8AA0;;;;N;;;;; 2F9D0;CJK COMPATIBILITY IDEOGRAPH-2F9D0;Lo;0;L;8AED;;;;N;;;;; 2F9D1;CJK COMPATIBILITY IDEOGRAPH-2F9D1;Lo;0;L;8B8A;;;;N;;;;; 2F9D2;CJK COMPATIBILITY IDEOGRAPH-2F9D2;Lo;0;L;8C55;;;;N;;;;; 2F9D3;CJK COMPATIBILITY IDEOGRAPH-2F9D3;Lo;0;L;27CA8;;;;N;;;;; 2F9D4;CJK COMPATIBILITY IDEOGRAPH-2F9D4;Lo;0;L;8CAB;;;;N;;;;; 2F9D5;CJK COMPATIBILITY IDEOGRAPH-2F9D5;Lo;0;L;8CC1;;;;N;;;;; 2F9D6;CJK COMPATIBILITY IDEOGRAPH-2F9D6;Lo;0;L;8D1B;;;;N;;;;; 2F9D7;CJK COMPATIBILITY IDEOGRAPH-2F9D7;Lo;0;L;8D77;;;;N;;;;; 2F9D8;CJK COMPATIBILITY IDEOGRAPH-2F9D8;Lo;0;L;27F2F;;;;N;;;;; 2F9D9;CJK COMPATIBILITY IDEOGRAPH-2F9D9;Lo;0;L;20804;;;;N;;;;; 2F9DA;CJK COMPATIBILITY IDEOGRAPH-2F9DA;Lo;0;L;8DCB;;;;N;;;;; 2F9DB;CJK COMPATIBILITY IDEOGRAPH-2F9DB;Lo;0;L;8DBC;;;;N;;;;; 2F9DC;CJK COMPATIBILITY IDEOGRAPH-2F9DC;Lo;0;L;8DF0;;;;N;;;;; 2F9DD;CJK COMPATIBILITY IDEOGRAPH-2F9DD;Lo;0;L;208DE;;;;N;;;;; 2F9DE;CJK COMPATIBILITY IDEOGRAPH-2F9DE;Lo;0;L;8ED4;;;;N;;;;; 2F9DF;CJK COMPATIBILITY IDEOGRAPH-2F9DF;Lo;0;L;8F38;;;;N;;;;; 2F9E0;CJK COMPATIBILITY IDEOGRAPH-2F9E0;Lo;0;L;285D2;;;;N;;;;; 2F9E1;CJK COMPATIBILITY IDEOGRAPH-2F9E1;Lo;0;L;285ED;;;;N;;;;; 2F9E2;CJK COMPATIBILITY IDEOGRAPH-2F9E2;Lo;0;L;9094;;;;N;;;;; 2F9E3;CJK COMPATIBILITY IDEOGRAPH-2F9E3;Lo;0;L;90F1;;;;N;;;;; 2F9E4;CJK COMPATIBILITY IDEOGRAPH-2F9E4;Lo;0;L;9111;;;;N;;;;; 2F9E5;CJK COMPATIBILITY IDEOGRAPH-2F9E5;Lo;0;L;2872E;;;;N;;;;; 2F9E6;CJK COMPATIBILITY IDEOGRAPH-2F9E6;Lo;0;L;911B;;;;N;;;;; 2F9E7;CJK COMPATIBILITY IDEOGRAPH-2F9E7;Lo;0;L;9238;;;;N;;;;; 2F9E8;CJK COMPATIBILITY IDEOGRAPH-2F9E8;Lo;0;L;92D7;;;;N;;;;; 2F9E9;CJK COMPATIBILITY IDEOGRAPH-2F9E9;Lo;0;L;92D8;;;;N;;;;; 2F9EA;CJK COMPATIBILITY IDEOGRAPH-2F9EA;Lo;0;L;927C;;;;N;;;;; 2F9EB;CJK COMPATIBILITY IDEOGRAPH-2F9EB;Lo;0;L;93F9;;;;N;;;;; 2F9EC;CJK COMPATIBILITY IDEOGRAPH-2F9EC;Lo;0;L;9415;;;;N;;;;; 2F9ED;CJK COMPATIBILITY IDEOGRAPH-2F9ED;Lo;0;L;28BFA;;;;N;;;;; 2F9EE;CJK COMPATIBILITY IDEOGRAPH-2F9EE;Lo;0;L;958B;;;;N;;;;; 2F9EF;CJK COMPATIBILITY IDEOGRAPH-2F9EF;Lo;0;L;4995;;;;N;;;;; 2F9F0;CJK COMPATIBILITY IDEOGRAPH-2F9F0;Lo;0;L;95B7;;;;N;;;;; 2F9F1;CJK COMPATIBILITY IDEOGRAPH-2F9F1;Lo;0;L;28D77;;;;N;;;;; 2F9F2;CJK COMPATIBILITY IDEOGRAPH-2F9F2;Lo;0;L;49E6;;;;N;;;;; 2F9F3;CJK COMPATIBILITY IDEOGRAPH-2F9F3;Lo;0;L;96C3;;;;N;;;;; 2F9F4;CJK COMPATIBILITY IDEOGRAPH-2F9F4;Lo;0;L;5DB2;;;;N;;;;; 2F9F5;CJK COMPATIBILITY IDEOGRAPH-2F9F5;Lo;0;L;9723;;;;N;;;;; 2F9F6;CJK COMPATIBILITY IDEOGRAPH-2F9F6;Lo;0;L;29145;;;;N;;;;; 2F9F7;CJK COMPATIBILITY IDEOGRAPH-2F9F7;Lo;0;L;2921A;;;;N;;;;; 2F9F8;CJK COMPATIBILITY IDEOGRAPH-2F9F8;Lo;0;L;4A6E;;;;N;;;;; 2F9F9;CJK COMPATIBILITY IDEOGRAPH-2F9F9;Lo;0;L;4A76;;;;N;;;;; 2F9FA;CJK COMPATIBILITY IDEOGRAPH-2F9FA;Lo;0;L;97E0;;;;N;;;;; 2F9FB;CJK COMPATIBILITY IDEOGRAPH-2F9FB;Lo;0;L;2940A;;;;N;;;;; 2F9FC;CJK COMPATIBILITY IDEOGRAPH-2F9FC;Lo;0;L;4AB2;;;;N;;;;; 2F9FD;CJK COMPATIBILITY IDEOGRAPH-2F9FD;Lo;0;L;29496;;;;N;;;;; 2F9FE;CJK COMPATIBILITY IDEOGRAPH-2F9FE;Lo;0;L;980B;;;;N;;;;; 2F9FF;CJK COMPATIBILITY IDEOGRAPH-2F9FF;Lo;0;L;980B;;;;N;;;;; 2FA00;CJK COMPATIBILITY IDEOGRAPH-2FA00;Lo;0;L;9829;;;;N;;;;; 2FA01;CJK COMPATIBILITY IDEOGRAPH-2FA01;Lo;0;L;295B6;;;;N;;;;; 2FA02;CJK COMPATIBILITY IDEOGRAPH-2FA02;Lo;0;L;98E2;;;;N;;;;; 2FA03;CJK COMPATIBILITY IDEOGRAPH-2FA03;Lo;0;L;4B33;;;;N;;;;; 2FA04;CJK COMPATIBILITY IDEOGRAPH-2FA04;Lo;0;L;9929;;;;N;;;;; 2FA05;CJK COMPATIBILITY IDEOGRAPH-2FA05;Lo;0;L;99A7;;;;N;;;;; 2FA06;CJK COMPATIBILITY IDEOGRAPH-2FA06;Lo;0;L;99C2;;;;N;;;;; 2FA07;CJK COMPATIBILITY IDEOGRAPH-2FA07;Lo;0;L;99FE;;;;N;;;;; 2FA08;CJK COMPATIBILITY IDEOGRAPH-2FA08;Lo;0;L;4BCE;;;;N;;;;; 2FA09;CJK COMPATIBILITY IDEOGRAPH-2FA09;Lo;0;L;29B30;;;;N;;;;; 2FA0A;CJK COMPATIBILITY IDEOGRAPH-2FA0A;Lo;0;L;9B12;;;;N;;;;; 2FA0B;CJK COMPATIBILITY IDEOGRAPH-2FA0B;Lo;0;L;9C40;;;;N;;;;; 2FA0C;CJK COMPATIBILITY IDEOGRAPH-2FA0C;Lo;0;L;9CFD;;;;N;;;;; 2FA0D;CJK COMPATIBILITY IDEOGRAPH-2FA0D;Lo;0;L;4CCE;;;;N;;;;; 2FA0E;CJK COMPATIBILITY IDEOGRAPH-2FA0E;Lo;0;L;4CED;;;;N;;;;; 2FA0F;CJK COMPATIBILITY IDEOGRAPH-2FA0F;Lo;0;L;9D67;;;;N;;;;; 2FA10;CJK COMPATIBILITY IDEOGRAPH-2FA10;Lo;0;L;2A0CE;;;;N;;;;; 2FA11;CJK COMPATIBILITY IDEOGRAPH-2FA11;Lo;0;L;4CF8;;;;N;;;;; 2FA12;CJK COMPATIBILITY IDEOGRAPH-2FA12;Lo;0;L;2A105;;;;N;;;;; 2FA13;CJK COMPATIBILITY IDEOGRAPH-2FA13;Lo;0;L;2A20E;;;;N;;;;; 2FA14;CJK COMPATIBILITY IDEOGRAPH-2FA14;Lo;0;L;2A291;;;;N;;;;; 2FA15;CJK COMPATIBILITY IDEOGRAPH-2FA15;Lo;0;L;9EBB;;;;N;;;;; 2FA16;CJK COMPATIBILITY IDEOGRAPH-2FA16;Lo;0;L;4D56;;;;N;;;;; 2FA17;CJK COMPATIBILITY IDEOGRAPH-2FA17;Lo;0;L;9EF9;;;;N;;;;; 2FA18;CJK COMPATIBILITY IDEOGRAPH-2FA18;Lo;0;L;9EFE;;;;N;;;;; 2FA19;CJK COMPATIBILITY IDEOGRAPH-2FA19;Lo;0;L;9F05;;;;N;;;;; 2FA1A;CJK COMPATIBILITY IDEOGRAPH-2FA1A;Lo;0;L;9F0F;;;;N;;;;; 2FA1B;CJK COMPATIBILITY IDEOGRAPH-2FA1B;Lo;0;L;9F16;;;;N;;;;; 2FA1C;CJK COMPATIBILITY IDEOGRAPH-2FA1C;Lo;0;L;9F3B;;;;N;;;;; 2FA1D;CJK COMPATIBILITY IDEOGRAPH-2FA1D;Lo;0;L;2A600;;;;N;;;;; E0001;LANGUAGE TAG;Cf;0;BN;;;;;N;;;;; E0020;TAG SPACE;Cf;0;BN;;;;;N;;;;; E0021;TAG EXCLAMATION MARK;Cf;0;BN;;;;;N;;;;; E0022;TAG QUOTATION MARK;Cf;0;BN;;;;;N;;;;; E0023;TAG NUMBER SIGN;Cf;0;BN;;;;;N;;;;; E0024;TAG DOLLAR SIGN;Cf;0;BN;;;;;N;;;;; E0025;TAG PERCENT SIGN;Cf;0;BN;;;;;N;;;;; E0026;TAG AMPERSAND;Cf;0;BN;;;;;N;;;;; E0027;TAG APOSTROPHE;Cf;0;BN;;;;;N;;;;; E0028;TAG LEFT PARENTHESIS;Cf;0;BN;;;;;N;;;;; E0029;TAG RIGHT PARENTHESIS;Cf;0;BN;;;;;N;;;;; E002A;TAG ASTERISK;Cf;0;BN;;;;;N;;;;; E002B;TAG PLUS SIGN;Cf;0;BN;;;;;N;;;;; E002C;TAG COMMA;Cf;0;BN;;;;;N;;;;; E002D;TAG HYPHEN-MINUS;Cf;0;BN;;;;;N;;;;; E002E;TAG FULL STOP;Cf;0;BN;;;;;N;;;;; E002F;TAG SOLIDUS;Cf;0;BN;;;;;N;;;;; E0030;TAG DIGIT ZERO;Cf;0;BN;;;;;N;;;;; E0031;TAG DIGIT ONE;Cf;0;BN;;;;;N;;;;; E0032;TAG DIGIT TWO;Cf;0;BN;;;;;N;;;;; E0033;TAG DIGIT THREE;Cf;0;BN;;;;;N;;;;; E0034;TAG DIGIT FOUR;Cf;0;BN;;;;;N;;;;; E0035;TAG DIGIT FIVE;Cf;0;BN;;;;;N;;;;; E0036;TAG DIGIT SIX;Cf;0;BN;;;;;N;;;;; E0037;TAG DIGIT SEVEN;Cf;0;BN;;;;;N;;;;; E0038;TAG DIGIT EIGHT;Cf;0;BN;;;;;N;;;;; E0039;TAG DIGIT NINE;Cf;0;BN;;;;;N;;;;; E003A;TAG COLON;Cf;0;BN;;;;;N;;;;; E003B;TAG SEMICOLON;Cf;0;BN;;;;;N;;;;; E003C;TAG LESS-THAN SIGN;Cf;0;BN;;;;;N;;;;; E003D;TAG EQUALS SIGN;Cf;0;BN;;;;;N;;;;; E003E;TAG GREATER-THAN SIGN;Cf;0;BN;;;;;N;;;;; E003F;TAG QUESTION MARK;Cf;0;BN;;;;;N;;;;; E0040;TAG COMMERCIAL AT;Cf;0;BN;;;;;N;;;;; E0041;TAG LATIN CAPITAL LETTER A;Cf;0;BN;;;;;N;;;;; E0042;TAG LATIN CAPITAL LETTER B;Cf;0;BN;;;;;N;;;;; E0043;TAG LATIN CAPITAL LETTER C;Cf;0;BN;;;;;N;;;;; E0044;TAG LATIN CAPITAL LETTER D;Cf;0;BN;;;;;N;;;;; E0045;TAG LATIN CAPITAL LETTER E;Cf;0;BN;;;;;N;;;;; E0046;TAG LATIN CAPITAL LETTER F;Cf;0;BN;;;;;N;;;;; E0047;TAG LATIN CAPITAL LETTER G;Cf;0;BN;;;;;N;;;;; E0048;TAG LATIN CAPITAL LETTER H;Cf;0;BN;;;;;N;;;;; E0049;TAG LATIN CAPITAL LETTER I;Cf;0;BN;;;;;N;;;;; E004A;TAG LATIN CAPITAL LETTER J;Cf;0;BN;;;;;N;;;;; E004B;TAG LATIN CAPITAL LETTER K;Cf;0;BN;;;;;N;;;;; E004C;TAG LATIN CAPITAL LETTER L;Cf;0;BN;;;;;N;;;;; E004D;TAG LATIN CAPITAL LETTER M;Cf;0;BN;;;;;N;;;;; E004E;TAG LATIN CAPITAL LETTER N;Cf;0;BN;;;;;N;;;;; E004F;TAG LATIN CAPITAL LETTER O;Cf;0;BN;;;;;N;;;;; E0050;TAG LATIN CAPITAL LETTER P;Cf;0;BN;;;;;N;;;;; E0051;TAG LATIN CAPITAL LETTER Q;Cf;0;BN;;;;;N;;;;; E0052;TAG LATIN CAPITAL LETTER R;Cf;0;BN;;;;;N;;;;; E0053;TAG LATIN CAPITAL LETTER S;Cf;0;BN;;;;;N;;;;; E0054;TAG LATIN CAPITAL LETTER T;Cf;0;BN;;;;;N;;;;; E0055;TAG LATIN CAPITAL LETTER U;Cf;0;BN;;;;;N;;;;; E0056;TAG LATIN CAPITAL LETTER V;Cf;0;BN;;;;;N;;;;; E0057;TAG LATIN CAPITAL LETTER W;Cf;0;BN;;;;;N;;;;; E0058;TAG LATIN CAPITAL LETTER X;Cf;0;BN;;;;;N;;;;; E0059;TAG LATIN CAPITAL LETTER Y;Cf;0;BN;;;;;N;;;;; E005A;TAG LATIN CAPITAL LETTER Z;Cf;0;BN;;;;;N;;;;; E005B;TAG LEFT SQUARE BRACKET;Cf;0;BN;;;;;N;;;;; E005C;TAG REVERSE SOLIDUS;Cf;0;BN;;;;;N;;;;; E005D;TAG RIGHT SQUARE BRACKET;Cf;0;BN;;;;;N;;;;; E005E;TAG CIRCUMFLEX ACCENT;Cf;0;BN;;;;;N;;;;; E005F;TAG LOW LINE;Cf;0;BN;;;;;N;;;;; E0060;TAG GRAVE ACCENT;Cf;0;BN;;;;;N;;;;; E0061;TAG LATIN SMALL LETTER A;Cf;0;BN;;;;;N;;;;; E0062;TAG LATIN SMALL LETTER B;Cf;0;BN;;;;;N;;;;; E0063;TAG LATIN SMALL LETTER C;Cf;0;BN;;;;;N;;;;; E0064;TAG LATIN SMALL LETTER D;Cf;0;BN;;;;;N;;;;; E0065;TAG LATIN SMALL LETTER E;Cf;0;BN;;;;;N;;;;; E0066;TAG LATIN SMALL LETTER F;Cf;0;BN;;;;;N;;;;; E0067;TAG LATIN SMALL LETTER G;Cf;0;BN;;;;;N;;;;; E0068;TAG LATIN SMALL LETTER H;Cf;0;BN;;;;;N;;;;; E0069;TAG LATIN SMALL LETTER I;Cf;0;BN;;;;;N;;;;; E006A;TAG LATIN SMALL LETTER J;Cf;0;BN;;;;;N;;;;; E006B;TAG LATIN SMALL LETTER K;Cf;0;BN;;;;;N;;;;; E006C;TAG LATIN SMALL LETTER L;Cf;0;BN;;;;;N;;;;; E006D;TAG LATIN SMALL LETTER M;Cf;0;BN;;;;;N;;;;; E006E;TAG LATIN SMALL LETTER N;Cf;0;BN;;;;;N;;;;; E006F;TAG LATIN SMALL LETTER O;Cf;0;BN;;;;;N;;;;; E0070;TAG LATIN SMALL LETTER P;Cf;0;BN;;;;;N;;;;; E0071;TAG LATIN SMALL LETTER Q;Cf;0;BN;;;;;N;;;;; E0072;TAG LATIN SMALL LETTER R;Cf;0;BN;;;;;N;;;;; E0073;TAG LATIN SMALL LETTER S;Cf;0;BN;;;;;N;;;;; E0074;TAG LATIN SMALL LETTER T;Cf;0;BN;;;;;N;;;;; E0075;TAG LATIN SMALL LETTER U;Cf;0;BN;;;;;N;;;;; E0076;TAG LATIN SMALL LETTER V;Cf;0;BN;;;;;N;;;;; E0077;TAG LATIN SMALL LETTER W;Cf;0;BN;;;;;N;;;;; E0078;TAG LATIN SMALL LETTER X;Cf;0;BN;;;;;N;;;;; E0079;TAG LATIN SMALL LETTER Y;Cf;0;BN;;;;;N;;;;; E007A;TAG LATIN SMALL LETTER Z;Cf;0;BN;;;;;N;;;;; E007B;TAG LEFT CURLY BRACKET;Cf;0;BN;;;;;N;;;;; E007C;TAG VERTICAL LINE;Cf;0;BN;;;;;N;;;;; E007D;TAG RIGHT CURLY BRACKET;Cf;0;BN;;;;;N;;;;; E007E;TAG TILDE;Cf;0;BN;;;;;N;;;;; E007F;CANCEL TAG;Cf;0;BN;;;;;N;;;;; F0000;;Co;0;L;;;;;N;;;;; FFFFD;;Co;0;L;;;;;N;;;;; 100000;;Co;0;L;;;;;N;;;;; 10FFFD;;Co;0;L;;;;;N;;;;; openldap-2.4.42+dfsg/libraries/liblunicode/UCD-Terms0000644000175000017500000000244012563404150020723 0ustar ryanryanUCD Terms of Use (http://www.unicode.org/Public/UNIDATA/UCD.html) Disclaimer The Unicode Character Database is provided as is by Unicode, Inc. No claims are made as to fitness for any particular purpose. No warranties of any kind are expressed or implied. The recipient agrees to determine applicability of information provided. If this file has been purchased on magnetic or optical media from Unicode, Inc., the sole remedy for any claim will be exchange of defective media within 90 days of receipt. This disclaimer is applicable for all other data files accompanying the Unicode Character Database, some of which have been compiled by the Unicode Consortium, and some of which have been supplied by other sources. Limitations on Rights to Redistribute This Data Recipient is granted the right to make copies in any form for internal distribution and to freely use the information supplied in the creation of products supporting the Unicode (TM) Standard. The files in the Unicode Character Database can be redistributed to third parties or other organizations (whether for profit or not) as long as this notice and the disclaimer notice are retained. Information can be extracted from these files and used in documentation or programs, as long as there is an accompanying notice indicating the source. openldap-2.4.42+dfsg/libraries/liblunicode/ucstr.c0000644000175000017500000002303412563404150020603 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #include "portable.h" #include #include #include #include #include #include #include #define malloc(x) ber_memalloc_x(x,ctx) #define realloc(x,y) ber_memrealloc_x(x,y,ctx) #define free(x) ber_memfree_x(x,ctx) int ucstrncmp( const ldap_unicode_t *u1, const ldap_unicode_t *u2, ber_len_t n ) { for(; 0 < n; ++u1, ++u2, --n ) { if( *u1 != *u2 ) { return *u1 < *u2 ? -1 : +1; } if ( *u1 == 0 ) { return 0; } } return 0; } int ucstrncasecmp( const ldap_unicode_t *u1, const ldap_unicode_t *u2, ber_len_t n ) { for(; 0 < n; ++u1, ++u2, --n ) { ldap_unicode_t uu1 = uctolower( *u1 ); ldap_unicode_t uu2 = uctolower( *u2 ); if( uu1 != uu2 ) { return uu1 < uu2 ? -1 : +1; } if ( uu1 == 0 ) { return 0; } } return 0; } ldap_unicode_t * ucstrnchr( const ldap_unicode_t *u, ber_len_t n, ldap_unicode_t c ) { for(; 0 < n; ++u, --n ) { if( *u == c ) { return (ldap_unicode_t *) u; } } return NULL; } ldap_unicode_t * ucstrncasechr( const ldap_unicode_t *u, ber_len_t n, ldap_unicode_t c ) { c = uctolower( c ); for(; 0 < n; ++u, --n ) { if( uctolower( *u ) == c ) { return (ldap_unicode_t *) u; } } return NULL; } void ucstr2upper( ldap_unicode_t *u, ber_len_t n ) { for(; 0 < n; ++u, --n ) { *u = uctoupper( *u ); } } struct berval * UTF8bvnormalize( struct berval *bv, struct berval *newbv, unsigned flags, void *ctx ) { int i, j, len, clen, outpos, ucsoutlen, outsize, last; char *out, *outtmp, *s; ac_uint4 *ucs, *p, *ucsout; static unsigned char mask[] = { 0, 0x7f, 0x1f, 0x0f, 0x07, 0x03, 0x01 }; unsigned casefold = flags & LDAP_UTF8_CASEFOLD; unsigned approx = flags & LDAP_UTF8_APPROX; if ( bv == NULL ) { return NULL; } s = bv->bv_val; len = bv->bv_len; if ( len == 0 ) { return ber_dupbv_x( newbv, bv, ctx ); } if ( !newbv ) { newbv = ber_memalloc_x( sizeof(struct berval), ctx ); if ( !newbv ) return NULL; } /* Should first check to see if string is already in proper * normalized form. This is almost as time consuming as * the normalization though. */ /* finish off everything up to character before first non-ascii */ if ( LDAP_UTF8_ISASCII( s ) ) { if ( casefold ) { outsize = len + 7; out = (char *) ber_memalloc_x( outsize, ctx ); if ( out == NULL ) { return NULL; } outpos = 0; for ( i = 1; (i < len) && LDAP_UTF8_ISASCII(s + i); i++ ) { out[outpos++] = TOLOWER( s[i-1] ); } if ( i == len ) { out[outpos++] = TOLOWER( s[len-1] ); out[outpos] = '\0'; newbv->bv_val = out; newbv->bv_len = outpos; return newbv; } } else { for ( i = 1; (i < len) && LDAP_UTF8_ISASCII(s + i); i++ ) { /* empty */ } if ( i == len ) { return ber_str2bv_x( s, len, 1, newbv, ctx ); } outsize = len + 7; out = (char *) ber_memalloc_x( outsize, ctx ); if ( out == NULL ) { return NULL; } outpos = i - 1; memcpy(out, s, outpos); } } else { outsize = len + 7; out = (char *) ber_memalloc_x( outsize, ctx ); if ( out == NULL ) { return NULL; } outpos = 0; i = 0; } p = ucs = ber_memalloc_x( len * sizeof(*ucs), ctx ); if ( ucs == NULL ) { ber_memfree_x(out, ctx); return NULL; } /* convert character before first non-ascii to ucs-4 */ if ( i > 0 ) { *p = casefold ? TOLOWER( s[i-1] ) : s[i-1]; p++; } /* s[i] is now first non-ascii character */ for (;;) { /* s[i] is non-ascii */ /* convert everything up to next ascii to ucs-4 */ while ( i < len ) { clen = LDAP_UTF8_CHARLEN2( s + i, clen ); if ( clen == 0 ) { ber_memfree_x( ucs, ctx ); ber_memfree_x( out, ctx ); return NULL; } if ( clen == 1 ) { /* ascii */ break; } *p = s[i] & mask[clen]; i++; for( j = 1; j < clen; j++ ) { if ( (s[i] & 0xc0) != 0x80 ) { ber_memfree_x( ucs, ctx ); ber_memfree_x( out, ctx ); return NULL; } *p <<= 6; *p |= s[i] & 0x3f; i++; } if ( casefold ) { *p = uctolower( *p ); } p++; } /* normalize ucs of length p - ucs */ uccompatdecomp( ucs, p - ucs, &ucsout, &ucsoutlen, ctx ); if ( approx ) { for ( j = 0; j < ucsoutlen; j++ ) { if ( ucsout[j] < 0x80 ) { out[outpos++] = ucsout[j]; } } } else { ucsoutlen = uccanoncomp( ucsout, ucsoutlen ); /* convert ucs to utf-8 and store in out */ for ( j = 0; j < ucsoutlen; j++ ) { /* allocate more space if not enough room for 6 bytes and terminator */ if ( outsize - outpos < 7 ) { outsize = ucsoutlen - j + outpos + 6; outtmp = (char *) ber_memrealloc_x( out, outsize, ctx ); if ( outtmp == NULL ) { ber_memfree_x( ucsout, ctx ); ber_memfree_x( ucs, ctx ); ber_memfree_x( out, ctx ); return NULL; } out = outtmp; } outpos += ldap_x_ucs4_to_utf8( ucsout[j], &out[outpos] ); } } ber_memfree_x( ucsout, ctx ); ucsout = NULL; if ( i == len ) { break; } last = i; /* Allocate more space in out if necessary */ if (len - i >= outsize - outpos) { outsize += 1 + ((len - i) - (outsize - outpos)); outtmp = (char *) ber_memrealloc_x(out, outsize, ctx); if (outtmp == NULL) { ber_memfree_x( ucs, ctx ); ber_memfree_x( out, ctx ); return NULL; } out = outtmp; } /* s[i] is ascii */ /* finish off everything up to char before next non-ascii */ for ( i++; (i < len) && LDAP_UTF8_ISASCII(s + i); i++ ) { out[outpos++] = casefold ? TOLOWER( s[i-1] ) : s[i-1]; } if ( i == len ) { out[outpos++] = casefold ? TOLOWER( s[len-1] ) : s[len-1]; break; } /* convert character before next non-ascii to ucs-4 */ *ucs = casefold ? TOLOWER( s[i-1] ) : s[i-1]; p = ucs + 1; } ber_memfree_x( ucs, ctx ); out[outpos] = '\0'; newbv->bv_val = out; newbv->bv_len = outpos; return newbv; } /* compare UTF8-strings, optionally ignore casing */ /* slow, should be optimized */ int UTF8bvnormcmp( struct berval *bv1, struct berval *bv2, unsigned flags, void *ctx ) { int i, l1, l2, len, ulen, res = 0; char *s1, *s2, *done; ac_uint4 *ucs, *ucsout1, *ucsout2; unsigned casefold = flags & LDAP_UTF8_CASEFOLD; unsigned norm1 = flags & LDAP_UTF8_ARG1NFC; unsigned norm2 = flags & LDAP_UTF8_ARG2NFC; if (bv1 == NULL) { return bv2 == NULL ? 0 : -1; } else if (bv2 == NULL) { return 1; } l1 = bv1->bv_len; l2 = bv2->bv_len; len = (l1 < l2) ? l1 : l2; if (len == 0) { return l1 == 0 ? (l2 == 0 ? 0 : -1) : 1; } s1 = bv1->bv_val; s2 = bv2->bv_val; done = s1 + len; while ( (s1 < done) && LDAP_UTF8_ISASCII(s1) && LDAP_UTF8_ISASCII(s2) ) { if (casefold) { char c1 = TOLOWER(*s1); char c2 = TOLOWER(*s2); res = c1 - c2; } else { res = *s1 - *s2; } s1++; s2++; if (res) { /* done unless next character in s1 or s2 is non-ascii */ if (s1 < done) { if (!LDAP_UTF8_ISASCII(s1) || !LDAP_UTF8_ISASCII(s2)) { break; } } else if (((len < l1) && !LDAP_UTF8_ISASCII(s1)) || ((len < l2) && !LDAP_UTF8_ISASCII(s2))) { break; } return res; } } /* We have encountered non-ascii or strings equal up to len */ /* set i to number of iterations */ i = s1 - done + len; /* passed through loop at least once? */ if (i > 0) { if (!res && (s1 == done) && ((len == l1) || LDAP_UTF8_ISASCII(s1)) && ((len == l2) || LDAP_UTF8_ISASCII(s2))) { /* all ascii and equal up to len */ return l1 - l2; } /* rewind one char, and do normalized compare from there */ s1--; s2--; l1 -= i - 1; l2 -= i - 1; } /* Should first check to see if strings are already in * proper normalized form. */ ucs = malloc( ( ( norm1 || l1 > l2 ) ? l1 : l2 ) * sizeof(*ucs) ); if ( ucs == NULL ) { return l1 > l2 ? 1 : -1; /* what to do??? */ } /* * XXYYZ: we convert to ucs4 even though -llunicode * expects ucs2 in an ac_uint4 */ /* convert and normalize 1st string */ for ( i = 0, ulen = 0; i < l1; i += len, ulen++ ) { ucs[ulen] = ldap_x_utf8_to_ucs4( s1 + i ); if ( ucs[ulen] == LDAP_UCS4_INVALID ) { free( ucs ); return -1; /* what to do??? */ } len = LDAP_UTF8_CHARLEN( s1 + i ); } if ( norm1 ) { ucsout1 = ucs; l1 = ulen; ucs = malloc( l2 * sizeof(*ucs) ); if ( ucs == NULL ) { free( ucsout1 ); return l1 > l2 ? 1 : -1; /* what to do??? */ } } else { uccompatdecomp( ucs, ulen, &ucsout1, &l1, ctx ); l1 = uccanoncomp( ucsout1, l1 ); } /* convert and normalize 2nd string */ for ( i = 0, ulen = 0; i < l2; i += len, ulen++ ) { ucs[ulen] = ldap_x_utf8_to_ucs4( s2 + i ); if ( ucs[ulen] == LDAP_UCS4_INVALID ) { free( ucsout1 ); free( ucs ); return 1; /* what to do??? */ } len = LDAP_UTF8_CHARLEN( s2 + i ); } if ( norm2 ) { ucsout2 = ucs; l2 = ulen; } else { uccompatdecomp( ucs, ulen, &ucsout2, &l2, ctx ); l2 = uccanoncomp( ucsout2, l2 ); free( ucs ); } res = casefold ? ucstrncasecmp( ucsout1, ucsout2, l1 < l2 ? l1 : l2 ) : ucstrncmp( ucsout1, ucsout2, l1 < l2 ? l1 : l2 ); free( ucsout1 ); free( ucsout2 ); if ( res != 0 ) { return res; } if ( l1 == l2 ) { return 0; } return l1 > l2 ? 1 : -1; } openldap-2.4.42+dfsg/libraries/liblunicode/ure/0000755000175000017500000000000012563404150020070 5ustar ryanryanopenldap-2.4.42+dfsg/libraries/liblunicode/ure/README0000644000175000017500000001406612563404150020757 0ustar ryanryan# # $Id: README,v 1.3 1999/09/21 15:47:43 mleisher Exp $ # # Copyright 1997, 1998, 1999 Computing Research Labs, # New Mexico State University # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT # OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR # THE USE OR OTHER DEALINGS IN THE SOFTWARE. # Unicode and Regular Expressions Version 0.5 This is a simple regular expression package for matching against Unicode text in UCS2 form. The implementation of this URE package is a variation on the RE->DFA algorithm done by Mark Hopkins (markh@csd4.csd.uwm.edu). Mark Hopkins' algorithm had the virtue of being very simple, so it was used as a model. --------------------------------------------------------------------------- Assumptions: o Regular expression and text already normalized. o Conversion to lower case assumes a 1-1 mapping. Definitions: Separator - any one of U+2028, U+2029, '\n', '\r'. Operators: . - match any character. * - match zero or more of the last subexpression. + - match one or more of the last subexpression. ? - match zero or one of the last subexpression. () - subexpression grouping. Notes: o The "." operator normally does not match separators, but a flag is available for the ure_exec() function that will allow this operator to match a separator. Literals and Constants: c - literal UCS2 character. \x.... - hexadecimal number of up to 4 digits. \X.... - hexadecimal number of up to 4 digits. \u.... - hexadecimal number of up to 4 digits. \U.... - hexadecimal number of up to 4 digits. Character classes: [...] - Character class. [^...] - Negated character class. \pN1,N2,...,Nn - Character properties class. \PN1,N2,...,Nn - Negated character properties class. POSIX character classes recognized: :alnum: :alpha: :cntrl: :digit: :graph: :lower: :print: :punct: :space: :upper: :xdigit: Notes: o Character property classes are \p or \P followed by a comma separated list of integers between 1 and 32. These integers are references to the following character properties: N Character Property -------------------------- 1 _URE_NONSPACING 2 _URE_COMBINING 3 _URE_NUMDIGIT 4 _URE_NUMOTHER 5 _URE_SPACESEP 6 _URE_LINESEP 7 _URE_PARASEP 8 _URE_CNTRL 9 _URE_PUA 10 _URE_UPPER 11 _URE_LOWER 12 _URE_TITLE 13 _URE_MODIFIER 14 _URE_OTHERLETTER 15 _URE_DASHPUNCT 16 _URE_OPENPUNCT 17 _URE_CLOSEPUNCT 18 _URE_OTHERPUNCT 19 _URE_MATHSYM 20 _URE_CURRENCYSYM 21 _URE_OTHERSYM 22 _URE_LTR 23 _URE_RTL 24 _URE_EURONUM 25 _URE_EURONUMSEP 26 _URE_EURONUMTERM 27 _URE_ARABNUM 28 _URE_COMMONSEP 29 _URE_BLOCKSEP 30 _URE_SEGMENTSEP 31 _URE_WHITESPACE 32 _URE_OTHERNEUT o Character classes can contain literals, constants, and character property classes. Example: [abc\U10A\p1,3,4] --------------------------------------------------------------------------- Before using URE ---------------- Before URE is used, two functions need to be created. One to check if a character matches a set of URE character properties, and one to convert a character to lower case. Stubs for these function are located in the urestubs.c file. Using URE --------- Sample pseudo-code fragment. ure_buffer_t rebuf; ure_dfa_t dfa; ucs2_t *re, *text; unsigned long relen, textlen; unsigned long match_start, match_end; /* * Allocate the dynamic storage needed to compile regular expressions. */ rebuf = ure_buffer_create(); for each regular expression in a list { re = next regular expression; relen = length(re); /* * Compile the regular expression with the case insensitive flag * turned on. */ dfa = ure_compile(re, relen, 1, rebuf); /* * Look for the first match in some text. The matching will be done * in a case insensitive manner because the expression was compiled * with the case insensitive flag on. */ if (ure_exec(dfa, 0, text, textlen, &match_start, &match_end)) printf("MATCH: %ld %ld\n", match_start, match_end); /* * Look for the first match in some text, ignoring non-spacing * characters. */ if (ure_exec(dfa, URE_IGNORE_NONSPACING, text, textlen, &match_start, &match_end)) printf("MATCH: %ld %ld\n", match_start, match_end); /* * Free the DFA. */ ure_free_dfa(dfa); } /* * Free the dynamic storage used for compiling the expressions. */ ure_free_buffer(rebuf); --------------------------------------------------------------------------- Mark Leisher 29 March 1997 =========================================================================== CHANGES ------- Version: 0.5 Date : 21 September 1999 ========================== 1. Added copyright stuff and put in CVS. openldap-2.4.42+dfsg/libraries/liblunicode/ure/ure.c0000644000175000017500000017044112563404150021036 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Copyright 1997, 1998, 1999 Computing Research Labs, * New Mexico State University * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* $Id: ure.c,v 1.2 1999/09/21 15:47:43 mleisher Exp $" */ #include "portable.h" #include #include #include #include "ure.h" /* * Flags used internally in the DFA. */ #define _URE_DFA_CASEFOLD 0x01 #define _URE_DFA_BLANKLINE 0x02 static unsigned long cclass_flags[] = { 0, _URE_NONSPACING, _URE_COMBINING, _URE_NUMDIGIT, _URE_NUMOTHER, _URE_SPACESEP, _URE_LINESEP, _URE_PARASEP, _URE_CNTRL, _URE_PUA, _URE_UPPER, _URE_LOWER, _URE_TITLE, _URE_MODIFIER, _URE_OTHERLETTER, _URE_DASHPUNCT, _URE_OPENPUNCT, _URE_CLOSEPUNCT, _URE_OTHERPUNCT, _URE_MATHSYM, _URE_CURRENCYSYM, _URE_OTHERSYM, _URE_LTR, _URE_RTL, _URE_EURONUM, _URE_EURONUMSEP, _URE_EURONUMTERM, _URE_ARABNUM, _URE_COMMONSEP, _URE_BLOCKSEP, _URE_SEGMENTSEP, _URE_WHITESPACE, _URE_OTHERNEUT, }; /* * Symbol types for the DFA. */ #define _URE_ANY_CHAR 1 #define _URE_CHAR 2 #define _URE_CCLASS 3 #define _URE_NCCLASS 4 #define _URE_BOL_ANCHOR 5 #define _URE_EOL_ANCHOR 6 /* * Op codes for converting the NFA to a DFA. */ #define _URE_SYMBOL 10 #define _URE_PAREN 11 #define _URE_QUEST 12 #define _URE_STAR 13 #define _URE_PLUS 14 #define _URE_ONE 15 #define _URE_AND 16 #define _URE_OR 17 #define _URE_NOOP 0xffff #define _URE_REGSTART 0x8000 #define _URE_REGEND 0x4000 /* * Structure used to handle a compacted range of characters. */ typedef struct { ucs4_t min_code; ucs4_t max_code; } _ure_range_t; typedef struct { _ure_range_t *ranges; ucs2_t ranges_used; ucs2_t ranges_size; } _ure_ccl_t; typedef union { ucs4_t chr; _ure_ccl_t ccl; } _ure_sym_t; /* * This is a general element structure used for expressions and stack * elements. */ typedef struct { ucs2_t reg; ucs2_t onstack; ucs2_t type; ucs2_t lhs; ucs2_t rhs; } _ure_elt_t; /* * This is a structure used to track a list or a stack of states. */ typedef struct { ucs2_t *slist; ucs2_t slist_size; ucs2_t slist_used; } _ure_stlist_t; /* * Structure to track the list of unique states for a symbol * during reduction. */ typedef struct { ucs2_t id; ucs2_t type; unsigned long mods; unsigned long props; _ure_sym_t sym; _ure_stlist_t states; } _ure_symtab_t; /* * Structure to hold a single state. */ typedef struct { ucs2_t id; ucs2_t accepting; ucs2_t pad; _ure_stlist_t st; _ure_elt_t *trans; ucs2_t trans_size; ucs2_t trans_used; } _ure_state_t; /* * Structure used for keeping lists of states. */ typedef struct { _ure_state_t *states; ucs2_t states_size; ucs2_t states_used; } _ure_statetable_t; /* * Structure to track pairs of DFA states when equivalent states are * merged. */ typedef struct { ucs2_t l; ucs2_t r; } _ure_equiv_t; /* * Structure used for constructing the NFA and reducing to a minimal DFA. */ typedef struct _ure_buffer_t { int reducing; int error; unsigned long flags; _ure_stlist_t stack; /* * Table of unique symbols encountered. */ _ure_symtab_t *symtab; ucs2_t symtab_size; ucs2_t symtab_used; /* * Tracks the unique expressions generated for the NFA and when the NFA is * reduced. */ _ure_elt_t *expr; ucs2_t expr_used; ucs2_t expr_size; /* * The reduced table of unique groups of NFA states. */ _ure_statetable_t states; /* * Tracks states when equivalent states are merged. */ _ure_equiv_t *equiv; ucs2_t equiv_used; ucs2_t equiv_size; } _ure_buffer_t; typedef struct { ucs2_t symbol; ucs2_t next_state; } _ure_trans_t; typedef struct { ucs2_t accepting; ucs2_t ntrans; _ure_trans_t *trans; } _ure_dstate_t; typedef struct _ure_dfa_t { unsigned long flags; _ure_symtab_t *syms; ucs2_t nsyms; _ure_dstate_t *states; ucs2_t nstates; _ure_trans_t *trans; ucs2_t ntrans; } _ure_dfa_t; /************************************************************************* * * Functions. * *************************************************************************/ static void _ure_memmove(char *dest, char *src, unsigned long bytes) { long i, j; i = (long) bytes; j = i & 7; i = (i + 7) >> 3; /* * Do a memmove using Ye Olde Duff's Device for efficiency. */ if (src < dest) { src += bytes; dest += bytes; switch (j) { case 0: do { *--dest = *--src; case 7: *--dest = *--src; case 6: *--dest = *--src; case 5: *--dest = *--src; case 4: *--dest = *--src; case 3: *--dest = *--src; case 2: *--dest = *--src; case 1: *--dest = *--src; } while (--i > 0); } } else if (src > dest) { switch (j) { case 0: do { *dest++ = *src++; case 7: *dest++ = *src++; case 6: *dest++ = *src++; case 5: *dest++ = *src++; case 4: *dest++ = *src++; case 3: *dest++ = *src++; case 2: *dest++ = *src++; case 1: *dest++ = *src++; } while (--i > 0); } } } static void _ure_push(ucs2_t v, _ure_buffer_t *b) { _ure_stlist_t *s; if (b == 0) return; /* * If the `reducing' parameter is non-zero, check to see if the value * passed is already on the stack. */ if (b->reducing != 0 && b->expr[v].onstack != 0) return; s = &b->stack; if (s->slist_used == s->slist_size) { if (s->slist_size == 0) s->slist = (ucs2_t *) malloc(sizeof(ucs2_t) << 3); else s->slist = (ucs2_t *) realloc((char *) s->slist, sizeof(ucs2_t) * (s->slist_size + 8)); s->slist_size += 8; } s->slist[s->slist_used++] = v; /* * If the `reducing' parameter is non-zero, flag the element as being on * the stack. */ if (b->reducing != 0) b->expr[v].onstack = 1; } static ucs2_t _ure_peek(_ure_buffer_t *b) { if (b == 0 || b->stack.slist_used == 0) return _URE_NOOP; return b->stack.slist[b->stack.slist_used - 1]; } static ucs2_t _ure_pop(_ure_buffer_t *b) { ucs2_t v; if (b == 0 || b->stack.slist_used == 0) return _URE_NOOP; v = b->stack.slist[--b->stack.slist_used]; if (b->reducing) b->expr[v].onstack = 0; return v; } /************************************************************************* * * Start symbol parse functions. * *************************************************************************/ /* * Parse a comma-separated list of integers that represent character * properties. Combine them into a mask that is returned in the `mask' * variable, and return the number of characters consumed. */ static unsigned long _ure_prop_list(ucs2_t *pp, unsigned long limit, unsigned long *mask, _ure_buffer_t *b) { unsigned long n, m; ucs2_t *sp, *ep; sp = pp; ep = sp + limit; for (m = n = 0; b->error == _URE_OK && sp < ep; sp++) { if (*sp == ',') { /* * Encountered a comma, so select the next character property flag * and reset the number. */ m |= cclass_flags[n]; n = 0; } else if (*sp >= '0' && *sp <= '9') /* * Encountered a digit, so start or continue building the cardinal * that represents the character property flag. */ n = (n * 10) + (*sp - '0'); else /* * Encountered something that is not part of the property list. * Indicate that we are done. */ break; /* * If a property number greater than 32 occurs, then there is a * problem. Most likely a missing comma separator. */ if (n > 32) b->error = _URE_INVALID_PROPERTY; } if (b->error == _URE_OK && n != 0) m |= cclass_flags[n]; /* * Set the mask that represents the group of character properties. */ *mask = m; /* * Return the number of characters consumed. */ return sp - pp; } /* * Collect a hex number with 1 to 4 digits and return the number * of characters used. */ static unsigned long _ure_hex(ucs2_t *np, unsigned long limit, ucs4_t *n) { ucs2_t i; ucs2_t *sp, *ep; ucs4_t nn; sp = np; ep = sp + limit; for (nn = 0, i = 0; i < 4 && sp < ep; i++, sp++) { if (*sp >= '0' && *sp <= '9') nn = (nn << 4) + (*sp - '0'); else if (*sp >= 'A' && *sp <= 'F') nn = (nn << 4) + ((*sp - 'A') + 10); else if (*sp >= 'a' && *sp <= 'f') nn = (nn << 4) + ((*sp - 'a') + 10); else /* * Encountered something that is not a hex digit. */ break; } /* * Assign the character code collected and return the number of * characters used. */ *n = nn; return sp - np; } /* * Insert a range into a character class, removing duplicates and ordering * them in increasing range-start order. */ static void _ure_add_range(_ure_ccl_t *ccl, _ure_range_t *r, _ure_buffer_t *b) { ucs2_t i; ucs4_t tmp; _ure_range_t *rp; /* * If the `casefold' flag is set, then make sure both endpoints of the * range are converted to lower case. */ if (b->flags & _URE_DFA_CASEFOLD) { r->min_code = _ure_tolower(r->min_code); r->max_code = _ure_tolower(r->max_code); } /* * Swap the range endpoints if they are not in increasing order. */ if (r->min_code > r->max_code) { tmp = r->min_code; r->min_code = r->max_code; r->max_code = tmp; } for (i = 0, rp = ccl->ranges; i < ccl->ranges_used && r->min_code < rp->min_code; i++, rp++) ; /* * Check for a duplicate. */ if (i < ccl->ranges_used && r->min_code == rp->min_code && r->max_code == rp->max_code) return; if (ccl->ranges_used == ccl->ranges_size) { if (ccl->ranges_size == 0) ccl->ranges = (_ure_range_t *) malloc(sizeof(_ure_range_t) << 3); else ccl->ranges = (_ure_range_t *) realloc((char *) ccl->ranges, sizeof(_ure_range_t) * (ccl->ranges_size + 8)); ccl->ranges_size += 8; } rp = ccl->ranges + ccl->ranges_used; if (i < ccl->ranges_used) _ure_memmove((char *) (rp + 1), (char *) rp, sizeof(_ure_range_t) * (ccl->ranges_used - i)); ccl->ranges_used++; rp->min_code = r->min_code; rp->max_code = r->max_code; } #define _URE_ALPHA_MASK (_URE_UPPER|_URE_LOWER|_URE_OTHERLETTER|\ _URE_MODIFIER|_URE_TITLE|_URE_NONSPACING|_URE_COMBINING) #define _URE_ALNUM_MASK (_URE_ALPHA_MASK|_URE_NUMDIGIT) #define _URE_PUNCT_MASK (_URE_DASHPUNCT|_URE_OPENPUNCT|_URE_CLOSEPUNCT|\ _URE_OTHERPUNCT) #define _URE_GRAPH_MASK (_URE_NUMDIGIT|_URE_NUMOTHER|_URE_ALPHA_MASK|\ _URE_MATHSYM|_URE_CURRENCYSYM|_URE_OTHERSYM) #define _URE_PRINT_MASK (_URE_GRAPH_MASK|_URE_SPACESEP) #define _URE_SPACE_MASK (_URE_SPACESEP|_URE_LINESEP|_URE_PARASEP) typedef void (*_ure_cclsetup_t)( _ure_symtab_t *sym, unsigned long mask, _ure_buffer_t *b ); typedef struct { ucs2_t key; unsigned long len; unsigned long next; _ure_cclsetup_t func; unsigned long mask; } _ure_trie_t; static void _ure_ccl_setup(_ure_symtab_t *sym, unsigned long mask, _ure_buffer_t *b) { sym->props |= mask; } static void _ure_space_setup(_ure_symtab_t *sym, unsigned long mask, _ure_buffer_t *b) { _ure_range_t range; sym->props |= mask; /* * Add the additional characters needed for handling isspace(). */ range.min_code = range.max_code = '\t'; _ure_add_range(&sym->sym.ccl, &range, b); range.min_code = range.max_code = '\r'; _ure_add_range(&sym->sym.ccl, &range, b); range.min_code = range.max_code = '\n'; _ure_add_range(&sym->sym.ccl, &range, b); range.min_code = range.max_code = '\f'; _ure_add_range(&sym->sym.ccl, &range, b); range.min_code = range.max_code = 0xfeff; _ure_add_range(&sym->sym.ccl, &range, b); } static void _ure_xdigit_setup(_ure_symtab_t *sym, unsigned long mask, _ure_buffer_t *b) { _ure_range_t range; /* * Add the additional characters needed for handling isxdigit(). */ range.min_code = '0'; range.max_code = '9'; _ure_add_range(&sym->sym.ccl, &range, b); range.min_code = 'A'; range.max_code = 'F'; _ure_add_range(&sym->sym.ccl, &range, b); range.min_code = 'a'; range.max_code = 'f'; _ure_add_range(&sym->sym.ccl, &range, b); } static _ure_trie_t cclass_trie[] = { {0x003a, 1, 1, 0, 0}, {0x0061, 9, 10, 0, 0}, {0x0063, 8, 19, 0, 0}, {0x0064, 7, 24, 0, 0}, {0x0067, 6, 29, 0, 0}, {0x006c, 5, 34, 0, 0}, {0x0070, 4, 39, 0, 0}, {0x0073, 3, 49, 0, 0}, {0x0075, 2, 54, 0, 0}, {0x0078, 1, 59, 0, 0}, {0x006c, 1, 11, 0, 0}, {0x006e, 2, 13, 0, 0}, {0x0070, 1, 16, 0, 0}, {0x0075, 1, 14, 0, 0}, {0x006d, 1, 15, 0, 0}, {0x003a, 1, 16, _ure_ccl_setup, _URE_ALNUM_MASK}, {0x0068, 1, 17, 0, 0}, {0x0061, 1, 18, 0, 0}, {0x003a, 1, 19, _ure_ccl_setup, _URE_ALPHA_MASK}, {0x006e, 1, 20, 0, 0}, {0x0074, 1, 21, 0, 0}, {0x0072, 1, 22, 0, 0}, {0x006c, 1, 23, 0, 0}, {0x003a, 1, 24, _ure_ccl_setup, _URE_CNTRL}, {0x0069, 1, 25, 0, 0}, {0x0067, 1, 26, 0, 0}, {0x0069, 1, 27, 0, 0}, {0x0074, 1, 28, 0, 0}, {0x003a, 1, 29, _ure_ccl_setup, _URE_NUMDIGIT}, {0x0072, 1, 30, 0, 0}, {0x0061, 1, 31, 0, 0}, {0x0070, 1, 32, 0, 0}, {0x0068, 1, 33, 0, 0}, {0x003a, 1, 34, _ure_ccl_setup, _URE_GRAPH_MASK}, {0x006f, 1, 35, 0, 0}, {0x0077, 1, 36, 0, 0}, {0x0065, 1, 37, 0, 0}, {0x0072, 1, 38, 0, 0}, {0x003a, 1, 39, _ure_ccl_setup, _URE_LOWER}, {0x0072, 2, 41, 0, 0}, {0x0075, 1, 45, 0, 0}, {0x0069, 1, 42, 0, 0}, {0x006e, 1, 43, 0, 0}, {0x0074, 1, 44, 0, 0}, {0x003a, 1, 45, _ure_ccl_setup, _URE_PRINT_MASK}, {0x006e, 1, 46, 0, 0}, {0x0063, 1, 47, 0, 0}, {0x0074, 1, 48, 0, 0}, {0x003a, 1, 49, _ure_ccl_setup, _URE_PUNCT_MASK}, {0x0070, 1, 50, 0, 0}, {0x0061, 1, 51, 0, 0}, {0x0063, 1, 52, 0, 0}, {0x0065, 1, 53, 0, 0}, {0x003a, 1, 54, _ure_space_setup, _URE_SPACE_MASK}, {0x0070, 1, 55, 0, 0}, {0x0070, 1, 56, 0, 0}, {0x0065, 1, 57, 0, 0}, {0x0072, 1, 58, 0, 0}, {0x003a, 1, 59, _ure_ccl_setup, _URE_UPPER}, {0x0064, 1, 60, 0, 0}, {0x0069, 1, 61, 0, 0}, {0x0067, 1, 62, 0, 0}, {0x0069, 1, 63, 0, 0}, {0x0074, 1, 64, 0, 0}, {0x003a, 1, 65, _ure_xdigit_setup, 0}, }; /* * Probe for one of the POSIX colon delimited character classes in the static * trie. */ static unsigned long _ure_posix_ccl(ucs2_t *cp, unsigned long limit, _ure_symtab_t *sym, _ure_buffer_t *b) { int i; unsigned long n; _ure_trie_t *tp; ucs2_t *sp, *ep; /* * If the number of characters left is less than 7, then this cannot be * interpreted as one of the colon delimited classes. */ if (limit < 7) return 0; sp = cp; ep = sp + limit; tp = cclass_trie; for (i = 0; sp < ep && i < 8; i++, sp++) { n = tp->len; for (; n > 0 && tp->key != *sp; tp++, n--) ; if (n == 0) return 0; if (*sp == ':' && (i == 6 || i == 7)) { sp++; break; } if (sp + 1 < ep) tp = cclass_trie + tp->next; } if (tp->func == 0) return 0; (*tp->func)(sym, tp->mask, b); return sp - cp; } /* * Construct a list of ranges and return the number of characters consumed. */ static unsigned long _ure_cclass(ucs2_t *cp, unsigned long limit, _ure_symtab_t *symp, _ure_buffer_t *b) { int range_end; unsigned long n; ucs2_t *sp, *ep; ucs4_t c, last; _ure_ccl_t *cclp; _ure_range_t range; sp = cp; ep = sp + limit; if (*sp == '^') { symp->type = _URE_NCCLASS; sp++; } else symp->type = _URE_CCLASS; for (last = 0, range_end = 0; b->error == _URE_OK && sp < ep && *sp != ']'; ) { c = *sp++; if (c == '\\') { if (sp == ep) { /* * The EOS was encountered when expecting the reverse solidus * to be followed by the character it is escaping. Set an * error code and return the number of characters consumed up * to this point. */ b->error = _URE_UNEXPECTED_EOS; return sp - cp; } c = *sp++; switch (c) { case 'a': c = 0x07; break; case 'b': c = 0x08; break; case 'f': c = 0x0c; break; case 'n': c = 0x0a; break; case 'r': c = 0x0d; break; case 't': c = 0x09; break; case 'v': c = 0x0b; break; case 'p': case 'P': sp += _ure_prop_list(sp, ep - sp, &symp->props, b); /* * Invert the bit mask of the properties if this is a negated * character class or if 'P' is used to specify a list of * character properties that should *not* match in a * character class. */ if (c == 'P') symp->props = ~symp->props; continue; break; case 'x': case 'X': case 'u': case 'U': if (sp < ep && ((*sp >= '0' && *sp <= '9') || (*sp >= 'A' && *sp <= 'F') || (*sp >= 'a' && *sp <= 'f'))) sp += _ure_hex(sp, ep - sp, &c); } } else if (c == ':') { /* * Probe for a POSIX colon delimited character class. */ sp--; if ((n = _ure_posix_ccl(sp, ep - sp, symp, b)) == 0) sp++; else { sp += n; continue; } } cclp = &symp->sym.ccl; /* * Check to see if the current character is a low surrogate that needs * to be combined with a preceding high surrogate. */ if (last != 0) { if (c >= 0xdc00 && c <= 0xdfff) /* * Construct the UTF16 character code. */ c = 0x10000 + (((last & 0x03ff) << 10) | (c & 0x03ff)); else { /* * Add the isolated high surrogate to the range. */ if (range_end == 1) range.max_code = last & 0xffff; else range.min_code = range.max_code = last & 0xffff; _ure_add_range(cclp, &range, b); range_end = 0; } } /* * Clear the last character code. */ last = 0; /* * This slightly awkward code handles the different cases needed to * construct a range. */ if (c >= 0xd800 && c <= 0xdbff) { /* * If the high surrogate is followed by a range indicator, simply * add it as the range start. Otherwise, save it in case the next * character is a low surrogate. */ if (*sp == '-') { sp++; range.min_code = c; range_end = 1; } else last = c; } else if (range_end == 1) { range.max_code = c; _ure_add_range(cclp, &range, b); range_end = 0; } else { range.min_code = range.max_code = c; if (*sp == '-') { sp++; range_end = 1; } else _ure_add_range(cclp, &range, b); } } if (sp < ep && *sp == ']') sp++; else /* * The parse was not terminated by the character class close symbol * (']'), so set an error code. */ b->error = _URE_CCLASS_OPEN; return sp - cp; } /* * Probe for a low surrogate hex code. */ static unsigned long _ure_probe_ls(ucs2_t *ls, unsigned long limit, ucs4_t *c) { ucs4_t i, code; ucs2_t *sp, *ep; for (i = code = 0, sp = ls, ep = sp + limit; i < 4 && sp < ep; sp++) { if (*sp >= '0' && *sp <= '9') code = (code << 4) + (*sp - '0'); else if (*sp >= 'A' && *sp <= 'F') code = (code << 4) + ((*sp - 'A') + 10); else if (*sp >= 'a' && *sp <= 'f') code = (code << 4) + ((*sp - 'a') + 10); else break; } *c = code; return (0xdc00 <= code && code <= 0xdfff) ? sp - ls : 0; } static unsigned long _ure_compile_symbol(ucs2_t *sym, unsigned long limit, _ure_symtab_t *symp, _ure_buffer_t *b) { ucs4_t c; ucs2_t *sp, *ep; sp = sym; ep = sym + limit; if ((c = *sp++) == '\\') { if (sp == ep) { /* * The EOS was encountered when expecting the reverse solidus to * be followed by the character it is escaping. Set an error code * and return the number of characters consumed up to this point. */ b->error = _URE_UNEXPECTED_EOS; return sp - sym; } c = *sp++; switch (c) { case 'p': case 'P': symp->type = (c == 'p') ? _URE_CCLASS : _URE_NCCLASS; sp += _ure_prop_list(sp, ep - sp, &symp->props, b); break; case 'a': symp->type = _URE_CHAR; symp->sym.chr = 0x07; break; case 'b': symp->type = _URE_CHAR; symp->sym.chr = 0x08; break; case 'f': symp->type = _URE_CHAR; symp->sym.chr = 0x0c; break; case 'n': symp->type = _URE_CHAR; symp->sym.chr = 0x0a; break; case 'r': symp->type = _URE_CHAR; symp->sym.chr = 0x0d; break; case 't': symp->type = _URE_CHAR; symp->sym.chr = 0x09; break; case 'v': symp->type = _URE_CHAR; symp->sym.chr = 0x0b; break; case 'x': case 'X': case 'u': case 'U': /* * Collect between 1 and 4 digits representing a UCS2 code. Fall * through to the next case. */ if (sp < ep && ((*sp >= '0' && *sp <= '9') || (*sp >= 'A' && *sp <= 'F') || (*sp >= 'a' && *sp <= 'f'))) sp += _ure_hex(sp, ep - sp, &c); /* FALLTHROUGH */ default: /* * Simply add an escaped character here. */ symp->type = _URE_CHAR; symp->sym.chr = c; } } else if (c == '^' || c == '$') /* * Handle the BOL and EOL anchors. This actually consists simply of * setting a flag that indicates that the user supplied anchor match * function should be called. This needs to be done instead of simply * matching line/paragraph separators because beginning-of-text and * end-of-text tests are needed as well. */ symp->type = (c == '^') ? _URE_BOL_ANCHOR : _URE_EOL_ANCHOR; else if (c == '[') /* * Construct a character class. */ sp += _ure_cclass(sp, ep - sp, symp, b); else if (c == '.') symp->type = _URE_ANY_CHAR; else { symp->type = _URE_CHAR; symp->sym.chr = c; } /* * If the symbol type happens to be a character and is a high surrogate, * then probe forward to see if it is followed by a low surrogate that * needs to be added. */ if (sp < ep && symp->type == _URE_CHAR && 0xd800 <= symp->sym.chr && symp->sym.chr <= 0xdbff) { if (0xdc00 <= *sp && *sp <= 0xdfff) { symp->sym.chr = 0x10000 + (((symp->sym.chr & 0x03ff) << 10) | (*sp & 0x03ff)); sp++; } else if (*sp == '\\' && (*(sp + 1) == 'x' || *(sp + 1) == 'X' || *(sp + 1) == 'u' || *(sp + 1) == 'U')) { sp += _ure_probe_ls(sp + 2, ep - (sp + 2), &c); if (0xdc00 <= c && c <= 0xdfff) { /* * Take into account the \[xu] in front of the hex code. */ sp += 2; symp->sym.chr = 0x10000 + (((symp->sym.chr & 0x03ff) << 10) | (c & 0x03ff)); } } } /* * Last, make sure any _URE_CHAR type symbols are changed to lower case if * the `casefold' flag is set. */ if ((b->flags & _URE_DFA_CASEFOLD) && symp->type == _URE_CHAR) symp->sym.chr = _ure_tolower(symp->sym.chr); /* * If the symbol constructed is anything other than one of the anchors, * make sure the _URE_DFA_BLANKLINE flag is removed. */ if (symp->type != _URE_BOL_ANCHOR && symp->type != _URE_EOL_ANCHOR) b->flags &= ~_URE_DFA_BLANKLINE; /* * Return the number of characters consumed. */ return sp - sym; } static int _ure_sym_neq(_ure_symtab_t *a, _ure_symtab_t *b) { if (a->type != b->type || a->mods != b->mods || a->props != b->props) return 1; if (a->type == _URE_CCLASS || a->type == _URE_NCCLASS) { if (a->sym.ccl.ranges_used != b->sym.ccl.ranges_used) return 1; if (a->sym.ccl.ranges_used > 0 && memcmp((char *) a->sym.ccl.ranges, (char *) b->sym.ccl.ranges, sizeof(_ure_range_t) * a->sym.ccl.ranges_used) != 0) return 1; } else if (a->type == _URE_CHAR && a->sym.chr != b->sym.chr) return 1; return 0; } /* * Construct a symbol, but only keep unique symbols. */ static ucs2_t _ure_make_symbol(ucs2_t *sym, unsigned long limit, unsigned long *consumed, _ure_buffer_t *b) { ucs2_t i; _ure_symtab_t *sp, symbol; /* * Build the next symbol so we can test to see if it is already in the * symbol table. */ (void) memset((char *) &symbol, '\0', sizeof(_ure_symtab_t)); *consumed = _ure_compile_symbol(sym, limit, &symbol, b); /* * Check to see if the symbol exists. */ for (i = 0, sp = b->symtab; i < b->symtab_used && _ure_sym_neq(&symbol, sp); i++, sp++) ; if (i < b->symtab_used) { /* * Free up any ranges used for the symbol. */ if ((symbol.type == _URE_CCLASS || symbol.type == _URE_NCCLASS) && symbol.sym.ccl.ranges_size > 0) free((char *) symbol.sym.ccl.ranges); return b->symtab[i].id; } /* * Need to add the new symbol. */ if (b->symtab_used == b->symtab_size) { if (b->symtab_size == 0) b->symtab = (_ure_symtab_t *) malloc(sizeof(_ure_symtab_t) << 3); else b->symtab = (_ure_symtab_t *) realloc((char *) b->symtab, sizeof(_ure_symtab_t) * (b->symtab_size + 8)); sp = b->symtab + b->symtab_size; (void) memset((char *) sp, '\0', sizeof(_ure_symtab_t) << 3); b->symtab_size += 8; } symbol.id = b->symtab_used++; (void) AC_MEMCPY((char *) &b->symtab[symbol.id], (char *) &symbol, sizeof(_ure_symtab_t)); return symbol.id; } /************************************************************************* * * End symbol parse functions. * *************************************************************************/ static ucs2_t _ure_make_expr(ucs2_t type, ucs2_t lhs, ucs2_t rhs, _ure_buffer_t *b) { ucs2_t i; if (b == 0) return _URE_NOOP; /* * Determine if the expression already exists or not. */ for (i = 0; i < b->expr_used; i++) { if (b->expr[i].type == type && b->expr[i].lhs == lhs && b->expr[i].rhs == rhs) break; } if (i < b->expr_used) return i; /* * Need to add a new expression. */ if (b->expr_used == b->expr_size) { if (b->expr_size == 0) b->expr = (_ure_elt_t *) malloc(sizeof(_ure_elt_t) << 3); else b->expr = (_ure_elt_t *) realloc((char *) b->expr, sizeof(_ure_elt_t) * (b->expr_size + 8)); b->expr_size += 8; } b->expr[b->expr_used].onstack = 0; b->expr[b->expr_used].type = type; b->expr[b->expr_used].lhs = lhs; b->expr[b->expr_used].rhs = rhs; return b->expr_used++; } static unsigned char spmap[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; #define _ure_isspecial(cc) ((cc) > 0x20 && (cc) < 0x7f && \ (spmap[(cc) >> 3] & (1 << ((cc) & 7)))) /* * Convert the regular expression into an NFA in a form that will be easy to * reduce to a DFA. The starting state for the reduction will be returned. */ static ucs2_t _ure_re2nfa(ucs2_t *re, unsigned long relen, _ure_buffer_t *b) { ucs2_t c, state, top, sym, *sp, *ep; unsigned long used; state = _URE_NOOP; sp = re; ep = sp + relen; while (b->error == _URE_OK && sp < ep) { c = *sp++; switch (c) { case '(': _ure_push(_URE_PAREN, b); break; case ')': /* * Check for the case of too many close parentheses. */ if (_ure_peek(b) == _URE_NOOP) { b->error = _URE_UNBALANCED_GROUP; break; } while ((top = _ure_peek(b)) == _URE_AND || top == _URE_OR) /* * Make an expression with the AND or OR operator and its right * hand side. */ state = _ure_make_expr(_ure_pop(b), _ure_pop(b), state, b); /* * Remove the _URE_PAREN off the stack. */ (void) _ure_pop(b); break; case '*': state = _ure_make_expr(_URE_STAR, state, _URE_NOOP, b); break; case '+': state = _ure_make_expr(_URE_PLUS, state, _URE_NOOP, b); break; case '?': state = _ure_make_expr(_URE_QUEST, state, _URE_NOOP, b); break; case '|': while ((top = _ure_peek(b)) == _URE_AND || top == _URE_OR) /* * Make an expression with the AND or OR operator and its right * hand side. */ state = _ure_make_expr(_ure_pop(b), _ure_pop(b), state, b); _ure_push(state, b); _ure_push(_URE_OR, b); break; default: sp--; sym = _ure_make_symbol(sp, ep - sp, &used, b); sp += used; state = _ure_make_expr(_URE_SYMBOL, sym, _URE_NOOP, b); break; } if (c != '(' && c != '|' && sp < ep && (!_ure_isspecial(*sp) || *sp == '(')) { _ure_push(state, b); _ure_push(_URE_AND, b); } } while ((top = _ure_peek(b)) == _URE_AND || top == _URE_OR) /* * Make an expression with the AND or OR operator and its right * hand side. */ state = _ure_make_expr(_ure_pop(b), _ure_pop(b), state, b); if (b->stack.slist_used > 0) b->error = _URE_UNBALANCED_GROUP; return (b->error == _URE_OK) ? state : _URE_NOOP; } static void _ure_add_symstate(ucs2_t sym, ucs2_t state, _ure_buffer_t *b) { ucs2_t i, *stp; _ure_symtab_t *sp; /* * Locate the symbol in the symbol table so the state can be added. * If the symbol doesn't exist, then a real problem exists. */ for (i = 0, sp = b->symtab; i < b->symtab_used && sym != sp->id; i++, sp++) ; /* * Now find out if the state exists in the symbol's state list. */ for (i = 0, stp = sp->states.slist; i < sp->states.slist_used && state > *stp; i++, stp++) ; if (i == sp->states.slist_used || state < *stp) { /* * Need to add the state in order. */ if (sp->states.slist_used == sp->states.slist_size) { if (sp->states.slist_size == 0) sp->states.slist = (ucs2_t *) malloc(sizeof(ucs2_t) << 3); else sp->states.slist = (ucs2_t *) realloc((char *) sp->states.slist, sizeof(ucs2_t) * (sp->states.slist_size + 8)); sp->states.slist_size += 8; } if (i < sp->states.slist_used) (void) _ure_memmove((char *) (sp->states.slist + i + 1), (char *) (sp->states.slist + i), sizeof(ucs2_t) * (sp->states.slist_used - i)); sp->states.slist[i] = state; sp->states.slist_used++; } } static ucs2_t _ure_add_state(ucs2_t nstates, ucs2_t *states, _ure_buffer_t *b) { ucs2_t i; _ure_state_t *sp; for (i = 0, sp = b->states.states; i < b->states.states_used; i++, sp++) { if (sp->st.slist_used == nstates && memcmp((char *) states, (char *) sp->st.slist, sizeof(ucs2_t) * nstates) == 0) break; } if (i == b->states.states_used) { /* * Need to add a new DFA state (set of NFA states). */ if (b->states.states_used == b->states.states_size) { if (b->states.states_size == 0) b->states.states = (_ure_state_t *) malloc(sizeof(_ure_state_t) << 3); else b->states.states = (_ure_state_t *) realloc((char *) b->states.states, sizeof(_ure_state_t) * (b->states.states_size + 8)); sp = b->states.states + b->states.states_size; (void) memset((char *) sp, '\0', sizeof(_ure_state_t) << 3); b->states.states_size += 8; } sp = b->states.states + b->states.states_used++; sp->id = i; if (sp->st.slist_used + nstates > sp->st.slist_size) { if (sp->st.slist_size == 0) sp->st.slist = (ucs2_t *) malloc(sizeof(ucs2_t) * (sp->st.slist_used + nstates)); else sp->st.slist = (ucs2_t *) realloc((char *) sp->st.slist, sizeof(ucs2_t) * (sp->st.slist_used + nstates)); sp->st.slist_size = sp->st.slist_used + nstates; } sp->st.slist_used = nstates; (void) AC_MEMCPY((char *) sp->st.slist, (char *) states, sizeof(ucs2_t) * nstates); } /* * Return the ID of the DFA state representing a group of NFA states. */ return i; } static void _ure_reduce(ucs2_t start, _ure_buffer_t *b) { ucs2_t i, j, state, eval, syms, rhs; ucs2_t s1, s2, ns1, ns2; _ure_state_t *sp; _ure_symtab_t *smp; b->reducing = 1; /* * Add the starting state for the reduction. */ _ure_add_state(1, &start, b); /* * Process each set of NFA states that get created. */ for (i = 0; i < b->states.states_used; i++) { sp = b->states.states + i; /* * Push the current states on the stack. */ for (j = 0; j < sp->st.slist_used; j++) _ure_push(sp->st.slist[j], b); /* * Reduce the NFA states. */ for (j = sp->accepting = syms = 0; j < b->stack.slist_used; j++) { state = b->stack.slist[j]; eval = 1; /* * This inner loop is the iterative equivalent of recursively * reducing subexpressions generated as a result of a reduction. */ while (eval) { switch (b->expr[state].type) { case _URE_SYMBOL: ns1 = _ure_make_expr(_URE_ONE, _URE_NOOP, _URE_NOOP, b); _ure_add_symstate(b->expr[state].lhs, ns1, b); syms++; eval = 0; break; case _URE_ONE: sp->accepting = 1; eval = 0; break; case _URE_QUEST: s1 = b->expr[state].lhs; ns1 = _ure_make_expr(_URE_ONE, _URE_NOOP, _URE_NOOP, b); state = _ure_make_expr(_URE_OR, ns1, s1, b); break; case _URE_PLUS: s1 = b->expr[state].lhs; ns1 = _ure_make_expr(_URE_STAR, s1, _URE_NOOP, b); state = _ure_make_expr(_URE_AND, s1, ns1, b); break; case _URE_STAR: s1 = b->expr[state].lhs; ns1 = _ure_make_expr(_URE_ONE, _URE_NOOP, _URE_NOOP, b); ns2 = _ure_make_expr(_URE_PLUS, s1, _URE_NOOP, b); state = _ure_make_expr(_URE_OR, ns1, ns2, b); break; case _URE_OR: s1 = b->expr[state].lhs; s2 = b->expr[state].rhs; _ure_push(s1, b); _ure_push(s2, b); eval = 0; break; case _URE_AND: s1 = b->expr[state].lhs; s2 = b->expr[state].rhs; switch (b->expr[s1].type) { case _URE_SYMBOL: _ure_add_symstate(b->expr[s1].lhs, s2, b); syms++; eval = 0; break; case _URE_ONE: state = s2; break; case _URE_QUEST: ns1 = b->expr[s1].lhs; ns2 = _ure_make_expr(_URE_AND, ns1, s2, b); state = _ure_make_expr(_URE_OR, s2, ns2, b); break; case _URE_PLUS: ns1 = b->expr[s1].lhs; ns2 = _ure_make_expr(_URE_OR, s2, state, b); state = _ure_make_expr(_URE_AND, ns1, ns2, b); break; case _URE_STAR: ns1 = b->expr[s1].lhs; ns2 = _ure_make_expr(_URE_AND, ns1, state, b); state = _ure_make_expr(_URE_OR, s2, ns2, b); break; case _URE_OR: ns1 = b->expr[s1].lhs; ns2 = b->expr[s1].rhs; ns1 = _ure_make_expr(_URE_AND, ns1, s2, b); ns2 = _ure_make_expr(_URE_AND, ns2, s2, b); state = _ure_make_expr(_URE_OR, ns1, ns2, b); break; case _URE_AND: ns1 = b->expr[s1].lhs; ns2 = b->expr[s1].rhs; ns2 = _ure_make_expr(_URE_AND, ns2, s2, b); state = _ure_make_expr(_URE_AND, ns1, ns2, b); break; } } } } /* * Clear the state stack. */ while (_ure_pop(b) != _URE_NOOP) ; /* * Reset the state pointer because the reduction may have moved it * during a reallocation. */ sp = b->states.states + i; /* * Generate the DFA states for the symbols collected during the * current reduction. */ if (sp->trans_used + syms > sp->trans_size) { if (sp->trans_size == 0) sp->trans = (_ure_elt_t *) malloc(sizeof(_ure_elt_t) * (sp->trans_used + syms)); else sp->trans = (_ure_elt_t *) realloc((char *) sp->trans, sizeof(_ure_elt_t) * (sp->trans_used + syms)); sp->trans_size = sp->trans_used + syms; } /* * Go through the symbol table and generate the DFA state transitions * for each symbol that has collected NFA states. */ for (j = syms = 0, smp = b->symtab; j < b->symtab_used; j++, smp++) { sp = b->states.states + i; if (smp->states.slist_used > 0) { sp->trans[syms].lhs = smp->id; rhs = _ure_add_state(smp->states.slist_used, smp->states.slist, b); /* * Reset the state pointer in case the reallocation moves it * in memory. */ sp = b->states.states + i; sp->trans[syms].rhs = rhs; smp->states.slist_used = 0; syms++; } } /* * Set the number of transitions actually used. */ sp->trans_used = syms; } b->reducing = 0; } static void _ure_add_equiv(ucs2_t l, ucs2_t r, _ure_buffer_t *b) { ucs2_t tmp; l = b->states.states[l].id; r = b->states.states[r].id; if (l == r) return; if (l > r) { tmp = l; l = r; r = tmp; } /* * Check to see if the equivalence pair already exists. */ for (tmp = 0; tmp < b->equiv_used && (b->equiv[tmp].l != l || b->equiv[tmp].r != r); tmp++) ; if (tmp < b->equiv_used) return; if (b->equiv_used == b->equiv_size) { if (b->equiv_size == 0) b->equiv = (_ure_equiv_t *) malloc(sizeof(_ure_equiv_t) << 3); else b->equiv = (_ure_equiv_t *) realloc((char *) b->equiv, sizeof(_ure_equiv_t) * (b->equiv_size + 8)); b->equiv_size += 8; } b->equiv[b->equiv_used].l = l; b->equiv[b->equiv_used].r = r; b->equiv_used++; } /* * Merge the DFA states that are equivalent. */ static void _ure_merge_equiv(_ure_buffer_t *b) { ucs2_t i, j, k, eq, done; _ure_state_t *sp1, *sp2, *ls, *rs; for (i = 0; i < b->states.states_used; i++) { sp1 = b->states.states + i; if (sp1->id != i) continue; for (j = 0; j < i; j++) { sp2 = b->states.states + j; if (sp2->id != j) continue; b->equiv_used = 0; _ure_add_equiv(i, j, b); for (eq = 0, done = 0; eq < b->equiv_used; eq++) { ls = b->states.states + b->equiv[eq].l; rs = b->states.states + b->equiv[eq].r; if (ls->accepting != rs->accepting || ls->trans_used != rs->trans_used) { done = 1; break; } for (k = 0; k < ls->trans_used && ls->trans[k].lhs == rs->trans[k].lhs; k++) ; if (k < ls->trans_used) { done = 1; break; } for (k = 0; k < ls->trans_used; k++) _ure_add_equiv(ls->trans[k].rhs, rs->trans[k].rhs, b); } if (done == 0) break; } for (eq = 0; j < i && eq < b->equiv_used; eq++) b->states.states[b->equiv[eq].r].id = b->states.states[b->equiv[eq].l].id; } /* * Renumber the states appropriately. */ for (i = eq = 0, sp1 = b->states.states; i < b->states.states_used; sp1++, i++) sp1->id = (sp1->id == i) ? eq++ : b->states.states[sp1->id].id; } /************************************************************************* * * API. * *************************************************************************/ ure_buffer_t ure_buffer_create(void) { ure_buffer_t b; b = (ure_buffer_t) calloc(1, sizeof(_ure_buffer_t)); return b; } void ure_buffer_free(ure_buffer_t buf) { unsigned long i; if (buf == 0) return; if (buf->stack.slist_size > 0) free((char *) buf->stack.slist); if (buf->expr_size > 0) free((char *) buf->expr); for (i = 0; i < buf->symtab_size; i++) { if (buf->symtab[i].states.slist_size > 0) free((char *) buf->symtab[i].states.slist); } if (buf->symtab_size > 0) free((char *) buf->symtab); for (i = 0; i < buf->states.states_size; i++) { if (buf->states.states[i].trans_size > 0) free((char *) buf->states.states[i].trans); if (buf->states.states[i].st.slist_size > 0) free((char *) buf->states.states[i].st.slist); } if (buf->states.states_size > 0) free((char *) buf->states.states); if (buf->equiv_size > 0) free((char *) buf->equiv); free((char *) buf); } ure_dfa_t ure_compile(ucs2_t *re, unsigned long relen, int casefold, ure_buffer_t buf) { ucs2_t i, j, state; _ure_state_t *sp; _ure_dstate_t *dsp; _ure_trans_t *tp; ure_dfa_t dfa; if (re == 0 || *re == 0 || relen == 0 || buf == 0) return 0; /* * Reset the various fields of the compilation buffer. Default the flags * to indicate the presense of the "^$" pattern. If any other pattern * occurs, then this flag will be removed. This is done to catch this * special pattern and handle it specially when matching. */ buf->flags = _URE_DFA_BLANKLINE | ((casefold) ? _URE_DFA_CASEFOLD : 0); buf->reducing = 0; buf->stack.slist_used = 0; buf->expr_used = 0; for (i = 0; i < buf->symtab_used; i++) buf->symtab[i].states.slist_used = 0; buf->symtab_used = 0; for (i = 0; i < buf->states.states_used; i++) { buf->states.states[i].st.slist_used = 0; buf->states.states[i].trans_used = 0; } buf->states.states_used = 0; /* * Construct the NFA. If this stage returns a 0, then an error occured or * an empty expression was passed. */ if ((state = _ure_re2nfa(re, relen, buf)) == _URE_NOOP) return 0; /* * Do the expression reduction to get the initial DFA. */ _ure_reduce(state, buf); /* * Merge all the equivalent DFA states. */ _ure_merge_equiv(buf); /* * Construct the minimal DFA. */ dfa = (ure_dfa_t) malloc(sizeof(_ure_dfa_t)); (void) memset((char *) dfa, '\0', sizeof(_ure_dfa_t)); dfa->flags = buf->flags & (_URE_DFA_CASEFOLD|_URE_DFA_BLANKLINE); /* * Free up the NFA state groups and transfer the symbols from the buffer * to the DFA. */ for (i = 0; i < buf->symtab_size; i++) { if (buf->symtab[i].states.slist_size > 0) free((char *) buf->symtab[i].states.slist); } dfa->syms = buf->symtab; dfa->nsyms = buf->symtab_used; buf->symtab_used = buf->symtab_size = 0; /* * Collect the total number of states and transitions needed for the DFA. */ for (i = state = 0, sp = buf->states.states; i < buf->states.states_used; i++, sp++) { if (sp->id == state) { dfa->nstates++; dfa->ntrans += sp->trans_used; state++; } } /* * Allocate enough space for the states and transitions. */ dfa->states = (_ure_dstate_t *) malloc(sizeof(_ure_dstate_t) * dfa->nstates); dfa->trans = (_ure_trans_t *) malloc(sizeof(_ure_trans_t) * dfa->ntrans); /* * Actually transfer the DFA states from the buffer. */ dsp = dfa->states; tp = dfa->trans; for (i = state = 0, sp = buf->states.states; i < buf->states.states_used; i++, sp++) { if (sp->id == state) { dsp->trans = tp; dsp->ntrans = sp->trans_used; dsp->accepting = sp->accepting; /* * Add the transitions for the state. */ for (j = 0; j < dsp->ntrans; j++, tp++) { tp->symbol = sp->trans[j].lhs; tp->next_state = buf->states.states[sp->trans[j].rhs].id; } dsp++; state++; } } return dfa; } void ure_dfa_free(ure_dfa_t dfa) { ucs2_t i; if (dfa == 0) return; for (i = 0; i < dfa->nsyms; i++) { if ((dfa->syms[i].type == _URE_CCLASS || dfa->syms[i].type == _URE_NCCLASS) && dfa->syms[i].sym.ccl.ranges_size > 0) free((char *) dfa->syms[i].sym.ccl.ranges); } if (dfa->nsyms > 0) free((char *) dfa->syms); if (dfa->nstates > 0) free((char *) dfa->states); if (dfa->ntrans > 0) free((char *) dfa->trans); free((char *) dfa); } void ure_write_dfa(ure_dfa_t dfa, FILE *out) { ucs2_t i, j, k, h, l; _ure_dstate_t *sp; _ure_symtab_t *sym; _ure_range_t *rp; if (dfa == 0 || out == 0) return; /* * Write all the different character classes. */ for (i = 0, sym = dfa->syms; i < dfa->nsyms; i++, sym++) { if (sym->type == _URE_CCLASS || sym->type == _URE_NCCLASS) { fprintf(out, "C%hd = ", sym->id); if (sym->sym.ccl.ranges_used > 0) { putc('[', out); if (sym->type == _URE_NCCLASS) putc('^', out); } if (sym->props != 0) { if (sym->type == _URE_NCCLASS) fprintf(out, "\\P"); else fprintf(out, "\\p"); for (k = h = 0; k < 32; k++) { if (sym->props & (1 << k)) { if (h != 0) putc(',', out); fprintf(out, "%hd", k + 1); h = 1; } } } /* * Dump the ranges. */ for (k = 0, rp = sym->sym.ccl.ranges; k < sym->sym.ccl.ranges_used; k++, rp++) { /* * Check for UTF16 characters. */ if (0x10000 <= rp->min_code && rp->min_code <= 0x10ffff) { h = (ucs2_t) (((rp->min_code - 0x10000) >> 10) + 0xd800); l = (ucs2_t) (((rp->min_code - 0x10000) & 1023) + 0xdc00); fprintf(out, "\\x%04hX\\x%04hX", h, l); } else fprintf(out, "\\x%04lX", rp->min_code & 0xffff); if (rp->max_code != rp->min_code) { putc('-', out); if (rp->max_code >= 0x10000 && rp->max_code <= 0x10ffff) { h = (ucs2_t) (((rp->max_code - 0x10000) >> 10) + 0xd800); l = (ucs2_t) (((rp->max_code - 0x10000) & 1023) + 0xdc00); fprintf(out, "\\x%04hX\\x%04hX", h, l); } else fprintf(out, "\\x%04lX", rp->max_code & 0xffff); } } if (sym->sym.ccl.ranges_used > 0) putc(']', out); putc('\n', out); } } for (i = 0, sp = dfa->states; i < dfa->nstates; i++, sp++) { fprintf(out, "S%hd = ", i); if (sp->accepting) { fprintf(out, "1 "); if (sp->ntrans) fprintf(out, "| "); } for (j = 0; j < sp->ntrans; j++) { if (j > 0) fprintf(out, "| "); sym = dfa->syms + sp->trans[j].symbol; switch (sym->type) { case _URE_CHAR: if (0x10000 <= sym->sym.chr && sym->sym.chr <= 0x10ffff) { /* * Take care of UTF16 characters. */ h = (ucs2_t) (((sym->sym.chr - 0x10000) >> 10) + 0xd800); l = (ucs2_t) (((sym->sym.chr - 0x10000) & 1023) + 0xdc00); fprintf(out, "\\x%04hX\\x%04hX ", h, l); } else fprintf(out, "\\x%04lX ", sym->sym.chr & 0xffff); break; case _URE_ANY_CHAR: fprintf(out, " "); break; case _URE_BOL_ANCHOR: fprintf(out, " "); break; case _URE_EOL_ANCHOR: fprintf(out, " "); break; case _URE_CCLASS: case _URE_NCCLASS: fprintf(out, "[C%hd] ", sym->id); break; } fprintf(out, "S%hd", sp->trans[j].next_state); if (j + 1 < sp->ntrans) putc(' ', out); } putc('\n', out); } } #define _ure_issep(cc) ((cc) == '\n' || (cc) == '\r' || (cc) == 0x2028 ||\ (cc) == 0x2029) int ure_exec(ure_dfa_t dfa, int flags, ucs2_t *text, unsigned long textlen, unsigned long *match_start, unsigned long *match_end) { int i, j, matched, found, skip; unsigned long ms, me; ucs4_t c; ucs2_t *sp, *ep, *lp; _ure_dstate_t *stp; _ure_symtab_t *sym; _ure_range_t *rp; if (dfa == 0 || text == 0) return 0; /* * Handle the special case of an empty string matching the "^$" pattern. */ if (textlen == 0 && (dfa->flags & _URE_DFA_BLANKLINE)) { *match_start = *match_end = 0; return 1; } sp = text; ep = sp + textlen; ms = me = ~0; stp = dfa->states; for (found = skip = 0; found == 0 && sp < ep; ) { lp = sp; c = *sp++; /* * Check to see if this is a high surrogate that should be * combined with a following low surrogate. */ if (sp < ep && 0xd800 <= c && c <= 0xdbff && 0xdc00 <= *sp && *sp <= 0xdfff) c = 0x10000 + (((c & 0x03ff) << 10) | (*sp++ & 0x03ff)); /* * Determine if the character is non-spacing and should be skipped. */ if (_ure_matches_properties(_URE_NONSPACING, c) && (flags & URE_IGNORE_NONSPACING)) { sp++; continue; } if (dfa->flags & _URE_DFA_CASEFOLD) c = _ure_tolower(c); /* * See if one of the transitions matches. */ for (i = 0, matched = 0; matched == 0 && i < stp->ntrans; i++) { sym = dfa->syms + stp->trans[i].symbol; switch (sym->type) { case _URE_ANY_CHAR: if ((flags & URE_DOT_MATCHES_SEPARATORS) || !_ure_issep(c)) matched = 1; break; case _URE_CHAR: if (c == sym->sym.chr) matched = 1; break; case _URE_BOL_ANCHOR: if (lp == text) { sp = lp; matched = 1; } else if (_ure_issep(c)) { if (c == '\r' && sp < ep && *sp == '\n') sp++; lp = sp; matched = 1; } break; case _URE_EOL_ANCHOR: if (_ure_issep(c)) { /* * Put the pointer back before the separator so the match * end position will be correct. This case will also * cause the `sp' pointer to be advanced over the current * separator once the match end point has been recorded. */ sp = lp; matched = 1; } break; case _URE_CCLASS: case _URE_NCCLASS: if (sym->props != 0) matched = _ure_matches_properties(sym->props, c); for (j = 0, rp = sym->sym.ccl.ranges; j < sym->sym.ccl.ranges_used; j++, rp++) { if (rp->min_code <= c && c <= rp->max_code) matched = 1; } if (sym->type == _URE_NCCLASS) matched = !matched; break; } if (matched) { if (ms == ~0UL) ms = lp - text; else me = sp - text; stp = dfa->states + stp->trans[i].next_state; /* * If the match was an EOL anchor, adjust the pointer past the * separator that caused the match. The correct match * position has been recorded already. */ if (sym->type == _URE_EOL_ANCHOR) { /* * Skip the character that caused the match. */ sp++; /* * Handle the infamous CRLF situation. */ if (sp < ep && c == '\r' && *sp == '\n') sp++; } } } if (matched == 0) { if (stp->accepting == 0) { /* * If the last state was not accepting, then reset * and start over. */ stp = dfa->states; ms = me = ~0; } else /* * The last state was accepting, so terminate the matching * loop to avoid more work. */ found = 1; } else if (sp == ep) { if (!stp->accepting) { /* * This ugly hack is to make sure the end-of-line anchors * match when the source text hits the end. This is only done * if the last subexpression matches. */ for (i = 0; found == 0 && i < stp->ntrans; i++) { sym = dfa->syms + stp->trans[i].symbol; if (sym->type ==_URE_EOL_ANCHOR) { stp = dfa->states + stp->trans[i].next_state; if (stp->accepting) { me = sp - text; found = 1; } else break; } } } else { /* * Make sure any conditions that match all the way to the end * of the string match. */ found = 1; me = sp - text; } } } if (found == 0) ms = me = ~0; *match_start = ms; *match_end = me; return (ms != ~0UL) ? 1 : 0; } openldap-2.4.42+dfsg/libraries/liblunicode/ure/urestubs.c0000644000175000017500000000750712563404150022121 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* * Copyright 1997, 1998, 1999 Computing Research Labs, * New Mexico State University * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* $Id: urestubs.c,v 1.2 1999/09/21 15:47:44 mleisher Exp $" */ #include "portable.h" #include #include "ure.h" #ifdef _MSC_VER # include "../ucdata/ucdata.h" #else # include "ucdata.h" #endif /* * This file contains stub routines needed by the URE package to test * character properties and other Unicode implementation specific details. */ /* * This routine should return the lower case equivalent for the character or, * if there is no lower case quivalent, the character itself. */ ucs4_t _ure_tolower(ucs4_t c) { return uctoupper(c); } static struct ucmaskmap { unsigned long mask1; unsigned long mask2; } masks[32] = { { UC_MN, 0 }, /* _URE_NONSPACING */ { UC_MC, 0 }, /* _URE_COMBINING */ { UC_ND, 0 }, /* _URE_NUMDIGIT */ { UC_NL|UC_NO, 0 }, /* _URE_NUMOTHER */ { UC_ZS, 0 }, /* _URE_SPACESEP */ { UC_ZL, 0 }, /* _URE_LINESEP */ { UC_ZP, 0 }, /* _URE_PARASEP */ { UC_CC, 0 }, /* _URE_CNTRL */ { UC_CO, 0 }, /* _URE_PUA */ { UC_LU, 0 }, /* _URE_UPPER */ { UC_LL, 0 }, /* _URE_LOWER */ { UC_LT, 0 }, /* _URE_TITLE */ { UC_LM, 0 }, /* _URE_MODIFIER */ { UC_LO, 0 }, /* _URE_OTHERLETTER */ { UC_PD, 0 }, /* _URE_DASHPUNCT */ { UC_PS, 0 }, /* _URE_OPENPUNCT */ { UC_PC, 0 }, /* _URE_CLOSEPUNCT */ { UC_PO, 0 }, /* _URE_OTHERPUNCT */ { UC_SM, 0 }, /* _URE_MATHSYM */ { UC_SC, 0 }, /* _URE_CURRENCYSYM */ { UC_SO, 0 }, /* _URE_OTHERSYM */ { UC_L, 0 }, /* _URE_LTR */ { UC_R, 0 }, /* _URE_RTL */ { 0, UC_EN }, /* _URE_EURONUM */ { 0, UC_ES }, /* _URE_EURONUMSEP */ { 0, UC_ET }, /* _URE_EURONUMTERM */ { 0, UC_AN }, /* _URE_ARABNUM */ { 0, UC_CS }, /* _URE_COMMONSEP */ { 0, UC_B }, /* _URE_BLOCKSEP */ { 0, UC_S }, /* _URE_SEGMENTSEP */ { 0, UC_WS }, /* _URE_WHITESPACE */ { 0, UC_ON } /* _URE_OTHERNEUT */ }; /* * This routine takes a set of URE character property flags (see ure.h) along * with a character and tests to see if the character has one or more of those * properties. */ int _ure_matches_properties(unsigned long props, ucs4_t c) { int i; unsigned long mask1=0, mask2=0; for( i=0; i<32; i++ ) { if( props & (1 << i) ) { mask1 |= masks[i].mask1; mask2 |= masks[i].mask2; } } return ucisprop( c, mask1, mask2 ); } openldap-2.4.42+dfsg/libraries/liblunicode/ure/ure.h0000644000175000017500000001133312563404150021035 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Copyright 1997, 1998, 1999 Computing Research Labs, * New Mexico State University * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* $Id: ure.h,v 1.2 1999/09/21 15:47:44 mleisher Exp $ */ #ifndef _h_ure #define _h_ure #include "portable.h" #include LDAP_BEGIN_DECL /* * Set of character class flags. */ #define _URE_NONSPACING 0x00000001 #define _URE_COMBINING 0x00000002 #define _URE_NUMDIGIT 0x00000004 #define _URE_NUMOTHER 0x00000008 #define _URE_SPACESEP 0x00000010 #define _URE_LINESEP 0x00000020 #define _URE_PARASEP 0x00000040 #define _URE_CNTRL 0x00000080 #define _URE_PUA 0x00000100 #define _URE_UPPER 0x00000200 #define _URE_LOWER 0x00000400 #define _URE_TITLE 0x00000800 #define _URE_MODIFIER 0x00001000 #define _URE_OTHERLETTER 0x00002000 #define _URE_DASHPUNCT 0x00004000 #define _URE_OPENPUNCT 0x00008000 #define _URE_CLOSEPUNCT 0x00010000 #define _URE_OTHERPUNCT 0x00020000 #define _URE_MATHSYM 0x00040000 #define _URE_CURRENCYSYM 0x00080000 #define _URE_OTHERSYM 0x00100000 #define _URE_LTR 0x00200000 #define _URE_RTL 0x00400000 #define _URE_EURONUM 0x00800000 #define _URE_EURONUMSEP 0x01000000 #define _URE_EURONUMTERM 0x02000000 #define _URE_ARABNUM 0x04000000 #define _URE_COMMONSEP 0x08000000 #define _URE_BLOCKSEP 0x10000000 #define _URE_SEGMENTSEP 0x20000000 #define _URE_WHITESPACE 0x40000000 #define _URE_OTHERNEUT 0x80000000 /* * Error codes. */ #define _URE_OK 0 #define _URE_UNEXPECTED_EOS -1 #define _URE_CCLASS_OPEN -2 #define _URE_UNBALANCED_GROUP -3 #define _URE_INVALID_PROPERTY -4 /* * Options that can be combined for searching. */ #define URE_IGNORE_NONSPACING 0x01 #define URE_DOT_MATCHES_SEPARATORS 0x02 typedef unsigned long ucs4_t; typedef unsigned short ucs2_t; /* * Opaque type for memory used when compiling expressions. */ typedef struct _ure_buffer_t *ure_buffer_t; /* * Opaque type for the minimal DFA used when matching. */ typedef struct _ure_dfa_t *ure_dfa_t; /************************************************************************* * * API. * *************************************************************************/ LDAP_LUNICODE_F (ure_buffer_t) ure_buffer_create LDAP_P((void)); LDAP_LUNICODE_F (void) ure_buffer_free LDAP_P((ure_buffer_t buf)); LDAP_LUNICODE_F (ure_dfa_t) ure_compile LDAP_P((ucs2_t *re, unsigned long relen, int casefold, ure_buffer_t buf)); LDAP_LUNICODE_F (void) ure_dfa_free LDAP_P((ure_dfa_t dfa)); LDAP_LUNICODE_F (void) ure_write_dfa LDAP_P((ure_dfa_t dfa, FILE *out)); LDAP_LUNICODE_F (int) ure_exec LDAP_P((ure_dfa_t dfa, int flags, ucs2_t *text, unsigned long textlen, unsigned long *match_start, unsigned long *match_end)); /************************************************************************* * * Prototypes for stub functions used for URE. These need to be rewritten to * use the Unicode support available on the system. * *************************************************************************/ LDAP_LUNICODE_F (ucs4_t) _ure_tolower LDAP_P((ucs4_t c)); LDAP_LUNICODE_F (int) _ure_matches_properties LDAP_P((unsigned long props, ucs4_t c)); LDAP_END_DECL #endif /* _h_ure */ openldap-2.4.42+dfsg/libraries/liblunicode/CompositionExclusions.txt0000644000175000017500000001644112563404150024424 0ustar ryanryan# CompositionExclusions-3.2.0.txt # Date: 2002-03-19,23:30:28 GMT [MD] # # This file lists the characters from the UAX #15 Composition Exclusion Table. # # The format of the comments in this file has been updated since the last version, # CompositionExclusions-3.txt. The only substantive change to this file between that # version and this one is the addition of U+2ADC FORKING. # # For more information, see # http://www.unicode.org/unicode/reports/tr15/#Primary Exclusion List Table # ================================================ # (1) Script Specifics # This list of characters cannot be derived from the UnicodeData file. # ================================================ 0958 # DEVANAGARI LETTER QA 0959 # DEVANAGARI LETTER KHHA 095A # DEVANAGARI LETTER GHHA 095B # DEVANAGARI LETTER ZA 095C # DEVANAGARI LETTER DDDHA 095D # DEVANAGARI LETTER RHA 095E # DEVANAGARI LETTER FA 095F # DEVANAGARI LETTER YYA 09DC # BENGALI LETTER RRA 09DD # BENGALI LETTER RHA 09DF # BENGALI LETTER YYA 0A33 # GURMUKHI LETTER LLA 0A36 # GURMUKHI LETTER SHA 0A59 # GURMUKHI LETTER KHHA 0A5A # GURMUKHI LETTER GHHA 0A5B # GURMUKHI LETTER ZA 0A5E # GURMUKHI LETTER FA 0B5C # ORIYA LETTER RRA 0B5D # ORIYA LETTER RHA 0F43 # TIBETAN LETTER GHA 0F4D # TIBETAN LETTER DDHA 0F52 # TIBETAN LETTER DHA 0F57 # TIBETAN LETTER BHA 0F5C # TIBETAN LETTER DZHA 0F69 # TIBETAN LETTER KSSA 0F76 # TIBETAN VOWEL SIGN VOCALIC R 0F78 # TIBETAN VOWEL SIGN VOCALIC L 0F93 # TIBETAN SUBJOINED LETTER GHA 0F9D # TIBETAN SUBJOINED LETTER DDHA 0FA2 # TIBETAN SUBJOINED LETTER DHA 0FA7 # TIBETAN SUBJOINED LETTER BHA 0FAC # TIBETAN SUBJOINED LETTER DZHA 0FB9 # TIBETAN SUBJOINED LETTER KSSA FB1D # HEBREW LETTER YOD WITH HIRIQ FB1F # HEBREW LIGATURE YIDDISH YOD YOD PATAH FB2A # HEBREW LETTER SHIN WITH SHIN DOT FB2B # HEBREW LETTER SHIN WITH SIN DOT FB2C # HEBREW LETTER SHIN WITH DAGESH AND SHIN DOT FB2D # HEBREW LETTER SHIN WITH DAGESH AND SIN DOT FB2E # HEBREW LETTER ALEF WITH PATAH FB2F # HEBREW LETTER ALEF WITH QAMATS FB30 # HEBREW LETTER ALEF WITH MAPIQ FB31 # HEBREW LETTER BET WITH DAGESH FB32 # HEBREW LETTER GIMEL WITH DAGESH FB33 # HEBREW LETTER DALET WITH DAGESH FB34 # HEBREW LETTER HE WITH MAPIQ FB35 # HEBREW LETTER VAV WITH DAGESH FB36 # HEBREW LETTER ZAYIN WITH DAGESH FB38 # HEBREW LETTER TET WITH DAGESH FB39 # HEBREW LETTER YOD WITH DAGESH FB3A # HEBREW LETTER FINAL KAF WITH DAGESH FB3B # HEBREW LETTER KAF WITH DAGESH FB3C # HEBREW LETTER LAMED WITH DAGESH FB3E # HEBREW LETTER MEM WITH DAGESH FB40 # HEBREW LETTER NUN WITH DAGESH FB41 # HEBREW LETTER SAMEKH WITH DAGESH FB43 # HEBREW LETTER FINAL PE WITH DAGESH FB44 # HEBREW LETTER PE WITH DAGESH FB46 # HEBREW LETTER TSADI WITH DAGESH FB47 # HEBREW LETTER QOF WITH DAGESH FB48 # HEBREW LETTER RESH WITH DAGESH FB49 # HEBREW LETTER SHIN WITH DAGESH FB4A # HEBREW LETTER TAV WITH DAGESH FB4B # HEBREW LETTER VAV WITH HOLAM FB4C # HEBREW LETTER BET WITH RAFE FB4D # HEBREW LETTER KAF WITH RAFE FB4E # HEBREW LETTER PE WITH RAFE # Total code points: 67 # ================================================ # (2) Post Composition Version precomposed characters # These characters cannot be derived solely from the UnicodeData.txt file # in this version of Unicode. # ================================================ 2ADC # FORKING 1D15E # MUSICAL SYMBOL HALF NOTE 1D15F # MUSICAL SYMBOL QUARTER NOTE 1D160 # MUSICAL SYMBOL EIGHTH NOTE 1D161 # MUSICAL SYMBOL SIXTEENTH NOTE 1D162 # MUSICAL SYMBOL THIRTY-SECOND NOTE 1D163 # MUSICAL SYMBOL SIXTY-FOURTH NOTE 1D164 # MUSICAL SYMBOL ONE HUNDRED TWENTY-EIGHTH NOTE 1D1BB # MUSICAL SYMBOL MINIMA 1D1BC # MUSICAL SYMBOL MINIMA BLACK 1D1BD # MUSICAL SYMBOL SEMIMINIMA WHITE 1D1BE # MUSICAL SYMBOL SEMIMINIMA BLACK 1D1BF # MUSICAL SYMBOL FUSA WHITE 1D1C0 # MUSICAL SYMBOL FUSA BLACK # Total code points: 14 # ================================================ # (3) Singleton Decompositions # These characters can be derived from the UnicodeData file # by including all characters whose canonical decomposition # consists of a single character. # These characters are simply quoted here for reference. # ================================================ # 0340..0341 [2] COMBINING GRAVE TONE MARK..COMBINING ACUTE TONE MARK # 0343 COMBINING GREEK KORONIS # 0374 GREEK NUMERAL SIGN # 037E GREEK QUESTION MARK # 0387 GREEK ANO TELEIA # 1F71 GREEK SMALL LETTER ALPHA WITH OXIA # 1F73 GREEK SMALL LETTER EPSILON WITH OXIA # 1F75 GREEK SMALL LETTER ETA WITH OXIA # 1F77 GREEK SMALL LETTER IOTA WITH OXIA # 1F79 GREEK SMALL LETTER OMICRON WITH OXIA # 1F7B GREEK SMALL LETTER UPSILON WITH OXIA # 1F7D GREEK SMALL LETTER OMEGA WITH OXIA # 1FBB GREEK CAPITAL LETTER ALPHA WITH OXIA # 1FBE GREEK PROSGEGRAMMENI # 1FC9 GREEK CAPITAL LETTER EPSILON WITH OXIA # 1FCB GREEK CAPITAL LETTER ETA WITH OXIA # 1FD3 GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA # 1FDB GREEK CAPITAL LETTER IOTA WITH OXIA # 1FE3 GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND OXIA # 1FEB GREEK CAPITAL LETTER UPSILON WITH OXIA # 1FEE..1FEF [2] GREEK DIALYTIKA AND OXIA..GREEK VARIA # 1FF9 GREEK CAPITAL LETTER OMICRON WITH OXIA # 1FFB GREEK CAPITAL LETTER OMEGA WITH OXIA # 1FFD GREEK OXIA # 2000..2001 [2] EN QUAD..EM QUAD # 2126 OHM SIGN # 212A..212B [2] KELVIN SIGN..ANGSTROM SIGN # 2329 LEFT-POINTING ANGLE BRACKET # 232A RIGHT-POINTING ANGLE BRACKET # F900..FA0D [270] CJK COMPATIBILITY IDEOGRAPH-F900..CJK COMPATIBILITY IDEOGRAPH-FA0D # FA10 CJK COMPATIBILITY IDEOGRAPH-FA10 # FA12 CJK COMPATIBILITY IDEOGRAPH-FA12 # FA15..FA1E [10] CJK COMPATIBILITY IDEOGRAPH-FA15..CJK COMPATIBILITY IDEOGRAPH-FA1E # FA20 CJK COMPATIBILITY IDEOGRAPH-FA20 # FA22 CJK COMPATIBILITY IDEOGRAPH-FA22 # FA25..FA26 [2] CJK COMPATIBILITY IDEOGRAPH-FA25..CJK COMPATIBILITY IDEOGRAPH-FA26 # FA2A..FA2D [4] CJK COMPATIBILITY IDEOGRAPH-FA2A..CJK COMPATIBILITY IDEOGRAPH-FA2D # FA30..FA6A [59] CJK COMPATIBILITY IDEOGRAPH-FA30..CJK COMPATIBILITY IDEOGRAPH-FA6A # 2F800..2FA1D [542] CJK COMPATIBILITY IDEOGRAPH-2F800..CJK COMPATIBILITY IDEOGRAPH-2FA1D # Total code points: 924 # ================================================ # (4) Non-Starter Decompositions # These characters can be derived from the UnicodeData file # by including all characters whose canonical decomposition consists # of a sequence of characters, the first of which has a non-zero # combining class. # These characters are simply quoted here for reference. # ================================================ # 0344 COMBINING GREEK DIALYTIKA TONOS # 0F73 TIBETAN VOWEL SIGN II # 0F75 TIBETAN VOWEL SIGN UU # 0F81 TIBETAN VOWEL SIGN REVERSED II # Total code points: 4 openldap-2.4.42+dfsg/libraries/liblunicode/ucdata/0000755000175000017500000000000012563404150020536 5ustar ryanryanopenldap-2.4.42+dfsg/libraries/liblunicode/ucdata/README0000644000175000017500000002477612563404150021436 0ustar ryanryan# # $Id: README,v 1.33 2001/01/02 18:46:19 mleisher Exp $ # MUTT UCData Package 2.5 ----------------------- This is a package that supports ctype-like operations for Unicode UCS-2 text (and surrogates), case mapping, decomposition lookup, and provides a bidirectional reordering algorithm. To use it, you will need to get the latest "UnicodeData-*.txt" (or later) file from the Unicode Web or FTP site. The character information portion of the package consists of three parts: 1. A program called "ucgendat" which generates five data files from the UnicodeData-*.txt file. The files are: A. case.dat - the case mappings. B. ctype.dat - the character property tables. C. comp.dat - the character composition pairs. D. decomp.dat - the character decompositions. E. cmbcl.dat - the non-zero combining classes. F. num.dat - the codes representing numbers. 2. The "ucdata.[ch]" files which implement the functions needed to check to see if a character matches groups of properties, to map between upper, lower, and title case, to look up the decomposition of a character, look up the combining class of a character, and get the number value of a character. 3. The UCData.java class which provides the same API (with minor changes for the numbers) and loads the same binary data files as the C code. A short reference to the functions available is in the "api.txt" file. Techie Details ============== The "ucgendat" program parses files from the command line which are all in the Unicode Character Database (UCDB) format. An additional properties file, "MUTTUCData.txt", provides some extra properties for some characters. The program looks for the two character properties fields (2 and 4), the combining class field (3), the decomposition field (5), the numeric value field (8), and the case mapping fields (12, 13, and 14). The decompositions are recursively expanded before being written out. The decomposition table contains all the canonical decompositions. This means all decompositions that do not have tags such as "" or "". The data is almost all stored as unsigned longs (32-bits assumed) and the routines that load the data take care of endian swaps when necessary. This also means that supplementary characters (>= 0x10000) can be placed in the data files the "ucgendat" program parses. The data is written as external files and broken into six parts so it can be selectively updated at runtime if necessary. The data files currently generated from the "ucgendat" program total about 56K in size all together. The format of the binary data files is documented in the "format.txt" file. ========================================================================== The "Pretty Good Bidi Algorithm" -------------------------------- This routine provides an alternative to the Unicode Bidi algorithm. The difference is that this version of the PGBA does not handle the explicit directional codes (LRE, RLE, LRO, RLO, PDF). It should now produce the same results as the Unicode BiDi algorithm for implicit reordering. Included are functions for doing cursor motion in both logical and visual order. This implementation is provided to demonstrate an effective alternate method for implicit reordering. To make this useful for an application, it probably needs some changes to the memory allocation and deallocation, as well as data structure additions for rendering. Mark Leisher 19 November 1999 ----------------------------------------------------------------------------- CHANGES ======= Version 2.5 ----------- 1. Changed the number lookup to set the denominator to 1 in cases of digits. This restores functional compatibility with John Cowan's UCType package. 2. Added support for the AL property. 3. Modified load and reload functions to return error codes. Version 2.4 ----------- 1. Improved some bidi algorithm documentation in the code. 2. Fixed a code mixup that produced a non-working version. Version 2.3 ----------- 1. Fixed a misspelling in the ucpgba.h header file. 2. Fixed a bug which caused trailing weak non-digit sequences to be left out of the reordered string in the bidi algorithm. 3. Fixed a problem with weak sequences containing non-spacing marks in the bidi algorithm. 4. Fixed a problem with text runs of the opposite direction of the string surrounding a weak + neutral text run appearing in the wrong order in the bidi algorithm. 5. Added a default overall direction parameter to the reordering function for cases of strings with no strong directional characters in the bidi algorithm. 6. The bidi API documentation was improved. 7. Added a man page for the bidi API. Version 2.2 ----------- 1. Fixed a problem with the bidi algorithm locating directional section boundaries. 2. Fixed a problem with the bidi algorithm starting the reordering correctly. 3. Fixed a problem with the bidi algorithm determining end boundaries for LTR segments. 4. Fixed a problem with the bidi algorithm reordering weak (digits and number separators) segments. 5. Added automatic switching of symmetrically paired characters when reversing RTL segments. 6. Added a missing symmetric character to the extra character properties in MUTTUCData.txt. 7. Added support for doing logical and visual cursor traversal. Version 2.1 ----------- 1. Updated the ucgendat program to handle the Unicode 3.0 character database properties. The AL and BM bidi properties gets marked as strong RTL and Other Neutral, the NSM, LRE, RLE, PDF, LRO, and RLO controls all get marked as Other Neutral. 2. Fixed some problems with testing against signed values in the UCData.java code and some minor cleanup. 3. Added the "Pretty Good Bidi Algorithm." Version 2.0 ----------- 1. Removed the old Java stuff for a new class that loads directly from the same data files as the C code does. 2. Fixed a problem with choosing the correct field when mapping case. 3. Adjust some search routines to start their search in the correct position. 4. Moved the copyright year to 1999. Version 1.9 ----------- 1. Fixed a problem with an incorrect amount of storage being allocated for the combining class nodes. 2. Fixed an invalid initialization in the number code. 3. Changed the Java template file formatting a bit. 4. Added tables and function for getting decompositions in the Java class. Version 1.8 ----------- 1. Fixed a problem with adding certain ranges. 2. Added two more macros for testing for identifiers. 3. Tested with the UnicodeData-2.1.5.txt file. Version 1.7 ----------- 1. Fixed a problem with looking up decompositions in "ucgendat." Version 1.6 ----------- 1. Added two new properties introduced with UnicodeData-2.1.4.txt. 2. Changed the "ucgendat.c" program a little to automatically align the property data on a 4-byte boundary when new properties are added. 3. Changed the "ucgendat.c" programs to only generate canonical decompositions. 4. Added two new macros ucisinitialpunct() and ucisfinalpunct() to check for initial and final punctuation characters. 5. Minor additions and changes to the documentation. Version 1.5 ----------- 1. Changed all file open calls to include binary mode with "b" for DOS/WIN platforms. 2. Wrapped the unistd.h include so it won't be included when compiled under Win32. 3. Fixed a bad range check for hex digits in ucgendat.c. 4. Fixed a bad endian swap for combining classes. 5. Added code to make a number table and associated lookup functions. Functions added are ucnumber(), ucdigit(), and ucgetnumber(). The last function is to maintain compatibility with John Cowan's "uctype" package. Version 1.4 ----------- 1. Fixed a bug with adding a range. 2. Fixed a bug with inserting a range in order. 3. Fixed incorrectly specified ucisdefined() and ucisundefined() macros. 4. Added the missing unload for the combining class data. 5. Fixed a bad macro placement in ucisweak(). Version 1.3 ----------- 1. Bug with case mapping calculations fixed. 2. Bug with empty character property entries fixed. 3. Bug with incorrect type in the combining class lookup fixed. 4. Some corrections done to api.txt. 5. Bug in certain character property lookups fixed. 6. Added a character property table that records the defined characters. 7. Replaced ucisunknown() with ucisdefined() and ucisundefined(). Version 1.2 ----------- 1. Added code to ucgendat to generate a combining class table. 2. Fixed an endian problem with the byte count of decompositions. 3. Fixed some minor problems in the "format.txt" file. 4. Removed some bogus "Ss" values from MUTTUCData.txt file. 5. Added API function to get combining class. 6. Changed the open mode to "rb" so binary data files will be opened correctly on DOS/WIN as well as other platforms. 7. Added the "api.txt" file. Version 1.1 ----------- 1. Added ucisxdigit() which I overlooked. 2. Added UC_LT to the ucisalpha() macro which I overlooked. 3. Change uciscntrl() to include UC_CF. 4. Added ucisocntrl() and ucfntcntrl() macros. 5. Added a ucisblank() which I overlooked. 6. Added missing properties to ucissymbol() and ucisnumber(). 7. Added ucisgraph() and ucisprint(). 8. Changed the "Mr" property to "Sy" to mark this subset of mirroring characters as symmetric to avoid trampling the Unicode/ISO10646 sense of mirroring. 9. Added another property called "Ss" which includes control characters traditionally seen as spaces in the isspace() macro. 10. Added a bunch of macros to be API compatible with John Cowan's package. ACKNOWLEDGEMENTS ================ Thanks go to John Cowan for pointing out lots of missing things and giving me stuff, particularly a bunch of new macros. Thanks go to Bob Verbrugge for pointing out various bugs. Thanks go to Christophe Pierret for pointing out that file modes need to have "b" for DOS/WIN machines, pointing out unistd.h is not a Win 32 header, and pointing out a problem with ucisalnum(). Thanks go to Kent Johnson for finding a bug that caused incomplete decompositions to be generated by the "ucgendat" program. Thanks go to Valeriy E. Ushakov for spotting an allocation error and an initialization error. Thanks go to Stig Venaas for providing a patch to support return types on load and reload, and for major updates to handle canonical composition and decomposition. openldap-2.4.42+dfsg/libraries/liblunicode/ucdata/ucgendat.c0000644000175000017500000014061312563404150022501 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Copyright 2001 Computing Research Labs, New Mexico State University * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* $Id: ucgendat.c,v 1.4 2001/01/02 18:46:20 mleisher Exp $" */ #include "portable.h" #include "ldap_config.h" #include #include #include #include #include #include #include #ifndef HARDCODE_DATA #define HARDCODE_DATA 1 #endif #undef ishdigit #define ishdigit(cc) (((cc) >= '0' && (cc) <= '9') ||\ ((cc) >= 'A' && (cc) <= 'F') ||\ ((cc) >= 'a' && (cc) <= 'f')) /* * A header written to the output file with the byte-order-mark and the number * of property nodes. */ static ac_uint2 hdr[2] = {0xfeff, 0}; #define NUMPROPS 50 #define NEEDPROPS (NUMPROPS + (4 - (NUMPROPS & 3))) typedef struct { char *name; int len; } _prop_t; /* * List of properties expected to be found in the Unicode Character Database * including some implementation specific properties. * * The implementation specific properties are: * Cm = Composed (can be decomposed) * Nb = Non-breaking * Sy = Symmetric (has left and right forms) * Hd = Hex digit * Qm = Quote marks * Mr = Mirroring * Ss = Space, other * Cp = Defined character */ static _prop_t props[NUMPROPS] = { {"Mn", 2}, {"Mc", 2}, {"Me", 2}, {"Nd", 2}, {"Nl", 2}, {"No", 2}, {"Zs", 2}, {"Zl", 2}, {"Zp", 2}, {"Cc", 2}, {"Cf", 2}, {"Cs", 2}, {"Co", 2}, {"Cn", 2}, {"Lu", 2}, {"Ll", 2}, {"Lt", 2}, {"Lm", 2}, {"Lo", 2}, {"Pc", 2}, {"Pd", 2}, {"Ps", 2}, {"Pe", 2}, {"Po", 2}, {"Sm", 2}, {"Sc", 2}, {"Sk", 2}, {"So", 2}, {"L", 1}, {"R", 1}, {"EN", 2}, {"ES", 2}, {"ET", 2}, {"AN", 2}, {"CS", 2}, {"B", 1}, {"S", 1}, {"WS", 2}, {"ON", 2}, {"Cm", 2}, {"Nb", 2}, {"Sy", 2}, {"Hd", 2}, {"Qm", 2}, {"Mr", 2}, {"Ss", 2}, {"Cp", 2}, {"Pi", 2}, {"Pf", 2}, {"AL", 2} }; typedef struct { ac_uint4 *ranges; ac_uint2 used; ac_uint2 size; } _ranges_t; static _ranges_t proptbl[NUMPROPS]; /* * Make sure this array is sized to be on a 4-byte boundary at compile time. */ static ac_uint2 propcnt[NEEDPROPS]; /* * Array used to collect a decomposition before adding it to the decomposition * table. */ static ac_uint4 dectmp[64]; static ac_uint4 dectmp_size; typedef struct { ac_uint4 code; ac_uint2 size; ac_uint2 used; ac_uint4 *decomp; } _decomp_t; /* * List of decomposition. Created and expanded in order as the characters are * encountered. First list contains canonical mappings, second also includes * compatibility mappings. */ static _decomp_t *decomps; static ac_uint4 decomps_used; static ac_uint4 decomps_size; static _decomp_t *kdecomps; static ac_uint4 kdecomps_used; static ac_uint4 kdecomps_size; /* * Composition exclusion table stuff. */ #define COMPEX_SET(c) (compexs[(c) >> 5] |= (1 << ((c) & 31))) #define COMPEX_TEST(c) (compexs[(c) >> 5] & (1 << ((c) & 31))) static ac_uint4 compexs[8192]; /* * Struct for holding a composition pair, and array of composition pairs */ typedef struct { ac_uint4 comp; ac_uint4 count; ac_uint4 code1; ac_uint4 code2; } _comp_t; static _comp_t *comps; static ac_uint4 comps_used; /* * Types and lists for handling lists of case mappings. */ typedef struct { ac_uint4 key; ac_uint4 other1; ac_uint4 other2; } _case_t; static _case_t *upper; static _case_t *lower; static _case_t *title; static ac_uint4 upper_used; static ac_uint4 upper_size; static ac_uint4 lower_used; static ac_uint4 lower_size; static ac_uint4 title_used; static ac_uint4 title_size; /* * Array used to collect case mappings before adding them to a list. */ static ac_uint4 cases[3]; /* * An array to hold ranges for combining classes. */ static ac_uint4 *ccl; static ac_uint4 ccl_used; static ac_uint4 ccl_size; /* * Structures for handling numbers. */ typedef struct { ac_uint4 code; ac_uint4 idx; } _codeidx_t; typedef struct { short numerator; short denominator; } _num_t; /* * Arrays to hold the mapping of codes to numbers. */ static _codeidx_t *ncodes; static ac_uint4 ncodes_used; static ac_uint4 ncodes_size; static _num_t *nums; static ac_uint4 nums_used; static ac_uint4 nums_size; /* * Array for holding numbers. */ static _num_t *nums; static ac_uint4 nums_used; static ac_uint4 nums_size; static void add_range(ac_uint4 start, ac_uint4 end, char *p1, char *p2) { int i, j, k, len; _ranges_t *rlp; char *name; for (k = 0; k < 2; k++) { if (k == 0) { name = p1; len = 2; } else { if (p2 == 0) break; name = p2; len = 1; } for (i = 0; i < NUMPROPS; i++) { if (props[i].len == len && memcmp(props[i].name, name, len) == 0) break; } if (i == NUMPROPS) continue; rlp = &proptbl[i]; /* * Resize the range list if necessary. */ if (rlp->used == rlp->size) { if (rlp->size == 0) rlp->ranges = (ac_uint4 *) malloc(sizeof(ac_uint4) << 3); else rlp->ranges = (ac_uint4 *) realloc((char *) rlp->ranges, sizeof(ac_uint4) * (rlp->size + 8)); rlp->size += 8; } /* * If this is the first code for this property list, just add it * and return. */ if (rlp->used == 0) { rlp->ranges[0] = start; rlp->ranges[1] = end; rlp->used += 2; continue; } /* * Optimize the case of adding the range to the end. */ j = rlp->used - 1; if (start > rlp->ranges[j]) { j = rlp->used; rlp->ranges[j++] = start; rlp->ranges[j++] = end; rlp->used = j; continue; } /* * Need to locate the insertion point. */ for (i = 0; i < rlp->used && start > rlp->ranges[i + 1] + 1; i += 2) ; /* * If the start value lies in the current range, then simply set the * new end point of the range to the end value passed as a parameter. */ if (rlp->ranges[i] <= start && start <= rlp->ranges[i + 1] + 1) { rlp->ranges[i + 1] = end; return; } /* * Shift following values up by two. */ for (j = rlp->used; j > i; j -= 2) { rlp->ranges[j] = rlp->ranges[j - 2]; rlp->ranges[j + 1] = rlp->ranges[j - 1]; } /* * Add the new range at the insertion point. */ rlp->ranges[i] = start; rlp->ranges[i + 1] = end; rlp->used += 2; } } static void ordered_range_insert(ac_uint4 c, char *name, int len) { int i, j; ac_uint4 s, e; _ranges_t *rlp; if (len == 0) return; /* * Deal with directionality codes introduced in Unicode 3.0. */ if ((len == 2 && memcmp(name, "BN", 2) == 0) || (len == 3 && (memcmp(name, "NSM", 3) == 0 || memcmp(name, "PDF", 3) == 0 || memcmp(name, "LRE", 3) == 0 || memcmp(name, "LRO", 3) == 0 || memcmp(name, "RLE", 3) == 0 || memcmp(name, "RLO", 3) == 0))) { /* * Mark all of these as Other Neutral to preserve compatibility with * older versions. */ len = 2; name = "ON"; } for (i = 0; i < NUMPROPS; i++) { if (props[i].len == len && memcmp(props[i].name, name, len) == 0) break; } if (i == NUMPROPS) return; /* * Have a match, so insert the code in order. */ rlp = &proptbl[i]; /* * Resize the range list if necessary. */ if (rlp->used == rlp->size) { if (rlp->size == 0) rlp->ranges = (ac_uint4 *) malloc(sizeof(ac_uint4) << 3); else rlp->ranges = (ac_uint4 *) realloc((char *) rlp->ranges, sizeof(ac_uint4) * (rlp->size + 8)); rlp->size += 8; } /* * If this is the first code for this property list, just add it * and return. */ if (rlp->used == 0) { rlp->ranges[0] = rlp->ranges[1] = c; rlp->used += 2; return; } /* * Optimize the cases of extending the last range and adding new ranges to * the end. */ j = rlp->used - 1; e = rlp->ranges[j]; s = rlp->ranges[j - 1]; if (c == e + 1) { /* * Extend the last range. */ rlp->ranges[j] = c; return; } if (c > e + 1) { /* * Start another range on the end. */ j = rlp->used; rlp->ranges[j] = rlp->ranges[j + 1] = c; rlp->used += 2; return; } if (c >= s) /* * The code is a duplicate of a code in the last range, so just return. */ return; /* * The code should be inserted somewhere before the last range in the * list. Locate the insertion point. */ for (i = 0; i < rlp->used && c > rlp->ranges[i + 1] + 1; i += 2) ; s = rlp->ranges[i]; e = rlp->ranges[i + 1]; if (c == e + 1) /* * Simply extend the current range. */ rlp->ranges[i + 1] = c; else if (c < s) { /* * Add a new entry before the current location. Shift all entries * before the current one up by one to make room. */ for (j = rlp->used; j > i; j -= 2) { rlp->ranges[j] = rlp->ranges[j - 2]; rlp->ranges[j + 1] = rlp->ranges[j - 1]; } rlp->ranges[i] = rlp->ranges[i + 1] = c; rlp->used += 2; } } static void add_decomp(ac_uint4 code, short compat) { ac_uint4 i, j, size; _decomp_t **pdecomps; ac_uint4 *pdecomps_used; ac_uint4 *pdecomps_size; if (compat) { pdecomps = &kdecomps; pdecomps_used = &kdecomps_used; pdecomps_size = &kdecomps_size; } else { pdecomps = &decomps; pdecomps_used = &decomps_used; pdecomps_size = &decomps_size; } /* * Add the code to the composite property. */ if (!compat) { ordered_range_insert(code, "Cm", 2); } /* * Locate the insertion point for the code. */ for (i = 0; i < *pdecomps_used && code > (*pdecomps)[i].code; i++) ; /* * Allocate space for a new decomposition. */ if (*pdecomps_used == *pdecomps_size) { if (*pdecomps_size == 0) *pdecomps = (_decomp_t *) malloc(sizeof(_decomp_t) << 3); else *pdecomps = (_decomp_t *) realloc((char *) *pdecomps, sizeof(_decomp_t) * (*pdecomps_size + 8)); (void) memset((char *) (*pdecomps + *pdecomps_size), '\0', sizeof(_decomp_t) << 3); *pdecomps_size += 8; } if (i < *pdecomps_used && code != (*pdecomps)[i].code) { /* * Shift the decomps up by one if the codes don't match. */ for (j = *pdecomps_used; j > i; j--) (void) AC_MEMCPY((char *) &(*pdecomps)[j], (char *) &(*pdecomps)[j - 1], sizeof(_decomp_t)); } /* * Insert or replace a decomposition. */ size = dectmp_size + (4 - (dectmp_size & 3)); if ((*pdecomps)[i].size < size) { if ((*pdecomps)[i].size == 0) (*pdecomps)[i].decomp = (ac_uint4 *) malloc(sizeof(ac_uint4) * size); else (*pdecomps)[i].decomp = (ac_uint4 *) realloc((char *) (*pdecomps)[i].decomp, sizeof(ac_uint4) * size); (*pdecomps)[i].size = size; } if ((*pdecomps)[i].code != code) (*pdecomps_used)++; (*pdecomps)[i].code = code; (*pdecomps)[i].used = dectmp_size; (void) AC_MEMCPY((char *) (*pdecomps)[i].decomp, (char *) dectmp, sizeof(ac_uint4) * dectmp_size); /* * NOTICE: This needs changing later so it is more general than simply * pairs. This calculation is done here to simplify allocation elsewhere. */ if (!compat && dectmp_size == 2) comps_used++; } static void add_title(ac_uint4 code) { ac_uint4 i, j; /* * Always map the code to itself. */ cases[2] = code; if (title_used == title_size) { if (title_size == 0) title = (_case_t *) malloc(sizeof(_case_t) << 3); else title = (_case_t *) realloc((char *) title, sizeof(_case_t) * (title_size + 8)); title_size += 8; } /* * Locate the insertion point. */ for (i = 0; i < title_used && code > title[i].key; i++) ; if (i < title_used) { /* * Shift the array up by one. */ for (j = title_used; j > i; j--) (void) AC_MEMCPY((char *) &title[j], (char *) &title[j - 1], sizeof(_case_t)); } title[i].key = cases[2]; /* Title */ title[i].other1 = cases[0]; /* Upper */ title[i].other2 = cases[1]; /* Lower */ title_used++; } static void add_upper(ac_uint4 code) { ac_uint4 i, j; /* * Always map the code to itself. */ cases[0] = code; /* * If the title case character is not present, then make it the same as * the upper case. */ if (cases[2] == 0) cases[2] = code; if (upper_used == upper_size) { if (upper_size == 0) upper = (_case_t *) malloc(sizeof(_case_t) << 3); else upper = (_case_t *) realloc((char *) upper, sizeof(_case_t) * (upper_size + 8)); upper_size += 8; } /* * Locate the insertion point. */ for (i = 0; i < upper_used && code > upper[i].key; i++) ; if (i < upper_used) { /* * Shift the array up by one. */ for (j = upper_used; j > i; j--) (void) AC_MEMCPY((char *) &upper[j], (char *) &upper[j - 1], sizeof(_case_t)); } upper[i].key = cases[0]; /* Upper */ upper[i].other1 = cases[1]; /* Lower */ upper[i].other2 = cases[2]; /* Title */ upper_used++; } static void add_lower(ac_uint4 code) { ac_uint4 i, j; /* * Always map the code to itself. */ cases[1] = code; /* * If the title case character is empty, then make it the same as the * upper case. */ if (cases[2] == 0) cases[2] = cases[0]; if (lower_used == lower_size) { if (lower_size == 0) lower = (_case_t *) malloc(sizeof(_case_t) << 3); else lower = (_case_t *) realloc((char *) lower, sizeof(_case_t) * (lower_size + 8)); lower_size += 8; } /* * Locate the insertion point. */ for (i = 0; i < lower_used && code > lower[i].key; i++) ; if (i < lower_used) { /* * Shift the array up by one. */ for (j = lower_used; j > i; j--) (void) AC_MEMCPY((char *) &lower[j], (char *) &lower[j - 1], sizeof(_case_t)); } lower[i].key = cases[1]; /* Lower */ lower[i].other1 = cases[0]; /* Upper */ lower[i].other2 = cases[2]; /* Title */ lower_used++; } static void ordered_ccl_insert(ac_uint4 c, ac_uint4 ccl_code) { ac_uint4 i, j; if (ccl_used == ccl_size) { if (ccl_size == 0) ccl = (ac_uint4 *) malloc(sizeof(ac_uint4) * 24); else ccl = (ac_uint4 *) realloc((char *) ccl, sizeof(ac_uint4) * (ccl_size + 24)); ccl_size += 24; } /* * Optimize adding the first item. */ if (ccl_used == 0) { ccl[0] = ccl[1] = c; ccl[2] = ccl_code; ccl_used += 3; return; } /* * Handle the special case of extending the range on the end. This * requires that the combining class codes are the same. */ if (ccl_code == ccl[ccl_used - 1] && c == ccl[ccl_used - 2] + 1) { ccl[ccl_used - 2] = c; return; } /* * Handle the special case of adding another range on the end. */ if (c > ccl[ccl_used - 2] + 1 || (c == ccl[ccl_used - 2] + 1 && ccl_code != ccl[ccl_used - 1])) { ccl[ccl_used++] = c; ccl[ccl_used++] = c; ccl[ccl_used++] = ccl_code; return; } /* * Locate either the insertion point or range for the code. */ for (i = 0; i < ccl_used && c > ccl[i + 1] + 1; i += 3) ; if (ccl_code == ccl[i + 2] && c == ccl[i + 1] + 1) { /* * Extend an existing range. */ ccl[i + 1] = c; return; } else if (c < ccl[i]) { /* * Start a new range before the current location. */ for (j = ccl_used; j > i; j -= 3) { ccl[j] = ccl[j - 3]; ccl[j - 1] = ccl[j - 4]; ccl[j - 2] = ccl[j - 5]; } ccl[i] = ccl[i + 1] = c; ccl[i + 2] = ccl_code; } } /* * Adds a number if it does not already exist and returns an index value * multiplied by 2. */ static ac_uint4 make_number(short num, short denom) { ac_uint4 n; /* * Determine if the number already exists. */ for (n = 0; n < nums_used; n++) { if (nums[n].numerator == num && nums[n].denominator == denom) return n << 1; } if (nums_used == nums_size) { if (nums_size == 0) nums = (_num_t *) malloc(sizeof(_num_t) << 3); else nums = (_num_t *) realloc((char *) nums, sizeof(_num_t) * (nums_size + 8)); nums_size += 8; } n = nums_used++; nums[n].numerator = num; nums[n].denominator = denom; return n << 1; } static void add_number(ac_uint4 code, short num, short denom) { ac_uint4 i, j; /* * Insert the code in order. */ for (i = 0; i < ncodes_used && code > ncodes[i].code; i++) ; /* * Handle the case of the codes matching and simply replace the number * that was there before. */ if (i < ncodes_used && code == ncodes[i].code) { ncodes[i].idx = make_number(num, denom); return; } /* * Resize the array if necessary. */ if (ncodes_used == ncodes_size) { if (ncodes_size == 0) ncodes = (_codeidx_t *) malloc(sizeof(_codeidx_t) << 3); else ncodes = (_codeidx_t *) realloc((char *) ncodes, sizeof(_codeidx_t) * (ncodes_size + 8)); ncodes_size += 8; } /* * Shift things around to insert the code if necessary. */ if (i < ncodes_used) { for (j = ncodes_used; j > i; j--) { ncodes[j].code = ncodes[j - 1].code; ncodes[j].idx = ncodes[j - 1].idx; } } ncodes[i].code = code; ncodes[i].idx = make_number(num, denom); ncodes_used++; } /* * This routine assumes that the line is a valid Unicode Character Database * entry. */ static void read_cdata(FILE *in) { ac_uint4 i, lineno, skip, code, ccl_code; short wnum, neg, number[2], compat; char line[512], *s, *e; lineno = skip = 0; while (fgets(line, sizeof(line), in)) { if( (s=strchr(line, '\n')) ) *s = '\0'; lineno++; /* * Skip blank lines and lines that start with a '#'. */ if (line[0] == 0 || line[0] == '#') continue; /* * If lines need to be skipped, do it here. */ if (skip) { skip--; continue; } /* * Collect the code. The code can be up to 6 hex digits in length to * allow surrogates to be specified. */ for (s = line, i = code = 0; *s != ';' && i < 6; i++, s++) { code <<= 4; if (*s >= '0' && *s <= '9') code += *s - '0'; else if (*s >= 'A' && *s <= 'F') code += (*s - 'A') + 10; else if (*s >= 'a' && *s <= 'f') code += (*s - 'a') + 10; } /* * Handle the following special cases: * 1. 4E00-9FA5 CJK Ideographs. * 2. AC00-D7A3 Hangul Syllables. * 3. D800-DFFF Surrogates. * 4. E000-F8FF Private Use Area. * 5. F900-FA2D Han compatibility. * ...Plus additional ranges in newer Unicode versions... */ switch (code) { case 0x3400: /* CJK Ideograph Extension A */ add_range(0x3400, 0x4db5, "Lo", "L"); add_range(0x3400, 0x4db5, "Cp", 0); skip = 1; break; case 0x4e00: /* * The Han ideographs. */ add_range(0x4e00, 0x9fff, "Lo", "L"); /* * Add the characters to the defined category. */ add_range(0x4e00, 0x9fa5, "Cp", 0); skip = 1; break; case 0xac00: /* * The Hangul syllables. */ add_range(0xac00, 0xd7a3, "Lo", "L"); /* * Add the characters to the defined category. */ add_range(0xac00, 0xd7a3, "Cp", 0); skip = 1; break; case 0xd800: /* * Make a range of all surrogates and assume some default * properties. */ add_range(0x010000, 0x10ffff, "Cs", "L"); skip = 5; break; case 0xe000: /* * The Private Use area. Add with a default set of properties. */ add_range(0xe000, 0xf8ff, "Co", "L"); skip = 1; break; case 0xf900: /* * The CJK compatibility area. */ add_range(0xf900, 0xfaff, "Lo", "L"); /* * Add the characters to the defined category. */ add_range(0xf900, 0xfaff, "Cp", 0); skip = 1; break; case 0x20000: /* CJK Ideograph Extension B */ add_range(0x20000, 0x2a6d6, "Lo", "L"); add_range(0x20000, 0x2a6d6, "Cp", 0); skip = 1; break; case 0xf0000: /* Plane 15 private use */ add_range(0xf0000, 0xffffd, "Co", "L"); skip = 1; break; case 0x100000: /* Plane 16 private use */ add_range(0x100000, 0x10fffd, "Co", "L"); skip = 1; break; } if (skip) continue; /* * Add the code to the defined category. */ ordered_range_insert(code, "Cp", 2); /* * Locate the first character property field. */ for (i = 0; *s != 0 && i < 2; s++) { if (*s == ';') i++; } for (e = s; *e && *e != ';'; e++) ; ordered_range_insert(code, s, e - s); /* * Locate the combining class code. */ for (s = e; *s != 0 && i < 3; s++) { if (*s == ';') i++; } /* * Convert the combining class code from decimal. */ for (ccl_code = 0, e = s; *e && *e != ';'; e++) ccl_code = (ccl_code * 10) + (*e - '0'); /* * Add the code if it not 0. */ if (ccl_code != 0) ordered_ccl_insert(code, ccl_code); /* * Locate the second character property field. */ for (s = e; *s != 0 && i < 4; s++) { if (*s == ';') i++; } for (e = s; *e && *e != ';'; e++) ; ordered_range_insert(code, s, e - s); /* * Check for a decomposition. */ s = ++e; if (*s != ';') { compat = *s == '<'; if (compat) { /* * Skip compatibility formatting tag. */ while (*s++ != '>'); } /* * Collect the codes of the decomposition. */ for (dectmp_size = 0; *s != ';'; ) { /* * Skip all leading non-hex digits. */ while (!ishdigit(*s)) s++; for (dectmp[dectmp_size] = 0; ishdigit(*s); s++) { dectmp[dectmp_size] <<= 4; if (*s >= '0' && *s <= '9') dectmp[dectmp_size] += *s - '0'; else if (*s >= 'A' && *s <= 'F') dectmp[dectmp_size] += (*s - 'A') + 10; else if (*s >= 'a' && *s <= 'f') dectmp[dectmp_size] += (*s - 'a') + 10; } dectmp_size++; } /* * If there are any codes in the temporary decomposition array, * then add the character with its decomposition. */ if (dectmp_size > 0) { if (!compat) { add_decomp(code, 0); } add_decomp(code, 1); } } /* * Skip to the number field. */ for (i = 0; i < 3 && *s; s++) { if (*s == ';') i++; } /* * Scan the number in. */ number[0] = number[1] = 0; for (e = s, neg = wnum = 0; *e && *e != ';'; e++) { if (*e == '-') { neg = 1; continue; } if (*e == '/') { /* * Move the the denominator of the fraction. */ if (neg) number[wnum] *= -1; neg = 0; e++; wnum++; } number[wnum] = (number[wnum] * 10) + (*e - '0'); } if (e > s) { /* * Adjust the denominator in case of integers and add the number. */ if (wnum == 0) number[1] = 1; add_number(code, number[0], number[1]); } /* * Skip to the start of the possible case mappings. */ for (s = e, i = 0; i < 4 && *s; s++) { if (*s == ';') i++; } /* * Collect the case mappings. */ cases[0] = cases[1] = cases[2] = 0; for (i = 0; i < 3; i++) { while (ishdigit(*s)) { cases[i] <<= 4; if (*s >= '0' && *s <= '9') cases[i] += *s - '0'; else if (*s >= 'A' && *s <= 'F') cases[i] += (*s - 'A') + 10; else if (*s >= 'a' && *s <= 'f') cases[i] += (*s - 'a') + 10; s++; } if (*s == ';') s++; } if (cases[0] && cases[1]) /* * Add the upper and lower mappings for a title case character. */ add_title(code); else if (cases[1]) /* * Add the lower and title case mappings for the upper case * character. */ add_upper(code); else if (cases[0]) /* * Add the upper and title case mappings for the lower case * character. */ add_lower(code); } } static _decomp_t * find_decomp(ac_uint4 code, short compat) { long l, r, m; _decomp_t *decs; l = 0; r = (compat ? kdecomps_used : decomps_used) - 1; decs = compat ? kdecomps : decomps; while (l <= r) { m = (l + r) >> 1; if (code > decs[m].code) l = m + 1; else if (code < decs[m].code) r = m - 1; else return &decs[m]; } return 0; } static void decomp_it(_decomp_t *d, short compat) { ac_uint4 i; _decomp_t *dp; for (i = 0; i < d->used; i++) { if ((dp = find_decomp(d->decomp[i], compat)) != 0) decomp_it(dp, compat); else dectmp[dectmp_size++] = d->decomp[i]; } } /* * Expand all decompositions by recursively decomposing each character * in the decomposition. */ static void expand_decomp(void) { ac_uint4 i; for (i = 0; i < decomps_used; i++) { dectmp_size = 0; decomp_it(&decomps[i], 0); if (dectmp_size > 0) add_decomp(decomps[i].code, 0); } for (i = 0; i < kdecomps_used; i++) { dectmp_size = 0; decomp_it(&kdecomps[i], 1); if (dectmp_size > 0) add_decomp(kdecomps[i].code, 1); } } static int cmpcomps(const void *v_comp1, const void *v_comp2) { const _comp_t *comp1 = v_comp1, *comp2 = v_comp2; long diff = comp1->code1 - comp2->code1; if (!diff) diff = comp1->code2 - comp2->code2; return (int) diff; } /* * Load composition exclusion data */ static void read_compexdata(FILE *in) { ac_uint2 i; ac_uint4 code; char line[512], *s; (void) memset((char *) compexs, 0, sizeof(compexs)); while (fgets(line, sizeof(line), in)) { if( (s=strchr(line, '\n')) ) *s = '\0'; /* * Skip blank lines and lines that start with a '#'. */ if (line[0] == 0 || line[0] == '#') continue; /* * Collect the code. Assume max 6 digits */ for (s = line, i = code = 0; *s != '#' && i < 6; i++, s++) { if (isspace((unsigned char)*s)) break; code <<= 4; if (*s >= '0' && *s <= '9') code += *s - '0'; else if (*s >= 'A' && *s <= 'F') code += (*s - 'A') + 10; else if (*s >= 'a' && *s <= 'f') code += (*s - 'a') + 10; } COMPEX_SET(code); } } /* * Creates array of compositions from decomposition array */ static void create_comps(void) { ac_uint4 i, cu; comps = (_comp_t *) malloc(comps_used * sizeof(_comp_t)); for (i = cu = 0; i < decomps_used; i++) { if (decomps[i].used != 2 || COMPEX_TEST(decomps[i].code)) continue; comps[cu].comp = decomps[i].code; comps[cu].count = 2; comps[cu].code1 = decomps[i].decomp[0]; comps[cu].code2 = decomps[i].decomp[1]; cu++; } comps_used = cu; qsort(comps, comps_used, sizeof(_comp_t), cmpcomps); } #if HARDCODE_DATA static void write_case(FILE *out, _case_t *tab, int num, int first) { int i; for (i=0; i 0) { for (j=0; j 0) fwrite((char *) proptbl[i].ranges, sizeof(ac_uint4), proptbl[i].used, out); } fclose(out); #endif /***************************************************************** * * Generate the case mapping data. * *****************************************************************/ #if HARDCODE_DATA fprintf(out, PREF "ac_uint4 _uccase_size = %ld;\n\n", (long) (upper_used + lower_used + title_used)); fprintf(out, PREF "ac_uint2 _uccase_len[2] = {%ld, %ld};\n\n", (long) upper_used, (long) lower_used); fprintf(out, PREF "ac_uint4 _uccase_map[] = {"); if (upper_used > 0) /* * Write the upper case table. */ write_case(out, upper, upper_used, 1); if (lower_used > 0) /* * Write the lower case table. */ write_case(out, lower, lower_used, !upper_used); if (title_used > 0) /* * Write the title case table. */ write_case(out, title, title_used, !(upper_used||lower_used)); if (!(upper_used || lower_used || title_used)) fprintf(out, "\t0"); fprintf(out, "\n};\n\n"); #else /* * Open the case.dat file. */ snprintf(path, sizeof path, "%s" LDAP_DIRSEP "case.dat", opath); if ((out = fopen(path, "wb")) == 0) return; /* * Write the case mapping tables. */ hdr[1] = upper_used + lower_used + title_used; casecnt[0] = upper_used; casecnt[1] = lower_used; /* * Write the header. */ fwrite((char *) hdr, sizeof(ac_uint2), 2, out); /* * Write the upper and lower case table sizes. */ fwrite((char *) casecnt, sizeof(ac_uint2), 2, out); if (upper_used > 0) /* * Write the upper case table. */ fwrite((char *) upper, sizeof(_case_t), upper_used, out); if (lower_used > 0) /* * Write the lower case table. */ fwrite((char *) lower, sizeof(_case_t), lower_used, out); if (title_used > 0) /* * Write the title case table. */ fwrite((char *) title, sizeof(_case_t), title_used, out); fclose(out); #endif /***************************************************************** * * Generate the composition data. * *****************************************************************/ /* * Create compositions from decomposition data */ create_comps(); #if HARDCODE_DATA fprintf(out, PREF "ac_uint4 _uccomp_size = %ld;\n\n", comps_used * 4L); fprintf(out, PREF "ac_uint4 _uccomp_data[] = {"); /* * Now, if comps exist, write them out. */ if (comps_used > 0) { for (i=0; i 0) fwrite((char *) comps, sizeof(_comp_t), comps_used, out); fclose(out); #endif /***************************************************************** * * Generate the decomposition data. * *****************************************************************/ /* * Fully expand all decompositions before generating the output file. */ expand_decomp(); #if HARDCODE_DATA fprintf(out, PREF "ac_uint4 _ucdcmp_size = %ld;\n\n", decomps_used * 2L); fprintf(out, PREF "ac_uint4 _ucdcmp_nodes[] = {"); if (decomps_used) { /* * Write the list of decomp nodes. */ for (i = idx = 0; i < decomps_used; i++) { fprintf(out, "\n\t0x%08lx, 0x%08lx,", (unsigned long) decomps[i].code, (unsigned long) idx); idx += decomps[i].used; } /* * Write the sentinel index as the last decomp node. */ fprintf(out, "\n\t0x%08lx\n};\n\n", (unsigned long) idx); fprintf(out, PREF "ac_uint4 _ucdcmp_decomp[] = {"); /* * Write the decompositions themselves. */ k = 0; for (i = 0; i < decomps_used; i++) for (j=0; j 0) { /* * Write the combining class ranges out. */ for (i = 0; i 0) /* * Write the combining class ranges out. */ fwrite((char *) ccl, sizeof(ac_uint4), ccl_used, out); fclose(out); #endif /***************************************************************** * * Generate the number data. * *****************************************************************/ #if HARDCODE_DATA fprintf(out, PREF "ac_uint4 _ucnum_size = %lu;\n\n", (unsigned long)ncodes_used<<1); fprintf(out, PREF "ac_uint4 _ucnum_nodes[] = {"); /* * Now, if number mappings exist, write them out. */ if (ncodes_used > 0) { for (i = 0; i 0) { fwrite((char *) ncodes, sizeof(_codeidx_t), ncodes_used, out); fwrite((char *) nums, sizeof(_num_t), nums_used, out); } #endif fclose(out); } static void usage(char *prog) { fprintf(stderr, "Usage: %s [-o output-directory|-x composition-exclusions]", prog); fprintf(stderr, " datafile1 datafile2 ...\n\n"); fprintf(stderr, "-o output-directory\n\t\tWrite the output files to a different"); fprintf(stderr, " directory (default: .).\n"); fprintf(stderr, "-x composition-exclusion\n\t\tFile of composition codes"); fprintf(stderr, " that should be excluded.\n"); exit(1); } int main(int argc, char *argv[]) { FILE *in; char *prog, *opath; prog = lutil_progname( "ucgendat", argc, argv ); opath = 0; in = stdin; argc--; argv++; while (argc > 0) { if (argv[0][0] == '-') { switch (argv[0][1]) { case 'o': argc--; argv++; opath = argv[0]; break; case 'x': argc--; argv++; if ((in = fopen(argv[0], "r")) == 0) fprintf(stderr, "%s: unable to open composition exclusion file %s\n", prog, argv[0]); else { read_compexdata(in); fclose(in); in = 0; } break; default: usage(prog); } } else { if (in != stdin && in != NULL) fclose(in); if ((in = fopen(argv[0], "r")) == 0) fprintf(stderr, "%s: unable to open ctype file %s\n", prog, argv[0]); else { read_cdata(in); fclose(in); in = 0; } } argc--; argv++; } if (opath == 0) opath = "."; write_cdata(opath); return 0; } openldap-2.4.42+dfsg/libraries/liblunicode/ucdata/ucdata.man0000644000175000017500000002774212563404150022510 0ustar ryanryan.\" .\" $Id: ucdata.man,v 1.5 2001/01/02 18:46:20 mleisher Exp $ .\" .TH ucdata 3 "03 January 2001" .SH NAME ucdata \- package for providing Unicode/ISO10646 character information .SH SYNOPSIS #include .sp void ucdata_load(char * paths, int masks) .sp void ucdata_unload(int masks) .sp void ucdata_reload(char * paths, int masks) .sp int ucdecomp(unsigned long code, unsigned long *num, unsigned long **decomp) .sp int uccanondecomp(const unsigned long *in, int inlen, unsigned long **out, int *outlen) .sp int ucdecomp_hangul(unsigned long code, unsigned long *num, unsigned long decomp[]) .sp int uccomp(unsigned long ch1, unsigned long ch2, unsigned long *comp) .sp int uccomp_hangul(unsigned long *str, int len) .sp int uccanoncomp(unsiged long *str, int len) .nf struct ucnumber { int numerator; int denominator; }; .sp int ucnumber_lookup(unsigned long code, struct ucnumber *num) .sp int ucdigit_lookup(unsigned long code, int *digit) .sp struct ucnumber ucgetnumber(unsigned long code) .sp int ucgetdigit(unsigned long code) .sp unsigned long uctoupper(unsigned long code) .sp unsigned long uctolower(unsigned long code) .sp unsigned long uctotitle(unsigned long code) .sp int ucisalpha(unsigned long code) .sp int ucisalnum(unsigned long code) .sp int ucisdigit(unsigned long code) .sp int uciscntrl(unsigned long code) .sp int ucisspace(unsigned long code) .sp int ucisblank(unsigned long code) .sp int ucispunct(unsigned long code) .sp int ucisgraph(unsigned long code) .sp int ucisprint(unsigned long code) .sp int ucisxdigit(unsigned long code) .sp int ucisupper(unsigned long code) .sp int ucislower(unsigned long code) .sp int ucistitle(unsigned long code) .sp int ucisisocntrl(unsigned long code) .sp int ucisfmtcntrl(unsigned long code) .sp int ucissymbol(unsigned long code) .sp int ucisnumber(unsigned long code) .sp int ucisnonspacing(unsigned long code) .sp int ucisopenpunct(unsigned long code) .sp int ucisclosepunct(unsigned long code) .sp int ucisinitialpunct(unsigned long code) .sp int ucisfinalpunct(unsigned long code) .sp int uciscomposite(unsigned long code) .sp int ucisquote(unsigned long code) .sp int ucissymmetric(unsigned long code) .sp int ucismirroring(unsigned long code) .sp int ucisnonbreaking(unsigned long code) .sp int ucisrtl(unsigned long code) .sp int ucisltr(unsigned long code) .sp int ucisstrong(unsigned long code) .sp int ucisweak(unsigned long code) .sp int ucisneutral(unsigned long code) .sp int ucisseparator(unsigned long code) .sp int ucislsep(unsigned long code) .sp int ucispsep(unsigned long code) .sp int ucismark(unsigned long code) .sp int ucisnsmark(unsigned long code) .sp int ucisspmark(unsigned long code) .sp int ucismodif(unsigned long code) .sp int ucismodifsymbol(unsigned long code) .sp int ucisletnum(unsigned long code) .sp int ucisconnect(unsigned long code) .sp int ucisdash(unsigned long code) .sp int ucismath(unsigned long code) .sp int uciscurrency(unsigned long code) .sp int ucisenclosing(unsigned long code) .sp int ucisprivate(unsigned long code) .sp int ucissurrogate(unsigned long code) .sp int ucisidentstart(unsigned long code) .sp int ucisidentpart(unsigned long code) .sp int ucisdefined(unsigned long code) .sp int ucisundefined(unsigned long code) .sp int ucishan(unsigned long code) .sp int ucishangul(unsigned long code) .SH DESCRIPTION .TP 4 .BR Macros .br UCDATA_CASE .br UCDATA_CTYPE .br UCDATA_DECOMP .br UCDATA_CMBCL .br UCDATA_NUM .br UCDATA_ALL .br .TP 4 .BR ucdata_load() This function initializes the UCData library by locating the data files in one of the colon-separated directories in the `paths' parameter. The data files to be loaded are specified in the `masks' parameter as a bitwise combination of the macros listed above. .sp This should be called before using any of the other functions. .TP 4 .BR ucdata_unload() This function unloads the data tables specified in the `masks' parameter. .sp This function should be called when the application is done using the UCData package. .TP 4 .BR ucdata_reload() This function reloads the data files from one of the colon-separated directories in the `paths' parameter. The data files to be reloaded are specified in the `masks' parameter as a bitwise combination of the macros listed above. .TP 4 .BR ucdecomp() This function determines if a character has a decomposition and returns the decomposition information if it exists. .sp If a zero is returned, there is no decomposition. If a non-zero is returned, then the `num' and `decomp' variables are filled in with the appropriate values. .sp Example call: .sp .nf unsigned long i, num, *decomp; if (ucdecomp(0x1d5, &num, &decomp) != 0) { for (i = 0; i < num; i++) printf("0x%08lX,", decomp[i]); putchar('\n'); } .TP 4 .BR uccanondecomp() This function will decompose a string, insuring the characters are in canonical order for comparison. .sp If a decomposed string is returned, the caller is responsible for deallocating the string. .sp If a -1 is returned, memory allocation failed. If a zero is returned, no decomposition was done. Any other value means a decomposition string was created and the values returned in the `out' and `outlen' parameters. .TP 4 .BR ucdecomp_hangul() This function determines if a Hangul syllable has a decomposition and returns the decomposition information. .sp An array of at least size 3 should be passed to the function for the decomposition of the syllable. .sp If a zero is returned, the character is not a Hangul syllable. If a non-zero is returned, the `num' field will be 2 or 3 and the syllable will be decomposed into the `decomp' array arithmetically. .sp Example call: .sp .nf unsigned long i, num, decomp[3]; if (ucdecomp_hangul(0xb1ba, &num, &decomp) != 0) { for (i = 0; i < num; i++) printf("0x%08lX,", decomp[i]); putchar('\n'); } .TP 4 .BR uccomp() This function determines if a pair of characters have a composition, and returns that composition if one exists. .sp A zero is returned is no composition exists for the character pair. Any other value indicates the `comp' field holds the character code representing the composition of the two character codes. .TP 4 .BR uccomp_hangul() This composes the Hangul Jamo in-place in the string. .sp The returned value is the new length of the string. .TP 4 .BR uccanoncomp() This function does a full composition in-place in the string, including the Hangul composition. .sp The returned value is the new length of the string. .TP 4 .BR ucnumber_lookup() This function determines if the code is a number and fills in the `num' field with the numerator and denominator. If the code happens to be a single digit, the numerator and denominator fields will be the same. .sp If the function returns 0, the code is not a number. Any other return value means the code is a number. .TP 4 .BR ucdigit_lookup() This function determines if the code is a digit and fills in the `digit' field with the digit value. .sp If the function returns 0, the code is not a number. Any other return value means the code is a number. .TP 4 .BR ucgetnumber() This is a compatibility function with John Cowan's "uctype" package. It uses ucnumber_lookup(). .TP 4 .BR ucgetdigit() This is a compatibility function with John Cowan's "uctype" package. It uses ucdigit_lookup(). .TP 4 .BR uctoupper() This function returns the code unchanged if it is already upper case or has no upper case equivalent. Otherwise the upper case equivalent is returned. .TP 4 .BR uctolower() This function returns the code unchanged if it is already lower case or has no lower case equivalent. Otherwise the lower case equivalent is returned. .TP 4 .BR uctotitle() This function returns the code unchanged if it is already title case or has no title case equivalent. Otherwise the title case equivalent is returned. .TP 4 .BR ucisalpha() Test if \fIcode\fR is an alpha character. .TP 4 .BR ucisalnum() Test if \fIcode\fR is an alpha or digit character. .TP 4 .BR ucisdigit() Test if \fIcode\fR is a digit character. .TP 4 .BR uciscntrl() Test if \fIcode\fR is a control character. .TP 4 .BR ucisspace() Test if \fIcode\fR is a space character. .TP 4 .BR ucisblank() Test if \fIcode\fR is a blank character. .TP 4 .BR ucispunct() Test if \fIcode\fR is a punctuation character. .TP 4 .BR ucisgraph() Test if \fIcode\fR is a graphical (visible) character. .TP 4 .BR ucisprint() Test if \fIcode\fR is a printable character. .TP 4 .BR ucisxdigit() Test if \fIcode\fR is a hexadecimal digit character. .TP 4 .BR ucisupper() Test if \fIcode\fR is an upper case character. .TP 4 .BR ucislower() Test if \fIcode\fR is a lower case character. .TP 4 .BR ucistitle() Test if \fIcode\fR is a title case character. .TP 4 .BR ucisisocntrl() Is the character a C0 control character (< 32)? .TP 4 .BR ucisfmtcntrl() Is the character a format control character? .TP 4 .BR ucissymbol() Is the character a symbol? .TP 4 .BR ucisnumber() Is the character a number or digit? .TP 4 .BR ucisnonspacing() Is the character non-spacing? .TP 4 .BR ucisopenpunct() Is the character an open/left punctuation (i.e. '[') .TP 4 .BR ucisclosepunct() Is the character an close/right punctuation (i.e. ']') .TP 4 .BR ucisinitialpunct() Is the character an initial punctuation (i.e. U+2018 LEFT SINGLE QUOTATION MARK) .TP 4 .BR ucisfinalpunct() Is the character a final punctuation (i.e. U+2019 RIGHT SINGLE QUOTATION MARK) .TP 4 .BR uciscomposite() Can the character be decomposed into a set of other characters? .TP 4 .BR ucisquote() Is the character one of the many quotation marks? .TP 4 .BR ucissymmetric() Is the character one that has an opposite form (i.e. <>) .TP 4 .BR ucismirroring() Is the character mirroring (superset of symmetric)? .TP 4 .BR ucisnonbreaking() Is the character non-breaking (i.e. non-breaking space)? .TP 4 .BR ucisrtl() Does the character have strong right-to-left directionality (i.e. Arabic letters)? .TP 4 .BR ucisltr() Does the character have strong left-to-right directionality (i.e. Latin letters)? .TP 4 .BR ucisstrong() Does the character have strong directionality? .TP 4 .BR ucisweak() Does the character have weak directionality (i.e. numbers)? .TP 4 .BR ucisneutral() Does the character have neutral directionality (i.e. whitespace)? .TP 4 .BR ucisseparator() Is the character a block or segment separator? .TP 4 .BR ucislsep() Is the character a line separator? .TP 4 .BR ucispsep() Is the character a paragraph separator? .TP 4 .BR ucismark() Is the character a mark of some kind? .TP 4 .BR ucisnsmark() Is the character a non-spacing mark? .TP 4 .BR ucisspmark() Is the character a spacing mark? .TP 4 .BR ucismodif() Is the character a modifier letter? .TP 4 .BR ucismodifsymbol() Is the character a modifier symbol? .TP 4 .BR ucisletnum() Is the character a number represented by a letter? .TP 4 .BR ucisconnect() Is the character connecting punctuation? .TP 4 .BR ucisdash() Is the character dash punctuation? .TP 4 .BR ucismath() Is the character a math character? .TP 4 .BR uciscurrency() Is the character a currency character? .TP 4 .BR ucisenclosing() Is the character enclosing (i.e. enclosing box)? .TP 4 .BR ucisprivate() Is the character from the Private Use Area? .TP 4 .BR ucissurrogate() Is the character one of the surrogate codes? .TP 4 .BR ucisidentstart() Is the character a legal initial character of an identifier? .TP 4 .BR ucisidentpart() Is the character a legal identifier character? .TP 4 .BR ucisdefined() Is the character defined (appeared in one of the data files)? .TP 4 .BR ucisundefined() Is the character not defined (non-Unicode)? .TP 4 .BR ucishan() Is the character a Han ideograph? .TP 4 .BR ucishangul() Is the character a pre-composed Hangul syllable? .SH "SEE ALSO" ctype(3) .SH ACKNOWLEDGMENTS These are people who have helped with patches or alerted me about problems. .sp John Cowan .br Bob Verbrugge .br Christophe Pierret .br Kent Johnson .br Valeriy E. Ushakov .br Stig Venaas .SH AUTHOR Mark Leisher .br Computing Research Lab .br New Mexico State University .br Email: mleisher@crl.nmsu.edu openldap-2.4.42+dfsg/libraries/liblunicode/ucdata/ucpgba.h0000644000175000017500000001356212563404150022157 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Copyright 1999 Computing Research Labs, New Mexico State University * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* $Id: ucpgba.h,v 1.4 1999/11/19 15:24:30 mleisher Exp $ */ #ifndef _h_ucpgba #define _h_ucpgba #include "portable.h" LDAP_BEGIN_DECL /*************************************************************************** * * Macros and types. * ***************************************************************************/ /* * These are the direction values that can appear in render runs and render * strings. */ #define UCPGBA_LTR 0 #define UCPGBA_RTL 1 /* * These are the flags for cursor motion. */ #define UCPGBA_CURSOR_VISUAL 0 #define UCPGBA_CURSOR_LOGICAL 1 /* * This structure is used to contain runs of text in a particular direction. */ typedef struct _ucrun_t { struct _ucrun_t *visual_prev; /* Pointer to the previous visual run. */ struct _ucrun_t *visual_next; /* Pointer to the next visual run. */ struct _ucrun_t *logical_prev; /* Pointer to the previous logical run. */ struct _ucrun_t *logical_next; /* Pointer to the next logical run. */ int direction; /* Direction of the run. */ long cursor; /* Position of "cursor" in the string. */ unsigned long *chars; /* List of characters for the run. */ unsigned long *positions; /* List of original positions in source. */ unsigned long *source; /* The source string. */ unsigned long start; /* Beginning offset in the source string. */ unsigned long end; /* Ending offset in the source string. */ } ucrun_t; /* * This represents a string of runs rendered up to a point that is not * platform specific. */ typedef struct _ucstring_t { int direction; /* Overall direction of the string. */ int cursor_motion; /* Logical or visual cursor motion flag. */ ucrun_t *cursor; /* The run containing the "cursor." */ ucrun_t *logical_first; /* First run in the logical order. */ ucrun_t *logical_last; /* Last run in the logical order. */ ucrun_t *visual_first; /* First run in the visual order. */ ucrun_t *visual_last; /* Last run in the visual order. */ unsigned long *source; /* The source string. */ unsigned long start; /* The beginning offset in the source. */ unsigned long end; /* The ending offset in the source. */ } ucstring_t; /*************************************************************************** * * API * ***************************************************************************/ /* * This creates and reorders the specified substring using the * "Pretty Good Bidi Algorithm." A default direction is provided for cases * of a string containing no strong direction characters and the default * cursor motion should be provided. */ LDAP_LUNICODE_F (ucstring_t *) ucstring_create LDAP_P((unsigned long *source, unsigned long start, unsigned long end, int default_direction, int cursor_motion)); /* * This releases the string. */ LDAP_LUNICODE_F (void) ucstring_free LDAP_P((ucstring_t *string)); /* * This changes the cursor motion flag for the string. */ LDAP_LUNICODE_F (int) ucstring_set_cursor_motion LDAP_P((ucstring_t *string, int cursor_motion)); /* * This function will move the cursor to the right depending on the * type of cursor motion that was specified for the string. * * A 0 is returned if no cursor motion is performed, otherwise a * 1 is returned. */ LDAP_LUNICODE_F (int) ucstring_cursor_right LDAP_P((ucstring_t *string, int count)); /* * This function will move the cursor to the left depending on the * type of cursor motion that was specified for the string. * * A 0 is returned if no cursor motion is performed, otherwise a * 1 is returned. */ LDAP_LUNICODE_F (int) ucstring_cursor_left LDAP_P((ucstring_t *string, int count)); /* * This routine retrieves the direction of the run containing the cursor * and the actual position in the original text string. */ LDAP_LUNICODE_F (void) ucstring_cursor_info LDAP_P((ucstring_t *string, int *direction, unsigned long *position)); LDAP_END_DECL #endif /* _h_ucpgba */ openldap-2.4.42+dfsg/libraries/liblunicode/ucdata/format.txt0000644000175000017500000002232712563404150022575 0ustar ryanryan# # $Id: format.txt,v 1.2 2001/01/02 18:46:20 mleisher Exp $ # CHARACTER DATA ============== This package generates some data files that contain character properties useful for text processing. CHARACTER PROPERTIES ==================== The first data file is called "ctype.dat" and contains a compressed form of the character properties found in the Unicode Character Database (UCDB). Additional properties can be specified in limited UCDB format in another file to avoid modifying the original UCDB. The following is a property name and code table to be used with the character data: NAME CODE DESCRIPTION --------------------- Mn 0 Mark, Non-Spacing Mc 1 Mark, Spacing Combining Me 2 Mark, Enclosing Nd 3 Number, Decimal Digit Nl 4 Number, Letter No 5 Number, Other Zs 6 Separator, Space Zl 7 Separator, Line Zp 8 Separator, Paragraph Cc 9 Other, Control Cf 10 Other, Format Cs 11 Other, Surrogate Co 12 Other, Private Use Cn 13 Other, Not Assigned Lu 14 Letter, Uppercase Ll 15 Letter, Lowercase Lt 16 Letter, Titlecase Lm 17 Letter, Modifier Lo 18 Letter, Other Pc 19 Punctuation, Connector Pd 20 Punctuation, Dash Ps 21 Punctuation, Open Pe 22 Punctuation, Close Po 23 Punctuation, Other Sm 24 Symbol, Math Sc 25 Symbol, Currency Sk 26 Symbol, Modifier So 27 Symbol, Other L 28 Left-To-Right R 29 Right-To-Left EN 30 European Number ES 31 European Number Separator ET 32 European Number Terminator AN 33 Arabic Number CS 34 Common Number Separator B 35 Block Separator S 36 Segment Separator WS 37 Whitespace ON 38 Other Neutrals Pi 47 Punctuation, Initial Pf 48 Punctuation, Final # # Implementation specific properties. # Cm 39 Composite Nb 40 Non-Breaking Sy 41 Symmetric (characters which are part of open/close pairs) Hd 42 Hex Digit Qm 43 Quote Mark Mr 44 Mirroring Ss 45 Space, Other (controls viewed as spaces in ctype isspace()) Cp 46 Defined character The actual binary data is formatted as follows: Assumptions: unsigned short is at least 16-bits in size and unsigned long is at least 32-bits in size. unsigned short ByteOrderMark unsigned short OffsetArraySize unsigned long Bytes unsigned short Offsets[OffsetArraySize + 1] unsigned long Ranges[N], N = value of Offsets[OffsetArraySize] The Bytes field provides the total byte count used for the Offsets[] and Ranges[] arrays. The Offsets[] array is aligned on a 4-byte boundary and there is always one extra node on the end to hold the final index of the Ranges[] array. The Ranges[] array contains pairs of 4-byte values representing a range of Unicode characters. The pairs are arranged in increasing order by the first character code in the range. Determining if a particular character is in the property list requires a simple binary search to determine if a character is in any of the ranges for the property. If the ByteOrderMark is equal to 0xFFFE, then the data was generated on a machine with a different endian order and the values must be byte-swapped. To swap a 16-bit value: c = (c >> 8) | ((c & 0xff) << 8) To swap a 32-bit value: c = ((c & 0xff) << 24) | (((c >> 8) & 0xff) << 16) | (((c >> 16) & 0xff) << 8) | (c >> 24) CASE MAPPINGS ============= The next data file is called "case.dat" and contains three case mapping tables in the following order: upper, lower, and title case. Each table is in increasing order by character code and each mapping contains 3 unsigned longs which represent the possible mappings. The format for the binary form of these tables is: unsigned short ByteOrderMark unsigned short NumMappingNodes, count of all mapping nodes unsigned short CaseTableSizes[2], upper and lower mapping node counts unsigned long CaseTables[NumMappingNodes] The starting indexes of the case tables are calculated as following: UpperIndex = 0; LowerIndex = CaseTableSizes[0] * 3; TitleIndex = LowerIndex + CaseTableSizes[1] * 3; The order of the fields for the three tables are: Upper case ---------- unsigned long upper; unsigned long lower; unsigned long title; Lower case ---------- unsigned long lower; unsigned long upper; unsigned long title; Title case ---------- unsigned long title; unsigned long upper; unsigned long lower; If the ByteOrderMark is equal to 0xFFFE, endian swapping is required in the same way as described in the CHARACTER PROPERTIES section. Because the tables are in increasing order by character code, locating a mapping requires a simple binary search on one of the 3 codes that make up each node. It is important to note that there can only be 65536 mapping nodes which divided into 3 portions allows 21845 nodes for each case mapping table. The distribution of mappings may be more or less than 21845 per table, but only 65536 are allowed. COMPOSITIONS ============ This data file is called "comp.dat" and contains data that tracks character pairs that have a single Unicode value representing the combination of the two characters. The format for the binary form of this table is: unsigned short ByteOrderMark unsigned short NumCompositionNodes, count of composition nodes unsigned long Bytes, total number of bytes used for composition nodes unsigned long CompositionNodes[NumCompositionNodes * 4] If the ByteOrderMark is equal to 0xFFFE, endian swapping is required in the same way as described in the CHARACTER PROPERTIES section. The CompositionNodes[] array consists of groups of 4 unsigned longs. The first of these is the character code representing the combination of two other character codes, the second records the number of character codes that make up the composition (not currently used), and the last two are the pair of character codes whose combination is represented by the character code in the first field. DECOMPOSITIONS ============== The next data file is called "decomp.dat" and contains the decomposition data for all characters with decompositions containing more than one character and are *not* compatibility decompositions. Compatibility decompositions are signaled in the UCDB format by the use of the tag in the decomposition field. Each list of character codes represents a full decomposition of a composite character. The nodes are arranged in increasing order by character code. The format for the binary form of this table is: unsigned short ByteOrderMark unsigned short NumDecompNodes, count of all decomposition nodes unsigned long Bytes unsigned long DecompNodes[(NumDecompNodes * 2) + 1] unsigned long Decomp[N], N = sum of all counts in DecompNodes[] If the ByteOrderMark is equal to 0xFFFE, endian swapping is required in the same way as described in the CHARACTER PROPERTIES section. The DecompNodes[] array consists of pairs of unsigned longs, the first of which is the character code and the second is the initial index of the list of character codes representing the decomposition. Locating the decomposition of a composite character requires a binary search for a character code in the DecompNodes[] array and using its index to locate the start of the decomposition. The length of the decomposition list is the index in the following element in DecompNode[] minus the current index. COMBINING CLASSES ================= The fourth data file is called "cmbcl.dat" and contains the characters with non-zero combining classes. The format for the binary form of this table is: unsigned short ByteOrderMark unsigned short NumCCLNodes unsigned long Bytes unsigned long CCLNodes[NumCCLNodes * 3] If the ByteOrderMark is equal to 0xFFFE, endian swapping is required in the same way as described in the CHARACTER PROPERTIES section. The CCLNodes[] array consists of groups of three unsigned longs. The first and second are the beginning and ending of a range and the third is the combining class of that range. If a character is not found in this table, then the combining class is assumed to be 0. It is important to note that only 65536 distinct ranges plus combining class can be specified because the NumCCLNodes is usually a 16-bit number. NUMBER TABLE ============ The final data file is called "num.dat" and contains the characters that have a numeric value associated with them. The format for the binary form of the table is: unsigned short ByteOrderMark unsigned short NumNumberNodes unsigned long Bytes unsigned long NumberNodes[NumNumberNodes] unsigned short ValueNodes[(Bytes - (NumNumberNodes * sizeof(unsigned long))) / sizeof(short)] If the ByteOrderMark is equal to 0xFFFE, endian swapping is required in the same way as described in the CHARACTER PROPERTIES section. The NumberNodes array contains pairs of values, the first of which is the character code and the second an index into the ValueNodes array. The ValueNodes array contains pairs of integers which represent the numerator and denominator of the numeric value of the character. If the character happens to map to an integer, both the values in ValueNodes will be the same. openldap-2.4.42+dfsg/libraries/liblunicode/ucdata/bidiapi.txt0000644000175000017500000000612612563404150022705 0ustar ryanryan# # $Id: bidiapi.txt,v 1.2 1999/11/19 15:24:29 mleisher Exp $ # "Pretty Good Bidi Algorithm" API The PGBA (Pretty Good Bidi Algorithm) is an effective alternative to the Unicode BiDi algorithm. It currently provides only implicit reordering and does not yet support explicit reordering codes that the Unicode BiDi algorithm supports. In addition to reordering, the PGBA includes cursor movement support for both visual and logical navigation. ----------------------------------------------------------------------------- #define UCPGBA_LTR 0 #define UCPGBA_RTL 1 These macros appear in the `direction' field of the data structures. #define UCPGBA_CURSOR_VISUAL 0 #define UCPGBA_CURSOR_LOGICAL 1 These macros are used to set the cursor movement for each reordered string. ----------------------------------------------------------------------------- ucstring_t *ucstring_create(unsigned long *source, unsigned long start, unsigned long end, int default_direction, int cursor_motion) This function will create a reordered string by using the implicit directionality of the characters in the specified substring. The `default_direction' parameter should be one of UCPGBA_LTR or UCPGBA_RTL and is used only in cases where a string contains no characters with strong directionality. The `cursor_motion' parameter should be one of UCPGBA_CURSOR_VISUAL or UCPGBA_CURSOR_LOGICAL, and is used to specify the initial cursor motion behavior. This behavior can be switched at any time using ustring_set_cursor_motion(). ----------------------------------------------------------------------------- void ucstring_free(ucstring_t *string) This function will deallocate the memory used by the string, incuding the string itself. ----------------------------------------------------------------------------- void ucstring_cursor_info(ustring_t *string, int *direction, unsigned long *position) This function will return the text position of the internal cursor and the directionality of the text at that position. The position returned is the original text position of the character. ----------------------------------------------------------------------------- int ucstring_set_cursor_motion(ucstring_t *string, int cursor_motion) This function will change the cursor motion type and return the previous cursor motion type. ----------------------------------------------------------------------------- int ucstring_cursor_right(ucstring_t *string, int count) This function will move the internal cursor to the right according to the type of cursor motion set for the string. If no cursor motion is performed, it returns 0. Otherwise it will return a 1. ----------------------------------------------------------------------------- int ucstring_cursor_left(ucstring_t *string, int count) This function will move the internal cursor to the left according to the type of cursor motion set for the string. If no cursor motion is performed, it returns 0. Otherwise it will return a 1. openldap-2.4.42+dfsg/libraries/liblunicode/ucdata/api.txt0000644000175000017500000002723112563404150022055 0ustar ryanryan# # $Id: api.txt,v 1.3 2001/01/02 18:46:20 mleisher Exp $ # The MUTT UCData API ------------------- #### NOTE: This library has been customized for use with OpenLDAP. The character data tables are hardcoded into the library and the load/unload/reload functions are no-ops. Also, the MUTT API claimed to be compatible with John Cowan's library but its ucnumber behavior was broken. This has been fixed in the OpenLDAP release. By default, the implementation specific properties in MUTTUCData.txt are not incorporated into the OpenLDAP build. You can supply them to ucgendat and recreate uctable.h if you need them. -- hyc@openldap.org #### ----------------------------------------------------------------------------- Macros that combine to select data tables for ucdata_load(), ucdata_unload(), and ucdata_reload(). #define UCDATA_CASE 0x01 #define UCDATA_CTYPE 0x02 #define UCDATA_DECOMP 0x04 #define UCDATA_CMBCL 0x08 #define UCDATA_NUM 0x10 #define UCDATA_COMP 0x20 #define UCATA_ALL (UCDATA_CASE|UCDATA_CTYPE|UCDATA_DECOMP|\ UCDATA_CMBCL|UCDATA_NUM|UCDATA_COMP) ----------------------------------------------------------------------------- void ucdata_load(char *paths, int masks) This function initializes the UCData library by locating the data files in one of the colon-separated directories in the `paths' parameter. The data files to be loaded are specified in the `masks' parameter as a bitwise combination of the macros listed above. This should be called before using any of the other functions. NOTE: the ucdata_setup(char *paths) function is now a macro that expands into this function at compile time. ----------------------------------------------------------------------------- void ucdata_unload(int masks) This function unloads the data tables specified in the `masks' parameter. This function should be called when the application is done using the UCData package. NOTE: the ucdata_cleanup() function is now a macro that expands into this function at compile time. ----------------------------------------------------------------------------- void ucdata_reload(char *paths, int masks) This function reloads the data files from one of the colon-separated directories in the `paths' parameter. The data files to be reloaded are specified in the `masks' parameter as a bitwise combination of the macros listed above. If the data files have already been loaded, they are unloaded before the data files are loaded again. ----------------------------------------------------------------------------- int ucdecomp(unsigned long code, unsigned long *num, unsigned long **decomp) This function determines if a character has a decomposition and returns the decomposition information if it exists. If a zero is returned, there is no decomposition. If a non-zero is returned, then the `num' and `decomp' variables are filled in with the appropriate values. Example call: unsigned long i, num, *decomp; if (ucdecomp(0x1d5, &num, &decomp) != 0) { for (i = 0; i < num; i++) printf("0x%08lX,", decomp[i]); putchar('\n'); } int uccanondecomp(const unsigned long *in, int inlen, unsigned long **out, int *outlen) This function decomposes an input string and does canonical reordering of the characters at the same time. If a -1 is returned, memory allocation was not successful. If a zero is returned, no decomposition occured. Any other value means the output string contains the fully decomposed string in canonical order. If the "outlen" parameter comes back with a value > 0, then the string returned in the "out" parameter needs to be deallocated by the caller. ----------------------------------------------------------------------------- int ucdecomp_hangul(unsigned long code, unsigned long *num, unsigned long decomp[]) This function determines if a Hangul syllable has a decomposition and returns the decomposition information. An array of at least size 3 should be passed to the function for the decomposition of the syllable. If a zero is returned, the character is not a Hangul syllable. If a non-zero is returned, the `num' field will be 2 or 3 and the syllable will be decomposed into the `decomp' array arithmetically. Example call: unsigned long i, num, decomp[3]; if (ucdecomp_hangul(0xb1ba, &num, &decomp) != 0) { for (i = 0; i < num; i++) printf("0x%08lX,", decomp[i]); putchar('\n'); } ----------------------------------------------------------------------------- int uccomp(unsigned long ch1, unsigned long ch2, unsigned long *comp) This function takes a pair of characters and determines if they combine to form another character. If a zero is returned, no composition is formed by the character pair. Any other value indicates the "comp" parameter has a value. int uccomp_hangul(unsigned long *str, int len) This function composes the Hangul Jamo in the string. The composition is done in-place. The return value provides the new length of the string. This will be smaller than "len" if compositions occured. int uccanoncomp(unsigned long *str, int len) This function does a canonical composition of characters in the string. The return value is the new length of the string. ----------------------------------------------------------------------------- struct ucnumber { int numerator; int denominator; }; int ucnumber_lookup(unsigned long code, struct ucnumber *num) This function determines if the code is a number and fills in the `num' field with the numerator and denominator. If the code happens to be a single digit, the denominator field will be 1. #### The original code would set numerator = denominator for regular digits. However, the Readme also claimed to be compatible with John Cowan's uctype library, but this behavior is both nonsensical and incompatible with the Cowan library. As such, it has been fixed here as described above. -- hyc@openldap.org #### If the function returns 0, the code is not a number. Any other return value means the code is a number. int ucdigit_lookup(unsigned long code, int *digit) This function determines if the code is a digit and fills in the `digit' field with the digit value. If the function returns 0, the code is not a number. Any other return value means the code is a number. struct ucnumber ucgetnumber(unsigned long code) This is a compatibility function with John Cowan's "uctype" package. It uses ucnumber_lookup(). int ucgetdigit(unsigned long code) This is a compatibility function with John Cowan's "uctype" package. It uses ucdigit_lookup(). ----------------------------------------------------------------------------- unsigned long uctoupper(unsigned long code) This function returns the code unchanged if it is already upper case or has no upper case equivalent. Otherwise the upper case equivalent is returned. ----------------------------------------------------------------------------- unsigned long uctolower(unsigned long code) This function returns the code unchanged if it is already lower case or has no lower case equivalent. Otherwise the lower case equivalent is returned. ----------------------------------------------------------------------------- unsigned long uctotitle(unsigned long code) This function returns the code unchanged if it is already title case or has no title case equivalent. Otherwise the title case equivalent is returned. ----------------------------------------------------------------------------- int ucisalpha(unsigned long code) int ucisalnum(unsigned long code) int ucisdigit(unsigned long code) int uciscntrl(unsigned long code) int ucisspace(unsigned long code) int ucisblank(unsigned long code) int ucispunct(unsigned long code) int ucisgraph(unsigned long code) int ucisprint(unsigned long code) int ucisxdigit(unsigned long code) int ucisupper(unsigned long code) int ucislower(unsigned long code) int ucistitle(unsigned long code) These functions (actually macros) determine if a character has these properties. These behave in a fashion very similar to the venerable ctype package. ----------------------------------------------------------------------------- int ucisisocntrl(unsigned long code) Is the character a C0 control character (< 32) ? int ucisfmtcntrl(unsigned long code) Is the character a format control character? int ucissymbol(unsigned long code) Is the character a symbol? int ucisnumber(unsigned long code) Is the character a number or digit? int ucisnonspacing(unsigned long code) Is the character non-spacing? int ucisopenpunct(unsigned long code) Is the character an open/left punctuation (i.e. '[') int ucisclosepunct(unsigned long code) Is the character an close/right punctuation (i.e. ']') int ucisinitialpunct(unsigned long code) Is the character an initial punctuation (i.e. U+2018 LEFT SINGLE QUOTATION MARK) int ucisfinalpunct(unsigned long code) Is the character a final punctuation (i.e. U+2019 RIGHT SINGLE QUOTATION MARK) int uciscomposite(unsigned long code) Can the character be decomposed into a set of other characters? int ucisquote(unsigned long code) Is the character one of the many quotation marks? int ucissymmetric(unsigned long code) Is the character one that has an opposite form (i.e. <>) int ucismirroring(unsigned long code) Is the character mirroring (superset of symmetric)? int ucisnonbreaking(unsigned long code) Is the character non-breaking (i.e. non-breaking space)? int ucisrtl(unsigned long code) Does the character have strong right-to-left directionality (i.e. Arabic letters)? int ucisltr(unsigned long code) Does the character have strong left-to-right directionality (i.e. Latin letters)? int ucisstrong(unsigned long code) Does the character have strong directionality? int ucisweak(unsigned long code) Does the character have weak directionality (i.e. numbers)? int ucisneutral(unsigned long code) Does the character have neutral directionality (i.e. whitespace)? int ucisseparator(unsigned long code) Is the character a block or segment separator? int ucislsep(unsigned long code) Is the character a line separator? int ucispsep(unsigned long code) Is the character a paragraph separator? int ucismark(unsigned long code) Is the character a mark of some kind? int ucisnsmark(unsigned long code) Is the character a non-spacing mark? int ucisspmark(unsigned long code) Is the character a spacing mark? int ucismodif(unsigned long code) Is the character a modifier letter? int ucismodifsymbol(unsigned long code) Is the character a modifier symbol? int ucisletnum(unsigned long code) Is the character a number represented by a letter? int ucisconnect(unsigned long code) Is the character connecting punctuation? int ucisdash(unsigned long code) Is the character dash punctuation? int ucismath(unsigned long code) Is the character a math character? int uciscurrency(unsigned long code) Is the character a currency character? int ucisenclosing(unsigned long code) Is the character enclosing (i.e. enclosing box)? int ucisprivate(unsigned long code) Is the character from the Private Use Area? int ucissurrogate(unsigned long code) Is the character one of the surrogate codes? int ucisdefined(unsigned long code) Is the character defined (appeared in one of the data files)? int ucisundefined(unsigned long code) Is the character not defined (non-Unicode)? int ucishan(unsigned long code) Is the character a Han ideograph? int ucishangul(unsigned long code) Is the character a pre-composed Hangul syllable? openldap-2.4.42+dfsg/libraries/liblunicode/ucdata/uctable.h0000644000175000017500000175012412563432307022345 0ustar ryanryanstatic const ac_uint4 _ucprop_size = 50; static const ac_uint2 _ucprop_offsets[] = { 0x0000, 0x00d0, 0x0138, 0x0140, 0x016a, 0x0176, 0x019e, 0x01ac, 0x01ae, 0x01b0, 0x01b4, 0x01cc, 0x01ce, 0xffff, 0x01d4, 0x051a, 0x0862, 0x0876, 0x089e, 0x0a32, 0x0a40, 0x0a58, 0x0ad8, 0x0b54, 0x0be0, 0x0c54, 0x0c6a, 0x0c96, 0x0d66, 0x0fee, 0x100a, 0x1020, 0x1024, 0x1054, 0x1058, 0x106e, 0x1078, 0x107e, 0x108e, 0x1240, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x13e8, 0x16e4, 0x16ee, 0x16f6, 0x1720, 0x0000 }; static const ac_uint4 _ucprop_ranges[] = { 0x00000300, 0x0000034f, 0x00000360, 0x0000036f, 0x00000483, 0x00000486, 0x00000591, 0x000005a1, 0x000005a3, 0x000005b9, 0x000005bb, 0x000005bd, 0x000005bf, 0x000005bf, 0x000005c1, 0x000005c2, 0x000005c4, 0x000005c4, 0x0000064b, 0x00000655, 0x00000670, 0x00000670, 0x000006d6, 0x000006dc, 0x000006df, 0x000006e4, 0x000006e7, 0x000006e8, 0x000006ea, 0x000006ed, 0x00000711, 0x00000711, 0x00000730, 0x0000074a, 0x000007a6, 0x000007b0, 0x00000901, 0x00000902, 0x0000093c, 0x0000093c, 0x00000941, 0x00000948, 0x0000094d, 0x0000094d, 0x00000951, 0x00000954, 0x00000962, 0x00000963, 0x00000981, 0x00000981, 0x000009bc, 0x000009bc, 0x000009c1, 0x000009c4, 0x000009cd, 0x000009cd, 0x000009e2, 0x000009e3, 0x00000a02, 0x00000a02, 0x00000a3c, 0x00000a3c, 0x00000a41, 0x00000a42, 0x00000a47, 0x00000a48, 0x00000a4b, 0x00000a4d, 0x00000a70, 0x00000a71, 0x00000a81, 0x00000a82, 0x00000abc, 0x00000abc, 0x00000ac1, 0x00000ac5, 0x00000ac7, 0x00000ac8, 0x00000acd, 0x00000acd, 0x00000b01, 0x00000b01, 0x00000b3c, 0x00000b3c, 0x00000b3f, 0x00000b3f, 0x00000b41, 0x00000b43, 0x00000b4d, 0x00000b4d, 0x00000b56, 0x00000b56, 0x00000b82, 0x00000b82, 0x00000bc0, 0x00000bc0, 0x00000bcd, 0x00000bcd, 0x00000c3e, 0x00000c40, 0x00000c46, 0x00000c48, 0x00000c4a, 0x00000c4d, 0x00000c55, 0x00000c56, 0x00000cbf, 0x00000cbf, 0x00000cc6, 0x00000cc6, 0x00000ccc, 0x00000ccd, 0x00000d41, 0x00000d43, 0x00000d4d, 0x00000d4d, 0x00000dca, 0x00000dca, 0x00000dd2, 0x00000dd4, 0x00000dd6, 0x00000dd6, 0x00000e31, 0x00000e31, 0x00000e34, 0x00000e3a, 0x00000e47, 0x00000e4e, 0x00000eb1, 0x00000eb1, 0x00000eb4, 0x00000eb9, 0x00000ebb, 0x00000ebc, 0x00000ec8, 0x00000ecd, 0x00000f18, 0x00000f19, 0x00000f35, 0x00000f35, 0x00000f37, 0x00000f37, 0x00000f39, 0x00000f39, 0x00000f71, 0x00000f7e, 0x00000f80, 0x00000f84, 0x00000f86, 0x00000f87, 0x00000f90, 0x00000f97, 0x00000f99, 0x00000fbc, 0x00000fc6, 0x00000fc6, 0x0000102d, 0x00001030, 0x00001032, 0x00001032, 0x00001036, 0x00001037, 0x00001039, 0x00001039, 0x00001058, 0x00001059, 0x00001712, 0x00001714, 0x00001732, 0x00001734, 0x00001752, 0x00001753, 0x00001772, 0x00001773, 0x000017b7, 0x000017bd, 0x000017c6, 0x000017c6, 0x000017c9, 0x000017d3, 0x0000180b, 0x0000180d, 0x000018a9, 0x000018a9, 0x000020d0, 0x000020dc, 0x000020e1, 0x000020e1, 0x000020e5, 0x000020ea, 0x0000302a, 0x0000302f, 0x00003099, 0x0000309a, 0x0000fb1e, 0x0000fb1e, 0x0000fe00, 0x0000fe0f, 0x0000fe20, 0x0000fe23, 0x0001d167, 0x0001d169, 0x0001d17b, 0x0001d182, 0x0001d185, 0x0001d18b, 0x0001d1aa, 0x0001d1ad, 0x00000903, 0x00000903, 0x0000093e, 0x00000940, 0x00000949, 0x0000094c, 0x00000982, 0x00000983, 0x000009be, 0x000009c0, 0x000009c7, 0x000009c8, 0x000009cb, 0x000009cc, 0x000009d7, 0x000009d7, 0x00000a3e, 0x00000a40, 0x00000a83, 0x00000a83, 0x00000abe, 0x00000ac0, 0x00000ac9, 0x00000ac9, 0x00000acb, 0x00000acc, 0x00000b02, 0x00000b03, 0x00000b3e, 0x00000b3e, 0x00000b40, 0x00000b40, 0x00000b47, 0x00000b48, 0x00000b4b, 0x00000b4c, 0x00000b57, 0x00000b57, 0x00000bbe, 0x00000bbf, 0x00000bc1, 0x00000bc2, 0x00000bc6, 0x00000bc8, 0x00000bca, 0x00000bcc, 0x00000bd7, 0x00000bd7, 0x00000c01, 0x00000c03, 0x00000c41, 0x00000c44, 0x00000c82, 0x00000c83, 0x00000cbe, 0x00000cbe, 0x00000cc0, 0x00000cc4, 0x00000cc7, 0x00000cc8, 0x00000cca, 0x00000ccb, 0x00000cd5, 0x00000cd6, 0x00000d02, 0x00000d03, 0x00000d3e, 0x00000d40, 0x00000d46, 0x00000d48, 0x00000d4a, 0x00000d4c, 0x00000d57, 0x00000d57, 0x00000d82, 0x00000d83, 0x00000dcf, 0x00000dd1, 0x00000dd8, 0x00000ddf, 0x00000df2, 0x00000df3, 0x00000f3e, 0x00000f3f, 0x00000f7f, 0x00000f7f, 0x0000102c, 0x0000102c, 0x00001031, 0x00001031, 0x00001038, 0x00001038, 0x00001056, 0x00001057, 0x000017b4, 0x000017b6, 0x000017be, 0x000017c5, 0x000017c7, 0x000017c8, 0x0001d165, 0x0001d166, 0x0001d16d, 0x0001d172, 0x00000488, 0x00000489, 0x000006de, 0x000006de, 0x000020dd, 0x000020e0, 0x000020e2, 0x000020e4, 0x00000030, 0x00000039, 0x00000660, 0x00000669, 0x000006f0, 0x000006f9, 0x00000966, 0x0000096f, 0x000009e6, 0x000009ef, 0x00000a66, 0x00000a6f, 0x00000ae6, 0x00000aef, 0x00000b66, 0x00000b6f, 0x00000be7, 0x00000bef, 0x00000c66, 0x00000c6f, 0x00000ce6, 0x00000cef, 0x00000d66, 0x00000d6f, 0x00000e50, 0x00000e59, 0x00000ed0, 0x00000ed9, 0x00000f20, 0x00000f29, 0x00001040, 0x00001049, 0x00001369, 0x00001371, 0x000017e0, 0x000017e9, 0x00001810, 0x00001819, 0x0000ff10, 0x0000ff19, 0x0001d7ce, 0x0001d7ff, 0x000016ee, 0x000016f0, 0x00002160, 0x00002183, 0x00003007, 0x00003007, 0x00003021, 0x00003029, 0x00003038, 0x0000303a, 0x0001034a, 0x0001034a, 0x000000b2, 0x000000b3, 0x000000b9, 0x000000b9, 0x000000bc, 0x000000be, 0x000009f4, 0x000009f9, 0x00000bf0, 0x00000bf2, 0x00000f2a, 0x00000f33, 0x00001372, 0x0000137c, 0x00002070, 0x00002070, 0x00002074, 0x00002079, 0x00002080, 0x00002089, 0x00002153, 0x0000215f, 0x00002460, 0x0000249b, 0x000024ea, 0x000024fe, 0x00002776, 0x00002793, 0x00003192, 0x00003195, 0x00003220, 0x00003229, 0x00003251, 0x0000325f, 0x00003280, 0x00003289, 0x000032b1, 0x000032bf, 0x00010320, 0x00010323, 0x00000020, 0x00000020, 0x000000a0, 0x000000a0, 0x00001680, 0x00001680, 0x00002000, 0x0000200b, 0x0000202f, 0x0000202f, 0x0000205f, 0x0000205f, 0x00003000, 0x00003000, 0x00002028, 0x00002028, 0x00002029, 0x00002029, 0x00000000, 0x0000001f, 0x0000007f, 0x0000009f, 0x000006dd, 0x000006dd, 0x0000070f, 0x0000070f, 0x0000180e, 0x0000180e, 0x0000200c, 0x0000200f, 0x0000202a, 0x0000202e, 0x00002060, 0x00002063, 0x0000206a, 0x0000206f, 0x0000feff, 0x0000feff, 0x0000fff9, 0x0000fffb, 0x0001d173, 0x0001d17a, 0x000e0001, 0x000e0001, 0x000e0020, 0x000e007f, 0x00010000, 0x0010ffff, 0x0000e000, 0x0000f8ff, 0x000f0000, 0x000ffffd, 0x00100000, 0x0010fffd, 0x00000041, 0x0000005a, 0x000000c0, 0x000000d6, 0x000000d8, 0x000000de, 0x00000100, 0x00000100, 0x00000102, 0x00000102, 0x00000104, 0x00000104, 0x00000106, 0x00000106, 0x00000108, 0x00000108, 0x0000010a, 0x0000010a, 0x0000010c, 0x0000010c, 0x0000010e, 0x0000010e, 0x00000110, 0x00000110, 0x00000112, 0x00000112, 0x00000114, 0x00000114, 0x00000116, 0x00000116, 0x00000118, 0x00000118, 0x0000011a, 0x0000011a, 0x0000011c, 0x0000011c, 0x0000011e, 0x0000011e, 0x00000120, 0x00000120, 0x00000122, 0x00000122, 0x00000124, 0x00000124, 0x00000126, 0x00000126, 0x00000128, 0x00000128, 0x0000012a, 0x0000012a, 0x0000012c, 0x0000012c, 0x0000012e, 0x0000012e, 0x00000130, 0x00000130, 0x00000132, 0x00000132, 0x00000134, 0x00000134, 0x00000136, 0x00000136, 0x00000139, 0x00000139, 0x0000013b, 0x0000013b, 0x0000013d, 0x0000013d, 0x0000013f, 0x0000013f, 0x00000141, 0x00000141, 0x00000143, 0x00000143, 0x00000145, 0x00000145, 0x00000147, 0x00000147, 0x0000014a, 0x0000014a, 0x0000014c, 0x0000014c, 0x0000014e, 0x0000014e, 0x00000150, 0x00000150, 0x00000152, 0x00000152, 0x00000154, 0x00000154, 0x00000156, 0x00000156, 0x00000158, 0x00000158, 0x0000015a, 0x0000015a, 0x0000015c, 0x0000015c, 0x0000015e, 0x0000015e, 0x00000160, 0x00000160, 0x00000162, 0x00000162, 0x00000164, 0x00000164, 0x00000166, 0x00000166, 0x00000168, 0x00000168, 0x0000016a, 0x0000016a, 0x0000016c, 0x0000016c, 0x0000016e, 0x0000016e, 0x00000170, 0x00000170, 0x00000172, 0x00000172, 0x00000174, 0x00000174, 0x00000176, 0x00000176, 0x00000178, 0x00000179, 0x0000017b, 0x0000017b, 0x0000017d, 0x0000017d, 0x00000181, 0x00000182, 0x00000184, 0x00000184, 0x00000186, 0x00000187, 0x00000189, 0x0000018b, 0x0000018e, 0x00000191, 0x00000193, 0x00000194, 0x00000196, 0x00000198, 0x0000019c, 0x0000019d, 0x0000019f, 0x000001a0, 0x000001a2, 0x000001a2, 0x000001a4, 0x000001a4, 0x000001a6, 0x000001a7, 0x000001a9, 0x000001a9, 0x000001ac, 0x000001ac, 0x000001ae, 0x000001af, 0x000001b1, 0x000001b3, 0x000001b5, 0x000001b5, 0x000001b7, 0x000001b8, 0x000001bc, 0x000001bc, 0x000001c4, 0x000001c4, 0x000001c7, 0x000001c7, 0x000001ca, 0x000001ca, 0x000001cd, 0x000001cd, 0x000001cf, 0x000001cf, 0x000001d1, 0x000001d1, 0x000001d3, 0x000001d3, 0x000001d5, 0x000001d5, 0x000001d7, 0x000001d7, 0x000001d9, 0x000001d9, 0x000001db, 0x000001db, 0x000001de, 0x000001de, 0x000001e0, 0x000001e0, 0x000001e2, 0x000001e2, 0x000001e4, 0x000001e4, 0x000001e6, 0x000001e6, 0x000001e8, 0x000001e8, 0x000001ea, 0x000001ea, 0x000001ec, 0x000001ec, 0x000001ee, 0x000001ee, 0x000001f1, 0x000001f1, 0x000001f4, 0x000001f4, 0x000001f6, 0x000001f8, 0x000001fa, 0x000001fa, 0x000001fc, 0x000001fc, 0x000001fe, 0x000001fe, 0x00000200, 0x00000200, 0x00000202, 0x00000202, 0x00000204, 0x00000204, 0x00000206, 0x00000206, 0x00000208, 0x00000208, 0x0000020a, 0x0000020a, 0x0000020c, 0x0000020c, 0x0000020e, 0x0000020e, 0x00000210, 0x00000210, 0x00000212, 0x00000212, 0x00000214, 0x00000214, 0x00000216, 0x00000216, 0x00000218, 0x00000218, 0x0000021a, 0x0000021a, 0x0000021c, 0x0000021c, 0x0000021e, 0x0000021e, 0x00000220, 0x00000220, 0x00000222, 0x00000222, 0x00000224, 0x00000224, 0x00000226, 0x00000226, 0x00000228, 0x00000228, 0x0000022a, 0x0000022a, 0x0000022c, 0x0000022c, 0x0000022e, 0x0000022e, 0x00000230, 0x00000230, 0x00000232, 0x00000232, 0x00000386, 0x00000386, 0x00000388, 0x0000038a, 0x0000038c, 0x0000038c, 0x0000038e, 0x0000038f, 0x00000391, 0x000003a1, 0x000003a3, 0x000003ab, 0x000003d2, 0x000003d4, 0x000003d8, 0x000003d8, 0x000003da, 0x000003da, 0x000003dc, 0x000003dc, 0x000003de, 0x000003de, 0x000003e0, 0x000003e0, 0x000003e2, 0x000003e2, 0x000003e4, 0x000003e4, 0x000003e6, 0x000003e6, 0x000003e8, 0x000003e8, 0x000003ea, 0x000003ea, 0x000003ec, 0x000003ec, 0x000003ee, 0x000003ee, 0x000003f4, 0x000003f4, 0x00000400, 0x0000042f, 0x00000460, 0x00000460, 0x00000462, 0x00000462, 0x00000464, 0x00000464, 0x00000466, 0x00000466, 0x00000468, 0x00000468, 0x0000046a, 0x0000046a, 0x0000046c, 0x0000046c, 0x0000046e, 0x0000046e, 0x00000470, 0x00000470, 0x00000472, 0x00000472, 0x00000474, 0x00000474, 0x00000476, 0x00000476, 0x00000478, 0x00000478, 0x0000047a, 0x0000047a, 0x0000047c, 0x0000047c, 0x0000047e, 0x0000047e, 0x00000480, 0x00000480, 0x0000048a, 0x0000048a, 0x0000048c, 0x0000048c, 0x0000048e, 0x0000048e, 0x00000490, 0x00000490, 0x00000492, 0x00000492, 0x00000494, 0x00000494, 0x00000496, 0x00000496, 0x00000498, 0x00000498, 0x0000049a, 0x0000049a, 0x0000049c, 0x0000049c, 0x0000049e, 0x0000049e, 0x000004a0, 0x000004a0, 0x000004a2, 0x000004a2, 0x000004a4, 0x000004a4, 0x000004a6, 0x000004a6, 0x000004a8, 0x000004a8, 0x000004aa, 0x000004aa, 0x000004ac, 0x000004ac, 0x000004ae, 0x000004ae, 0x000004b0, 0x000004b0, 0x000004b2, 0x000004b2, 0x000004b4, 0x000004b4, 0x000004b6, 0x000004b6, 0x000004b8, 0x000004b8, 0x000004ba, 0x000004ba, 0x000004bc, 0x000004bc, 0x000004be, 0x000004be, 0x000004c0, 0x000004c1, 0x000004c3, 0x000004c3, 0x000004c5, 0x000004c5, 0x000004c7, 0x000004c7, 0x000004c9, 0x000004c9, 0x000004cb, 0x000004cb, 0x000004cd, 0x000004cd, 0x000004d0, 0x000004d0, 0x000004d2, 0x000004d2, 0x000004d4, 0x000004d4, 0x000004d6, 0x000004d6, 0x000004d8, 0x000004d8, 0x000004da, 0x000004da, 0x000004dc, 0x000004dc, 0x000004de, 0x000004de, 0x000004e0, 0x000004e0, 0x000004e2, 0x000004e2, 0x000004e4, 0x000004e4, 0x000004e6, 0x000004e6, 0x000004e8, 0x000004e8, 0x000004ea, 0x000004ea, 0x000004ec, 0x000004ec, 0x000004ee, 0x000004ee, 0x000004f0, 0x000004f0, 0x000004f2, 0x000004f2, 0x000004f4, 0x000004f4, 0x000004f8, 0x000004f8, 0x00000500, 0x00000500, 0x00000502, 0x00000502, 0x00000504, 0x00000504, 0x00000506, 0x00000506, 0x00000508, 0x00000508, 0x0000050a, 0x0000050a, 0x0000050c, 0x0000050c, 0x0000050e, 0x0000050e, 0x00000531, 0x00000556, 0x000010a0, 0x000010c5, 0x00001e00, 0x00001e00, 0x00001e02, 0x00001e02, 0x00001e04, 0x00001e04, 0x00001e06, 0x00001e06, 0x00001e08, 0x00001e08, 0x00001e0a, 0x00001e0a, 0x00001e0c, 0x00001e0c, 0x00001e0e, 0x00001e0e, 0x00001e10, 0x00001e10, 0x00001e12, 0x00001e12, 0x00001e14, 0x00001e14, 0x00001e16, 0x00001e16, 0x00001e18, 0x00001e18, 0x00001e1a, 0x00001e1a, 0x00001e1c, 0x00001e1c, 0x00001e1e, 0x00001e1e, 0x00001e20, 0x00001e20, 0x00001e22, 0x00001e22, 0x00001e24, 0x00001e24, 0x00001e26, 0x00001e26, 0x00001e28, 0x00001e28, 0x00001e2a, 0x00001e2a, 0x00001e2c, 0x00001e2c, 0x00001e2e, 0x00001e2e, 0x00001e30, 0x00001e30, 0x00001e32, 0x00001e32, 0x00001e34, 0x00001e34, 0x00001e36, 0x00001e36, 0x00001e38, 0x00001e38, 0x00001e3a, 0x00001e3a, 0x00001e3c, 0x00001e3c, 0x00001e3e, 0x00001e3e, 0x00001e40, 0x00001e40, 0x00001e42, 0x00001e42, 0x00001e44, 0x00001e44, 0x00001e46, 0x00001e46, 0x00001e48, 0x00001e48, 0x00001e4a, 0x00001e4a, 0x00001e4c, 0x00001e4c, 0x00001e4e, 0x00001e4e, 0x00001e50, 0x00001e50, 0x00001e52, 0x00001e52, 0x00001e54, 0x00001e54, 0x00001e56, 0x00001e56, 0x00001e58, 0x00001e58, 0x00001e5a, 0x00001e5a, 0x00001e5c, 0x00001e5c, 0x00001e5e, 0x00001e5e, 0x00001e60, 0x00001e60, 0x00001e62, 0x00001e62, 0x00001e64, 0x00001e64, 0x00001e66, 0x00001e66, 0x00001e68, 0x00001e68, 0x00001e6a, 0x00001e6a, 0x00001e6c, 0x00001e6c, 0x00001e6e, 0x00001e6e, 0x00001e70, 0x00001e70, 0x00001e72, 0x00001e72, 0x00001e74, 0x00001e74, 0x00001e76, 0x00001e76, 0x00001e78, 0x00001e78, 0x00001e7a, 0x00001e7a, 0x00001e7c, 0x00001e7c, 0x00001e7e, 0x00001e7e, 0x00001e80, 0x00001e80, 0x00001e82, 0x00001e82, 0x00001e84, 0x00001e84, 0x00001e86, 0x00001e86, 0x00001e88, 0x00001e88, 0x00001e8a, 0x00001e8a, 0x00001e8c, 0x00001e8c, 0x00001e8e, 0x00001e8e, 0x00001e90, 0x00001e90, 0x00001e92, 0x00001e92, 0x00001e94, 0x00001e94, 0x00001ea0, 0x00001ea0, 0x00001ea2, 0x00001ea2, 0x00001ea4, 0x00001ea4, 0x00001ea6, 0x00001ea6, 0x00001ea8, 0x00001ea8, 0x00001eaa, 0x00001eaa, 0x00001eac, 0x00001eac, 0x00001eae, 0x00001eae, 0x00001eb0, 0x00001eb0, 0x00001eb2, 0x00001eb2, 0x00001eb4, 0x00001eb4, 0x00001eb6, 0x00001eb6, 0x00001eb8, 0x00001eb8, 0x00001eba, 0x00001eba, 0x00001ebc, 0x00001ebc, 0x00001ebe, 0x00001ebe, 0x00001ec0, 0x00001ec0, 0x00001ec2, 0x00001ec2, 0x00001ec4, 0x00001ec4, 0x00001ec6, 0x00001ec6, 0x00001ec8, 0x00001ec8, 0x00001eca, 0x00001eca, 0x00001ecc, 0x00001ecc, 0x00001ece, 0x00001ece, 0x00001ed0, 0x00001ed0, 0x00001ed2, 0x00001ed2, 0x00001ed4, 0x00001ed4, 0x00001ed6, 0x00001ed6, 0x00001ed8, 0x00001ed8, 0x00001eda, 0x00001eda, 0x00001edc, 0x00001edc, 0x00001ede, 0x00001ede, 0x00001ee0, 0x00001ee0, 0x00001ee2, 0x00001ee2, 0x00001ee4, 0x00001ee4, 0x00001ee6, 0x00001ee6, 0x00001ee8, 0x00001ee8, 0x00001eea, 0x00001eea, 0x00001eec, 0x00001eec, 0x00001eee, 0x00001eee, 0x00001ef0, 0x00001ef0, 0x00001ef2, 0x00001ef2, 0x00001ef4, 0x00001ef4, 0x00001ef6, 0x00001ef6, 0x00001ef8, 0x00001ef8, 0x00001f08, 0x00001f0f, 0x00001f18, 0x00001f1d, 0x00001f28, 0x00001f2f, 0x00001f38, 0x00001f3f, 0x00001f48, 0x00001f4d, 0x00001f59, 0x00001f59, 0x00001f5b, 0x00001f5b, 0x00001f5d, 0x00001f5d, 0x00001f5f, 0x00001f5f, 0x00001f68, 0x00001f6f, 0x00001fb8, 0x00001fbb, 0x00001fc8, 0x00001fcb, 0x00001fd8, 0x00001fdb, 0x00001fe8, 0x00001fec, 0x00001ff8, 0x00001ffb, 0x00002102, 0x00002102, 0x00002107, 0x00002107, 0x0000210b, 0x0000210d, 0x00002110, 0x00002112, 0x00002115, 0x00002115, 0x00002119, 0x0000211d, 0x00002124, 0x00002124, 0x00002126, 0x00002126, 0x00002128, 0x00002128, 0x0000212a, 0x0000212d, 0x00002130, 0x00002131, 0x00002133, 0x00002133, 0x0000213e, 0x0000213f, 0x00002145, 0x00002145, 0x0000ff21, 0x0000ff3a, 0x00010400, 0x00010425, 0x0001d400, 0x0001d419, 0x0001d434, 0x0001d44d, 0x0001d468, 0x0001d481, 0x0001d49c, 0x0001d49c, 0x0001d49e, 0x0001d49f, 0x0001d4a2, 0x0001d4a2, 0x0001d4a5, 0x0001d4a6, 0x0001d4a9, 0x0001d4ac, 0x0001d4ae, 0x0001d4b5, 0x0001d4d0, 0x0001d4e9, 0x0001d504, 0x0001d505, 0x0001d507, 0x0001d50a, 0x0001d50d, 0x0001d514, 0x0001d516, 0x0001d51c, 0x0001d538, 0x0001d539, 0x0001d53b, 0x0001d53e, 0x0001d540, 0x0001d544, 0x0001d546, 0x0001d546, 0x0001d54a, 0x0001d550, 0x0001d56c, 0x0001d585, 0x0001d5a0, 0x0001d5b9, 0x0001d5d4, 0x0001d5ed, 0x0001d608, 0x0001d621, 0x0001d63c, 0x0001d655, 0x0001d670, 0x0001d689, 0x0001d6a8, 0x0001d6c0, 0x0001d6e2, 0x0001d6fa, 0x0001d71c, 0x0001d734, 0x0001d756, 0x0001d76e, 0x0001d790, 0x0001d7a8, 0x00000061, 0x0000007a, 0x000000aa, 0x000000aa, 0x000000b5, 0x000000b5, 0x000000ba, 0x000000ba, 0x000000df, 0x000000f6, 0x000000f8, 0x000000ff, 0x00000101, 0x00000101, 0x00000103, 0x00000103, 0x00000105, 0x00000105, 0x00000107, 0x00000107, 0x00000109, 0x00000109, 0x0000010b, 0x0000010b, 0x0000010d, 0x0000010d, 0x0000010f, 0x0000010f, 0x00000111, 0x00000111, 0x00000113, 0x00000113, 0x00000115, 0x00000115, 0x00000117, 0x00000117, 0x00000119, 0x00000119, 0x0000011b, 0x0000011b, 0x0000011d, 0x0000011d, 0x0000011f, 0x0000011f, 0x00000121, 0x00000121, 0x00000123, 0x00000123, 0x00000125, 0x00000125, 0x00000127, 0x00000127, 0x00000129, 0x00000129, 0x0000012b, 0x0000012b, 0x0000012d, 0x0000012d, 0x0000012f, 0x0000012f, 0x00000131, 0x00000131, 0x00000133, 0x00000133, 0x00000135, 0x00000135, 0x00000137, 0x00000138, 0x0000013a, 0x0000013a, 0x0000013c, 0x0000013c, 0x0000013e, 0x0000013e, 0x00000140, 0x00000140, 0x00000142, 0x00000142, 0x00000144, 0x00000144, 0x00000146, 0x00000146, 0x00000148, 0x00000149, 0x0000014b, 0x0000014b, 0x0000014d, 0x0000014d, 0x0000014f, 0x0000014f, 0x00000151, 0x00000151, 0x00000153, 0x00000153, 0x00000155, 0x00000155, 0x00000157, 0x00000157, 0x00000159, 0x00000159, 0x0000015b, 0x0000015b, 0x0000015d, 0x0000015d, 0x0000015f, 0x0000015f, 0x00000161, 0x00000161, 0x00000163, 0x00000163, 0x00000165, 0x00000165, 0x00000167, 0x00000167, 0x00000169, 0x00000169, 0x0000016b, 0x0000016b, 0x0000016d, 0x0000016d, 0x0000016f, 0x0000016f, 0x00000171, 0x00000171, 0x00000173, 0x00000173, 0x00000175, 0x00000175, 0x00000177, 0x00000177, 0x0000017a, 0x0000017a, 0x0000017c, 0x0000017c, 0x0000017e, 0x00000180, 0x00000183, 0x00000183, 0x00000185, 0x00000185, 0x00000188, 0x00000188, 0x0000018c, 0x0000018d, 0x00000192, 0x00000192, 0x00000195, 0x00000195, 0x00000199, 0x0000019b, 0x0000019e, 0x0000019e, 0x000001a1, 0x000001a1, 0x000001a3, 0x000001a3, 0x000001a5, 0x000001a5, 0x000001a8, 0x000001a8, 0x000001aa, 0x000001ab, 0x000001ad, 0x000001ad, 0x000001b0, 0x000001b0, 0x000001b4, 0x000001b4, 0x000001b6, 0x000001b6, 0x000001b9, 0x000001ba, 0x000001bd, 0x000001bf, 0x000001c6, 0x000001c6, 0x000001c9, 0x000001c9, 0x000001cc, 0x000001cc, 0x000001ce, 0x000001ce, 0x000001d0, 0x000001d0, 0x000001d2, 0x000001d2, 0x000001d4, 0x000001d4, 0x000001d6, 0x000001d6, 0x000001d8, 0x000001d8, 0x000001da, 0x000001da, 0x000001dc, 0x000001dd, 0x000001df, 0x000001df, 0x000001e1, 0x000001e1, 0x000001e3, 0x000001e3, 0x000001e5, 0x000001e5, 0x000001e7, 0x000001e7, 0x000001e9, 0x000001e9, 0x000001eb, 0x000001eb, 0x000001ed, 0x000001ed, 0x000001ef, 0x000001f0, 0x000001f3, 0x000001f3, 0x000001f5, 0x000001f5, 0x000001f9, 0x000001f9, 0x000001fb, 0x000001fb, 0x000001fd, 0x000001fd, 0x000001ff, 0x000001ff, 0x00000201, 0x00000201, 0x00000203, 0x00000203, 0x00000205, 0x00000205, 0x00000207, 0x00000207, 0x00000209, 0x00000209, 0x0000020b, 0x0000020b, 0x0000020d, 0x0000020d, 0x0000020f, 0x0000020f, 0x00000211, 0x00000211, 0x00000213, 0x00000213, 0x00000215, 0x00000215, 0x00000217, 0x00000217, 0x00000219, 0x00000219, 0x0000021b, 0x0000021b, 0x0000021d, 0x0000021d, 0x0000021f, 0x0000021f, 0x00000223, 0x00000223, 0x00000225, 0x00000225, 0x00000227, 0x00000227, 0x00000229, 0x00000229, 0x0000022b, 0x0000022b, 0x0000022d, 0x0000022d, 0x0000022f, 0x0000022f, 0x00000231, 0x00000231, 0x00000233, 0x00000233, 0x00000250, 0x000002ad, 0x00000390, 0x00000390, 0x000003ac, 0x000003ce, 0x000003d0, 0x000003d1, 0x000003d5, 0x000003d7, 0x000003d9, 0x000003d9, 0x000003db, 0x000003db, 0x000003dd, 0x000003dd, 0x000003df, 0x000003df, 0x000003e1, 0x000003e1, 0x000003e3, 0x000003e3, 0x000003e5, 0x000003e5, 0x000003e7, 0x000003e7, 0x000003e9, 0x000003e9, 0x000003eb, 0x000003eb, 0x000003ed, 0x000003ed, 0x000003ef, 0x000003f3, 0x000003f5, 0x000003f5, 0x00000430, 0x0000045f, 0x00000461, 0x00000461, 0x00000463, 0x00000463, 0x00000465, 0x00000465, 0x00000467, 0x00000467, 0x00000469, 0x00000469, 0x0000046b, 0x0000046b, 0x0000046d, 0x0000046d, 0x0000046f, 0x0000046f, 0x00000471, 0x00000471, 0x00000473, 0x00000473, 0x00000475, 0x00000475, 0x00000477, 0x00000477, 0x00000479, 0x00000479, 0x0000047b, 0x0000047b, 0x0000047d, 0x0000047d, 0x0000047f, 0x0000047f, 0x00000481, 0x00000481, 0x0000048b, 0x0000048b, 0x0000048d, 0x0000048d, 0x0000048f, 0x0000048f, 0x00000491, 0x00000491, 0x00000493, 0x00000493, 0x00000495, 0x00000495, 0x00000497, 0x00000497, 0x00000499, 0x00000499, 0x0000049b, 0x0000049b, 0x0000049d, 0x0000049d, 0x0000049f, 0x0000049f, 0x000004a1, 0x000004a1, 0x000004a3, 0x000004a3, 0x000004a5, 0x000004a5, 0x000004a7, 0x000004a7, 0x000004a9, 0x000004a9, 0x000004ab, 0x000004ab, 0x000004ad, 0x000004ad, 0x000004af, 0x000004af, 0x000004b1, 0x000004b1, 0x000004b3, 0x000004b3, 0x000004b5, 0x000004b5, 0x000004b7, 0x000004b7, 0x000004b9, 0x000004b9, 0x000004bb, 0x000004bb, 0x000004bd, 0x000004bd, 0x000004bf, 0x000004bf, 0x000004c2, 0x000004c2, 0x000004c4, 0x000004c4, 0x000004c6, 0x000004c6, 0x000004c8, 0x000004c8, 0x000004ca, 0x000004ca, 0x000004cc, 0x000004cc, 0x000004ce, 0x000004ce, 0x000004d1, 0x000004d1, 0x000004d3, 0x000004d3, 0x000004d5, 0x000004d5, 0x000004d7, 0x000004d7, 0x000004d9, 0x000004d9, 0x000004db, 0x000004db, 0x000004dd, 0x000004dd, 0x000004df, 0x000004df, 0x000004e1, 0x000004e1, 0x000004e3, 0x000004e3, 0x000004e5, 0x000004e5, 0x000004e7, 0x000004e7, 0x000004e9, 0x000004e9, 0x000004eb, 0x000004eb, 0x000004ed, 0x000004ed, 0x000004ef, 0x000004ef, 0x000004f1, 0x000004f1, 0x000004f3, 0x000004f3, 0x000004f5, 0x000004f5, 0x000004f9, 0x000004f9, 0x00000501, 0x00000501, 0x00000503, 0x00000503, 0x00000505, 0x00000505, 0x00000507, 0x00000507, 0x00000509, 0x00000509, 0x0000050b, 0x0000050b, 0x0000050d, 0x0000050d, 0x0000050f, 0x0000050f, 0x00000561, 0x00000587, 0x00001e01, 0x00001e01, 0x00001e03, 0x00001e03, 0x00001e05, 0x00001e05, 0x00001e07, 0x00001e07, 0x00001e09, 0x00001e09, 0x00001e0b, 0x00001e0b, 0x00001e0d, 0x00001e0d, 0x00001e0f, 0x00001e0f, 0x00001e11, 0x00001e11, 0x00001e13, 0x00001e13, 0x00001e15, 0x00001e15, 0x00001e17, 0x00001e17, 0x00001e19, 0x00001e19, 0x00001e1b, 0x00001e1b, 0x00001e1d, 0x00001e1d, 0x00001e1f, 0x00001e1f, 0x00001e21, 0x00001e21, 0x00001e23, 0x00001e23, 0x00001e25, 0x00001e25, 0x00001e27, 0x00001e27, 0x00001e29, 0x00001e29, 0x00001e2b, 0x00001e2b, 0x00001e2d, 0x00001e2d, 0x00001e2f, 0x00001e2f, 0x00001e31, 0x00001e31, 0x00001e33, 0x00001e33, 0x00001e35, 0x00001e35, 0x00001e37, 0x00001e37, 0x00001e39, 0x00001e39, 0x00001e3b, 0x00001e3b, 0x00001e3d, 0x00001e3d, 0x00001e3f, 0x00001e3f, 0x00001e41, 0x00001e41, 0x00001e43, 0x00001e43, 0x00001e45, 0x00001e45, 0x00001e47, 0x00001e47, 0x00001e49, 0x00001e49, 0x00001e4b, 0x00001e4b, 0x00001e4d, 0x00001e4d, 0x00001e4f, 0x00001e4f, 0x00001e51, 0x00001e51, 0x00001e53, 0x00001e53, 0x00001e55, 0x00001e55, 0x00001e57, 0x00001e57, 0x00001e59, 0x00001e59, 0x00001e5b, 0x00001e5b, 0x00001e5d, 0x00001e5d, 0x00001e5f, 0x00001e5f, 0x00001e61, 0x00001e61, 0x00001e63, 0x00001e63, 0x00001e65, 0x00001e65, 0x00001e67, 0x00001e67, 0x00001e69, 0x00001e69, 0x00001e6b, 0x00001e6b, 0x00001e6d, 0x00001e6d, 0x00001e6f, 0x00001e6f, 0x00001e71, 0x00001e71, 0x00001e73, 0x00001e73, 0x00001e75, 0x00001e75, 0x00001e77, 0x00001e77, 0x00001e79, 0x00001e79, 0x00001e7b, 0x00001e7b, 0x00001e7d, 0x00001e7d, 0x00001e7f, 0x00001e7f, 0x00001e81, 0x00001e81, 0x00001e83, 0x00001e83, 0x00001e85, 0x00001e85, 0x00001e87, 0x00001e87, 0x00001e89, 0x00001e89, 0x00001e8b, 0x00001e8b, 0x00001e8d, 0x00001e8d, 0x00001e8f, 0x00001e8f, 0x00001e91, 0x00001e91, 0x00001e93, 0x00001e93, 0x00001e95, 0x00001e9b, 0x00001ea1, 0x00001ea1, 0x00001ea3, 0x00001ea3, 0x00001ea5, 0x00001ea5, 0x00001ea7, 0x00001ea7, 0x00001ea9, 0x00001ea9, 0x00001eab, 0x00001eab, 0x00001ead, 0x00001ead, 0x00001eaf, 0x00001eaf, 0x00001eb1, 0x00001eb1, 0x00001eb3, 0x00001eb3, 0x00001eb5, 0x00001eb5, 0x00001eb7, 0x00001eb7, 0x00001eb9, 0x00001eb9, 0x00001ebb, 0x00001ebb, 0x00001ebd, 0x00001ebd, 0x00001ebf, 0x00001ebf, 0x00001ec1, 0x00001ec1, 0x00001ec3, 0x00001ec3, 0x00001ec5, 0x00001ec5, 0x00001ec7, 0x00001ec7, 0x00001ec9, 0x00001ec9, 0x00001ecb, 0x00001ecb, 0x00001ecd, 0x00001ecd, 0x00001ecf, 0x00001ecf, 0x00001ed1, 0x00001ed1, 0x00001ed3, 0x00001ed3, 0x00001ed5, 0x00001ed5, 0x00001ed7, 0x00001ed7, 0x00001ed9, 0x00001ed9, 0x00001edb, 0x00001edb, 0x00001edd, 0x00001edd, 0x00001edf, 0x00001edf, 0x00001ee1, 0x00001ee1, 0x00001ee3, 0x00001ee3, 0x00001ee5, 0x00001ee5, 0x00001ee7, 0x00001ee7, 0x00001ee9, 0x00001ee9, 0x00001eeb, 0x00001eeb, 0x00001eed, 0x00001eed, 0x00001eef, 0x00001eef, 0x00001ef1, 0x00001ef1, 0x00001ef3, 0x00001ef3, 0x00001ef5, 0x00001ef5, 0x00001ef7, 0x00001ef7, 0x00001ef9, 0x00001ef9, 0x00001f00, 0x00001f07, 0x00001f10, 0x00001f15, 0x00001f20, 0x00001f27, 0x00001f30, 0x00001f37, 0x00001f40, 0x00001f45, 0x00001f50, 0x00001f57, 0x00001f60, 0x00001f67, 0x00001f70, 0x00001f7d, 0x00001f80, 0x00001f87, 0x00001f90, 0x00001f97, 0x00001fa0, 0x00001fa7, 0x00001fb0, 0x00001fb4, 0x00001fb6, 0x00001fb7, 0x00001fbe, 0x00001fbe, 0x00001fc2, 0x00001fc4, 0x00001fc6, 0x00001fc7, 0x00001fd0, 0x00001fd3, 0x00001fd6, 0x00001fd7, 0x00001fe0, 0x00001fe7, 0x00001ff2, 0x00001ff4, 0x00001ff6, 0x00001ff7, 0x00002071, 0x00002071, 0x0000207f, 0x0000207f, 0x0000210a, 0x0000210a, 0x0000210e, 0x0000210f, 0x00002113, 0x00002113, 0x0000212f, 0x0000212f, 0x00002134, 0x00002134, 0x00002139, 0x00002139, 0x0000213d, 0x0000213d, 0x00002146, 0x00002149, 0x0000fb00, 0x0000fb06, 0x0000fb13, 0x0000fb17, 0x0000ff41, 0x0000ff5a, 0x00010428, 0x0001044d, 0x0001d41a, 0x0001d433, 0x0001d44e, 0x0001d454, 0x0001d456, 0x0001d467, 0x0001d482, 0x0001d49b, 0x0001d4b6, 0x0001d4b9, 0x0001d4bb, 0x0001d4bb, 0x0001d4bd, 0x0001d4c0, 0x0001d4c2, 0x0001d4c3, 0x0001d4c5, 0x0001d4cf, 0x0001d4ea, 0x0001d503, 0x0001d51e, 0x0001d537, 0x0001d552, 0x0001d56b, 0x0001d586, 0x0001d59f, 0x0001d5ba, 0x0001d5d3, 0x0001d5ee, 0x0001d607, 0x0001d622, 0x0001d63b, 0x0001d656, 0x0001d66f, 0x0001d68a, 0x0001d6a3, 0x0001d6c2, 0x0001d6da, 0x0001d6dc, 0x0001d6e1, 0x0001d6fc, 0x0001d714, 0x0001d716, 0x0001d71b, 0x0001d736, 0x0001d74e, 0x0001d750, 0x0001d755, 0x0001d770, 0x0001d788, 0x0001d78a, 0x0001d78f, 0x0001d7aa, 0x0001d7c2, 0x0001d7c4, 0x0001d7c9, 0x000001c5, 0x000001c5, 0x000001c8, 0x000001c8, 0x000001cb, 0x000001cb, 0x000001f2, 0x000001f2, 0x00001f88, 0x00001f8f, 0x00001f98, 0x00001f9f, 0x00001fa8, 0x00001faf, 0x00001fbc, 0x00001fbc, 0x00001fcc, 0x00001fcc, 0x00001ffc, 0x00001ffc, 0x000002b0, 0x000002b8, 0x000002bb, 0x000002c1, 0x000002d0, 0x000002d1, 0x000002e0, 0x000002e4, 0x000002ee, 0x000002ee, 0x0000037a, 0x0000037a, 0x00000559, 0x00000559, 0x00000640, 0x00000640, 0x000006e5, 0x000006e6, 0x00000e46, 0x00000e46, 0x00000ec6, 0x00000ec6, 0x000017d7, 0x000017d7, 0x00001843, 0x00001843, 0x00003005, 0x00003005, 0x00003031, 0x00003035, 0x0000303b, 0x0000303b, 0x0000309d, 0x0000309e, 0x000030fc, 0x000030fe, 0x0000ff70, 0x0000ff70, 0x0000ff9e, 0x0000ff9f, 0x000001bb, 0x000001bb, 0x000001c0, 0x000001c3, 0x000005d0, 0x000005ea, 0x000005f0, 0x000005f2, 0x00000621, 0x0000063a, 0x00000641, 0x0000064a, 0x0000066e, 0x0000066f, 0x00000671, 0x000006d3, 0x000006d5, 0x000006d5, 0x000006fa, 0x000006fc, 0x00000710, 0x00000710, 0x00000712, 0x0000072c, 0x00000780, 0x000007a5, 0x000007b1, 0x000007b1, 0x00000905, 0x00000939, 0x0000093d, 0x0000093d, 0x00000950, 0x00000950, 0x00000958, 0x00000961, 0x00000985, 0x0000098c, 0x0000098f, 0x00000990, 0x00000993, 0x000009a8, 0x000009aa, 0x000009b0, 0x000009b2, 0x000009b2, 0x000009b6, 0x000009b9, 0x000009dc, 0x000009dd, 0x000009df, 0x000009e1, 0x000009f0, 0x000009f1, 0x00000a05, 0x00000a0a, 0x00000a0f, 0x00000a10, 0x00000a13, 0x00000a28, 0x00000a2a, 0x00000a30, 0x00000a32, 0x00000a33, 0x00000a35, 0x00000a36, 0x00000a38, 0x00000a39, 0x00000a59, 0x00000a5c, 0x00000a5e, 0x00000a5e, 0x00000a72, 0x00000a74, 0x00000a85, 0x00000a8b, 0x00000a8d, 0x00000a8d, 0x00000a8f, 0x00000a91, 0x00000a93, 0x00000aa8, 0x00000aaa, 0x00000ab0, 0x00000ab2, 0x00000ab3, 0x00000ab5, 0x00000ab9, 0x00000abd, 0x00000abd, 0x00000ad0, 0x00000ad0, 0x00000ae0, 0x00000ae0, 0x00000b05, 0x00000b0c, 0x00000b0f, 0x00000b10, 0x00000b13, 0x00000b28, 0x00000b2a, 0x00000b30, 0x00000b32, 0x00000b33, 0x00000b36, 0x00000b39, 0x00000b3d, 0x00000b3d, 0x00000b5c, 0x00000b5d, 0x00000b5f, 0x00000b61, 0x00000b83, 0x00000b83, 0x00000b85, 0x00000b8a, 0x00000b8e, 0x00000b90, 0x00000b92, 0x00000b95, 0x00000b99, 0x00000b9a, 0x00000b9c, 0x00000b9c, 0x00000b9e, 0x00000b9f, 0x00000ba3, 0x00000ba4, 0x00000ba8, 0x00000baa, 0x00000bae, 0x00000bb5, 0x00000bb7, 0x00000bb9, 0x00000c05, 0x00000c0c, 0x00000c0e, 0x00000c10, 0x00000c12, 0x00000c28, 0x00000c2a, 0x00000c33, 0x00000c35, 0x00000c39, 0x00000c60, 0x00000c61, 0x00000c85, 0x00000c8c, 0x00000c8e, 0x00000c90, 0x00000c92, 0x00000ca8, 0x00000caa, 0x00000cb3, 0x00000cb5, 0x00000cb9, 0x00000cde, 0x00000cde, 0x00000ce0, 0x00000ce1, 0x00000d05, 0x00000d0c, 0x00000d0e, 0x00000d10, 0x00000d12, 0x00000d28, 0x00000d2a, 0x00000d39, 0x00000d60, 0x00000d61, 0x00000d85, 0x00000d96, 0x00000d9a, 0x00000db1, 0x00000db3, 0x00000dbb, 0x00000dbd, 0x00000dbd, 0x00000dc0, 0x00000dc6, 0x00000e01, 0x00000e30, 0x00000e32, 0x00000e33, 0x00000e40, 0x00000e45, 0x00000e81, 0x00000e82, 0x00000e84, 0x00000e84, 0x00000e87, 0x00000e88, 0x00000e8a, 0x00000e8a, 0x00000e8d, 0x00000e8d, 0x00000e94, 0x00000e97, 0x00000e99, 0x00000e9f, 0x00000ea1, 0x00000ea3, 0x00000ea5, 0x00000ea5, 0x00000ea7, 0x00000ea7, 0x00000eaa, 0x00000eab, 0x00000ead, 0x00000eb0, 0x00000eb2, 0x00000eb3, 0x00000ebd, 0x00000ebd, 0x00000ec0, 0x00000ec4, 0x00000edc, 0x00000edd, 0x00000f00, 0x00000f00, 0x00000f40, 0x00000f47, 0x00000f49, 0x00000f6a, 0x00000f88, 0x00000f8b, 0x00001000, 0x00001021, 0x00001023, 0x00001027, 0x00001029, 0x0000102a, 0x00001050, 0x00001055, 0x000010d0, 0x000010f8, 0x00001100, 0x00001159, 0x0000115f, 0x000011a2, 0x000011a8, 0x000011f9, 0x00001200, 0x00001206, 0x00001208, 0x00001246, 0x00001248, 0x00001248, 0x0000124a, 0x0000124d, 0x00001250, 0x00001256, 0x00001258, 0x00001258, 0x0000125a, 0x0000125d, 0x00001260, 0x00001286, 0x00001288, 0x00001288, 0x0000128a, 0x0000128d, 0x00001290, 0x000012ae, 0x000012b0, 0x000012b0, 0x000012b2, 0x000012b5, 0x000012b8, 0x000012be, 0x000012c0, 0x000012c0, 0x000012c2, 0x000012c5, 0x000012c8, 0x000012ce, 0x000012d0, 0x000012d6, 0x000012d8, 0x000012ee, 0x000012f0, 0x0000130e, 0x00001310, 0x00001310, 0x00001312, 0x00001315, 0x00001318, 0x0000131e, 0x00001320, 0x00001346, 0x00001348, 0x0000135a, 0x000013a0, 0x000013f4, 0x00001401, 0x0000166c, 0x0000166f, 0x00001676, 0x00001681, 0x0000169a, 0x000016a0, 0x000016ea, 0x00001700, 0x0000170c, 0x0000170e, 0x00001711, 0x00001720, 0x00001731, 0x00001740, 0x00001751, 0x00001760, 0x0000176c, 0x0000176e, 0x00001770, 0x00001780, 0x000017b3, 0x000017dc, 0x000017dc, 0x00001820, 0x00001842, 0x00001844, 0x00001877, 0x00001880, 0x000018a8, 0x00002135, 0x00002138, 0x00003006, 0x00003006, 0x0000303c, 0x0000303c, 0x00003041, 0x00003096, 0x0000309f, 0x0000309f, 0x000030a1, 0x000030fa, 0x000030ff, 0x000030ff, 0x00003105, 0x0000312c, 0x00003131, 0x0000318e, 0x000031a0, 0x000031b7, 0x000031f0, 0x000031ff, 0x00003400, 0x00004db5, 0x00004e00, 0x0000a48c, 0x0000ac00, 0x0000d7a3, 0x0000f900, 0x0000faff, 0x0000fb1d, 0x0000fb1d, 0x0000fb1f, 0x0000fb28, 0x0000fb2a, 0x0000fb36, 0x0000fb38, 0x0000fb3c, 0x0000fb3e, 0x0000fb3e, 0x0000fb40, 0x0000fb41, 0x0000fb43, 0x0000fb44, 0x0000fb46, 0x0000fbb1, 0x0000fbd3, 0x0000fd3d, 0x0000fd50, 0x0000fd8f, 0x0000fd92, 0x0000fdc7, 0x0000fdf0, 0x0000fdfb, 0x0000fe70, 0x0000fe74, 0x0000fe76, 0x0000fefc, 0x0000ff66, 0x0000ff6f, 0x0000ff71, 0x0000ff9d, 0x0000ffa0, 0x0000ffbe, 0x0000ffc2, 0x0000ffc7, 0x0000ffca, 0x0000ffcf, 0x0000ffd2, 0x0000ffd7, 0x0000ffda, 0x0000ffdc, 0x00010300, 0x0001031e, 0x00010330, 0x00010349, 0x00020000, 0x0002a6d6, 0x0002f800, 0x0002fa1d, 0x0000005f, 0x0000005f, 0x0000203f, 0x00002040, 0x000030fb, 0x000030fb, 0x0000fe33, 0x0000fe34, 0x0000fe4d, 0x0000fe4f, 0x0000ff3f, 0x0000ff3f, 0x0000ff65, 0x0000ff65, 0x0000002d, 0x0000002d, 0x000000ad, 0x000000ad, 0x0000058a, 0x0000058a, 0x00001806, 0x00001806, 0x00002010, 0x00002015, 0x0000301c, 0x0000301c, 0x00003030, 0x00003030, 0x000030a0, 0x000030a0, 0x0000fe31, 0x0000fe32, 0x0000fe58, 0x0000fe58, 0x0000fe63, 0x0000fe63, 0x0000ff0d, 0x0000ff0d, 0x00000028, 0x00000028, 0x0000005b, 0x0000005b, 0x0000007b, 0x0000007b, 0x00000f3a, 0x00000f3a, 0x00000f3c, 0x00000f3c, 0x0000169b, 0x0000169b, 0x0000201a, 0x0000201a, 0x0000201e, 0x0000201e, 0x00002045, 0x00002045, 0x0000207d, 0x0000207d, 0x0000208d, 0x0000208d, 0x00002329, 0x00002329, 0x000023b4, 0x000023b4, 0x00002768, 0x00002768, 0x0000276a, 0x0000276a, 0x0000276c, 0x0000276c, 0x0000276e, 0x0000276e, 0x00002770, 0x00002770, 0x00002772, 0x00002772, 0x00002774, 0x00002774, 0x000027e6, 0x000027e6, 0x000027e8, 0x000027e8, 0x000027ea, 0x000027ea, 0x00002983, 0x00002983, 0x00002985, 0x00002985, 0x00002987, 0x00002987, 0x00002989, 0x00002989, 0x0000298b, 0x0000298b, 0x0000298d, 0x0000298d, 0x0000298f, 0x0000298f, 0x00002991, 0x00002991, 0x00002993, 0x00002993, 0x00002995, 0x00002995, 0x00002997, 0x00002997, 0x000029d8, 0x000029d8, 0x000029da, 0x000029da, 0x000029fc, 0x000029fc, 0x00003008, 0x00003008, 0x0000300a, 0x0000300a, 0x0000300c, 0x0000300c, 0x0000300e, 0x0000300e, 0x00003010, 0x00003010, 0x00003014, 0x00003014, 0x00003016, 0x00003016, 0x00003018, 0x00003018, 0x0000301a, 0x0000301a, 0x0000301d, 0x0000301d, 0x0000fd3e, 0x0000fd3e, 0x0000fe35, 0x0000fe35, 0x0000fe37, 0x0000fe37, 0x0000fe39, 0x0000fe39, 0x0000fe3b, 0x0000fe3b, 0x0000fe3d, 0x0000fe3d, 0x0000fe3f, 0x0000fe3f, 0x0000fe41, 0x0000fe41, 0x0000fe43, 0x0000fe43, 0x0000fe59, 0x0000fe59, 0x0000fe5b, 0x0000fe5b, 0x0000fe5d, 0x0000fe5d, 0x0000ff08, 0x0000ff08, 0x0000ff3b, 0x0000ff3b, 0x0000ff5b, 0x0000ff5b, 0x0000ff5f, 0x0000ff5f, 0x0000ff62, 0x0000ff62, 0x00000029, 0x00000029, 0x0000005d, 0x0000005d, 0x0000007d, 0x0000007d, 0x00000f3b, 0x00000f3b, 0x00000f3d, 0x00000f3d, 0x0000169c, 0x0000169c, 0x00002046, 0x00002046, 0x0000207e, 0x0000207e, 0x0000208e, 0x0000208e, 0x0000232a, 0x0000232a, 0x000023b5, 0x000023b5, 0x00002769, 0x00002769, 0x0000276b, 0x0000276b, 0x0000276d, 0x0000276d, 0x0000276f, 0x0000276f, 0x00002771, 0x00002771, 0x00002773, 0x00002773, 0x00002775, 0x00002775, 0x000027e7, 0x000027e7, 0x000027e9, 0x000027e9, 0x000027eb, 0x000027eb, 0x00002984, 0x00002984, 0x00002986, 0x00002986, 0x00002988, 0x00002988, 0x0000298a, 0x0000298a, 0x0000298c, 0x0000298c, 0x0000298e, 0x0000298e, 0x00002990, 0x00002990, 0x00002992, 0x00002992, 0x00002994, 0x00002994, 0x00002996, 0x00002996, 0x00002998, 0x00002998, 0x000029d9, 0x000029d9, 0x000029db, 0x000029db, 0x000029fd, 0x000029fd, 0x00003009, 0x00003009, 0x0000300b, 0x0000300b, 0x0000300d, 0x0000300d, 0x0000300f, 0x0000300f, 0x00003011, 0x00003011, 0x00003015, 0x00003015, 0x00003017, 0x00003017, 0x00003019, 0x00003019, 0x0000301b, 0x0000301b, 0x0000301e, 0x0000301f, 0x0000fd3f, 0x0000fd3f, 0x0000fe36, 0x0000fe36, 0x0000fe38, 0x0000fe38, 0x0000fe3a, 0x0000fe3a, 0x0000fe3c, 0x0000fe3c, 0x0000fe3e, 0x0000fe3e, 0x0000fe40, 0x0000fe40, 0x0000fe42, 0x0000fe42, 0x0000fe44, 0x0000fe44, 0x0000fe5a, 0x0000fe5a, 0x0000fe5c, 0x0000fe5c, 0x0000fe5e, 0x0000fe5e, 0x0000ff09, 0x0000ff09, 0x0000ff3d, 0x0000ff3d, 0x0000ff5d, 0x0000ff5d, 0x0000ff60, 0x0000ff60, 0x0000ff63, 0x0000ff63, 0x00000021, 0x00000023, 0x00000025, 0x00000027, 0x0000002a, 0x0000002a, 0x0000002c, 0x0000002c, 0x0000002e, 0x0000002f, 0x0000003a, 0x0000003b, 0x0000003f, 0x00000040, 0x0000005c, 0x0000005c, 0x000000a1, 0x000000a1, 0x000000b7, 0x000000b7, 0x000000bf, 0x000000bf, 0x0000037e, 0x0000037e, 0x00000387, 0x00000387, 0x0000055a, 0x0000055f, 0x00000589, 0x00000589, 0x000005be, 0x000005be, 0x000005c0, 0x000005c0, 0x000005c3, 0x000005c3, 0x000005f3, 0x000005f4, 0x0000060c, 0x0000060c, 0x0000061b, 0x0000061b, 0x0000061f, 0x0000061f, 0x0000066a, 0x0000066d, 0x000006d4, 0x000006d4, 0x00000700, 0x0000070d, 0x00000964, 0x00000965, 0x00000970, 0x00000970, 0x00000df4, 0x00000df4, 0x00000e4f, 0x00000e4f, 0x00000e5a, 0x00000e5b, 0x00000f04, 0x00000f12, 0x00000f85, 0x00000f85, 0x0000104a, 0x0000104f, 0x000010fb, 0x000010fb, 0x00001361, 0x00001368, 0x0000166d, 0x0000166e, 0x000016eb, 0x000016ed, 0x00001735, 0x00001736, 0x000017d4, 0x000017d6, 0x000017d8, 0x000017da, 0x00001800, 0x00001805, 0x00001807, 0x0000180a, 0x00002016, 0x00002017, 0x00002020, 0x00002027, 0x00002030, 0x00002038, 0x0000203b, 0x0000203e, 0x00002041, 0x00002043, 0x00002047, 0x00002051, 0x00002057, 0x00002057, 0x000023b6, 0x000023b6, 0x00003001, 0x00003003, 0x0000303d, 0x0000303d, 0x0000fe30, 0x0000fe30, 0x0000fe45, 0x0000fe46, 0x0000fe49, 0x0000fe4c, 0x0000fe50, 0x0000fe52, 0x0000fe54, 0x0000fe57, 0x0000fe5f, 0x0000fe61, 0x0000fe68, 0x0000fe68, 0x0000fe6a, 0x0000fe6b, 0x0000ff01, 0x0000ff03, 0x0000ff05, 0x0000ff07, 0x0000ff0a, 0x0000ff0a, 0x0000ff0c, 0x0000ff0c, 0x0000ff0e, 0x0000ff0f, 0x0000ff1a, 0x0000ff1b, 0x0000ff1f, 0x0000ff20, 0x0000ff3c, 0x0000ff3c, 0x0000ff61, 0x0000ff61, 0x0000ff64, 0x0000ff64, 0x0000002b, 0x0000002b, 0x0000003c, 0x0000003e, 0x0000007c, 0x0000007c, 0x0000007e, 0x0000007e, 0x000000ac, 0x000000ac, 0x000000b1, 0x000000b1, 0x000000d7, 0x000000d7, 0x000000f7, 0x000000f7, 0x000003f6, 0x000003f6, 0x00002044, 0x00002044, 0x00002052, 0x00002052, 0x0000207a, 0x0000207c, 0x0000208a, 0x0000208c, 0x00002140, 0x00002144, 0x0000214b, 0x0000214b, 0x00002190, 0x00002194, 0x0000219a, 0x0000219b, 0x000021a0, 0x000021a0, 0x000021a3, 0x000021a3, 0x000021a6, 0x000021a6, 0x000021ae, 0x000021ae, 0x000021ce, 0x000021cf, 0x000021d2, 0x000021d2, 0x000021d4, 0x000021d4, 0x000021f4, 0x000022ff, 0x00002308, 0x0000230b, 0x00002320, 0x00002321, 0x0000237c, 0x0000237c, 0x0000239b, 0x000023b3, 0x000025b7, 0x000025b7, 0x000025c1, 0x000025c1, 0x000025f8, 0x000025ff, 0x0000266f, 0x0000266f, 0x000027d0, 0x000027e5, 0x000027f0, 0x000027ff, 0x00002900, 0x00002982, 0x00002999, 0x000029d7, 0x000029dc, 0x000029fb, 0x000029fe, 0x00002aff, 0x0000fb29, 0x0000fb29, 0x0000fe62, 0x0000fe62, 0x0000fe64, 0x0000fe66, 0x0000ff0b, 0x0000ff0b, 0x0000ff1c, 0x0000ff1e, 0x0000ff5c, 0x0000ff5c, 0x0000ff5e, 0x0000ff5e, 0x0000ffe2, 0x0000ffe2, 0x0000ffe9, 0x0000ffec, 0x0001d6c1, 0x0001d6c1, 0x0001d6db, 0x0001d6db, 0x0001d6fb, 0x0001d6fb, 0x0001d715, 0x0001d715, 0x0001d735, 0x0001d735, 0x0001d74f, 0x0001d74f, 0x0001d76f, 0x0001d76f, 0x0001d789, 0x0001d789, 0x0001d7a9, 0x0001d7a9, 0x0001d7c3, 0x0001d7c3, 0x00000024, 0x00000024, 0x000000a2, 0x000000a5, 0x000009f2, 0x000009f3, 0x00000e3f, 0x00000e3f, 0x000017db, 0x000017db, 0x000020a0, 0x000020b1, 0x0000fdfc, 0x0000fdfc, 0x0000fe69, 0x0000fe69, 0x0000ff04, 0x0000ff04, 0x0000ffe0, 0x0000ffe1, 0x0000ffe5, 0x0000ffe6, 0x0000005e, 0x0000005e, 0x00000060, 0x00000060, 0x000000a8, 0x000000a8, 0x000000af, 0x000000af, 0x000000b4, 0x000000b4, 0x000000b8, 0x000000b8, 0x000002b9, 0x000002ba, 0x000002c2, 0x000002cf, 0x000002d2, 0x000002df, 0x000002e5, 0x000002ed, 0x00000374, 0x00000375, 0x00000384, 0x00000385, 0x00001fbd, 0x00001fbd, 0x00001fbf, 0x00001fc1, 0x00001fcd, 0x00001fcf, 0x00001fdd, 0x00001fdf, 0x00001fed, 0x00001fef, 0x00001ffd, 0x00001ffe, 0x0000309b, 0x0000309c, 0x0000ff3e, 0x0000ff3e, 0x0000ff40, 0x0000ff40, 0x0000ffe3, 0x0000ffe3, 0x000000a6, 0x000000a7, 0x000000a9, 0x000000a9, 0x000000ae, 0x000000ae, 0x000000b0, 0x000000b0, 0x000000b6, 0x000000b6, 0x00000482, 0x00000482, 0x000006e9, 0x000006e9, 0x000006fd, 0x000006fe, 0x000009fa, 0x000009fa, 0x00000b70, 0x00000b70, 0x00000f01, 0x00000f03, 0x00000f13, 0x00000f17, 0x00000f1a, 0x00000f1f, 0x00000f34, 0x00000f34, 0x00000f36, 0x00000f36, 0x00000f38, 0x00000f38, 0x00000fbe, 0x00000fc5, 0x00000fc7, 0x00000fcc, 0x00000fcf, 0x00000fcf, 0x00002100, 0x00002101, 0x00002103, 0x00002106, 0x00002108, 0x00002109, 0x00002114, 0x00002114, 0x00002116, 0x00002118, 0x0000211e, 0x00002123, 0x00002125, 0x00002125, 0x00002127, 0x00002127, 0x00002129, 0x00002129, 0x0000212e, 0x0000212e, 0x00002132, 0x00002132, 0x0000213a, 0x0000213a, 0x0000214a, 0x0000214a, 0x00002195, 0x00002199, 0x0000219c, 0x0000219f, 0x000021a1, 0x000021a2, 0x000021a4, 0x000021a5, 0x000021a7, 0x000021ad, 0x000021af, 0x000021cd, 0x000021d0, 0x000021d1, 0x000021d3, 0x000021d3, 0x000021d5, 0x000021f3, 0x00002300, 0x00002307, 0x0000230c, 0x0000231f, 0x00002322, 0x00002328, 0x0000232b, 0x0000237b, 0x0000237d, 0x0000239a, 0x000023b7, 0x000023ce, 0x00002400, 0x00002426, 0x00002440, 0x0000244a, 0x0000249c, 0x000024e9, 0x00002500, 0x000025b6, 0x000025b8, 0x000025c0, 0x000025c2, 0x000025f7, 0x00002600, 0x00002613, 0x00002616, 0x00002617, 0x00002619, 0x0000266e, 0x00002670, 0x0000267d, 0x00002680, 0x00002689, 0x00002701, 0x00002704, 0x00002706, 0x00002709, 0x0000270c, 0x00002727, 0x00002729, 0x0000274b, 0x0000274d, 0x0000274d, 0x0000274f, 0x00002752, 0x00002756, 0x00002756, 0x00002758, 0x0000275e, 0x00002761, 0x00002767, 0x00002794, 0x00002794, 0x00002798, 0x000027af, 0x000027b1, 0x000027be, 0x00002800, 0x000028ff, 0x00002e80, 0x00002e99, 0x00002e9b, 0x00002ef3, 0x00002f00, 0x00002fd5, 0x00002ff0, 0x00002ffb, 0x00003004, 0x00003004, 0x00003012, 0x00003013, 0x00003020, 0x00003020, 0x00003036, 0x00003037, 0x0000303e, 0x0000303f, 0x00003190, 0x00003191, 0x00003196, 0x0000319f, 0x00003200, 0x0000321c, 0x0000322a, 0x00003243, 0x00003260, 0x0000327b, 0x0000327f, 0x0000327f, 0x0000328a, 0x000032b0, 0x000032c0, 0x000032cb, 0x000032d0, 0x000032fe, 0x00003300, 0x00003376, 0x0000337b, 0x000033dd, 0x000033e0, 0x000033fe, 0x0000a490, 0x0000a4c6, 0x0000ffe4, 0x0000ffe4, 0x0000ffe8, 0x0000ffe8, 0x0000ffed, 0x0000ffee, 0x0000fffc, 0x0000fffd, 0x0001d000, 0x0001d0f5, 0x0001d100, 0x0001d126, 0x0001d12a, 0x0001d164, 0x0001d16a, 0x0001d16c, 0x0001d183, 0x0001d184, 0x0001d18c, 0x0001d1a9, 0x0001d1ae, 0x0001d1dd, 0x00000041, 0x0000005a, 0x00000061, 0x0000007a, 0x000000aa, 0x000000aa, 0x000000b5, 0x000000b5, 0x000000ba, 0x000000ba, 0x000000c0, 0x000000d6, 0x000000d8, 0x000000f6, 0x000000f8, 0x00000220, 0x00000222, 0x00000233, 0x00000250, 0x000002ad, 0x000002b0, 0x000002b8, 0x000002bb, 0x000002c1, 0x000002d0, 0x000002d1, 0x000002e0, 0x000002e4, 0x000002ee, 0x000002ee, 0x0000037a, 0x0000037a, 0x00000386, 0x00000386, 0x00000388, 0x0000038a, 0x0000038c, 0x0000038c, 0x0000038e, 0x000003a1, 0x000003a3, 0x000003ce, 0x000003d0, 0x000003f5, 0x00000400, 0x00000482, 0x0000048a, 0x000004ce, 0x000004d0, 0x000004f5, 0x000004f8, 0x000004f9, 0x00000500, 0x0000050f, 0x00000531, 0x00000556, 0x00000559, 0x0000055f, 0x00000561, 0x00000587, 0x00000589, 0x00000589, 0x00000903, 0x00000903, 0x00000905, 0x00000939, 0x0000093d, 0x00000940, 0x00000949, 0x0000094c, 0x00000950, 0x00000950, 0x00000958, 0x00000961, 0x00000964, 0x00000970, 0x00000982, 0x00000983, 0x00000985, 0x0000098c, 0x0000098f, 0x00000990, 0x00000993, 0x000009a8, 0x000009aa, 0x000009b0, 0x000009b2, 0x000009b2, 0x000009b6, 0x000009b9, 0x000009be, 0x000009c0, 0x000009c7, 0x000009c8, 0x000009cb, 0x000009cc, 0x000009d7, 0x000009d7, 0x000009dc, 0x000009dd, 0x000009df, 0x000009e1, 0x000009e6, 0x000009f1, 0x000009f4, 0x000009fa, 0x00000a05, 0x00000a0a, 0x00000a0f, 0x00000a10, 0x00000a13, 0x00000a28, 0x00000a2a, 0x00000a30, 0x00000a32, 0x00000a33, 0x00000a35, 0x00000a36, 0x00000a38, 0x00000a39, 0x00000a3e, 0x00000a40, 0x00000a59, 0x00000a5c, 0x00000a5e, 0x00000a5e, 0x00000a66, 0x00000a6f, 0x00000a72, 0x00000a74, 0x00000a83, 0x00000a83, 0x00000a85, 0x00000a8b, 0x00000a8d, 0x00000a8d, 0x00000a8f, 0x00000a91, 0x00000a93, 0x00000aa8, 0x00000aaa, 0x00000ab0, 0x00000ab2, 0x00000ab3, 0x00000ab5, 0x00000ab9, 0x00000abd, 0x00000ac0, 0x00000ac9, 0x00000ac9, 0x00000acb, 0x00000acc, 0x00000ad0, 0x00000ad0, 0x00000ae0, 0x00000ae0, 0x00000ae6, 0x00000aef, 0x00000b02, 0x00000b03, 0x00000b05, 0x00000b0c, 0x00000b0f, 0x00000b10, 0x00000b13, 0x00000b28, 0x00000b2a, 0x00000b30, 0x00000b32, 0x00000b33, 0x00000b36, 0x00000b39, 0x00000b3d, 0x00000b3e, 0x00000b40, 0x00000b40, 0x00000b47, 0x00000b48, 0x00000b4b, 0x00000b4c, 0x00000b57, 0x00000b57, 0x00000b5c, 0x00000b5d, 0x00000b5f, 0x00000b61, 0x00000b66, 0x00000b70, 0x00000b83, 0x00000b83, 0x00000b85, 0x00000b8a, 0x00000b8e, 0x00000b90, 0x00000b92, 0x00000b95, 0x00000b99, 0x00000b9a, 0x00000b9c, 0x00000b9c, 0x00000b9e, 0x00000b9f, 0x00000ba3, 0x00000ba4, 0x00000ba8, 0x00000baa, 0x00000bae, 0x00000bb5, 0x00000bb7, 0x00000bb9, 0x00000bbe, 0x00000bbf, 0x00000bc1, 0x00000bc2, 0x00000bc6, 0x00000bc8, 0x00000bca, 0x00000bcc, 0x00000bd7, 0x00000bd7, 0x00000be7, 0x00000bf2, 0x00000c01, 0x00000c03, 0x00000c05, 0x00000c0c, 0x00000c0e, 0x00000c10, 0x00000c12, 0x00000c28, 0x00000c2a, 0x00000c33, 0x00000c35, 0x00000c39, 0x00000c41, 0x00000c44, 0x00000c60, 0x00000c61, 0x00000c66, 0x00000c6f, 0x00000c82, 0x00000c83, 0x00000c85, 0x00000c8c, 0x00000c8e, 0x00000c90, 0x00000c92, 0x00000ca8, 0x00000caa, 0x00000cb3, 0x00000cb5, 0x00000cb9, 0x00000cbe, 0x00000cbe, 0x00000cc0, 0x00000cc4, 0x00000cc7, 0x00000cc8, 0x00000cca, 0x00000ccb, 0x00000cd5, 0x00000cd6, 0x00000cde, 0x00000cde, 0x00000ce0, 0x00000ce1, 0x00000ce6, 0x00000cef, 0x00000d02, 0x00000d03, 0x00000d05, 0x00000d0c, 0x00000d0e, 0x00000d10, 0x00000d12, 0x00000d28, 0x00000d2a, 0x00000d39, 0x00000d3e, 0x00000d40, 0x00000d46, 0x00000d48, 0x00000d4a, 0x00000d4c, 0x00000d57, 0x00000d57, 0x00000d60, 0x00000d61, 0x00000d66, 0x00000d6f, 0x00000d82, 0x00000d83, 0x00000d85, 0x00000d96, 0x00000d9a, 0x00000db1, 0x00000db3, 0x00000dbb, 0x00000dbd, 0x00000dbd, 0x00000dc0, 0x00000dc6, 0x00000dcf, 0x00000dd1, 0x00000dd8, 0x00000ddf, 0x00000df2, 0x00000df4, 0x00000e01, 0x00000e30, 0x00000e32, 0x00000e33, 0x00000e40, 0x00000e46, 0x00000e4f, 0x00000e5b, 0x00000e81, 0x00000e82, 0x00000e84, 0x00000e84, 0x00000e87, 0x00000e88, 0x00000e8a, 0x00000e8a, 0x00000e8d, 0x00000e8d, 0x00000e94, 0x00000e97, 0x00000e99, 0x00000e9f, 0x00000ea1, 0x00000ea3, 0x00000ea5, 0x00000ea5, 0x00000ea7, 0x00000ea7, 0x00000eaa, 0x00000eab, 0x00000ead, 0x00000eb0, 0x00000eb2, 0x00000eb3, 0x00000ebd, 0x00000ebd, 0x00000ec0, 0x00000ec4, 0x00000ec6, 0x00000ec6, 0x00000ed0, 0x00000ed9, 0x00000edc, 0x00000edd, 0x00000f00, 0x00000f17, 0x00000f1a, 0x00000f34, 0x00000f36, 0x00000f36, 0x00000f38, 0x00000f38, 0x00000f3e, 0x00000f47, 0x00000f49, 0x00000f6a, 0x00000f7f, 0x00000f7f, 0x00000f85, 0x00000f85, 0x00000f88, 0x00000f8b, 0x00000fbe, 0x00000fc5, 0x00000fc7, 0x00000fcc, 0x00000fcf, 0x00000fcf, 0x00001000, 0x00001021, 0x00001023, 0x00001027, 0x00001029, 0x0000102a, 0x0000102c, 0x0000102c, 0x00001031, 0x00001031, 0x00001038, 0x00001038, 0x00001040, 0x00001057, 0x000010a0, 0x000010c5, 0x000010d0, 0x000010f8, 0x000010fb, 0x000010fb, 0x00001100, 0x00001159, 0x0000115f, 0x000011a2, 0x000011a8, 0x000011f9, 0x00001200, 0x00001206, 0x00001208, 0x00001246, 0x00001248, 0x00001248, 0x0000124a, 0x0000124d, 0x00001250, 0x00001256, 0x00001258, 0x00001258, 0x0000125a, 0x0000125d, 0x00001260, 0x00001286, 0x00001288, 0x00001288, 0x0000128a, 0x0000128d, 0x00001290, 0x000012ae, 0x000012b0, 0x000012b0, 0x000012b2, 0x000012b5, 0x000012b8, 0x000012be, 0x000012c0, 0x000012c0, 0x000012c2, 0x000012c5, 0x000012c8, 0x000012ce, 0x000012d0, 0x000012d6, 0x000012d8, 0x000012ee, 0x000012f0, 0x0000130e, 0x00001310, 0x00001310, 0x00001312, 0x00001315, 0x00001318, 0x0000131e, 0x00001320, 0x00001346, 0x00001348, 0x0000135a, 0x00001361, 0x0000137c, 0x000013a0, 0x000013f4, 0x00001401, 0x00001676, 0x00001681, 0x0000169a, 0x000016a0, 0x000016f0, 0x00001700, 0x0000170c, 0x0000170e, 0x00001711, 0x00001720, 0x00001731, 0x00001735, 0x00001736, 0x00001740, 0x00001751, 0x00001760, 0x0000176c, 0x0000176e, 0x00001770, 0x00001780, 0x000017b6, 0x000017be, 0x000017c5, 0x000017c7, 0x000017c8, 0x000017d4, 0x000017da, 0x000017dc, 0x000017dc, 0x000017e0, 0x000017e9, 0x00001810, 0x00001819, 0x00001820, 0x00001877, 0x00001880, 0x000018a8, 0x00001e00, 0x00001e9b, 0x00001ea0, 0x00001ef9, 0x00001f00, 0x00001f15, 0x00001f18, 0x00001f1d, 0x00001f20, 0x00001f45, 0x00001f48, 0x00001f4d, 0x00001f50, 0x00001f57, 0x00001f59, 0x00001f59, 0x00001f5b, 0x00001f5b, 0x00001f5d, 0x00001f5d, 0x00001f5f, 0x00001f7d, 0x00001f80, 0x00001fb4, 0x00001fb6, 0x00001fbc, 0x00001fbe, 0x00001fbe, 0x00001fc2, 0x00001fc4, 0x00001fc6, 0x00001fcc, 0x00001fd0, 0x00001fd3, 0x00001fd6, 0x00001fdb, 0x00001fe0, 0x00001fec, 0x00001ff2, 0x00001ff4, 0x00001ff6, 0x00001ffc, 0x0000200e, 0x0000200e, 0x00002071, 0x00002071, 0x0000207f, 0x0000207f, 0x00002102, 0x00002102, 0x00002107, 0x00002107, 0x0000210a, 0x00002113, 0x00002115, 0x00002115, 0x00002119, 0x0000211d, 0x00002124, 0x00002124, 0x00002126, 0x00002126, 0x00002128, 0x00002128, 0x0000212a, 0x0000212d, 0x0000212f, 0x00002131, 0x00002133, 0x00002139, 0x0000213d, 0x0000213f, 0x00002145, 0x00002149, 0x00002160, 0x00002183, 0x00002336, 0x0000237a, 0x00002395, 0x00002395, 0x0000249c, 0x000024e9, 0x00003005, 0x00003007, 0x00003021, 0x00003029, 0x00003031, 0x00003035, 0x00003038, 0x0000303c, 0x00003041, 0x00003096, 0x0000309d, 0x0000309f, 0x000030a1, 0x000030fa, 0x000030fc, 0x000030ff, 0x00003105, 0x0000312c, 0x00003131, 0x0000318e, 0x00003190, 0x000031b7, 0x000031f0, 0x0000321c, 0x00003220, 0x00003243, 0x00003260, 0x0000327b, 0x0000327f, 0x000032b0, 0x000032c0, 0x000032cb, 0x000032d0, 0x000032fe, 0x00003300, 0x00003376, 0x0000337b, 0x000033dd, 0x000033e0, 0x000033fe, 0x00003400, 0x00004db5, 0x00004e00, 0x0000a48c, 0x0000ac00, 0x0000d7a3, 0x0000e000, 0x0000fb06, 0x0000fb13, 0x0000fb17, 0x0000ff21, 0x0000ff3a, 0x0000ff41, 0x0000ff5a, 0x0000ff66, 0x0000ffbe, 0x0000ffc2, 0x0000ffc7, 0x0000ffca, 0x0000ffcf, 0x0000ffd2, 0x0000ffd7, 0x0000ffda, 0x0000ffdc, 0x00010000, 0x0002a6d6, 0x0002f800, 0x0002fa1d, 0x000f0000, 0x000ffffd, 0x00100000, 0x0010fffd, 0x000005be, 0x000005be, 0x000005c0, 0x000005c0, 0x000005c3, 0x000005c3, 0x000005d0, 0x000005ea, 0x000005f0, 0x000005f4, 0x0000200f, 0x0000200f, 0x0000fb1d, 0x0000fb1d, 0x0000fb1f, 0x0000fb28, 0x0000fb2a, 0x0000fb36, 0x0000fb38, 0x0000fb3c, 0x0000fb3e, 0x0000fb3e, 0x0000fb40, 0x0000fb41, 0x0000fb43, 0x0000fb44, 0x0000fb46, 0x0000fb4f, 0x00000030, 0x00000039, 0x000000b2, 0x000000b3, 0x000000b9, 0x000000b9, 0x000006f0, 0x000006f9, 0x00002070, 0x00002070, 0x00002074, 0x00002079, 0x00002080, 0x00002089, 0x00002460, 0x0000249b, 0x000024ea, 0x000024ea, 0x0000ff10, 0x0000ff19, 0x0001d7ce, 0x0001d7ff, 0x0000002f, 0x0000002f, 0x0000ff0f, 0x0000ff0f, 0x00000023, 0x00000025, 0x0000002b, 0x0000002b, 0x0000002d, 0x0000002d, 0x000000a2, 0x000000a5, 0x000000b0, 0x000000b1, 0x0000066a, 0x0000066a, 0x000009f2, 0x000009f3, 0x00000e3f, 0x00000e3f, 0x000017db, 0x000017db, 0x00002030, 0x00002034, 0x0000207a, 0x0000207b, 0x0000208a, 0x0000208b, 0x000020a0, 0x000020b1, 0x0000212e, 0x0000212e, 0x00002212, 0x00002213, 0x0000fb29, 0x0000fb29, 0x0000fe5f, 0x0000fe5f, 0x0000fe62, 0x0000fe63, 0x0000fe69, 0x0000fe6a, 0x0000ff03, 0x0000ff05, 0x0000ff0b, 0x0000ff0b, 0x0000ff0d, 0x0000ff0d, 0x0000ffe0, 0x0000ffe1, 0x0000ffe5, 0x0000ffe6, 0x00000660, 0x00000669, 0x0000066b, 0x0000066c, 0x0000002c, 0x0000002c, 0x0000002e, 0x0000002e, 0x0000003a, 0x0000003a, 0x000000a0, 0x000000a0, 0x0000060c, 0x0000060c, 0x0000fe50, 0x0000fe50, 0x0000fe52, 0x0000fe52, 0x0000fe55, 0x0000fe55, 0x0000ff0c, 0x0000ff0c, 0x0000ff0e, 0x0000ff0e, 0x0000ff1a, 0x0000ff1a, 0x0000000a, 0x0000000a, 0x0000000d, 0x0000000d, 0x0000001c, 0x0000001e, 0x00000085, 0x00000085, 0x00002029, 0x00002029, 0x00000009, 0x00000009, 0x0000000b, 0x0000000b, 0x0000001f, 0x0000001f, 0x0000000c, 0x0000000c, 0x00000020, 0x00000020, 0x00001680, 0x00001680, 0x00002000, 0x0000200a, 0x00002028, 0x00002028, 0x0000202f, 0x0000202f, 0x0000205f, 0x0000205f, 0x00003000, 0x00003000, 0x00000000, 0x00000008, 0x0000000e, 0x0000001b, 0x00000021, 0x00000022, 0x00000026, 0x0000002a, 0x0000003b, 0x00000040, 0x0000005b, 0x00000060, 0x0000007b, 0x00000084, 0x00000086, 0x0000009f, 0x000000a1, 0x000000a1, 0x000000a6, 0x000000a9, 0x000000ab, 0x000000af, 0x000000b4, 0x000000b4, 0x000000b6, 0x000000b8, 0x000000bb, 0x000000bf, 0x000000d7, 0x000000d7, 0x000000f7, 0x000000f7, 0x000002b9, 0x000002ba, 0x000002c2, 0x000002cf, 0x000002d2, 0x000002df, 0x000002e5, 0x000002ed, 0x00000300, 0x0000034f, 0x00000360, 0x0000036f, 0x00000374, 0x00000375, 0x0000037e, 0x0000037e, 0x00000384, 0x00000385, 0x00000387, 0x00000387, 0x000003f6, 0x000003f6, 0x00000483, 0x00000486, 0x00000488, 0x00000489, 0x0000058a, 0x0000058a, 0x00000591, 0x000005a1, 0x000005a3, 0x000005b9, 0x000005bb, 0x000005bd, 0x000005bf, 0x000005bf, 0x000005c1, 0x000005c2, 0x000005c4, 0x000005c4, 0x0000064b, 0x00000655, 0x00000670, 0x00000670, 0x000006d6, 0x000006dc, 0x000006de, 0x000006e4, 0x000006e7, 0x000006ed, 0x0000070f, 0x0000070f, 0x00000711, 0x00000711, 0x00000730, 0x0000074a, 0x000007a6, 0x000007b0, 0x00000901, 0x00000902, 0x0000093c, 0x0000093c, 0x00000941, 0x00000948, 0x0000094d, 0x0000094d, 0x00000951, 0x00000954, 0x00000962, 0x00000963, 0x00000981, 0x00000981, 0x000009bc, 0x000009bc, 0x000009c1, 0x000009c4, 0x000009cd, 0x000009cd, 0x000009e2, 0x000009e3, 0x00000a02, 0x00000a02, 0x00000a3c, 0x00000a3c, 0x00000a41, 0x00000a42, 0x00000a47, 0x00000a48, 0x00000a4b, 0x00000a4d, 0x00000a70, 0x00000a71, 0x00000a81, 0x00000a82, 0x00000abc, 0x00000abc, 0x00000ac1, 0x00000ac5, 0x00000ac7, 0x00000ac8, 0x00000acd, 0x00000acd, 0x00000b01, 0x00000b01, 0x00000b3c, 0x00000b3c, 0x00000b3f, 0x00000b3f, 0x00000b41, 0x00000b43, 0x00000b4d, 0x00000b4d, 0x00000b56, 0x00000b56, 0x00000b82, 0x00000b82, 0x00000bc0, 0x00000bc0, 0x00000bcd, 0x00000bcd, 0x00000c3e, 0x00000c40, 0x00000c46, 0x00000c48, 0x00000c4a, 0x00000c4d, 0x00000c55, 0x00000c56, 0x00000cbf, 0x00000cbf, 0x00000cc6, 0x00000cc6, 0x00000ccc, 0x00000ccd, 0x00000d41, 0x00000d43, 0x00000d4d, 0x00000d4d, 0x00000dca, 0x00000dca, 0x00000dd2, 0x00000dd4, 0x00000dd6, 0x00000dd6, 0x00000e31, 0x00000e31, 0x00000e34, 0x00000e3a, 0x00000e47, 0x00000e4e, 0x00000eb1, 0x00000eb1, 0x00000eb4, 0x00000eb9, 0x00000ebb, 0x00000ebc, 0x00000ec8, 0x00000ecd, 0x00000f18, 0x00000f19, 0x00000f35, 0x00000f35, 0x00000f37, 0x00000f37, 0x00000f39, 0x00000f3d, 0x00000f71, 0x00000f7e, 0x00000f80, 0x00000f84, 0x00000f86, 0x00000f87, 0x00000f90, 0x00000f97, 0x00000f99, 0x00000fbc, 0x00000fc6, 0x00000fc6, 0x0000102d, 0x00001030, 0x00001032, 0x00001032, 0x00001036, 0x00001037, 0x00001039, 0x00001039, 0x00001058, 0x00001059, 0x0000169b, 0x0000169c, 0x00001712, 0x00001714, 0x00001732, 0x00001734, 0x00001752, 0x00001753, 0x00001772, 0x00001773, 0x000017b7, 0x000017bd, 0x000017c6, 0x000017c6, 0x000017c9, 0x000017d3, 0x00001800, 0x0000180e, 0x000018a9, 0x000018a9, 0x00001fbd, 0x00001fbd, 0x00001fbf, 0x00001fc1, 0x00001fcd, 0x00001fcf, 0x00001fdd, 0x00001fdf, 0x00001fed, 0x00001fef, 0x00001ffd, 0x00001ffe, 0x0000200b, 0x0000200d, 0x00002010, 0x00002027, 0x0000202a, 0x0000202e, 0x00002035, 0x00002052, 0x00002057, 0x00002057, 0x00002060, 0x00002063, 0x0000206a, 0x0000206f, 0x0000207c, 0x0000207e, 0x0000208c, 0x0000208e, 0x000020d0, 0x000020ea, 0x00002100, 0x00002101, 0x00002103, 0x00002106, 0x00002108, 0x00002109, 0x00002114, 0x00002114, 0x00002116, 0x00002118, 0x0000211e, 0x00002123, 0x00002125, 0x00002125, 0x00002127, 0x00002127, 0x00002129, 0x00002129, 0x00002132, 0x00002132, 0x0000213a, 0x0000213a, 0x00002140, 0x00002144, 0x0000214a, 0x0000214b, 0x00002153, 0x0000215f, 0x00002190, 0x00002211, 0x00002214, 0x00002335, 0x0000237b, 0x00002394, 0x00002396, 0x000023ce, 0x00002400, 0x00002426, 0x00002440, 0x0000244a, 0x000024eb, 0x000024fe, 0x00002500, 0x00002613, 0x00002616, 0x00002617, 0x00002619, 0x0000267d, 0x00002680, 0x00002689, 0x00002701, 0x00002704, 0x00002706, 0x00002709, 0x0000270c, 0x00002727, 0x00002729, 0x0000274b, 0x0000274d, 0x0000274d, 0x0000274f, 0x00002752, 0x00002756, 0x00002756, 0x00002758, 0x0000275e, 0x00002761, 0x00002794, 0x00002798, 0x000027af, 0x000027b1, 0x000027be, 0x000027d0, 0x000027eb, 0x000027f0, 0x00002aff, 0x00002e80, 0x00002e99, 0x00002e9b, 0x00002ef3, 0x00002f00, 0x00002fd5, 0x00002ff0, 0x00002ffb, 0x00003001, 0x00003004, 0x00003008, 0x00003020, 0x0000302a, 0x00003030, 0x00003036, 0x00003037, 0x0000303d, 0x0000303f, 0x00003099, 0x0000309c, 0x000030a0, 0x000030a0, 0x000030fb, 0x000030fb, 0x00003251, 0x0000325f, 0x000032b1, 0x000032bf, 0x0000a490, 0x0000a4c6, 0x0000fb1e, 0x0000fb1e, 0x0000fd3e, 0x0000fd3f, 0x0000fe00, 0x0000fe0f, 0x0000fe20, 0x0000fe23, 0x0000fe30, 0x0000fe46, 0x0000fe49, 0x0000fe4f, 0x0000fe51, 0x0000fe51, 0x0000fe54, 0x0000fe54, 0x0000fe56, 0x0000fe5e, 0x0000fe60, 0x0000fe61, 0x0000fe64, 0x0000fe66, 0x0000fe68, 0x0000fe68, 0x0000fe6b, 0x0000fe6b, 0x0000feff, 0x0000feff, 0x0000ff01, 0x0000ff02, 0x0000ff06, 0x0000ff0a, 0x0000ff1b, 0x0000ff20, 0x0000ff3b, 0x0000ff40, 0x0000ff5b, 0x0000ff65, 0x0000ffe2, 0x0000ffe4, 0x0000ffe8, 0x0000ffee, 0x0000fff9, 0x0000fffd, 0x0001d167, 0x0001d169, 0x0001d173, 0x0001d182, 0x0001d185, 0x0001d18b, 0x0001d1aa, 0x0001d1ad, 0x000e0001, 0x000e0001, 0x000e0020, 0x000e007f, 0x000000c0, 0x000000c5, 0x000000c7, 0x000000cf, 0x000000d1, 0x000000d6, 0x000000d9, 0x000000dd, 0x000000e0, 0x000000e5, 0x000000e7, 0x000000ef, 0x000000f1, 0x000000f6, 0x000000f9, 0x000000fd, 0x000000ff, 0x0000010f, 0x00000112, 0x00000125, 0x00000128, 0x00000130, 0x00000134, 0x00000137, 0x00000139, 0x0000013e, 0x00000143, 0x00000148, 0x0000014c, 0x00000151, 0x00000154, 0x00000165, 0x00000168, 0x0000017e, 0x000001a0, 0x000001a1, 0x000001af, 0x000001b0, 0x000001cd, 0x000001dc, 0x000001de, 0x000001e3, 0x000001e6, 0x000001f0, 0x000001f4, 0x000001f5, 0x000001f8, 0x0000021b, 0x0000021e, 0x0000021f, 0x00000226, 0x00000233, 0x00000340, 0x00000341, 0x00000343, 0x00000344, 0x00000374, 0x00000374, 0x0000037e, 0x0000037e, 0x00000385, 0x0000038a, 0x0000038c, 0x0000038c, 0x0000038e, 0x00000390, 0x000003aa, 0x000003b0, 0x000003ca, 0x000003ce, 0x000003d3, 0x000003d4, 0x00000400, 0x00000401, 0x00000403, 0x00000403, 0x00000407, 0x00000407, 0x0000040c, 0x0000040e, 0x00000419, 0x00000419, 0x00000439, 0x00000439, 0x00000450, 0x00000451, 0x00000453, 0x00000453, 0x00000457, 0x00000457, 0x0000045c, 0x0000045e, 0x00000476, 0x00000477, 0x000004c1, 0x000004c2, 0x000004d0, 0x000004d3, 0x000004d6, 0x000004d7, 0x000004da, 0x000004df, 0x000004e2, 0x000004e7, 0x000004ea, 0x000004f5, 0x000004f8, 0x000004f9, 0x00000622, 0x00000626, 0x000006c0, 0x000006c0, 0x000006c2, 0x000006c2, 0x000006d3, 0x000006d3, 0x00000929, 0x00000929, 0x00000931, 0x00000931, 0x00000934, 0x00000934, 0x00000958, 0x0000095f, 0x000009cb, 0x000009cc, 0x000009dc, 0x000009dd, 0x000009df, 0x000009df, 0x00000a33, 0x00000a33, 0x00000a36, 0x00000a36, 0x00000a59, 0x00000a5b, 0x00000a5e, 0x00000a5e, 0x00000b48, 0x00000b48, 0x00000b4b, 0x00000b4c, 0x00000b5c, 0x00000b5d, 0x00000b94, 0x00000b94, 0x00000bca, 0x00000bcc, 0x00000c48, 0x00000c48, 0x00000cc0, 0x00000cc0, 0x00000cc7, 0x00000cc8, 0x00000cca, 0x00000ccb, 0x00000d4a, 0x00000d4c, 0x00000dda, 0x00000dda, 0x00000ddc, 0x00000dde, 0x00000f43, 0x00000f43, 0x00000f4d, 0x00000f4d, 0x00000f52, 0x00000f52, 0x00000f57, 0x00000f57, 0x00000f5c, 0x00000f5c, 0x00000f69, 0x00000f69, 0x00000f73, 0x00000f73, 0x00000f75, 0x00000f76, 0x00000f78, 0x00000f78, 0x00000f81, 0x00000f81, 0x00000f93, 0x00000f93, 0x00000f9d, 0x00000f9d, 0x00000fa2, 0x00000fa2, 0x00000fa7, 0x00000fa7, 0x00000fac, 0x00000fac, 0x00000fb9, 0x00000fb9, 0x00001026, 0x00001026, 0x00001e00, 0x00001e99, 0x00001e9b, 0x00001e9b, 0x00001ea0, 0x00001ef9, 0x00001f00, 0x00001f15, 0x00001f18, 0x00001f1d, 0x00001f20, 0x00001f45, 0x00001f48, 0x00001f4d, 0x00001f50, 0x00001f57, 0x00001f59, 0x00001f59, 0x00001f5b, 0x00001f5b, 0x00001f5d, 0x00001f5d, 0x00001f5f, 0x00001f7d, 0x00001f80, 0x00001fb4, 0x00001fb6, 0x00001fbc, 0x00001fbe, 0x00001fbe, 0x00001fc1, 0x00001fc4, 0x00001fc6, 0x00001fd3, 0x00001fd6, 0x00001fdb, 0x00001fdd, 0x00001fef, 0x00001ff2, 0x00001ff4, 0x00001ff6, 0x00001ffd, 0x00002000, 0x00002001, 0x00002126, 0x00002126, 0x0000212a, 0x0000212b, 0x0000219a, 0x0000219b, 0x000021ae, 0x000021ae, 0x000021cd, 0x000021cf, 0x00002204, 0x00002204, 0x00002209, 0x00002209, 0x0000220c, 0x0000220c, 0x00002224, 0x00002224, 0x00002226, 0x00002226, 0x00002241, 0x00002241, 0x00002244, 0x00002244, 0x00002247, 0x00002247, 0x00002249, 0x00002249, 0x00002260, 0x00002260, 0x00002262, 0x00002262, 0x0000226d, 0x00002271, 0x00002274, 0x00002275, 0x00002278, 0x00002279, 0x00002280, 0x00002281, 0x00002284, 0x00002285, 0x00002288, 0x00002289, 0x000022ac, 0x000022af, 0x000022e0, 0x000022e3, 0x000022ea, 0x000022ed, 0x00002329, 0x0000232a, 0x00002adc, 0x00002adc, 0x0000304c, 0x0000304c, 0x0000304e, 0x0000304e, 0x00003050, 0x00003050, 0x00003052, 0x00003052, 0x00003054, 0x00003054, 0x00003056, 0x00003056, 0x00003058, 0x00003058, 0x0000305a, 0x0000305a, 0x0000305c, 0x0000305c, 0x0000305e, 0x0000305e, 0x00003060, 0x00003060, 0x00003062, 0x00003062, 0x00003065, 0x00003065, 0x00003067, 0x00003067, 0x00003069, 0x00003069, 0x00003070, 0x00003071, 0x00003073, 0x00003074, 0x00003076, 0x00003077, 0x00003079, 0x0000307a, 0x0000307c, 0x0000307d, 0x00003094, 0x00003094, 0x0000309e, 0x0000309e, 0x000030ac, 0x000030ac, 0x000030ae, 0x000030ae, 0x000030b0, 0x000030b0, 0x000030b2, 0x000030b2, 0x000030b4, 0x000030b4, 0x000030b6, 0x000030b6, 0x000030b8, 0x000030b8, 0x000030ba, 0x000030ba, 0x000030bc, 0x000030bc, 0x000030be, 0x000030be, 0x000030c0, 0x000030c0, 0x000030c2, 0x000030c2, 0x000030c5, 0x000030c5, 0x000030c7, 0x000030c7, 0x000030c9, 0x000030c9, 0x000030d0, 0x000030d1, 0x000030d3, 0x000030d4, 0x000030d6, 0x000030d7, 0x000030d9, 0x000030da, 0x000030dc, 0x000030dd, 0x000030f4, 0x000030f4, 0x000030f7, 0x000030fa, 0x000030fe, 0x000030fe, 0x0000f902, 0x0000fa0d, 0x0000fa10, 0x0000fa10, 0x0000fa12, 0x0000fa12, 0x0000fa15, 0x0000fa1e, 0x0000fa20, 0x0000fa20, 0x0000fa22, 0x0000fa22, 0x0000fa25, 0x0000fa26, 0x0000fa2a, 0x0000fa2d, 0x0000fa30, 0x0000fa6a, 0x0000fb1d, 0x0000fb1d, 0x0000fb1f, 0x0000fb1f, 0x0000fb2a, 0x0000fb36, 0x0000fb38, 0x0000fb3c, 0x0000fb3e, 0x0000fb3e, 0x0000fb40, 0x0000fb41, 0x0000fb43, 0x0000fb44, 0x0000fb46, 0x0000fb4e, 0x0001d15e, 0x0001d164, 0x0001d1bb, 0x0001d1c0, 0x0002f800, 0x0002fa1d, 0x00000000, 0x00000220, 0x00000222, 0x00000233, 0x00000250, 0x000002ad, 0x000002b0, 0x000002ee, 0x00000300, 0x0000034f, 0x00000360, 0x0000036f, 0x00000374, 0x00000375, 0x0000037a, 0x0000037a, 0x0000037e, 0x0000037e, 0x00000384, 0x0000038a, 0x0000038c, 0x0000038c, 0x0000038e, 0x000003a1, 0x000003a3, 0x000003ce, 0x000003d0, 0x000003f6, 0x00000400, 0x00000486, 0x00000488, 0x000004ce, 0x000004d0, 0x000004f5, 0x000004f8, 0x000004f9, 0x00000500, 0x0000050f, 0x00000531, 0x00000556, 0x00000559, 0x0000055f, 0x00000561, 0x00000587, 0x00000589, 0x0000058a, 0x00000591, 0x000005a1, 0x000005a3, 0x000005b9, 0x000005bb, 0x000005c4, 0x000005d0, 0x000005ea, 0x000005f0, 0x000005f4, 0x0000060c, 0x0000060c, 0x0000061b, 0x0000061b, 0x0000061f, 0x0000061f, 0x00000621, 0x0000063a, 0x00000640, 0x00000655, 0x00000660, 0x000006ed, 0x000006f0, 0x000006fe, 0x00000700, 0x0000070d, 0x0000070f, 0x0000072c, 0x00000730, 0x0000074a, 0x00000780, 0x000007b1, 0x00000901, 0x00000903, 0x00000905, 0x00000939, 0x0000093c, 0x0000094d, 0x00000950, 0x00000954, 0x00000958, 0x00000970, 0x00000981, 0x00000983, 0x00000985, 0x0000098c, 0x0000098f, 0x00000990, 0x00000993, 0x000009a8, 0x000009aa, 0x000009b0, 0x000009b2, 0x000009b2, 0x000009b6, 0x000009b9, 0x000009bc, 0x000009bc, 0x000009be, 0x000009c4, 0x000009c7, 0x000009c8, 0x000009cb, 0x000009cd, 0x000009d7, 0x000009d7, 0x000009dc, 0x000009dd, 0x000009df, 0x000009e3, 0x000009e6, 0x000009fa, 0x00000a02, 0x00000a02, 0x00000a05, 0x00000a0a, 0x00000a0f, 0x00000a10, 0x00000a13, 0x00000a28, 0x00000a2a, 0x00000a30, 0x00000a32, 0x00000a33, 0x00000a35, 0x00000a36, 0x00000a38, 0x00000a39, 0x00000a3c, 0x00000a3c, 0x00000a3e, 0x00000a42, 0x00000a47, 0x00000a48, 0x00000a4b, 0x00000a4d, 0x00000a59, 0x00000a5c, 0x00000a5e, 0x00000a5e, 0x00000a66, 0x00000a74, 0x00000a81, 0x00000a83, 0x00000a85, 0x00000a8b, 0x00000a8d, 0x00000a8d, 0x00000a8f, 0x00000a91, 0x00000a93, 0x00000aa8, 0x00000aaa, 0x00000ab0, 0x00000ab2, 0x00000ab3, 0x00000ab5, 0x00000ab9, 0x00000abc, 0x00000ac5, 0x00000ac7, 0x00000ac9, 0x00000acb, 0x00000acd, 0x00000ad0, 0x00000ad0, 0x00000ae0, 0x00000ae0, 0x00000ae6, 0x00000aef, 0x00000b01, 0x00000b03, 0x00000b05, 0x00000b0c, 0x00000b0f, 0x00000b10, 0x00000b13, 0x00000b28, 0x00000b2a, 0x00000b30, 0x00000b32, 0x00000b33, 0x00000b36, 0x00000b39, 0x00000b3c, 0x00000b43, 0x00000b47, 0x00000b48, 0x00000b4b, 0x00000b4d, 0x00000b56, 0x00000b57, 0x00000b5c, 0x00000b5d, 0x00000b5f, 0x00000b61, 0x00000b66, 0x00000b70, 0x00000b82, 0x00000b83, 0x00000b85, 0x00000b8a, 0x00000b8e, 0x00000b90, 0x00000b92, 0x00000b95, 0x00000b99, 0x00000b9a, 0x00000b9c, 0x00000b9c, 0x00000b9e, 0x00000b9f, 0x00000ba3, 0x00000ba4, 0x00000ba8, 0x00000baa, 0x00000bae, 0x00000bb5, 0x00000bb7, 0x00000bb9, 0x00000bbe, 0x00000bc2, 0x00000bc6, 0x00000bc8, 0x00000bca, 0x00000bcd, 0x00000bd7, 0x00000bd7, 0x00000be7, 0x00000bf2, 0x00000c01, 0x00000c03, 0x00000c05, 0x00000c0c, 0x00000c0e, 0x00000c10, 0x00000c12, 0x00000c28, 0x00000c2a, 0x00000c33, 0x00000c35, 0x00000c39, 0x00000c3e, 0x00000c44, 0x00000c46, 0x00000c48, 0x00000c4a, 0x00000c4d, 0x00000c55, 0x00000c56, 0x00000c60, 0x00000c61, 0x00000c66, 0x00000c6f, 0x00000c82, 0x00000c83, 0x00000c85, 0x00000c8c, 0x00000c8e, 0x00000c90, 0x00000c92, 0x00000ca8, 0x00000caa, 0x00000cb3, 0x00000cb5, 0x00000cb9, 0x00000cbe, 0x00000cc4, 0x00000cc6, 0x00000cc8, 0x00000cca, 0x00000ccd, 0x00000cd5, 0x00000cd6, 0x00000cde, 0x00000cde, 0x00000ce0, 0x00000ce1, 0x00000ce6, 0x00000cef, 0x00000d02, 0x00000d03, 0x00000d05, 0x00000d0c, 0x00000d0e, 0x00000d10, 0x00000d12, 0x00000d28, 0x00000d2a, 0x00000d39, 0x00000d3e, 0x00000d43, 0x00000d46, 0x00000d48, 0x00000d4a, 0x00000d4d, 0x00000d57, 0x00000d57, 0x00000d60, 0x00000d61, 0x00000d66, 0x00000d6f, 0x00000d82, 0x00000d83, 0x00000d85, 0x00000d96, 0x00000d9a, 0x00000db1, 0x00000db3, 0x00000dbb, 0x00000dbd, 0x00000dbd, 0x00000dc0, 0x00000dc6, 0x00000dca, 0x00000dca, 0x00000dcf, 0x00000dd4, 0x00000dd6, 0x00000dd6, 0x00000dd8, 0x00000ddf, 0x00000df2, 0x00000df4, 0x00000e01, 0x00000e3a, 0x00000e3f, 0x00000e5b, 0x00000e81, 0x00000e82, 0x00000e84, 0x00000e84, 0x00000e87, 0x00000e88, 0x00000e8a, 0x00000e8a, 0x00000e8d, 0x00000e8d, 0x00000e94, 0x00000e97, 0x00000e99, 0x00000e9f, 0x00000ea1, 0x00000ea3, 0x00000ea5, 0x00000ea5, 0x00000ea7, 0x00000ea7, 0x00000eaa, 0x00000eab, 0x00000ead, 0x00000eb9, 0x00000ebb, 0x00000ebd, 0x00000ec0, 0x00000ec4, 0x00000ec6, 0x00000ec6, 0x00000ec8, 0x00000ecd, 0x00000ed0, 0x00000ed9, 0x00000edc, 0x00000edd, 0x00000f00, 0x00000f47, 0x00000f49, 0x00000f6a, 0x00000f71, 0x00000f8b, 0x00000f90, 0x00000f97, 0x00000f99, 0x00000fbc, 0x00000fbe, 0x00000fcc, 0x00000fcf, 0x00000fcf, 0x00001000, 0x00001021, 0x00001023, 0x00001027, 0x00001029, 0x0000102a, 0x0000102c, 0x00001032, 0x00001036, 0x00001039, 0x00001040, 0x00001059, 0x000010a0, 0x000010c5, 0x000010d0, 0x000010f8, 0x000010fb, 0x000010fb, 0x00001100, 0x00001159, 0x0000115f, 0x000011a2, 0x000011a8, 0x000011f9, 0x00001200, 0x00001206, 0x00001208, 0x00001246, 0x00001248, 0x00001248, 0x0000124a, 0x0000124d, 0x00001250, 0x00001256, 0x00001258, 0x00001258, 0x0000125a, 0x0000125d, 0x00001260, 0x00001286, 0x00001288, 0x00001288, 0x0000128a, 0x0000128d, 0x00001290, 0x000012ae, 0x000012b0, 0x000012b0, 0x000012b2, 0x000012b5, 0x000012b8, 0x000012be, 0x000012c0, 0x000012c0, 0x000012c2, 0x000012c5, 0x000012c8, 0x000012ce, 0x000012d0, 0x000012d6, 0x000012d8, 0x000012ee, 0x000012f0, 0x0000130e, 0x00001310, 0x00001310, 0x00001312, 0x00001315, 0x00001318, 0x0000131e, 0x00001320, 0x00001346, 0x00001348, 0x0000135a, 0x00001361, 0x0000137c, 0x000013a0, 0x000013f4, 0x00001401, 0x00001676, 0x00001680, 0x0000169c, 0x000016a0, 0x000016f0, 0x00001700, 0x0000170c, 0x0000170e, 0x00001714, 0x00001720, 0x00001736, 0x00001740, 0x00001753, 0x00001760, 0x0000176c, 0x0000176e, 0x00001770, 0x00001772, 0x00001773, 0x00001780, 0x000017dc, 0x000017e0, 0x000017e9, 0x00001800, 0x0000180e, 0x00001810, 0x00001819, 0x00001820, 0x00001877, 0x00001880, 0x000018a9, 0x00001e00, 0x00001e9b, 0x00001ea0, 0x00001ef9, 0x00001f00, 0x00001f15, 0x00001f18, 0x00001f1d, 0x00001f20, 0x00001f45, 0x00001f48, 0x00001f4d, 0x00001f50, 0x00001f57, 0x00001f59, 0x00001f59, 0x00001f5b, 0x00001f5b, 0x00001f5d, 0x00001f5d, 0x00001f5f, 0x00001f7d, 0x00001f80, 0x00001fb4, 0x00001fb6, 0x00001fc4, 0x00001fc6, 0x00001fd3, 0x00001fd6, 0x00001fdb, 0x00001fdd, 0x00001fef, 0x00001ff2, 0x00001ff4, 0x00001ff6, 0x00001ffe, 0x00002000, 0x00002052, 0x00002057, 0x00002057, 0x0000205f, 0x00002063, 0x0000206a, 0x00002071, 0x00002074, 0x0000208e, 0x000020a0, 0x000020b1, 0x000020d0, 0x000020ea, 0x00002100, 0x0000213a, 0x0000213d, 0x0000214b, 0x00002153, 0x00002183, 0x00002190, 0x000023ce, 0x00002400, 0x00002426, 0x00002440, 0x0000244a, 0x00002460, 0x000024fe, 0x00002500, 0x00002613, 0x00002616, 0x00002617, 0x00002619, 0x0000267d, 0x00002680, 0x00002689, 0x00002701, 0x00002704, 0x00002706, 0x00002709, 0x0000270c, 0x00002727, 0x00002729, 0x0000274b, 0x0000274d, 0x0000274d, 0x0000274f, 0x00002752, 0x00002756, 0x00002756, 0x00002758, 0x0000275e, 0x00002761, 0x00002794, 0x00002798, 0x000027af, 0x000027b1, 0x000027be, 0x000027d0, 0x000027eb, 0x000027f0, 0x00002aff, 0x00002e80, 0x00002e99, 0x00002e9b, 0x00002ef3, 0x00002f00, 0x00002fd5, 0x00002ff0, 0x00002ffb, 0x00003000, 0x0000303f, 0x00003041, 0x00003096, 0x00003099, 0x000030ff, 0x00003105, 0x0000312c, 0x00003131, 0x0000318e, 0x00003190, 0x000031b7, 0x000031f0, 0x0000321c, 0x00003220, 0x00003243, 0x00003251, 0x0000327b, 0x0000327f, 0x000032cb, 0x000032d0, 0x000032fe, 0x00003300, 0x00003376, 0x0000337b, 0x000033dd, 0x000033e0, 0x000033fe, 0x00003400, 0x00004db5, 0x00004e00, 0x00009fa5, 0x0000a000, 0x0000a48c, 0x0000a490, 0x0000a4c6, 0x0000ac00, 0x0000d7a3, 0x0000f900, 0x0000fb06, 0x0000fb13, 0x0000fb17, 0x0000fb1d, 0x0000fb36, 0x0000fb38, 0x0000fb3c, 0x0000fb3e, 0x0000fb3e, 0x0000fb40, 0x0000fb41, 0x0000fb43, 0x0000fb44, 0x0000fb46, 0x0000fbb1, 0x0000fbd3, 0x0000fd3f, 0x0000fd50, 0x0000fd8f, 0x0000fd92, 0x0000fdc7, 0x0000fdf0, 0x0000fdfc, 0x0000fe00, 0x0000fe0f, 0x0000fe20, 0x0000fe23, 0x0000fe30, 0x0000fe46, 0x0000fe49, 0x0000fe52, 0x0000fe54, 0x0000fe66, 0x0000fe68, 0x0000fe6b, 0x0000fe70, 0x0000fe74, 0x0000fe76, 0x0000fefc, 0x0000feff, 0x0000feff, 0x0000ff01, 0x0000ffbe, 0x0000ffc2, 0x0000ffc7, 0x0000ffca, 0x0000ffcf, 0x0000ffd2, 0x0000ffd7, 0x0000ffda, 0x0000ffdc, 0x0000ffe0, 0x0000ffe6, 0x0000ffe8, 0x0000ffee, 0x0000fff9, 0x0000fffd, 0x00010300, 0x0001031e, 0x00010320, 0x00010323, 0x00010330, 0x0001034a, 0x00010400, 0x00010425, 0x00010428, 0x0001044d, 0x0001d000, 0x0001d0f5, 0x0001d100, 0x0001d126, 0x0001d12a, 0x0001d1dd, 0x0001d400, 0x0001d454, 0x0001d456, 0x0001d49c, 0x0001d49e, 0x0001d49f, 0x0001d4a2, 0x0001d4a2, 0x0001d4a5, 0x0001d4a6, 0x0001d4a9, 0x0001d4ac, 0x0001d4ae, 0x0001d4b9, 0x0001d4bb, 0x0001d4bb, 0x0001d4bd, 0x0001d4c0, 0x0001d4c2, 0x0001d4c3, 0x0001d4c5, 0x0001d505, 0x0001d507, 0x0001d50a, 0x0001d50d, 0x0001d514, 0x0001d516, 0x0001d51c, 0x0001d51e, 0x0001d539, 0x0001d53b, 0x0001d53e, 0x0001d540, 0x0001d544, 0x0001d546, 0x0001d546, 0x0001d54a, 0x0001d550, 0x0001d552, 0x0001d6a3, 0x0001d6a8, 0x0001d7c9, 0x0001d7ce, 0x0001d7ff, 0x00020000, 0x0002a6d6, 0x0002f800, 0x0002fa1d, 0x000e0001, 0x000e0001, 0x000e0020, 0x000e007f, 0x000000ab, 0x000000ab, 0x00002018, 0x00002018, 0x0000201b, 0x0000201c, 0x0000201f, 0x0000201f, 0x00002039, 0x00002039, 0x000000bb, 0x000000bb, 0x00002019, 0x00002019, 0x0000201d, 0x0000201d, 0x0000203a, 0x0000203a, 0x0000061b, 0x0000061b, 0x0000061f, 0x0000061f, 0x00000621, 0x0000063a, 0x00000640, 0x0000064a, 0x0000066d, 0x0000066f, 0x00000671, 0x000006d5, 0x000006dd, 0x000006dd, 0x000006e5, 0x000006e6, 0x000006fa, 0x000006fe, 0x00000700, 0x0000070d, 0x00000710, 0x00000710, 0x00000712, 0x0000072c, 0x00000780, 0x000007a5, 0x000007b1, 0x000007b1, 0x0000fb50, 0x0000fbb1, 0x0000fbd3, 0x0000fd3d, 0x0000fd50, 0x0000fd8f, 0x0000fd92, 0x0000fdc7, 0x0000fdf0, 0x0000fdfc, 0x0000fe70, 0x0000fe74, 0x0000fe76, 0x0000fefc }; static const ac_uint4 _uccase_size = 1504; static const ac_uint2 _uccase_len[2] = {745, 755}; static const ac_uint4 _uccase_map[] = { 0x00000041, 0x00000061, 0x00000041, 0x00000042, 0x00000062, 0x00000042, 0x00000043, 0x00000063, 0x00000043, 0x00000044, 0x00000064, 0x00000044, 0x00000045, 0x00000065, 0x00000045, 0x00000046, 0x00000066, 0x00000046, 0x00000047, 0x00000067, 0x00000047, 0x00000048, 0x00000068, 0x00000048, 0x00000049, 0x00000069, 0x00000049, 0x0000004a, 0x0000006a, 0x0000004a, 0x0000004b, 0x0000006b, 0x0000004b, 0x0000004c, 0x0000006c, 0x0000004c, 0x0000004d, 0x0000006d, 0x0000004d, 0x0000004e, 0x0000006e, 0x0000004e, 0x0000004f, 0x0000006f, 0x0000004f, 0x00000050, 0x00000070, 0x00000050, 0x00000051, 0x00000071, 0x00000051, 0x00000052, 0x00000072, 0x00000052, 0x00000053, 0x00000073, 0x00000053, 0x00000054, 0x00000074, 0x00000054, 0x00000055, 0x00000075, 0x00000055, 0x00000056, 0x00000076, 0x00000056, 0x00000057, 0x00000077, 0x00000057, 0x00000058, 0x00000078, 0x00000058, 0x00000059, 0x00000079, 0x00000059, 0x0000005a, 0x0000007a, 0x0000005a, 0x000000c0, 0x000000e0, 0x000000c0, 0x000000c1, 0x000000e1, 0x000000c1, 0x000000c2, 0x000000e2, 0x000000c2, 0x000000c3, 0x000000e3, 0x000000c3, 0x000000c4, 0x000000e4, 0x000000c4, 0x000000c5, 0x000000e5, 0x000000c5, 0x000000c6, 0x000000e6, 0x000000c6, 0x000000c7, 0x000000e7, 0x000000c7, 0x000000c8, 0x000000e8, 0x000000c8, 0x000000c9, 0x000000e9, 0x000000c9, 0x000000ca, 0x000000ea, 0x000000ca, 0x000000cb, 0x000000eb, 0x000000cb, 0x000000cc, 0x000000ec, 0x000000cc, 0x000000cd, 0x000000ed, 0x000000cd, 0x000000ce, 0x000000ee, 0x000000ce, 0x000000cf, 0x000000ef, 0x000000cf, 0x000000d0, 0x000000f0, 0x000000d0, 0x000000d1, 0x000000f1, 0x000000d1, 0x000000d2, 0x000000f2, 0x000000d2, 0x000000d3, 0x000000f3, 0x000000d3, 0x000000d4, 0x000000f4, 0x000000d4, 0x000000d5, 0x000000f5, 0x000000d5, 0x000000d6, 0x000000f6, 0x000000d6, 0x000000d8, 0x000000f8, 0x000000d8, 0x000000d9, 0x000000f9, 0x000000d9, 0x000000da, 0x000000fa, 0x000000da, 0x000000db, 0x000000fb, 0x000000db, 0x000000dc, 0x000000fc, 0x000000dc, 0x000000dd, 0x000000fd, 0x000000dd, 0x000000de, 0x000000fe, 0x000000de, 0x00000100, 0x00000101, 0x00000100, 0x00000102, 0x00000103, 0x00000102, 0x00000104, 0x00000105, 0x00000104, 0x00000106, 0x00000107, 0x00000106, 0x00000108, 0x00000109, 0x00000108, 0x0000010a, 0x0000010b, 0x0000010a, 0x0000010c, 0x0000010d, 0x0000010c, 0x0000010e, 0x0000010f, 0x0000010e, 0x00000110, 0x00000111, 0x00000110, 0x00000112, 0x00000113, 0x00000112, 0x00000114, 0x00000115, 0x00000114, 0x00000116, 0x00000117, 0x00000116, 0x00000118, 0x00000119, 0x00000118, 0x0000011a, 0x0000011b, 0x0000011a, 0x0000011c, 0x0000011d, 0x0000011c, 0x0000011e, 0x0000011f, 0x0000011e, 0x00000120, 0x00000121, 0x00000120, 0x00000122, 0x00000123, 0x00000122, 0x00000124, 0x00000125, 0x00000124, 0x00000126, 0x00000127, 0x00000126, 0x00000128, 0x00000129, 0x00000128, 0x0000012a, 0x0000012b, 0x0000012a, 0x0000012c, 0x0000012d, 0x0000012c, 0x0000012e, 0x0000012f, 0x0000012e, 0x00000130, 0x00000069, 0x00000130, 0x00000132, 0x00000133, 0x00000132, 0x00000134, 0x00000135, 0x00000134, 0x00000136, 0x00000137, 0x00000136, 0x00000139, 0x0000013a, 0x00000139, 0x0000013b, 0x0000013c, 0x0000013b, 0x0000013d, 0x0000013e, 0x0000013d, 0x0000013f, 0x00000140, 0x0000013f, 0x00000141, 0x00000142, 0x00000141, 0x00000143, 0x00000144, 0x00000143, 0x00000145, 0x00000146, 0x00000145, 0x00000147, 0x00000148, 0x00000147, 0x0000014a, 0x0000014b, 0x0000014a, 0x0000014c, 0x0000014d, 0x0000014c, 0x0000014e, 0x0000014f, 0x0000014e, 0x00000150, 0x00000151, 0x00000150, 0x00000152, 0x00000153, 0x00000152, 0x00000154, 0x00000155, 0x00000154, 0x00000156, 0x00000157, 0x00000156, 0x00000158, 0x00000159, 0x00000158, 0x0000015a, 0x0000015b, 0x0000015a, 0x0000015c, 0x0000015d, 0x0000015c, 0x0000015e, 0x0000015f, 0x0000015e, 0x00000160, 0x00000161, 0x00000160, 0x00000162, 0x00000163, 0x00000162, 0x00000164, 0x00000165, 0x00000164, 0x00000166, 0x00000167, 0x00000166, 0x00000168, 0x00000169, 0x00000168, 0x0000016a, 0x0000016b, 0x0000016a, 0x0000016c, 0x0000016d, 0x0000016c, 0x0000016e, 0x0000016f, 0x0000016e, 0x00000170, 0x00000171, 0x00000170, 0x00000172, 0x00000173, 0x00000172, 0x00000174, 0x00000175, 0x00000174, 0x00000176, 0x00000177, 0x00000176, 0x00000178, 0x000000ff, 0x00000178, 0x00000179, 0x0000017a, 0x00000179, 0x0000017b, 0x0000017c, 0x0000017b, 0x0000017d, 0x0000017e, 0x0000017d, 0x00000181, 0x00000253, 0x00000181, 0x00000182, 0x00000183, 0x00000182, 0x00000184, 0x00000185, 0x00000184, 0x00000186, 0x00000254, 0x00000186, 0x00000187, 0x00000188, 0x00000187, 0x00000189, 0x00000256, 0x00000189, 0x0000018a, 0x00000257, 0x0000018a, 0x0000018b, 0x0000018c, 0x0000018b, 0x0000018e, 0x000001dd, 0x0000018e, 0x0000018f, 0x00000259, 0x0000018f, 0x00000190, 0x0000025b, 0x00000190, 0x00000191, 0x00000192, 0x00000191, 0x00000193, 0x00000260, 0x00000193, 0x00000194, 0x00000263, 0x00000194, 0x00000196, 0x00000269, 0x00000196, 0x00000197, 0x00000268, 0x00000197, 0x00000198, 0x00000199, 0x00000198, 0x0000019c, 0x0000026f, 0x0000019c, 0x0000019d, 0x00000272, 0x0000019d, 0x0000019f, 0x00000275, 0x0000019f, 0x000001a0, 0x000001a1, 0x000001a0, 0x000001a2, 0x000001a3, 0x000001a2, 0x000001a4, 0x000001a5, 0x000001a4, 0x000001a6, 0x00000280, 0x000001a6, 0x000001a7, 0x000001a8, 0x000001a7, 0x000001a9, 0x00000283, 0x000001a9, 0x000001ac, 0x000001ad, 0x000001ac, 0x000001ae, 0x00000288, 0x000001ae, 0x000001af, 0x000001b0, 0x000001af, 0x000001b1, 0x0000028a, 0x000001b1, 0x000001b2, 0x0000028b, 0x000001b2, 0x000001b3, 0x000001b4, 0x000001b3, 0x000001b5, 0x000001b6, 0x000001b5, 0x000001b7, 0x00000292, 0x000001b7, 0x000001b8, 0x000001b9, 0x000001b8, 0x000001bc, 0x000001bd, 0x000001bc, 0x000001c4, 0x000001c6, 0x000001c5, 0x000001c7, 0x000001c9, 0x000001c8, 0x000001ca, 0x000001cc, 0x000001cb, 0x000001cd, 0x000001ce, 0x000001cd, 0x000001cf, 0x000001d0, 0x000001cf, 0x000001d1, 0x000001d2, 0x000001d1, 0x000001d3, 0x000001d4, 0x000001d3, 0x000001d5, 0x000001d6, 0x000001d5, 0x000001d7, 0x000001d8, 0x000001d7, 0x000001d9, 0x000001da, 0x000001d9, 0x000001db, 0x000001dc, 0x000001db, 0x000001de, 0x000001df, 0x000001de, 0x000001e0, 0x000001e1, 0x000001e0, 0x000001e2, 0x000001e3, 0x000001e2, 0x000001e4, 0x000001e5, 0x000001e4, 0x000001e6, 0x000001e7, 0x000001e6, 0x000001e8, 0x000001e9, 0x000001e8, 0x000001ea, 0x000001eb, 0x000001ea, 0x000001ec, 0x000001ed, 0x000001ec, 0x000001ee, 0x000001ef, 0x000001ee, 0x000001f1, 0x000001f3, 0x000001f2, 0x000001f4, 0x000001f5, 0x000001f4, 0x000001f6, 0x00000195, 0x000001f6, 0x000001f7, 0x000001bf, 0x000001f7, 0x000001f8, 0x000001f9, 0x000001f8, 0x000001fa, 0x000001fb, 0x000001fa, 0x000001fc, 0x000001fd, 0x000001fc, 0x000001fe, 0x000001ff, 0x000001fe, 0x00000200, 0x00000201, 0x00000200, 0x00000202, 0x00000203, 0x00000202, 0x00000204, 0x00000205, 0x00000204, 0x00000206, 0x00000207, 0x00000206, 0x00000208, 0x00000209, 0x00000208, 0x0000020a, 0x0000020b, 0x0000020a, 0x0000020c, 0x0000020d, 0x0000020c, 0x0000020e, 0x0000020f, 0x0000020e, 0x00000210, 0x00000211, 0x00000210, 0x00000212, 0x00000213, 0x00000212, 0x00000214, 0x00000215, 0x00000214, 0x00000216, 0x00000217, 0x00000216, 0x00000218, 0x00000219, 0x00000218, 0x0000021a, 0x0000021b, 0x0000021a, 0x0000021c, 0x0000021d, 0x0000021c, 0x0000021e, 0x0000021f, 0x0000021e, 0x00000220, 0x0000019e, 0x00000220, 0x00000222, 0x00000223, 0x00000222, 0x00000224, 0x00000225, 0x00000224, 0x00000226, 0x00000227, 0x00000226, 0x00000228, 0x00000229, 0x00000228, 0x0000022a, 0x0000022b, 0x0000022a, 0x0000022c, 0x0000022d, 0x0000022c, 0x0000022e, 0x0000022f, 0x0000022e, 0x00000230, 0x00000231, 0x00000230, 0x00000232, 0x00000233, 0x00000232, 0x00000386, 0x000003ac, 0x00000386, 0x00000388, 0x000003ad, 0x00000388, 0x00000389, 0x000003ae, 0x00000389, 0x0000038a, 0x000003af, 0x0000038a, 0x0000038c, 0x000003cc, 0x0000038c, 0x0000038e, 0x000003cd, 0x0000038e, 0x0000038f, 0x000003ce, 0x0000038f, 0x00000391, 0x000003b1, 0x00000391, 0x00000392, 0x000003b2, 0x00000392, 0x00000393, 0x000003b3, 0x00000393, 0x00000394, 0x000003b4, 0x00000394, 0x00000395, 0x000003b5, 0x00000395, 0x00000396, 0x000003b6, 0x00000396, 0x00000397, 0x000003b7, 0x00000397, 0x00000398, 0x000003b8, 0x00000398, 0x00000399, 0x000003b9, 0x00000399, 0x0000039a, 0x000003ba, 0x0000039a, 0x0000039b, 0x000003bb, 0x0000039b, 0x0000039c, 0x000003bc, 0x0000039c, 0x0000039d, 0x000003bd, 0x0000039d, 0x0000039e, 0x000003be, 0x0000039e, 0x0000039f, 0x000003bf, 0x0000039f, 0x000003a0, 0x000003c0, 0x000003a0, 0x000003a1, 0x000003c1, 0x000003a1, 0x000003a3, 0x000003c3, 0x000003a3, 0x000003a4, 0x000003c4, 0x000003a4, 0x000003a5, 0x000003c5, 0x000003a5, 0x000003a6, 0x000003c6, 0x000003a6, 0x000003a7, 0x000003c7, 0x000003a7, 0x000003a8, 0x000003c8, 0x000003a8, 0x000003a9, 0x000003c9, 0x000003a9, 0x000003aa, 0x000003ca, 0x000003aa, 0x000003ab, 0x000003cb, 0x000003ab, 0x000003d8, 0x000003d9, 0x000003d8, 0x000003da, 0x000003db, 0x000003da, 0x000003dc, 0x000003dd, 0x000003dc, 0x000003de, 0x000003df, 0x000003de, 0x000003e0, 0x000003e1, 0x000003e0, 0x000003e2, 0x000003e3, 0x000003e2, 0x000003e4, 0x000003e5, 0x000003e4, 0x000003e6, 0x000003e7, 0x000003e6, 0x000003e8, 0x000003e9, 0x000003e8, 0x000003ea, 0x000003eb, 0x000003ea, 0x000003ec, 0x000003ed, 0x000003ec, 0x000003ee, 0x000003ef, 0x000003ee, 0x000003f4, 0x000003b8, 0x000003f4, 0x00000400, 0x00000450, 0x00000400, 0x00000401, 0x00000451, 0x00000401, 0x00000402, 0x00000452, 0x00000402, 0x00000403, 0x00000453, 0x00000403, 0x00000404, 0x00000454, 0x00000404, 0x00000405, 0x00000455, 0x00000405, 0x00000406, 0x00000456, 0x00000406, 0x00000407, 0x00000457, 0x00000407, 0x00000408, 0x00000458, 0x00000408, 0x00000409, 0x00000459, 0x00000409, 0x0000040a, 0x0000045a, 0x0000040a, 0x0000040b, 0x0000045b, 0x0000040b, 0x0000040c, 0x0000045c, 0x0000040c, 0x0000040d, 0x0000045d, 0x0000040d, 0x0000040e, 0x0000045e, 0x0000040e, 0x0000040f, 0x0000045f, 0x0000040f, 0x00000410, 0x00000430, 0x00000410, 0x00000411, 0x00000431, 0x00000411, 0x00000412, 0x00000432, 0x00000412, 0x00000413, 0x00000433, 0x00000413, 0x00000414, 0x00000434, 0x00000414, 0x00000415, 0x00000435, 0x00000415, 0x00000416, 0x00000436, 0x00000416, 0x00000417, 0x00000437, 0x00000417, 0x00000418, 0x00000438, 0x00000418, 0x00000419, 0x00000439, 0x00000419, 0x0000041a, 0x0000043a, 0x0000041a, 0x0000041b, 0x0000043b, 0x0000041b, 0x0000041c, 0x0000043c, 0x0000041c, 0x0000041d, 0x0000043d, 0x0000041d, 0x0000041e, 0x0000043e, 0x0000041e, 0x0000041f, 0x0000043f, 0x0000041f, 0x00000420, 0x00000440, 0x00000420, 0x00000421, 0x00000441, 0x00000421, 0x00000422, 0x00000442, 0x00000422, 0x00000423, 0x00000443, 0x00000423, 0x00000424, 0x00000444, 0x00000424, 0x00000425, 0x00000445, 0x00000425, 0x00000426, 0x00000446, 0x00000426, 0x00000427, 0x00000447, 0x00000427, 0x00000428, 0x00000448, 0x00000428, 0x00000429, 0x00000449, 0x00000429, 0x0000042a, 0x0000044a, 0x0000042a, 0x0000042b, 0x0000044b, 0x0000042b, 0x0000042c, 0x0000044c, 0x0000042c, 0x0000042d, 0x0000044d, 0x0000042d, 0x0000042e, 0x0000044e, 0x0000042e, 0x0000042f, 0x0000044f, 0x0000042f, 0x00000460, 0x00000461, 0x00000460, 0x00000462, 0x00000463, 0x00000462, 0x00000464, 0x00000465, 0x00000464, 0x00000466, 0x00000467, 0x00000466, 0x00000468, 0x00000469, 0x00000468, 0x0000046a, 0x0000046b, 0x0000046a, 0x0000046c, 0x0000046d, 0x0000046c, 0x0000046e, 0x0000046f, 0x0000046e, 0x00000470, 0x00000471, 0x00000470, 0x00000472, 0x00000473, 0x00000472, 0x00000474, 0x00000475, 0x00000474, 0x00000476, 0x00000477, 0x00000476, 0x00000478, 0x00000479, 0x00000478, 0x0000047a, 0x0000047b, 0x0000047a, 0x0000047c, 0x0000047d, 0x0000047c, 0x0000047e, 0x0000047f, 0x0000047e, 0x00000480, 0x00000481, 0x00000480, 0x0000048a, 0x0000048b, 0x0000048a, 0x0000048c, 0x0000048d, 0x0000048c, 0x0000048e, 0x0000048f, 0x0000048e, 0x00000490, 0x00000491, 0x00000490, 0x00000492, 0x00000493, 0x00000492, 0x00000494, 0x00000495, 0x00000494, 0x00000496, 0x00000497, 0x00000496, 0x00000498, 0x00000499, 0x00000498, 0x0000049a, 0x0000049b, 0x0000049a, 0x0000049c, 0x0000049d, 0x0000049c, 0x0000049e, 0x0000049f, 0x0000049e, 0x000004a0, 0x000004a1, 0x000004a0, 0x000004a2, 0x000004a3, 0x000004a2, 0x000004a4, 0x000004a5, 0x000004a4, 0x000004a6, 0x000004a7, 0x000004a6, 0x000004a8, 0x000004a9, 0x000004a8, 0x000004aa, 0x000004ab, 0x000004aa, 0x000004ac, 0x000004ad, 0x000004ac, 0x000004ae, 0x000004af, 0x000004ae, 0x000004b0, 0x000004b1, 0x000004b0, 0x000004b2, 0x000004b3, 0x000004b2, 0x000004b4, 0x000004b5, 0x000004b4, 0x000004b6, 0x000004b7, 0x000004b6, 0x000004b8, 0x000004b9, 0x000004b8, 0x000004ba, 0x000004bb, 0x000004ba, 0x000004bc, 0x000004bd, 0x000004bc, 0x000004be, 0x000004bf, 0x000004be, 0x000004c1, 0x000004c2, 0x000004c1, 0x000004c3, 0x000004c4, 0x000004c3, 0x000004c5, 0x000004c6, 0x000004c5, 0x000004c7, 0x000004c8, 0x000004c7, 0x000004c9, 0x000004ca, 0x000004c9, 0x000004cb, 0x000004cc, 0x000004cb, 0x000004cd, 0x000004ce, 0x000004cd, 0x000004d0, 0x000004d1, 0x000004d0, 0x000004d2, 0x000004d3, 0x000004d2, 0x000004d4, 0x000004d5, 0x000004d4, 0x000004d6, 0x000004d7, 0x000004d6, 0x000004d8, 0x000004d9, 0x000004d8, 0x000004da, 0x000004db, 0x000004da, 0x000004dc, 0x000004dd, 0x000004dc, 0x000004de, 0x000004df, 0x000004de, 0x000004e0, 0x000004e1, 0x000004e0, 0x000004e2, 0x000004e3, 0x000004e2, 0x000004e4, 0x000004e5, 0x000004e4, 0x000004e6, 0x000004e7, 0x000004e6, 0x000004e8, 0x000004e9, 0x000004e8, 0x000004ea, 0x000004eb, 0x000004ea, 0x000004ec, 0x000004ed, 0x000004ec, 0x000004ee, 0x000004ef, 0x000004ee, 0x000004f0, 0x000004f1, 0x000004f0, 0x000004f2, 0x000004f3, 0x000004f2, 0x000004f4, 0x000004f5, 0x000004f4, 0x000004f8, 0x000004f9, 0x000004f8, 0x00000500, 0x00000501, 0x00000500, 0x00000502, 0x00000503, 0x00000502, 0x00000504, 0x00000505, 0x00000504, 0x00000506, 0x00000507, 0x00000506, 0x00000508, 0x00000509, 0x00000508, 0x0000050a, 0x0000050b, 0x0000050a, 0x0000050c, 0x0000050d, 0x0000050c, 0x0000050e, 0x0000050f, 0x0000050e, 0x00000531, 0x00000561, 0x00000531, 0x00000532, 0x00000562, 0x00000532, 0x00000533, 0x00000563, 0x00000533, 0x00000534, 0x00000564, 0x00000534, 0x00000535, 0x00000565, 0x00000535, 0x00000536, 0x00000566, 0x00000536, 0x00000537, 0x00000567, 0x00000537, 0x00000538, 0x00000568, 0x00000538, 0x00000539, 0x00000569, 0x00000539, 0x0000053a, 0x0000056a, 0x0000053a, 0x0000053b, 0x0000056b, 0x0000053b, 0x0000053c, 0x0000056c, 0x0000053c, 0x0000053d, 0x0000056d, 0x0000053d, 0x0000053e, 0x0000056e, 0x0000053e, 0x0000053f, 0x0000056f, 0x0000053f, 0x00000540, 0x00000570, 0x00000540, 0x00000541, 0x00000571, 0x00000541, 0x00000542, 0x00000572, 0x00000542, 0x00000543, 0x00000573, 0x00000543, 0x00000544, 0x00000574, 0x00000544, 0x00000545, 0x00000575, 0x00000545, 0x00000546, 0x00000576, 0x00000546, 0x00000547, 0x00000577, 0x00000547, 0x00000548, 0x00000578, 0x00000548, 0x00000549, 0x00000579, 0x00000549, 0x0000054a, 0x0000057a, 0x0000054a, 0x0000054b, 0x0000057b, 0x0000054b, 0x0000054c, 0x0000057c, 0x0000054c, 0x0000054d, 0x0000057d, 0x0000054d, 0x0000054e, 0x0000057e, 0x0000054e, 0x0000054f, 0x0000057f, 0x0000054f, 0x00000550, 0x00000580, 0x00000550, 0x00000551, 0x00000581, 0x00000551, 0x00000552, 0x00000582, 0x00000552, 0x00000553, 0x00000583, 0x00000553, 0x00000554, 0x00000584, 0x00000554, 0x00000555, 0x00000585, 0x00000555, 0x00000556, 0x00000586, 0x00000556, 0x00001e00, 0x00001e01, 0x00001e00, 0x00001e02, 0x00001e03, 0x00001e02, 0x00001e04, 0x00001e05, 0x00001e04, 0x00001e06, 0x00001e07, 0x00001e06, 0x00001e08, 0x00001e09, 0x00001e08, 0x00001e0a, 0x00001e0b, 0x00001e0a, 0x00001e0c, 0x00001e0d, 0x00001e0c, 0x00001e0e, 0x00001e0f, 0x00001e0e, 0x00001e10, 0x00001e11, 0x00001e10, 0x00001e12, 0x00001e13, 0x00001e12, 0x00001e14, 0x00001e15, 0x00001e14, 0x00001e16, 0x00001e17, 0x00001e16, 0x00001e18, 0x00001e19, 0x00001e18, 0x00001e1a, 0x00001e1b, 0x00001e1a, 0x00001e1c, 0x00001e1d, 0x00001e1c, 0x00001e1e, 0x00001e1f, 0x00001e1e, 0x00001e20, 0x00001e21, 0x00001e20, 0x00001e22, 0x00001e23, 0x00001e22, 0x00001e24, 0x00001e25, 0x00001e24, 0x00001e26, 0x00001e27, 0x00001e26, 0x00001e28, 0x00001e29, 0x00001e28, 0x00001e2a, 0x00001e2b, 0x00001e2a, 0x00001e2c, 0x00001e2d, 0x00001e2c, 0x00001e2e, 0x00001e2f, 0x00001e2e, 0x00001e30, 0x00001e31, 0x00001e30, 0x00001e32, 0x00001e33, 0x00001e32, 0x00001e34, 0x00001e35, 0x00001e34, 0x00001e36, 0x00001e37, 0x00001e36, 0x00001e38, 0x00001e39, 0x00001e38, 0x00001e3a, 0x00001e3b, 0x00001e3a, 0x00001e3c, 0x00001e3d, 0x00001e3c, 0x00001e3e, 0x00001e3f, 0x00001e3e, 0x00001e40, 0x00001e41, 0x00001e40, 0x00001e42, 0x00001e43, 0x00001e42, 0x00001e44, 0x00001e45, 0x00001e44, 0x00001e46, 0x00001e47, 0x00001e46, 0x00001e48, 0x00001e49, 0x00001e48, 0x00001e4a, 0x00001e4b, 0x00001e4a, 0x00001e4c, 0x00001e4d, 0x00001e4c, 0x00001e4e, 0x00001e4f, 0x00001e4e, 0x00001e50, 0x00001e51, 0x00001e50, 0x00001e52, 0x00001e53, 0x00001e52, 0x00001e54, 0x00001e55, 0x00001e54, 0x00001e56, 0x00001e57, 0x00001e56, 0x00001e58, 0x00001e59, 0x00001e58, 0x00001e5a, 0x00001e5b, 0x00001e5a, 0x00001e5c, 0x00001e5d, 0x00001e5c, 0x00001e5e, 0x00001e5f, 0x00001e5e, 0x00001e60, 0x00001e61, 0x00001e60, 0x00001e62, 0x00001e63, 0x00001e62, 0x00001e64, 0x00001e65, 0x00001e64, 0x00001e66, 0x00001e67, 0x00001e66, 0x00001e68, 0x00001e69, 0x00001e68, 0x00001e6a, 0x00001e6b, 0x00001e6a, 0x00001e6c, 0x00001e6d, 0x00001e6c, 0x00001e6e, 0x00001e6f, 0x00001e6e, 0x00001e70, 0x00001e71, 0x00001e70, 0x00001e72, 0x00001e73, 0x00001e72, 0x00001e74, 0x00001e75, 0x00001e74, 0x00001e76, 0x00001e77, 0x00001e76, 0x00001e78, 0x00001e79, 0x00001e78, 0x00001e7a, 0x00001e7b, 0x00001e7a, 0x00001e7c, 0x00001e7d, 0x00001e7c, 0x00001e7e, 0x00001e7f, 0x00001e7e, 0x00001e80, 0x00001e81, 0x00001e80, 0x00001e82, 0x00001e83, 0x00001e82, 0x00001e84, 0x00001e85, 0x00001e84, 0x00001e86, 0x00001e87, 0x00001e86, 0x00001e88, 0x00001e89, 0x00001e88, 0x00001e8a, 0x00001e8b, 0x00001e8a, 0x00001e8c, 0x00001e8d, 0x00001e8c, 0x00001e8e, 0x00001e8f, 0x00001e8e, 0x00001e90, 0x00001e91, 0x00001e90, 0x00001e92, 0x00001e93, 0x00001e92, 0x00001e94, 0x00001e95, 0x00001e94, 0x00001ea0, 0x00001ea1, 0x00001ea0, 0x00001ea2, 0x00001ea3, 0x00001ea2, 0x00001ea4, 0x00001ea5, 0x00001ea4, 0x00001ea6, 0x00001ea7, 0x00001ea6, 0x00001ea8, 0x00001ea9, 0x00001ea8, 0x00001eaa, 0x00001eab, 0x00001eaa, 0x00001eac, 0x00001ead, 0x00001eac, 0x00001eae, 0x00001eaf, 0x00001eae, 0x00001eb0, 0x00001eb1, 0x00001eb0, 0x00001eb2, 0x00001eb3, 0x00001eb2, 0x00001eb4, 0x00001eb5, 0x00001eb4, 0x00001eb6, 0x00001eb7, 0x00001eb6, 0x00001eb8, 0x00001eb9, 0x00001eb8, 0x00001eba, 0x00001ebb, 0x00001eba, 0x00001ebc, 0x00001ebd, 0x00001ebc, 0x00001ebe, 0x00001ebf, 0x00001ebe, 0x00001ec0, 0x00001ec1, 0x00001ec0, 0x00001ec2, 0x00001ec3, 0x00001ec2, 0x00001ec4, 0x00001ec5, 0x00001ec4, 0x00001ec6, 0x00001ec7, 0x00001ec6, 0x00001ec8, 0x00001ec9, 0x00001ec8, 0x00001eca, 0x00001ecb, 0x00001eca, 0x00001ecc, 0x00001ecd, 0x00001ecc, 0x00001ece, 0x00001ecf, 0x00001ece, 0x00001ed0, 0x00001ed1, 0x00001ed0, 0x00001ed2, 0x00001ed3, 0x00001ed2, 0x00001ed4, 0x00001ed5, 0x00001ed4, 0x00001ed6, 0x00001ed7, 0x00001ed6, 0x00001ed8, 0x00001ed9, 0x00001ed8, 0x00001eda, 0x00001edb, 0x00001eda, 0x00001edc, 0x00001edd, 0x00001edc, 0x00001ede, 0x00001edf, 0x00001ede, 0x00001ee0, 0x00001ee1, 0x00001ee0, 0x00001ee2, 0x00001ee3, 0x00001ee2, 0x00001ee4, 0x00001ee5, 0x00001ee4, 0x00001ee6, 0x00001ee7, 0x00001ee6, 0x00001ee8, 0x00001ee9, 0x00001ee8, 0x00001eea, 0x00001eeb, 0x00001eea, 0x00001eec, 0x00001eed, 0x00001eec, 0x00001eee, 0x00001eef, 0x00001eee, 0x00001ef0, 0x00001ef1, 0x00001ef0, 0x00001ef2, 0x00001ef3, 0x00001ef2, 0x00001ef4, 0x00001ef5, 0x00001ef4, 0x00001ef6, 0x00001ef7, 0x00001ef6, 0x00001ef8, 0x00001ef9, 0x00001ef8, 0x00001f08, 0x00001f00, 0x00001f08, 0x00001f09, 0x00001f01, 0x00001f09, 0x00001f0a, 0x00001f02, 0x00001f0a, 0x00001f0b, 0x00001f03, 0x00001f0b, 0x00001f0c, 0x00001f04, 0x00001f0c, 0x00001f0d, 0x00001f05, 0x00001f0d, 0x00001f0e, 0x00001f06, 0x00001f0e, 0x00001f0f, 0x00001f07, 0x00001f0f, 0x00001f18, 0x00001f10, 0x00001f18, 0x00001f19, 0x00001f11, 0x00001f19, 0x00001f1a, 0x00001f12, 0x00001f1a, 0x00001f1b, 0x00001f13, 0x00001f1b, 0x00001f1c, 0x00001f14, 0x00001f1c, 0x00001f1d, 0x00001f15, 0x00001f1d, 0x00001f28, 0x00001f20, 0x00001f28, 0x00001f29, 0x00001f21, 0x00001f29, 0x00001f2a, 0x00001f22, 0x00001f2a, 0x00001f2b, 0x00001f23, 0x00001f2b, 0x00001f2c, 0x00001f24, 0x00001f2c, 0x00001f2d, 0x00001f25, 0x00001f2d, 0x00001f2e, 0x00001f26, 0x00001f2e, 0x00001f2f, 0x00001f27, 0x00001f2f, 0x00001f38, 0x00001f30, 0x00001f38, 0x00001f39, 0x00001f31, 0x00001f39, 0x00001f3a, 0x00001f32, 0x00001f3a, 0x00001f3b, 0x00001f33, 0x00001f3b, 0x00001f3c, 0x00001f34, 0x00001f3c, 0x00001f3d, 0x00001f35, 0x00001f3d, 0x00001f3e, 0x00001f36, 0x00001f3e, 0x00001f3f, 0x00001f37, 0x00001f3f, 0x00001f48, 0x00001f40, 0x00001f48, 0x00001f49, 0x00001f41, 0x00001f49, 0x00001f4a, 0x00001f42, 0x00001f4a, 0x00001f4b, 0x00001f43, 0x00001f4b, 0x00001f4c, 0x00001f44, 0x00001f4c, 0x00001f4d, 0x00001f45, 0x00001f4d, 0x00001f59, 0x00001f51, 0x00001f59, 0x00001f5b, 0x00001f53, 0x00001f5b, 0x00001f5d, 0x00001f55, 0x00001f5d, 0x00001f5f, 0x00001f57, 0x00001f5f, 0x00001f68, 0x00001f60, 0x00001f68, 0x00001f69, 0x00001f61, 0x00001f69, 0x00001f6a, 0x00001f62, 0x00001f6a, 0x00001f6b, 0x00001f63, 0x00001f6b, 0x00001f6c, 0x00001f64, 0x00001f6c, 0x00001f6d, 0x00001f65, 0x00001f6d, 0x00001f6e, 0x00001f66, 0x00001f6e, 0x00001f6f, 0x00001f67, 0x00001f6f, 0x00001f88, 0x00001f80, 0x00001f88, 0x00001f89, 0x00001f81, 0x00001f89, 0x00001f8a, 0x00001f82, 0x00001f8a, 0x00001f8b, 0x00001f83, 0x00001f8b, 0x00001f8c, 0x00001f84, 0x00001f8c, 0x00001f8d, 0x00001f85, 0x00001f8d, 0x00001f8e, 0x00001f86, 0x00001f8e, 0x00001f8f, 0x00001f87, 0x00001f8f, 0x00001f98, 0x00001f90, 0x00001f98, 0x00001f99, 0x00001f91, 0x00001f99, 0x00001f9a, 0x00001f92, 0x00001f9a, 0x00001f9b, 0x00001f93, 0x00001f9b, 0x00001f9c, 0x00001f94, 0x00001f9c, 0x00001f9d, 0x00001f95, 0x00001f9d, 0x00001f9e, 0x00001f96, 0x00001f9e, 0x00001f9f, 0x00001f97, 0x00001f9f, 0x00001fa8, 0x00001fa0, 0x00001fa8, 0x00001fa9, 0x00001fa1, 0x00001fa9, 0x00001faa, 0x00001fa2, 0x00001faa, 0x00001fab, 0x00001fa3, 0x00001fab, 0x00001fac, 0x00001fa4, 0x00001fac, 0x00001fad, 0x00001fa5, 0x00001fad, 0x00001fae, 0x00001fa6, 0x00001fae, 0x00001faf, 0x00001fa7, 0x00001faf, 0x00001fb8, 0x00001fb0, 0x00001fb8, 0x00001fb9, 0x00001fb1, 0x00001fb9, 0x00001fba, 0x00001f70, 0x00001fba, 0x00001fbb, 0x00001f71, 0x00001fbb, 0x00001fbc, 0x00001fb3, 0x00001fbc, 0x00001fc8, 0x00001f72, 0x00001fc8, 0x00001fc9, 0x00001f73, 0x00001fc9, 0x00001fca, 0x00001f74, 0x00001fca, 0x00001fcb, 0x00001f75, 0x00001fcb, 0x00001fcc, 0x00001fc3, 0x00001fcc, 0x00001fd8, 0x00001fd0, 0x00001fd8, 0x00001fd9, 0x00001fd1, 0x00001fd9, 0x00001fda, 0x00001f76, 0x00001fda, 0x00001fdb, 0x00001f77, 0x00001fdb, 0x00001fe8, 0x00001fe0, 0x00001fe8, 0x00001fe9, 0x00001fe1, 0x00001fe9, 0x00001fea, 0x00001f7a, 0x00001fea, 0x00001feb, 0x00001f7b, 0x00001feb, 0x00001fec, 0x00001fe5, 0x00001fec, 0x00001ff8, 0x00001f78, 0x00001ff8, 0x00001ff9, 0x00001f79, 0x00001ff9, 0x00001ffa, 0x00001f7c, 0x00001ffa, 0x00001ffb, 0x00001f7d, 0x00001ffb, 0x00001ffc, 0x00001ff3, 0x00001ffc, 0x00002126, 0x000003c9, 0x00002126, 0x0000212a, 0x0000006b, 0x0000212a, 0x0000212b, 0x000000e5, 0x0000212b, 0x00002160, 0x00002170, 0x00002160, 0x00002161, 0x00002171, 0x00002161, 0x00002162, 0x00002172, 0x00002162, 0x00002163, 0x00002173, 0x00002163, 0x00002164, 0x00002174, 0x00002164, 0x00002165, 0x00002175, 0x00002165, 0x00002166, 0x00002176, 0x00002166, 0x00002167, 0x00002177, 0x00002167, 0x00002168, 0x00002178, 0x00002168, 0x00002169, 0x00002179, 0x00002169, 0x0000216a, 0x0000217a, 0x0000216a, 0x0000216b, 0x0000217b, 0x0000216b, 0x0000216c, 0x0000217c, 0x0000216c, 0x0000216d, 0x0000217d, 0x0000216d, 0x0000216e, 0x0000217e, 0x0000216e, 0x0000216f, 0x0000217f, 0x0000216f, 0x000024b6, 0x000024d0, 0x000024b6, 0x000024b7, 0x000024d1, 0x000024b7, 0x000024b8, 0x000024d2, 0x000024b8, 0x000024b9, 0x000024d3, 0x000024b9, 0x000024ba, 0x000024d4, 0x000024ba, 0x000024bb, 0x000024d5, 0x000024bb, 0x000024bc, 0x000024d6, 0x000024bc, 0x000024bd, 0x000024d7, 0x000024bd, 0x000024be, 0x000024d8, 0x000024be, 0x000024bf, 0x000024d9, 0x000024bf, 0x000024c0, 0x000024da, 0x000024c0, 0x000024c1, 0x000024db, 0x000024c1, 0x000024c2, 0x000024dc, 0x000024c2, 0x000024c3, 0x000024dd, 0x000024c3, 0x000024c4, 0x000024de, 0x000024c4, 0x000024c5, 0x000024df, 0x000024c5, 0x000024c6, 0x000024e0, 0x000024c6, 0x000024c7, 0x000024e1, 0x000024c7, 0x000024c8, 0x000024e2, 0x000024c8, 0x000024c9, 0x000024e3, 0x000024c9, 0x000024ca, 0x000024e4, 0x000024ca, 0x000024cb, 0x000024e5, 0x000024cb, 0x000024cc, 0x000024e6, 0x000024cc, 0x000024cd, 0x000024e7, 0x000024cd, 0x000024ce, 0x000024e8, 0x000024ce, 0x000024cf, 0x000024e9, 0x000024cf, 0x0000ff21, 0x0000ff41, 0x0000ff21, 0x0000ff22, 0x0000ff42, 0x0000ff22, 0x0000ff23, 0x0000ff43, 0x0000ff23, 0x0000ff24, 0x0000ff44, 0x0000ff24, 0x0000ff25, 0x0000ff45, 0x0000ff25, 0x0000ff26, 0x0000ff46, 0x0000ff26, 0x0000ff27, 0x0000ff47, 0x0000ff27, 0x0000ff28, 0x0000ff48, 0x0000ff28, 0x0000ff29, 0x0000ff49, 0x0000ff29, 0x0000ff2a, 0x0000ff4a, 0x0000ff2a, 0x0000ff2b, 0x0000ff4b, 0x0000ff2b, 0x0000ff2c, 0x0000ff4c, 0x0000ff2c, 0x0000ff2d, 0x0000ff4d, 0x0000ff2d, 0x0000ff2e, 0x0000ff4e, 0x0000ff2e, 0x0000ff2f, 0x0000ff4f, 0x0000ff2f, 0x0000ff30, 0x0000ff50, 0x0000ff30, 0x0000ff31, 0x0000ff51, 0x0000ff31, 0x0000ff32, 0x0000ff52, 0x0000ff32, 0x0000ff33, 0x0000ff53, 0x0000ff33, 0x0000ff34, 0x0000ff54, 0x0000ff34, 0x0000ff35, 0x0000ff55, 0x0000ff35, 0x0000ff36, 0x0000ff56, 0x0000ff36, 0x0000ff37, 0x0000ff57, 0x0000ff37, 0x0000ff38, 0x0000ff58, 0x0000ff38, 0x0000ff39, 0x0000ff59, 0x0000ff39, 0x0000ff3a, 0x0000ff5a, 0x0000ff3a, 0x00010400, 0x00010428, 0x00010400, 0x00010401, 0x00010429, 0x00010401, 0x00010402, 0x0001042a, 0x00010402, 0x00010403, 0x0001042b, 0x00010403, 0x00010404, 0x0001042c, 0x00010404, 0x00010405, 0x0001042d, 0x00010405, 0x00010406, 0x0001042e, 0x00010406, 0x00010407, 0x0001042f, 0x00010407, 0x00010408, 0x00010430, 0x00010408, 0x00010409, 0x00010431, 0x00010409, 0x0001040a, 0x00010432, 0x0001040a, 0x0001040b, 0x00010433, 0x0001040b, 0x0001040c, 0x00010434, 0x0001040c, 0x0001040d, 0x00010435, 0x0001040d, 0x0001040e, 0x00010436, 0x0001040e, 0x0001040f, 0x00010437, 0x0001040f, 0x00010410, 0x00010438, 0x00010410, 0x00010411, 0x00010439, 0x00010411, 0x00010412, 0x0001043a, 0x00010412, 0x00010413, 0x0001043b, 0x00010413, 0x00010414, 0x0001043c, 0x00010414, 0x00010415, 0x0001043d, 0x00010415, 0x00010416, 0x0001043e, 0x00010416, 0x00010417, 0x0001043f, 0x00010417, 0x00010418, 0x00010440, 0x00010418, 0x00010419, 0x00010441, 0x00010419, 0x0001041a, 0x00010442, 0x0001041a, 0x0001041b, 0x00010443, 0x0001041b, 0x0001041c, 0x00010444, 0x0001041c, 0x0001041d, 0x00010445, 0x0001041d, 0x0001041e, 0x00010446, 0x0001041e, 0x0001041f, 0x00010447, 0x0001041f, 0x00010420, 0x00010448, 0x00010420, 0x00010421, 0x00010449, 0x00010421, 0x00010422, 0x0001044a, 0x00010422, 0x00010423, 0x0001044b, 0x00010423, 0x00010424, 0x0001044c, 0x00010424, 0x00010425, 0x0001044d, 0x00010425, 0x00000061, 0x00000041, 0x00000041, 0x00000062, 0x00000042, 0x00000042, 0x00000063, 0x00000043, 0x00000043, 0x00000064, 0x00000044, 0x00000044, 0x00000065, 0x00000045, 0x00000045, 0x00000066, 0x00000046, 0x00000046, 0x00000067, 0x00000047, 0x00000047, 0x00000068, 0x00000048, 0x00000048, 0x00000069, 0x00000049, 0x00000049, 0x0000006a, 0x0000004a, 0x0000004a, 0x0000006b, 0x0000004b, 0x0000004b, 0x0000006c, 0x0000004c, 0x0000004c, 0x0000006d, 0x0000004d, 0x0000004d, 0x0000006e, 0x0000004e, 0x0000004e, 0x0000006f, 0x0000004f, 0x0000004f, 0x00000070, 0x00000050, 0x00000050, 0x00000071, 0x00000051, 0x00000051, 0x00000072, 0x00000052, 0x00000052, 0x00000073, 0x00000053, 0x00000053, 0x00000074, 0x00000054, 0x00000054, 0x00000075, 0x00000055, 0x00000055, 0x00000076, 0x00000056, 0x00000056, 0x00000077, 0x00000057, 0x00000057, 0x00000078, 0x00000058, 0x00000058, 0x00000079, 0x00000059, 0x00000059, 0x0000007a, 0x0000005a, 0x0000005a, 0x000000b5, 0x0000039c, 0x0000039c, 0x000000e0, 0x000000c0, 0x000000c0, 0x000000e1, 0x000000c1, 0x000000c1, 0x000000e2, 0x000000c2, 0x000000c2, 0x000000e3, 0x000000c3, 0x000000c3, 0x000000e4, 0x000000c4, 0x000000c4, 0x000000e5, 0x000000c5, 0x000000c5, 0x000000e6, 0x000000c6, 0x000000c6, 0x000000e7, 0x000000c7, 0x000000c7, 0x000000e8, 0x000000c8, 0x000000c8, 0x000000e9, 0x000000c9, 0x000000c9, 0x000000ea, 0x000000ca, 0x000000ca, 0x000000eb, 0x000000cb, 0x000000cb, 0x000000ec, 0x000000cc, 0x000000cc, 0x000000ed, 0x000000cd, 0x000000cd, 0x000000ee, 0x000000ce, 0x000000ce, 0x000000ef, 0x000000cf, 0x000000cf, 0x000000f0, 0x000000d0, 0x000000d0, 0x000000f1, 0x000000d1, 0x000000d1, 0x000000f2, 0x000000d2, 0x000000d2, 0x000000f3, 0x000000d3, 0x000000d3, 0x000000f4, 0x000000d4, 0x000000d4, 0x000000f5, 0x000000d5, 0x000000d5, 0x000000f6, 0x000000d6, 0x000000d6, 0x000000f8, 0x000000d8, 0x000000d8, 0x000000f9, 0x000000d9, 0x000000d9, 0x000000fa, 0x000000da, 0x000000da, 0x000000fb, 0x000000db, 0x000000db, 0x000000fc, 0x000000dc, 0x000000dc, 0x000000fd, 0x000000dd, 0x000000dd, 0x000000fe, 0x000000de, 0x000000de, 0x000000ff, 0x00000178, 0x00000178, 0x00000101, 0x00000100, 0x00000100, 0x00000103, 0x00000102, 0x00000102, 0x00000105, 0x00000104, 0x00000104, 0x00000107, 0x00000106, 0x00000106, 0x00000109, 0x00000108, 0x00000108, 0x0000010b, 0x0000010a, 0x0000010a, 0x0000010d, 0x0000010c, 0x0000010c, 0x0000010f, 0x0000010e, 0x0000010e, 0x00000111, 0x00000110, 0x00000110, 0x00000113, 0x00000112, 0x00000112, 0x00000115, 0x00000114, 0x00000114, 0x00000117, 0x00000116, 0x00000116, 0x00000119, 0x00000118, 0x00000118, 0x0000011b, 0x0000011a, 0x0000011a, 0x0000011d, 0x0000011c, 0x0000011c, 0x0000011f, 0x0000011e, 0x0000011e, 0x00000121, 0x00000120, 0x00000120, 0x00000123, 0x00000122, 0x00000122, 0x00000125, 0x00000124, 0x00000124, 0x00000127, 0x00000126, 0x00000126, 0x00000129, 0x00000128, 0x00000128, 0x0000012b, 0x0000012a, 0x0000012a, 0x0000012d, 0x0000012c, 0x0000012c, 0x0000012f, 0x0000012e, 0x0000012e, 0x00000131, 0x00000049, 0x00000049, 0x00000133, 0x00000132, 0x00000132, 0x00000135, 0x00000134, 0x00000134, 0x00000137, 0x00000136, 0x00000136, 0x0000013a, 0x00000139, 0x00000139, 0x0000013c, 0x0000013b, 0x0000013b, 0x0000013e, 0x0000013d, 0x0000013d, 0x00000140, 0x0000013f, 0x0000013f, 0x00000142, 0x00000141, 0x00000141, 0x00000144, 0x00000143, 0x00000143, 0x00000146, 0x00000145, 0x00000145, 0x00000148, 0x00000147, 0x00000147, 0x0000014b, 0x0000014a, 0x0000014a, 0x0000014d, 0x0000014c, 0x0000014c, 0x0000014f, 0x0000014e, 0x0000014e, 0x00000151, 0x00000150, 0x00000150, 0x00000153, 0x00000152, 0x00000152, 0x00000155, 0x00000154, 0x00000154, 0x00000157, 0x00000156, 0x00000156, 0x00000159, 0x00000158, 0x00000158, 0x0000015b, 0x0000015a, 0x0000015a, 0x0000015d, 0x0000015c, 0x0000015c, 0x0000015f, 0x0000015e, 0x0000015e, 0x00000161, 0x00000160, 0x00000160, 0x00000163, 0x00000162, 0x00000162, 0x00000165, 0x00000164, 0x00000164, 0x00000167, 0x00000166, 0x00000166, 0x00000169, 0x00000168, 0x00000168, 0x0000016b, 0x0000016a, 0x0000016a, 0x0000016d, 0x0000016c, 0x0000016c, 0x0000016f, 0x0000016e, 0x0000016e, 0x00000171, 0x00000170, 0x00000170, 0x00000173, 0x00000172, 0x00000172, 0x00000175, 0x00000174, 0x00000174, 0x00000177, 0x00000176, 0x00000176, 0x0000017a, 0x00000179, 0x00000179, 0x0000017c, 0x0000017b, 0x0000017b, 0x0000017e, 0x0000017d, 0x0000017d, 0x0000017f, 0x00000053, 0x00000053, 0x00000183, 0x00000182, 0x00000182, 0x00000185, 0x00000184, 0x00000184, 0x00000188, 0x00000187, 0x00000187, 0x0000018c, 0x0000018b, 0x0000018b, 0x00000192, 0x00000191, 0x00000191, 0x00000195, 0x000001f6, 0x000001f6, 0x00000199, 0x00000198, 0x00000198, 0x0000019e, 0x00000220, 0x00000220, 0x000001a1, 0x000001a0, 0x000001a0, 0x000001a3, 0x000001a2, 0x000001a2, 0x000001a5, 0x000001a4, 0x000001a4, 0x000001a8, 0x000001a7, 0x000001a7, 0x000001ad, 0x000001ac, 0x000001ac, 0x000001b0, 0x000001af, 0x000001af, 0x000001b4, 0x000001b3, 0x000001b3, 0x000001b6, 0x000001b5, 0x000001b5, 0x000001b9, 0x000001b8, 0x000001b8, 0x000001bd, 0x000001bc, 0x000001bc, 0x000001bf, 0x000001f7, 0x000001f7, 0x000001c6, 0x000001c4, 0x000001c5, 0x000001c9, 0x000001c7, 0x000001c8, 0x000001cc, 0x000001ca, 0x000001cb, 0x000001ce, 0x000001cd, 0x000001cd, 0x000001d0, 0x000001cf, 0x000001cf, 0x000001d2, 0x000001d1, 0x000001d1, 0x000001d4, 0x000001d3, 0x000001d3, 0x000001d6, 0x000001d5, 0x000001d5, 0x000001d8, 0x000001d7, 0x000001d7, 0x000001da, 0x000001d9, 0x000001d9, 0x000001dc, 0x000001db, 0x000001db, 0x000001dd, 0x0000018e, 0x0000018e, 0x000001df, 0x000001de, 0x000001de, 0x000001e1, 0x000001e0, 0x000001e0, 0x000001e3, 0x000001e2, 0x000001e2, 0x000001e5, 0x000001e4, 0x000001e4, 0x000001e7, 0x000001e6, 0x000001e6, 0x000001e9, 0x000001e8, 0x000001e8, 0x000001eb, 0x000001ea, 0x000001ea, 0x000001ed, 0x000001ec, 0x000001ec, 0x000001ef, 0x000001ee, 0x000001ee, 0x000001f3, 0x000001f1, 0x000001f2, 0x000001f5, 0x000001f4, 0x000001f4, 0x000001f9, 0x000001f8, 0x000001f8, 0x000001fb, 0x000001fa, 0x000001fa, 0x000001fd, 0x000001fc, 0x000001fc, 0x000001ff, 0x000001fe, 0x000001fe, 0x00000201, 0x00000200, 0x00000200, 0x00000203, 0x00000202, 0x00000202, 0x00000205, 0x00000204, 0x00000204, 0x00000207, 0x00000206, 0x00000206, 0x00000209, 0x00000208, 0x00000208, 0x0000020b, 0x0000020a, 0x0000020a, 0x0000020d, 0x0000020c, 0x0000020c, 0x0000020f, 0x0000020e, 0x0000020e, 0x00000211, 0x00000210, 0x00000210, 0x00000213, 0x00000212, 0x00000212, 0x00000215, 0x00000214, 0x00000214, 0x00000217, 0x00000216, 0x00000216, 0x00000219, 0x00000218, 0x00000218, 0x0000021b, 0x0000021a, 0x0000021a, 0x0000021d, 0x0000021c, 0x0000021c, 0x0000021f, 0x0000021e, 0x0000021e, 0x00000223, 0x00000222, 0x00000222, 0x00000225, 0x00000224, 0x00000224, 0x00000227, 0x00000226, 0x00000226, 0x00000229, 0x00000228, 0x00000228, 0x0000022b, 0x0000022a, 0x0000022a, 0x0000022d, 0x0000022c, 0x0000022c, 0x0000022f, 0x0000022e, 0x0000022e, 0x00000231, 0x00000230, 0x00000230, 0x00000233, 0x00000232, 0x00000232, 0x00000253, 0x00000181, 0x00000181, 0x00000254, 0x00000186, 0x00000186, 0x00000256, 0x00000189, 0x00000189, 0x00000257, 0x0000018a, 0x0000018a, 0x00000259, 0x0000018f, 0x0000018f, 0x0000025b, 0x00000190, 0x00000190, 0x00000260, 0x00000193, 0x00000193, 0x00000263, 0x00000194, 0x00000194, 0x00000268, 0x00000197, 0x00000197, 0x00000269, 0x00000196, 0x00000196, 0x0000026f, 0x0000019c, 0x0000019c, 0x00000272, 0x0000019d, 0x0000019d, 0x00000275, 0x0000019f, 0x0000019f, 0x00000280, 0x000001a6, 0x000001a6, 0x00000283, 0x000001a9, 0x000001a9, 0x00000288, 0x000001ae, 0x000001ae, 0x0000028a, 0x000001b1, 0x000001b1, 0x0000028b, 0x000001b2, 0x000001b2, 0x00000292, 0x000001b7, 0x000001b7, 0x00000345, 0x00000399, 0x00000399, 0x000003ac, 0x00000386, 0x00000386, 0x000003ad, 0x00000388, 0x00000388, 0x000003ae, 0x00000389, 0x00000389, 0x000003af, 0x0000038a, 0x0000038a, 0x000003b1, 0x00000391, 0x00000391, 0x000003b2, 0x00000392, 0x00000392, 0x000003b3, 0x00000393, 0x00000393, 0x000003b4, 0x00000394, 0x00000394, 0x000003b5, 0x00000395, 0x00000395, 0x000003b6, 0x00000396, 0x00000396, 0x000003b7, 0x00000397, 0x00000397, 0x000003b8, 0x00000398, 0x00000398, 0x000003b9, 0x00000399, 0x00000399, 0x000003ba, 0x0000039a, 0x0000039a, 0x000003bb, 0x0000039b, 0x0000039b, 0x000003bc, 0x0000039c, 0x0000039c, 0x000003bd, 0x0000039d, 0x0000039d, 0x000003be, 0x0000039e, 0x0000039e, 0x000003bf, 0x0000039f, 0x0000039f, 0x000003c0, 0x000003a0, 0x000003a0, 0x000003c1, 0x000003a1, 0x000003a1, 0x000003c2, 0x000003a3, 0x000003a3, 0x000003c3, 0x000003a3, 0x000003a3, 0x000003c4, 0x000003a4, 0x000003a4, 0x000003c5, 0x000003a5, 0x000003a5, 0x000003c6, 0x000003a6, 0x000003a6, 0x000003c7, 0x000003a7, 0x000003a7, 0x000003c8, 0x000003a8, 0x000003a8, 0x000003c9, 0x000003a9, 0x000003a9, 0x000003ca, 0x000003aa, 0x000003aa, 0x000003cb, 0x000003ab, 0x000003ab, 0x000003cc, 0x0000038c, 0x0000038c, 0x000003cd, 0x0000038e, 0x0000038e, 0x000003ce, 0x0000038f, 0x0000038f, 0x000003d0, 0x00000392, 0x00000392, 0x000003d1, 0x00000398, 0x00000398, 0x000003d5, 0x000003a6, 0x000003a6, 0x000003d6, 0x000003a0, 0x000003a0, 0x000003d9, 0x000003d8, 0x000003d8, 0x000003db, 0x000003da, 0x000003da, 0x000003dd, 0x000003dc, 0x000003dc, 0x000003df, 0x000003de, 0x000003de, 0x000003e1, 0x000003e0, 0x000003e0, 0x000003e3, 0x000003e2, 0x000003e2, 0x000003e5, 0x000003e4, 0x000003e4, 0x000003e7, 0x000003e6, 0x000003e6, 0x000003e9, 0x000003e8, 0x000003e8, 0x000003eb, 0x000003ea, 0x000003ea, 0x000003ed, 0x000003ec, 0x000003ec, 0x000003ef, 0x000003ee, 0x000003ee, 0x000003f0, 0x0000039a, 0x0000039a, 0x000003f1, 0x000003a1, 0x000003a1, 0x000003f2, 0x000003a3, 0x000003a3, 0x000003f5, 0x00000395, 0x00000395, 0x00000430, 0x00000410, 0x00000410, 0x00000431, 0x00000411, 0x00000411, 0x00000432, 0x00000412, 0x00000412, 0x00000433, 0x00000413, 0x00000413, 0x00000434, 0x00000414, 0x00000414, 0x00000435, 0x00000415, 0x00000415, 0x00000436, 0x00000416, 0x00000416, 0x00000437, 0x00000417, 0x00000417, 0x00000438, 0x00000418, 0x00000418, 0x00000439, 0x00000419, 0x00000419, 0x0000043a, 0x0000041a, 0x0000041a, 0x0000043b, 0x0000041b, 0x0000041b, 0x0000043c, 0x0000041c, 0x0000041c, 0x0000043d, 0x0000041d, 0x0000041d, 0x0000043e, 0x0000041e, 0x0000041e, 0x0000043f, 0x0000041f, 0x0000041f, 0x00000440, 0x00000420, 0x00000420, 0x00000441, 0x00000421, 0x00000421, 0x00000442, 0x00000422, 0x00000422, 0x00000443, 0x00000423, 0x00000423, 0x00000444, 0x00000424, 0x00000424, 0x00000445, 0x00000425, 0x00000425, 0x00000446, 0x00000426, 0x00000426, 0x00000447, 0x00000427, 0x00000427, 0x00000448, 0x00000428, 0x00000428, 0x00000449, 0x00000429, 0x00000429, 0x0000044a, 0x0000042a, 0x0000042a, 0x0000044b, 0x0000042b, 0x0000042b, 0x0000044c, 0x0000042c, 0x0000042c, 0x0000044d, 0x0000042d, 0x0000042d, 0x0000044e, 0x0000042e, 0x0000042e, 0x0000044f, 0x0000042f, 0x0000042f, 0x00000450, 0x00000400, 0x00000400, 0x00000451, 0x00000401, 0x00000401, 0x00000452, 0x00000402, 0x00000402, 0x00000453, 0x00000403, 0x00000403, 0x00000454, 0x00000404, 0x00000404, 0x00000455, 0x00000405, 0x00000405, 0x00000456, 0x00000406, 0x00000406, 0x00000457, 0x00000407, 0x00000407, 0x00000458, 0x00000408, 0x00000408, 0x00000459, 0x00000409, 0x00000409, 0x0000045a, 0x0000040a, 0x0000040a, 0x0000045b, 0x0000040b, 0x0000040b, 0x0000045c, 0x0000040c, 0x0000040c, 0x0000045d, 0x0000040d, 0x0000040d, 0x0000045e, 0x0000040e, 0x0000040e, 0x0000045f, 0x0000040f, 0x0000040f, 0x00000461, 0x00000460, 0x00000460, 0x00000463, 0x00000462, 0x00000462, 0x00000465, 0x00000464, 0x00000464, 0x00000467, 0x00000466, 0x00000466, 0x00000469, 0x00000468, 0x00000468, 0x0000046b, 0x0000046a, 0x0000046a, 0x0000046d, 0x0000046c, 0x0000046c, 0x0000046f, 0x0000046e, 0x0000046e, 0x00000471, 0x00000470, 0x00000470, 0x00000473, 0x00000472, 0x00000472, 0x00000475, 0x00000474, 0x00000474, 0x00000477, 0x00000476, 0x00000476, 0x00000479, 0x00000478, 0x00000478, 0x0000047b, 0x0000047a, 0x0000047a, 0x0000047d, 0x0000047c, 0x0000047c, 0x0000047f, 0x0000047e, 0x0000047e, 0x00000481, 0x00000480, 0x00000480, 0x0000048b, 0x0000048a, 0x0000048a, 0x0000048d, 0x0000048c, 0x0000048c, 0x0000048f, 0x0000048e, 0x0000048e, 0x00000491, 0x00000490, 0x00000490, 0x00000493, 0x00000492, 0x00000492, 0x00000495, 0x00000494, 0x00000494, 0x00000497, 0x00000496, 0x00000496, 0x00000499, 0x00000498, 0x00000498, 0x0000049b, 0x0000049a, 0x0000049a, 0x0000049d, 0x0000049c, 0x0000049c, 0x0000049f, 0x0000049e, 0x0000049e, 0x000004a1, 0x000004a0, 0x000004a0, 0x000004a3, 0x000004a2, 0x000004a2, 0x000004a5, 0x000004a4, 0x000004a4, 0x000004a7, 0x000004a6, 0x000004a6, 0x000004a9, 0x000004a8, 0x000004a8, 0x000004ab, 0x000004aa, 0x000004aa, 0x000004ad, 0x000004ac, 0x000004ac, 0x000004af, 0x000004ae, 0x000004ae, 0x000004b1, 0x000004b0, 0x000004b0, 0x000004b3, 0x000004b2, 0x000004b2, 0x000004b5, 0x000004b4, 0x000004b4, 0x000004b7, 0x000004b6, 0x000004b6, 0x000004b9, 0x000004b8, 0x000004b8, 0x000004bb, 0x000004ba, 0x000004ba, 0x000004bd, 0x000004bc, 0x000004bc, 0x000004bf, 0x000004be, 0x000004be, 0x000004c2, 0x000004c1, 0x000004c1, 0x000004c4, 0x000004c3, 0x000004c3, 0x000004c6, 0x000004c5, 0x000004c5, 0x000004c8, 0x000004c7, 0x000004c7, 0x000004ca, 0x000004c9, 0x000004c9, 0x000004cc, 0x000004cb, 0x000004cb, 0x000004ce, 0x000004cd, 0x000004cd, 0x000004d1, 0x000004d0, 0x000004d0, 0x000004d3, 0x000004d2, 0x000004d2, 0x000004d5, 0x000004d4, 0x000004d4, 0x000004d7, 0x000004d6, 0x000004d6, 0x000004d9, 0x000004d8, 0x000004d8, 0x000004db, 0x000004da, 0x000004da, 0x000004dd, 0x000004dc, 0x000004dc, 0x000004df, 0x000004de, 0x000004de, 0x000004e1, 0x000004e0, 0x000004e0, 0x000004e3, 0x000004e2, 0x000004e2, 0x000004e5, 0x000004e4, 0x000004e4, 0x000004e7, 0x000004e6, 0x000004e6, 0x000004e9, 0x000004e8, 0x000004e8, 0x000004eb, 0x000004ea, 0x000004ea, 0x000004ed, 0x000004ec, 0x000004ec, 0x000004ef, 0x000004ee, 0x000004ee, 0x000004f1, 0x000004f0, 0x000004f0, 0x000004f3, 0x000004f2, 0x000004f2, 0x000004f5, 0x000004f4, 0x000004f4, 0x000004f9, 0x000004f8, 0x000004f8, 0x00000501, 0x00000500, 0x00000500, 0x00000503, 0x00000502, 0x00000502, 0x00000505, 0x00000504, 0x00000504, 0x00000507, 0x00000506, 0x00000506, 0x00000509, 0x00000508, 0x00000508, 0x0000050b, 0x0000050a, 0x0000050a, 0x0000050d, 0x0000050c, 0x0000050c, 0x0000050f, 0x0000050e, 0x0000050e, 0x00000561, 0x00000531, 0x00000531, 0x00000562, 0x00000532, 0x00000532, 0x00000563, 0x00000533, 0x00000533, 0x00000564, 0x00000534, 0x00000534, 0x00000565, 0x00000535, 0x00000535, 0x00000566, 0x00000536, 0x00000536, 0x00000567, 0x00000537, 0x00000537, 0x00000568, 0x00000538, 0x00000538, 0x00000569, 0x00000539, 0x00000539, 0x0000056a, 0x0000053a, 0x0000053a, 0x0000056b, 0x0000053b, 0x0000053b, 0x0000056c, 0x0000053c, 0x0000053c, 0x0000056d, 0x0000053d, 0x0000053d, 0x0000056e, 0x0000053e, 0x0000053e, 0x0000056f, 0x0000053f, 0x0000053f, 0x00000570, 0x00000540, 0x00000540, 0x00000571, 0x00000541, 0x00000541, 0x00000572, 0x00000542, 0x00000542, 0x00000573, 0x00000543, 0x00000543, 0x00000574, 0x00000544, 0x00000544, 0x00000575, 0x00000545, 0x00000545, 0x00000576, 0x00000546, 0x00000546, 0x00000577, 0x00000547, 0x00000547, 0x00000578, 0x00000548, 0x00000548, 0x00000579, 0x00000549, 0x00000549, 0x0000057a, 0x0000054a, 0x0000054a, 0x0000057b, 0x0000054b, 0x0000054b, 0x0000057c, 0x0000054c, 0x0000054c, 0x0000057d, 0x0000054d, 0x0000054d, 0x0000057e, 0x0000054e, 0x0000054e, 0x0000057f, 0x0000054f, 0x0000054f, 0x00000580, 0x00000550, 0x00000550, 0x00000581, 0x00000551, 0x00000551, 0x00000582, 0x00000552, 0x00000552, 0x00000583, 0x00000553, 0x00000553, 0x00000584, 0x00000554, 0x00000554, 0x00000585, 0x00000555, 0x00000555, 0x00000586, 0x00000556, 0x00000556, 0x00001e01, 0x00001e00, 0x00001e00, 0x00001e03, 0x00001e02, 0x00001e02, 0x00001e05, 0x00001e04, 0x00001e04, 0x00001e07, 0x00001e06, 0x00001e06, 0x00001e09, 0x00001e08, 0x00001e08, 0x00001e0b, 0x00001e0a, 0x00001e0a, 0x00001e0d, 0x00001e0c, 0x00001e0c, 0x00001e0f, 0x00001e0e, 0x00001e0e, 0x00001e11, 0x00001e10, 0x00001e10, 0x00001e13, 0x00001e12, 0x00001e12, 0x00001e15, 0x00001e14, 0x00001e14, 0x00001e17, 0x00001e16, 0x00001e16, 0x00001e19, 0x00001e18, 0x00001e18, 0x00001e1b, 0x00001e1a, 0x00001e1a, 0x00001e1d, 0x00001e1c, 0x00001e1c, 0x00001e1f, 0x00001e1e, 0x00001e1e, 0x00001e21, 0x00001e20, 0x00001e20, 0x00001e23, 0x00001e22, 0x00001e22, 0x00001e25, 0x00001e24, 0x00001e24, 0x00001e27, 0x00001e26, 0x00001e26, 0x00001e29, 0x00001e28, 0x00001e28, 0x00001e2b, 0x00001e2a, 0x00001e2a, 0x00001e2d, 0x00001e2c, 0x00001e2c, 0x00001e2f, 0x00001e2e, 0x00001e2e, 0x00001e31, 0x00001e30, 0x00001e30, 0x00001e33, 0x00001e32, 0x00001e32, 0x00001e35, 0x00001e34, 0x00001e34, 0x00001e37, 0x00001e36, 0x00001e36, 0x00001e39, 0x00001e38, 0x00001e38, 0x00001e3b, 0x00001e3a, 0x00001e3a, 0x00001e3d, 0x00001e3c, 0x00001e3c, 0x00001e3f, 0x00001e3e, 0x00001e3e, 0x00001e41, 0x00001e40, 0x00001e40, 0x00001e43, 0x00001e42, 0x00001e42, 0x00001e45, 0x00001e44, 0x00001e44, 0x00001e47, 0x00001e46, 0x00001e46, 0x00001e49, 0x00001e48, 0x00001e48, 0x00001e4b, 0x00001e4a, 0x00001e4a, 0x00001e4d, 0x00001e4c, 0x00001e4c, 0x00001e4f, 0x00001e4e, 0x00001e4e, 0x00001e51, 0x00001e50, 0x00001e50, 0x00001e53, 0x00001e52, 0x00001e52, 0x00001e55, 0x00001e54, 0x00001e54, 0x00001e57, 0x00001e56, 0x00001e56, 0x00001e59, 0x00001e58, 0x00001e58, 0x00001e5b, 0x00001e5a, 0x00001e5a, 0x00001e5d, 0x00001e5c, 0x00001e5c, 0x00001e5f, 0x00001e5e, 0x00001e5e, 0x00001e61, 0x00001e60, 0x00001e60, 0x00001e63, 0x00001e62, 0x00001e62, 0x00001e65, 0x00001e64, 0x00001e64, 0x00001e67, 0x00001e66, 0x00001e66, 0x00001e69, 0x00001e68, 0x00001e68, 0x00001e6b, 0x00001e6a, 0x00001e6a, 0x00001e6d, 0x00001e6c, 0x00001e6c, 0x00001e6f, 0x00001e6e, 0x00001e6e, 0x00001e71, 0x00001e70, 0x00001e70, 0x00001e73, 0x00001e72, 0x00001e72, 0x00001e75, 0x00001e74, 0x00001e74, 0x00001e77, 0x00001e76, 0x00001e76, 0x00001e79, 0x00001e78, 0x00001e78, 0x00001e7b, 0x00001e7a, 0x00001e7a, 0x00001e7d, 0x00001e7c, 0x00001e7c, 0x00001e7f, 0x00001e7e, 0x00001e7e, 0x00001e81, 0x00001e80, 0x00001e80, 0x00001e83, 0x00001e82, 0x00001e82, 0x00001e85, 0x00001e84, 0x00001e84, 0x00001e87, 0x00001e86, 0x00001e86, 0x00001e89, 0x00001e88, 0x00001e88, 0x00001e8b, 0x00001e8a, 0x00001e8a, 0x00001e8d, 0x00001e8c, 0x00001e8c, 0x00001e8f, 0x00001e8e, 0x00001e8e, 0x00001e91, 0x00001e90, 0x00001e90, 0x00001e93, 0x00001e92, 0x00001e92, 0x00001e95, 0x00001e94, 0x00001e94, 0x00001e9b, 0x00001e60, 0x00001e60, 0x00001ea1, 0x00001ea0, 0x00001ea0, 0x00001ea3, 0x00001ea2, 0x00001ea2, 0x00001ea5, 0x00001ea4, 0x00001ea4, 0x00001ea7, 0x00001ea6, 0x00001ea6, 0x00001ea9, 0x00001ea8, 0x00001ea8, 0x00001eab, 0x00001eaa, 0x00001eaa, 0x00001ead, 0x00001eac, 0x00001eac, 0x00001eaf, 0x00001eae, 0x00001eae, 0x00001eb1, 0x00001eb0, 0x00001eb0, 0x00001eb3, 0x00001eb2, 0x00001eb2, 0x00001eb5, 0x00001eb4, 0x00001eb4, 0x00001eb7, 0x00001eb6, 0x00001eb6, 0x00001eb9, 0x00001eb8, 0x00001eb8, 0x00001ebb, 0x00001eba, 0x00001eba, 0x00001ebd, 0x00001ebc, 0x00001ebc, 0x00001ebf, 0x00001ebe, 0x00001ebe, 0x00001ec1, 0x00001ec0, 0x00001ec0, 0x00001ec3, 0x00001ec2, 0x00001ec2, 0x00001ec5, 0x00001ec4, 0x00001ec4, 0x00001ec7, 0x00001ec6, 0x00001ec6, 0x00001ec9, 0x00001ec8, 0x00001ec8, 0x00001ecb, 0x00001eca, 0x00001eca, 0x00001ecd, 0x00001ecc, 0x00001ecc, 0x00001ecf, 0x00001ece, 0x00001ece, 0x00001ed1, 0x00001ed0, 0x00001ed0, 0x00001ed3, 0x00001ed2, 0x00001ed2, 0x00001ed5, 0x00001ed4, 0x00001ed4, 0x00001ed7, 0x00001ed6, 0x00001ed6, 0x00001ed9, 0x00001ed8, 0x00001ed8, 0x00001edb, 0x00001eda, 0x00001eda, 0x00001edd, 0x00001edc, 0x00001edc, 0x00001edf, 0x00001ede, 0x00001ede, 0x00001ee1, 0x00001ee0, 0x00001ee0, 0x00001ee3, 0x00001ee2, 0x00001ee2, 0x00001ee5, 0x00001ee4, 0x00001ee4, 0x00001ee7, 0x00001ee6, 0x00001ee6, 0x00001ee9, 0x00001ee8, 0x00001ee8, 0x00001eeb, 0x00001eea, 0x00001eea, 0x00001eed, 0x00001eec, 0x00001eec, 0x00001eef, 0x00001eee, 0x00001eee, 0x00001ef1, 0x00001ef0, 0x00001ef0, 0x00001ef3, 0x00001ef2, 0x00001ef2, 0x00001ef5, 0x00001ef4, 0x00001ef4, 0x00001ef7, 0x00001ef6, 0x00001ef6, 0x00001ef9, 0x00001ef8, 0x00001ef8, 0x00001f00, 0x00001f08, 0x00001f08, 0x00001f01, 0x00001f09, 0x00001f09, 0x00001f02, 0x00001f0a, 0x00001f0a, 0x00001f03, 0x00001f0b, 0x00001f0b, 0x00001f04, 0x00001f0c, 0x00001f0c, 0x00001f05, 0x00001f0d, 0x00001f0d, 0x00001f06, 0x00001f0e, 0x00001f0e, 0x00001f07, 0x00001f0f, 0x00001f0f, 0x00001f10, 0x00001f18, 0x00001f18, 0x00001f11, 0x00001f19, 0x00001f19, 0x00001f12, 0x00001f1a, 0x00001f1a, 0x00001f13, 0x00001f1b, 0x00001f1b, 0x00001f14, 0x00001f1c, 0x00001f1c, 0x00001f15, 0x00001f1d, 0x00001f1d, 0x00001f20, 0x00001f28, 0x00001f28, 0x00001f21, 0x00001f29, 0x00001f29, 0x00001f22, 0x00001f2a, 0x00001f2a, 0x00001f23, 0x00001f2b, 0x00001f2b, 0x00001f24, 0x00001f2c, 0x00001f2c, 0x00001f25, 0x00001f2d, 0x00001f2d, 0x00001f26, 0x00001f2e, 0x00001f2e, 0x00001f27, 0x00001f2f, 0x00001f2f, 0x00001f30, 0x00001f38, 0x00001f38, 0x00001f31, 0x00001f39, 0x00001f39, 0x00001f32, 0x00001f3a, 0x00001f3a, 0x00001f33, 0x00001f3b, 0x00001f3b, 0x00001f34, 0x00001f3c, 0x00001f3c, 0x00001f35, 0x00001f3d, 0x00001f3d, 0x00001f36, 0x00001f3e, 0x00001f3e, 0x00001f37, 0x00001f3f, 0x00001f3f, 0x00001f40, 0x00001f48, 0x00001f48, 0x00001f41, 0x00001f49, 0x00001f49, 0x00001f42, 0x00001f4a, 0x00001f4a, 0x00001f43, 0x00001f4b, 0x00001f4b, 0x00001f44, 0x00001f4c, 0x00001f4c, 0x00001f45, 0x00001f4d, 0x00001f4d, 0x00001f51, 0x00001f59, 0x00001f59, 0x00001f53, 0x00001f5b, 0x00001f5b, 0x00001f55, 0x00001f5d, 0x00001f5d, 0x00001f57, 0x00001f5f, 0x00001f5f, 0x00001f60, 0x00001f68, 0x00001f68, 0x00001f61, 0x00001f69, 0x00001f69, 0x00001f62, 0x00001f6a, 0x00001f6a, 0x00001f63, 0x00001f6b, 0x00001f6b, 0x00001f64, 0x00001f6c, 0x00001f6c, 0x00001f65, 0x00001f6d, 0x00001f6d, 0x00001f66, 0x00001f6e, 0x00001f6e, 0x00001f67, 0x00001f6f, 0x00001f6f, 0x00001f70, 0x00001fba, 0x00001fba, 0x00001f71, 0x00001fbb, 0x00001fbb, 0x00001f72, 0x00001fc8, 0x00001fc8, 0x00001f73, 0x00001fc9, 0x00001fc9, 0x00001f74, 0x00001fca, 0x00001fca, 0x00001f75, 0x00001fcb, 0x00001fcb, 0x00001f76, 0x00001fda, 0x00001fda, 0x00001f77, 0x00001fdb, 0x00001fdb, 0x00001f78, 0x00001ff8, 0x00001ff8, 0x00001f79, 0x00001ff9, 0x00001ff9, 0x00001f7a, 0x00001fea, 0x00001fea, 0x00001f7b, 0x00001feb, 0x00001feb, 0x00001f7c, 0x00001ffa, 0x00001ffa, 0x00001f7d, 0x00001ffb, 0x00001ffb, 0x00001f80, 0x00001f88, 0x00001f88, 0x00001f81, 0x00001f89, 0x00001f89, 0x00001f82, 0x00001f8a, 0x00001f8a, 0x00001f83, 0x00001f8b, 0x00001f8b, 0x00001f84, 0x00001f8c, 0x00001f8c, 0x00001f85, 0x00001f8d, 0x00001f8d, 0x00001f86, 0x00001f8e, 0x00001f8e, 0x00001f87, 0x00001f8f, 0x00001f8f, 0x00001f90, 0x00001f98, 0x00001f98, 0x00001f91, 0x00001f99, 0x00001f99, 0x00001f92, 0x00001f9a, 0x00001f9a, 0x00001f93, 0x00001f9b, 0x00001f9b, 0x00001f94, 0x00001f9c, 0x00001f9c, 0x00001f95, 0x00001f9d, 0x00001f9d, 0x00001f96, 0x00001f9e, 0x00001f9e, 0x00001f97, 0x00001f9f, 0x00001f9f, 0x00001fa0, 0x00001fa8, 0x00001fa8, 0x00001fa1, 0x00001fa9, 0x00001fa9, 0x00001fa2, 0x00001faa, 0x00001faa, 0x00001fa3, 0x00001fab, 0x00001fab, 0x00001fa4, 0x00001fac, 0x00001fac, 0x00001fa5, 0x00001fad, 0x00001fad, 0x00001fa6, 0x00001fae, 0x00001fae, 0x00001fa7, 0x00001faf, 0x00001faf, 0x00001fb0, 0x00001fb8, 0x00001fb8, 0x00001fb1, 0x00001fb9, 0x00001fb9, 0x00001fb3, 0x00001fbc, 0x00001fbc, 0x00001fbe, 0x00000399, 0x00000399, 0x00001fc3, 0x00001fcc, 0x00001fcc, 0x00001fd0, 0x00001fd8, 0x00001fd8, 0x00001fd1, 0x00001fd9, 0x00001fd9, 0x00001fe0, 0x00001fe8, 0x00001fe8, 0x00001fe1, 0x00001fe9, 0x00001fe9, 0x00001fe5, 0x00001fec, 0x00001fec, 0x00001ff3, 0x00001ffc, 0x00001ffc, 0x00002170, 0x00002160, 0x00002160, 0x00002171, 0x00002161, 0x00002161, 0x00002172, 0x00002162, 0x00002162, 0x00002173, 0x00002163, 0x00002163, 0x00002174, 0x00002164, 0x00002164, 0x00002175, 0x00002165, 0x00002165, 0x00002176, 0x00002166, 0x00002166, 0x00002177, 0x00002167, 0x00002167, 0x00002178, 0x00002168, 0x00002168, 0x00002179, 0x00002169, 0x00002169, 0x0000217a, 0x0000216a, 0x0000216a, 0x0000217b, 0x0000216b, 0x0000216b, 0x0000217c, 0x0000216c, 0x0000216c, 0x0000217d, 0x0000216d, 0x0000216d, 0x0000217e, 0x0000216e, 0x0000216e, 0x0000217f, 0x0000216f, 0x0000216f, 0x000024d0, 0x000024b6, 0x000024b6, 0x000024d1, 0x000024b7, 0x000024b7, 0x000024d2, 0x000024b8, 0x000024b8, 0x000024d3, 0x000024b9, 0x000024b9, 0x000024d4, 0x000024ba, 0x000024ba, 0x000024d5, 0x000024bb, 0x000024bb, 0x000024d6, 0x000024bc, 0x000024bc, 0x000024d7, 0x000024bd, 0x000024bd, 0x000024d8, 0x000024be, 0x000024be, 0x000024d9, 0x000024bf, 0x000024bf, 0x000024da, 0x000024c0, 0x000024c0, 0x000024db, 0x000024c1, 0x000024c1, 0x000024dc, 0x000024c2, 0x000024c2, 0x000024dd, 0x000024c3, 0x000024c3, 0x000024de, 0x000024c4, 0x000024c4, 0x000024df, 0x000024c5, 0x000024c5, 0x000024e0, 0x000024c6, 0x000024c6, 0x000024e1, 0x000024c7, 0x000024c7, 0x000024e2, 0x000024c8, 0x000024c8, 0x000024e3, 0x000024c9, 0x000024c9, 0x000024e4, 0x000024ca, 0x000024ca, 0x000024e5, 0x000024cb, 0x000024cb, 0x000024e6, 0x000024cc, 0x000024cc, 0x000024e7, 0x000024cd, 0x000024cd, 0x000024e8, 0x000024ce, 0x000024ce, 0x000024e9, 0x000024cf, 0x000024cf, 0x0000ff41, 0x0000ff21, 0x0000ff21, 0x0000ff42, 0x0000ff22, 0x0000ff22, 0x0000ff43, 0x0000ff23, 0x0000ff23, 0x0000ff44, 0x0000ff24, 0x0000ff24, 0x0000ff45, 0x0000ff25, 0x0000ff25, 0x0000ff46, 0x0000ff26, 0x0000ff26, 0x0000ff47, 0x0000ff27, 0x0000ff27, 0x0000ff48, 0x0000ff28, 0x0000ff28, 0x0000ff49, 0x0000ff29, 0x0000ff29, 0x0000ff4a, 0x0000ff2a, 0x0000ff2a, 0x0000ff4b, 0x0000ff2b, 0x0000ff2b, 0x0000ff4c, 0x0000ff2c, 0x0000ff2c, 0x0000ff4d, 0x0000ff2d, 0x0000ff2d, 0x0000ff4e, 0x0000ff2e, 0x0000ff2e, 0x0000ff4f, 0x0000ff2f, 0x0000ff2f, 0x0000ff50, 0x0000ff30, 0x0000ff30, 0x0000ff51, 0x0000ff31, 0x0000ff31, 0x0000ff52, 0x0000ff32, 0x0000ff32, 0x0000ff53, 0x0000ff33, 0x0000ff33, 0x0000ff54, 0x0000ff34, 0x0000ff34, 0x0000ff55, 0x0000ff35, 0x0000ff35, 0x0000ff56, 0x0000ff36, 0x0000ff36, 0x0000ff57, 0x0000ff37, 0x0000ff37, 0x0000ff58, 0x0000ff38, 0x0000ff38, 0x0000ff59, 0x0000ff39, 0x0000ff39, 0x0000ff5a, 0x0000ff3a, 0x0000ff3a, 0x00010428, 0x00010400, 0x00010400, 0x00010429, 0x00010401, 0x00010401, 0x0001042a, 0x00010402, 0x00010402, 0x0001042b, 0x00010403, 0x00010403, 0x0001042c, 0x00010404, 0x00010404, 0x0001042d, 0x00010405, 0x00010405, 0x0001042e, 0x00010406, 0x00010406, 0x0001042f, 0x00010407, 0x00010407, 0x00010430, 0x00010408, 0x00010408, 0x00010431, 0x00010409, 0x00010409, 0x00010432, 0x0001040a, 0x0001040a, 0x00010433, 0x0001040b, 0x0001040b, 0x00010434, 0x0001040c, 0x0001040c, 0x00010435, 0x0001040d, 0x0001040d, 0x00010436, 0x0001040e, 0x0001040e, 0x00010437, 0x0001040f, 0x0001040f, 0x00010438, 0x00010410, 0x00010410, 0x00010439, 0x00010411, 0x00010411, 0x0001043a, 0x00010412, 0x00010412, 0x0001043b, 0x00010413, 0x00010413, 0x0001043c, 0x00010414, 0x00010414, 0x0001043d, 0x00010415, 0x00010415, 0x0001043e, 0x00010416, 0x00010416, 0x0001043f, 0x00010417, 0x00010417, 0x00010440, 0x00010418, 0x00010418, 0x00010441, 0x00010419, 0x00010419, 0x00010442, 0x0001041a, 0x0001041a, 0x00010443, 0x0001041b, 0x0001041b, 0x00010444, 0x0001041c, 0x0001041c, 0x00010445, 0x0001041d, 0x0001041d, 0x00010446, 0x0001041e, 0x0001041e, 0x00010447, 0x0001041f, 0x0001041f, 0x00010448, 0x00010420, 0x00010420, 0x00010449, 0x00010421, 0x00010421, 0x0001044a, 0x00010422, 0x00010422, 0x0001044b, 0x00010423, 0x00010423, 0x0001044c, 0x00010424, 0x00010424, 0x0001044d, 0x00010425, 0x00010425, 0x000001c5, 0x000001c4, 0x000001c6, 0x000001c8, 0x000001c7, 0x000001c9, 0x000001cb, 0x000001ca, 0x000001cc, 0x000001f2, 0x000001f1, 0x000001f3 }; static const ac_uint4 _uccomp_size = 3684; static const ac_uint4 _uccomp_data[] = { 0x0000226e, 0x00000002, 0x0000003c, 0x00000338, 0x00002260, 0x00000002, 0x0000003d, 0x00000338, 0x0000226f, 0x00000002, 0x0000003e, 0x00000338, 0x000000c0, 0x00000002, 0x00000041, 0x00000300, 0x000000c1, 0x00000002, 0x00000041, 0x00000301, 0x000000c2, 0x00000002, 0x00000041, 0x00000302, 0x000000c3, 0x00000002, 0x00000041, 0x00000303, 0x00000100, 0x00000002, 0x00000041, 0x00000304, 0x00000102, 0x00000002, 0x00000041, 0x00000306, 0x00000226, 0x00000002, 0x00000041, 0x00000307, 0x000000c4, 0x00000002, 0x00000041, 0x00000308, 0x00001ea2, 0x00000002, 0x00000041, 0x00000309, 0x000000c5, 0x00000002, 0x00000041, 0x0000030a, 0x000001cd, 0x00000002, 0x00000041, 0x0000030c, 0x00000200, 0x00000002, 0x00000041, 0x0000030f, 0x00000202, 0x00000002, 0x00000041, 0x00000311, 0x00001ea0, 0x00000002, 0x00000041, 0x00000323, 0x00001e00, 0x00000002, 0x00000041, 0x00000325, 0x00000104, 0x00000002, 0x00000041, 0x00000328, 0x00001e02, 0x00000002, 0x00000042, 0x00000307, 0x00001e04, 0x00000002, 0x00000042, 0x00000323, 0x00001e06, 0x00000002, 0x00000042, 0x00000331, 0x00000106, 0x00000002, 0x00000043, 0x00000301, 0x00000108, 0x00000002, 0x00000043, 0x00000302, 0x0000010a, 0x00000002, 0x00000043, 0x00000307, 0x0000010c, 0x00000002, 0x00000043, 0x0000030c, 0x000000c7, 0x00000002, 0x00000043, 0x00000327, 0x00001e0a, 0x00000002, 0x00000044, 0x00000307, 0x0000010e, 0x00000002, 0x00000044, 0x0000030c, 0x00001e0c, 0x00000002, 0x00000044, 0x00000323, 0x00001e10, 0x00000002, 0x00000044, 0x00000327, 0x00001e12, 0x00000002, 0x00000044, 0x0000032d, 0x00001e0e, 0x00000002, 0x00000044, 0x00000331, 0x000000c8, 0x00000002, 0x00000045, 0x00000300, 0x000000c9, 0x00000002, 0x00000045, 0x00000301, 0x000000ca, 0x00000002, 0x00000045, 0x00000302, 0x00001ebc, 0x00000002, 0x00000045, 0x00000303, 0x00000112, 0x00000002, 0x00000045, 0x00000304, 0x00000114, 0x00000002, 0x00000045, 0x00000306, 0x00000116, 0x00000002, 0x00000045, 0x00000307, 0x000000cb, 0x00000002, 0x00000045, 0x00000308, 0x00001eba, 0x00000002, 0x00000045, 0x00000309, 0x0000011a, 0x00000002, 0x00000045, 0x0000030c, 0x00000204, 0x00000002, 0x00000045, 0x0000030f, 0x00000206, 0x00000002, 0x00000045, 0x00000311, 0x00001eb8, 0x00000002, 0x00000045, 0x00000323, 0x00000228, 0x00000002, 0x00000045, 0x00000327, 0x00000118, 0x00000002, 0x00000045, 0x00000328, 0x00001e18, 0x00000002, 0x00000045, 0x0000032d, 0x00001e1a, 0x00000002, 0x00000045, 0x00000330, 0x00001e1e, 0x00000002, 0x00000046, 0x00000307, 0x000001f4, 0x00000002, 0x00000047, 0x00000301, 0x0000011c, 0x00000002, 0x00000047, 0x00000302, 0x00001e20, 0x00000002, 0x00000047, 0x00000304, 0x0000011e, 0x00000002, 0x00000047, 0x00000306, 0x00000120, 0x00000002, 0x00000047, 0x00000307, 0x000001e6, 0x00000002, 0x00000047, 0x0000030c, 0x00000122, 0x00000002, 0x00000047, 0x00000327, 0x00000124, 0x00000002, 0x00000048, 0x00000302, 0x00001e22, 0x00000002, 0x00000048, 0x00000307, 0x00001e26, 0x00000002, 0x00000048, 0x00000308, 0x0000021e, 0x00000002, 0x00000048, 0x0000030c, 0x00001e24, 0x00000002, 0x00000048, 0x00000323, 0x00001e28, 0x00000002, 0x00000048, 0x00000327, 0x00001e2a, 0x00000002, 0x00000048, 0x0000032e, 0x000000cc, 0x00000002, 0x00000049, 0x00000300, 0x000000cd, 0x00000002, 0x00000049, 0x00000301, 0x000000ce, 0x00000002, 0x00000049, 0x00000302, 0x00000128, 0x00000002, 0x00000049, 0x00000303, 0x0000012a, 0x00000002, 0x00000049, 0x00000304, 0x0000012c, 0x00000002, 0x00000049, 0x00000306, 0x00000130, 0x00000002, 0x00000049, 0x00000307, 0x000000cf, 0x00000002, 0x00000049, 0x00000308, 0x00001ec8, 0x00000002, 0x00000049, 0x00000309, 0x000001cf, 0x00000002, 0x00000049, 0x0000030c, 0x00000208, 0x00000002, 0x00000049, 0x0000030f, 0x0000020a, 0x00000002, 0x00000049, 0x00000311, 0x00001eca, 0x00000002, 0x00000049, 0x00000323, 0x0000012e, 0x00000002, 0x00000049, 0x00000328, 0x00001e2c, 0x00000002, 0x00000049, 0x00000330, 0x00000134, 0x00000002, 0x0000004a, 0x00000302, 0x00001e30, 0x00000002, 0x0000004b, 0x00000301, 0x000001e8, 0x00000002, 0x0000004b, 0x0000030c, 0x00001e32, 0x00000002, 0x0000004b, 0x00000323, 0x00000136, 0x00000002, 0x0000004b, 0x00000327, 0x00001e34, 0x00000002, 0x0000004b, 0x00000331, 0x00000139, 0x00000002, 0x0000004c, 0x00000301, 0x0000013d, 0x00000002, 0x0000004c, 0x0000030c, 0x00001e36, 0x00000002, 0x0000004c, 0x00000323, 0x0000013b, 0x00000002, 0x0000004c, 0x00000327, 0x00001e3c, 0x00000002, 0x0000004c, 0x0000032d, 0x00001e3a, 0x00000002, 0x0000004c, 0x00000331, 0x00001e3e, 0x00000002, 0x0000004d, 0x00000301, 0x00001e40, 0x00000002, 0x0000004d, 0x00000307, 0x00001e42, 0x00000002, 0x0000004d, 0x00000323, 0x000001f8, 0x00000002, 0x0000004e, 0x00000300, 0x00000143, 0x00000002, 0x0000004e, 0x00000301, 0x000000d1, 0x00000002, 0x0000004e, 0x00000303, 0x00001e44, 0x00000002, 0x0000004e, 0x00000307, 0x00000147, 0x00000002, 0x0000004e, 0x0000030c, 0x00001e46, 0x00000002, 0x0000004e, 0x00000323, 0x00000145, 0x00000002, 0x0000004e, 0x00000327, 0x00001e4a, 0x00000002, 0x0000004e, 0x0000032d, 0x00001e48, 0x00000002, 0x0000004e, 0x00000331, 0x000000d2, 0x00000002, 0x0000004f, 0x00000300, 0x000000d3, 0x00000002, 0x0000004f, 0x00000301, 0x000000d4, 0x00000002, 0x0000004f, 0x00000302, 0x000000d5, 0x00000002, 0x0000004f, 0x00000303, 0x0000014c, 0x00000002, 0x0000004f, 0x00000304, 0x0000014e, 0x00000002, 0x0000004f, 0x00000306, 0x0000022e, 0x00000002, 0x0000004f, 0x00000307, 0x000000d6, 0x00000002, 0x0000004f, 0x00000308, 0x00001ece, 0x00000002, 0x0000004f, 0x00000309, 0x00000150, 0x00000002, 0x0000004f, 0x0000030b, 0x000001d1, 0x00000002, 0x0000004f, 0x0000030c, 0x0000020c, 0x00000002, 0x0000004f, 0x0000030f, 0x0000020e, 0x00000002, 0x0000004f, 0x00000311, 0x000001a0, 0x00000002, 0x0000004f, 0x0000031b, 0x00001ecc, 0x00000002, 0x0000004f, 0x00000323, 0x000001ea, 0x00000002, 0x0000004f, 0x00000328, 0x00001e54, 0x00000002, 0x00000050, 0x00000301, 0x00001e56, 0x00000002, 0x00000050, 0x00000307, 0x00000154, 0x00000002, 0x00000052, 0x00000301, 0x00001e58, 0x00000002, 0x00000052, 0x00000307, 0x00000158, 0x00000002, 0x00000052, 0x0000030c, 0x00000210, 0x00000002, 0x00000052, 0x0000030f, 0x00000212, 0x00000002, 0x00000052, 0x00000311, 0x00001e5a, 0x00000002, 0x00000052, 0x00000323, 0x00000156, 0x00000002, 0x00000052, 0x00000327, 0x00001e5e, 0x00000002, 0x00000052, 0x00000331, 0x0000015a, 0x00000002, 0x00000053, 0x00000301, 0x0000015c, 0x00000002, 0x00000053, 0x00000302, 0x00001e60, 0x00000002, 0x00000053, 0x00000307, 0x00000160, 0x00000002, 0x00000053, 0x0000030c, 0x00001e62, 0x00000002, 0x00000053, 0x00000323, 0x00000218, 0x00000002, 0x00000053, 0x00000326, 0x0000015e, 0x00000002, 0x00000053, 0x00000327, 0x00001e6a, 0x00000002, 0x00000054, 0x00000307, 0x00000164, 0x00000002, 0x00000054, 0x0000030c, 0x00001e6c, 0x00000002, 0x00000054, 0x00000323, 0x0000021a, 0x00000002, 0x00000054, 0x00000326, 0x00000162, 0x00000002, 0x00000054, 0x00000327, 0x00001e70, 0x00000002, 0x00000054, 0x0000032d, 0x00001e6e, 0x00000002, 0x00000054, 0x00000331, 0x000000d9, 0x00000002, 0x00000055, 0x00000300, 0x000000da, 0x00000002, 0x00000055, 0x00000301, 0x000000db, 0x00000002, 0x00000055, 0x00000302, 0x00000168, 0x00000002, 0x00000055, 0x00000303, 0x0000016a, 0x00000002, 0x00000055, 0x00000304, 0x0000016c, 0x00000002, 0x00000055, 0x00000306, 0x000000dc, 0x00000002, 0x00000055, 0x00000308, 0x00001ee6, 0x00000002, 0x00000055, 0x00000309, 0x0000016e, 0x00000002, 0x00000055, 0x0000030a, 0x00000170, 0x00000002, 0x00000055, 0x0000030b, 0x000001d3, 0x00000002, 0x00000055, 0x0000030c, 0x00000214, 0x00000002, 0x00000055, 0x0000030f, 0x00000216, 0x00000002, 0x00000055, 0x00000311, 0x000001af, 0x00000002, 0x00000055, 0x0000031b, 0x00001ee4, 0x00000002, 0x00000055, 0x00000323, 0x00001e72, 0x00000002, 0x00000055, 0x00000324, 0x00000172, 0x00000002, 0x00000055, 0x00000328, 0x00001e76, 0x00000002, 0x00000055, 0x0000032d, 0x00001e74, 0x00000002, 0x00000055, 0x00000330, 0x00001e7c, 0x00000002, 0x00000056, 0x00000303, 0x00001e7e, 0x00000002, 0x00000056, 0x00000323, 0x00001e80, 0x00000002, 0x00000057, 0x00000300, 0x00001e82, 0x00000002, 0x00000057, 0x00000301, 0x00000174, 0x00000002, 0x00000057, 0x00000302, 0x00001e86, 0x00000002, 0x00000057, 0x00000307, 0x00001e84, 0x00000002, 0x00000057, 0x00000308, 0x00001e88, 0x00000002, 0x00000057, 0x00000323, 0x00001e8a, 0x00000002, 0x00000058, 0x00000307, 0x00001e8c, 0x00000002, 0x00000058, 0x00000308, 0x00001ef2, 0x00000002, 0x00000059, 0x00000300, 0x000000dd, 0x00000002, 0x00000059, 0x00000301, 0x00000176, 0x00000002, 0x00000059, 0x00000302, 0x00001ef8, 0x00000002, 0x00000059, 0x00000303, 0x00000232, 0x00000002, 0x00000059, 0x00000304, 0x00001e8e, 0x00000002, 0x00000059, 0x00000307, 0x00000178, 0x00000002, 0x00000059, 0x00000308, 0x00001ef6, 0x00000002, 0x00000059, 0x00000309, 0x00001ef4, 0x00000002, 0x00000059, 0x00000323, 0x00000179, 0x00000002, 0x0000005a, 0x00000301, 0x00001e90, 0x00000002, 0x0000005a, 0x00000302, 0x0000017b, 0x00000002, 0x0000005a, 0x00000307, 0x0000017d, 0x00000002, 0x0000005a, 0x0000030c, 0x00001e92, 0x00000002, 0x0000005a, 0x00000323, 0x00001e94, 0x00000002, 0x0000005a, 0x00000331, 0x000000e0, 0x00000002, 0x00000061, 0x00000300, 0x000000e1, 0x00000002, 0x00000061, 0x00000301, 0x000000e2, 0x00000002, 0x00000061, 0x00000302, 0x000000e3, 0x00000002, 0x00000061, 0x00000303, 0x00000101, 0x00000002, 0x00000061, 0x00000304, 0x00000103, 0x00000002, 0x00000061, 0x00000306, 0x00000227, 0x00000002, 0x00000061, 0x00000307, 0x000000e4, 0x00000002, 0x00000061, 0x00000308, 0x00001ea3, 0x00000002, 0x00000061, 0x00000309, 0x000000e5, 0x00000002, 0x00000061, 0x0000030a, 0x000001ce, 0x00000002, 0x00000061, 0x0000030c, 0x00000201, 0x00000002, 0x00000061, 0x0000030f, 0x00000203, 0x00000002, 0x00000061, 0x00000311, 0x00001ea1, 0x00000002, 0x00000061, 0x00000323, 0x00001e01, 0x00000002, 0x00000061, 0x00000325, 0x00000105, 0x00000002, 0x00000061, 0x00000328, 0x00001e03, 0x00000002, 0x00000062, 0x00000307, 0x00001e05, 0x00000002, 0x00000062, 0x00000323, 0x00001e07, 0x00000002, 0x00000062, 0x00000331, 0x00000107, 0x00000002, 0x00000063, 0x00000301, 0x00000109, 0x00000002, 0x00000063, 0x00000302, 0x0000010b, 0x00000002, 0x00000063, 0x00000307, 0x0000010d, 0x00000002, 0x00000063, 0x0000030c, 0x000000e7, 0x00000002, 0x00000063, 0x00000327, 0x00001e0b, 0x00000002, 0x00000064, 0x00000307, 0x0000010f, 0x00000002, 0x00000064, 0x0000030c, 0x00001e0d, 0x00000002, 0x00000064, 0x00000323, 0x00001e11, 0x00000002, 0x00000064, 0x00000327, 0x00001e13, 0x00000002, 0x00000064, 0x0000032d, 0x00001e0f, 0x00000002, 0x00000064, 0x00000331, 0x000000e8, 0x00000002, 0x00000065, 0x00000300, 0x000000e9, 0x00000002, 0x00000065, 0x00000301, 0x000000ea, 0x00000002, 0x00000065, 0x00000302, 0x00001ebd, 0x00000002, 0x00000065, 0x00000303, 0x00000113, 0x00000002, 0x00000065, 0x00000304, 0x00000115, 0x00000002, 0x00000065, 0x00000306, 0x00000117, 0x00000002, 0x00000065, 0x00000307, 0x000000eb, 0x00000002, 0x00000065, 0x00000308, 0x00001ebb, 0x00000002, 0x00000065, 0x00000309, 0x0000011b, 0x00000002, 0x00000065, 0x0000030c, 0x00000205, 0x00000002, 0x00000065, 0x0000030f, 0x00000207, 0x00000002, 0x00000065, 0x00000311, 0x00001eb9, 0x00000002, 0x00000065, 0x00000323, 0x00000229, 0x00000002, 0x00000065, 0x00000327, 0x00000119, 0x00000002, 0x00000065, 0x00000328, 0x00001e19, 0x00000002, 0x00000065, 0x0000032d, 0x00001e1b, 0x00000002, 0x00000065, 0x00000330, 0x00001e1f, 0x00000002, 0x00000066, 0x00000307, 0x000001f5, 0x00000002, 0x00000067, 0x00000301, 0x0000011d, 0x00000002, 0x00000067, 0x00000302, 0x00001e21, 0x00000002, 0x00000067, 0x00000304, 0x0000011f, 0x00000002, 0x00000067, 0x00000306, 0x00000121, 0x00000002, 0x00000067, 0x00000307, 0x000001e7, 0x00000002, 0x00000067, 0x0000030c, 0x00000123, 0x00000002, 0x00000067, 0x00000327, 0x00000125, 0x00000002, 0x00000068, 0x00000302, 0x00001e23, 0x00000002, 0x00000068, 0x00000307, 0x00001e27, 0x00000002, 0x00000068, 0x00000308, 0x0000021f, 0x00000002, 0x00000068, 0x0000030c, 0x00001e25, 0x00000002, 0x00000068, 0x00000323, 0x00001e29, 0x00000002, 0x00000068, 0x00000327, 0x00001e2b, 0x00000002, 0x00000068, 0x0000032e, 0x00001e96, 0x00000002, 0x00000068, 0x00000331, 0x000000ec, 0x00000002, 0x00000069, 0x00000300, 0x000000ed, 0x00000002, 0x00000069, 0x00000301, 0x000000ee, 0x00000002, 0x00000069, 0x00000302, 0x00000129, 0x00000002, 0x00000069, 0x00000303, 0x0000012b, 0x00000002, 0x00000069, 0x00000304, 0x0000012d, 0x00000002, 0x00000069, 0x00000306, 0x000000ef, 0x00000002, 0x00000069, 0x00000308, 0x00001ec9, 0x00000002, 0x00000069, 0x00000309, 0x000001d0, 0x00000002, 0x00000069, 0x0000030c, 0x00000209, 0x00000002, 0x00000069, 0x0000030f, 0x0000020b, 0x00000002, 0x00000069, 0x00000311, 0x00001ecb, 0x00000002, 0x00000069, 0x00000323, 0x0000012f, 0x00000002, 0x00000069, 0x00000328, 0x00001e2d, 0x00000002, 0x00000069, 0x00000330, 0x00000135, 0x00000002, 0x0000006a, 0x00000302, 0x000001f0, 0x00000002, 0x0000006a, 0x0000030c, 0x00001e31, 0x00000002, 0x0000006b, 0x00000301, 0x000001e9, 0x00000002, 0x0000006b, 0x0000030c, 0x00001e33, 0x00000002, 0x0000006b, 0x00000323, 0x00000137, 0x00000002, 0x0000006b, 0x00000327, 0x00001e35, 0x00000002, 0x0000006b, 0x00000331, 0x0000013a, 0x00000002, 0x0000006c, 0x00000301, 0x0000013e, 0x00000002, 0x0000006c, 0x0000030c, 0x00001e37, 0x00000002, 0x0000006c, 0x00000323, 0x0000013c, 0x00000002, 0x0000006c, 0x00000327, 0x00001e3d, 0x00000002, 0x0000006c, 0x0000032d, 0x00001e3b, 0x00000002, 0x0000006c, 0x00000331, 0x00001e3f, 0x00000002, 0x0000006d, 0x00000301, 0x00001e41, 0x00000002, 0x0000006d, 0x00000307, 0x00001e43, 0x00000002, 0x0000006d, 0x00000323, 0x000001f9, 0x00000002, 0x0000006e, 0x00000300, 0x00000144, 0x00000002, 0x0000006e, 0x00000301, 0x000000f1, 0x00000002, 0x0000006e, 0x00000303, 0x00001e45, 0x00000002, 0x0000006e, 0x00000307, 0x00000148, 0x00000002, 0x0000006e, 0x0000030c, 0x00001e47, 0x00000002, 0x0000006e, 0x00000323, 0x00000146, 0x00000002, 0x0000006e, 0x00000327, 0x00001e4b, 0x00000002, 0x0000006e, 0x0000032d, 0x00001e49, 0x00000002, 0x0000006e, 0x00000331, 0x000000f2, 0x00000002, 0x0000006f, 0x00000300, 0x000000f3, 0x00000002, 0x0000006f, 0x00000301, 0x000000f4, 0x00000002, 0x0000006f, 0x00000302, 0x000000f5, 0x00000002, 0x0000006f, 0x00000303, 0x0000014d, 0x00000002, 0x0000006f, 0x00000304, 0x0000014f, 0x00000002, 0x0000006f, 0x00000306, 0x0000022f, 0x00000002, 0x0000006f, 0x00000307, 0x000000f6, 0x00000002, 0x0000006f, 0x00000308, 0x00001ecf, 0x00000002, 0x0000006f, 0x00000309, 0x00000151, 0x00000002, 0x0000006f, 0x0000030b, 0x000001d2, 0x00000002, 0x0000006f, 0x0000030c, 0x0000020d, 0x00000002, 0x0000006f, 0x0000030f, 0x0000020f, 0x00000002, 0x0000006f, 0x00000311, 0x000001a1, 0x00000002, 0x0000006f, 0x0000031b, 0x00001ecd, 0x00000002, 0x0000006f, 0x00000323, 0x000001eb, 0x00000002, 0x0000006f, 0x00000328, 0x00001e55, 0x00000002, 0x00000070, 0x00000301, 0x00001e57, 0x00000002, 0x00000070, 0x00000307, 0x00000155, 0x00000002, 0x00000072, 0x00000301, 0x00001e59, 0x00000002, 0x00000072, 0x00000307, 0x00000159, 0x00000002, 0x00000072, 0x0000030c, 0x00000211, 0x00000002, 0x00000072, 0x0000030f, 0x00000213, 0x00000002, 0x00000072, 0x00000311, 0x00001e5b, 0x00000002, 0x00000072, 0x00000323, 0x00000157, 0x00000002, 0x00000072, 0x00000327, 0x00001e5f, 0x00000002, 0x00000072, 0x00000331, 0x0000015b, 0x00000002, 0x00000073, 0x00000301, 0x0000015d, 0x00000002, 0x00000073, 0x00000302, 0x00001e61, 0x00000002, 0x00000073, 0x00000307, 0x00000161, 0x00000002, 0x00000073, 0x0000030c, 0x00001e63, 0x00000002, 0x00000073, 0x00000323, 0x00000219, 0x00000002, 0x00000073, 0x00000326, 0x0000015f, 0x00000002, 0x00000073, 0x00000327, 0x00001e6b, 0x00000002, 0x00000074, 0x00000307, 0x00001e97, 0x00000002, 0x00000074, 0x00000308, 0x00000165, 0x00000002, 0x00000074, 0x0000030c, 0x00001e6d, 0x00000002, 0x00000074, 0x00000323, 0x0000021b, 0x00000002, 0x00000074, 0x00000326, 0x00000163, 0x00000002, 0x00000074, 0x00000327, 0x00001e71, 0x00000002, 0x00000074, 0x0000032d, 0x00001e6f, 0x00000002, 0x00000074, 0x00000331, 0x000000f9, 0x00000002, 0x00000075, 0x00000300, 0x000000fa, 0x00000002, 0x00000075, 0x00000301, 0x000000fb, 0x00000002, 0x00000075, 0x00000302, 0x00000169, 0x00000002, 0x00000075, 0x00000303, 0x0000016b, 0x00000002, 0x00000075, 0x00000304, 0x0000016d, 0x00000002, 0x00000075, 0x00000306, 0x000000fc, 0x00000002, 0x00000075, 0x00000308, 0x00001ee7, 0x00000002, 0x00000075, 0x00000309, 0x0000016f, 0x00000002, 0x00000075, 0x0000030a, 0x00000171, 0x00000002, 0x00000075, 0x0000030b, 0x000001d4, 0x00000002, 0x00000075, 0x0000030c, 0x00000215, 0x00000002, 0x00000075, 0x0000030f, 0x00000217, 0x00000002, 0x00000075, 0x00000311, 0x000001b0, 0x00000002, 0x00000075, 0x0000031b, 0x00001ee5, 0x00000002, 0x00000075, 0x00000323, 0x00001e73, 0x00000002, 0x00000075, 0x00000324, 0x00000173, 0x00000002, 0x00000075, 0x00000328, 0x00001e77, 0x00000002, 0x00000075, 0x0000032d, 0x00001e75, 0x00000002, 0x00000075, 0x00000330, 0x00001e7d, 0x00000002, 0x00000076, 0x00000303, 0x00001e7f, 0x00000002, 0x00000076, 0x00000323, 0x00001e81, 0x00000002, 0x00000077, 0x00000300, 0x00001e83, 0x00000002, 0x00000077, 0x00000301, 0x00000175, 0x00000002, 0x00000077, 0x00000302, 0x00001e87, 0x00000002, 0x00000077, 0x00000307, 0x00001e85, 0x00000002, 0x00000077, 0x00000308, 0x00001e98, 0x00000002, 0x00000077, 0x0000030a, 0x00001e89, 0x00000002, 0x00000077, 0x00000323, 0x00001e8b, 0x00000002, 0x00000078, 0x00000307, 0x00001e8d, 0x00000002, 0x00000078, 0x00000308, 0x00001ef3, 0x00000002, 0x00000079, 0x00000300, 0x000000fd, 0x00000002, 0x00000079, 0x00000301, 0x00000177, 0x00000002, 0x00000079, 0x00000302, 0x00001ef9, 0x00000002, 0x00000079, 0x00000303, 0x00000233, 0x00000002, 0x00000079, 0x00000304, 0x00001e8f, 0x00000002, 0x00000079, 0x00000307, 0x000000ff, 0x00000002, 0x00000079, 0x00000308, 0x00001ef7, 0x00000002, 0x00000079, 0x00000309, 0x00001e99, 0x00000002, 0x00000079, 0x0000030a, 0x00001ef5, 0x00000002, 0x00000079, 0x00000323, 0x0000017a, 0x00000002, 0x0000007a, 0x00000301, 0x00001e91, 0x00000002, 0x0000007a, 0x00000302, 0x0000017c, 0x00000002, 0x0000007a, 0x00000307, 0x0000017e, 0x00000002, 0x0000007a, 0x0000030c, 0x00001e93, 0x00000002, 0x0000007a, 0x00000323, 0x00001e95, 0x00000002, 0x0000007a, 0x00000331, 0x00001fed, 0x00000002, 0x000000a8, 0x00000300, 0x00000385, 0x00000002, 0x000000a8, 0x00000301, 0x00001fc1, 0x00000002, 0x000000a8, 0x00000342, 0x00001ea6, 0x00000002, 0x000000c2, 0x00000300, 0x00001ea4, 0x00000002, 0x000000c2, 0x00000301, 0x00001eaa, 0x00000002, 0x000000c2, 0x00000303, 0x00001ea8, 0x00000002, 0x000000c2, 0x00000309, 0x000001de, 0x00000002, 0x000000c4, 0x00000304, 0x000001fa, 0x00000002, 0x000000c5, 0x00000301, 0x000001fc, 0x00000002, 0x000000c6, 0x00000301, 0x000001e2, 0x00000002, 0x000000c6, 0x00000304, 0x00001e08, 0x00000002, 0x000000c7, 0x00000301, 0x00001ec0, 0x00000002, 0x000000ca, 0x00000300, 0x00001ebe, 0x00000002, 0x000000ca, 0x00000301, 0x00001ec4, 0x00000002, 0x000000ca, 0x00000303, 0x00001ec2, 0x00000002, 0x000000ca, 0x00000309, 0x00001e2e, 0x00000002, 0x000000cf, 0x00000301, 0x00001ed2, 0x00000002, 0x000000d4, 0x00000300, 0x00001ed0, 0x00000002, 0x000000d4, 0x00000301, 0x00001ed6, 0x00000002, 0x000000d4, 0x00000303, 0x00001ed4, 0x00000002, 0x000000d4, 0x00000309, 0x00001e4c, 0x00000002, 0x000000d5, 0x00000301, 0x0000022c, 0x00000002, 0x000000d5, 0x00000304, 0x00001e4e, 0x00000002, 0x000000d5, 0x00000308, 0x0000022a, 0x00000002, 0x000000d6, 0x00000304, 0x000001fe, 0x00000002, 0x000000d8, 0x00000301, 0x000001db, 0x00000002, 0x000000dc, 0x00000300, 0x000001d7, 0x00000002, 0x000000dc, 0x00000301, 0x000001d5, 0x00000002, 0x000000dc, 0x00000304, 0x000001d9, 0x00000002, 0x000000dc, 0x0000030c, 0x00001ea7, 0x00000002, 0x000000e2, 0x00000300, 0x00001ea5, 0x00000002, 0x000000e2, 0x00000301, 0x00001eab, 0x00000002, 0x000000e2, 0x00000303, 0x00001ea9, 0x00000002, 0x000000e2, 0x00000309, 0x000001df, 0x00000002, 0x000000e4, 0x00000304, 0x000001fb, 0x00000002, 0x000000e5, 0x00000301, 0x000001fd, 0x00000002, 0x000000e6, 0x00000301, 0x000001e3, 0x00000002, 0x000000e6, 0x00000304, 0x00001e09, 0x00000002, 0x000000e7, 0x00000301, 0x00001ec1, 0x00000002, 0x000000ea, 0x00000300, 0x00001ebf, 0x00000002, 0x000000ea, 0x00000301, 0x00001ec5, 0x00000002, 0x000000ea, 0x00000303, 0x00001ec3, 0x00000002, 0x000000ea, 0x00000309, 0x00001e2f, 0x00000002, 0x000000ef, 0x00000301, 0x00001ed3, 0x00000002, 0x000000f4, 0x00000300, 0x00001ed1, 0x00000002, 0x000000f4, 0x00000301, 0x00001ed7, 0x00000002, 0x000000f4, 0x00000303, 0x00001ed5, 0x00000002, 0x000000f4, 0x00000309, 0x00001e4d, 0x00000002, 0x000000f5, 0x00000301, 0x0000022d, 0x00000002, 0x000000f5, 0x00000304, 0x00001e4f, 0x00000002, 0x000000f5, 0x00000308, 0x0000022b, 0x00000002, 0x000000f6, 0x00000304, 0x000001ff, 0x00000002, 0x000000f8, 0x00000301, 0x000001dc, 0x00000002, 0x000000fc, 0x00000300, 0x000001d8, 0x00000002, 0x000000fc, 0x00000301, 0x000001d6, 0x00000002, 0x000000fc, 0x00000304, 0x000001da, 0x00000002, 0x000000fc, 0x0000030c, 0x00001eb0, 0x00000002, 0x00000102, 0x00000300, 0x00001eae, 0x00000002, 0x00000102, 0x00000301, 0x00001eb4, 0x00000002, 0x00000102, 0x00000303, 0x00001eb2, 0x00000002, 0x00000102, 0x00000309, 0x00001eb1, 0x00000002, 0x00000103, 0x00000300, 0x00001eaf, 0x00000002, 0x00000103, 0x00000301, 0x00001eb5, 0x00000002, 0x00000103, 0x00000303, 0x00001eb3, 0x00000002, 0x00000103, 0x00000309, 0x00001e14, 0x00000002, 0x00000112, 0x00000300, 0x00001e16, 0x00000002, 0x00000112, 0x00000301, 0x00001e15, 0x00000002, 0x00000113, 0x00000300, 0x00001e17, 0x00000002, 0x00000113, 0x00000301, 0x00001e50, 0x00000002, 0x0000014c, 0x00000300, 0x00001e52, 0x00000002, 0x0000014c, 0x00000301, 0x00001e51, 0x00000002, 0x0000014d, 0x00000300, 0x00001e53, 0x00000002, 0x0000014d, 0x00000301, 0x00001e64, 0x00000002, 0x0000015a, 0x00000307, 0x00001e65, 0x00000002, 0x0000015b, 0x00000307, 0x00001e66, 0x00000002, 0x00000160, 0x00000307, 0x00001e67, 0x00000002, 0x00000161, 0x00000307, 0x00001e78, 0x00000002, 0x00000168, 0x00000301, 0x00001e79, 0x00000002, 0x00000169, 0x00000301, 0x00001e7a, 0x00000002, 0x0000016a, 0x00000308, 0x00001e7b, 0x00000002, 0x0000016b, 0x00000308, 0x00001e9b, 0x00000002, 0x0000017f, 0x00000307, 0x00001edc, 0x00000002, 0x000001a0, 0x00000300, 0x00001eda, 0x00000002, 0x000001a0, 0x00000301, 0x00001ee0, 0x00000002, 0x000001a0, 0x00000303, 0x00001ede, 0x00000002, 0x000001a0, 0x00000309, 0x00001ee2, 0x00000002, 0x000001a0, 0x00000323, 0x00001edd, 0x00000002, 0x000001a1, 0x00000300, 0x00001edb, 0x00000002, 0x000001a1, 0x00000301, 0x00001ee1, 0x00000002, 0x000001a1, 0x00000303, 0x00001edf, 0x00000002, 0x000001a1, 0x00000309, 0x00001ee3, 0x00000002, 0x000001a1, 0x00000323, 0x00001eea, 0x00000002, 0x000001af, 0x00000300, 0x00001ee8, 0x00000002, 0x000001af, 0x00000301, 0x00001eee, 0x00000002, 0x000001af, 0x00000303, 0x00001eec, 0x00000002, 0x000001af, 0x00000309, 0x00001ef0, 0x00000002, 0x000001af, 0x00000323, 0x00001eeb, 0x00000002, 0x000001b0, 0x00000300, 0x00001ee9, 0x00000002, 0x000001b0, 0x00000301, 0x00001eef, 0x00000002, 0x000001b0, 0x00000303, 0x00001eed, 0x00000002, 0x000001b0, 0x00000309, 0x00001ef1, 0x00000002, 0x000001b0, 0x00000323, 0x000001ee, 0x00000002, 0x000001b7, 0x0000030c, 0x000001ec, 0x00000002, 0x000001ea, 0x00000304, 0x000001ed, 0x00000002, 0x000001eb, 0x00000304, 0x000001e0, 0x00000002, 0x00000226, 0x00000304, 0x000001e1, 0x00000002, 0x00000227, 0x00000304, 0x00001e1c, 0x00000002, 0x00000228, 0x00000306, 0x00001e1d, 0x00000002, 0x00000229, 0x00000306, 0x00000230, 0x00000002, 0x0000022e, 0x00000304, 0x00000231, 0x00000002, 0x0000022f, 0x00000304, 0x000001ef, 0x00000002, 0x00000292, 0x0000030c, 0x00000344, 0x00000002, 0x00000308, 0x00000301, 0x00001fba, 0x00000002, 0x00000391, 0x00000300, 0x00000386, 0x00000002, 0x00000391, 0x00000301, 0x00001fb9, 0x00000002, 0x00000391, 0x00000304, 0x00001fb8, 0x00000002, 0x00000391, 0x00000306, 0x00001f08, 0x00000002, 0x00000391, 0x00000313, 0x00001f09, 0x00000002, 0x00000391, 0x00000314, 0x00001fbc, 0x00000002, 0x00000391, 0x00000345, 0x00001fc8, 0x00000002, 0x00000395, 0x00000300, 0x00000388, 0x00000002, 0x00000395, 0x00000301, 0x00001f18, 0x00000002, 0x00000395, 0x00000313, 0x00001f19, 0x00000002, 0x00000395, 0x00000314, 0x00001fca, 0x00000002, 0x00000397, 0x00000300, 0x00000389, 0x00000002, 0x00000397, 0x00000301, 0x00001f28, 0x00000002, 0x00000397, 0x00000313, 0x00001f29, 0x00000002, 0x00000397, 0x00000314, 0x00001fcc, 0x00000002, 0x00000397, 0x00000345, 0x00001fda, 0x00000002, 0x00000399, 0x00000300, 0x0000038a, 0x00000002, 0x00000399, 0x00000301, 0x00001fd9, 0x00000002, 0x00000399, 0x00000304, 0x00001fd8, 0x00000002, 0x00000399, 0x00000306, 0x000003aa, 0x00000002, 0x00000399, 0x00000308, 0x00001f38, 0x00000002, 0x00000399, 0x00000313, 0x00001f39, 0x00000002, 0x00000399, 0x00000314, 0x00001ff8, 0x00000002, 0x0000039f, 0x00000300, 0x0000038c, 0x00000002, 0x0000039f, 0x00000301, 0x00001f48, 0x00000002, 0x0000039f, 0x00000313, 0x00001f49, 0x00000002, 0x0000039f, 0x00000314, 0x00001fec, 0x00000002, 0x000003a1, 0x00000314, 0x00001fea, 0x00000002, 0x000003a5, 0x00000300, 0x0000038e, 0x00000002, 0x000003a5, 0x00000301, 0x00001fe9, 0x00000002, 0x000003a5, 0x00000304, 0x00001fe8, 0x00000002, 0x000003a5, 0x00000306, 0x000003ab, 0x00000002, 0x000003a5, 0x00000308, 0x00001f59, 0x00000002, 0x000003a5, 0x00000314, 0x00001ffa, 0x00000002, 0x000003a9, 0x00000300, 0x0000038f, 0x00000002, 0x000003a9, 0x00000301, 0x00001f68, 0x00000002, 0x000003a9, 0x00000313, 0x00001f69, 0x00000002, 0x000003a9, 0x00000314, 0x00001ffc, 0x00000002, 0x000003a9, 0x00000345, 0x00001fb4, 0x00000002, 0x000003ac, 0x00000345, 0x00001fc4, 0x00000002, 0x000003ae, 0x00000345, 0x00001f70, 0x00000002, 0x000003b1, 0x00000300, 0x000003ac, 0x00000002, 0x000003b1, 0x00000301, 0x00001fb1, 0x00000002, 0x000003b1, 0x00000304, 0x00001fb0, 0x00000002, 0x000003b1, 0x00000306, 0x00001f00, 0x00000002, 0x000003b1, 0x00000313, 0x00001f01, 0x00000002, 0x000003b1, 0x00000314, 0x00001fb6, 0x00000002, 0x000003b1, 0x00000342, 0x00001fb3, 0x00000002, 0x000003b1, 0x00000345, 0x00001f72, 0x00000002, 0x000003b5, 0x00000300, 0x000003ad, 0x00000002, 0x000003b5, 0x00000301, 0x00001f10, 0x00000002, 0x000003b5, 0x00000313, 0x00001f11, 0x00000002, 0x000003b5, 0x00000314, 0x00001f74, 0x00000002, 0x000003b7, 0x00000300, 0x000003ae, 0x00000002, 0x000003b7, 0x00000301, 0x00001f20, 0x00000002, 0x000003b7, 0x00000313, 0x00001f21, 0x00000002, 0x000003b7, 0x00000314, 0x00001fc6, 0x00000002, 0x000003b7, 0x00000342, 0x00001fc3, 0x00000002, 0x000003b7, 0x00000345, 0x00001f76, 0x00000002, 0x000003b9, 0x00000300, 0x000003af, 0x00000002, 0x000003b9, 0x00000301, 0x00001fd1, 0x00000002, 0x000003b9, 0x00000304, 0x00001fd0, 0x00000002, 0x000003b9, 0x00000306, 0x000003ca, 0x00000002, 0x000003b9, 0x00000308, 0x00001f30, 0x00000002, 0x000003b9, 0x00000313, 0x00001f31, 0x00000002, 0x000003b9, 0x00000314, 0x00001fd6, 0x00000002, 0x000003b9, 0x00000342, 0x00001f78, 0x00000002, 0x000003bf, 0x00000300, 0x000003cc, 0x00000002, 0x000003bf, 0x00000301, 0x00001f40, 0x00000002, 0x000003bf, 0x00000313, 0x00001f41, 0x00000002, 0x000003bf, 0x00000314, 0x00001fe4, 0x00000002, 0x000003c1, 0x00000313, 0x00001fe5, 0x00000002, 0x000003c1, 0x00000314, 0x00001f7a, 0x00000002, 0x000003c5, 0x00000300, 0x000003cd, 0x00000002, 0x000003c5, 0x00000301, 0x00001fe1, 0x00000002, 0x000003c5, 0x00000304, 0x00001fe0, 0x00000002, 0x000003c5, 0x00000306, 0x000003cb, 0x00000002, 0x000003c5, 0x00000308, 0x00001f50, 0x00000002, 0x000003c5, 0x00000313, 0x00001f51, 0x00000002, 0x000003c5, 0x00000314, 0x00001fe6, 0x00000002, 0x000003c5, 0x00000342, 0x00001f7c, 0x00000002, 0x000003c9, 0x00000300, 0x000003ce, 0x00000002, 0x000003c9, 0x00000301, 0x00001f60, 0x00000002, 0x000003c9, 0x00000313, 0x00001f61, 0x00000002, 0x000003c9, 0x00000314, 0x00001ff6, 0x00000002, 0x000003c9, 0x00000342, 0x00001ff3, 0x00000002, 0x000003c9, 0x00000345, 0x00001fd2, 0x00000002, 0x000003ca, 0x00000300, 0x00000390, 0x00000002, 0x000003ca, 0x00000301, 0x00001fd7, 0x00000002, 0x000003ca, 0x00000342, 0x00001fe2, 0x00000002, 0x000003cb, 0x00000300, 0x000003b0, 0x00000002, 0x000003cb, 0x00000301, 0x00001fe7, 0x00000002, 0x000003cb, 0x00000342, 0x00001ff4, 0x00000002, 0x000003ce, 0x00000345, 0x000003d3, 0x00000002, 0x000003d2, 0x00000301, 0x000003d4, 0x00000002, 0x000003d2, 0x00000308, 0x00000407, 0x00000002, 0x00000406, 0x00000308, 0x000004d0, 0x00000002, 0x00000410, 0x00000306, 0x000004d2, 0x00000002, 0x00000410, 0x00000308, 0x00000403, 0x00000002, 0x00000413, 0x00000301, 0x00000400, 0x00000002, 0x00000415, 0x00000300, 0x000004d6, 0x00000002, 0x00000415, 0x00000306, 0x00000401, 0x00000002, 0x00000415, 0x00000308, 0x000004c1, 0x00000002, 0x00000416, 0x00000306, 0x000004dc, 0x00000002, 0x00000416, 0x00000308, 0x000004de, 0x00000002, 0x00000417, 0x00000308, 0x0000040d, 0x00000002, 0x00000418, 0x00000300, 0x000004e2, 0x00000002, 0x00000418, 0x00000304, 0x00000419, 0x00000002, 0x00000418, 0x00000306, 0x000004e4, 0x00000002, 0x00000418, 0x00000308, 0x0000040c, 0x00000002, 0x0000041a, 0x00000301, 0x000004e6, 0x00000002, 0x0000041e, 0x00000308, 0x000004ee, 0x00000002, 0x00000423, 0x00000304, 0x0000040e, 0x00000002, 0x00000423, 0x00000306, 0x000004f0, 0x00000002, 0x00000423, 0x00000308, 0x000004f2, 0x00000002, 0x00000423, 0x0000030b, 0x000004f4, 0x00000002, 0x00000427, 0x00000308, 0x000004f8, 0x00000002, 0x0000042b, 0x00000308, 0x000004ec, 0x00000002, 0x0000042d, 0x00000308, 0x000004d1, 0x00000002, 0x00000430, 0x00000306, 0x000004d3, 0x00000002, 0x00000430, 0x00000308, 0x00000453, 0x00000002, 0x00000433, 0x00000301, 0x00000450, 0x00000002, 0x00000435, 0x00000300, 0x000004d7, 0x00000002, 0x00000435, 0x00000306, 0x00000451, 0x00000002, 0x00000435, 0x00000308, 0x000004c2, 0x00000002, 0x00000436, 0x00000306, 0x000004dd, 0x00000002, 0x00000436, 0x00000308, 0x000004df, 0x00000002, 0x00000437, 0x00000308, 0x0000045d, 0x00000002, 0x00000438, 0x00000300, 0x000004e3, 0x00000002, 0x00000438, 0x00000304, 0x00000439, 0x00000002, 0x00000438, 0x00000306, 0x000004e5, 0x00000002, 0x00000438, 0x00000308, 0x0000045c, 0x00000002, 0x0000043a, 0x00000301, 0x000004e7, 0x00000002, 0x0000043e, 0x00000308, 0x000004ef, 0x00000002, 0x00000443, 0x00000304, 0x0000045e, 0x00000002, 0x00000443, 0x00000306, 0x000004f1, 0x00000002, 0x00000443, 0x00000308, 0x000004f3, 0x00000002, 0x00000443, 0x0000030b, 0x000004f5, 0x00000002, 0x00000447, 0x00000308, 0x000004f9, 0x00000002, 0x0000044b, 0x00000308, 0x000004ed, 0x00000002, 0x0000044d, 0x00000308, 0x00000457, 0x00000002, 0x00000456, 0x00000308, 0x00000476, 0x00000002, 0x00000474, 0x0000030f, 0x00000477, 0x00000002, 0x00000475, 0x0000030f, 0x000004da, 0x00000002, 0x000004d8, 0x00000308, 0x000004db, 0x00000002, 0x000004d9, 0x00000308, 0x000004ea, 0x00000002, 0x000004e8, 0x00000308, 0x000004eb, 0x00000002, 0x000004e9, 0x00000308, 0x00000622, 0x00000002, 0x00000627, 0x00000653, 0x00000623, 0x00000002, 0x00000627, 0x00000654, 0x00000625, 0x00000002, 0x00000627, 0x00000655, 0x00000624, 0x00000002, 0x00000648, 0x00000654, 0x00000626, 0x00000002, 0x0000064a, 0x00000654, 0x000006c2, 0x00000002, 0x000006c1, 0x00000654, 0x000006d3, 0x00000002, 0x000006d2, 0x00000654, 0x000006c0, 0x00000002, 0x000006d5, 0x00000654, 0x00000929, 0x00000002, 0x00000928, 0x0000093c, 0x00000931, 0x00000002, 0x00000930, 0x0000093c, 0x00000934, 0x00000002, 0x00000933, 0x0000093c, 0x000009cb, 0x00000002, 0x000009c7, 0x000009be, 0x000009cc, 0x00000002, 0x000009c7, 0x000009d7, 0x00000b4b, 0x00000002, 0x00000b47, 0x00000b3e, 0x00000b48, 0x00000002, 0x00000b47, 0x00000b56, 0x00000b4c, 0x00000002, 0x00000b47, 0x00000b57, 0x00000b94, 0x00000002, 0x00000b92, 0x00000bd7, 0x00000bca, 0x00000002, 0x00000bc6, 0x00000bbe, 0x00000bcc, 0x00000002, 0x00000bc6, 0x00000bd7, 0x00000bcb, 0x00000002, 0x00000bc7, 0x00000bbe, 0x00000c48, 0x00000002, 0x00000c46, 0x00000c56, 0x00000cc0, 0x00000002, 0x00000cbf, 0x00000cd5, 0x00000cca, 0x00000002, 0x00000cc6, 0x00000cc2, 0x00000cc7, 0x00000002, 0x00000cc6, 0x00000cd5, 0x00000cc8, 0x00000002, 0x00000cc6, 0x00000cd6, 0x00000ccb, 0x00000002, 0x00000cca, 0x00000cd5, 0x00000d4a, 0x00000002, 0x00000d46, 0x00000d3e, 0x00000d4c, 0x00000002, 0x00000d46, 0x00000d57, 0x00000d4b, 0x00000002, 0x00000d47, 0x00000d3e, 0x00000dda, 0x00000002, 0x00000dd9, 0x00000dca, 0x00000ddc, 0x00000002, 0x00000dd9, 0x00000dcf, 0x00000dde, 0x00000002, 0x00000dd9, 0x00000ddf, 0x00000ddd, 0x00000002, 0x00000ddc, 0x00000dca, 0x00000f73, 0x00000002, 0x00000f71, 0x00000f72, 0x00000f75, 0x00000002, 0x00000f71, 0x00000f74, 0x00000f81, 0x00000002, 0x00000f71, 0x00000f80, 0x00001026, 0x00000002, 0x00001025, 0x0000102e, 0x00001e38, 0x00000002, 0x00001e36, 0x00000304, 0x00001e39, 0x00000002, 0x00001e37, 0x00000304, 0x00001e5c, 0x00000002, 0x00001e5a, 0x00000304, 0x00001e5d, 0x00000002, 0x00001e5b, 0x00000304, 0x00001e68, 0x00000002, 0x00001e62, 0x00000307, 0x00001e69, 0x00000002, 0x00001e63, 0x00000307, 0x00001eac, 0x00000002, 0x00001ea0, 0x00000302, 0x00001eb6, 0x00000002, 0x00001ea0, 0x00000306, 0x00001ead, 0x00000002, 0x00001ea1, 0x00000302, 0x00001eb7, 0x00000002, 0x00001ea1, 0x00000306, 0x00001ec6, 0x00000002, 0x00001eb8, 0x00000302, 0x00001ec7, 0x00000002, 0x00001eb9, 0x00000302, 0x00001ed8, 0x00000002, 0x00001ecc, 0x00000302, 0x00001ed9, 0x00000002, 0x00001ecd, 0x00000302, 0x00001f02, 0x00000002, 0x00001f00, 0x00000300, 0x00001f04, 0x00000002, 0x00001f00, 0x00000301, 0x00001f06, 0x00000002, 0x00001f00, 0x00000342, 0x00001f80, 0x00000002, 0x00001f00, 0x00000345, 0x00001f03, 0x00000002, 0x00001f01, 0x00000300, 0x00001f05, 0x00000002, 0x00001f01, 0x00000301, 0x00001f07, 0x00000002, 0x00001f01, 0x00000342, 0x00001f81, 0x00000002, 0x00001f01, 0x00000345, 0x00001f82, 0x00000002, 0x00001f02, 0x00000345, 0x00001f83, 0x00000002, 0x00001f03, 0x00000345, 0x00001f84, 0x00000002, 0x00001f04, 0x00000345, 0x00001f85, 0x00000002, 0x00001f05, 0x00000345, 0x00001f86, 0x00000002, 0x00001f06, 0x00000345, 0x00001f87, 0x00000002, 0x00001f07, 0x00000345, 0x00001f0a, 0x00000002, 0x00001f08, 0x00000300, 0x00001f0c, 0x00000002, 0x00001f08, 0x00000301, 0x00001f0e, 0x00000002, 0x00001f08, 0x00000342, 0x00001f88, 0x00000002, 0x00001f08, 0x00000345, 0x00001f0b, 0x00000002, 0x00001f09, 0x00000300, 0x00001f0d, 0x00000002, 0x00001f09, 0x00000301, 0x00001f0f, 0x00000002, 0x00001f09, 0x00000342, 0x00001f89, 0x00000002, 0x00001f09, 0x00000345, 0x00001f8a, 0x00000002, 0x00001f0a, 0x00000345, 0x00001f8b, 0x00000002, 0x00001f0b, 0x00000345, 0x00001f8c, 0x00000002, 0x00001f0c, 0x00000345, 0x00001f8d, 0x00000002, 0x00001f0d, 0x00000345, 0x00001f8e, 0x00000002, 0x00001f0e, 0x00000345, 0x00001f8f, 0x00000002, 0x00001f0f, 0x00000345, 0x00001f12, 0x00000002, 0x00001f10, 0x00000300, 0x00001f14, 0x00000002, 0x00001f10, 0x00000301, 0x00001f13, 0x00000002, 0x00001f11, 0x00000300, 0x00001f15, 0x00000002, 0x00001f11, 0x00000301, 0x00001f1a, 0x00000002, 0x00001f18, 0x00000300, 0x00001f1c, 0x00000002, 0x00001f18, 0x00000301, 0x00001f1b, 0x00000002, 0x00001f19, 0x00000300, 0x00001f1d, 0x00000002, 0x00001f19, 0x00000301, 0x00001f22, 0x00000002, 0x00001f20, 0x00000300, 0x00001f24, 0x00000002, 0x00001f20, 0x00000301, 0x00001f26, 0x00000002, 0x00001f20, 0x00000342, 0x00001f90, 0x00000002, 0x00001f20, 0x00000345, 0x00001f23, 0x00000002, 0x00001f21, 0x00000300, 0x00001f25, 0x00000002, 0x00001f21, 0x00000301, 0x00001f27, 0x00000002, 0x00001f21, 0x00000342, 0x00001f91, 0x00000002, 0x00001f21, 0x00000345, 0x00001f92, 0x00000002, 0x00001f22, 0x00000345, 0x00001f93, 0x00000002, 0x00001f23, 0x00000345, 0x00001f94, 0x00000002, 0x00001f24, 0x00000345, 0x00001f95, 0x00000002, 0x00001f25, 0x00000345, 0x00001f96, 0x00000002, 0x00001f26, 0x00000345, 0x00001f97, 0x00000002, 0x00001f27, 0x00000345, 0x00001f2a, 0x00000002, 0x00001f28, 0x00000300, 0x00001f2c, 0x00000002, 0x00001f28, 0x00000301, 0x00001f2e, 0x00000002, 0x00001f28, 0x00000342, 0x00001f98, 0x00000002, 0x00001f28, 0x00000345, 0x00001f2b, 0x00000002, 0x00001f29, 0x00000300, 0x00001f2d, 0x00000002, 0x00001f29, 0x00000301, 0x00001f2f, 0x00000002, 0x00001f29, 0x00000342, 0x00001f99, 0x00000002, 0x00001f29, 0x00000345, 0x00001f9a, 0x00000002, 0x00001f2a, 0x00000345, 0x00001f9b, 0x00000002, 0x00001f2b, 0x00000345, 0x00001f9c, 0x00000002, 0x00001f2c, 0x00000345, 0x00001f9d, 0x00000002, 0x00001f2d, 0x00000345, 0x00001f9e, 0x00000002, 0x00001f2e, 0x00000345, 0x00001f9f, 0x00000002, 0x00001f2f, 0x00000345, 0x00001f32, 0x00000002, 0x00001f30, 0x00000300, 0x00001f34, 0x00000002, 0x00001f30, 0x00000301, 0x00001f36, 0x00000002, 0x00001f30, 0x00000342, 0x00001f33, 0x00000002, 0x00001f31, 0x00000300, 0x00001f35, 0x00000002, 0x00001f31, 0x00000301, 0x00001f37, 0x00000002, 0x00001f31, 0x00000342, 0x00001f3a, 0x00000002, 0x00001f38, 0x00000300, 0x00001f3c, 0x00000002, 0x00001f38, 0x00000301, 0x00001f3e, 0x00000002, 0x00001f38, 0x00000342, 0x00001f3b, 0x00000002, 0x00001f39, 0x00000300, 0x00001f3d, 0x00000002, 0x00001f39, 0x00000301, 0x00001f3f, 0x00000002, 0x00001f39, 0x00000342, 0x00001f42, 0x00000002, 0x00001f40, 0x00000300, 0x00001f44, 0x00000002, 0x00001f40, 0x00000301, 0x00001f43, 0x00000002, 0x00001f41, 0x00000300, 0x00001f45, 0x00000002, 0x00001f41, 0x00000301, 0x00001f4a, 0x00000002, 0x00001f48, 0x00000300, 0x00001f4c, 0x00000002, 0x00001f48, 0x00000301, 0x00001f4b, 0x00000002, 0x00001f49, 0x00000300, 0x00001f4d, 0x00000002, 0x00001f49, 0x00000301, 0x00001f52, 0x00000002, 0x00001f50, 0x00000300, 0x00001f54, 0x00000002, 0x00001f50, 0x00000301, 0x00001f56, 0x00000002, 0x00001f50, 0x00000342, 0x00001f53, 0x00000002, 0x00001f51, 0x00000300, 0x00001f55, 0x00000002, 0x00001f51, 0x00000301, 0x00001f57, 0x00000002, 0x00001f51, 0x00000342, 0x00001f5b, 0x00000002, 0x00001f59, 0x00000300, 0x00001f5d, 0x00000002, 0x00001f59, 0x00000301, 0x00001f5f, 0x00000002, 0x00001f59, 0x00000342, 0x00001f62, 0x00000002, 0x00001f60, 0x00000300, 0x00001f64, 0x00000002, 0x00001f60, 0x00000301, 0x00001f66, 0x00000002, 0x00001f60, 0x00000342, 0x00001fa0, 0x00000002, 0x00001f60, 0x00000345, 0x00001f63, 0x00000002, 0x00001f61, 0x00000300, 0x00001f65, 0x00000002, 0x00001f61, 0x00000301, 0x00001f67, 0x00000002, 0x00001f61, 0x00000342, 0x00001fa1, 0x00000002, 0x00001f61, 0x00000345, 0x00001fa2, 0x00000002, 0x00001f62, 0x00000345, 0x00001fa3, 0x00000002, 0x00001f63, 0x00000345, 0x00001fa4, 0x00000002, 0x00001f64, 0x00000345, 0x00001fa5, 0x00000002, 0x00001f65, 0x00000345, 0x00001fa6, 0x00000002, 0x00001f66, 0x00000345, 0x00001fa7, 0x00000002, 0x00001f67, 0x00000345, 0x00001f6a, 0x00000002, 0x00001f68, 0x00000300, 0x00001f6c, 0x00000002, 0x00001f68, 0x00000301, 0x00001f6e, 0x00000002, 0x00001f68, 0x00000342, 0x00001fa8, 0x00000002, 0x00001f68, 0x00000345, 0x00001f6b, 0x00000002, 0x00001f69, 0x00000300, 0x00001f6d, 0x00000002, 0x00001f69, 0x00000301, 0x00001f6f, 0x00000002, 0x00001f69, 0x00000342, 0x00001fa9, 0x00000002, 0x00001f69, 0x00000345, 0x00001faa, 0x00000002, 0x00001f6a, 0x00000345, 0x00001fab, 0x00000002, 0x00001f6b, 0x00000345, 0x00001fac, 0x00000002, 0x00001f6c, 0x00000345, 0x00001fad, 0x00000002, 0x00001f6d, 0x00000345, 0x00001fae, 0x00000002, 0x00001f6e, 0x00000345, 0x00001faf, 0x00000002, 0x00001f6f, 0x00000345, 0x00001fb2, 0x00000002, 0x00001f70, 0x00000345, 0x00001fc2, 0x00000002, 0x00001f74, 0x00000345, 0x00001ff2, 0x00000002, 0x00001f7c, 0x00000345, 0x00001fb7, 0x00000002, 0x00001fb6, 0x00000345, 0x00001fcd, 0x00000002, 0x00001fbf, 0x00000300, 0x00001fce, 0x00000002, 0x00001fbf, 0x00000301, 0x00001fcf, 0x00000002, 0x00001fbf, 0x00000342, 0x00001fc7, 0x00000002, 0x00001fc6, 0x00000345, 0x00001ff7, 0x00000002, 0x00001ff6, 0x00000345, 0x00001fdd, 0x00000002, 0x00001ffe, 0x00000300, 0x00001fde, 0x00000002, 0x00001ffe, 0x00000301, 0x00001fdf, 0x00000002, 0x00001ffe, 0x00000342, 0x0000219a, 0x00000002, 0x00002190, 0x00000338, 0x0000219b, 0x00000002, 0x00002192, 0x00000338, 0x000021ae, 0x00000002, 0x00002194, 0x00000338, 0x000021cd, 0x00000002, 0x000021d0, 0x00000338, 0x000021cf, 0x00000002, 0x000021d2, 0x00000338, 0x000021ce, 0x00000002, 0x000021d4, 0x00000338, 0x00002204, 0x00000002, 0x00002203, 0x00000338, 0x00002209, 0x00000002, 0x00002208, 0x00000338, 0x0000220c, 0x00000002, 0x0000220b, 0x00000338, 0x00002224, 0x00000002, 0x00002223, 0x00000338, 0x00002226, 0x00000002, 0x00002225, 0x00000338, 0x00002241, 0x00000002, 0x0000223c, 0x00000338, 0x00002244, 0x00000002, 0x00002243, 0x00000338, 0x00002247, 0x00000002, 0x00002245, 0x00000338, 0x00002249, 0x00000002, 0x00002248, 0x00000338, 0x0000226d, 0x00000002, 0x0000224d, 0x00000338, 0x00002262, 0x00000002, 0x00002261, 0x00000338, 0x00002270, 0x00000002, 0x00002264, 0x00000338, 0x00002271, 0x00000002, 0x00002265, 0x00000338, 0x00002274, 0x00000002, 0x00002272, 0x00000338, 0x00002275, 0x00000002, 0x00002273, 0x00000338, 0x00002278, 0x00000002, 0x00002276, 0x00000338, 0x00002279, 0x00000002, 0x00002277, 0x00000338, 0x00002280, 0x00000002, 0x0000227a, 0x00000338, 0x00002281, 0x00000002, 0x0000227b, 0x00000338, 0x000022e0, 0x00000002, 0x0000227c, 0x00000338, 0x000022e1, 0x00000002, 0x0000227d, 0x00000338, 0x00002284, 0x00000002, 0x00002282, 0x00000338, 0x00002285, 0x00000002, 0x00002283, 0x00000338, 0x00002288, 0x00000002, 0x00002286, 0x00000338, 0x00002289, 0x00000002, 0x00002287, 0x00000338, 0x000022e2, 0x00000002, 0x00002291, 0x00000338, 0x000022e3, 0x00000002, 0x00002292, 0x00000338, 0x000022ac, 0x00000002, 0x000022a2, 0x00000338, 0x000022ad, 0x00000002, 0x000022a8, 0x00000338, 0x000022ae, 0x00000002, 0x000022a9, 0x00000338, 0x000022af, 0x00000002, 0x000022ab, 0x00000338, 0x000022ea, 0x00000002, 0x000022b2, 0x00000338, 0x000022eb, 0x00000002, 0x000022b3, 0x00000338, 0x000022ec, 0x00000002, 0x000022b4, 0x00000338, 0x000022ed, 0x00000002, 0x000022b5, 0x00000338, 0x00003094, 0x00000002, 0x00003046, 0x00003099, 0x0000304c, 0x00000002, 0x0000304b, 0x00003099, 0x0000304e, 0x00000002, 0x0000304d, 0x00003099, 0x00003050, 0x00000002, 0x0000304f, 0x00003099, 0x00003052, 0x00000002, 0x00003051, 0x00003099, 0x00003054, 0x00000002, 0x00003053, 0x00003099, 0x00003056, 0x00000002, 0x00003055, 0x00003099, 0x00003058, 0x00000002, 0x00003057, 0x00003099, 0x0000305a, 0x00000002, 0x00003059, 0x00003099, 0x0000305c, 0x00000002, 0x0000305b, 0x00003099, 0x0000305e, 0x00000002, 0x0000305d, 0x00003099, 0x00003060, 0x00000002, 0x0000305f, 0x00003099, 0x00003062, 0x00000002, 0x00003061, 0x00003099, 0x00003065, 0x00000002, 0x00003064, 0x00003099, 0x00003067, 0x00000002, 0x00003066, 0x00003099, 0x00003069, 0x00000002, 0x00003068, 0x00003099, 0x00003070, 0x00000002, 0x0000306f, 0x00003099, 0x00003071, 0x00000002, 0x0000306f, 0x0000309a, 0x00003073, 0x00000002, 0x00003072, 0x00003099, 0x00003074, 0x00000002, 0x00003072, 0x0000309a, 0x00003076, 0x00000002, 0x00003075, 0x00003099, 0x00003077, 0x00000002, 0x00003075, 0x0000309a, 0x00003079, 0x00000002, 0x00003078, 0x00003099, 0x0000307a, 0x00000002, 0x00003078, 0x0000309a, 0x0000307c, 0x00000002, 0x0000307b, 0x00003099, 0x0000307d, 0x00000002, 0x0000307b, 0x0000309a, 0x0000309e, 0x00000002, 0x0000309d, 0x00003099, 0x000030f4, 0x00000002, 0x000030a6, 0x00003099, 0x000030ac, 0x00000002, 0x000030ab, 0x00003099, 0x000030ae, 0x00000002, 0x000030ad, 0x00003099, 0x000030b0, 0x00000002, 0x000030af, 0x00003099, 0x000030b2, 0x00000002, 0x000030b1, 0x00003099, 0x000030b4, 0x00000002, 0x000030b3, 0x00003099, 0x000030b6, 0x00000002, 0x000030b5, 0x00003099, 0x000030b8, 0x00000002, 0x000030b7, 0x00003099, 0x000030ba, 0x00000002, 0x000030b9, 0x00003099, 0x000030bc, 0x00000002, 0x000030bb, 0x00003099, 0x000030be, 0x00000002, 0x000030bd, 0x00003099, 0x000030c0, 0x00000002, 0x000030bf, 0x00003099, 0x000030c2, 0x00000002, 0x000030c1, 0x00003099, 0x000030c5, 0x00000002, 0x000030c4, 0x00003099, 0x000030c7, 0x00000002, 0x000030c6, 0x00003099, 0x000030c9, 0x00000002, 0x000030c8, 0x00003099, 0x000030d0, 0x00000002, 0x000030cf, 0x00003099, 0x000030d1, 0x00000002, 0x000030cf, 0x0000309a, 0x000030d3, 0x00000002, 0x000030d2, 0x00003099, 0x000030d4, 0x00000002, 0x000030d2, 0x0000309a, 0x000030d6, 0x00000002, 0x000030d5, 0x00003099, 0x000030d7, 0x00000002, 0x000030d5, 0x0000309a, 0x000030d9, 0x00000002, 0x000030d8, 0x00003099, 0x000030da, 0x00000002, 0x000030d8, 0x0000309a, 0x000030dc, 0x00000002, 0x000030db, 0x00003099, 0x000030dd, 0x00000002, 0x000030db, 0x0000309a, 0x000030f7, 0x00000002, 0x000030ef, 0x00003099, 0x000030f8, 0x00000002, 0x000030f0, 0x00003099, 0x000030f9, 0x00000002, 0x000030f1, 0x00003099, 0x000030fa, 0x00000002, 0x000030f2, 0x00003099, 0x000030fe, 0x00000002, 0x000030fd, 0x00003099 }; static const ac_uint4 _ucdcmp_size = 3848; static const ac_uint4 _ucdcmp_nodes[] = { 0x000000c0, 0x00000000, 0x000000c1, 0x00000002, 0x000000c2, 0x00000004, 0x000000c3, 0x00000006, 0x000000c4, 0x00000008, 0x000000c5, 0x0000000a, 0x000000c7, 0x0000000c, 0x000000c8, 0x0000000e, 0x000000c9, 0x00000010, 0x000000ca, 0x00000012, 0x000000cb, 0x00000014, 0x000000cc, 0x00000016, 0x000000cd, 0x00000018, 0x000000ce, 0x0000001a, 0x000000cf, 0x0000001c, 0x000000d1, 0x0000001e, 0x000000d2, 0x00000020, 0x000000d3, 0x00000022, 0x000000d4, 0x00000024, 0x000000d5, 0x00000026, 0x000000d6, 0x00000028, 0x000000d9, 0x0000002a, 0x000000da, 0x0000002c, 0x000000db, 0x0000002e, 0x000000dc, 0x00000030, 0x000000dd, 0x00000032, 0x000000e0, 0x00000034, 0x000000e1, 0x00000036, 0x000000e2, 0x00000038, 0x000000e3, 0x0000003a, 0x000000e4, 0x0000003c, 0x000000e5, 0x0000003e, 0x000000e7, 0x00000040, 0x000000e8, 0x00000042, 0x000000e9, 0x00000044, 0x000000ea, 0x00000046, 0x000000eb, 0x00000048, 0x000000ec, 0x0000004a, 0x000000ed, 0x0000004c, 0x000000ee, 0x0000004e, 0x000000ef, 0x00000050, 0x000000f1, 0x00000052, 0x000000f2, 0x00000054, 0x000000f3, 0x00000056, 0x000000f4, 0x00000058, 0x000000f5, 0x0000005a, 0x000000f6, 0x0000005c, 0x000000f9, 0x0000005e, 0x000000fa, 0x00000060, 0x000000fb, 0x00000062, 0x000000fc, 0x00000064, 0x000000fd, 0x00000066, 0x000000ff, 0x00000068, 0x00000100, 0x0000006a, 0x00000101, 0x0000006c, 0x00000102, 0x0000006e, 0x00000103, 0x00000070, 0x00000104, 0x00000072, 0x00000105, 0x00000074, 0x00000106, 0x00000076, 0x00000107, 0x00000078, 0x00000108, 0x0000007a, 0x00000109, 0x0000007c, 0x0000010a, 0x0000007e, 0x0000010b, 0x00000080, 0x0000010c, 0x00000082, 0x0000010d, 0x00000084, 0x0000010e, 0x00000086, 0x0000010f, 0x00000088, 0x00000112, 0x0000008a, 0x00000113, 0x0000008c, 0x00000114, 0x0000008e, 0x00000115, 0x00000090, 0x00000116, 0x00000092, 0x00000117, 0x00000094, 0x00000118, 0x00000096, 0x00000119, 0x00000098, 0x0000011a, 0x0000009a, 0x0000011b, 0x0000009c, 0x0000011c, 0x0000009e, 0x0000011d, 0x000000a0, 0x0000011e, 0x000000a2, 0x0000011f, 0x000000a4, 0x00000120, 0x000000a6, 0x00000121, 0x000000a8, 0x00000122, 0x000000aa, 0x00000123, 0x000000ac, 0x00000124, 0x000000ae, 0x00000125, 0x000000b0, 0x00000128, 0x000000b2, 0x00000129, 0x000000b4, 0x0000012a, 0x000000b6, 0x0000012b, 0x000000b8, 0x0000012c, 0x000000ba, 0x0000012d, 0x000000bc, 0x0000012e, 0x000000be, 0x0000012f, 0x000000c0, 0x00000130, 0x000000c2, 0x00000134, 0x000000c4, 0x00000135, 0x000000c6, 0x00000136, 0x000000c8, 0x00000137, 0x000000ca, 0x00000139, 0x000000cc, 0x0000013a, 0x000000ce, 0x0000013b, 0x000000d0, 0x0000013c, 0x000000d2, 0x0000013d, 0x000000d4, 0x0000013e, 0x000000d6, 0x00000143, 0x000000d8, 0x00000144, 0x000000da, 0x00000145, 0x000000dc, 0x00000146, 0x000000de, 0x00000147, 0x000000e0, 0x00000148, 0x000000e2, 0x0000014c, 0x000000e4, 0x0000014d, 0x000000e6, 0x0000014e, 0x000000e8, 0x0000014f, 0x000000ea, 0x00000150, 0x000000ec, 0x00000151, 0x000000ee, 0x00000154, 0x000000f0, 0x00000155, 0x000000f2, 0x00000156, 0x000000f4, 0x00000157, 0x000000f6, 0x00000158, 0x000000f8, 0x00000159, 0x000000fa, 0x0000015a, 0x000000fc, 0x0000015b, 0x000000fe, 0x0000015c, 0x00000100, 0x0000015d, 0x00000102, 0x0000015e, 0x00000104, 0x0000015f, 0x00000106, 0x00000160, 0x00000108, 0x00000161, 0x0000010a, 0x00000162, 0x0000010c, 0x00000163, 0x0000010e, 0x00000164, 0x00000110, 0x00000165, 0x00000112, 0x00000168, 0x00000114, 0x00000169, 0x00000116, 0x0000016a, 0x00000118, 0x0000016b, 0x0000011a, 0x0000016c, 0x0000011c, 0x0000016d, 0x0000011e, 0x0000016e, 0x00000120, 0x0000016f, 0x00000122, 0x00000170, 0x00000124, 0x00000171, 0x00000126, 0x00000172, 0x00000128, 0x00000173, 0x0000012a, 0x00000174, 0x0000012c, 0x00000175, 0x0000012e, 0x00000176, 0x00000130, 0x00000177, 0x00000132, 0x00000178, 0x00000134, 0x00000179, 0x00000136, 0x0000017a, 0x00000138, 0x0000017b, 0x0000013a, 0x0000017c, 0x0000013c, 0x0000017d, 0x0000013e, 0x0000017e, 0x00000140, 0x000001a0, 0x00000142, 0x000001a1, 0x00000144, 0x000001af, 0x00000146, 0x000001b0, 0x00000148, 0x000001cd, 0x0000014a, 0x000001ce, 0x0000014c, 0x000001cf, 0x0000014e, 0x000001d0, 0x00000150, 0x000001d1, 0x00000152, 0x000001d2, 0x00000154, 0x000001d3, 0x00000156, 0x000001d4, 0x00000158, 0x000001d5, 0x0000015a, 0x000001d6, 0x0000015d, 0x000001d7, 0x00000160, 0x000001d8, 0x00000163, 0x000001d9, 0x00000166, 0x000001da, 0x00000169, 0x000001db, 0x0000016c, 0x000001dc, 0x0000016f, 0x000001de, 0x00000172, 0x000001df, 0x00000175, 0x000001e0, 0x00000178, 0x000001e1, 0x0000017b, 0x000001e2, 0x0000017e, 0x000001e3, 0x00000180, 0x000001e6, 0x00000182, 0x000001e7, 0x00000184, 0x000001e8, 0x00000186, 0x000001e9, 0x00000188, 0x000001ea, 0x0000018a, 0x000001eb, 0x0000018c, 0x000001ec, 0x0000018e, 0x000001ed, 0x00000191, 0x000001ee, 0x00000194, 0x000001ef, 0x00000196, 0x000001f0, 0x00000198, 0x000001f4, 0x0000019a, 0x000001f5, 0x0000019c, 0x000001f8, 0x0000019e, 0x000001f9, 0x000001a0, 0x000001fa, 0x000001a2, 0x000001fb, 0x000001a5, 0x000001fc, 0x000001a8, 0x000001fd, 0x000001aa, 0x000001fe, 0x000001ac, 0x000001ff, 0x000001ae, 0x00000200, 0x000001b0, 0x00000201, 0x000001b2, 0x00000202, 0x000001b4, 0x00000203, 0x000001b6, 0x00000204, 0x000001b8, 0x00000205, 0x000001ba, 0x00000206, 0x000001bc, 0x00000207, 0x000001be, 0x00000208, 0x000001c0, 0x00000209, 0x000001c2, 0x0000020a, 0x000001c4, 0x0000020b, 0x000001c6, 0x0000020c, 0x000001c8, 0x0000020d, 0x000001ca, 0x0000020e, 0x000001cc, 0x0000020f, 0x000001ce, 0x00000210, 0x000001d0, 0x00000211, 0x000001d2, 0x00000212, 0x000001d4, 0x00000213, 0x000001d6, 0x00000214, 0x000001d8, 0x00000215, 0x000001da, 0x00000216, 0x000001dc, 0x00000217, 0x000001de, 0x00000218, 0x000001e0, 0x00000219, 0x000001e2, 0x0000021a, 0x000001e4, 0x0000021b, 0x000001e6, 0x0000021e, 0x000001e8, 0x0000021f, 0x000001ea, 0x00000226, 0x000001ec, 0x00000227, 0x000001ee, 0x00000228, 0x000001f0, 0x00000229, 0x000001f2, 0x0000022a, 0x000001f4, 0x0000022b, 0x000001f7, 0x0000022c, 0x000001fa, 0x0000022d, 0x000001fd, 0x0000022e, 0x00000200, 0x0000022f, 0x00000202, 0x00000230, 0x00000204, 0x00000231, 0x00000207, 0x00000232, 0x0000020a, 0x00000233, 0x0000020c, 0x00000340, 0x0000020e, 0x00000341, 0x0000020f, 0x00000343, 0x00000210, 0x00000344, 0x00000211, 0x00000374, 0x00000213, 0x0000037e, 0x00000214, 0x00000385, 0x00000215, 0x00000386, 0x00000217, 0x00000387, 0x00000219, 0x00000388, 0x0000021a, 0x00000389, 0x0000021c, 0x0000038a, 0x0000021e, 0x0000038c, 0x00000220, 0x0000038e, 0x00000222, 0x0000038f, 0x00000224, 0x00000390, 0x00000226, 0x000003aa, 0x00000229, 0x000003ab, 0x0000022b, 0x000003ac, 0x0000022d, 0x000003ad, 0x0000022f, 0x000003ae, 0x00000231, 0x000003af, 0x00000233, 0x000003b0, 0x00000235, 0x000003ca, 0x00000238, 0x000003cb, 0x0000023a, 0x000003cc, 0x0000023c, 0x000003cd, 0x0000023e, 0x000003ce, 0x00000240, 0x000003d3, 0x00000242, 0x000003d4, 0x00000244, 0x00000400, 0x00000246, 0x00000401, 0x00000248, 0x00000403, 0x0000024a, 0x00000407, 0x0000024c, 0x0000040c, 0x0000024e, 0x0000040d, 0x00000250, 0x0000040e, 0x00000252, 0x00000419, 0x00000254, 0x00000439, 0x00000256, 0x00000450, 0x00000258, 0x00000451, 0x0000025a, 0x00000453, 0x0000025c, 0x00000457, 0x0000025e, 0x0000045c, 0x00000260, 0x0000045d, 0x00000262, 0x0000045e, 0x00000264, 0x00000476, 0x00000266, 0x00000477, 0x00000268, 0x000004c1, 0x0000026a, 0x000004c2, 0x0000026c, 0x000004d0, 0x0000026e, 0x000004d1, 0x00000270, 0x000004d2, 0x00000272, 0x000004d3, 0x00000274, 0x000004d6, 0x00000276, 0x000004d7, 0x00000278, 0x000004da, 0x0000027a, 0x000004db, 0x0000027c, 0x000004dc, 0x0000027e, 0x000004dd, 0x00000280, 0x000004de, 0x00000282, 0x000004df, 0x00000284, 0x000004e2, 0x00000286, 0x000004e3, 0x00000288, 0x000004e4, 0x0000028a, 0x000004e5, 0x0000028c, 0x000004e6, 0x0000028e, 0x000004e7, 0x00000290, 0x000004ea, 0x00000292, 0x000004eb, 0x00000294, 0x000004ec, 0x00000296, 0x000004ed, 0x00000298, 0x000004ee, 0x0000029a, 0x000004ef, 0x0000029c, 0x000004f0, 0x0000029e, 0x000004f1, 0x000002a0, 0x000004f2, 0x000002a2, 0x000004f3, 0x000002a4, 0x000004f4, 0x000002a6, 0x000004f5, 0x000002a8, 0x000004f8, 0x000002aa, 0x000004f9, 0x000002ac, 0x00000622, 0x000002ae, 0x00000623, 0x000002b0, 0x00000624, 0x000002b2, 0x00000625, 0x000002b4, 0x00000626, 0x000002b6, 0x000006c0, 0x000002b8, 0x000006c2, 0x000002ba, 0x000006d3, 0x000002bc, 0x00000929, 0x000002be, 0x00000931, 0x000002c0, 0x00000934, 0x000002c2, 0x00000958, 0x000002c4, 0x00000959, 0x000002c6, 0x0000095a, 0x000002c8, 0x0000095b, 0x000002ca, 0x0000095c, 0x000002cc, 0x0000095d, 0x000002ce, 0x0000095e, 0x000002d0, 0x0000095f, 0x000002d2, 0x000009cb, 0x000002d4, 0x000009cc, 0x000002d6, 0x000009dc, 0x000002d8, 0x000009dd, 0x000002da, 0x000009df, 0x000002dc, 0x00000a33, 0x000002de, 0x00000a36, 0x000002e0, 0x00000a59, 0x000002e2, 0x00000a5a, 0x000002e4, 0x00000a5b, 0x000002e6, 0x00000a5e, 0x000002e8, 0x00000b48, 0x000002ea, 0x00000b4b, 0x000002ec, 0x00000b4c, 0x000002ee, 0x00000b5c, 0x000002f0, 0x00000b5d, 0x000002f2, 0x00000b94, 0x000002f4, 0x00000bca, 0x000002f6, 0x00000bcb, 0x000002f8, 0x00000bcc, 0x000002fa, 0x00000c48, 0x000002fc, 0x00000cc0, 0x000002fe, 0x00000cc7, 0x00000300, 0x00000cc8, 0x00000302, 0x00000cca, 0x00000304, 0x00000ccb, 0x00000306, 0x00000d4a, 0x00000309, 0x00000d4b, 0x0000030b, 0x00000d4c, 0x0000030d, 0x00000dda, 0x0000030f, 0x00000ddc, 0x00000311, 0x00000ddd, 0x00000313, 0x00000dde, 0x00000316, 0x00000f43, 0x00000318, 0x00000f4d, 0x0000031a, 0x00000f52, 0x0000031c, 0x00000f57, 0x0000031e, 0x00000f5c, 0x00000320, 0x00000f69, 0x00000322, 0x00000f73, 0x00000324, 0x00000f75, 0x00000326, 0x00000f76, 0x00000328, 0x00000f78, 0x0000032a, 0x00000f81, 0x0000032c, 0x00000f93, 0x0000032e, 0x00000f9d, 0x00000330, 0x00000fa2, 0x00000332, 0x00000fa7, 0x00000334, 0x00000fac, 0x00000336, 0x00000fb9, 0x00000338, 0x00001026, 0x0000033a, 0x00001e00, 0x0000033c, 0x00001e01, 0x0000033e, 0x00001e02, 0x00000340, 0x00001e03, 0x00000342, 0x00001e04, 0x00000344, 0x00001e05, 0x00000346, 0x00001e06, 0x00000348, 0x00001e07, 0x0000034a, 0x00001e08, 0x0000034c, 0x00001e09, 0x0000034f, 0x00001e0a, 0x00000352, 0x00001e0b, 0x00000354, 0x00001e0c, 0x00000356, 0x00001e0d, 0x00000358, 0x00001e0e, 0x0000035a, 0x00001e0f, 0x0000035c, 0x00001e10, 0x0000035e, 0x00001e11, 0x00000360, 0x00001e12, 0x00000362, 0x00001e13, 0x00000364, 0x00001e14, 0x00000366, 0x00001e15, 0x00000369, 0x00001e16, 0x0000036c, 0x00001e17, 0x0000036f, 0x00001e18, 0x00000372, 0x00001e19, 0x00000374, 0x00001e1a, 0x00000376, 0x00001e1b, 0x00000378, 0x00001e1c, 0x0000037a, 0x00001e1d, 0x0000037d, 0x00001e1e, 0x00000380, 0x00001e1f, 0x00000382, 0x00001e20, 0x00000384, 0x00001e21, 0x00000386, 0x00001e22, 0x00000388, 0x00001e23, 0x0000038a, 0x00001e24, 0x0000038c, 0x00001e25, 0x0000038e, 0x00001e26, 0x00000390, 0x00001e27, 0x00000392, 0x00001e28, 0x00000394, 0x00001e29, 0x00000396, 0x00001e2a, 0x00000398, 0x00001e2b, 0x0000039a, 0x00001e2c, 0x0000039c, 0x00001e2d, 0x0000039e, 0x00001e2e, 0x000003a0, 0x00001e2f, 0x000003a3, 0x00001e30, 0x000003a6, 0x00001e31, 0x000003a8, 0x00001e32, 0x000003aa, 0x00001e33, 0x000003ac, 0x00001e34, 0x000003ae, 0x00001e35, 0x000003b0, 0x00001e36, 0x000003b2, 0x00001e37, 0x000003b4, 0x00001e38, 0x000003b6, 0x00001e39, 0x000003b9, 0x00001e3a, 0x000003bc, 0x00001e3b, 0x000003be, 0x00001e3c, 0x000003c0, 0x00001e3d, 0x000003c2, 0x00001e3e, 0x000003c4, 0x00001e3f, 0x000003c6, 0x00001e40, 0x000003c8, 0x00001e41, 0x000003ca, 0x00001e42, 0x000003cc, 0x00001e43, 0x000003ce, 0x00001e44, 0x000003d0, 0x00001e45, 0x000003d2, 0x00001e46, 0x000003d4, 0x00001e47, 0x000003d6, 0x00001e48, 0x000003d8, 0x00001e49, 0x000003da, 0x00001e4a, 0x000003dc, 0x00001e4b, 0x000003de, 0x00001e4c, 0x000003e0, 0x00001e4d, 0x000003e3, 0x00001e4e, 0x000003e6, 0x00001e4f, 0x000003e9, 0x00001e50, 0x000003ec, 0x00001e51, 0x000003ef, 0x00001e52, 0x000003f2, 0x00001e53, 0x000003f5, 0x00001e54, 0x000003f8, 0x00001e55, 0x000003fa, 0x00001e56, 0x000003fc, 0x00001e57, 0x000003fe, 0x00001e58, 0x00000400, 0x00001e59, 0x00000402, 0x00001e5a, 0x00000404, 0x00001e5b, 0x00000406, 0x00001e5c, 0x00000408, 0x00001e5d, 0x0000040b, 0x00001e5e, 0x0000040e, 0x00001e5f, 0x00000410, 0x00001e60, 0x00000412, 0x00001e61, 0x00000414, 0x00001e62, 0x00000416, 0x00001e63, 0x00000418, 0x00001e64, 0x0000041a, 0x00001e65, 0x0000041d, 0x00001e66, 0x00000420, 0x00001e67, 0x00000423, 0x00001e68, 0x00000426, 0x00001e69, 0x00000429, 0x00001e6a, 0x0000042c, 0x00001e6b, 0x0000042e, 0x00001e6c, 0x00000430, 0x00001e6d, 0x00000432, 0x00001e6e, 0x00000434, 0x00001e6f, 0x00000436, 0x00001e70, 0x00000438, 0x00001e71, 0x0000043a, 0x00001e72, 0x0000043c, 0x00001e73, 0x0000043e, 0x00001e74, 0x00000440, 0x00001e75, 0x00000442, 0x00001e76, 0x00000444, 0x00001e77, 0x00000446, 0x00001e78, 0x00000448, 0x00001e79, 0x0000044b, 0x00001e7a, 0x0000044e, 0x00001e7b, 0x00000451, 0x00001e7c, 0x00000454, 0x00001e7d, 0x00000456, 0x00001e7e, 0x00000458, 0x00001e7f, 0x0000045a, 0x00001e80, 0x0000045c, 0x00001e81, 0x0000045e, 0x00001e82, 0x00000460, 0x00001e83, 0x00000462, 0x00001e84, 0x00000464, 0x00001e85, 0x00000466, 0x00001e86, 0x00000468, 0x00001e87, 0x0000046a, 0x00001e88, 0x0000046c, 0x00001e89, 0x0000046e, 0x00001e8a, 0x00000470, 0x00001e8b, 0x00000472, 0x00001e8c, 0x00000474, 0x00001e8d, 0x00000476, 0x00001e8e, 0x00000478, 0x00001e8f, 0x0000047a, 0x00001e90, 0x0000047c, 0x00001e91, 0x0000047e, 0x00001e92, 0x00000480, 0x00001e93, 0x00000482, 0x00001e94, 0x00000484, 0x00001e95, 0x00000486, 0x00001e96, 0x00000488, 0x00001e97, 0x0000048a, 0x00001e98, 0x0000048c, 0x00001e99, 0x0000048e, 0x00001e9b, 0x00000490, 0x00001ea0, 0x00000492, 0x00001ea1, 0x00000494, 0x00001ea2, 0x00000496, 0x00001ea3, 0x00000498, 0x00001ea4, 0x0000049a, 0x00001ea5, 0x0000049d, 0x00001ea6, 0x000004a0, 0x00001ea7, 0x000004a3, 0x00001ea8, 0x000004a6, 0x00001ea9, 0x000004a9, 0x00001eaa, 0x000004ac, 0x00001eab, 0x000004af, 0x00001eac, 0x000004b2, 0x00001ead, 0x000004b5, 0x00001eae, 0x000004b8, 0x00001eaf, 0x000004bb, 0x00001eb0, 0x000004be, 0x00001eb1, 0x000004c1, 0x00001eb2, 0x000004c4, 0x00001eb3, 0x000004c7, 0x00001eb4, 0x000004ca, 0x00001eb5, 0x000004cd, 0x00001eb6, 0x000004d0, 0x00001eb7, 0x000004d3, 0x00001eb8, 0x000004d6, 0x00001eb9, 0x000004d8, 0x00001eba, 0x000004da, 0x00001ebb, 0x000004dc, 0x00001ebc, 0x000004de, 0x00001ebd, 0x000004e0, 0x00001ebe, 0x000004e2, 0x00001ebf, 0x000004e5, 0x00001ec0, 0x000004e8, 0x00001ec1, 0x000004eb, 0x00001ec2, 0x000004ee, 0x00001ec3, 0x000004f1, 0x00001ec4, 0x000004f4, 0x00001ec5, 0x000004f7, 0x00001ec6, 0x000004fa, 0x00001ec7, 0x000004fd, 0x00001ec8, 0x00000500, 0x00001ec9, 0x00000502, 0x00001eca, 0x00000504, 0x00001ecb, 0x00000506, 0x00001ecc, 0x00000508, 0x00001ecd, 0x0000050a, 0x00001ece, 0x0000050c, 0x00001ecf, 0x0000050e, 0x00001ed0, 0x00000510, 0x00001ed1, 0x00000513, 0x00001ed2, 0x00000516, 0x00001ed3, 0x00000519, 0x00001ed4, 0x0000051c, 0x00001ed5, 0x0000051f, 0x00001ed6, 0x00000522, 0x00001ed7, 0x00000525, 0x00001ed8, 0x00000528, 0x00001ed9, 0x0000052b, 0x00001eda, 0x0000052e, 0x00001edb, 0x00000531, 0x00001edc, 0x00000534, 0x00001edd, 0x00000537, 0x00001ede, 0x0000053a, 0x00001edf, 0x0000053d, 0x00001ee0, 0x00000540, 0x00001ee1, 0x00000543, 0x00001ee2, 0x00000546, 0x00001ee3, 0x00000549, 0x00001ee4, 0x0000054c, 0x00001ee5, 0x0000054e, 0x00001ee6, 0x00000550, 0x00001ee7, 0x00000552, 0x00001ee8, 0x00000554, 0x00001ee9, 0x00000557, 0x00001eea, 0x0000055a, 0x00001eeb, 0x0000055d, 0x00001eec, 0x00000560, 0x00001eed, 0x00000563, 0x00001eee, 0x00000566, 0x00001eef, 0x00000569, 0x00001ef0, 0x0000056c, 0x00001ef1, 0x0000056f, 0x00001ef2, 0x00000572, 0x00001ef3, 0x00000574, 0x00001ef4, 0x00000576, 0x00001ef5, 0x00000578, 0x00001ef6, 0x0000057a, 0x00001ef7, 0x0000057c, 0x00001ef8, 0x0000057e, 0x00001ef9, 0x00000580, 0x00001f00, 0x00000582, 0x00001f01, 0x00000584, 0x00001f02, 0x00000586, 0x00001f03, 0x00000589, 0x00001f04, 0x0000058c, 0x00001f05, 0x0000058f, 0x00001f06, 0x00000592, 0x00001f07, 0x00000595, 0x00001f08, 0x00000598, 0x00001f09, 0x0000059a, 0x00001f0a, 0x0000059c, 0x00001f0b, 0x0000059f, 0x00001f0c, 0x000005a2, 0x00001f0d, 0x000005a5, 0x00001f0e, 0x000005a8, 0x00001f0f, 0x000005ab, 0x00001f10, 0x000005ae, 0x00001f11, 0x000005b0, 0x00001f12, 0x000005b2, 0x00001f13, 0x000005b5, 0x00001f14, 0x000005b8, 0x00001f15, 0x000005bb, 0x00001f18, 0x000005be, 0x00001f19, 0x000005c0, 0x00001f1a, 0x000005c2, 0x00001f1b, 0x000005c5, 0x00001f1c, 0x000005c8, 0x00001f1d, 0x000005cb, 0x00001f20, 0x000005ce, 0x00001f21, 0x000005d0, 0x00001f22, 0x000005d2, 0x00001f23, 0x000005d5, 0x00001f24, 0x000005d8, 0x00001f25, 0x000005db, 0x00001f26, 0x000005de, 0x00001f27, 0x000005e1, 0x00001f28, 0x000005e4, 0x00001f29, 0x000005e6, 0x00001f2a, 0x000005e8, 0x00001f2b, 0x000005eb, 0x00001f2c, 0x000005ee, 0x00001f2d, 0x000005f1, 0x00001f2e, 0x000005f4, 0x00001f2f, 0x000005f7, 0x00001f30, 0x000005fa, 0x00001f31, 0x000005fc, 0x00001f32, 0x000005fe, 0x00001f33, 0x00000601, 0x00001f34, 0x00000604, 0x00001f35, 0x00000607, 0x00001f36, 0x0000060a, 0x00001f37, 0x0000060d, 0x00001f38, 0x00000610, 0x00001f39, 0x00000612, 0x00001f3a, 0x00000614, 0x00001f3b, 0x00000617, 0x00001f3c, 0x0000061a, 0x00001f3d, 0x0000061d, 0x00001f3e, 0x00000620, 0x00001f3f, 0x00000623, 0x00001f40, 0x00000626, 0x00001f41, 0x00000628, 0x00001f42, 0x0000062a, 0x00001f43, 0x0000062d, 0x00001f44, 0x00000630, 0x00001f45, 0x00000633, 0x00001f48, 0x00000636, 0x00001f49, 0x00000638, 0x00001f4a, 0x0000063a, 0x00001f4b, 0x0000063d, 0x00001f4c, 0x00000640, 0x00001f4d, 0x00000643, 0x00001f50, 0x00000646, 0x00001f51, 0x00000648, 0x00001f52, 0x0000064a, 0x00001f53, 0x0000064d, 0x00001f54, 0x00000650, 0x00001f55, 0x00000653, 0x00001f56, 0x00000656, 0x00001f57, 0x00000659, 0x00001f59, 0x0000065c, 0x00001f5b, 0x0000065e, 0x00001f5d, 0x00000661, 0x00001f5f, 0x00000664, 0x00001f60, 0x00000667, 0x00001f61, 0x00000669, 0x00001f62, 0x0000066b, 0x00001f63, 0x0000066e, 0x00001f64, 0x00000671, 0x00001f65, 0x00000674, 0x00001f66, 0x00000677, 0x00001f67, 0x0000067a, 0x00001f68, 0x0000067d, 0x00001f69, 0x0000067f, 0x00001f6a, 0x00000681, 0x00001f6b, 0x00000684, 0x00001f6c, 0x00000687, 0x00001f6d, 0x0000068a, 0x00001f6e, 0x0000068d, 0x00001f6f, 0x00000690, 0x00001f70, 0x00000693, 0x00001f71, 0x00000695, 0x00001f72, 0x00000697, 0x00001f73, 0x00000699, 0x00001f74, 0x0000069b, 0x00001f75, 0x0000069d, 0x00001f76, 0x0000069f, 0x00001f77, 0x000006a1, 0x00001f78, 0x000006a3, 0x00001f79, 0x000006a5, 0x00001f7a, 0x000006a7, 0x00001f7b, 0x000006a9, 0x00001f7c, 0x000006ab, 0x00001f7d, 0x000006ad, 0x00001f80, 0x000006af, 0x00001f81, 0x000006b2, 0x00001f82, 0x000006b5, 0x00001f83, 0x000006b9, 0x00001f84, 0x000006bd, 0x00001f85, 0x000006c1, 0x00001f86, 0x000006c5, 0x00001f87, 0x000006c9, 0x00001f88, 0x000006cd, 0x00001f89, 0x000006d0, 0x00001f8a, 0x000006d3, 0x00001f8b, 0x000006d7, 0x00001f8c, 0x000006db, 0x00001f8d, 0x000006df, 0x00001f8e, 0x000006e3, 0x00001f8f, 0x000006e7, 0x00001f90, 0x000006eb, 0x00001f91, 0x000006ee, 0x00001f92, 0x000006f1, 0x00001f93, 0x000006f5, 0x00001f94, 0x000006f9, 0x00001f95, 0x000006fd, 0x00001f96, 0x00000701, 0x00001f97, 0x00000705, 0x00001f98, 0x00000709, 0x00001f99, 0x0000070c, 0x00001f9a, 0x0000070f, 0x00001f9b, 0x00000713, 0x00001f9c, 0x00000717, 0x00001f9d, 0x0000071b, 0x00001f9e, 0x0000071f, 0x00001f9f, 0x00000723, 0x00001fa0, 0x00000727, 0x00001fa1, 0x0000072a, 0x00001fa2, 0x0000072d, 0x00001fa3, 0x00000731, 0x00001fa4, 0x00000735, 0x00001fa5, 0x00000739, 0x00001fa6, 0x0000073d, 0x00001fa7, 0x00000741, 0x00001fa8, 0x00000745, 0x00001fa9, 0x00000748, 0x00001faa, 0x0000074b, 0x00001fab, 0x0000074f, 0x00001fac, 0x00000753, 0x00001fad, 0x00000757, 0x00001fae, 0x0000075b, 0x00001faf, 0x0000075f, 0x00001fb0, 0x00000763, 0x00001fb1, 0x00000765, 0x00001fb2, 0x00000767, 0x00001fb3, 0x0000076a, 0x00001fb4, 0x0000076c, 0x00001fb6, 0x0000076f, 0x00001fb7, 0x00000771, 0x00001fb8, 0x00000774, 0x00001fb9, 0x00000776, 0x00001fba, 0x00000778, 0x00001fbb, 0x0000077a, 0x00001fbc, 0x0000077c, 0x00001fbe, 0x0000077e, 0x00001fc1, 0x0000077f, 0x00001fc2, 0x00000781, 0x00001fc3, 0x00000784, 0x00001fc4, 0x00000786, 0x00001fc6, 0x00000789, 0x00001fc7, 0x0000078b, 0x00001fc8, 0x0000078e, 0x00001fc9, 0x00000790, 0x00001fca, 0x00000792, 0x00001fcb, 0x00000794, 0x00001fcc, 0x00000796, 0x00001fcd, 0x00000798, 0x00001fce, 0x0000079a, 0x00001fcf, 0x0000079c, 0x00001fd0, 0x0000079e, 0x00001fd1, 0x000007a0, 0x00001fd2, 0x000007a2, 0x00001fd3, 0x000007a5, 0x00001fd6, 0x000007a8, 0x00001fd7, 0x000007aa, 0x00001fd8, 0x000007ad, 0x00001fd9, 0x000007af, 0x00001fda, 0x000007b1, 0x00001fdb, 0x000007b3, 0x00001fdd, 0x000007b5, 0x00001fde, 0x000007b7, 0x00001fdf, 0x000007b9, 0x00001fe0, 0x000007bb, 0x00001fe1, 0x000007bd, 0x00001fe2, 0x000007bf, 0x00001fe3, 0x000007c2, 0x00001fe4, 0x000007c5, 0x00001fe5, 0x000007c7, 0x00001fe6, 0x000007c9, 0x00001fe7, 0x000007cb, 0x00001fe8, 0x000007ce, 0x00001fe9, 0x000007d0, 0x00001fea, 0x000007d2, 0x00001feb, 0x000007d4, 0x00001fec, 0x000007d6, 0x00001fed, 0x000007d8, 0x00001fee, 0x000007da, 0x00001fef, 0x000007dc, 0x00001ff2, 0x000007dd, 0x00001ff3, 0x000007e0, 0x00001ff4, 0x000007e2, 0x00001ff6, 0x000007e5, 0x00001ff7, 0x000007e7, 0x00001ff8, 0x000007ea, 0x00001ff9, 0x000007ec, 0x00001ffa, 0x000007ee, 0x00001ffb, 0x000007f0, 0x00001ffc, 0x000007f2, 0x00001ffd, 0x000007f4, 0x00002000, 0x000007f5, 0x00002001, 0x000007f6, 0x00002126, 0x000007f7, 0x0000212a, 0x000007f8, 0x0000212b, 0x000007f9, 0x0000219a, 0x000007fb, 0x0000219b, 0x000007fd, 0x000021ae, 0x000007ff, 0x000021cd, 0x00000801, 0x000021ce, 0x00000803, 0x000021cf, 0x00000805, 0x00002204, 0x00000807, 0x00002209, 0x00000809, 0x0000220c, 0x0000080b, 0x00002224, 0x0000080d, 0x00002226, 0x0000080f, 0x00002241, 0x00000811, 0x00002244, 0x00000813, 0x00002247, 0x00000815, 0x00002249, 0x00000817, 0x00002260, 0x00000819, 0x00002262, 0x0000081b, 0x0000226d, 0x0000081d, 0x0000226e, 0x0000081f, 0x0000226f, 0x00000821, 0x00002270, 0x00000823, 0x00002271, 0x00000825, 0x00002274, 0x00000827, 0x00002275, 0x00000829, 0x00002278, 0x0000082b, 0x00002279, 0x0000082d, 0x00002280, 0x0000082f, 0x00002281, 0x00000831, 0x00002284, 0x00000833, 0x00002285, 0x00000835, 0x00002288, 0x00000837, 0x00002289, 0x00000839, 0x000022ac, 0x0000083b, 0x000022ad, 0x0000083d, 0x000022ae, 0x0000083f, 0x000022af, 0x00000841, 0x000022e0, 0x00000843, 0x000022e1, 0x00000845, 0x000022e2, 0x00000847, 0x000022e3, 0x00000849, 0x000022ea, 0x0000084b, 0x000022eb, 0x0000084d, 0x000022ec, 0x0000084f, 0x000022ed, 0x00000851, 0x00002329, 0x00000853, 0x0000232a, 0x00000854, 0x00002adc, 0x00000855, 0x0000304c, 0x00000857, 0x0000304e, 0x00000859, 0x00003050, 0x0000085b, 0x00003052, 0x0000085d, 0x00003054, 0x0000085f, 0x00003056, 0x00000861, 0x00003058, 0x00000863, 0x0000305a, 0x00000865, 0x0000305c, 0x00000867, 0x0000305e, 0x00000869, 0x00003060, 0x0000086b, 0x00003062, 0x0000086d, 0x00003065, 0x0000086f, 0x00003067, 0x00000871, 0x00003069, 0x00000873, 0x00003070, 0x00000875, 0x00003071, 0x00000877, 0x00003073, 0x00000879, 0x00003074, 0x0000087b, 0x00003076, 0x0000087d, 0x00003077, 0x0000087f, 0x00003079, 0x00000881, 0x0000307a, 0x00000883, 0x0000307c, 0x00000885, 0x0000307d, 0x00000887, 0x00003094, 0x00000889, 0x0000309e, 0x0000088b, 0x000030ac, 0x0000088d, 0x000030ae, 0x0000088f, 0x000030b0, 0x00000891, 0x000030b2, 0x00000893, 0x000030b4, 0x00000895, 0x000030b6, 0x00000897, 0x000030b8, 0x00000899, 0x000030ba, 0x0000089b, 0x000030bc, 0x0000089d, 0x000030be, 0x0000089f, 0x000030c0, 0x000008a1, 0x000030c2, 0x000008a3, 0x000030c5, 0x000008a5, 0x000030c7, 0x000008a7, 0x000030c9, 0x000008a9, 0x000030d0, 0x000008ab, 0x000030d1, 0x000008ad, 0x000030d3, 0x000008af, 0x000030d4, 0x000008b1, 0x000030d6, 0x000008b3, 0x000030d7, 0x000008b5, 0x000030d9, 0x000008b7, 0x000030da, 0x000008b9, 0x000030dc, 0x000008bb, 0x000030dd, 0x000008bd, 0x000030f4, 0x000008bf, 0x000030f7, 0x000008c1, 0x000030f8, 0x000008c3, 0x000030f9, 0x000008c5, 0x000030fa, 0x000008c7, 0x000030fe, 0x000008c9, 0x0000f902, 0x000008cb, 0x0000f903, 0x000008cc, 0x0000f904, 0x000008cd, 0x0000f905, 0x000008ce, 0x0000f906, 0x000008cf, 0x0000f907, 0x000008d0, 0x0000f908, 0x000008d1, 0x0000f909, 0x000008d2, 0x0000f90a, 0x000008d3, 0x0000f90b, 0x000008d4, 0x0000f90c, 0x000008d5, 0x0000f90d, 0x000008d6, 0x0000f90e, 0x000008d7, 0x0000f90f, 0x000008d8, 0x0000f910, 0x000008d9, 0x0000f911, 0x000008da, 0x0000f912, 0x000008db, 0x0000f913, 0x000008dc, 0x0000f914, 0x000008dd, 0x0000f915, 0x000008de, 0x0000f916, 0x000008df, 0x0000f917, 0x000008e0, 0x0000f918, 0x000008e1, 0x0000f919, 0x000008e2, 0x0000f91a, 0x000008e3, 0x0000f91b, 0x000008e4, 0x0000f91c, 0x000008e5, 0x0000f91d, 0x000008e6, 0x0000f91e, 0x000008e7, 0x0000f91f, 0x000008e8, 0x0000f920, 0x000008e9, 0x0000f921, 0x000008ea, 0x0000f922, 0x000008eb, 0x0000f923, 0x000008ec, 0x0000f924, 0x000008ed, 0x0000f925, 0x000008ee, 0x0000f926, 0x000008ef, 0x0000f927, 0x000008f0, 0x0000f928, 0x000008f1, 0x0000f929, 0x000008f2, 0x0000f92a, 0x000008f3, 0x0000f92b, 0x000008f4, 0x0000f92c, 0x000008f5, 0x0000f92d, 0x000008f6, 0x0000f92e, 0x000008f7, 0x0000f92f, 0x000008f8, 0x0000f930, 0x000008f9, 0x0000f931, 0x000008fa, 0x0000f932, 0x000008fb, 0x0000f933, 0x000008fc, 0x0000f934, 0x000008fd, 0x0000f935, 0x000008fe, 0x0000f936, 0x000008ff, 0x0000f937, 0x00000900, 0x0000f938, 0x00000901, 0x0000f939, 0x00000902, 0x0000f93a, 0x00000903, 0x0000f93b, 0x00000904, 0x0000f93c, 0x00000905, 0x0000f93d, 0x00000906, 0x0000f93e, 0x00000907, 0x0000f93f, 0x00000908, 0x0000f940, 0x00000909, 0x0000f941, 0x0000090a, 0x0000f942, 0x0000090b, 0x0000f943, 0x0000090c, 0x0000f944, 0x0000090d, 0x0000f945, 0x0000090e, 0x0000f946, 0x0000090f, 0x0000f947, 0x00000910, 0x0000f948, 0x00000911, 0x0000f949, 0x00000912, 0x0000f94a, 0x00000913, 0x0000f94b, 0x00000914, 0x0000f94c, 0x00000915, 0x0000f94d, 0x00000916, 0x0000f94e, 0x00000917, 0x0000f94f, 0x00000918, 0x0000f950, 0x00000919, 0x0000f951, 0x0000091a, 0x0000f952, 0x0000091b, 0x0000f953, 0x0000091c, 0x0000f954, 0x0000091d, 0x0000f955, 0x0000091e, 0x0000f956, 0x0000091f, 0x0000f957, 0x00000920, 0x0000f958, 0x00000921, 0x0000f959, 0x00000922, 0x0000f95a, 0x00000923, 0x0000f95b, 0x00000924, 0x0000f95c, 0x00000925, 0x0000f95d, 0x00000926, 0x0000f95e, 0x00000927, 0x0000f95f, 0x00000928, 0x0000f960, 0x00000929, 0x0000f961, 0x0000092a, 0x0000f962, 0x0000092b, 0x0000f963, 0x0000092c, 0x0000f964, 0x0000092d, 0x0000f965, 0x0000092e, 0x0000f966, 0x0000092f, 0x0000f967, 0x00000930, 0x0000f968, 0x00000931, 0x0000f969, 0x00000932, 0x0000f96a, 0x00000933, 0x0000f96b, 0x00000934, 0x0000f96c, 0x00000935, 0x0000f96d, 0x00000936, 0x0000f96e, 0x00000937, 0x0000f96f, 0x00000938, 0x0000f970, 0x00000939, 0x0000f971, 0x0000093a, 0x0000f972, 0x0000093b, 0x0000f973, 0x0000093c, 0x0000f974, 0x0000093d, 0x0000f975, 0x0000093e, 0x0000f976, 0x0000093f, 0x0000f977, 0x00000940, 0x0000f978, 0x00000941, 0x0000f979, 0x00000942, 0x0000f97a, 0x00000943, 0x0000f97b, 0x00000944, 0x0000f97c, 0x00000945, 0x0000f97d, 0x00000946, 0x0000f97e, 0x00000947, 0x0000f97f, 0x00000948, 0x0000f980, 0x00000949, 0x0000f981, 0x0000094a, 0x0000f982, 0x0000094b, 0x0000f983, 0x0000094c, 0x0000f984, 0x0000094d, 0x0000f985, 0x0000094e, 0x0000f986, 0x0000094f, 0x0000f987, 0x00000950, 0x0000f988, 0x00000951, 0x0000f989, 0x00000952, 0x0000f98a, 0x00000953, 0x0000f98b, 0x00000954, 0x0000f98c, 0x00000955, 0x0000f98d, 0x00000956, 0x0000f98e, 0x00000957, 0x0000f98f, 0x00000958, 0x0000f990, 0x00000959, 0x0000f991, 0x0000095a, 0x0000f992, 0x0000095b, 0x0000f993, 0x0000095c, 0x0000f994, 0x0000095d, 0x0000f995, 0x0000095e, 0x0000f996, 0x0000095f, 0x0000f997, 0x00000960, 0x0000f998, 0x00000961, 0x0000f999, 0x00000962, 0x0000f99a, 0x00000963, 0x0000f99b, 0x00000964, 0x0000f99c, 0x00000965, 0x0000f99d, 0x00000966, 0x0000f99e, 0x00000967, 0x0000f99f, 0x00000968, 0x0000f9a0, 0x00000969, 0x0000f9a1, 0x0000096a, 0x0000f9a2, 0x0000096b, 0x0000f9a3, 0x0000096c, 0x0000f9a4, 0x0000096d, 0x0000f9a5, 0x0000096e, 0x0000f9a6, 0x0000096f, 0x0000f9a7, 0x00000970, 0x0000f9a8, 0x00000971, 0x0000f9a9, 0x00000972, 0x0000f9aa, 0x00000973, 0x0000f9ab, 0x00000974, 0x0000f9ac, 0x00000975, 0x0000f9ad, 0x00000976, 0x0000f9ae, 0x00000977, 0x0000f9af, 0x00000978, 0x0000f9b0, 0x00000979, 0x0000f9b1, 0x0000097a, 0x0000f9b2, 0x0000097b, 0x0000f9b3, 0x0000097c, 0x0000f9b4, 0x0000097d, 0x0000f9b5, 0x0000097e, 0x0000f9b6, 0x0000097f, 0x0000f9b7, 0x00000980, 0x0000f9b8, 0x00000981, 0x0000f9b9, 0x00000982, 0x0000f9ba, 0x00000983, 0x0000f9bb, 0x00000984, 0x0000f9bc, 0x00000985, 0x0000f9bd, 0x00000986, 0x0000f9be, 0x00000987, 0x0000f9bf, 0x00000988, 0x0000f9c0, 0x00000989, 0x0000f9c1, 0x0000098a, 0x0000f9c2, 0x0000098b, 0x0000f9c3, 0x0000098c, 0x0000f9c4, 0x0000098d, 0x0000f9c5, 0x0000098e, 0x0000f9c6, 0x0000098f, 0x0000f9c7, 0x00000990, 0x0000f9c8, 0x00000991, 0x0000f9c9, 0x00000992, 0x0000f9ca, 0x00000993, 0x0000f9cb, 0x00000994, 0x0000f9cc, 0x00000995, 0x0000f9cd, 0x00000996, 0x0000f9ce, 0x00000997, 0x0000f9cf, 0x00000998, 0x0000f9d0, 0x00000999, 0x0000f9d1, 0x0000099a, 0x0000f9d2, 0x0000099b, 0x0000f9d3, 0x0000099c, 0x0000f9d4, 0x0000099d, 0x0000f9d5, 0x0000099e, 0x0000f9d6, 0x0000099f, 0x0000f9d7, 0x000009a0, 0x0000f9d8, 0x000009a1, 0x0000f9d9, 0x000009a2, 0x0000f9da, 0x000009a3, 0x0000f9db, 0x000009a4, 0x0000f9dc, 0x000009a5, 0x0000f9dd, 0x000009a6, 0x0000f9de, 0x000009a7, 0x0000f9df, 0x000009a8, 0x0000f9e0, 0x000009a9, 0x0000f9e1, 0x000009aa, 0x0000f9e2, 0x000009ab, 0x0000f9e3, 0x000009ac, 0x0000f9e4, 0x000009ad, 0x0000f9e5, 0x000009ae, 0x0000f9e6, 0x000009af, 0x0000f9e7, 0x000009b0, 0x0000f9e8, 0x000009b1, 0x0000f9e9, 0x000009b2, 0x0000f9ea, 0x000009b3, 0x0000f9eb, 0x000009b4, 0x0000f9ec, 0x000009b5, 0x0000f9ed, 0x000009b6, 0x0000f9ee, 0x000009b7, 0x0000f9ef, 0x000009b8, 0x0000f9f0, 0x000009b9, 0x0000f9f1, 0x000009ba, 0x0000f9f2, 0x000009bb, 0x0000f9f3, 0x000009bc, 0x0000f9f4, 0x000009bd, 0x0000f9f5, 0x000009be, 0x0000f9f6, 0x000009bf, 0x0000f9f7, 0x000009c0, 0x0000f9f8, 0x000009c1, 0x0000f9f9, 0x000009c2, 0x0000f9fa, 0x000009c3, 0x0000f9fb, 0x000009c4, 0x0000f9fc, 0x000009c5, 0x0000f9fd, 0x000009c6, 0x0000f9fe, 0x000009c7, 0x0000f9ff, 0x000009c8, 0x0000fa00, 0x000009c9, 0x0000fa01, 0x000009ca, 0x0000fa02, 0x000009cb, 0x0000fa03, 0x000009cc, 0x0000fa04, 0x000009cd, 0x0000fa05, 0x000009ce, 0x0000fa06, 0x000009cf, 0x0000fa07, 0x000009d0, 0x0000fa08, 0x000009d1, 0x0000fa09, 0x000009d2, 0x0000fa0a, 0x000009d3, 0x0000fa0b, 0x000009d4, 0x0000fa0c, 0x000009d5, 0x0000fa0d, 0x000009d6, 0x0000fa10, 0x000009d7, 0x0000fa12, 0x000009d8, 0x0000fa15, 0x000009d9, 0x0000fa16, 0x000009da, 0x0000fa17, 0x000009db, 0x0000fa18, 0x000009dc, 0x0000fa19, 0x000009dd, 0x0000fa1a, 0x000009de, 0x0000fa1b, 0x000009df, 0x0000fa1c, 0x000009e0, 0x0000fa1d, 0x000009e1, 0x0000fa1e, 0x000009e2, 0x0000fa20, 0x000009e3, 0x0000fa22, 0x000009e4, 0x0000fa25, 0x000009e5, 0x0000fa26, 0x000009e6, 0x0000fa2a, 0x000009e7, 0x0000fa2b, 0x000009e8, 0x0000fa2c, 0x000009e9, 0x0000fa2d, 0x000009ea, 0x0000fa30, 0x000009eb, 0x0000fa31, 0x000009ec, 0x0000fa32, 0x000009ed, 0x0000fa33, 0x000009ee, 0x0000fa34, 0x000009ef, 0x0000fa35, 0x000009f0, 0x0000fa36, 0x000009f1, 0x0000fa37, 0x000009f2, 0x0000fa38, 0x000009f3, 0x0000fa39, 0x000009f4, 0x0000fa3a, 0x000009f5, 0x0000fa3b, 0x000009f6, 0x0000fa3c, 0x000009f7, 0x0000fa3d, 0x000009f8, 0x0000fa3e, 0x000009f9, 0x0000fa3f, 0x000009fa, 0x0000fa40, 0x000009fb, 0x0000fa41, 0x000009fc, 0x0000fa42, 0x000009fd, 0x0000fa43, 0x000009fe, 0x0000fa44, 0x000009ff, 0x0000fa45, 0x00000a00, 0x0000fa46, 0x00000a01, 0x0000fa47, 0x00000a02, 0x0000fa48, 0x00000a03, 0x0000fa49, 0x00000a04, 0x0000fa4a, 0x00000a05, 0x0000fa4b, 0x00000a06, 0x0000fa4c, 0x00000a07, 0x0000fa4d, 0x00000a08, 0x0000fa4e, 0x00000a09, 0x0000fa4f, 0x00000a0a, 0x0000fa50, 0x00000a0b, 0x0000fa51, 0x00000a0c, 0x0000fa52, 0x00000a0d, 0x0000fa53, 0x00000a0e, 0x0000fa54, 0x00000a0f, 0x0000fa55, 0x00000a10, 0x0000fa56, 0x00000a11, 0x0000fa57, 0x00000a12, 0x0000fa58, 0x00000a13, 0x0000fa59, 0x00000a14, 0x0000fa5a, 0x00000a15, 0x0000fa5b, 0x00000a16, 0x0000fa5c, 0x00000a17, 0x0000fa5d, 0x00000a18, 0x0000fa5e, 0x00000a19, 0x0000fa5f, 0x00000a1a, 0x0000fa60, 0x00000a1b, 0x0000fa61, 0x00000a1c, 0x0000fa62, 0x00000a1d, 0x0000fa63, 0x00000a1e, 0x0000fa64, 0x00000a1f, 0x0000fa65, 0x00000a20, 0x0000fa66, 0x00000a21, 0x0000fa67, 0x00000a22, 0x0000fa68, 0x00000a23, 0x0000fa69, 0x00000a24, 0x0000fa6a, 0x00000a25, 0x0000fb1d, 0x00000a26, 0x0000fb1f, 0x00000a28, 0x0000fb2a, 0x00000a2a, 0x0000fb2b, 0x00000a2c, 0x0000fb2c, 0x00000a2e, 0x0000fb2d, 0x00000a31, 0x0000fb2e, 0x00000a34, 0x0000fb2f, 0x00000a36, 0x0000fb30, 0x00000a38, 0x0000fb31, 0x00000a3a, 0x0000fb32, 0x00000a3c, 0x0000fb33, 0x00000a3e, 0x0000fb34, 0x00000a40, 0x0000fb35, 0x00000a42, 0x0000fb36, 0x00000a44, 0x0000fb38, 0x00000a46, 0x0000fb39, 0x00000a48, 0x0000fb3a, 0x00000a4a, 0x0000fb3b, 0x00000a4c, 0x0000fb3c, 0x00000a4e, 0x0000fb3e, 0x00000a50, 0x0000fb40, 0x00000a52, 0x0000fb41, 0x00000a54, 0x0000fb43, 0x00000a56, 0x0000fb44, 0x00000a58, 0x0000fb46, 0x00000a5a, 0x0000fb47, 0x00000a5c, 0x0000fb48, 0x00000a5e, 0x0000fb49, 0x00000a60, 0x0000fb4a, 0x00000a62, 0x0000fb4b, 0x00000a64, 0x0000fb4c, 0x00000a66, 0x0000fb4d, 0x00000a68, 0x0000fb4e, 0x00000a6a, 0x0001d15e, 0x00000a6c, 0x0001d15f, 0x00000a6e, 0x0001d160, 0x00000a70, 0x0001d161, 0x00000a73, 0x0001d162, 0x00000a76, 0x0001d163, 0x00000a79, 0x0001d164, 0x00000a7c, 0x0001d1bb, 0x00000a7f, 0x0001d1bc, 0x00000a81, 0x0001d1bd, 0x00000a83, 0x0001d1be, 0x00000a86, 0x0001d1bf, 0x00000a89, 0x0001d1c0, 0x00000a8c, 0x0002f800, 0x00000a8f, 0x0002f801, 0x00000a90, 0x0002f802, 0x00000a91, 0x0002f803, 0x00000a92, 0x0002f804, 0x00000a93, 0x0002f805, 0x00000a94, 0x0002f806, 0x00000a95, 0x0002f807, 0x00000a96, 0x0002f808, 0x00000a97, 0x0002f809, 0x00000a98, 0x0002f80a, 0x00000a99, 0x0002f80b, 0x00000a9a, 0x0002f80c, 0x00000a9b, 0x0002f80d, 0x00000a9c, 0x0002f80e, 0x00000a9d, 0x0002f80f, 0x00000a9e, 0x0002f810, 0x00000a9f, 0x0002f811, 0x00000aa0, 0x0002f812, 0x00000aa1, 0x0002f813, 0x00000aa2, 0x0002f814, 0x00000aa3, 0x0002f815, 0x00000aa4, 0x0002f816, 0x00000aa5, 0x0002f817, 0x00000aa6, 0x0002f818, 0x00000aa7, 0x0002f819, 0x00000aa8, 0x0002f81a, 0x00000aa9, 0x0002f81b, 0x00000aaa, 0x0002f81c, 0x00000aab, 0x0002f81d, 0x00000aac, 0x0002f81e, 0x00000aad, 0x0002f81f, 0x00000aae, 0x0002f820, 0x00000aaf, 0x0002f821, 0x00000ab0, 0x0002f822, 0x00000ab1, 0x0002f823, 0x00000ab2, 0x0002f824, 0x00000ab3, 0x0002f825, 0x00000ab4, 0x0002f826, 0x00000ab5, 0x0002f827, 0x00000ab6, 0x0002f828, 0x00000ab7, 0x0002f829, 0x00000ab8, 0x0002f82a, 0x00000ab9, 0x0002f82b, 0x00000aba, 0x0002f82c, 0x00000abb, 0x0002f82d, 0x00000abc, 0x0002f82e, 0x00000abd, 0x0002f82f, 0x00000abe, 0x0002f830, 0x00000abf, 0x0002f831, 0x00000ac0, 0x0002f832, 0x00000ac1, 0x0002f833, 0x00000ac2, 0x0002f834, 0x00000ac3, 0x0002f835, 0x00000ac4, 0x0002f836, 0x00000ac5, 0x0002f837, 0x00000ac6, 0x0002f838, 0x00000ac7, 0x0002f839, 0x00000ac8, 0x0002f83a, 0x00000ac9, 0x0002f83b, 0x00000aca, 0x0002f83c, 0x00000acb, 0x0002f83d, 0x00000acc, 0x0002f83e, 0x00000acd, 0x0002f83f, 0x00000ace, 0x0002f840, 0x00000acf, 0x0002f841, 0x00000ad0, 0x0002f842, 0x00000ad1, 0x0002f843, 0x00000ad2, 0x0002f844, 0x00000ad3, 0x0002f845, 0x00000ad4, 0x0002f846, 0x00000ad5, 0x0002f847, 0x00000ad6, 0x0002f848, 0x00000ad7, 0x0002f849, 0x00000ad8, 0x0002f84a, 0x00000ad9, 0x0002f84b, 0x00000ada, 0x0002f84c, 0x00000adb, 0x0002f84d, 0x00000adc, 0x0002f84e, 0x00000add, 0x0002f84f, 0x00000ade, 0x0002f850, 0x00000adf, 0x0002f851, 0x00000ae0, 0x0002f852, 0x00000ae1, 0x0002f853, 0x00000ae2, 0x0002f854, 0x00000ae3, 0x0002f855, 0x00000ae4, 0x0002f856, 0x00000ae5, 0x0002f857, 0x00000ae6, 0x0002f858, 0x00000ae7, 0x0002f859, 0x00000ae8, 0x0002f85a, 0x00000ae9, 0x0002f85b, 0x00000aea, 0x0002f85c, 0x00000aeb, 0x0002f85d, 0x00000aec, 0x0002f85e, 0x00000aed, 0x0002f85f, 0x00000aee, 0x0002f860, 0x00000aef, 0x0002f861, 0x00000af0, 0x0002f862, 0x00000af1, 0x0002f863, 0x00000af2, 0x0002f864, 0x00000af3, 0x0002f865, 0x00000af4, 0x0002f866, 0x00000af5, 0x0002f867, 0x00000af6, 0x0002f868, 0x00000af7, 0x0002f869, 0x00000af8, 0x0002f86a, 0x00000af9, 0x0002f86b, 0x00000afa, 0x0002f86c, 0x00000afb, 0x0002f86d, 0x00000afc, 0x0002f86e, 0x00000afd, 0x0002f86f, 0x00000afe, 0x0002f870, 0x00000aff, 0x0002f871, 0x00000b00, 0x0002f872, 0x00000b01, 0x0002f873, 0x00000b02, 0x0002f874, 0x00000b03, 0x0002f875, 0x00000b04, 0x0002f876, 0x00000b05, 0x0002f877, 0x00000b06, 0x0002f878, 0x00000b07, 0x0002f879, 0x00000b08, 0x0002f87a, 0x00000b09, 0x0002f87b, 0x00000b0a, 0x0002f87c, 0x00000b0b, 0x0002f87d, 0x00000b0c, 0x0002f87e, 0x00000b0d, 0x0002f87f, 0x00000b0e, 0x0002f880, 0x00000b0f, 0x0002f881, 0x00000b10, 0x0002f882, 0x00000b11, 0x0002f883, 0x00000b12, 0x0002f884, 0x00000b13, 0x0002f885, 0x00000b14, 0x0002f886, 0x00000b15, 0x0002f887, 0x00000b16, 0x0002f888, 0x00000b17, 0x0002f889, 0x00000b18, 0x0002f88a, 0x00000b19, 0x0002f88b, 0x00000b1a, 0x0002f88c, 0x00000b1b, 0x0002f88d, 0x00000b1c, 0x0002f88e, 0x00000b1d, 0x0002f88f, 0x00000b1e, 0x0002f890, 0x00000b1f, 0x0002f891, 0x00000b20, 0x0002f892, 0x00000b21, 0x0002f893, 0x00000b22, 0x0002f894, 0x00000b23, 0x0002f895, 0x00000b24, 0x0002f896, 0x00000b25, 0x0002f897, 0x00000b26, 0x0002f898, 0x00000b27, 0x0002f899, 0x00000b28, 0x0002f89a, 0x00000b29, 0x0002f89b, 0x00000b2a, 0x0002f89c, 0x00000b2b, 0x0002f89d, 0x00000b2c, 0x0002f89e, 0x00000b2d, 0x0002f89f, 0x00000b2e, 0x0002f8a0, 0x00000b2f, 0x0002f8a1, 0x00000b30, 0x0002f8a2, 0x00000b31, 0x0002f8a3, 0x00000b32, 0x0002f8a4, 0x00000b33, 0x0002f8a5, 0x00000b34, 0x0002f8a6, 0x00000b35, 0x0002f8a7, 0x00000b36, 0x0002f8a8, 0x00000b37, 0x0002f8a9, 0x00000b38, 0x0002f8aa, 0x00000b39, 0x0002f8ab, 0x00000b3a, 0x0002f8ac, 0x00000b3b, 0x0002f8ad, 0x00000b3c, 0x0002f8ae, 0x00000b3d, 0x0002f8af, 0x00000b3e, 0x0002f8b0, 0x00000b3f, 0x0002f8b1, 0x00000b40, 0x0002f8b2, 0x00000b41, 0x0002f8b3, 0x00000b42, 0x0002f8b4, 0x00000b43, 0x0002f8b5, 0x00000b44, 0x0002f8b6, 0x00000b45, 0x0002f8b7, 0x00000b46, 0x0002f8b8, 0x00000b47, 0x0002f8b9, 0x00000b48, 0x0002f8ba, 0x00000b49, 0x0002f8bb, 0x00000b4a, 0x0002f8bc, 0x00000b4b, 0x0002f8bd, 0x00000b4c, 0x0002f8be, 0x00000b4d, 0x0002f8bf, 0x00000b4e, 0x0002f8c0, 0x00000b4f, 0x0002f8c1, 0x00000b50, 0x0002f8c2, 0x00000b51, 0x0002f8c3, 0x00000b52, 0x0002f8c4, 0x00000b53, 0x0002f8c5, 0x00000b54, 0x0002f8c6, 0x00000b55, 0x0002f8c7, 0x00000b56, 0x0002f8c8, 0x00000b57, 0x0002f8c9, 0x00000b58, 0x0002f8ca, 0x00000b59, 0x0002f8cb, 0x00000b5a, 0x0002f8cc, 0x00000b5b, 0x0002f8cd, 0x00000b5c, 0x0002f8ce, 0x00000b5d, 0x0002f8cf, 0x00000b5e, 0x0002f8d0, 0x00000b5f, 0x0002f8d1, 0x00000b60, 0x0002f8d2, 0x00000b61, 0x0002f8d3, 0x00000b62, 0x0002f8d4, 0x00000b63, 0x0002f8d5, 0x00000b64, 0x0002f8d6, 0x00000b65, 0x0002f8d7, 0x00000b66, 0x0002f8d8, 0x00000b67, 0x0002f8d9, 0x00000b68, 0x0002f8da, 0x00000b69, 0x0002f8db, 0x00000b6a, 0x0002f8dc, 0x00000b6b, 0x0002f8dd, 0x00000b6c, 0x0002f8de, 0x00000b6d, 0x0002f8df, 0x00000b6e, 0x0002f8e0, 0x00000b6f, 0x0002f8e1, 0x00000b70, 0x0002f8e2, 0x00000b71, 0x0002f8e3, 0x00000b72, 0x0002f8e4, 0x00000b73, 0x0002f8e5, 0x00000b74, 0x0002f8e6, 0x00000b75, 0x0002f8e7, 0x00000b76, 0x0002f8e8, 0x00000b77, 0x0002f8e9, 0x00000b78, 0x0002f8ea, 0x00000b79, 0x0002f8eb, 0x00000b7a, 0x0002f8ec, 0x00000b7b, 0x0002f8ed, 0x00000b7c, 0x0002f8ee, 0x00000b7d, 0x0002f8ef, 0x00000b7e, 0x0002f8f0, 0x00000b7f, 0x0002f8f1, 0x00000b80, 0x0002f8f2, 0x00000b81, 0x0002f8f3, 0x00000b82, 0x0002f8f4, 0x00000b83, 0x0002f8f5, 0x00000b84, 0x0002f8f6, 0x00000b85, 0x0002f8f7, 0x00000b86, 0x0002f8f8, 0x00000b87, 0x0002f8f9, 0x00000b88, 0x0002f8fa, 0x00000b89, 0x0002f8fb, 0x00000b8a, 0x0002f8fc, 0x00000b8b, 0x0002f8fd, 0x00000b8c, 0x0002f8fe, 0x00000b8d, 0x0002f8ff, 0x00000b8e, 0x0002f900, 0x00000b8f, 0x0002f901, 0x00000b90, 0x0002f902, 0x00000b91, 0x0002f903, 0x00000b92, 0x0002f904, 0x00000b93, 0x0002f905, 0x00000b94, 0x0002f906, 0x00000b95, 0x0002f907, 0x00000b96, 0x0002f908, 0x00000b97, 0x0002f909, 0x00000b98, 0x0002f90a, 0x00000b99, 0x0002f90b, 0x00000b9a, 0x0002f90c, 0x00000b9b, 0x0002f90d, 0x00000b9c, 0x0002f90e, 0x00000b9d, 0x0002f90f, 0x00000b9e, 0x0002f910, 0x00000b9f, 0x0002f911, 0x00000ba0, 0x0002f912, 0x00000ba1, 0x0002f913, 0x00000ba2, 0x0002f914, 0x00000ba3, 0x0002f915, 0x00000ba4, 0x0002f916, 0x00000ba5, 0x0002f917, 0x00000ba6, 0x0002f918, 0x00000ba7, 0x0002f919, 0x00000ba8, 0x0002f91a, 0x00000ba9, 0x0002f91b, 0x00000baa, 0x0002f91c, 0x00000bab, 0x0002f91d, 0x00000bac, 0x0002f91e, 0x00000bad, 0x0002f91f, 0x00000bae, 0x0002f920, 0x00000baf, 0x0002f921, 0x00000bb0, 0x0002f922, 0x00000bb1, 0x0002f923, 0x00000bb2, 0x0002f924, 0x00000bb3, 0x0002f925, 0x00000bb4, 0x0002f926, 0x00000bb5, 0x0002f927, 0x00000bb6, 0x0002f928, 0x00000bb7, 0x0002f929, 0x00000bb8, 0x0002f92a, 0x00000bb9, 0x0002f92b, 0x00000bba, 0x0002f92c, 0x00000bbb, 0x0002f92d, 0x00000bbc, 0x0002f92e, 0x00000bbd, 0x0002f92f, 0x00000bbe, 0x0002f930, 0x00000bbf, 0x0002f931, 0x00000bc0, 0x0002f932, 0x00000bc1, 0x0002f933, 0x00000bc2, 0x0002f934, 0x00000bc3, 0x0002f935, 0x00000bc4, 0x0002f936, 0x00000bc5, 0x0002f937, 0x00000bc6, 0x0002f938, 0x00000bc7, 0x0002f939, 0x00000bc8, 0x0002f93a, 0x00000bc9, 0x0002f93b, 0x00000bca, 0x0002f93c, 0x00000bcb, 0x0002f93d, 0x00000bcc, 0x0002f93e, 0x00000bcd, 0x0002f93f, 0x00000bce, 0x0002f940, 0x00000bcf, 0x0002f941, 0x00000bd0, 0x0002f942, 0x00000bd1, 0x0002f943, 0x00000bd2, 0x0002f944, 0x00000bd3, 0x0002f945, 0x00000bd4, 0x0002f946, 0x00000bd5, 0x0002f947, 0x00000bd6, 0x0002f948, 0x00000bd7, 0x0002f949, 0x00000bd8, 0x0002f94a, 0x00000bd9, 0x0002f94b, 0x00000bda, 0x0002f94c, 0x00000bdb, 0x0002f94d, 0x00000bdc, 0x0002f94e, 0x00000bdd, 0x0002f94f, 0x00000bde, 0x0002f950, 0x00000bdf, 0x0002f951, 0x00000be0, 0x0002f952, 0x00000be1, 0x0002f953, 0x00000be2, 0x0002f954, 0x00000be3, 0x0002f955, 0x00000be4, 0x0002f956, 0x00000be5, 0x0002f957, 0x00000be6, 0x0002f958, 0x00000be7, 0x0002f959, 0x00000be8, 0x0002f95a, 0x00000be9, 0x0002f95b, 0x00000bea, 0x0002f95c, 0x00000beb, 0x0002f95d, 0x00000bec, 0x0002f95e, 0x00000bed, 0x0002f95f, 0x00000bee, 0x0002f960, 0x00000bef, 0x0002f961, 0x00000bf0, 0x0002f962, 0x00000bf1, 0x0002f963, 0x00000bf2, 0x0002f964, 0x00000bf3, 0x0002f965, 0x00000bf4, 0x0002f966, 0x00000bf5, 0x0002f967, 0x00000bf6, 0x0002f968, 0x00000bf7, 0x0002f969, 0x00000bf8, 0x0002f96a, 0x00000bf9, 0x0002f96b, 0x00000bfa, 0x0002f96c, 0x00000bfb, 0x0002f96d, 0x00000bfc, 0x0002f96e, 0x00000bfd, 0x0002f96f, 0x00000bfe, 0x0002f970, 0x00000bff, 0x0002f971, 0x00000c00, 0x0002f972, 0x00000c01, 0x0002f973, 0x00000c02, 0x0002f974, 0x00000c03, 0x0002f975, 0x00000c04, 0x0002f976, 0x00000c05, 0x0002f977, 0x00000c06, 0x0002f978, 0x00000c07, 0x0002f979, 0x00000c08, 0x0002f97a, 0x00000c09, 0x0002f97b, 0x00000c0a, 0x0002f97c, 0x00000c0b, 0x0002f97d, 0x00000c0c, 0x0002f97e, 0x00000c0d, 0x0002f97f, 0x00000c0e, 0x0002f980, 0x00000c0f, 0x0002f981, 0x00000c10, 0x0002f982, 0x00000c11, 0x0002f983, 0x00000c12, 0x0002f984, 0x00000c13, 0x0002f985, 0x00000c14, 0x0002f986, 0x00000c15, 0x0002f987, 0x00000c16, 0x0002f988, 0x00000c17, 0x0002f989, 0x00000c18, 0x0002f98a, 0x00000c19, 0x0002f98b, 0x00000c1a, 0x0002f98c, 0x00000c1b, 0x0002f98d, 0x00000c1c, 0x0002f98e, 0x00000c1d, 0x0002f98f, 0x00000c1e, 0x0002f990, 0x00000c1f, 0x0002f991, 0x00000c20, 0x0002f992, 0x00000c21, 0x0002f993, 0x00000c22, 0x0002f994, 0x00000c23, 0x0002f995, 0x00000c24, 0x0002f996, 0x00000c25, 0x0002f997, 0x00000c26, 0x0002f998, 0x00000c27, 0x0002f999, 0x00000c28, 0x0002f99a, 0x00000c29, 0x0002f99b, 0x00000c2a, 0x0002f99c, 0x00000c2b, 0x0002f99d, 0x00000c2c, 0x0002f99e, 0x00000c2d, 0x0002f99f, 0x00000c2e, 0x0002f9a0, 0x00000c2f, 0x0002f9a1, 0x00000c30, 0x0002f9a2, 0x00000c31, 0x0002f9a3, 0x00000c32, 0x0002f9a4, 0x00000c33, 0x0002f9a5, 0x00000c34, 0x0002f9a6, 0x00000c35, 0x0002f9a7, 0x00000c36, 0x0002f9a8, 0x00000c37, 0x0002f9a9, 0x00000c38, 0x0002f9aa, 0x00000c39, 0x0002f9ab, 0x00000c3a, 0x0002f9ac, 0x00000c3b, 0x0002f9ad, 0x00000c3c, 0x0002f9ae, 0x00000c3d, 0x0002f9af, 0x00000c3e, 0x0002f9b0, 0x00000c3f, 0x0002f9b1, 0x00000c40, 0x0002f9b2, 0x00000c41, 0x0002f9b3, 0x00000c42, 0x0002f9b4, 0x00000c43, 0x0002f9b5, 0x00000c44, 0x0002f9b6, 0x00000c45, 0x0002f9b7, 0x00000c46, 0x0002f9b8, 0x00000c47, 0x0002f9b9, 0x00000c48, 0x0002f9ba, 0x00000c49, 0x0002f9bb, 0x00000c4a, 0x0002f9bc, 0x00000c4b, 0x0002f9bd, 0x00000c4c, 0x0002f9be, 0x00000c4d, 0x0002f9bf, 0x00000c4e, 0x0002f9c0, 0x00000c4f, 0x0002f9c1, 0x00000c50, 0x0002f9c2, 0x00000c51, 0x0002f9c3, 0x00000c52, 0x0002f9c4, 0x00000c53, 0x0002f9c5, 0x00000c54, 0x0002f9c6, 0x00000c55, 0x0002f9c7, 0x00000c56, 0x0002f9c8, 0x00000c57, 0x0002f9c9, 0x00000c58, 0x0002f9ca, 0x00000c59, 0x0002f9cb, 0x00000c5a, 0x0002f9cc, 0x00000c5b, 0x0002f9cd, 0x00000c5c, 0x0002f9ce, 0x00000c5d, 0x0002f9cf, 0x00000c5e, 0x0002f9d0, 0x00000c5f, 0x0002f9d1, 0x00000c60, 0x0002f9d2, 0x00000c61, 0x0002f9d3, 0x00000c62, 0x0002f9d4, 0x00000c63, 0x0002f9d5, 0x00000c64, 0x0002f9d6, 0x00000c65, 0x0002f9d7, 0x00000c66, 0x0002f9d8, 0x00000c67, 0x0002f9d9, 0x00000c68, 0x0002f9da, 0x00000c69, 0x0002f9db, 0x00000c6a, 0x0002f9dc, 0x00000c6b, 0x0002f9dd, 0x00000c6c, 0x0002f9de, 0x00000c6d, 0x0002f9df, 0x00000c6e, 0x0002f9e0, 0x00000c6f, 0x0002f9e1, 0x00000c70, 0x0002f9e2, 0x00000c71, 0x0002f9e3, 0x00000c72, 0x0002f9e4, 0x00000c73, 0x0002f9e5, 0x00000c74, 0x0002f9e6, 0x00000c75, 0x0002f9e7, 0x00000c76, 0x0002f9e8, 0x00000c77, 0x0002f9e9, 0x00000c78, 0x0002f9ea, 0x00000c79, 0x0002f9eb, 0x00000c7a, 0x0002f9ec, 0x00000c7b, 0x0002f9ed, 0x00000c7c, 0x0002f9ee, 0x00000c7d, 0x0002f9ef, 0x00000c7e, 0x0002f9f0, 0x00000c7f, 0x0002f9f1, 0x00000c80, 0x0002f9f2, 0x00000c81, 0x0002f9f3, 0x00000c82, 0x0002f9f4, 0x00000c83, 0x0002f9f5, 0x00000c84, 0x0002f9f6, 0x00000c85, 0x0002f9f7, 0x00000c86, 0x0002f9f8, 0x00000c87, 0x0002f9f9, 0x00000c88, 0x0002f9fa, 0x00000c89, 0x0002f9fb, 0x00000c8a, 0x0002f9fc, 0x00000c8b, 0x0002f9fd, 0x00000c8c, 0x0002f9fe, 0x00000c8d, 0x0002f9ff, 0x00000c8e, 0x0002fa00, 0x00000c8f, 0x0002fa01, 0x00000c90, 0x0002fa02, 0x00000c91, 0x0002fa03, 0x00000c92, 0x0002fa04, 0x00000c93, 0x0002fa05, 0x00000c94, 0x0002fa06, 0x00000c95, 0x0002fa07, 0x00000c96, 0x0002fa08, 0x00000c97, 0x0002fa09, 0x00000c98, 0x0002fa0a, 0x00000c99, 0x0002fa0b, 0x00000c9a, 0x0002fa0c, 0x00000c9b, 0x0002fa0d, 0x00000c9c, 0x0002fa0e, 0x00000c9d, 0x0002fa0f, 0x00000c9e, 0x0002fa10, 0x00000c9f, 0x0002fa11, 0x00000ca0, 0x0002fa12, 0x00000ca1, 0x0002fa13, 0x00000ca2, 0x0002fa14, 0x00000ca3, 0x0002fa15, 0x00000ca4, 0x0002fa16, 0x00000ca5, 0x0002fa17, 0x00000ca6, 0x0002fa18, 0x00000ca7, 0x0002fa19, 0x00000ca8, 0x0002fa1a, 0x00000ca9, 0x0002fa1b, 0x00000caa, 0x0002fa1c, 0x00000cab, 0x0002fa1d, 0x00000cac, 0x00000cad }; static const ac_uint4 _ucdcmp_decomp[] = { 0x00000041, 0x00000300, 0x00000041, 0x00000301, 0x00000041, 0x00000302, 0x00000041, 0x00000303, 0x00000041, 0x00000308, 0x00000041, 0x0000030a, 0x00000043, 0x00000327, 0x00000045, 0x00000300, 0x00000045, 0x00000301, 0x00000045, 0x00000302, 0x00000045, 0x00000308, 0x00000049, 0x00000300, 0x00000049, 0x00000301, 0x00000049, 0x00000302, 0x00000049, 0x00000308, 0x0000004e, 0x00000303, 0x0000004f, 0x00000300, 0x0000004f, 0x00000301, 0x0000004f, 0x00000302, 0x0000004f, 0x00000303, 0x0000004f, 0x00000308, 0x00000055, 0x00000300, 0x00000055, 0x00000301, 0x00000055, 0x00000302, 0x00000055, 0x00000308, 0x00000059, 0x00000301, 0x00000061, 0x00000300, 0x00000061, 0x00000301, 0x00000061, 0x00000302, 0x00000061, 0x00000303, 0x00000061, 0x00000308, 0x00000061, 0x0000030a, 0x00000063, 0x00000327, 0x00000065, 0x00000300, 0x00000065, 0x00000301, 0x00000065, 0x00000302, 0x00000065, 0x00000308, 0x00000069, 0x00000300, 0x00000069, 0x00000301, 0x00000069, 0x00000302, 0x00000069, 0x00000308, 0x0000006e, 0x00000303, 0x0000006f, 0x00000300, 0x0000006f, 0x00000301, 0x0000006f, 0x00000302, 0x0000006f, 0x00000303, 0x0000006f, 0x00000308, 0x00000075, 0x00000300, 0x00000075, 0x00000301, 0x00000075, 0x00000302, 0x00000075, 0x00000308, 0x00000079, 0x00000301, 0x00000079, 0x00000308, 0x00000041, 0x00000304, 0x00000061, 0x00000304, 0x00000041, 0x00000306, 0x00000061, 0x00000306, 0x00000041, 0x00000328, 0x00000061, 0x00000328, 0x00000043, 0x00000301, 0x00000063, 0x00000301, 0x00000043, 0x00000302, 0x00000063, 0x00000302, 0x00000043, 0x00000307, 0x00000063, 0x00000307, 0x00000043, 0x0000030c, 0x00000063, 0x0000030c, 0x00000044, 0x0000030c, 0x00000064, 0x0000030c, 0x00000045, 0x00000304, 0x00000065, 0x00000304, 0x00000045, 0x00000306, 0x00000065, 0x00000306, 0x00000045, 0x00000307, 0x00000065, 0x00000307, 0x00000045, 0x00000328, 0x00000065, 0x00000328, 0x00000045, 0x0000030c, 0x00000065, 0x0000030c, 0x00000047, 0x00000302, 0x00000067, 0x00000302, 0x00000047, 0x00000306, 0x00000067, 0x00000306, 0x00000047, 0x00000307, 0x00000067, 0x00000307, 0x00000047, 0x00000327, 0x00000067, 0x00000327, 0x00000048, 0x00000302, 0x00000068, 0x00000302, 0x00000049, 0x00000303, 0x00000069, 0x00000303, 0x00000049, 0x00000304, 0x00000069, 0x00000304, 0x00000049, 0x00000306, 0x00000069, 0x00000306, 0x00000049, 0x00000328, 0x00000069, 0x00000328, 0x00000049, 0x00000307, 0x0000004a, 0x00000302, 0x0000006a, 0x00000302, 0x0000004b, 0x00000327, 0x0000006b, 0x00000327, 0x0000004c, 0x00000301, 0x0000006c, 0x00000301, 0x0000004c, 0x00000327, 0x0000006c, 0x00000327, 0x0000004c, 0x0000030c, 0x0000006c, 0x0000030c, 0x0000004e, 0x00000301, 0x0000006e, 0x00000301, 0x0000004e, 0x00000327, 0x0000006e, 0x00000327, 0x0000004e, 0x0000030c, 0x0000006e, 0x0000030c, 0x0000004f, 0x00000304, 0x0000006f, 0x00000304, 0x0000004f, 0x00000306, 0x0000006f, 0x00000306, 0x0000004f, 0x0000030b, 0x0000006f, 0x0000030b, 0x00000052, 0x00000301, 0x00000072, 0x00000301, 0x00000052, 0x00000327, 0x00000072, 0x00000327, 0x00000052, 0x0000030c, 0x00000072, 0x0000030c, 0x00000053, 0x00000301, 0x00000073, 0x00000301, 0x00000053, 0x00000302, 0x00000073, 0x00000302, 0x00000053, 0x00000327, 0x00000073, 0x00000327, 0x00000053, 0x0000030c, 0x00000073, 0x0000030c, 0x00000054, 0x00000327, 0x00000074, 0x00000327, 0x00000054, 0x0000030c, 0x00000074, 0x0000030c, 0x00000055, 0x00000303, 0x00000075, 0x00000303, 0x00000055, 0x00000304, 0x00000075, 0x00000304, 0x00000055, 0x00000306, 0x00000075, 0x00000306, 0x00000055, 0x0000030a, 0x00000075, 0x0000030a, 0x00000055, 0x0000030b, 0x00000075, 0x0000030b, 0x00000055, 0x00000328, 0x00000075, 0x00000328, 0x00000057, 0x00000302, 0x00000077, 0x00000302, 0x00000059, 0x00000302, 0x00000079, 0x00000302, 0x00000059, 0x00000308, 0x0000005a, 0x00000301, 0x0000007a, 0x00000301, 0x0000005a, 0x00000307, 0x0000007a, 0x00000307, 0x0000005a, 0x0000030c, 0x0000007a, 0x0000030c, 0x0000004f, 0x0000031b, 0x0000006f, 0x0000031b, 0x00000055, 0x0000031b, 0x00000075, 0x0000031b, 0x00000041, 0x0000030c, 0x00000061, 0x0000030c, 0x00000049, 0x0000030c, 0x00000069, 0x0000030c, 0x0000004f, 0x0000030c, 0x0000006f, 0x0000030c, 0x00000055, 0x0000030c, 0x00000075, 0x0000030c, 0x00000055, 0x00000308, 0x00000304, 0x00000075, 0x00000308, 0x00000304, 0x00000055, 0x00000308, 0x00000301, 0x00000075, 0x00000308, 0x00000301, 0x00000055, 0x00000308, 0x0000030c, 0x00000075, 0x00000308, 0x0000030c, 0x00000055, 0x00000308, 0x00000300, 0x00000075, 0x00000308, 0x00000300, 0x00000041, 0x00000308, 0x00000304, 0x00000061, 0x00000308, 0x00000304, 0x00000041, 0x00000307, 0x00000304, 0x00000061, 0x00000307, 0x00000304, 0x000000c6, 0x00000304, 0x000000e6, 0x00000304, 0x00000047, 0x0000030c, 0x00000067, 0x0000030c, 0x0000004b, 0x0000030c, 0x0000006b, 0x0000030c, 0x0000004f, 0x00000328, 0x0000006f, 0x00000328, 0x0000004f, 0x00000328, 0x00000304, 0x0000006f, 0x00000328, 0x00000304, 0x000001b7, 0x0000030c, 0x00000292, 0x0000030c, 0x0000006a, 0x0000030c, 0x00000047, 0x00000301, 0x00000067, 0x00000301, 0x0000004e, 0x00000300, 0x0000006e, 0x00000300, 0x00000041, 0x0000030a, 0x00000301, 0x00000061, 0x0000030a, 0x00000301, 0x000000c6, 0x00000301, 0x000000e6, 0x00000301, 0x000000d8, 0x00000301, 0x000000f8, 0x00000301, 0x00000041, 0x0000030f, 0x00000061, 0x0000030f, 0x00000041, 0x00000311, 0x00000061, 0x00000311, 0x00000045, 0x0000030f, 0x00000065, 0x0000030f, 0x00000045, 0x00000311, 0x00000065, 0x00000311, 0x00000049, 0x0000030f, 0x00000069, 0x0000030f, 0x00000049, 0x00000311, 0x00000069, 0x00000311, 0x0000004f, 0x0000030f, 0x0000006f, 0x0000030f, 0x0000004f, 0x00000311, 0x0000006f, 0x00000311, 0x00000052, 0x0000030f, 0x00000072, 0x0000030f, 0x00000052, 0x00000311, 0x00000072, 0x00000311, 0x00000055, 0x0000030f, 0x00000075, 0x0000030f, 0x00000055, 0x00000311, 0x00000075, 0x00000311, 0x00000053, 0x00000326, 0x00000073, 0x00000326, 0x00000054, 0x00000326, 0x00000074, 0x00000326, 0x00000048, 0x0000030c, 0x00000068, 0x0000030c, 0x00000041, 0x00000307, 0x00000061, 0x00000307, 0x00000045, 0x00000327, 0x00000065, 0x00000327, 0x0000004f, 0x00000308, 0x00000304, 0x0000006f, 0x00000308, 0x00000304, 0x0000004f, 0x00000303, 0x00000304, 0x0000006f, 0x00000303, 0x00000304, 0x0000004f, 0x00000307, 0x0000006f, 0x00000307, 0x0000004f, 0x00000307, 0x00000304, 0x0000006f, 0x00000307, 0x00000304, 0x00000059, 0x00000304, 0x00000079, 0x00000304, 0x00000300, 0x00000301, 0x00000313, 0x00000308, 0x00000301, 0x000002b9, 0x0000003b, 0x000000a8, 0x00000301, 0x00000391, 0x00000301, 0x000000b7, 0x00000395, 0x00000301, 0x00000397, 0x00000301, 0x00000399, 0x00000301, 0x0000039f, 0x00000301, 0x000003a5, 0x00000301, 0x000003a9, 0x00000301, 0x000003b9, 0x00000308, 0x00000301, 0x00000399, 0x00000308, 0x000003a5, 0x00000308, 0x000003b1, 0x00000301, 0x000003b5, 0x00000301, 0x000003b7, 0x00000301, 0x000003b9, 0x00000301, 0x000003c5, 0x00000308, 0x00000301, 0x000003b9, 0x00000308, 0x000003c5, 0x00000308, 0x000003bf, 0x00000301, 0x000003c5, 0x00000301, 0x000003c9, 0x00000301, 0x000003d2, 0x00000301, 0x000003d2, 0x00000308, 0x00000415, 0x00000300, 0x00000415, 0x00000308, 0x00000413, 0x00000301, 0x00000406, 0x00000308, 0x0000041a, 0x00000301, 0x00000418, 0x00000300, 0x00000423, 0x00000306, 0x00000418, 0x00000306, 0x00000438, 0x00000306, 0x00000435, 0x00000300, 0x00000435, 0x00000308, 0x00000433, 0x00000301, 0x00000456, 0x00000308, 0x0000043a, 0x00000301, 0x00000438, 0x00000300, 0x00000443, 0x00000306, 0x00000474, 0x0000030f, 0x00000475, 0x0000030f, 0x00000416, 0x00000306, 0x00000436, 0x00000306, 0x00000410, 0x00000306, 0x00000430, 0x00000306, 0x00000410, 0x00000308, 0x00000430, 0x00000308, 0x00000415, 0x00000306, 0x00000435, 0x00000306, 0x000004d8, 0x00000308, 0x000004d9, 0x00000308, 0x00000416, 0x00000308, 0x00000436, 0x00000308, 0x00000417, 0x00000308, 0x00000437, 0x00000308, 0x00000418, 0x00000304, 0x00000438, 0x00000304, 0x00000418, 0x00000308, 0x00000438, 0x00000308, 0x0000041e, 0x00000308, 0x0000043e, 0x00000308, 0x000004e8, 0x00000308, 0x000004e9, 0x00000308, 0x0000042d, 0x00000308, 0x0000044d, 0x00000308, 0x00000423, 0x00000304, 0x00000443, 0x00000304, 0x00000423, 0x00000308, 0x00000443, 0x00000308, 0x00000423, 0x0000030b, 0x00000443, 0x0000030b, 0x00000427, 0x00000308, 0x00000447, 0x00000308, 0x0000042b, 0x00000308, 0x0000044b, 0x00000308, 0x00000627, 0x00000653, 0x00000627, 0x00000654, 0x00000648, 0x00000654, 0x00000627, 0x00000655, 0x0000064a, 0x00000654, 0x000006d5, 0x00000654, 0x000006c1, 0x00000654, 0x000006d2, 0x00000654, 0x00000928, 0x0000093c, 0x00000930, 0x0000093c, 0x00000933, 0x0000093c, 0x00000915, 0x0000093c, 0x00000916, 0x0000093c, 0x00000917, 0x0000093c, 0x0000091c, 0x0000093c, 0x00000921, 0x0000093c, 0x00000922, 0x0000093c, 0x0000092b, 0x0000093c, 0x0000092f, 0x0000093c, 0x000009c7, 0x000009be, 0x000009c7, 0x000009d7, 0x000009a1, 0x000009bc, 0x000009a2, 0x000009bc, 0x000009af, 0x000009bc, 0x00000a32, 0x00000a3c, 0x00000a38, 0x00000a3c, 0x00000a16, 0x00000a3c, 0x00000a17, 0x00000a3c, 0x00000a1c, 0x00000a3c, 0x00000a2b, 0x00000a3c, 0x00000b47, 0x00000b56, 0x00000b47, 0x00000b3e, 0x00000b47, 0x00000b57, 0x00000b21, 0x00000b3c, 0x00000b22, 0x00000b3c, 0x00000b92, 0x00000bd7, 0x00000bc6, 0x00000bbe, 0x00000bc7, 0x00000bbe, 0x00000bc6, 0x00000bd7, 0x00000c46, 0x00000c56, 0x00000cbf, 0x00000cd5, 0x00000cc6, 0x00000cd5, 0x00000cc6, 0x00000cd6, 0x00000cc6, 0x00000cc2, 0x00000cc6, 0x00000cc2, 0x00000cd5, 0x00000d46, 0x00000d3e, 0x00000d47, 0x00000d3e, 0x00000d46, 0x00000d57, 0x00000dd9, 0x00000dca, 0x00000dd9, 0x00000dcf, 0x00000dd9, 0x00000dcf, 0x00000dca, 0x00000dd9, 0x00000ddf, 0x00000f42, 0x00000fb7, 0x00000f4c, 0x00000fb7, 0x00000f51, 0x00000fb7, 0x00000f56, 0x00000fb7, 0x00000f5b, 0x00000fb7, 0x00000f40, 0x00000fb5, 0x00000f71, 0x00000f72, 0x00000f71, 0x00000f74, 0x00000fb2, 0x00000f80, 0x00000fb3, 0x00000f80, 0x00000f71, 0x00000f80, 0x00000f92, 0x00000fb7, 0x00000f9c, 0x00000fb7, 0x00000fa1, 0x00000fb7, 0x00000fa6, 0x00000fb7, 0x00000fab, 0x00000fb7, 0x00000f90, 0x00000fb5, 0x00001025, 0x0000102e, 0x00000041, 0x00000325, 0x00000061, 0x00000325, 0x00000042, 0x00000307, 0x00000062, 0x00000307, 0x00000042, 0x00000323, 0x00000062, 0x00000323, 0x00000042, 0x00000331, 0x00000062, 0x00000331, 0x00000043, 0x00000327, 0x00000301, 0x00000063, 0x00000327, 0x00000301, 0x00000044, 0x00000307, 0x00000064, 0x00000307, 0x00000044, 0x00000323, 0x00000064, 0x00000323, 0x00000044, 0x00000331, 0x00000064, 0x00000331, 0x00000044, 0x00000327, 0x00000064, 0x00000327, 0x00000044, 0x0000032d, 0x00000064, 0x0000032d, 0x00000045, 0x00000304, 0x00000300, 0x00000065, 0x00000304, 0x00000300, 0x00000045, 0x00000304, 0x00000301, 0x00000065, 0x00000304, 0x00000301, 0x00000045, 0x0000032d, 0x00000065, 0x0000032d, 0x00000045, 0x00000330, 0x00000065, 0x00000330, 0x00000045, 0x00000327, 0x00000306, 0x00000065, 0x00000327, 0x00000306, 0x00000046, 0x00000307, 0x00000066, 0x00000307, 0x00000047, 0x00000304, 0x00000067, 0x00000304, 0x00000048, 0x00000307, 0x00000068, 0x00000307, 0x00000048, 0x00000323, 0x00000068, 0x00000323, 0x00000048, 0x00000308, 0x00000068, 0x00000308, 0x00000048, 0x00000327, 0x00000068, 0x00000327, 0x00000048, 0x0000032e, 0x00000068, 0x0000032e, 0x00000049, 0x00000330, 0x00000069, 0x00000330, 0x00000049, 0x00000308, 0x00000301, 0x00000069, 0x00000308, 0x00000301, 0x0000004b, 0x00000301, 0x0000006b, 0x00000301, 0x0000004b, 0x00000323, 0x0000006b, 0x00000323, 0x0000004b, 0x00000331, 0x0000006b, 0x00000331, 0x0000004c, 0x00000323, 0x0000006c, 0x00000323, 0x0000004c, 0x00000323, 0x00000304, 0x0000006c, 0x00000323, 0x00000304, 0x0000004c, 0x00000331, 0x0000006c, 0x00000331, 0x0000004c, 0x0000032d, 0x0000006c, 0x0000032d, 0x0000004d, 0x00000301, 0x0000006d, 0x00000301, 0x0000004d, 0x00000307, 0x0000006d, 0x00000307, 0x0000004d, 0x00000323, 0x0000006d, 0x00000323, 0x0000004e, 0x00000307, 0x0000006e, 0x00000307, 0x0000004e, 0x00000323, 0x0000006e, 0x00000323, 0x0000004e, 0x00000331, 0x0000006e, 0x00000331, 0x0000004e, 0x0000032d, 0x0000006e, 0x0000032d, 0x0000004f, 0x00000303, 0x00000301, 0x0000006f, 0x00000303, 0x00000301, 0x0000004f, 0x00000303, 0x00000308, 0x0000006f, 0x00000303, 0x00000308, 0x0000004f, 0x00000304, 0x00000300, 0x0000006f, 0x00000304, 0x00000300, 0x0000004f, 0x00000304, 0x00000301, 0x0000006f, 0x00000304, 0x00000301, 0x00000050, 0x00000301, 0x00000070, 0x00000301, 0x00000050, 0x00000307, 0x00000070, 0x00000307, 0x00000052, 0x00000307, 0x00000072, 0x00000307, 0x00000052, 0x00000323, 0x00000072, 0x00000323, 0x00000052, 0x00000323, 0x00000304, 0x00000072, 0x00000323, 0x00000304, 0x00000052, 0x00000331, 0x00000072, 0x00000331, 0x00000053, 0x00000307, 0x00000073, 0x00000307, 0x00000053, 0x00000323, 0x00000073, 0x00000323, 0x00000053, 0x00000301, 0x00000307, 0x00000073, 0x00000301, 0x00000307, 0x00000053, 0x0000030c, 0x00000307, 0x00000073, 0x0000030c, 0x00000307, 0x00000053, 0x00000323, 0x00000307, 0x00000073, 0x00000323, 0x00000307, 0x00000054, 0x00000307, 0x00000074, 0x00000307, 0x00000054, 0x00000323, 0x00000074, 0x00000323, 0x00000054, 0x00000331, 0x00000074, 0x00000331, 0x00000054, 0x0000032d, 0x00000074, 0x0000032d, 0x00000055, 0x00000324, 0x00000075, 0x00000324, 0x00000055, 0x00000330, 0x00000075, 0x00000330, 0x00000055, 0x0000032d, 0x00000075, 0x0000032d, 0x00000055, 0x00000303, 0x00000301, 0x00000075, 0x00000303, 0x00000301, 0x00000055, 0x00000304, 0x00000308, 0x00000075, 0x00000304, 0x00000308, 0x00000056, 0x00000303, 0x00000076, 0x00000303, 0x00000056, 0x00000323, 0x00000076, 0x00000323, 0x00000057, 0x00000300, 0x00000077, 0x00000300, 0x00000057, 0x00000301, 0x00000077, 0x00000301, 0x00000057, 0x00000308, 0x00000077, 0x00000308, 0x00000057, 0x00000307, 0x00000077, 0x00000307, 0x00000057, 0x00000323, 0x00000077, 0x00000323, 0x00000058, 0x00000307, 0x00000078, 0x00000307, 0x00000058, 0x00000308, 0x00000078, 0x00000308, 0x00000059, 0x00000307, 0x00000079, 0x00000307, 0x0000005a, 0x00000302, 0x0000007a, 0x00000302, 0x0000005a, 0x00000323, 0x0000007a, 0x00000323, 0x0000005a, 0x00000331, 0x0000007a, 0x00000331, 0x00000068, 0x00000331, 0x00000074, 0x00000308, 0x00000077, 0x0000030a, 0x00000079, 0x0000030a, 0x0000017f, 0x00000307, 0x00000041, 0x00000323, 0x00000061, 0x00000323, 0x00000041, 0x00000309, 0x00000061, 0x00000309, 0x00000041, 0x00000302, 0x00000301, 0x00000061, 0x00000302, 0x00000301, 0x00000041, 0x00000302, 0x00000300, 0x00000061, 0x00000302, 0x00000300, 0x00000041, 0x00000302, 0x00000309, 0x00000061, 0x00000302, 0x00000309, 0x00000041, 0x00000302, 0x00000303, 0x00000061, 0x00000302, 0x00000303, 0x00000041, 0x00000323, 0x00000302, 0x00000061, 0x00000323, 0x00000302, 0x00000041, 0x00000306, 0x00000301, 0x00000061, 0x00000306, 0x00000301, 0x00000041, 0x00000306, 0x00000300, 0x00000061, 0x00000306, 0x00000300, 0x00000041, 0x00000306, 0x00000309, 0x00000061, 0x00000306, 0x00000309, 0x00000041, 0x00000306, 0x00000303, 0x00000061, 0x00000306, 0x00000303, 0x00000041, 0x00000323, 0x00000306, 0x00000061, 0x00000323, 0x00000306, 0x00000045, 0x00000323, 0x00000065, 0x00000323, 0x00000045, 0x00000309, 0x00000065, 0x00000309, 0x00000045, 0x00000303, 0x00000065, 0x00000303, 0x00000045, 0x00000302, 0x00000301, 0x00000065, 0x00000302, 0x00000301, 0x00000045, 0x00000302, 0x00000300, 0x00000065, 0x00000302, 0x00000300, 0x00000045, 0x00000302, 0x00000309, 0x00000065, 0x00000302, 0x00000309, 0x00000045, 0x00000302, 0x00000303, 0x00000065, 0x00000302, 0x00000303, 0x00000045, 0x00000323, 0x00000302, 0x00000065, 0x00000323, 0x00000302, 0x00000049, 0x00000309, 0x00000069, 0x00000309, 0x00000049, 0x00000323, 0x00000069, 0x00000323, 0x0000004f, 0x00000323, 0x0000006f, 0x00000323, 0x0000004f, 0x00000309, 0x0000006f, 0x00000309, 0x0000004f, 0x00000302, 0x00000301, 0x0000006f, 0x00000302, 0x00000301, 0x0000004f, 0x00000302, 0x00000300, 0x0000006f, 0x00000302, 0x00000300, 0x0000004f, 0x00000302, 0x00000309, 0x0000006f, 0x00000302, 0x00000309, 0x0000004f, 0x00000302, 0x00000303, 0x0000006f, 0x00000302, 0x00000303, 0x0000004f, 0x00000323, 0x00000302, 0x0000006f, 0x00000323, 0x00000302, 0x0000004f, 0x0000031b, 0x00000301, 0x0000006f, 0x0000031b, 0x00000301, 0x0000004f, 0x0000031b, 0x00000300, 0x0000006f, 0x0000031b, 0x00000300, 0x0000004f, 0x0000031b, 0x00000309, 0x0000006f, 0x0000031b, 0x00000309, 0x0000004f, 0x0000031b, 0x00000303, 0x0000006f, 0x0000031b, 0x00000303, 0x0000004f, 0x0000031b, 0x00000323, 0x0000006f, 0x0000031b, 0x00000323, 0x00000055, 0x00000323, 0x00000075, 0x00000323, 0x00000055, 0x00000309, 0x00000075, 0x00000309, 0x00000055, 0x0000031b, 0x00000301, 0x00000075, 0x0000031b, 0x00000301, 0x00000055, 0x0000031b, 0x00000300, 0x00000075, 0x0000031b, 0x00000300, 0x00000055, 0x0000031b, 0x00000309, 0x00000075, 0x0000031b, 0x00000309, 0x00000055, 0x0000031b, 0x00000303, 0x00000075, 0x0000031b, 0x00000303, 0x00000055, 0x0000031b, 0x00000323, 0x00000075, 0x0000031b, 0x00000323, 0x00000059, 0x00000300, 0x00000079, 0x00000300, 0x00000059, 0x00000323, 0x00000079, 0x00000323, 0x00000059, 0x00000309, 0x00000079, 0x00000309, 0x00000059, 0x00000303, 0x00000079, 0x00000303, 0x000003b1, 0x00000313, 0x000003b1, 0x00000314, 0x000003b1, 0x00000313, 0x00000300, 0x000003b1, 0x00000314, 0x00000300, 0x000003b1, 0x00000313, 0x00000301, 0x000003b1, 0x00000314, 0x00000301, 0x000003b1, 0x00000313, 0x00000342, 0x000003b1, 0x00000314, 0x00000342, 0x00000391, 0x00000313, 0x00000391, 0x00000314, 0x00000391, 0x00000313, 0x00000300, 0x00000391, 0x00000314, 0x00000300, 0x00000391, 0x00000313, 0x00000301, 0x00000391, 0x00000314, 0x00000301, 0x00000391, 0x00000313, 0x00000342, 0x00000391, 0x00000314, 0x00000342, 0x000003b5, 0x00000313, 0x000003b5, 0x00000314, 0x000003b5, 0x00000313, 0x00000300, 0x000003b5, 0x00000314, 0x00000300, 0x000003b5, 0x00000313, 0x00000301, 0x000003b5, 0x00000314, 0x00000301, 0x00000395, 0x00000313, 0x00000395, 0x00000314, 0x00000395, 0x00000313, 0x00000300, 0x00000395, 0x00000314, 0x00000300, 0x00000395, 0x00000313, 0x00000301, 0x00000395, 0x00000314, 0x00000301, 0x000003b7, 0x00000313, 0x000003b7, 0x00000314, 0x000003b7, 0x00000313, 0x00000300, 0x000003b7, 0x00000314, 0x00000300, 0x000003b7, 0x00000313, 0x00000301, 0x000003b7, 0x00000314, 0x00000301, 0x000003b7, 0x00000313, 0x00000342, 0x000003b7, 0x00000314, 0x00000342, 0x00000397, 0x00000313, 0x00000397, 0x00000314, 0x00000397, 0x00000313, 0x00000300, 0x00000397, 0x00000314, 0x00000300, 0x00000397, 0x00000313, 0x00000301, 0x00000397, 0x00000314, 0x00000301, 0x00000397, 0x00000313, 0x00000342, 0x00000397, 0x00000314, 0x00000342, 0x000003b9, 0x00000313, 0x000003b9, 0x00000314, 0x000003b9, 0x00000313, 0x00000300, 0x000003b9, 0x00000314, 0x00000300, 0x000003b9, 0x00000313, 0x00000301, 0x000003b9, 0x00000314, 0x00000301, 0x000003b9, 0x00000313, 0x00000342, 0x000003b9, 0x00000314, 0x00000342, 0x00000399, 0x00000313, 0x00000399, 0x00000314, 0x00000399, 0x00000313, 0x00000300, 0x00000399, 0x00000314, 0x00000300, 0x00000399, 0x00000313, 0x00000301, 0x00000399, 0x00000314, 0x00000301, 0x00000399, 0x00000313, 0x00000342, 0x00000399, 0x00000314, 0x00000342, 0x000003bf, 0x00000313, 0x000003bf, 0x00000314, 0x000003bf, 0x00000313, 0x00000300, 0x000003bf, 0x00000314, 0x00000300, 0x000003bf, 0x00000313, 0x00000301, 0x000003bf, 0x00000314, 0x00000301, 0x0000039f, 0x00000313, 0x0000039f, 0x00000314, 0x0000039f, 0x00000313, 0x00000300, 0x0000039f, 0x00000314, 0x00000300, 0x0000039f, 0x00000313, 0x00000301, 0x0000039f, 0x00000314, 0x00000301, 0x000003c5, 0x00000313, 0x000003c5, 0x00000314, 0x000003c5, 0x00000313, 0x00000300, 0x000003c5, 0x00000314, 0x00000300, 0x000003c5, 0x00000313, 0x00000301, 0x000003c5, 0x00000314, 0x00000301, 0x000003c5, 0x00000313, 0x00000342, 0x000003c5, 0x00000314, 0x00000342, 0x000003a5, 0x00000314, 0x000003a5, 0x00000314, 0x00000300, 0x000003a5, 0x00000314, 0x00000301, 0x000003a5, 0x00000314, 0x00000342, 0x000003c9, 0x00000313, 0x000003c9, 0x00000314, 0x000003c9, 0x00000313, 0x00000300, 0x000003c9, 0x00000314, 0x00000300, 0x000003c9, 0x00000313, 0x00000301, 0x000003c9, 0x00000314, 0x00000301, 0x000003c9, 0x00000313, 0x00000342, 0x000003c9, 0x00000314, 0x00000342, 0x000003a9, 0x00000313, 0x000003a9, 0x00000314, 0x000003a9, 0x00000313, 0x00000300, 0x000003a9, 0x00000314, 0x00000300, 0x000003a9, 0x00000313, 0x00000301, 0x000003a9, 0x00000314, 0x00000301, 0x000003a9, 0x00000313, 0x00000342, 0x000003a9, 0x00000314, 0x00000342, 0x000003b1, 0x00000300, 0x000003b1, 0x00000301, 0x000003b5, 0x00000300, 0x000003b5, 0x00000301, 0x000003b7, 0x00000300, 0x000003b7, 0x00000301, 0x000003b9, 0x00000300, 0x000003b9, 0x00000301, 0x000003bf, 0x00000300, 0x000003bf, 0x00000301, 0x000003c5, 0x00000300, 0x000003c5, 0x00000301, 0x000003c9, 0x00000300, 0x000003c9, 0x00000301, 0x000003b1, 0x00000313, 0x00000345, 0x000003b1, 0x00000314, 0x00000345, 0x000003b1, 0x00000313, 0x00000300, 0x00000345, 0x000003b1, 0x00000314, 0x00000300, 0x00000345, 0x000003b1, 0x00000313, 0x00000301, 0x00000345, 0x000003b1, 0x00000314, 0x00000301, 0x00000345, 0x000003b1, 0x00000313, 0x00000342, 0x00000345, 0x000003b1, 0x00000314, 0x00000342, 0x00000345, 0x00000391, 0x00000313, 0x00000345, 0x00000391, 0x00000314, 0x00000345, 0x00000391, 0x00000313, 0x00000300, 0x00000345, 0x00000391, 0x00000314, 0x00000300, 0x00000345, 0x00000391, 0x00000313, 0x00000301, 0x00000345, 0x00000391, 0x00000314, 0x00000301, 0x00000345, 0x00000391, 0x00000313, 0x00000342, 0x00000345, 0x00000391, 0x00000314, 0x00000342, 0x00000345, 0x000003b7, 0x00000313, 0x00000345, 0x000003b7, 0x00000314, 0x00000345, 0x000003b7, 0x00000313, 0x00000300, 0x00000345, 0x000003b7, 0x00000314, 0x00000300, 0x00000345, 0x000003b7, 0x00000313, 0x00000301, 0x00000345, 0x000003b7, 0x00000314, 0x00000301, 0x00000345, 0x000003b7, 0x00000313, 0x00000342, 0x00000345, 0x000003b7, 0x00000314, 0x00000342, 0x00000345, 0x00000397, 0x00000313, 0x00000345, 0x00000397, 0x00000314, 0x00000345, 0x00000397, 0x00000313, 0x00000300, 0x00000345, 0x00000397, 0x00000314, 0x00000300, 0x00000345, 0x00000397, 0x00000313, 0x00000301, 0x00000345, 0x00000397, 0x00000314, 0x00000301, 0x00000345, 0x00000397, 0x00000313, 0x00000342, 0x00000345, 0x00000397, 0x00000314, 0x00000342, 0x00000345, 0x000003c9, 0x00000313, 0x00000345, 0x000003c9, 0x00000314, 0x00000345, 0x000003c9, 0x00000313, 0x00000300, 0x00000345, 0x000003c9, 0x00000314, 0x00000300, 0x00000345, 0x000003c9, 0x00000313, 0x00000301, 0x00000345, 0x000003c9, 0x00000314, 0x00000301, 0x00000345, 0x000003c9, 0x00000313, 0x00000342, 0x00000345, 0x000003c9, 0x00000314, 0x00000342, 0x00000345, 0x000003a9, 0x00000313, 0x00000345, 0x000003a9, 0x00000314, 0x00000345, 0x000003a9, 0x00000313, 0x00000300, 0x00000345, 0x000003a9, 0x00000314, 0x00000300, 0x00000345, 0x000003a9, 0x00000313, 0x00000301, 0x00000345, 0x000003a9, 0x00000314, 0x00000301, 0x00000345, 0x000003a9, 0x00000313, 0x00000342, 0x00000345, 0x000003a9, 0x00000314, 0x00000342, 0x00000345, 0x000003b1, 0x00000306, 0x000003b1, 0x00000304, 0x000003b1, 0x00000300, 0x00000345, 0x000003b1, 0x00000345, 0x000003b1, 0x00000301, 0x00000345, 0x000003b1, 0x00000342, 0x000003b1, 0x00000342, 0x00000345, 0x00000391, 0x00000306, 0x00000391, 0x00000304, 0x00000391, 0x00000300, 0x00000391, 0x00000301, 0x00000391, 0x00000345, 0x000003b9, 0x000000a8, 0x00000342, 0x000003b7, 0x00000300, 0x00000345, 0x000003b7, 0x00000345, 0x000003b7, 0x00000301, 0x00000345, 0x000003b7, 0x00000342, 0x000003b7, 0x00000342, 0x00000345, 0x00000395, 0x00000300, 0x00000395, 0x00000301, 0x00000397, 0x00000300, 0x00000397, 0x00000301, 0x00000397, 0x00000345, 0x00001fbf, 0x00000300, 0x00001fbf, 0x00000301, 0x00001fbf, 0x00000342, 0x000003b9, 0x00000306, 0x000003b9, 0x00000304, 0x000003b9, 0x00000308, 0x00000300, 0x000003b9, 0x00000308, 0x00000301, 0x000003b9, 0x00000342, 0x000003b9, 0x00000308, 0x00000342, 0x00000399, 0x00000306, 0x00000399, 0x00000304, 0x00000399, 0x00000300, 0x00000399, 0x00000301, 0x00001ffe, 0x00000300, 0x00001ffe, 0x00000301, 0x00001ffe, 0x00000342, 0x000003c5, 0x00000306, 0x000003c5, 0x00000304, 0x000003c5, 0x00000308, 0x00000300, 0x000003c5, 0x00000308, 0x00000301, 0x000003c1, 0x00000313, 0x000003c1, 0x00000314, 0x000003c5, 0x00000342, 0x000003c5, 0x00000308, 0x00000342, 0x000003a5, 0x00000306, 0x000003a5, 0x00000304, 0x000003a5, 0x00000300, 0x000003a5, 0x00000301, 0x000003a1, 0x00000314, 0x000000a8, 0x00000300, 0x000000a8, 0x00000301, 0x00000060, 0x000003c9, 0x00000300, 0x00000345, 0x000003c9, 0x00000345, 0x000003c9, 0x00000301, 0x00000345, 0x000003c9, 0x00000342, 0x000003c9, 0x00000342, 0x00000345, 0x0000039f, 0x00000300, 0x0000039f, 0x00000301, 0x000003a9, 0x00000300, 0x000003a9, 0x00000301, 0x000003a9, 0x00000345, 0x000000b4, 0x00002002, 0x00002003, 0x000003a9, 0x0000004b, 0x00000041, 0x0000030a, 0x00002190, 0x00000338, 0x00002192, 0x00000338, 0x00002194, 0x00000338, 0x000021d0, 0x00000338, 0x000021d4, 0x00000338, 0x000021d2, 0x00000338, 0x00002203, 0x00000338, 0x00002208, 0x00000338, 0x0000220b, 0x00000338, 0x00002223, 0x00000338, 0x00002225, 0x00000338, 0x0000223c, 0x00000338, 0x00002243, 0x00000338, 0x00002245, 0x00000338, 0x00002248, 0x00000338, 0x0000003d, 0x00000338, 0x00002261, 0x00000338, 0x0000224d, 0x00000338, 0x0000003c, 0x00000338, 0x0000003e, 0x00000338, 0x00002264, 0x00000338, 0x00002265, 0x00000338, 0x00002272, 0x00000338, 0x00002273, 0x00000338, 0x00002276, 0x00000338, 0x00002277, 0x00000338, 0x0000227a, 0x00000338, 0x0000227b, 0x00000338, 0x00002282, 0x00000338, 0x00002283, 0x00000338, 0x00002286, 0x00000338, 0x00002287, 0x00000338, 0x000022a2, 0x00000338, 0x000022a8, 0x00000338, 0x000022a9, 0x00000338, 0x000022ab, 0x00000338, 0x0000227c, 0x00000338, 0x0000227d, 0x00000338, 0x00002291, 0x00000338, 0x00002292, 0x00000338, 0x000022b2, 0x00000338, 0x000022b3, 0x00000338, 0x000022b4, 0x00000338, 0x000022b5, 0x00000338, 0x00003008, 0x00003009, 0x00002add, 0x00000338, 0x0000304b, 0x00003099, 0x0000304d, 0x00003099, 0x0000304f, 0x00003099, 0x00003051, 0x00003099, 0x00003053, 0x00003099, 0x00003055, 0x00003099, 0x00003057, 0x00003099, 0x00003059, 0x00003099, 0x0000305b, 0x00003099, 0x0000305d, 0x00003099, 0x0000305f, 0x00003099, 0x00003061, 0x00003099, 0x00003064, 0x00003099, 0x00003066, 0x00003099, 0x00003068, 0x00003099, 0x0000306f, 0x00003099, 0x0000306f, 0x0000309a, 0x00003072, 0x00003099, 0x00003072, 0x0000309a, 0x00003075, 0x00003099, 0x00003075, 0x0000309a, 0x00003078, 0x00003099, 0x00003078, 0x0000309a, 0x0000307b, 0x00003099, 0x0000307b, 0x0000309a, 0x00003046, 0x00003099, 0x0000309d, 0x00003099, 0x000030ab, 0x00003099, 0x000030ad, 0x00003099, 0x000030af, 0x00003099, 0x000030b1, 0x00003099, 0x000030b3, 0x00003099, 0x000030b5, 0x00003099, 0x000030b7, 0x00003099, 0x000030b9, 0x00003099, 0x000030bb, 0x00003099, 0x000030bd, 0x00003099, 0x000030bf, 0x00003099, 0x000030c1, 0x00003099, 0x000030c4, 0x00003099, 0x000030c6, 0x00003099, 0x000030c8, 0x00003099, 0x000030cf, 0x00003099, 0x000030cf, 0x0000309a, 0x000030d2, 0x00003099, 0x000030d2, 0x0000309a, 0x000030d5, 0x00003099, 0x000030d5, 0x0000309a, 0x000030d8, 0x00003099, 0x000030d8, 0x0000309a, 0x000030db, 0x00003099, 0x000030db, 0x0000309a, 0x000030a6, 0x00003099, 0x000030ef, 0x00003099, 0x000030f0, 0x00003099, 0x000030f1, 0x00003099, 0x000030f2, 0x00003099, 0x000030fd, 0x00003099, 0x00008eca, 0x00008cc8, 0x00006ed1, 0x00004e32, 0x000053e5, 0x00009f9c, 0x00009f9c, 0x00005951, 0x000091d1, 0x00005587, 0x00005948, 0x000061f6, 0x00007669, 0x00007f85, 0x0000863f, 0x000087ba, 0x000088f8, 0x0000908f, 0x00006a02, 0x00006d1b, 0x000070d9, 0x000073de, 0x0000843d, 0x0000916a, 0x000099f1, 0x00004e82, 0x00005375, 0x00006b04, 0x0000721b, 0x0000862d, 0x00009e1e, 0x00005d50, 0x00006feb, 0x000085cd, 0x00008964, 0x000062c9, 0x000081d8, 0x0000881f, 0x00005eca, 0x00006717, 0x00006d6a, 0x000072fc, 0x000090ce, 0x00004f86, 0x000051b7, 0x000052de, 0x000064c4, 0x00006ad3, 0x00007210, 0x000076e7, 0x00008001, 0x00008606, 0x0000865c, 0x00008def, 0x00009732, 0x00009b6f, 0x00009dfa, 0x0000788c, 0x0000797f, 0x00007da0, 0x000083c9, 0x00009304, 0x00009e7f, 0x00008ad6, 0x000058df, 0x00005f04, 0x00007c60, 0x0000807e, 0x00007262, 0x000078ca, 0x00008cc2, 0x000096f7, 0x000058d8, 0x00005c62, 0x00006a13, 0x00006dda, 0x00006f0f, 0x00007d2f, 0x00007e37, 0x0000964b, 0x000052d2, 0x0000808b, 0x000051dc, 0x000051cc, 0x00007a1c, 0x00007dbe, 0x000083f1, 0x00009675, 0x00008b80, 0x000062cf, 0x00006a02, 0x00008afe, 0x00004e39, 0x00005be7, 0x00006012, 0x00007387, 0x00007570, 0x00005317, 0x000078fb, 0x00004fbf, 0x00005fa9, 0x00004e0d, 0x00006ccc, 0x00006578, 0x00007d22, 0x000053c3, 0x0000585e, 0x00007701, 0x00008449, 0x00008aaa, 0x00006bba, 0x00008fb0, 0x00006c88, 0x000062fe, 0x000082e5, 0x000063a0, 0x00007565, 0x00004eae, 0x00005169, 0x000051c9, 0x00006881, 0x00007ce7, 0x0000826f, 0x00008ad2, 0x000091cf, 0x000052f5, 0x00005442, 0x00005973, 0x00005eec, 0x000065c5, 0x00006ffe, 0x0000792a, 0x000095ad, 0x00009a6a, 0x00009e97, 0x00009ece, 0x0000529b, 0x000066c6, 0x00006b77, 0x00008f62, 0x00005e74, 0x00006190, 0x00006200, 0x0000649a, 0x00006f23, 0x00007149, 0x00007489, 0x000079ca, 0x00007df4, 0x0000806f, 0x00008f26, 0x000084ee, 0x00009023, 0x0000934a, 0x00005217, 0x000052a3, 0x000054bd, 0x000070c8, 0x000088c2, 0x00008aaa, 0x00005ec9, 0x00005ff5, 0x0000637b, 0x00006bae, 0x00007c3e, 0x00007375, 0x00004ee4, 0x000056f9, 0x00005be7, 0x00005dba, 0x0000601c, 0x000073b2, 0x00007469, 0x00007f9a, 0x00008046, 0x00009234, 0x000096f6, 0x00009748, 0x00009818, 0x00004f8b, 0x000079ae, 0x000091b4, 0x000096b8, 0x000060e1, 0x00004e86, 0x000050da, 0x00005bee, 0x00005c3f, 0x00006599, 0x00006a02, 0x000071ce, 0x00007642, 0x000084fc, 0x0000907c, 0x00009f8d, 0x00006688, 0x0000962e, 0x00005289, 0x0000677b, 0x000067f3, 0x00006d41, 0x00006e9c, 0x00007409, 0x00007559, 0x0000786b, 0x00007d10, 0x0000985e, 0x0000516d, 0x0000622e, 0x00009678, 0x0000502b, 0x00005d19, 0x00006dea, 0x00008f2a, 0x00005f8b, 0x00006144, 0x00006817, 0x00007387, 0x00009686, 0x00005229, 0x0000540f, 0x00005c65, 0x00006613, 0x0000674e, 0x000068a8, 0x00006ce5, 0x00007406, 0x000075e2, 0x00007f79, 0x000088cf, 0x000088e1, 0x000091cc, 0x000096e2, 0x0000533f, 0x00006eba, 0x0000541d, 0x000071d0, 0x00007498, 0x000085fa, 0x000096a3, 0x00009c57, 0x00009e9f, 0x00006797, 0x00006dcb, 0x000081e8, 0x00007acb, 0x00007b20, 0x00007c92, 0x000072c0, 0x00007099, 0x00008b58, 0x00004ec0, 0x00008336, 0x0000523a, 0x00005207, 0x00005ea6, 0x000062d3, 0x00007cd6, 0x00005b85, 0x00006d1e, 0x000066b4, 0x00008f3b, 0x0000884c, 0x0000964d, 0x0000898b, 0x00005ed3, 0x00005140, 0x000055c0, 0x0000585a, 0x00006674, 0x000051de, 0x0000732a, 0x000076ca, 0x0000793c, 0x0000795e, 0x00007965, 0x0000798f, 0x00009756, 0x00007cbe, 0x00007fbd, 0x00008612, 0x00008af8, 0x00009038, 0x000090fd, 0x000098ef, 0x000098fc, 0x00009928, 0x00009db4, 0x00004fae, 0x000050e7, 0x0000514d, 0x000052c9, 0x000052e4, 0x00005351, 0x0000559d, 0x00005606, 0x00005668, 0x00005840, 0x000058a8, 0x00005c64, 0x00005c6e, 0x00006094, 0x00006168, 0x0000618e, 0x000061f2, 0x0000654f, 0x000065e2, 0x00006691, 0x00006885, 0x00006d77, 0x00006e1a, 0x00006f22, 0x0000716e, 0x0000722b, 0x00007422, 0x00007891, 0x0000793e, 0x00007949, 0x00007948, 0x00007950, 0x00007956, 0x0000795d, 0x0000798d, 0x0000798e, 0x00007a40, 0x00007a81, 0x00007bc0, 0x00007df4, 0x00007e09, 0x00007e41, 0x00007f72, 0x00008005, 0x000081ed, 0x00008279, 0x00008279, 0x00008457, 0x00008910, 0x00008996, 0x00008b01, 0x00008b39, 0x00008cd3, 0x00008d08, 0x00008fb6, 0x00009038, 0x000096e3, 0x000097ff, 0x0000983b, 0x000005d9, 0x000005b4, 0x000005f2, 0x000005b7, 0x000005e9, 0x000005c1, 0x000005e9, 0x000005c2, 0x000005e9, 0x000005bc, 0x000005c1, 0x000005e9, 0x000005bc, 0x000005c2, 0x000005d0, 0x000005b7, 0x000005d0, 0x000005b8, 0x000005d0, 0x000005bc, 0x000005d1, 0x000005bc, 0x000005d2, 0x000005bc, 0x000005d3, 0x000005bc, 0x000005d4, 0x000005bc, 0x000005d5, 0x000005bc, 0x000005d6, 0x000005bc, 0x000005d8, 0x000005bc, 0x000005d9, 0x000005bc, 0x000005da, 0x000005bc, 0x000005db, 0x000005bc, 0x000005dc, 0x000005bc, 0x000005de, 0x000005bc, 0x000005e0, 0x000005bc, 0x000005e1, 0x000005bc, 0x000005e3, 0x000005bc, 0x000005e4, 0x000005bc, 0x000005e6, 0x000005bc, 0x000005e7, 0x000005bc, 0x000005e8, 0x000005bc, 0x000005e9, 0x000005bc, 0x000005ea, 0x000005bc, 0x000005d5, 0x000005b9, 0x000005d1, 0x000005bf, 0x000005db, 0x000005bf, 0x000005e4, 0x000005bf, 0x0001d157, 0x0001d165, 0x0001d158, 0x0001d165, 0x0001d158, 0x0001d165, 0x0001d16e, 0x0001d158, 0x0001d165, 0x0001d16f, 0x0001d158, 0x0001d165, 0x0001d170, 0x0001d158, 0x0001d165, 0x0001d171, 0x0001d158, 0x0001d165, 0x0001d172, 0x0001d1b9, 0x0001d165, 0x0001d1ba, 0x0001d165, 0x0001d1b9, 0x0001d165, 0x0001d16e, 0x0001d1ba, 0x0001d165, 0x0001d16e, 0x0001d1b9, 0x0001d165, 0x0001d16f, 0x0001d1ba, 0x0001d165, 0x0001d16f, 0x00004e3d, 0x00004e38, 0x00004e41, 0x00020122, 0x00004f60, 0x00004fae, 0x00004fbb, 0x00005002, 0x0000507a, 0x00005099, 0x000050e7, 0x000050cf, 0x0000349e, 0x0002063a, 0x0000514d, 0x00005154, 0x00005164, 0x00005177, 0x0002051c, 0x000034b9, 0x00005167, 0x0000518d, 0x0002054b, 0x00005197, 0x000051a4, 0x00004ecc, 0x000051ac, 0x000051b5, 0x000291df, 0x000051f5, 0x00005203, 0x000034df, 0x0000523b, 0x00005246, 0x00005272, 0x00005277, 0x00003515, 0x000052c7, 0x000052c9, 0x000052e4, 0x000052fa, 0x00005305, 0x00005306, 0x00005317, 0x00005349, 0x00005351, 0x0000535a, 0x00005373, 0x0000537d, 0x0000537f, 0x0000537f, 0x0000537f, 0x00020a2c, 0x00007070, 0x000053ca, 0x000053df, 0x00020b63, 0x000053eb, 0x000053f1, 0x00005406, 0x0000549e, 0x00005438, 0x00005448, 0x00005468, 0x000054a2, 0x000054f6, 0x00005510, 0x00005553, 0x00005563, 0x00005584, 0x00005584, 0x00005599, 0x000055ab, 0x000055b3, 0x000055c2, 0x00005716, 0x00005606, 0x00005717, 0x00005651, 0x00005674, 0x00005207, 0x000058ee, 0x000057ce, 0x000057f4, 0x0000580d, 0x0000578b, 0x00005832, 0x00005831, 0x000058ac, 0x000214e4, 0x000058f2, 0x000058f7, 0x00005906, 0x0000591a, 0x00005922, 0x00005962, 0x000216a8, 0x000216ea, 0x000059ec, 0x00005a1b, 0x00005a27, 0x000059d8, 0x00005a66, 0x000036ee, 0x0002136a, 0x00005b08, 0x00005b3e, 0x00005b3e, 0x000219c8, 0x00005bc3, 0x00005bd8, 0x00005be7, 0x00005bf3, 0x00021b18, 0x00005bff, 0x00005c06, 0x00005f33, 0x00005c22, 0x00003781, 0x00005c60, 0x00005c6e, 0x00005cc0, 0x00005c8d, 0x00021de4, 0x00005d43, 0x00021de6, 0x00005d6e, 0x00005d6b, 0x00005d7c, 0x00005de1, 0x00005de2, 0x0000382f, 0x00005dfd, 0x00005e28, 0x00005e3d, 0x00005e69, 0x00003862, 0x00022183, 0x0000387c, 0x00005eb0, 0x00005eb3, 0x00005eb6, 0x00005eca, 0x0002a392, 0x00005efe, 0x00022331, 0x00022331, 0x00008201, 0x00005f22, 0x00005f22, 0x000038c7, 0x000232b8, 0x000261da, 0x00005f62, 0x00005f6b, 0x000038e3, 0x00005f9a, 0x00005fcd, 0x00005fd7, 0x00005ff9, 0x00006081, 0x0000393a, 0x0000391c, 0x00006094, 0x000226d4, 0x000060c7, 0x00006148, 0x0000614c, 0x0000614e, 0x0000614c, 0x0000617a, 0x0000618e, 0x000061b2, 0x000061a4, 0x000061af, 0x000061de, 0x000061f2, 0x000061f6, 0x00006210, 0x0000621b, 0x0000625d, 0x000062b1, 0x000062d4, 0x00006350, 0x00022b0c, 0x0000633d, 0x000062fc, 0x00006368, 0x00006383, 0x000063e4, 0x00022bf1, 0x00006422, 0x000063c5, 0x000063a9, 0x00003a2e, 0x00006469, 0x0000647e, 0x0000649d, 0x00006477, 0x00003a6c, 0x0000654f, 0x0000656c, 0x0002300a, 0x000065e3, 0x000066f8, 0x00006649, 0x00003b19, 0x00006691, 0x00003b08, 0x00003ae4, 0x00005192, 0x00005195, 0x00006700, 0x0000669c, 0x000080ad, 0x000043d9, 0x00006717, 0x0000671b, 0x00006721, 0x0000675e, 0x00006753, 0x000233c3, 0x00003b49, 0x000067fa, 0x00006785, 0x00006852, 0x00006885, 0x0002346d, 0x0000688e, 0x0000681f, 0x00006914, 0x00003b9d, 0x00006942, 0x000069a3, 0x000069ea, 0x00006aa8, 0x000236a3, 0x00006adb, 0x00003c18, 0x00006b21, 0x000238a7, 0x00006b54, 0x00003c4e, 0x00006b72, 0x00006b9f, 0x00006bba, 0x00006bbb, 0x00023a8d, 0x00021d0b, 0x00023afa, 0x00006c4e, 0x00023cbc, 0x00006cbf, 0x00006ccd, 0x00006c67, 0x00006d16, 0x00006d3e, 0x00006d77, 0x00006d41, 0x00006d69, 0x00006d78, 0x00006d85, 0x00023d1e, 0x00006d34, 0x00006e2f, 0x00006e6e, 0x00003d33, 0x00006ecb, 0x00006ec7, 0x00023ed1, 0x00006df9, 0x00006f6e, 0x00023f5e, 0x00023f8e, 0x00006fc6, 0x00007039, 0x0000701e, 0x0000701b, 0x00003d96, 0x0000704a, 0x0000707d, 0x00007077, 0x000070ad, 0x00020525, 0x00007145, 0x00024263, 0x0000719c, 0x000043ab, 0x00007228, 0x00007235, 0x00007250, 0x00024608, 0x00007280, 0x00007295, 0x00024735, 0x00024814, 0x0000737a, 0x0000738b, 0x00003eac, 0x000073a5, 0x00003eb8, 0x00003eb8, 0x00007447, 0x0000745c, 0x00007471, 0x00007485, 0x000074ca, 0x00003f1b, 0x00007524, 0x00024c36, 0x0000753e, 0x00024c92, 0x00007570, 0x0002219f, 0x00007610, 0x00024fa1, 0x00024fb8, 0x00025044, 0x00003ffc, 0x00004008, 0x000076f4, 0x000250f3, 0x000250f2, 0x00025119, 0x00025133, 0x0000771e, 0x0000771f, 0x0000771f, 0x0000774a, 0x00004039, 0x0000778b, 0x00004046, 0x00004096, 0x0002541d, 0x0000784e, 0x0000788c, 0x000078cc, 0x000040e3, 0x00025626, 0x00007956, 0x0002569a, 0x000256c5, 0x0000798f, 0x000079eb, 0x0000412f, 0x00007a40, 0x00007a4a, 0x00007a4f, 0x0002597c, 0x00025aa7, 0x00025aa7, 0x00007aae, 0x00004202, 0x00025bab, 0x00007bc6, 0x00007bc9, 0x00004227, 0x00025c80, 0x00007cd2, 0x000042a0, 0x00007ce8, 0x00007ce3, 0x00007d00, 0x00025f86, 0x00007d63, 0x00004301, 0x00007dc7, 0x00007e02, 0x00007e45, 0x00004334, 0x00026228, 0x00026247, 0x00004359, 0x000262d9, 0x00007f7a, 0x0002633e, 0x00007f95, 0x00007ffa, 0x00008005, 0x000264da, 0x00026523, 0x00008060, 0x000265a8, 0x00008070, 0x0002335f, 0x000043d5, 0x000080b2, 0x00008103, 0x0000440b, 0x0000813e, 0x00005ab5, 0x000267a7, 0x000267b5, 0x00023393, 0x0002339c, 0x00008201, 0x00008204, 0x00008f9e, 0x0000446b, 0x00008291, 0x0000828b, 0x0000829d, 0x000052b3, 0x000082b1, 0x000082b3, 0x000082bd, 0x000082e6, 0x00026b3c, 0x000082e5, 0x0000831d, 0x00008363, 0x000083ad, 0x00008323, 0x000083bd, 0x000083e7, 0x00008457, 0x00008353, 0x000083ca, 0x000083cc, 0x000083dc, 0x00026c36, 0x00026d6b, 0x00026cd5, 0x0000452b, 0x000084f1, 0x000084f3, 0x00008516, 0x000273ca, 0x00008564, 0x00026f2c, 0x0000455d, 0x00004561, 0x00026fb1, 0x000270d2, 0x0000456b, 0x00008650, 0x0000865c, 0x00008667, 0x00008669, 0x000086a9, 0x00008688, 0x0000870e, 0x000086e2, 0x00008779, 0x00008728, 0x0000876b, 0x00008786, 0x00004d57, 0x000087e1, 0x00008801, 0x000045f9, 0x00008860, 0x00008863, 0x00027667, 0x000088d7, 0x000088de, 0x00004635, 0x000088fa, 0x000034bb, 0x000278ae, 0x00027966, 0x000046be, 0x000046c7, 0x00008aa0, 0x00008aed, 0x00008b8a, 0x00008c55, 0x00027ca8, 0x00008cab, 0x00008cc1, 0x00008d1b, 0x00008d77, 0x00027f2f, 0x00020804, 0x00008dcb, 0x00008dbc, 0x00008df0, 0x000208de, 0x00008ed4, 0x00008f38, 0x000285d2, 0x000285ed, 0x00009094, 0x000090f1, 0x00009111, 0x0002872e, 0x0000911b, 0x00009238, 0x000092d7, 0x000092d8, 0x0000927c, 0x000093f9, 0x00009415, 0x00028bfa, 0x0000958b, 0x00004995, 0x000095b7, 0x00028d77, 0x000049e6, 0x000096c3, 0x00005db2, 0x00009723, 0x00029145, 0x0002921a, 0x00004a6e, 0x00004a76, 0x000097e0, 0x0002940a, 0x00004ab2, 0x00029496, 0x0000980b, 0x0000980b, 0x00009829, 0x000295b6, 0x000098e2, 0x00004b33, 0x00009929, 0x000099a7, 0x000099c2, 0x000099fe, 0x00004bce, 0x00029b30, 0x00009b12, 0x00009c40, 0x00009cfd, 0x00004cce, 0x00004ced, 0x00009d67, 0x0002a0ce, 0x00004cf8, 0x0002a105, 0x0002a20e, 0x0002a291, 0x00009ebb, 0x00004d56, 0x00009ef9, 0x00009efe, 0x00009f05, 0x00009f0f, 0x00009f16, 0x00009f3b, 0x0002a600 }; static const ac_uint4 _uckdcmp_size = 10282; static const ac_uint4 _uckdcmp_nodes[] = { 0x000000a0, 0x00000000, 0x000000a8, 0x00000001, 0x000000aa, 0x00000003, 0x000000af, 0x00000004, 0x000000b2, 0x00000006, 0x000000b3, 0x00000007, 0x000000b4, 0x00000008, 0x000000b5, 0x0000000a, 0x000000b8, 0x0000000b, 0x000000b9, 0x0000000d, 0x000000ba, 0x0000000e, 0x000000bc, 0x0000000f, 0x000000bd, 0x00000012, 0x000000be, 0x00000015, 0x000000c0, 0x00000018, 0x000000c1, 0x0000001a, 0x000000c2, 0x0000001c, 0x000000c3, 0x0000001e, 0x000000c4, 0x00000020, 0x000000c5, 0x00000022, 0x000000c7, 0x00000024, 0x000000c8, 0x00000026, 0x000000c9, 0x00000028, 0x000000ca, 0x0000002a, 0x000000cb, 0x0000002c, 0x000000cc, 0x0000002e, 0x000000cd, 0x00000030, 0x000000ce, 0x00000032, 0x000000cf, 0x00000034, 0x000000d1, 0x00000036, 0x000000d2, 0x00000038, 0x000000d3, 0x0000003a, 0x000000d4, 0x0000003c, 0x000000d5, 0x0000003e, 0x000000d6, 0x00000040, 0x000000d9, 0x00000042, 0x000000da, 0x00000044, 0x000000db, 0x00000046, 0x000000dc, 0x00000048, 0x000000dd, 0x0000004a, 0x000000e0, 0x0000004c, 0x000000e1, 0x0000004e, 0x000000e2, 0x00000050, 0x000000e3, 0x00000052, 0x000000e4, 0x00000054, 0x000000e5, 0x00000056, 0x000000e7, 0x00000058, 0x000000e8, 0x0000005a, 0x000000e9, 0x0000005c, 0x000000ea, 0x0000005e, 0x000000eb, 0x00000060, 0x000000ec, 0x00000062, 0x000000ed, 0x00000064, 0x000000ee, 0x00000066, 0x000000ef, 0x00000068, 0x000000f1, 0x0000006a, 0x000000f2, 0x0000006c, 0x000000f3, 0x0000006e, 0x000000f4, 0x00000070, 0x000000f5, 0x00000072, 0x000000f6, 0x00000074, 0x000000f9, 0x00000076, 0x000000fa, 0x00000078, 0x000000fb, 0x0000007a, 0x000000fc, 0x0000007c, 0x000000fd, 0x0000007e, 0x000000ff, 0x00000080, 0x00000100, 0x00000082, 0x00000101, 0x00000084, 0x00000102, 0x00000086, 0x00000103, 0x00000088, 0x00000104, 0x0000008a, 0x00000105, 0x0000008c, 0x00000106, 0x0000008e, 0x00000107, 0x00000090, 0x00000108, 0x00000092, 0x00000109, 0x00000094, 0x0000010a, 0x00000096, 0x0000010b, 0x00000098, 0x0000010c, 0x0000009a, 0x0000010d, 0x0000009c, 0x0000010e, 0x0000009e, 0x0000010f, 0x000000a0, 0x00000112, 0x000000a2, 0x00000113, 0x000000a4, 0x00000114, 0x000000a6, 0x00000115, 0x000000a8, 0x00000116, 0x000000aa, 0x00000117, 0x000000ac, 0x00000118, 0x000000ae, 0x00000119, 0x000000b0, 0x0000011a, 0x000000b2, 0x0000011b, 0x000000b4, 0x0000011c, 0x000000b6, 0x0000011d, 0x000000b8, 0x0000011e, 0x000000ba, 0x0000011f, 0x000000bc, 0x00000120, 0x000000be, 0x00000121, 0x000000c0, 0x00000122, 0x000000c2, 0x00000123, 0x000000c4, 0x00000124, 0x000000c6, 0x00000125, 0x000000c8, 0x00000128, 0x000000ca, 0x00000129, 0x000000cc, 0x0000012a, 0x000000ce, 0x0000012b, 0x000000d0, 0x0000012c, 0x000000d2, 0x0000012d, 0x000000d4, 0x0000012e, 0x000000d6, 0x0000012f, 0x000000d8, 0x00000130, 0x000000da, 0x00000132, 0x000000dc, 0x00000133, 0x000000de, 0x00000134, 0x000000e0, 0x00000135, 0x000000e2, 0x00000136, 0x000000e4, 0x00000137, 0x000000e6, 0x00000139, 0x000000e8, 0x0000013a, 0x000000ea, 0x0000013b, 0x000000ec, 0x0000013c, 0x000000ee, 0x0000013d, 0x000000f0, 0x0000013e, 0x000000f2, 0x0000013f, 0x000000f4, 0x00000140, 0x000000f6, 0x00000143, 0x000000f8, 0x00000144, 0x000000fa, 0x00000145, 0x000000fc, 0x00000146, 0x000000fe, 0x00000147, 0x00000100, 0x00000148, 0x00000102, 0x00000149, 0x00000104, 0x0000014c, 0x00000106, 0x0000014d, 0x00000108, 0x0000014e, 0x0000010a, 0x0000014f, 0x0000010c, 0x00000150, 0x0000010e, 0x00000151, 0x00000110, 0x00000154, 0x00000112, 0x00000155, 0x00000114, 0x00000156, 0x00000116, 0x00000157, 0x00000118, 0x00000158, 0x0000011a, 0x00000159, 0x0000011c, 0x0000015a, 0x0000011e, 0x0000015b, 0x00000120, 0x0000015c, 0x00000122, 0x0000015d, 0x00000124, 0x0000015e, 0x00000126, 0x0000015f, 0x00000128, 0x00000160, 0x0000012a, 0x00000161, 0x0000012c, 0x00000162, 0x0000012e, 0x00000163, 0x00000130, 0x00000164, 0x00000132, 0x00000165, 0x00000134, 0x00000168, 0x00000136, 0x00000169, 0x00000138, 0x0000016a, 0x0000013a, 0x0000016b, 0x0000013c, 0x0000016c, 0x0000013e, 0x0000016d, 0x00000140, 0x0000016e, 0x00000142, 0x0000016f, 0x00000144, 0x00000170, 0x00000146, 0x00000171, 0x00000148, 0x00000172, 0x0000014a, 0x00000173, 0x0000014c, 0x00000174, 0x0000014e, 0x00000175, 0x00000150, 0x00000176, 0x00000152, 0x00000177, 0x00000154, 0x00000178, 0x00000156, 0x00000179, 0x00000158, 0x0000017a, 0x0000015a, 0x0000017b, 0x0000015c, 0x0000017c, 0x0000015e, 0x0000017d, 0x00000160, 0x0000017e, 0x00000162, 0x0000017f, 0x00000164, 0x000001a0, 0x00000165, 0x000001a1, 0x00000167, 0x000001af, 0x00000169, 0x000001b0, 0x0000016b, 0x000001c4, 0x0000016d, 0x000001c5, 0x00000170, 0x000001c6, 0x00000173, 0x000001c7, 0x00000176, 0x000001c8, 0x00000178, 0x000001c9, 0x0000017a, 0x000001ca, 0x0000017c, 0x000001cb, 0x0000017e, 0x000001cc, 0x00000180, 0x000001cd, 0x00000182, 0x000001ce, 0x00000184, 0x000001cf, 0x00000186, 0x000001d0, 0x00000188, 0x000001d1, 0x0000018a, 0x000001d2, 0x0000018c, 0x000001d3, 0x0000018e, 0x000001d4, 0x00000190, 0x000001d5, 0x00000192, 0x000001d6, 0x00000195, 0x000001d7, 0x00000198, 0x000001d8, 0x0000019b, 0x000001d9, 0x0000019e, 0x000001da, 0x000001a1, 0x000001db, 0x000001a4, 0x000001dc, 0x000001a7, 0x000001de, 0x000001aa, 0x000001df, 0x000001ad, 0x000001e0, 0x000001b0, 0x000001e1, 0x000001b3, 0x000001e2, 0x000001b6, 0x000001e3, 0x000001b8, 0x000001e6, 0x000001ba, 0x000001e7, 0x000001bc, 0x000001e8, 0x000001be, 0x000001e9, 0x000001c0, 0x000001ea, 0x000001c2, 0x000001eb, 0x000001c4, 0x000001ec, 0x000001c6, 0x000001ed, 0x000001c9, 0x000001ee, 0x000001cc, 0x000001ef, 0x000001ce, 0x000001f0, 0x000001d0, 0x000001f1, 0x000001d2, 0x000001f2, 0x000001d4, 0x000001f3, 0x000001d6, 0x000001f4, 0x000001d8, 0x000001f5, 0x000001da, 0x000001f8, 0x000001dc, 0x000001f9, 0x000001de, 0x000001fa, 0x000001e0, 0x000001fb, 0x000001e3, 0x000001fc, 0x000001e6, 0x000001fd, 0x000001e8, 0x000001fe, 0x000001ea, 0x000001ff, 0x000001ec, 0x00000200, 0x000001ee, 0x00000201, 0x000001f0, 0x00000202, 0x000001f2, 0x00000203, 0x000001f4, 0x00000204, 0x000001f6, 0x00000205, 0x000001f8, 0x00000206, 0x000001fa, 0x00000207, 0x000001fc, 0x00000208, 0x000001fe, 0x00000209, 0x00000200, 0x0000020a, 0x00000202, 0x0000020b, 0x00000204, 0x0000020c, 0x00000206, 0x0000020d, 0x00000208, 0x0000020e, 0x0000020a, 0x0000020f, 0x0000020c, 0x00000210, 0x0000020e, 0x00000211, 0x00000210, 0x00000212, 0x00000212, 0x00000213, 0x00000214, 0x00000214, 0x00000216, 0x00000215, 0x00000218, 0x00000216, 0x0000021a, 0x00000217, 0x0000021c, 0x00000218, 0x0000021e, 0x00000219, 0x00000220, 0x0000021a, 0x00000222, 0x0000021b, 0x00000224, 0x0000021e, 0x00000226, 0x0000021f, 0x00000228, 0x00000226, 0x0000022a, 0x00000227, 0x0000022c, 0x00000228, 0x0000022e, 0x00000229, 0x00000230, 0x0000022a, 0x00000232, 0x0000022b, 0x00000235, 0x0000022c, 0x00000238, 0x0000022d, 0x0000023b, 0x0000022e, 0x0000023e, 0x0000022f, 0x00000240, 0x00000230, 0x00000242, 0x00000231, 0x00000245, 0x00000232, 0x00000248, 0x00000233, 0x0000024a, 0x000002b0, 0x0000024c, 0x000002b1, 0x0000024d, 0x000002b2, 0x0000024e, 0x000002b3, 0x0000024f, 0x000002b4, 0x00000250, 0x000002b5, 0x00000251, 0x000002b6, 0x00000252, 0x000002b7, 0x00000253, 0x000002b8, 0x00000254, 0x000002d8, 0x00000255, 0x000002d9, 0x00000257, 0x000002da, 0x00000259, 0x000002db, 0x0000025b, 0x000002dc, 0x0000025d, 0x000002dd, 0x0000025f, 0x000002e0, 0x00000261, 0x000002e1, 0x00000262, 0x000002e2, 0x00000263, 0x000002e3, 0x00000264, 0x000002e4, 0x00000265, 0x00000340, 0x00000266, 0x00000341, 0x00000267, 0x00000343, 0x00000268, 0x00000344, 0x00000269, 0x00000374, 0x0000026b, 0x0000037a, 0x0000026c, 0x0000037e, 0x0000026e, 0x00000384, 0x0000026f, 0x00000385, 0x00000271, 0x00000386, 0x00000274, 0x00000387, 0x00000276, 0x00000388, 0x00000277, 0x00000389, 0x00000279, 0x0000038a, 0x0000027b, 0x0000038c, 0x0000027d, 0x0000038e, 0x0000027f, 0x0000038f, 0x00000281, 0x00000390, 0x00000283, 0x000003aa, 0x00000286, 0x000003ab, 0x00000288, 0x000003ac, 0x0000028a, 0x000003ad, 0x0000028c, 0x000003ae, 0x0000028e, 0x000003af, 0x00000290, 0x000003b0, 0x00000292, 0x000003ca, 0x00000295, 0x000003cb, 0x00000297, 0x000003cc, 0x00000299, 0x000003cd, 0x0000029b, 0x000003ce, 0x0000029d, 0x000003d0, 0x0000029f, 0x000003d1, 0x000002a0, 0x000003d2, 0x000002a1, 0x000003d3, 0x000002a2, 0x000003d4, 0x000002a4, 0x000003d5, 0x000002a6, 0x000003d6, 0x000002a7, 0x000003f0, 0x000002a8, 0x000003f1, 0x000002a9, 0x000003f2, 0x000002aa, 0x000003f4, 0x000002ab, 0x000003f5, 0x000002ac, 0x00000400, 0x000002ad, 0x00000401, 0x000002af, 0x00000403, 0x000002b1, 0x00000407, 0x000002b3, 0x0000040c, 0x000002b5, 0x0000040d, 0x000002b7, 0x0000040e, 0x000002b9, 0x00000419, 0x000002bb, 0x00000439, 0x000002bd, 0x00000450, 0x000002bf, 0x00000451, 0x000002c1, 0x00000453, 0x000002c3, 0x00000457, 0x000002c5, 0x0000045c, 0x000002c7, 0x0000045d, 0x000002c9, 0x0000045e, 0x000002cb, 0x00000476, 0x000002cd, 0x00000477, 0x000002cf, 0x000004c1, 0x000002d1, 0x000004c2, 0x000002d3, 0x000004d0, 0x000002d5, 0x000004d1, 0x000002d7, 0x000004d2, 0x000002d9, 0x000004d3, 0x000002db, 0x000004d6, 0x000002dd, 0x000004d7, 0x000002df, 0x000004da, 0x000002e1, 0x000004db, 0x000002e3, 0x000004dc, 0x000002e5, 0x000004dd, 0x000002e7, 0x000004de, 0x000002e9, 0x000004df, 0x000002eb, 0x000004e2, 0x000002ed, 0x000004e3, 0x000002ef, 0x000004e4, 0x000002f1, 0x000004e5, 0x000002f3, 0x000004e6, 0x000002f5, 0x000004e7, 0x000002f7, 0x000004ea, 0x000002f9, 0x000004eb, 0x000002fb, 0x000004ec, 0x000002fd, 0x000004ed, 0x000002ff, 0x000004ee, 0x00000301, 0x000004ef, 0x00000303, 0x000004f0, 0x00000305, 0x000004f1, 0x00000307, 0x000004f2, 0x00000309, 0x000004f3, 0x0000030b, 0x000004f4, 0x0000030d, 0x000004f5, 0x0000030f, 0x000004f8, 0x00000311, 0x000004f9, 0x00000313, 0x00000587, 0x00000315, 0x00000622, 0x00000317, 0x00000623, 0x00000319, 0x00000624, 0x0000031b, 0x00000625, 0x0000031d, 0x00000626, 0x0000031f, 0x00000675, 0x00000321, 0x00000676, 0x00000323, 0x00000677, 0x00000325, 0x00000678, 0x00000327, 0x000006c0, 0x00000329, 0x000006c2, 0x0000032b, 0x000006d3, 0x0000032d, 0x00000929, 0x0000032f, 0x00000931, 0x00000331, 0x00000934, 0x00000333, 0x00000958, 0x00000335, 0x00000959, 0x00000337, 0x0000095a, 0x00000339, 0x0000095b, 0x0000033b, 0x0000095c, 0x0000033d, 0x0000095d, 0x0000033f, 0x0000095e, 0x00000341, 0x0000095f, 0x00000343, 0x000009cb, 0x00000345, 0x000009cc, 0x00000347, 0x000009dc, 0x00000349, 0x000009dd, 0x0000034b, 0x000009df, 0x0000034d, 0x00000a33, 0x0000034f, 0x00000a36, 0x00000351, 0x00000a59, 0x00000353, 0x00000a5a, 0x00000355, 0x00000a5b, 0x00000357, 0x00000a5e, 0x00000359, 0x00000b48, 0x0000035b, 0x00000b4b, 0x0000035d, 0x00000b4c, 0x0000035f, 0x00000b5c, 0x00000361, 0x00000b5d, 0x00000363, 0x00000b94, 0x00000365, 0x00000bca, 0x00000367, 0x00000bcb, 0x00000369, 0x00000bcc, 0x0000036b, 0x00000c48, 0x0000036d, 0x00000cc0, 0x0000036f, 0x00000cc7, 0x00000371, 0x00000cc8, 0x00000373, 0x00000cca, 0x00000375, 0x00000ccb, 0x00000377, 0x00000d4a, 0x0000037a, 0x00000d4b, 0x0000037c, 0x00000d4c, 0x0000037e, 0x00000dda, 0x00000380, 0x00000ddc, 0x00000382, 0x00000ddd, 0x00000384, 0x00000dde, 0x00000387, 0x00000e33, 0x00000389, 0x00000eb3, 0x0000038b, 0x00000edc, 0x0000038d, 0x00000edd, 0x0000038f, 0x00000f0c, 0x00000391, 0x00000f43, 0x00000392, 0x00000f4d, 0x00000394, 0x00000f52, 0x00000396, 0x00000f57, 0x00000398, 0x00000f5c, 0x0000039a, 0x00000f69, 0x0000039c, 0x00000f73, 0x0000039e, 0x00000f75, 0x000003a0, 0x00000f76, 0x000003a2, 0x00000f77, 0x000003a4, 0x00000f78, 0x000003a7, 0x00000f79, 0x000003a9, 0x00000f81, 0x000003ac, 0x00000f93, 0x000003ae, 0x00000f9d, 0x000003b0, 0x00000fa2, 0x000003b2, 0x00000fa7, 0x000003b4, 0x00000fac, 0x000003b6, 0x00000fb9, 0x000003b8, 0x00001026, 0x000003ba, 0x00001e00, 0x000003bc, 0x00001e01, 0x000003be, 0x00001e02, 0x000003c0, 0x00001e03, 0x000003c2, 0x00001e04, 0x000003c4, 0x00001e05, 0x000003c6, 0x00001e06, 0x000003c8, 0x00001e07, 0x000003ca, 0x00001e08, 0x000003cc, 0x00001e09, 0x000003cf, 0x00001e0a, 0x000003d2, 0x00001e0b, 0x000003d4, 0x00001e0c, 0x000003d6, 0x00001e0d, 0x000003d8, 0x00001e0e, 0x000003da, 0x00001e0f, 0x000003dc, 0x00001e10, 0x000003de, 0x00001e11, 0x000003e0, 0x00001e12, 0x000003e2, 0x00001e13, 0x000003e4, 0x00001e14, 0x000003e6, 0x00001e15, 0x000003e9, 0x00001e16, 0x000003ec, 0x00001e17, 0x000003ef, 0x00001e18, 0x000003f2, 0x00001e19, 0x000003f4, 0x00001e1a, 0x000003f6, 0x00001e1b, 0x000003f8, 0x00001e1c, 0x000003fa, 0x00001e1d, 0x000003fd, 0x00001e1e, 0x00000400, 0x00001e1f, 0x00000402, 0x00001e20, 0x00000404, 0x00001e21, 0x00000406, 0x00001e22, 0x00000408, 0x00001e23, 0x0000040a, 0x00001e24, 0x0000040c, 0x00001e25, 0x0000040e, 0x00001e26, 0x00000410, 0x00001e27, 0x00000412, 0x00001e28, 0x00000414, 0x00001e29, 0x00000416, 0x00001e2a, 0x00000418, 0x00001e2b, 0x0000041a, 0x00001e2c, 0x0000041c, 0x00001e2d, 0x0000041e, 0x00001e2e, 0x00000420, 0x00001e2f, 0x00000423, 0x00001e30, 0x00000426, 0x00001e31, 0x00000428, 0x00001e32, 0x0000042a, 0x00001e33, 0x0000042c, 0x00001e34, 0x0000042e, 0x00001e35, 0x00000430, 0x00001e36, 0x00000432, 0x00001e37, 0x00000434, 0x00001e38, 0x00000436, 0x00001e39, 0x00000439, 0x00001e3a, 0x0000043c, 0x00001e3b, 0x0000043e, 0x00001e3c, 0x00000440, 0x00001e3d, 0x00000442, 0x00001e3e, 0x00000444, 0x00001e3f, 0x00000446, 0x00001e40, 0x00000448, 0x00001e41, 0x0000044a, 0x00001e42, 0x0000044c, 0x00001e43, 0x0000044e, 0x00001e44, 0x00000450, 0x00001e45, 0x00000452, 0x00001e46, 0x00000454, 0x00001e47, 0x00000456, 0x00001e48, 0x00000458, 0x00001e49, 0x0000045a, 0x00001e4a, 0x0000045c, 0x00001e4b, 0x0000045e, 0x00001e4c, 0x00000460, 0x00001e4d, 0x00000463, 0x00001e4e, 0x00000466, 0x00001e4f, 0x00000469, 0x00001e50, 0x0000046c, 0x00001e51, 0x0000046f, 0x00001e52, 0x00000472, 0x00001e53, 0x00000475, 0x00001e54, 0x00000478, 0x00001e55, 0x0000047a, 0x00001e56, 0x0000047c, 0x00001e57, 0x0000047e, 0x00001e58, 0x00000480, 0x00001e59, 0x00000482, 0x00001e5a, 0x00000484, 0x00001e5b, 0x00000486, 0x00001e5c, 0x00000488, 0x00001e5d, 0x0000048b, 0x00001e5e, 0x0000048e, 0x00001e5f, 0x00000490, 0x00001e60, 0x00000492, 0x00001e61, 0x00000494, 0x00001e62, 0x00000496, 0x00001e63, 0x00000498, 0x00001e64, 0x0000049a, 0x00001e65, 0x0000049d, 0x00001e66, 0x000004a0, 0x00001e67, 0x000004a3, 0x00001e68, 0x000004a6, 0x00001e69, 0x000004a9, 0x00001e6a, 0x000004ac, 0x00001e6b, 0x000004ae, 0x00001e6c, 0x000004b0, 0x00001e6d, 0x000004b2, 0x00001e6e, 0x000004b4, 0x00001e6f, 0x000004b6, 0x00001e70, 0x000004b8, 0x00001e71, 0x000004ba, 0x00001e72, 0x000004bc, 0x00001e73, 0x000004be, 0x00001e74, 0x000004c0, 0x00001e75, 0x000004c2, 0x00001e76, 0x000004c4, 0x00001e77, 0x000004c6, 0x00001e78, 0x000004c8, 0x00001e79, 0x000004cb, 0x00001e7a, 0x000004ce, 0x00001e7b, 0x000004d1, 0x00001e7c, 0x000004d4, 0x00001e7d, 0x000004d6, 0x00001e7e, 0x000004d8, 0x00001e7f, 0x000004da, 0x00001e80, 0x000004dc, 0x00001e81, 0x000004de, 0x00001e82, 0x000004e0, 0x00001e83, 0x000004e2, 0x00001e84, 0x000004e4, 0x00001e85, 0x000004e6, 0x00001e86, 0x000004e8, 0x00001e87, 0x000004ea, 0x00001e88, 0x000004ec, 0x00001e89, 0x000004ee, 0x00001e8a, 0x000004f0, 0x00001e8b, 0x000004f2, 0x00001e8c, 0x000004f4, 0x00001e8d, 0x000004f6, 0x00001e8e, 0x000004f8, 0x00001e8f, 0x000004fa, 0x00001e90, 0x000004fc, 0x00001e91, 0x000004fe, 0x00001e92, 0x00000500, 0x00001e93, 0x00000502, 0x00001e94, 0x00000504, 0x00001e95, 0x00000506, 0x00001e96, 0x00000508, 0x00001e97, 0x0000050a, 0x00001e98, 0x0000050c, 0x00001e99, 0x0000050e, 0x00001e9a, 0x00000510, 0x00001e9b, 0x00000512, 0x00001ea0, 0x00000514, 0x00001ea1, 0x00000516, 0x00001ea2, 0x00000518, 0x00001ea3, 0x0000051a, 0x00001ea4, 0x0000051c, 0x00001ea5, 0x0000051f, 0x00001ea6, 0x00000522, 0x00001ea7, 0x00000525, 0x00001ea8, 0x00000528, 0x00001ea9, 0x0000052b, 0x00001eaa, 0x0000052e, 0x00001eab, 0x00000531, 0x00001eac, 0x00000534, 0x00001ead, 0x00000537, 0x00001eae, 0x0000053a, 0x00001eaf, 0x0000053d, 0x00001eb0, 0x00000540, 0x00001eb1, 0x00000543, 0x00001eb2, 0x00000546, 0x00001eb3, 0x00000549, 0x00001eb4, 0x0000054c, 0x00001eb5, 0x0000054f, 0x00001eb6, 0x00000552, 0x00001eb7, 0x00000555, 0x00001eb8, 0x00000558, 0x00001eb9, 0x0000055a, 0x00001eba, 0x0000055c, 0x00001ebb, 0x0000055e, 0x00001ebc, 0x00000560, 0x00001ebd, 0x00000562, 0x00001ebe, 0x00000564, 0x00001ebf, 0x00000567, 0x00001ec0, 0x0000056a, 0x00001ec1, 0x0000056d, 0x00001ec2, 0x00000570, 0x00001ec3, 0x00000573, 0x00001ec4, 0x00000576, 0x00001ec5, 0x00000579, 0x00001ec6, 0x0000057c, 0x00001ec7, 0x0000057f, 0x00001ec8, 0x00000582, 0x00001ec9, 0x00000584, 0x00001eca, 0x00000586, 0x00001ecb, 0x00000588, 0x00001ecc, 0x0000058a, 0x00001ecd, 0x0000058c, 0x00001ece, 0x0000058e, 0x00001ecf, 0x00000590, 0x00001ed0, 0x00000592, 0x00001ed1, 0x00000595, 0x00001ed2, 0x00000598, 0x00001ed3, 0x0000059b, 0x00001ed4, 0x0000059e, 0x00001ed5, 0x000005a1, 0x00001ed6, 0x000005a4, 0x00001ed7, 0x000005a7, 0x00001ed8, 0x000005aa, 0x00001ed9, 0x000005ad, 0x00001eda, 0x000005b0, 0x00001edb, 0x000005b3, 0x00001edc, 0x000005b6, 0x00001edd, 0x000005b9, 0x00001ede, 0x000005bc, 0x00001edf, 0x000005bf, 0x00001ee0, 0x000005c2, 0x00001ee1, 0x000005c5, 0x00001ee2, 0x000005c8, 0x00001ee3, 0x000005cb, 0x00001ee4, 0x000005ce, 0x00001ee5, 0x000005d0, 0x00001ee6, 0x000005d2, 0x00001ee7, 0x000005d4, 0x00001ee8, 0x000005d6, 0x00001ee9, 0x000005d9, 0x00001eea, 0x000005dc, 0x00001eeb, 0x000005df, 0x00001eec, 0x000005e2, 0x00001eed, 0x000005e5, 0x00001eee, 0x000005e8, 0x00001eef, 0x000005eb, 0x00001ef0, 0x000005ee, 0x00001ef1, 0x000005f1, 0x00001ef2, 0x000005f4, 0x00001ef3, 0x000005f6, 0x00001ef4, 0x000005f8, 0x00001ef5, 0x000005fa, 0x00001ef6, 0x000005fc, 0x00001ef7, 0x000005fe, 0x00001ef8, 0x00000600, 0x00001ef9, 0x00000602, 0x00001f00, 0x00000604, 0x00001f01, 0x00000606, 0x00001f02, 0x00000608, 0x00001f03, 0x0000060b, 0x00001f04, 0x0000060e, 0x00001f05, 0x00000611, 0x00001f06, 0x00000614, 0x00001f07, 0x00000617, 0x00001f08, 0x0000061a, 0x00001f09, 0x0000061c, 0x00001f0a, 0x0000061e, 0x00001f0b, 0x00000621, 0x00001f0c, 0x00000624, 0x00001f0d, 0x00000627, 0x00001f0e, 0x0000062a, 0x00001f0f, 0x0000062d, 0x00001f10, 0x00000630, 0x00001f11, 0x00000632, 0x00001f12, 0x00000634, 0x00001f13, 0x00000637, 0x00001f14, 0x0000063a, 0x00001f15, 0x0000063d, 0x00001f18, 0x00000640, 0x00001f19, 0x00000642, 0x00001f1a, 0x00000644, 0x00001f1b, 0x00000647, 0x00001f1c, 0x0000064a, 0x00001f1d, 0x0000064d, 0x00001f20, 0x00000650, 0x00001f21, 0x00000652, 0x00001f22, 0x00000654, 0x00001f23, 0x00000657, 0x00001f24, 0x0000065a, 0x00001f25, 0x0000065d, 0x00001f26, 0x00000660, 0x00001f27, 0x00000663, 0x00001f28, 0x00000666, 0x00001f29, 0x00000668, 0x00001f2a, 0x0000066a, 0x00001f2b, 0x0000066d, 0x00001f2c, 0x00000670, 0x00001f2d, 0x00000673, 0x00001f2e, 0x00000676, 0x00001f2f, 0x00000679, 0x00001f30, 0x0000067c, 0x00001f31, 0x0000067e, 0x00001f32, 0x00000680, 0x00001f33, 0x00000683, 0x00001f34, 0x00000686, 0x00001f35, 0x00000689, 0x00001f36, 0x0000068c, 0x00001f37, 0x0000068f, 0x00001f38, 0x00000692, 0x00001f39, 0x00000694, 0x00001f3a, 0x00000696, 0x00001f3b, 0x00000699, 0x00001f3c, 0x0000069c, 0x00001f3d, 0x0000069f, 0x00001f3e, 0x000006a2, 0x00001f3f, 0x000006a5, 0x00001f40, 0x000006a8, 0x00001f41, 0x000006aa, 0x00001f42, 0x000006ac, 0x00001f43, 0x000006af, 0x00001f44, 0x000006b2, 0x00001f45, 0x000006b5, 0x00001f48, 0x000006b8, 0x00001f49, 0x000006ba, 0x00001f4a, 0x000006bc, 0x00001f4b, 0x000006bf, 0x00001f4c, 0x000006c2, 0x00001f4d, 0x000006c5, 0x00001f50, 0x000006c8, 0x00001f51, 0x000006ca, 0x00001f52, 0x000006cc, 0x00001f53, 0x000006cf, 0x00001f54, 0x000006d2, 0x00001f55, 0x000006d5, 0x00001f56, 0x000006d8, 0x00001f57, 0x000006db, 0x00001f59, 0x000006de, 0x00001f5b, 0x000006e0, 0x00001f5d, 0x000006e3, 0x00001f5f, 0x000006e6, 0x00001f60, 0x000006e9, 0x00001f61, 0x000006eb, 0x00001f62, 0x000006ed, 0x00001f63, 0x000006f0, 0x00001f64, 0x000006f3, 0x00001f65, 0x000006f6, 0x00001f66, 0x000006f9, 0x00001f67, 0x000006fc, 0x00001f68, 0x000006ff, 0x00001f69, 0x00000701, 0x00001f6a, 0x00000703, 0x00001f6b, 0x00000706, 0x00001f6c, 0x00000709, 0x00001f6d, 0x0000070c, 0x00001f6e, 0x0000070f, 0x00001f6f, 0x00000712, 0x00001f70, 0x00000715, 0x00001f71, 0x00000717, 0x00001f72, 0x00000719, 0x00001f73, 0x0000071b, 0x00001f74, 0x0000071d, 0x00001f75, 0x0000071f, 0x00001f76, 0x00000721, 0x00001f77, 0x00000723, 0x00001f78, 0x00000725, 0x00001f79, 0x00000727, 0x00001f7a, 0x00000729, 0x00001f7b, 0x0000072b, 0x00001f7c, 0x0000072d, 0x00001f7d, 0x0000072f, 0x00001f80, 0x00000731, 0x00001f81, 0x00000734, 0x00001f82, 0x00000737, 0x00001f83, 0x0000073b, 0x00001f84, 0x0000073f, 0x00001f85, 0x00000743, 0x00001f86, 0x00000747, 0x00001f87, 0x0000074b, 0x00001f88, 0x0000074f, 0x00001f89, 0x00000752, 0x00001f8a, 0x00000755, 0x00001f8b, 0x00000759, 0x00001f8c, 0x0000075d, 0x00001f8d, 0x00000761, 0x00001f8e, 0x00000765, 0x00001f8f, 0x00000769, 0x00001f90, 0x0000076d, 0x00001f91, 0x00000770, 0x00001f92, 0x00000773, 0x00001f93, 0x00000777, 0x00001f94, 0x0000077b, 0x00001f95, 0x0000077f, 0x00001f96, 0x00000783, 0x00001f97, 0x00000787, 0x00001f98, 0x0000078b, 0x00001f99, 0x0000078e, 0x00001f9a, 0x00000791, 0x00001f9b, 0x00000795, 0x00001f9c, 0x00000799, 0x00001f9d, 0x0000079d, 0x00001f9e, 0x000007a1, 0x00001f9f, 0x000007a5, 0x00001fa0, 0x000007a9, 0x00001fa1, 0x000007ac, 0x00001fa2, 0x000007af, 0x00001fa3, 0x000007b3, 0x00001fa4, 0x000007b7, 0x00001fa5, 0x000007bb, 0x00001fa6, 0x000007bf, 0x00001fa7, 0x000007c3, 0x00001fa8, 0x000007c7, 0x00001fa9, 0x000007ca, 0x00001faa, 0x000007cd, 0x00001fab, 0x000007d1, 0x00001fac, 0x000007d5, 0x00001fad, 0x000007d9, 0x00001fae, 0x000007dd, 0x00001faf, 0x000007e1, 0x00001fb0, 0x000007e5, 0x00001fb1, 0x000007e7, 0x00001fb2, 0x000007e9, 0x00001fb3, 0x000007ec, 0x00001fb4, 0x000007ee, 0x00001fb6, 0x000007f1, 0x00001fb7, 0x000007f3, 0x00001fb8, 0x000007f6, 0x00001fb9, 0x000007f8, 0x00001fba, 0x000007fa, 0x00001fbb, 0x000007fc, 0x00001fbc, 0x000007fe, 0x00001fbd, 0x00000800, 0x00001fbe, 0x00000802, 0x00001fbf, 0x00000803, 0x00001fc0, 0x00000805, 0x00001fc1, 0x00000807, 0x00001fc2, 0x0000080a, 0x00001fc3, 0x0000080d, 0x00001fc4, 0x0000080f, 0x00001fc6, 0x00000812, 0x00001fc7, 0x00000814, 0x00001fc8, 0x00000817, 0x00001fc9, 0x00000819, 0x00001fca, 0x0000081b, 0x00001fcb, 0x0000081d, 0x00001fcc, 0x0000081f, 0x00001fcd, 0x00000821, 0x00001fce, 0x00000824, 0x00001fcf, 0x00000827, 0x00001fd0, 0x0000082a, 0x00001fd1, 0x0000082c, 0x00001fd2, 0x0000082e, 0x00001fd3, 0x00000831, 0x00001fd6, 0x00000834, 0x00001fd7, 0x00000836, 0x00001fd8, 0x00000839, 0x00001fd9, 0x0000083b, 0x00001fda, 0x0000083d, 0x00001fdb, 0x0000083f, 0x00001fdd, 0x00000841, 0x00001fde, 0x00000844, 0x00001fdf, 0x00000847, 0x00001fe0, 0x0000084a, 0x00001fe1, 0x0000084c, 0x00001fe2, 0x0000084e, 0x00001fe3, 0x00000851, 0x00001fe4, 0x00000854, 0x00001fe5, 0x00000856, 0x00001fe6, 0x00000858, 0x00001fe7, 0x0000085a, 0x00001fe8, 0x0000085d, 0x00001fe9, 0x0000085f, 0x00001fea, 0x00000861, 0x00001feb, 0x00000863, 0x00001fec, 0x00000865, 0x00001fed, 0x00000867, 0x00001fee, 0x0000086a, 0x00001fef, 0x0000086d, 0x00001ff2, 0x0000086e, 0x00001ff3, 0x00000871, 0x00001ff4, 0x00000873, 0x00001ff6, 0x00000876, 0x00001ff7, 0x00000878, 0x00001ff8, 0x0000087b, 0x00001ff9, 0x0000087d, 0x00001ffa, 0x0000087f, 0x00001ffb, 0x00000881, 0x00001ffc, 0x00000883, 0x00001ffd, 0x00000885, 0x00001ffe, 0x00000887, 0x00002000, 0x00000889, 0x00002001, 0x0000088a, 0x00002002, 0x0000088b, 0x00002003, 0x0000088c, 0x00002004, 0x0000088d, 0x00002005, 0x0000088e, 0x00002006, 0x0000088f, 0x00002007, 0x00000890, 0x00002008, 0x00000891, 0x00002009, 0x00000892, 0x0000200a, 0x00000893, 0x00002011, 0x00000894, 0x00002017, 0x00000895, 0x00002024, 0x00000897, 0x00002025, 0x00000898, 0x00002026, 0x0000089a, 0x0000202f, 0x0000089d, 0x00002033, 0x0000089e, 0x00002034, 0x000008a0, 0x00002036, 0x000008a3, 0x00002037, 0x000008a5, 0x0000203c, 0x000008a8, 0x0000203e, 0x000008aa, 0x00002047, 0x000008ac, 0x00002048, 0x000008ae, 0x00002049, 0x000008b0, 0x00002057, 0x000008b2, 0x0000205f, 0x000008b6, 0x00002070, 0x000008b7, 0x00002071, 0x000008b8, 0x00002074, 0x000008b9, 0x00002075, 0x000008ba, 0x00002076, 0x000008bb, 0x00002077, 0x000008bc, 0x00002078, 0x000008bd, 0x00002079, 0x000008be, 0x0000207a, 0x000008bf, 0x0000207b, 0x000008c0, 0x0000207c, 0x000008c1, 0x0000207d, 0x000008c2, 0x0000207e, 0x000008c3, 0x0000207f, 0x000008c4, 0x00002080, 0x000008c5, 0x00002081, 0x000008c6, 0x00002082, 0x000008c7, 0x00002083, 0x000008c8, 0x00002084, 0x000008c9, 0x00002085, 0x000008ca, 0x00002086, 0x000008cb, 0x00002087, 0x000008cc, 0x00002088, 0x000008cd, 0x00002089, 0x000008ce, 0x0000208a, 0x000008cf, 0x0000208b, 0x000008d0, 0x0000208c, 0x000008d1, 0x0000208d, 0x000008d2, 0x0000208e, 0x000008d3, 0x000020a8, 0x000008d4, 0x00002100, 0x000008d6, 0x00002101, 0x000008d9, 0x00002102, 0x000008dc, 0x00002103, 0x000008dd, 0x00002105, 0x000008df, 0x00002106, 0x000008e2, 0x00002107, 0x000008e5, 0x00002109, 0x000008e6, 0x0000210a, 0x000008e8, 0x0000210b, 0x000008e9, 0x0000210c, 0x000008ea, 0x0000210d, 0x000008eb, 0x0000210e, 0x000008ec, 0x0000210f, 0x000008ed, 0x00002110, 0x000008ee, 0x00002111, 0x000008ef, 0x00002112, 0x000008f0, 0x00002113, 0x000008f1, 0x00002115, 0x000008f2, 0x00002116, 0x000008f3, 0x00002119, 0x000008f5, 0x0000211a, 0x000008f6, 0x0000211b, 0x000008f7, 0x0000211c, 0x000008f8, 0x0000211d, 0x000008f9, 0x00002120, 0x000008fa, 0x00002121, 0x000008fc, 0x00002122, 0x000008ff, 0x00002124, 0x00000901, 0x00002126, 0x00000902, 0x00002128, 0x00000903, 0x0000212a, 0x00000904, 0x0000212b, 0x00000905, 0x0000212c, 0x00000907, 0x0000212d, 0x00000908, 0x0000212f, 0x00000909, 0x00002130, 0x0000090a, 0x00002131, 0x0000090b, 0x00002133, 0x0000090c, 0x00002134, 0x0000090d, 0x00002135, 0x0000090e, 0x00002136, 0x0000090f, 0x00002137, 0x00000910, 0x00002138, 0x00000911, 0x00002139, 0x00000912, 0x0000213d, 0x00000913, 0x0000213e, 0x00000914, 0x0000213f, 0x00000915, 0x00002140, 0x00000916, 0x00002145, 0x00000917, 0x00002146, 0x00000918, 0x00002147, 0x00000919, 0x00002148, 0x0000091a, 0x00002149, 0x0000091b, 0x00002153, 0x0000091c, 0x00002154, 0x0000091f, 0x00002155, 0x00000922, 0x00002156, 0x00000925, 0x00002157, 0x00000928, 0x00002158, 0x0000092b, 0x00002159, 0x0000092e, 0x0000215a, 0x00000931, 0x0000215b, 0x00000934, 0x0000215c, 0x00000937, 0x0000215d, 0x0000093a, 0x0000215e, 0x0000093d, 0x0000215f, 0x00000940, 0x00002160, 0x00000942, 0x00002161, 0x00000943, 0x00002162, 0x00000945, 0x00002163, 0x00000948, 0x00002164, 0x0000094a, 0x00002165, 0x0000094b, 0x00002166, 0x0000094d, 0x00002167, 0x00000950, 0x00002168, 0x00000954, 0x00002169, 0x00000956, 0x0000216a, 0x00000957, 0x0000216b, 0x00000959, 0x0000216c, 0x0000095c, 0x0000216d, 0x0000095d, 0x0000216e, 0x0000095e, 0x0000216f, 0x0000095f, 0x00002170, 0x00000960, 0x00002171, 0x00000961, 0x00002172, 0x00000963, 0x00002173, 0x00000966, 0x00002174, 0x00000968, 0x00002175, 0x00000969, 0x00002176, 0x0000096b, 0x00002177, 0x0000096e, 0x00002178, 0x00000972, 0x00002179, 0x00000974, 0x0000217a, 0x00000975, 0x0000217b, 0x00000977, 0x0000217c, 0x0000097a, 0x0000217d, 0x0000097b, 0x0000217e, 0x0000097c, 0x0000217f, 0x0000097d, 0x0000219a, 0x0000097e, 0x0000219b, 0x00000980, 0x000021ae, 0x00000982, 0x000021cd, 0x00000984, 0x000021ce, 0x00000986, 0x000021cf, 0x00000988, 0x00002204, 0x0000098a, 0x00002209, 0x0000098c, 0x0000220c, 0x0000098e, 0x00002224, 0x00000990, 0x00002226, 0x00000992, 0x0000222c, 0x00000994, 0x0000222d, 0x00000996, 0x0000222f, 0x00000999, 0x00002230, 0x0000099b, 0x00002241, 0x0000099e, 0x00002244, 0x000009a0, 0x00002247, 0x000009a2, 0x00002249, 0x000009a4, 0x00002260, 0x000009a6, 0x00002262, 0x000009a8, 0x0000226d, 0x000009aa, 0x0000226e, 0x000009ac, 0x0000226f, 0x000009ae, 0x00002270, 0x000009b0, 0x00002271, 0x000009b2, 0x00002274, 0x000009b4, 0x00002275, 0x000009b6, 0x00002278, 0x000009b8, 0x00002279, 0x000009ba, 0x00002280, 0x000009bc, 0x00002281, 0x000009be, 0x00002284, 0x000009c0, 0x00002285, 0x000009c2, 0x00002288, 0x000009c4, 0x00002289, 0x000009c6, 0x000022ac, 0x000009c8, 0x000022ad, 0x000009ca, 0x000022ae, 0x000009cc, 0x000022af, 0x000009ce, 0x000022e0, 0x000009d0, 0x000022e1, 0x000009d2, 0x000022e2, 0x000009d4, 0x000022e3, 0x000009d6, 0x000022ea, 0x000009d8, 0x000022eb, 0x000009da, 0x000022ec, 0x000009dc, 0x000022ed, 0x000009de, 0x00002329, 0x000009e0, 0x0000232a, 0x000009e1, 0x00002460, 0x000009e2, 0x00002461, 0x000009e3, 0x00002462, 0x000009e4, 0x00002463, 0x000009e5, 0x00002464, 0x000009e6, 0x00002465, 0x000009e7, 0x00002466, 0x000009e8, 0x00002467, 0x000009e9, 0x00002468, 0x000009ea, 0x00002469, 0x000009eb, 0x0000246a, 0x000009ed, 0x0000246b, 0x000009ef, 0x0000246c, 0x000009f1, 0x0000246d, 0x000009f3, 0x0000246e, 0x000009f5, 0x0000246f, 0x000009f7, 0x00002470, 0x000009f9, 0x00002471, 0x000009fb, 0x00002472, 0x000009fd, 0x00002473, 0x000009ff, 0x00002474, 0x00000a01, 0x00002475, 0x00000a04, 0x00002476, 0x00000a07, 0x00002477, 0x00000a0a, 0x00002478, 0x00000a0d, 0x00002479, 0x00000a10, 0x0000247a, 0x00000a13, 0x0000247b, 0x00000a16, 0x0000247c, 0x00000a19, 0x0000247d, 0x00000a1c, 0x0000247e, 0x00000a20, 0x0000247f, 0x00000a24, 0x00002480, 0x00000a28, 0x00002481, 0x00000a2c, 0x00002482, 0x00000a30, 0x00002483, 0x00000a34, 0x00002484, 0x00000a38, 0x00002485, 0x00000a3c, 0x00002486, 0x00000a40, 0x00002487, 0x00000a44, 0x00002488, 0x00000a48, 0x00002489, 0x00000a4a, 0x0000248a, 0x00000a4c, 0x0000248b, 0x00000a4e, 0x0000248c, 0x00000a50, 0x0000248d, 0x00000a52, 0x0000248e, 0x00000a54, 0x0000248f, 0x00000a56, 0x00002490, 0x00000a58, 0x00002491, 0x00000a5a, 0x00002492, 0x00000a5d, 0x00002493, 0x00000a60, 0x00002494, 0x00000a63, 0x00002495, 0x00000a66, 0x00002496, 0x00000a69, 0x00002497, 0x00000a6c, 0x00002498, 0x00000a6f, 0x00002499, 0x00000a72, 0x0000249a, 0x00000a75, 0x0000249b, 0x00000a78, 0x0000249c, 0x00000a7b, 0x0000249d, 0x00000a7e, 0x0000249e, 0x00000a81, 0x0000249f, 0x00000a84, 0x000024a0, 0x00000a87, 0x000024a1, 0x00000a8a, 0x000024a2, 0x00000a8d, 0x000024a3, 0x00000a90, 0x000024a4, 0x00000a93, 0x000024a5, 0x00000a96, 0x000024a6, 0x00000a99, 0x000024a7, 0x00000a9c, 0x000024a8, 0x00000a9f, 0x000024a9, 0x00000aa2, 0x000024aa, 0x00000aa5, 0x000024ab, 0x00000aa8, 0x000024ac, 0x00000aab, 0x000024ad, 0x00000aae, 0x000024ae, 0x00000ab1, 0x000024af, 0x00000ab4, 0x000024b0, 0x00000ab7, 0x000024b1, 0x00000aba, 0x000024b2, 0x00000abd, 0x000024b3, 0x00000ac0, 0x000024b4, 0x00000ac3, 0x000024b5, 0x00000ac6, 0x000024b6, 0x00000ac9, 0x000024b7, 0x00000aca, 0x000024b8, 0x00000acb, 0x000024b9, 0x00000acc, 0x000024ba, 0x00000acd, 0x000024bb, 0x00000ace, 0x000024bc, 0x00000acf, 0x000024bd, 0x00000ad0, 0x000024be, 0x00000ad1, 0x000024bf, 0x00000ad2, 0x000024c0, 0x00000ad3, 0x000024c1, 0x00000ad4, 0x000024c2, 0x00000ad5, 0x000024c3, 0x00000ad6, 0x000024c4, 0x00000ad7, 0x000024c5, 0x00000ad8, 0x000024c6, 0x00000ad9, 0x000024c7, 0x00000ada, 0x000024c8, 0x00000adb, 0x000024c9, 0x00000adc, 0x000024ca, 0x00000add, 0x000024cb, 0x00000ade, 0x000024cc, 0x00000adf, 0x000024cd, 0x00000ae0, 0x000024ce, 0x00000ae1, 0x000024cf, 0x00000ae2, 0x000024d0, 0x00000ae3, 0x000024d1, 0x00000ae4, 0x000024d2, 0x00000ae5, 0x000024d3, 0x00000ae6, 0x000024d4, 0x00000ae7, 0x000024d5, 0x00000ae8, 0x000024d6, 0x00000ae9, 0x000024d7, 0x00000aea, 0x000024d8, 0x00000aeb, 0x000024d9, 0x00000aec, 0x000024da, 0x00000aed, 0x000024db, 0x00000aee, 0x000024dc, 0x00000aef, 0x000024dd, 0x00000af0, 0x000024de, 0x00000af1, 0x000024df, 0x00000af2, 0x000024e0, 0x00000af3, 0x000024e1, 0x00000af4, 0x000024e2, 0x00000af5, 0x000024e3, 0x00000af6, 0x000024e4, 0x00000af7, 0x000024e5, 0x00000af8, 0x000024e6, 0x00000af9, 0x000024e7, 0x00000afa, 0x000024e8, 0x00000afb, 0x000024e9, 0x00000afc, 0x000024ea, 0x00000afd, 0x00002a0c, 0x00000afe, 0x00002a74, 0x00000b02, 0x00002a75, 0x00000b05, 0x00002a76, 0x00000b07, 0x00002adc, 0x00000b0a, 0x00002e9f, 0x00000b0c, 0x00002ef3, 0x00000b0d, 0x00002f00, 0x00000b0e, 0x00002f01, 0x00000b0f, 0x00002f02, 0x00000b10, 0x00002f03, 0x00000b11, 0x00002f04, 0x00000b12, 0x00002f05, 0x00000b13, 0x00002f06, 0x00000b14, 0x00002f07, 0x00000b15, 0x00002f08, 0x00000b16, 0x00002f09, 0x00000b17, 0x00002f0a, 0x00000b18, 0x00002f0b, 0x00000b19, 0x00002f0c, 0x00000b1a, 0x00002f0d, 0x00000b1b, 0x00002f0e, 0x00000b1c, 0x00002f0f, 0x00000b1d, 0x00002f10, 0x00000b1e, 0x00002f11, 0x00000b1f, 0x00002f12, 0x00000b20, 0x00002f13, 0x00000b21, 0x00002f14, 0x00000b22, 0x00002f15, 0x00000b23, 0x00002f16, 0x00000b24, 0x00002f17, 0x00000b25, 0x00002f18, 0x00000b26, 0x00002f19, 0x00000b27, 0x00002f1a, 0x00000b28, 0x00002f1b, 0x00000b29, 0x00002f1c, 0x00000b2a, 0x00002f1d, 0x00000b2b, 0x00002f1e, 0x00000b2c, 0x00002f1f, 0x00000b2d, 0x00002f20, 0x00000b2e, 0x00002f21, 0x00000b2f, 0x00002f22, 0x00000b30, 0x00002f23, 0x00000b31, 0x00002f24, 0x00000b32, 0x00002f25, 0x00000b33, 0x00002f26, 0x00000b34, 0x00002f27, 0x00000b35, 0x00002f28, 0x00000b36, 0x00002f29, 0x00000b37, 0x00002f2a, 0x00000b38, 0x00002f2b, 0x00000b39, 0x00002f2c, 0x00000b3a, 0x00002f2d, 0x00000b3b, 0x00002f2e, 0x00000b3c, 0x00002f2f, 0x00000b3d, 0x00002f30, 0x00000b3e, 0x00002f31, 0x00000b3f, 0x00002f32, 0x00000b40, 0x00002f33, 0x00000b41, 0x00002f34, 0x00000b42, 0x00002f35, 0x00000b43, 0x00002f36, 0x00000b44, 0x00002f37, 0x00000b45, 0x00002f38, 0x00000b46, 0x00002f39, 0x00000b47, 0x00002f3a, 0x00000b48, 0x00002f3b, 0x00000b49, 0x00002f3c, 0x00000b4a, 0x00002f3d, 0x00000b4b, 0x00002f3e, 0x00000b4c, 0x00002f3f, 0x00000b4d, 0x00002f40, 0x00000b4e, 0x00002f41, 0x00000b4f, 0x00002f42, 0x00000b50, 0x00002f43, 0x00000b51, 0x00002f44, 0x00000b52, 0x00002f45, 0x00000b53, 0x00002f46, 0x00000b54, 0x00002f47, 0x00000b55, 0x00002f48, 0x00000b56, 0x00002f49, 0x00000b57, 0x00002f4a, 0x00000b58, 0x00002f4b, 0x00000b59, 0x00002f4c, 0x00000b5a, 0x00002f4d, 0x00000b5b, 0x00002f4e, 0x00000b5c, 0x00002f4f, 0x00000b5d, 0x00002f50, 0x00000b5e, 0x00002f51, 0x00000b5f, 0x00002f52, 0x00000b60, 0x00002f53, 0x00000b61, 0x00002f54, 0x00000b62, 0x00002f55, 0x00000b63, 0x00002f56, 0x00000b64, 0x00002f57, 0x00000b65, 0x00002f58, 0x00000b66, 0x00002f59, 0x00000b67, 0x00002f5a, 0x00000b68, 0x00002f5b, 0x00000b69, 0x00002f5c, 0x00000b6a, 0x00002f5d, 0x00000b6b, 0x00002f5e, 0x00000b6c, 0x00002f5f, 0x00000b6d, 0x00002f60, 0x00000b6e, 0x00002f61, 0x00000b6f, 0x00002f62, 0x00000b70, 0x00002f63, 0x00000b71, 0x00002f64, 0x00000b72, 0x00002f65, 0x00000b73, 0x00002f66, 0x00000b74, 0x00002f67, 0x00000b75, 0x00002f68, 0x00000b76, 0x00002f69, 0x00000b77, 0x00002f6a, 0x00000b78, 0x00002f6b, 0x00000b79, 0x00002f6c, 0x00000b7a, 0x00002f6d, 0x00000b7b, 0x00002f6e, 0x00000b7c, 0x00002f6f, 0x00000b7d, 0x00002f70, 0x00000b7e, 0x00002f71, 0x00000b7f, 0x00002f72, 0x00000b80, 0x00002f73, 0x00000b81, 0x00002f74, 0x00000b82, 0x00002f75, 0x00000b83, 0x00002f76, 0x00000b84, 0x00002f77, 0x00000b85, 0x00002f78, 0x00000b86, 0x00002f79, 0x00000b87, 0x00002f7a, 0x00000b88, 0x00002f7b, 0x00000b89, 0x00002f7c, 0x00000b8a, 0x00002f7d, 0x00000b8b, 0x00002f7e, 0x00000b8c, 0x00002f7f, 0x00000b8d, 0x00002f80, 0x00000b8e, 0x00002f81, 0x00000b8f, 0x00002f82, 0x00000b90, 0x00002f83, 0x00000b91, 0x00002f84, 0x00000b92, 0x00002f85, 0x00000b93, 0x00002f86, 0x00000b94, 0x00002f87, 0x00000b95, 0x00002f88, 0x00000b96, 0x00002f89, 0x00000b97, 0x00002f8a, 0x00000b98, 0x00002f8b, 0x00000b99, 0x00002f8c, 0x00000b9a, 0x00002f8d, 0x00000b9b, 0x00002f8e, 0x00000b9c, 0x00002f8f, 0x00000b9d, 0x00002f90, 0x00000b9e, 0x00002f91, 0x00000b9f, 0x00002f92, 0x00000ba0, 0x00002f93, 0x00000ba1, 0x00002f94, 0x00000ba2, 0x00002f95, 0x00000ba3, 0x00002f96, 0x00000ba4, 0x00002f97, 0x00000ba5, 0x00002f98, 0x00000ba6, 0x00002f99, 0x00000ba7, 0x00002f9a, 0x00000ba8, 0x00002f9b, 0x00000ba9, 0x00002f9c, 0x00000baa, 0x00002f9d, 0x00000bab, 0x00002f9e, 0x00000bac, 0x00002f9f, 0x00000bad, 0x00002fa0, 0x00000bae, 0x00002fa1, 0x00000baf, 0x00002fa2, 0x00000bb0, 0x00002fa3, 0x00000bb1, 0x00002fa4, 0x00000bb2, 0x00002fa5, 0x00000bb3, 0x00002fa6, 0x00000bb4, 0x00002fa7, 0x00000bb5, 0x00002fa8, 0x00000bb6, 0x00002fa9, 0x00000bb7, 0x00002faa, 0x00000bb8, 0x00002fab, 0x00000bb9, 0x00002fac, 0x00000bba, 0x00002fad, 0x00000bbb, 0x00002fae, 0x00000bbc, 0x00002faf, 0x00000bbd, 0x00002fb0, 0x00000bbe, 0x00002fb1, 0x00000bbf, 0x00002fb2, 0x00000bc0, 0x00002fb3, 0x00000bc1, 0x00002fb4, 0x00000bc2, 0x00002fb5, 0x00000bc3, 0x00002fb6, 0x00000bc4, 0x00002fb7, 0x00000bc5, 0x00002fb8, 0x00000bc6, 0x00002fb9, 0x00000bc7, 0x00002fba, 0x00000bc8, 0x00002fbb, 0x00000bc9, 0x00002fbc, 0x00000bca, 0x00002fbd, 0x00000bcb, 0x00002fbe, 0x00000bcc, 0x00002fbf, 0x00000bcd, 0x00002fc0, 0x00000bce, 0x00002fc1, 0x00000bcf, 0x00002fc2, 0x00000bd0, 0x00002fc3, 0x00000bd1, 0x00002fc4, 0x00000bd2, 0x00002fc5, 0x00000bd3, 0x00002fc6, 0x00000bd4, 0x00002fc7, 0x00000bd5, 0x00002fc8, 0x00000bd6, 0x00002fc9, 0x00000bd7, 0x00002fca, 0x00000bd8, 0x00002fcb, 0x00000bd9, 0x00002fcc, 0x00000bda, 0x00002fcd, 0x00000bdb, 0x00002fce, 0x00000bdc, 0x00002fcf, 0x00000bdd, 0x00002fd0, 0x00000bde, 0x00002fd1, 0x00000bdf, 0x00002fd2, 0x00000be0, 0x00002fd3, 0x00000be1, 0x00002fd4, 0x00000be2, 0x00002fd5, 0x00000be3, 0x00003000, 0x00000be4, 0x00003036, 0x00000be5, 0x00003038, 0x00000be6, 0x00003039, 0x00000be7, 0x0000303a, 0x00000be8, 0x0000304c, 0x00000be9, 0x0000304e, 0x00000beb, 0x00003050, 0x00000bed, 0x00003052, 0x00000bef, 0x00003054, 0x00000bf1, 0x00003056, 0x00000bf3, 0x00003058, 0x00000bf5, 0x0000305a, 0x00000bf7, 0x0000305c, 0x00000bf9, 0x0000305e, 0x00000bfb, 0x00003060, 0x00000bfd, 0x00003062, 0x00000bff, 0x00003065, 0x00000c01, 0x00003067, 0x00000c03, 0x00003069, 0x00000c05, 0x00003070, 0x00000c07, 0x00003071, 0x00000c09, 0x00003073, 0x00000c0b, 0x00003074, 0x00000c0d, 0x00003076, 0x00000c0f, 0x00003077, 0x00000c11, 0x00003079, 0x00000c13, 0x0000307a, 0x00000c15, 0x0000307c, 0x00000c17, 0x0000307d, 0x00000c19, 0x00003094, 0x00000c1b, 0x0000309b, 0x00000c1d, 0x0000309c, 0x00000c1f, 0x0000309e, 0x00000c21, 0x0000309f, 0x00000c23, 0x000030ac, 0x00000c25, 0x000030ae, 0x00000c27, 0x000030b0, 0x00000c29, 0x000030b2, 0x00000c2b, 0x000030b4, 0x00000c2d, 0x000030b6, 0x00000c2f, 0x000030b8, 0x00000c31, 0x000030ba, 0x00000c33, 0x000030bc, 0x00000c35, 0x000030be, 0x00000c37, 0x000030c0, 0x00000c39, 0x000030c2, 0x00000c3b, 0x000030c5, 0x00000c3d, 0x000030c7, 0x00000c3f, 0x000030c9, 0x00000c41, 0x000030d0, 0x00000c43, 0x000030d1, 0x00000c45, 0x000030d3, 0x00000c47, 0x000030d4, 0x00000c49, 0x000030d6, 0x00000c4b, 0x000030d7, 0x00000c4d, 0x000030d9, 0x00000c4f, 0x000030da, 0x00000c51, 0x000030dc, 0x00000c53, 0x000030dd, 0x00000c55, 0x000030f4, 0x00000c57, 0x000030f7, 0x00000c59, 0x000030f8, 0x00000c5b, 0x000030f9, 0x00000c5d, 0x000030fa, 0x00000c5f, 0x000030fe, 0x00000c61, 0x000030ff, 0x00000c63, 0x00003131, 0x00000c65, 0x00003132, 0x00000c66, 0x00003133, 0x00000c67, 0x00003134, 0x00000c68, 0x00003135, 0x00000c69, 0x00003136, 0x00000c6a, 0x00003137, 0x00000c6b, 0x00003138, 0x00000c6c, 0x00003139, 0x00000c6d, 0x0000313a, 0x00000c6e, 0x0000313b, 0x00000c6f, 0x0000313c, 0x00000c70, 0x0000313d, 0x00000c71, 0x0000313e, 0x00000c72, 0x0000313f, 0x00000c73, 0x00003140, 0x00000c74, 0x00003141, 0x00000c75, 0x00003142, 0x00000c76, 0x00003143, 0x00000c77, 0x00003144, 0x00000c78, 0x00003145, 0x00000c79, 0x00003146, 0x00000c7a, 0x00003147, 0x00000c7b, 0x00003148, 0x00000c7c, 0x00003149, 0x00000c7d, 0x0000314a, 0x00000c7e, 0x0000314b, 0x00000c7f, 0x0000314c, 0x00000c80, 0x0000314d, 0x00000c81, 0x0000314e, 0x00000c82, 0x0000314f, 0x00000c83, 0x00003150, 0x00000c84, 0x00003151, 0x00000c85, 0x00003152, 0x00000c86, 0x00003153, 0x00000c87, 0x00003154, 0x00000c88, 0x00003155, 0x00000c89, 0x00003156, 0x00000c8a, 0x00003157, 0x00000c8b, 0x00003158, 0x00000c8c, 0x00003159, 0x00000c8d, 0x0000315a, 0x00000c8e, 0x0000315b, 0x00000c8f, 0x0000315c, 0x00000c90, 0x0000315d, 0x00000c91, 0x0000315e, 0x00000c92, 0x0000315f, 0x00000c93, 0x00003160, 0x00000c94, 0x00003161, 0x00000c95, 0x00003162, 0x00000c96, 0x00003163, 0x00000c97, 0x00003164, 0x00000c98, 0x00003165, 0x00000c99, 0x00003166, 0x00000c9a, 0x00003167, 0x00000c9b, 0x00003168, 0x00000c9c, 0x00003169, 0x00000c9d, 0x0000316a, 0x00000c9e, 0x0000316b, 0x00000c9f, 0x0000316c, 0x00000ca0, 0x0000316d, 0x00000ca1, 0x0000316e, 0x00000ca2, 0x0000316f, 0x00000ca3, 0x00003170, 0x00000ca4, 0x00003171, 0x00000ca5, 0x00003172, 0x00000ca6, 0x00003173, 0x00000ca7, 0x00003174, 0x00000ca8, 0x00003175, 0x00000ca9, 0x00003176, 0x00000caa, 0x00003177, 0x00000cab, 0x00003178, 0x00000cac, 0x00003179, 0x00000cad, 0x0000317a, 0x00000cae, 0x0000317b, 0x00000caf, 0x0000317c, 0x00000cb0, 0x0000317d, 0x00000cb1, 0x0000317e, 0x00000cb2, 0x0000317f, 0x00000cb3, 0x00003180, 0x00000cb4, 0x00003181, 0x00000cb5, 0x00003182, 0x00000cb6, 0x00003183, 0x00000cb7, 0x00003184, 0x00000cb8, 0x00003185, 0x00000cb9, 0x00003186, 0x00000cba, 0x00003187, 0x00000cbb, 0x00003188, 0x00000cbc, 0x00003189, 0x00000cbd, 0x0000318a, 0x00000cbe, 0x0000318b, 0x00000cbf, 0x0000318c, 0x00000cc0, 0x0000318d, 0x00000cc1, 0x0000318e, 0x00000cc2, 0x00003192, 0x00000cc3, 0x00003193, 0x00000cc4, 0x00003194, 0x00000cc5, 0x00003195, 0x00000cc6, 0x00003196, 0x00000cc7, 0x00003197, 0x00000cc8, 0x00003198, 0x00000cc9, 0x00003199, 0x00000cca, 0x0000319a, 0x00000ccb, 0x0000319b, 0x00000ccc, 0x0000319c, 0x00000ccd, 0x0000319d, 0x00000cce, 0x0000319e, 0x00000ccf, 0x0000319f, 0x00000cd0, 0x00003200, 0x00000cd1, 0x00003201, 0x00000cd4, 0x00003202, 0x00000cd7, 0x00003203, 0x00000cda, 0x00003204, 0x00000cdd, 0x00003205, 0x00000ce0, 0x00003206, 0x00000ce3, 0x00003207, 0x00000ce6, 0x00003208, 0x00000ce9, 0x00003209, 0x00000cec, 0x0000320a, 0x00000cef, 0x0000320b, 0x00000cf2, 0x0000320c, 0x00000cf5, 0x0000320d, 0x00000cf8, 0x0000320e, 0x00000cfb, 0x0000320f, 0x00000cff, 0x00003210, 0x00000d03, 0x00003211, 0x00000d07, 0x00003212, 0x00000d0b, 0x00003213, 0x00000d0f, 0x00003214, 0x00000d13, 0x00003215, 0x00000d17, 0x00003216, 0x00000d1b, 0x00003217, 0x00000d1f, 0x00003218, 0x00000d23, 0x00003219, 0x00000d27, 0x0000321a, 0x00000d2b, 0x0000321b, 0x00000d2f, 0x0000321c, 0x00000d33, 0x00003220, 0x00000d37, 0x00003221, 0x00000d3a, 0x00003222, 0x00000d3d, 0x00003223, 0x00000d40, 0x00003224, 0x00000d43, 0x00003225, 0x00000d46, 0x00003226, 0x00000d49, 0x00003227, 0x00000d4c, 0x00003228, 0x00000d4f, 0x00003229, 0x00000d52, 0x0000322a, 0x00000d55, 0x0000322b, 0x00000d58, 0x0000322c, 0x00000d5b, 0x0000322d, 0x00000d5e, 0x0000322e, 0x00000d61, 0x0000322f, 0x00000d64, 0x00003230, 0x00000d67, 0x00003231, 0x00000d6a, 0x00003232, 0x00000d6d, 0x00003233, 0x00000d70, 0x00003234, 0x00000d73, 0x00003235, 0x00000d76, 0x00003236, 0x00000d79, 0x00003237, 0x00000d7c, 0x00003238, 0x00000d7f, 0x00003239, 0x00000d82, 0x0000323a, 0x00000d85, 0x0000323b, 0x00000d88, 0x0000323c, 0x00000d8b, 0x0000323d, 0x00000d8e, 0x0000323e, 0x00000d91, 0x0000323f, 0x00000d94, 0x00003240, 0x00000d97, 0x00003241, 0x00000d9a, 0x00003242, 0x00000d9d, 0x00003243, 0x00000da0, 0x00003251, 0x00000da3, 0x00003252, 0x00000da5, 0x00003253, 0x00000da7, 0x00003254, 0x00000da9, 0x00003255, 0x00000dab, 0x00003256, 0x00000dad, 0x00003257, 0x00000daf, 0x00003258, 0x00000db1, 0x00003259, 0x00000db3, 0x0000325a, 0x00000db5, 0x0000325b, 0x00000db7, 0x0000325c, 0x00000db9, 0x0000325d, 0x00000dbb, 0x0000325e, 0x00000dbd, 0x0000325f, 0x00000dbf, 0x00003260, 0x00000dc1, 0x00003261, 0x00000dc2, 0x00003262, 0x00000dc3, 0x00003263, 0x00000dc4, 0x00003264, 0x00000dc5, 0x00003265, 0x00000dc6, 0x00003266, 0x00000dc7, 0x00003267, 0x00000dc8, 0x00003268, 0x00000dc9, 0x00003269, 0x00000dca, 0x0000326a, 0x00000dcb, 0x0000326b, 0x00000dcc, 0x0000326c, 0x00000dcd, 0x0000326d, 0x00000dce, 0x0000326e, 0x00000dcf, 0x0000326f, 0x00000dd1, 0x00003270, 0x00000dd3, 0x00003271, 0x00000dd5, 0x00003272, 0x00000dd7, 0x00003273, 0x00000dd9, 0x00003274, 0x00000ddb, 0x00003275, 0x00000ddd, 0x00003276, 0x00000ddf, 0x00003277, 0x00000de1, 0x00003278, 0x00000de3, 0x00003279, 0x00000de5, 0x0000327a, 0x00000de7, 0x0000327b, 0x00000de9, 0x00003280, 0x00000deb, 0x00003281, 0x00000dec, 0x00003282, 0x00000ded, 0x00003283, 0x00000dee, 0x00003284, 0x00000def, 0x00003285, 0x00000df0, 0x00003286, 0x00000df1, 0x00003287, 0x00000df2, 0x00003288, 0x00000df3, 0x00003289, 0x00000df4, 0x0000328a, 0x00000df5, 0x0000328b, 0x00000df6, 0x0000328c, 0x00000df7, 0x0000328d, 0x00000df8, 0x0000328e, 0x00000df9, 0x0000328f, 0x00000dfa, 0x00003290, 0x00000dfb, 0x00003291, 0x00000dfc, 0x00003292, 0x00000dfd, 0x00003293, 0x00000dfe, 0x00003294, 0x00000dff, 0x00003295, 0x00000e00, 0x00003296, 0x00000e01, 0x00003297, 0x00000e02, 0x00003298, 0x00000e03, 0x00003299, 0x00000e04, 0x0000329a, 0x00000e05, 0x0000329b, 0x00000e06, 0x0000329c, 0x00000e07, 0x0000329d, 0x00000e08, 0x0000329e, 0x00000e09, 0x0000329f, 0x00000e0a, 0x000032a0, 0x00000e0b, 0x000032a1, 0x00000e0c, 0x000032a2, 0x00000e0d, 0x000032a3, 0x00000e0e, 0x000032a4, 0x00000e0f, 0x000032a5, 0x00000e10, 0x000032a6, 0x00000e11, 0x000032a7, 0x00000e12, 0x000032a8, 0x00000e13, 0x000032a9, 0x00000e14, 0x000032aa, 0x00000e15, 0x000032ab, 0x00000e16, 0x000032ac, 0x00000e17, 0x000032ad, 0x00000e18, 0x000032ae, 0x00000e19, 0x000032af, 0x00000e1a, 0x000032b0, 0x00000e1b, 0x000032b1, 0x00000e1c, 0x000032b2, 0x00000e1e, 0x000032b3, 0x00000e20, 0x000032b4, 0x00000e22, 0x000032b5, 0x00000e24, 0x000032b6, 0x00000e26, 0x000032b7, 0x00000e28, 0x000032b8, 0x00000e2a, 0x000032b9, 0x00000e2c, 0x000032ba, 0x00000e2e, 0x000032bb, 0x00000e30, 0x000032bc, 0x00000e32, 0x000032bd, 0x00000e34, 0x000032be, 0x00000e36, 0x000032bf, 0x00000e38, 0x000032c0, 0x00000e3a, 0x000032c1, 0x00000e3c, 0x000032c2, 0x00000e3e, 0x000032c3, 0x00000e40, 0x000032c4, 0x00000e42, 0x000032c5, 0x00000e44, 0x000032c6, 0x00000e46, 0x000032c7, 0x00000e48, 0x000032c8, 0x00000e4a, 0x000032c9, 0x00000e4c, 0x000032ca, 0x00000e4f, 0x000032cb, 0x00000e52, 0x000032d0, 0x00000e55, 0x000032d1, 0x00000e56, 0x000032d2, 0x00000e57, 0x000032d3, 0x00000e58, 0x000032d4, 0x00000e59, 0x000032d5, 0x00000e5a, 0x000032d6, 0x00000e5b, 0x000032d7, 0x00000e5c, 0x000032d8, 0x00000e5d, 0x000032d9, 0x00000e5e, 0x000032da, 0x00000e5f, 0x000032db, 0x00000e60, 0x000032dc, 0x00000e61, 0x000032dd, 0x00000e62, 0x000032de, 0x00000e63, 0x000032df, 0x00000e64, 0x000032e0, 0x00000e65, 0x000032e1, 0x00000e66, 0x000032e2, 0x00000e67, 0x000032e3, 0x00000e68, 0x000032e4, 0x00000e69, 0x000032e5, 0x00000e6a, 0x000032e6, 0x00000e6b, 0x000032e7, 0x00000e6c, 0x000032e8, 0x00000e6d, 0x000032e9, 0x00000e6e, 0x000032ea, 0x00000e6f, 0x000032eb, 0x00000e70, 0x000032ec, 0x00000e71, 0x000032ed, 0x00000e72, 0x000032ee, 0x00000e73, 0x000032ef, 0x00000e74, 0x000032f0, 0x00000e75, 0x000032f1, 0x00000e76, 0x000032f2, 0x00000e77, 0x000032f3, 0x00000e78, 0x000032f4, 0x00000e79, 0x000032f5, 0x00000e7a, 0x000032f6, 0x00000e7b, 0x000032f7, 0x00000e7c, 0x000032f8, 0x00000e7d, 0x000032f9, 0x00000e7e, 0x000032fa, 0x00000e7f, 0x000032fb, 0x00000e80, 0x000032fc, 0x00000e81, 0x000032fd, 0x00000e82, 0x000032fe, 0x00000e83, 0x00003300, 0x00000e84, 0x00003301, 0x00000e89, 0x00003302, 0x00000e8d, 0x00003303, 0x00000e92, 0x00003304, 0x00000e95, 0x00003305, 0x00000e9a, 0x00003306, 0x00000e9d, 0x00003307, 0x00000ea0, 0x00003308, 0x00000ea6, 0x00003309, 0x00000eaa, 0x0000330a, 0x00000ead, 0x0000330b, 0x00000eb0, 0x0000330c, 0x00000eb3, 0x0000330d, 0x00000eb7, 0x0000330e, 0x00000ebb, 0x0000330f, 0x00000ebf, 0x00003310, 0x00000ec3, 0x00003311, 0x00000ec7, 0x00003312, 0x00000ecb, 0x00003313, 0x00000ecf, 0x00003314, 0x00000ed5, 0x00003315, 0x00000ed7, 0x00003316, 0x00000edd, 0x00003317, 0x00000ee3, 0x00003318, 0x00000ee8, 0x00003319, 0x00000eec, 0x0000331a, 0x00000ef2, 0x0000331b, 0x00000ef8, 0x0000331c, 0x00000efc, 0x0000331d, 0x00000eff, 0x0000331e, 0x00000f02, 0x0000331f, 0x00000f06, 0x00003320, 0x00000f0a, 0x00003321, 0x00000f0f, 0x00003322, 0x00000f14, 0x00003323, 0x00000f17, 0x00003324, 0x00000f1a, 0x00003325, 0x00000f1e, 0x00003326, 0x00000f21, 0x00003327, 0x00000f24, 0x00003328, 0x00000f26, 0x00003329, 0x00000f28, 0x0000332a, 0x00000f2b, 0x0000332b, 0x00000f2e, 0x0000332c, 0x00000f34, 0x0000332d, 0x00000f38, 0x0000332e, 0x00000f3d, 0x0000332f, 0x00000f43, 0x00003330, 0x00000f47, 0x00003331, 0x00000f4a, 0x00003332, 0x00000f4d, 0x00003333, 0x00000f53, 0x00003334, 0x00000f57, 0x00003335, 0x00000f5d, 0x00003336, 0x00000f60, 0x00003337, 0x00000f65, 0x00003338, 0x00000f68, 0x00003339, 0x00000f6c, 0x0000333a, 0x00000f6f, 0x0000333b, 0x00000f73, 0x0000333c, 0x00000f78, 0x0000333d, 0x00000f7c, 0x0000333e, 0x00000f81, 0x0000333f, 0x00000f85, 0x00003340, 0x00000f87, 0x00003341, 0x00000f8c, 0x00003342, 0x00000f8f, 0x00003343, 0x00000f92, 0x00003344, 0x00000f96, 0x00003345, 0x00000f99, 0x00003346, 0x00000f9c, 0x00003347, 0x00000f9f, 0x00003348, 0x00000fa4, 0x00003349, 0x00000fa8, 0x0000334a, 0x00000faa, 0x0000334b, 0x00000fb0, 0x0000334c, 0x00000fb3, 0x0000334d, 0x00000fb8, 0x0000334e, 0x00000fbc, 0x0000334f, 0x00000fc0, 0x00003350, 0x00000fc3, 0x00003351, 0x00000fc6, 0x00003352, 0x00000fca, 0x00003353, 0x00000fcc, 0x00003354, 0x00000fd0, 0x00003355, 0x00000fd5, 0x00003356, 0x00000fd7, 0x00003357, 0x00000fdd, 0x00003358, 0x00000fe0, 0x00003359, 0x00000fe2, 0x0000335a, 0x00000fe4, 0x0000335b, 0x00000fe6, 0x0000335c, 0x00000fe8, 0x0000335d, 0x00000fea, 0x0000335e, 0x00000fec, 0x0000335f, 0x00000fee, 0x00003360, 0x00000ff0, 0x00003361, 0x00000ff2, 0x00003362, 0x00000ff4, 0x00003363, 0x00000ff7, 0x00003364, 0x00000ffa, 0x00003365, 0x00000ffd, 0x00003366, 0x00001000, 0x00003367, 0x00001003, 0x00003368, 0x00001006, 0x00003369, 0x00001009, 0x0000336a, 0x0000100c, 0x0000336b, 0x0000100f, 0x0000336c, 0x00001012, 0x0000336d, 0x00001015, 0x0000336e, 0x00001018, 0x0000336f, 0x0000101b, 0x00003370, 0x0000101e, 0x00003371, 0x00001021, 0x00003372, 0x00001024, 0x00003373, 0x00001026, 0x00003374, 0x00001028, 0x00003375, 0x0000102b, 0x00003376, 0x0000102d, 0x0000337b, 0x0000102f, 0x0000337c, 0x00001031, 0x0000337d, 0x00001033, 0x0000337e, 0x00001035, 0x0000337f, 0x00001037, 0x00003380, 0x0000103b, 0x00003381, 0x0000103d, 0x00003382, 0x0000103f, 0x00003383, 0x00001041, 0x00003384, 0x00001043, 0x00003385, 0x00001045, 0x00003386, 0x00001047, 0x00003387, 0x00001049, 0x00003388, 0x0000104b, 0x00003389, 0x0000104e, 0x0000338a, 0x00001052, 0x0000338b, 0x00001054, 0x0000338c, 0x00001056, 0x0000338d, 0x00001058, 0x0000338e, 0x0000105a, 0x0000338f, 0x0000105c, 0x00003390, 0x0000105e, 0x00003391, 0x00001060, 0x00003392, 0x00001063, 0x00003393, 0x00001066, 0x00003394, 0x00001069, 0x00003395, 0x0000106c, 0x00003396, 0x0000106e, 0x00003397, 0x00001070, 0x00003398, 0x00001072, 0x00003399, 0x00001074, 0x0000339a, 0x00001076, 0x0000339b, 0x00001078, 0x0000339c, 0x0000107a, 0x0000339d, 0x0000107c, 0x0000339e, 0x0000107e, 0x0000339f, 0x00001080, 0x000033a0, 0x00001083, 0x000033a1, 0x00001086, 0x000033a2, 0x00001088, 0x000033a3, 0x0000108b, 0x000033a4, 0x0000108e, 0x000033a5, 0x00001091, 0x000033a6, 0x00001093, 0x000033a7, 0x00001096, 0x000033a8, 0x00001099, 0x000033a9, 0x0000109d, 0x000033aa, 0x0000109f, 0x000033ab, 0x000010a2, 0x000033ac, 0x000010a5, 0x000033ad, 0x000010a8, 0x000033ae, 0x000010ab, 0x000033af, 0x000010b0, 0x000033b0, 0x000010b6, 0x000033b1, 0x000010b8, 0x000033b2, 0x000010ba, 0x000033b3, 0x000010bc, 0x000033b4, 0x000010be, 0x000033b5, 0x000010c0, 0x000033b6, 0x000010c2, 0x000033b7, 0x000010c4, 0x000033b8, 0x000010c6, 0x000033b9, 0x000010c8, 0x000033ba, 0x000010ca, 0x000033bb, 0x000010cc, 0x000033bc, 0x000010ce, 0x000033bd, 0x000010d0, 0x000033be, 0x000010d2, 0x000033bf, 0x000010d4, 0x000033c0, 0x000010d6, 0x000033c1, 0x000010d8, 0x000033c2, 0x000010da, 0x000033c3, 0x000010de, 0x000033c4, 0x000010e0, 0x000033c5, 0x000010e2, 0x000033c6, 0x000010e4, 0x000033c7, 0x000010e8, 0x000033c8, 0x000010eb, 0x000033c9, 0x000010ed, 0x000033ca, 0x000010ef, 0x000033cb, 0x000010f1, 0x000033cc, 0x000010f3, 0x000033cd, 0x000010f5, 0x000033ce, 0x000010f7, 0x000033cf, 0x000010f9, 0x000033d0, 0x000010fb, 0x000033d1, 0x000010fd, 0x000033d2, 0x000010ff, 0x000033d3, 0x00001102, 0x000033d4, 0x00001104, 0x000033d5, 0x00001106, 0x000033d6, 0x00001109, 0x000033d7, 0x0000110c, 0x000033d8, 0x0000110e, 0x000033d9, 0x00001112, 0x000033da, 0x00001115, 0x000033db, 0x00001117, 0x000033dc, 0x00001119, 0x000033dd, 0x0000111b, 0x000033e0, 0x0000111d, 0x000033e1, 0x0000111f, 0x000033e2, 0x00001121, 0x000033e3, 0x00001123, 0x000033e4, 0x00001125, 0x000033e5, 0x00001127, 0x000033e6, 0x00001129, 0x000033e7, 0x0000112b, 0x000033e8, 0x0000112d, 0x000033e9, 0x0000112f, 0x000033ea, 0x00001132, 0x000033eb, 0x00001135, 0x000033ec, 0x00001138, 0x000033ed, 0x0000113b, 0x000033ee, 0x0000113e, 0x000033ef, 0x00001141, 0x000033f0, 0x00001144, 0x000033f1, 0x00001147, 0x000033f2, 0x0000114a, 0x000033f3, 0x0000114d, 0x000033f4, 0x00001150, 0x000033f5, 0x00001153, 0x000033f6, 0x00001156, 0x000033f7, 0x00001159, 0x000033f8, 0x0000115c, 0x000033f9, 0x0000115f, 0x000033fa, 0x00001162, 0x000033fb, 0x00001165, 0x000033fc, 0x00001168, 0x000033fd, 0x0000116b, 0x000033fe, 0x0000116e, 0x0000f902, 0x00001171, 0x0000f903, 0x00001172, 0x0000f904, 0x00001173, 0x0000f905, 0x00001174, 0x0000f906, 0x00001175, 0x0000f907, 0x00001176, 0x0000f908, 0x00001177, 0x0000f909, 0x00001178, 0x0000f90a, 0x00001179, 0x0000f90b, 0x0000117a, 0x0000f90c, 0x0000117b, 0x0000f90d, 0x0000117c, 0x0000f90e, 0x0000117d, 0x0000f90f, 0x0000117e, 0x0000f910, 0x0000117f, 0x0000f911, 0x00001180, 0x0000f912, 0x00001181, 0x0000f913, 0x00001182, 0x0000f914, 0x00001183, 0x0000f915, 0x00001184, 0x0000f916, 0x00001185, 0x0000f917, 0x00001186, 0x0000f918, 0x00001187, 0x0000f919, 0x00001188, 0x0000f91a, 0x00001189, 0x0000f91b, 0x0000118a, 0x0000f91c, 0x0000118b, 0x0000f91d, 0x0000118c, 0x0000f91e, 0x0000118d, 0x0000f91f, 0x0000118e, 0x0000f920, 0x0000118f, 0x0000f921, 0x00001190, 0x0000f922, 0x00001191, 0x0000f923, 0x00001192, 0x0000f924, 0x00001193, 0x0000f925, 0x00001194, 0x0000f926, 0x00001195, 0x0000f927, 0x00001196, 0x0000f928, 0x00001197, 0x0000f929, 0x00001198, 0x0000f92a, 0x00001199, 0x0000f92b, 0x0000119a, 0x0000f92c, 0x0000119b, 0x0000f92d, 0x0000119c, 0x0000f92e, 0x0000119d, 0x0000f92f, 0x0000119e, 0x0000f930, 0x0000119f, 0x0000f931, 0x000011a0, 0x0000f932, 0x000011a1, 0x0000f933, 0x000011a2, 0x0000f934, 0x000011a3, 0x0000f935, 0x000011a4, 0x0000f936, 0x000011a5, 0x0000f937, 0x000011a6, 0x0000f938, 0x000011a7, 0x0000f939, 0x000011a8, 0x0000f93a, 0x000011a9, 0x0000f93b, 0x000011aa, 0x0000f93c, 0x000011ab, 0x0000f93d, 0x000011ac, 0x0000f93e, 0x000011ad, 0x0000f93f, 0x000011ae, 0x0000f940, 0x000011af, 0x0000f941, 0x000011b0, 0x0000f942, 0x000011b1, 0x0000f943, 0x000011b2, 0x0000f944, 0x000011b3, 0x0000f945, 0x000011b4, 0x0000f946, 0x000011b5, 0x0000f947, 0x000011b6, 0x0000f948, 0x000011b7, 0x0000f949, 0x000011b8, 0x0000f94a, 0x000011b9, 0x0000f94b, 0x000011ba, 0x0000f94c, 0x000011bb, 0x0000f94d, 0x000011bc, 0x0000f94e, 0x000011bd, 0x0000f94f, 0x000011be, 0x0000f950, 0x000011bf, 0x0000f951, 0x000011c0, 0x0000f952, 0x000011c1, 0x0000f953, 0x000011c2, 0x0000f954, 0x000011c3, 0x0000f955, 0x000011c4, 0x0000f956, 0x000011c5, 0x0000f957, 0x000011c6, 0x0000f958, 0x000011c7, 0x0000f959, 0x000011c8, 0x0000f95a, 0x000011c9, 0x0000f95b, 0x000011ca, 0x0000f95c, 0x000011cb, 0x0000f95d, 0x000011cc, 0x0000f95e, 0x000011cd, 0x0000f95f, 0x000011ce, 0x0000f960, 0x000011cf, 0x0000f961, 0x000011d0, 0x0000f962, 0x000011d1, 0x0000f963, 0x000011d2, 0x0000f964, 0x000011d3, 0x0000f965, 0x000011d4, 0x0000f966, 0x000011d5, 0x0000f967, 0x000011d6, 0x0000f968, 0x000011d7, 0x0000f969, 0x000011d8, 0x0000f96a, 0x000011d9, 0x0000f96b, 0x000011da, 0x0000f96c, 0x000011db, 0x0000f96d, 0x000011dc, 0x0000f96e, 0x000011dd, 0x0000f96f, 0x000011de, 0x0000f970, 0x000011df, 0x0000f971, 0x000011e0, 0x0000f972, 0x000011e1, 0x0000f973, 0x000011e2, 0x0000f974, 0x000011e3, 0x0000f975, 0x000011e4, 0x0000f976, 0x000011e5, 0x0000f977, 0x000011e6, 0x0000f978, 0x000011e7, 0x0000f979, 0x000011e8, 0x0000f97a, 0x000011e9, 0x0000f97b, 0x000011ea, 0x0000f97c, 0x000011eb, 0x0000f97d, 0x000011ec, 0x0000f97e, 0x000011ed, 0x0000f97f, 0x000011ee, 0x0000f980, 0x000011ef, 0x0000f981, 0x000011f0, 0x0000f982, 0x000011f1, 0x0000f983, 0x000011f2, 0x0000f984, 0x000011f3, 0x0000f985, 0x000011f4, 0x0000f986, 0x000011f5, 0x0000f987, 0x000011f6, 0x0000f988, 0x000011f7, 0x0000f989, 0x000011f8, 0x0000f98a, 0x000011f9, 0x0000f98b, 0x000011fa, 0x0000f98c, 0x000011fb, 0x0000f98d, 0x000011fc, 0x0000f98e, 0x000011fd, 0x0000f98f, 0x000011fe, 0x0000f990, 0x000011ff, 0x0000f991, 0x00001200, 0x0000f992, 0x00001201, 0x0000f993, 0x00001202, 0x0000f994, 0x00001203, 0x0000f995, 0x00001204, 0x0000f996, 0x00001205, 0x0000f997, 0x00001206, 0x0000f998, 0x00001207, 0x0000f999, 0x00001208, 0x0000f99a, 0x00001209, 0x0000f99b, 0x0000120a, 0x0000f99c, 0x0000120b, 0x0000f99d, 0x0000120c, 0x0000f99e, 0x0000120d, 0x0000f99f, 0x0000120e, 0x0000f9a0, 0x0000120f, 0x0000f9a1, 0x00001210, 0x0000f9a2, 0x00001211, 0x0000f9a3, 0x00001212, 0x0000f9a4, 0x00001213, 0x0000f9a5, 0x00001214, 0x0000f9a6, 0x00001215, 0x0000f9a7, 0x00001216, 0x0000f9a8, 0x00001217, 0x0000f9a9, 0x00001218, 0x0000f9aa, 0x00001219, 0x0000f9ab, 0x0000121a, 0x0000f9ac, 0x0000121b, 0x0000f9ad, 0x0000121c, 0x0000f9ae, 0x0000121d, 0x0000f9af, 0x0000121e, 0x0000f9b0, 0x0000121f, 0x0000f9b1, 0x00001220, 0x0000f9b2, 0x00001221, 0x0000f9b3, 0x00001222, 0x0000f9b4, 0x00001223, 0x0000f9b5, 0x00001224, 0x0000f9b6, 0x00001225, 0x0000f9b7, 0x00001226, 0x0000f9b8, 0x00001227, 0x0000f9b9, 0x00001228, 0x0000f9ba, 0x00001229, 0x0000f9bb, 0x0000122a, 0x0000f9bc, 0x0000122b, 0x0000f9bd, 0x0000122c, 0x0000f9be, 0x0000122d, 0x0000f9bf, 0x0000122e, 0x0000f9c0, 0x0000122f, 0x0000f9c1, 0x00001230, 0x0000f9c2, 0x00001231, 0x0000f9c3, 0x00001232, 0x0000f9c4, 0x00001233, 0x0000f9c5, 0x00001234, 0x0000f9c6, 0x00001235, 0x0000f9c7, 0x00001236, 0x0000f9c8, 0x00001237, 0x0000f9c9, 0x00001238, 0x0000f9ca, 0x00001239, 0x0000f9cb, 0x0000123a, 0x0000f9cc, 0x0000123b, 0x0000f9cd, 0x0000123c, 0x0000f9ce, 0x0000123d, 0x0000f9cf, 0x0000123e, 0x0000f9d0, 0x0000123f, 0x0000f9d1, 0x00001240, 0x0000f9d2, 0x00001241, 0x0000f9d3, 0x00001242, 0x0000f9d4, 0x00001243, 0x0000f9d5, 0x00001244, 0x0000f9d6, 0x00001245, 0x0000f9d7, 0x00001246, 0x0000f9d8, 0x00001247, 0x0000f9d9, 0x00001248, 0x0000f9da, 0x00001249, 0x0000f9db, 0x0000124a, 0x0000f9dc, 0x0000124b, 0x0000f9dd, 0x0000124c, 0x0000f9de, 0x0000124d, 0x0000f9df, 0x0000124e, 0x0000f9e0, 0x0000124f, 0x0000f9e1, 0x00001250, 0x0000f9e2, 0x00001251, 0x0000f9e3, 0x00001252, 0x0000f9e4, 0x00001253, 0x0000f9e5, 0x00001254, 0x0000f9e6, 0x00001255, 0x0000f9e7, 0x00001256, 0x0000f9e8, 0x00001257, 0x0000f9e9, 0x00001258, 0x0000f9ea, 0x00001259, 0x0000f9eb, 0x0000125a, 0x0000f9ec, 0x0000125b, 0x0000f9ed, 0x0000125c, 0x0000f9ee, 0x0000125d, 0x0000f9ef, 0x0000125e, 0x0000f9f0, 0x0000125f, 0x0000f9f1, 0x00001260, 0x0000f9f2, 0x00001261, 0x0000f9f3, 0x00001262, 0x0000f9f4, 0x00001263, 0x0000f9f5, 0x00001264, 0x0000f9f6, 0x00001265, 0x0000f9f7, 0x00001266, 0x0000f9f8, 0x00001267, 0x0000f9f9, 0x00001268, 0x0000f9fa, 0x00001269, 0x0000f9fb, 0x0000126a, 0x0000f9fc, 0x0000126b, 0x0000f9fd, 0x0000126c, 0x0000f9fe, 0x0000126d, 0x0000f9ff, 0x0000126e, 0x0000fa00, 0x0000126f, 0x0000fa01, 0x00001270, 0x0000fa02, 0x00001271, 0x0000fa03, 0x00001272, 0x0000fa04, 0x00001273, 0x0000fa05, 0x00001274, 0x0000fa06, 0x00001275, 0x0000fa07, 0x00001276, 0x0000fa08, 0x00001277, 0x0000fa09, 0x00001278, 0x0000fa0a, 0x00001279, 0x0000fa0b, 0x0000127a, 0x0000fa0c, 0x0000127b, 0x0000fa0d, 0x0000127c, 0x0000fa10, 0x0000127d, 0x0000fa12, 0x0000127e, 0x0000fa15, 0x0000127f, 0x0000fa16, 0x00001280, 0x0000fa17, 0x00001281, 0x0000fa18, 0x00001282, 0x0000fa19, 0x00001283, 0x0000fa1a, 0x00001284, 0x0000fa1b, 0x00001285, 0x0000fa1c, 0x00001286, 0x0000fa1d, 0x00001287, 0x0000fa1e, 0x00001288, 0x0000fa20, 0x00001289, 0x0000fa22, 0x0000128a, 0x0000fa25, 0x0000128b, 0x0000fa26, 0x0000128c, 0x0000fa2a, 0x0000128d, 0x0000fa2b, 0x0000128e, 0x0000fa2c, 0x0000128f, 0x0000fa2d, 0x00001290, 0x0000fa30, 0x00001291, 0x0000fa31, 0x00001292, 0x0000fa32, 0x00001293, 0x0000fa33, 0x00001294, 0x0000fa34, 0x00001295, 0x0000fa35, 0x00001296, 0x0000fa36, 0x00001297, 0x0000fa37, 0x00001298, 0x0000fa38, 0x00001299, 0x0000fa39, 0x0000129a, 0x0000fa3a, 0x0000129b, 0x0000fa3b, 0x0000129c, 0x0000fa3c, 0x0000129d, 0x0000fa3d, 0x0000129e, 0x0000fa3e, 0x0000129f, 0x0000fa3f, 0x000012a0, 0x0000fa40, 0x000012a1, 0x0000fa41, 0x000012a2, 0x0000fa42, 0x000012a3, 0x0000fa43, 0x000012a4, 0x0000fa44, 0x000012a5, 0x0000fa45, 0x000012a6, 0x0000fa46, 0x000012a7, 0x0000fa47, 0x000012a8, 0x0000fa48, 0x000012a9, 0x0000fa49, 0x000012aa, 0x0000fa4a, 0x000012ab, 0x0000fa4b, 0x000012ac, 0x0000fa4c, 0x000012ad, 0x0000fa4d, 0x000012ae, 0x0000fa4e, 0x000012af, 0x0000fa4f, 0x000012b0, 0x0000fa50, 0x000012b1, 0x0000fa51, 0x000012b2, 0x0000fa52, 0x000012b3, 0x0000fa53, 0x000012b4, 0x0000fa54, 0x000012b5, 0x0000fa55, 0x000012b6, 0x0000fa56, 0x000012b7, 0x0000fa57, 0x000012b8, 0x0000fa58, 0x000012b9, 0x0000fa59, 0x000012ba, 0x0000fa5a, 0x000012bb, 0x0000fa5b, 0x000012bc, 0x0000fa5c, 0x000012bd, 0x0000fa5d, 0x000012be, 0x0000fa5e, 0x000012bf, 0x0000fa5f, 0x000012c0, 0x0000fa60, 0x000012c1, 0x0000fa61, 0x000012c2, 0x0000fa62, 0x000012c3, 0x0000fa63, 0x000012c4, 0x0000fa64, 0x000012c5, 0x0000fa65, 0x000012c6, 0x0000fa66, 0x000012c7, 0x0000fa67, 0x000012c8, 0x0000fa68, 0x000012c9, 0x0000fa69, 0x000012ca, 0x0000fa6a, 0x000012cb, 0x0000fb00, 0x000012cc, 0x0000fb01, 0x000012ce, 0x0000fb02, 0x000012d0, 0x0000fb03, 0x000012d2, 0x0000fb04, 0x000012d5, 0x0000fb05, 0x000012d8, 0x0000fb06, 0x000012da, 0x0000fb13, 0x000012dc, 0x0000fb14, 0x000012de, 0x0000fb15, 0x000012e0, 0x0000fb16, 0x000012e2, 0x0000fb17, 0x000012e4, 0x0000fb1d, 0x000012e6, 0x0000fb1f, 0x000012e8, 0x0000fb20, 0x000012ea, 0x0000fb21, 0x000012eb, 0x0000fb22, 0x000012ec, 0x0000fb23, 0x000012ed, 0x0000fb24, 0x000012ee, 0x0000fb25, 0x000012ef, 0x0000fb26, 0x000012f0, 0x0000fb27, 0x000012f1, 0x0000fb28, 0x000012f2, 0x0000fb29, 0x000012f3, 0x0000fb2a, 0x000012f4, 0x0000fb2b, 0x000012f6, 0x0000fb2c, 0x000012f8, 0x0000fb2d, 0x000012fb, 0x0000fb2e, 0x000012fe, 0x0000fb2f, 0x00001300, 0x0000fb30, 0x00001302, 0x0000fb31, 0x00001304, 0x0000fb32, 0x00001306, 0x0000fb33, 0x00001308, 0x0000fb34, 0x0000130a, 0x0000fb35, 0x0000130c, 0x0000fb36, 0x0000130e, 0x0000fb38, 0x00001310, 0x0000fb39, 0x00001312, 0x0000fb3a, 0x00001314, 0x0000fb3b, 0x00001316, 0x0000fb3c, 0x00001318, 0x0000fb3e, 0x0000131a, 0x0000fb40, 0x0000131c, 0x0000fb41, 0x0000131e, 0x0000fb43, 0x00001320, 0x0000fb44, 0x00001322, 0x0000fb46, 0x00001324, 0x0000fb47, 0x00001326, 0x0000fb48, 0x00001328, 0x0000fb49, 0x0000132a, 0x0000fb4a, 0x0000132c, 0x0000fb4b, 0x0000132e, 0x0000fb4c, 0x00001330, 0x0000fb4d, 0x00001332, 0x0000fb4e, 0x00001334, 0x0000fb4f, 0x00001336, 0x0000fb50, 0x00001338, 0x0000fb51, 0x00001339, 0x0000fb52, 0x0000133a, 0x0000fb53, 0x0000133b, 0x0000fb54, 0x0000133c, 0x0000fb55, 0x0000133d, 0x0000fb56, 0x0000133e, 0x0000fb57, 0x0000133f, 0x0000fb58, 0x00001340, 0x0000fb59, 0x00001341, 0x0000fb5a, 0x00001342, 0x0000fb5b, 0x00001343, 0x0000fb5c, 0x00001344, 0x0000fb5d, 0x00001345, 0x0000fb5e, 0x00001346, 0x0000fb5f, 0x00001347, 0x0000fb60, 0x00001348, 0x0000fb61, 0x00001349, 0x0000fb62, 0x0000134a, 0x0000fb63, 0x0000134b, 0x0000fb64, 0x0000134c, 0x0000fb65, 0x0000134d, 0x0000fb66, 0x0000134e, 0x0000fb67, 0x0000134f, 0x0000fb68, 0x00001350, 0x0000fb69, 0x00001351, 0x0000fb6a, 0x00001352, 0x0000fb6b, 0x00001353, 0x0000fb6c, 0x00001354, 0x0000fb6d, 0x00001355, 0x0000fb6e, 0x00001356, 0x0000fb6f, 0x00001357, 0x0000fb70, 0x00001358, 0x0000fb71, 0x00001359, 0x0000fb72, 0x0000135a, 0x0000fb73, 0x0000135b, 0x0000fb74, 0x0000135c, 0x0000fb75, 0x0000135d, 0x0000fb76, 0x0000135e, 0x0000fb77, 0x0000135f, 0x0000fb78, 0x00001360, 0x0000fb79, 0x00001361, 0x0000fb7a, 0x00001362, 0x0000fb7b, 0x00001363, 0x0000fb7c, 0x00001364, 0x0000fb7d, 0x00001365, 0x0000fb7e, 0x00001366, 0x0000fb7f, 0x00001367, 0x0000fb80, 0x00001368, 0x0000fb81, 0x00001369, 0x0000fb82, 0x0000136a, 0x0000fb83, 0x0000136b, 0x0000fb84, 0x0000136c, 0x0000fb85, 0x0000136d, 0x0000fb86, 0x0000136e, 0x0000fb87, 0x0000136f, 0x0000fb88, 0x00001370, 0x0000fb89, 0x00001371, 0x0000fb8a, 0x00001372, 0x0000fb8b, 0x00001373, 0x0000fb8c, 0x00001374, 0x0000fb8d, 0x00001375, 0x0000fb8e, 0x00001376, 0x0000fb8f, 0x00001377, 0x0000fb90, 0x00001378, 0x0000fb91, 0x00001379, 0x0000fb92, 0x0000137a, 0x0000fb93, 0x0000137b, 0x0000fb94, 0x0000137c, 0x0000fb95, 0x0000137d, 0x0000fb96, 0x0000137e, 0x0000fb97, 0x0000137f, 0x0000fb98, 0x00001380, 0x0000fb99, 0x00001381, 0x0000fb9a, 0x00001382, 0x0000fb9b, 0x00001383, 0x0000fb9c, 0x00001384, 0x0000fb9d, 0x00001385, 0x0000fb9e, 0x00001386, 0x0000fb9f, 0x00001387, 0x0000fba0, 0x00001388, 0x0000fba1, 0x00001389, 0x0000fba2, 0x0000138a, 0x0000fba3, 0x0000138b, 0x0000fba4, 0x0000138c, 0x0000fba5, 0x0000138e, 0x0000fba6, 0x00001390, 0x0000fba7, 0x00001391, 0x0000fba8, 0x00001392, 0x0000fba9, 0x00001393, 0x0000fbaa, 0x00001394, 0x0000fbab, 0x00001395, 0x0000fbac, 0x00001396, 0x0000fbad, 0x00001397, 0x0000fbae, 0x00001398, 0x0000fbaf, 0x00001399, 0x0000fbb0, 0x0000139a, 0x0000fbb1, 0x0000139c, 0x0000fbd3, 0x0000139e, 0x0000fbd4, 0x0000139f, 0x0000fbd5, 0x000013a0, 0x0000fbd6, 0x000013a1, 0x0000fbd7, 0x000013a2, 0x0000fbd8, 0x000013a3, 0x0000fbd9, 0x000013a4, 0x0000fbda, 0x000013a5, 0x0000fbdb, 0x000013a6, 0x0000fbdc, 0x000013a7, 0x0000fbdd, 0x000013a8, 0x0000fbde, 0x000013aa, 0x0000fbdf, 0x000013ab, 0x0000fbe0, 0x000013ac, 0x0000fbe1, 0x000013ad, 0x0000fbe2, 0x000013ae, 0x0000fbe3, 0x000013af, 0x0000fbe4, 0x000013b0, 0x0000fbe5, 0x000013b1, 0x0000fbe6, 0x000013b2, 0x0000fbe7, 0x000013b3, 0x0000fbe8, 0x000013b4, 0x0000fbe9, 0x000013b5, 0x0000fbea, 0x000013b6, 0x0000fbeb, 0x000013b9, 0x0000fbec, 0x000013bc, 0x0000fbed, 0x000013bf, 0x0000fbee, 0x000013c2, 0x0000fbef, 0x000013c5, 0x0000fbf0, 0x000013c8, 0x0000fbf1, 0x000013cb, 0x0000fbf2, 0x000013ce, 0x0000fbf3, 0x000013d1, 0x0000fbf4, 0x000013d4, 0x0000fbf5, 0x000013d7, 0x0000fbf6, 0x000013da, 0x0000fbf7, 0x000013dd, 0x0000fbf8, 0x000013e0, 0x0000fbf9, 0x000013e3, 0x0000fbfa, 0x000013e6, 0x0000fbfb, 0x000013e9, 0x0000fbfc, 0x000013ec, 0x0000fbfd, 0x000013ed, 0x0000fbfe, 0x000013ee, 0x0000fbff, 0x000013ef, 0x0000fc00, 0x000013f0, 0x0000fc01, 0x000013f3, 0x0000fc02, 0x000013f6, 0x0000fc03, 0x000013f9, 0x0000fc04, 0x000013fc, 0x0000fc05, 0x000013ff, 0x0000fc06, 0x00001401, 0x0000fc07, 0x00001403, 0x0000fc08, 0x00001405, 0x0000fc09, 0x00001407, 0x0000fc0a, 0x00001409, 0x0000fc0b, 0x0000140b, 0x0000fc0c, 0x0000140d, 0x0000fc0d, 0x0000140f, 0x0000fc0e, 0x00001411, 0x0000fc0f, 0x00001413, 0x0000fc10, 0x00001415, 0x0000fc11, 0x00001417, 0x0000fc12, 0x00001419, 0x0000fc13, 0x0000141b, 0x0000fc14, 0x0000141d, 0x0000fc15, 0x0000141f, 0x0000fc16, 0x00001421, 0x0000fc17, 0x00001423, 0x0000fc18, 0x00001425, 0x0000fc19, 0x00001427, 0x0000fc1a, 0x00001429, 0x0000fc1b, 0x0000142b, 0x0000fc1c, 0x0000142d, 0x0000fc1d, 0x0000142f, 0x0000fc1e, 0x00001431, 0x0000fc1f, 0x00001433, 0x0000fc20, 0x00001435, 0x0000fc21, 0x00001437, 0x0000fc22, 0x00001439, 0x0000fc23, 0x0000143b, 0x0000fc24, 0x0000143d, 0x0000fc25, 0x0000143f, 0x0000fc26, 0x00001441, 0x0000fc27, 0x00001443, 0x0000fc28, 0x00001445, 0x0000fc29, 0x00001447, 0x0000fc2a, 0x00001449, 0x0000fc2b, 0x0000144b, 0x0000fc2c, 0x0000144d, 0x0000fc2d, 0x0000144f, 0x0000fc2e, 0x00001451, 0x0000fc2f, 0x00001453, 0x0000fc30, 0x00001455, 0x0000fc31, 0x00001457, 0x0000fc32, 0x00001459, 0x0000fc33, 0x0000145b, 0x0000fc34, 0x0000145d, 0x0000fc35, 0x0000145f, 0x0000fc36, 0x00001461, 0x0000fc37, 0x00001463, 0x0000fc38, 0x00001465, 0x0000fc39, 0x00001467, 0x0000fc3a, 0x00001469, 0x0000fc3b, 0x0000146b, 0x0000fc3c, 0x0000146d, 0x0000fc3d, 0x0000146f, 0x0000fc3e, 0x00001471, 0x0000fc3f, 0x00001473, 0x0000fc40, 0x00001475, 0x0000fc41, 0x00001477, 0x0000fc42, 0x00001479, 0x0000fc43, 0x0000147b, 0x0000fc44, 0x0000147d, 0x0000fc45, 0x0000147f, 0x0000fc46, 0x00001481, 0x0000fc47, 0x00001483, 0x0000fc48, 0x00001485, 0x0000fc49, 0x00001487, 0x0000fc4a, 0x00001489, 0x0000fc4b, 0x0000148b, 0x0000fc4c, 0x0000148d, 0x0000fc4d, 0x0000148f, 0x0000fc4e, 0x00001491, 0x0000fc4f, 0x00001493, 0x0000fc50, 0x00001495, 0x0000fc51, 0x00001497, 0x0000fc52, 0x00001499, 0x0000fc53, 0x0000149b, 0x0000fc54, 0x0000149d, 0x0000fc55, 0x0000149f, 0x0000fc56, 0x000014a1, 0x0000fc57, 0x000014a3, 0x0000fc58, 0x000014a5, 0x0000fc59, 0x000014a7, 0x0000fc5a, 0x000014a9, 0x0000fc5b, 0x000014ab, 0x0000fc5c, 0x000014ad, 0x0000fc5d, 0x000014af, 0x0000fc5e, 0x000014b1, 0x0000fc5f, 0x000014b4, 0x0000fc60, 0x000014b7, 0x0000fc61, 0x000014ba, 0x0000fc62, 0x000014bd, 0x0000fc63, 0x000014c0, 0x0000fc64, 0x000014c3, 0x0000fc65, 0x000014c6, 0x0000fc66, 0x000014c9, 0x0000fc67, 0x000014cc, 0x0000fc68, 0x000014cf, 0x0000fc69, 0x000014d2, 0x0000fc6a, 0x000014d5, 0x0000fc6b, 0x000014d7, 0x0000fc6c, 0x000014d9, 0x0000fc6d, 0x000014db, 0x0000fc6e, 0x000014dd, 0x0000fc6f, 0x000014df, 0x0000fc70, 0x000014e1, 0x0000fc71, 0x000014e3, 0x0000fc72, 0x000014e5, 0x0000fc73, 0x000014e7, 0x0000fc74, 0x000014e9, 0x0000fc75, 0x000014eb, 0x0000fc76, 0x000014ed, 0x0000fc77, 0x000014ef, 0x0000fc78, 0x000014f1, 0x0000fc79, 0x000014f3, 0x0000fc7a, 0x000014f5, 0x0000fc7b, 0x000014f7, 0x0000fc7c, 0x000014f9, 0x0000fc7d, 0x000014fb, 0x0000fc7e, 0x000014fd, 0x0000fc7f, 0x000014ff, 0x0000fc80, 0x00001501, 0x0000fc81, 0x00001503, 0x0000fc82, 0x00001505, 0x0000fc83, 0x00001507, 0x0000fc84, 0x00001509, 0x0000fc85, 0x0000150b, 0x0000fc86, 0x0000150d, 0x0000fc87, 0x0000150f, 0x0000fc88, 0x00001511, 0x0000fc89, 0x00001513, 0x0000fc8a, 0x00001515, 0x0000fc8b, 0x00001517, 0x0000fc8c, 0x00001519, 0x0000fc8d, 0x0000151b, 0x0000fc8e, 0x0000151d, 0x0000fc8f, 0x0000151f, 0x0000fc90, 0x00001521, 0x0000fc91, 0x00001523, 0x0000fc92, 0x00001525, 0x0000fc93, 0x00001527, 0x0000fc94, 0x00001529, 0x0000fc95, 0x0000152b, 0x0000fc96, 0x0000152d, 0x0000fc97, 0x0000152f, 0x0000fc98, 0x00001532, 0x0000fc99, 0x00001535, 0x0000fc9a, 0x00001538, 0x0000fc9b, 0x0000153b, 0x0000fc9c, 0x0000153e, 0x0000fc9d, 0x00001540, 0x0000fc9e, 0x00001542, 0x0000fc9f, 0x00001544, 0x0000fca0, 0x00001546, 0x0000fca1, 0x00001548, 0x0000fca2, 0x0000154a, 0x0000fca3, 0x0000154c, 0x0000fca4, 0x0000154e, 0x0000fca5, 0x00001550, 0x0000fca6, 0x00001552, 0x0000fca7, 0x00001554, 0x0000fca8, 0x00001556, 0x0000fca9, 0x00001558, 0x0000fcaa, 0x0000155a, 0x0000fcab, 0x0000155c, 0x0000fcac, 0x0000155e, 0x0000fcad, 0x00001560, 0x0000fcae, 0x00001562, 0x0000fcaf, 0x00001564, 0x0000fcb0, 0x00001566, 0x0000fcb1, 0x00001568, 0x0000fcb2, 0x0000156a, 0x0000fcb3, 0x0000156c, 0x0000fcb4, 0x0000156e, 0x0000fcb5, 0x00001570, 0x0000fcb6, 0x00001572, 0x0000fcb7, 0x00001574, 0x0000fcb8, 0x00001576, 0x0000fcb9, 0x00001578, 0x0000fcba, 0x0000157a, 0x0000fcbb, 0x0000157c, 0x0000fcbc, 0x0000157e, 0x0000fcbd, 0x00001580, 0x0000fcbe, 0x00001582, 0x0000fcbf, 0x00001584, 0x0000fcc0, 0x00001586, 0x0000fcc1, 0x00001588, 0x0000fcc2, 0x0000158a, 0x0000fcc3, 0x0000158c, 0x0000fcc4, 0x0000158e, 0x0000fcc5, 0x00001590, 0x0000fcc6, 0x00001592, 0x0000fcc7, 0x00001594, 0x0000fcc8, 0x00001596, 0x0000fcc9, 0x00001598, 0x0000fcca, 0x0000159a, 0x0000fccb, 0x0000159c, 0x0000fccc, 0x0000159e, 0x0000fccd, 0x000015a0, 0x0000fcce, 0x000015a2, 0x0000fccf, 0x000015a4, 0x0000fcd0, 0x000015a6, 0x0000fcd1, 0x000015a8, 0x0000fcd2, 0x000015aa, 0x0000fcd3, 0x000015ac, 0x0000fcd4, 0x000015ae, 0x0000fcd5, 0x000015b0, 0x0000fcd6, 0x000015b2, 0x0000fcd7, 0x000015b4, 0x0000fcd8, 0x000015b6, 0x0000fcd9, 0x000015b8, 0x0000fcda, 0x000015ba, 0x0000fcdb, 0x000015bc, 0x0000fcdc, 0x000015be, 0x0000fcdd, 0x000015c0, 0x0000fcde, 0x000015c2, 0x0000fcdf, 0x000015c4, 0x0000fce0, 0x000015c7, 0x0000fce1, 0x000015ca, 0x0000fce2, 0x000015cc, 0x0000fce3, 0x000015ce, 0x0000fce4, 0x000015d0, 0x0000fce5, 0x000015d2, 0x0000fce6, 0x000015d4, 0x0000fce7, 0x000015d6, 0x0000fce8, 0x000015d8, 0x0000fce9, 0x000015da, 0x0000fcea, 0x000015dc, 0x0000fceb, 0x000015de, 0x0000fcec, 0x000015e0, 0x0000fced, 0x000015e2, 0x0000fcee, 0x000015e4, 0x0000fcef, 0x000015e6, 0x0000fcf0, 0x000015e8, 0x0000fcf1, 0x000015ea, 0x0000fcf2, 0x000015ec, 0x0000fcf3, 0x000015ef, 0x0000fcf4, 0x000015f2, 0x0000fcf5, 0x000015f5, 0x0000fcf6, 0x000015f7, 0x0000fcf7, 0x000015f9, 0x0000fcf8, 0x000015fb, 0x0000fcf9, 0x000015fd, 0x0000fcfa, 0x000015ff, 0x0000fcfb, 0x00001601, 0x0000fcfc, 0x00001603, 0x0000fcfd, 0x00001605, 0x0000fcfe, 0x00001607, 0x0000fcff, 0x00001609, 0x0000fd00, 0x0000160b, 0x0000fd01, 0x0000160d, 0x0000fd02, 0x0000160f, 0x0000fd03, 0x00001611, 0x0000fd04, 0x00001613, 0x0000fd05, 0x00001615, 0x0000fd06, 0x00001617, 0x0000fd07, 0x00001619, 0x0000fd08, 0x0000161b, 0x0000fd09, 0x0000161d, 0x0000fd0a, 0x0000161f, 0x0000fd0b, 0x00001621, 0x0000fd0c, 0x00001623, 0x0000fd0d, 0x00001625, 0x0000fd0e, 0x00001627, 0x0000fd0f, 0x00001629, 0x0000fd10, 0x0000162b, 0x0000fd11, 0x0000162d, 0x0000fd12, 0x0000162f, 0x0000fd13, 0x00001631, 0x0000fd14, 0x00001633, 0x0000fd15, 0x00001635, 0x0000fd16, 0x00001637, 0x0000fd17, 0x00001639, 0x0000fd18, 0x0000163b, 0x0000fd19, 0x0000163d, 0x0000fd1a, 0x0000163f, 0x0000fd1b, 0x00001641, 0x0000fd1c, 0x00001643, 0x0000fd1d, 0x00001645, 0x0000fd1e, 0x00001647, 0x0000fd1f, 0x00001649, 0x0000fd20, 0x0000164b, 0x0000fd21, 0x0000164d, 0x0000fd22, 0x0000164f, 0x0000fd23, 0x00001651, 0x0000fd24, 0x00001653, 0x0000fd25, 0x00001655, 0x0000fd26, 0x00001657, 0x0000fd27, 0x00001659, 0x0000fd28, 0x0000165b, 0x0000fd29, 0x0000165d, 0x0000fd2a, 0x0000165f, 0x0000fd2b, 0x00001661, 0x0000fd2c, 0x00001663, 0x0000fd2d, 0x00001665, 0x0000fd2e, 0x00001667, 0x0000fd2f, 0x00001669, 0x0000fd30, 0x0000166b, 0x0000fd31, 0x0000166d, 0x0000fd32, 0x0000166f, 0x0000fd33, 0x00001671, 0x0000fd34, 0x00001673, 0x0000fd35, 0x00001675, 0x0000fd36, 0x00001677, 0x0000fd37, 0x00001679, 0x0000fd38, 0x0000167b, 0x0000fd39, 0x0000167d, 0x0000fd3a, 0x0000167f, 0x0000fd3b, 0x00001681, 0x0000fd3c, 0x00001683, 0x0000fd3d, 0x00001685, 0x0000fd50, 0x00001687, 0x0000fd51, 0x0000168a, 0x0000fd52, 0x0000168d, 0x0000fd53, 0x00001690, 0x0000fd54, 0x00001693, 0x0000fd55, 0x00001696, 0x0000fd56, 0x00001699, 0x0000fd57, 0x0000169c, 0x0000fd58, 0x0000169f, 0x0000fd59, 0x000016a2, 0x0000fd5a, 0x000016a5, 0x0000fd5b, 0x000016a8, 0x0000fd5c, 0x000016ab, 0x0000fd5d, 0x000016ae, 0x0000fd5e, 0x000016b1, 0x0000fd5f, 0x000016b4, 0x0000fd60, 0x000016b7, 0x0000fd61, 0x000016ba, 0x0000fd62, 0x000016bd, 0x0000fd63, 0x000016c0, 0x0000fd64, 0x000016c3, 0x0000fd65, 0x000016c6, 0x0000fd66, 0x000016c9, 0x0000fd67, 0x000016cc, 0x0000fd68, 0x000016cf, 0x0000fd69, 0x000016d2, 0x0000fd6a, 0x000016d5, 0x0000fd6b, 0x000016d8, 0x0000fd6c, 0x000016db, 0x0000fd6d, 0x000016de, 0x0000fd6e, 0x000016e1, 0x0000fd6f, 0x000016e4, 0x0000fd70, 0x000016e7, 0x0000fd71, 0x000016ea, 0x0000fd72, 0x000016ed, 0x0000fd73, 0x000016f0, 0x0000fd74, 0x000016f3, 0x0000fd75, 0x000016f6, 0x0000fd76, 0x000016f9, 0x0000fd77, 0x000016fc, 0x0000fd78, 0x000016ff, 0x0000fd79, 0x00001702, 0x0000fd7a, 0x00001705, 0x0000fd7b, 0x00001708, 0x0000fd7c, 0x0000170b, 0x0000fd7d, 0x0000170e, 0x0000fd7e, 0x00001711, 0x0000fd7f, 0x00001714, 0x0000fd80, 0x00001717, 0x0000fd81, 0x0000171a, 0x0000fd82, 0x0000171d, 0x0000fd83, 0x00001720, 0x0000fd84, 0x00001723, 0x0000fd85, 0x00001726, 0x0000fd86, 0x00001729, 0x0000fd87, 0x0000172c, 0x0000fd88, 0x0000172f, 0x0000fd89, 0x00001732, 0x0000fd8a, 0x00001735, 0x0000fd8b, 0x00001738, 0x0000fd8c, 0x0000173b, 0x0000fd8d, 0x0000173e, 0x0000fd8e, 0x00001741, 0x0000fd8f, 0x00001744, 0x0000fd92, 0x00001747, 0x0000fd93, 0x0000174a, 0x0000fd94, 0x0000174d, 0x0000fd95, 0x00001750, 0x0000fd96, 0x00001753, 0x0000fd97, 0x00001756, 0x0000fd98, 0x00001759, 0x0000fd99, 0x0000175c, 0x0000fd9a, 0x0000175f, 0x0000fd9b, 0x00001762, 0x0000fd9c, 0x00001765, 0x0000fd9d, 0x00001768, 0x0000fd9e, 0x0000176b, 0x0000fd9f, 0x0000176e, 0x0000fda0, 0x00001771, 0x0000fda1, 0x00001774, 0x0000fda2, 0x00001777, 0x0000fda3, 0x0000177a, 0x0000fda4, 0x0000177d, 0x0000fda5, 0x00001780, 0x0000fda6, 0x00001783, 0x0000fda7, 0x00001786, 0x0000fda8, 0x00001789, 0x0000fda9, 0x0000178c, 0x0000fdaa, 0x0000178f, 0x0000fdab, 0x00001792, 0x0000fdac, 0x00001795, 0x0000fdad, 0x00001798, 0x0000fdae, 0x0000179b, 0x0000fdaf, 0x0000179e, 0x0000fdb0, 0x000017a1, 0x0000fdb1, 0x000017a4, 0x0000fdb2, 0x000017a7, 0x0000fdb3, 0x000017aa, 0x0000fdb4, 0x000017ad, 0x0000fdb5, 0x000017b0, 0x0000fdb6, 0x000017b3, 0x0000fdb7, 0x000017b6, 0x0000fdb8, 0x000017b9, 0x0000fdb9, 0x000017bc, 0x0000fdba, 0x000017bf, 0x0000fdbb, 0x000017c2, 0x0000fdbc, 0x000017c5, 0x0000fdbd, 0x000017c8, 0x0000fdbe, 0x000017cb, 0x0000fdbf, 0x000017ce, 0x0000fdc0, 0x000017d1, 0x0000fdc1, 0x000017d4, 0x0000fdc2, 0x000017d7, 0x0000fdc3, 0x000017da, 0x0000fdc4, 0x000017dd, 0x0000fdc5, 0x000017e0, 0x0000fdc6, 0x000017e3, 0x0000fdc7, 0x000017e6, 0x0000fdf0, 0x000017e9, 0x0000fdf1, 0x000017ec, 0x0000fdf2, 0x000017ef, 0x0000fdf3, 0x000017f3, 0x0000fdf4, 0x000017f7, 0x0000fdf5, 0x000017fb, 0x0000fdf6, 0x000017ff, 0x0000fdf7, 0x00001803, 0x0000fdf8, 0x00001807, 0x0000fdf9, 0x0000180b, 0x0000fdfa, 0x0000180e, 0x0000fdfb, 0x00001820, 0x0000fdfc, 0x00001828, 0x0000fe30, 0x0000182c, 0x0000fe31, 0x0000182e, 0x0000fe32, 0x0000182f, 0x0000fe33, 0x00001830, 0x0000fe34, 0x00001831, 0x0000fe35, 0x00001832, 0x0000fe36, 0x00001833, 0x0000fe37, 0x00001834, 0x0000fe38, 0x00001835, 0x0000fe39, 0x00001836, 0x0000fe3a, 0x00001837, 0x0000fe3b, 0x00001838, 0x0000fe3c, 0x00001839, 0x0000fe3d, 0x0000183a, 0x0000fe3e, 0x0000183b, 0x0000fe3f, 0x0000183c, 0x0000fe40, 0x0000183d, 0x0000fe41, 0x0000183e, 0x0000fe42, 0x0000183f, 0x0000fe43, 0x00001840, 0x0000fe44, 0x00001841, 0x0000fe49, 0x00001842, 0x0000fe4a, 0x00001844, 0x0000fe4b, 0x00001846, 0x0000fe4c, 0x00001848, 0x0000fe4d, 0x0000184a, 0x0000fe4e, 0x0000184b, 0x0000fe4f, 0x0000184c, 0x0000fe50, 0x0000184d, 0x0000fe51, 0x0000184e, 0x0000fe52, 0x0000184f, 0x0000fe54, 0x00001850, 0x0000fe55, 0x00001851, 0x0000fe56, 0x00001852, 0x0000fe57, 0x00001853, 0x0000fe58, 0x00001854, 0x0000fe59, 0x00001855, 0x0000fe5a, 0x00001856, 0x0000fe5b, 0x00001857, 0x0000fe5c, 0x00001858, 0x0000fe5d, 0x00001859, 0x0000fe5e, 0x0000185a, 0x0000fe5f, 0x0000185b, 0x0000fe60, 0x0000185c, 0x0000fe61, 0x0000185d, 0x0000fe62, 0x0000185e, 0x0000fe63, 0x0000185f, 0x0000fe64, 0x00001860, 0x0000fe65, 0x00001861, 0x0000fe66, 0x00001862, 0x0000fe68, 0x00001863, 0x0000fe69, 0x00001864, 0x0000fe6a, 0x00001865, 0x0000fe6b, 0x00001866, 0x0000fe70, 0x00001867, 0x0000fe71, 0x00001869, 0x0000fe72, 0x0000186b, 0x0000fe74, 0x0000186d, 0x0000fe76, 0x0000186f, 0x0000fe77, 0x00001871, 0x0000fe78, 0x00001873, 0x0000fe79, 0x00001875, 0x0000fe7a, 0x00001877, 0x0000fe7b, 0x00001879, 0x0000fe7c, 0x0000187b, 0x0000fe7d, 0x0000187d, 0x0000fe7e, 0x0000187f, 0x0000fe7f, 0x00001881, 0x0000fe80, 0x00001883, 0x0000fe81, 0x00001884, 0x0000fe82, 0x00001886, 0x0000fe83, 0x00001888, 0x0000fe84, 0x0000188a, 0x0000fe85, 0x0000188c, 0x0000fe86, 0x0000188e, 0x0000fe87, 0x00001890, 0x0000fe88, 0x00001892, 0x0000fe89, 0x00001894, 0x0000fe8a, 0x00001896, 0x0000fe8b, 0x00001898, 0x0000fe8c, 0x0000189a, 0x0000fe8d, 0x0000189c, 0x0000fe8e, 0x0000189d, 0x0000fe8f, 0x0000189e, 0x0000fe90, 0x0000189f, 0x0000fe91, 0x000018a0, 0x0000fe92, 0x000018a1, 0x0000fe93, 0x000018a2, 0x0000fe94, 0x000018a3, 0x0000fe95, 0x000018a4, 0x0000fe96, 0x000018a5, 0x0000fe97, 0x000018a6, 0x0000fe98, 0x000018a7, 0x0000fe99, 0x000018a8, 0x0000fe9a, 0x000018a9, 0x0000fe9b, 0x000018aa, 0x0000fe9c, 0x000018ab, 0x0000fe9d, 0x000018ac, 0x0000fe9e, 0x000018ad, 0x0000fe9f, 0x000018ae, 0x0000fea0, 0x000018af, 0x0000fea1, 0x000018b0, 0x0000fea2, 0x000018b1, 0x0000fea3, 0x000018b2, 0x0000fea4, 0x000018b3, 0x0000fea5, 0x000018b4, 0x0000fea6, 0x000018b5, 0x0000fea7, 0x000018b6, 0x0000fea8, 0x000018b7, 0x0000fea9, 0x000018b8, 0x0000feaa, 0x000018b9, 0x0000feab, 0x000018ba, 0x0000feac, 0x000018bb, 0x0000fead, 0x000018bc, 0x0000feae, 0x000018bd, 0x0000feaf, 0x000018be, 0x0000feb0, 0x000018bf, 0x0000feb1, 0x000018c0, 0x0000feb2, 0x000018c1, 0x0000feb3, 0x000018c2, 0x0000feb4, 0x000018c3, 0x0000feb5, 0x000018c4, 0x0000feb6, 0x000018c5, 0x0000feb7, 0x000018c6, 0x0000feb8, 0x000018c7, 0x0000feb9, 0x000018c8, 0x0000feba, 0x000018c9, 0x0000febb, 0x000018ca, 0x0000febc, 0x000018cb, 0x0000febd, 0x000018cc, 0x0000febe, 0x000018cd, 0x0000febf, 0x000018ce, 0x0000fec0, 0x000018cf, 0x0000fec1, 0x000018d0, 0x0000fec2, 0x000018d1, 0x0000fec3, 0x000018d2, 0x0000fec4, 0x000018d3, 0x0000fec5, 0x000018d4, 0x0000fec6, 0x000018d5, 0x0000fec7, 0x000018d6, 0x0000fec8, 0x000018d7, 0x0000fec9, 0x000018d8, 0x0000feca, 0x000018d9, 0x0000fecb, 0x000018da, 0x0000fecc, 0x000018db, 0x0000fecd, 0x000018dc, 0x0000fece, 0x000018dd, 0x0000fecf, 0x000018de, 0x0000fed0, 0x000018df, 0x0000fed1, 0x000018e0, 0x0000fed2, 0x000018e1, 0x0000fed3, 0x000018e2, 0x0000fed4, 0x000018e3, 0x0000fed5, 0x000018e4, 0x0000fed6, 0x000018e5, 0x0000fed7, 0x000018e6, 0x0000fed8, 0x000018e7, 0x0000fed9, 0x000018e8, 0x0000feda, 0x000018e9, 0x0000fedb, 0x000018ea, 0x0000fedc, 0x000018eb, 0x0000fedd, 0x000018ec, 0x0000fede, 0x000018ed, 0x0000fedf, 0x000018ee, 0x0000fee0, 0x000018ef, 0x0000fee1, 0x000018f0, 0x0000fee2, 0x000018f1, 0x0000fee3, 0x000018f2, 0x0000fee4, 0x000018f3, 0x0000fee5, 0x000018f4, 0x0000fee6, 0x000018f5, 0x0000fee7, 0x000018f6, 0x0000fee8, 0x000018f7, 0x0000fee9, 0x000018f8, 0x0000feea, 0x000018f9, 0x0000feeb, 0x000018fa, 0x0000feec, 0x000018fb, 0x0000feed, 0x000018fc, 0x0000feee, 0x000018fd, 0x0000feef, 0x000018fe, 0x0000fef0, 0x000018ff, 0x0000fef1, 0x00001900, 0x0000fef2, 0x00001901, 0x0000fef3, 0x00001902, 0x0000fef4, 0x00001903, 0x0000fef5, 0x00001904, 0x0000fef6, 0x00001907, 0x0000fef7, 0x0000190a, 0x0000fef8, 0x0000190d, 0x0000fef9, 0x00001910, 0x0000fefa, 0x00001913, 0x0000fefb, 0x00001916, 0x0000fefc, 0x00001918, 0x0000ff01, 0x0000191a, 0x0000ff02, 0x0000191b, 0x0000ff03, 0x0000191c, 0x0000ff04, 0x0000191d, 0x0000ff05, 0x0000191e, 0x0000ff06, 0x0000191f, 0x0000ff07, 0x00001920, 0x0000ff08, 0x00001921, 0x0000ff09, 0x00001922, 0x0000ff0a, 0x00001923, 0x0000ff0b, 0x00001924, 0x0000ff0c, 0x00001925, 0x0000ff0d, 0x00001926, 0x0000ff0e, 0x00001927, 0x0000ff0f, 0x00001928, 0x0000ff10, 0x00001929, 0x0000ff11, 0x0000192a, 0x0000ff12, 0x0000192b, 0x0000ff13, 0x0000192c, 0x0000ff14, 0x0000192d, 0x0000ff15, 0x0000192e, 0x0000ff16, 0x0000192f, 0x0000ff17, 0x00001930, 0x0000ff18, 0x00001931, 0x0000ff19, 0x00001932, 0x0000ff1a, 0x00001933, 0x0000ff1b, 0x00001934, 0x0000ff1c, 0x00001935, 0x0000ff1d, 0x00001936, 0x0000ff1e, 0x00001937, 0x0000ff1f, 0x00001938, 0x0000ff20, 0x00001939, 0x0000ff21, 0x0000193a, 0x0000ff22, 0x0000193b, 0x0000ff23, 0x0000193c, 0x0000ff24, 0x0000193d, 0x0000ff25, 0x0000193e, 0x0000ff26, 0x0000193f, 0x0000ff27, 0x00001940, 0x0000ff28, 0x00001941, 0x0000ff29, 0x00001942, 0x0000ff2a, 0x00001943, 0x0000ff2b, 0x00001944, 0x0000ff2c, 0x00001945, 0x0000ff2d, 0x00001946, 0x0000ff2e, 0x00001947, 0x0000ff2f, 0x00001948, 0x0000ff30, 0x00001949, 0x0000ff31, 0x0000194a, 0x0000ff32, 0x0000194b, 0x0000ff33, 0x0000194c, 0x0000ff34, 0x0000194d, 0x0000ff35, 0x0000194e, 0x0000ff36, 0x0000194f, 0x0000ff37, 0x00001950, 0x0000ff38, 0x00001951, 0x0000ff39, 0x00001952, 0x0000ff3a, 0x00001953, 0x0000ff3b, 0x00001954, 0x0000ff3c, 0x00001955, 0x0000ff3d, 0x00001956, 0x0000ff3e, 0x00001957, 0x0000ff3f, 0x00001958, 0x0000ff40, 0x00001959, 0x0000ff41, 0x0000195a, 0x0000ff42, 0x0000195b, 0x0000ff43, 0x0000195c, 0x0000ff44, 0x0000195d, 0x0000ff45, 0x0000195e, 0x0000ff46, 0x0000195f, 0x0000ff47, 0x00001960, 0x0000ff48, 0x00001961, 0x0000ff49, 0x00001962, 0x0000ff4a, 0x00001963, 0x0000ff4b, 0x00001964, 0x0000ff4c, 0x00001965, 0x0000ff4d, 0x00001966, 0x0000ff4e, 0x00001967, 0x0000ff4f, 0x00001968, 0x0000ff50, 0x00001969, 0x0000ff51, 0x0000196a, 0x0000ff52, 0x0000196b, 0x0000ff53, 0x0000196c, 0x0000ff54, 0x0000196d, 0x0000ff55, 0x0000196e, 0x0000ff56, 0x0000196f, 0x0000ff57, 0x00001970, 0x0000ff58, 0x00001971, 0x0000ff59, 0x00001972, 0x0000ff5a, 0x00001973, 0x0000ff5b, 0x00001974, 0x0000ff5c, 0x00001975, 0x0000ff5d, 0x00001976, 0x0000ff5e, 0x00001977, 0x0000ff5f, 0x00001978, 0x0000ff60, 0x00001979, 0x0000ff61, 0x0000197a, 0x0000ff62, 0x0000197b, 0x0000ff63, 0x0000197c, 0x0000ff64, 0x0000197d, 0x0000ff65, 0x0000197e, 0x0000ff66, 0x0000197f, 0x0000ff67, 0x00001980, 0x0000ff68, 0x00001981, 0x0000ff69, 0x00001982, 0x0000ff6a, 0x00001983, 0x0000ff6b, 0x00001984, 0x0000ff6c, 0x00001985, 0x0000ff6d, 0x00001986, 0x0000ff6e, 0x00001987, 0x0000ff6f, 0x00001988, 0x0000ff70, 0x00001989, 0x0000ff71, 0x0000198a, 0x0000ff72, 0x0000198b, 0x0000ff73, 0x0000198c, 0x0000ff74, 0x0000198d, 0x0000ff75, 0x0000198e, 0x0000ff76, 0x0000198f, 0x0000ff77, 0x00001990, 0x0000ff78, 0x00001991, 0x0000ff79, 0x00001992, 0x0000ff7a, 0x00001993, 0x0000ff7b, 0x00001994, 0x0000ff7c, 0x00001995, 0x0000ff7d, 0x00001996, 0x0000ff7e, 0x00001997, 0x0000ff7f, 0x00001998, 0x0000ff80, 0x00001999, 0x0000ff81, 0x0000199a, 0x0000ff82, 0x0000199b, 0x0000ff83, 0x0000199c, 0x0000ff84, 0x0000199d, 0x0000ff85, 0x0000199e, 0x0000ff86, 0x0000199f, 0x0000ff87, 0x000019a0, 0x0000ff88, 0x000019a1, 0x0000ff89, 0x000019a2, 0x0000ff8a, 0x000019a3, 0x0000ff8b, 0x000019a4, 0x0000ff8c, 0x000019a5, 0x0000ff8d, 0x000019a6, 0x0000ff8e, 0x000019a7, 0x0000ff8f, 0x000019a8, 0x0000ff90, 0x000019a9, 0x0000ff91, 0x000019aa, 0x0000ff92, 0x000019ab, 0x0000ff93, 0x000019ac, 0x0000ff94, 0x000019ad, 0x0000ff95, 0x000019ae, 0x0000ff96, 0x000019af, 0x0000ff97, 0x000019b0, 0x0000ff98, 0x000019b1, 0x0000ff99, 0x000019b2, 0x0000ff9a, 0x000019b3, 0x0000ff9b, 0x000019b4, 0x0000ff9c, 0x000019b5, 0x0000ff9d, 0x000019b6, 0x0000ff9e, 0x000019b7, 0x0000ff9f, 0x000019b8, 0x0000ffa0, 0x000019b9, 0x0000ffa1, 0x000019ba, 0x0000ffa2, 0x000019bb, 0x0000ffa3, 0x000019bc, 0x0000ffa4, 0x000019bd, 0x0000ffa5, 0x000019be, 0x0000ffa6, 0x000019bf, 0x0000ffa7, 0x000019c0, 0x0000ffa8, 0x000019c1, 0x0000ffa9, 0x000019c2, 0x0000ffaa, 0x000019c3, 0x0000ffab, 0x000019c4, 0x0000ffac, 0x000019c5, 0x0000ffad, 0x000019c6, 0x0000ffae, 0x000019c7, 0x0000ffaf, 0x000019c8, 0x0000ffb0, 0x000019c9, 0x0000ffb1, 0x000019ca, 0x0000ffb2, 0x000019cb, 0x0000ffb3, 0x000019cc, 0x0000ffb4, 0x000019cd, 0x0000ffb5, 0x000019ce, 0x0000ffb6, 0x000019cf, 0x0000ffb7, 0x000019d0, 0x0000ffb8, 0x000019d1, 0x0000ffb9, 0x000019d2, 0x0000ffba, 0x000019d3, 0x0000ffbb, 0x000019d4, 0x0000ffbc, 0x000019d5, 0x0000ffbd, 0x000019d6, 0x0000ffbe, 0x000019d7, 0x0000ffc2, 0x000019d8, 0x0000ffc3, 0x000019d9, 0x0000ffc4, 0x000019da, 0x0000ffc5, 0x000019db, 0x0000ffc6, 0x000019dc, 0x0000ffc7, 0x000019dd, 0x0000ffca, 0x000019de, 0x0000ffcb, 0x000019df, 0x0000ffcc, 0x000019e0, 0x0000ffcd, 0x000019e1, 0x0000ffce, 0x000019e2, 0x0000ffcf, 0x000019e3, 0x0000ffd2, 0x000019e4, 0x0000ffd3, 0x000019e5, 0x0000ffd4, 0x000019e6, 0x0000ffd5, 0x000019e7, 0x0000ffd6, 0x000019e8, 0x0000ffd7, 0x000019e9, 0x0000ffda, 0x000019ea, 0x0000ffdb, 0x000019eb, 0x0000ffdc, 0x000019ec, 0x0000ffe0, 0x000019ed, 0x0000ffe1, 0x000019ee, 0x0000ffe2, 0x000019ef, 0x0000ffe3, 0x000019f0, 0x0000ffe4, 0x000019f2, 0x0000ffe5, 0x000019f3, 0x0000ffe6, 0x000019f4, 0x0000ffe8, 0x000019f5, 0x0000ffe9, 0x000019f6, 0x0000ffea, 0x000019f7, 0x0000ffeb, 0x000019f8, 0x0000ffec, 0x000019f9, 0x0000ffed, 0x000019fa, 0x0000ffee, 0x000019fb, 0x0001d15e, 0x000019fc, 0x0001d15f, 0x000019fe, 0x0001d160, 0x00001a00, 0x0001d161, 0x00001a03, 0x0001d162, 0x00001a06, 0x0001d163, 0x00001a09, 0x0001d164, 0x00001a0c, 0x0001d1bb, 0x00001a0f, 0x0001d1bc, 0x00001a11, 0x0001d1bd, 0x00001a13, 0x0001d1be, 0x00001a16, 0x0001d1bf, 0x00001a19, 0x0001d1c0, 0x00001a1c, 0x0001d400, 0x00001a1f, 0x0001d401, 0x00001a20, 0x0001d402, 0x00001a21, 0x0001d403, 0x00001a22, 0x0001d404, 0x00001a23, 0x0001d405, 0x00001a24, 0x0001d406, 0x00001a25, 0x0001d407, 0x00001a26, 0x0001d408, 0x00001a27, 0x0001d409, 0x00001a28, 0x0001d40a, 0x00001a29, 0x0001d40b, 0x00001a2a, 0x0001d40c, 0x00001a2b, 0x0001d40d, 0x00001a2c, 0x0001d40e, 0x00001a2d, 0x0001d40f, 0x00001a2e, 0x0001d410, 0x00001a2f, 0x0001d411, 0x00001a30, 0x0001d412, 0x00001a31, 0x0001d413, 0x00001a32, 0x0001d414, 0x00001a33, 0x0001d415, 0x00001a34, 0x0001d416, 0x00001a35, 0x0001d417, 0x00001a36, 0x0001d418, 0x00001a37, 0x0001d419, 0x00001a38, 0x0001d41a, 0x00001a39, 0x0001d41b, 0x00001a3a, 0x0001d41c, 0x00001a3b, 0x0001d41d, 0x00001a3c, 0x0001d41e, 0x00001a3d, 0x0001d41f, 0x00001a3e, 0x0001d420, 0x00001a3f, 0x0001d421, 0x00001a40, 0x0001d422, 0x00001a41, 0x0001d423, 0x00001a42, 0x0001d424, 0x00001a43, 0x0001d425, 0x00001a44, 0x0001d426, 0x00001a45, 0x0001d427, 0x00001a46, 0x0001d428, 0x00001a47, 0x0001d429, 0x00001a48, 0x0001d42a, 0x00001a49, 0x0001d42b, 0x00001a4a, 0x0001d42c, 0x00001a4b, 0x0001d42d, 0x00001a4c, 0x0001d42e, 0x00001a4d, 0x0001d42f, 0x00001a4e, 0x0001d430, 0x00001a4f, 0x0001d431, 0x00001a50, 0x0001d432, 0x00001a51, 0x0001d433, 0x00001a52, 0x0001d434, 0x00001a53, 0x0001d435, 0x00001a54, 0x0001d436, 0x00001a55, 0x0001d437, 0x00001a56, 0x0001d438, 0x00001a57, 0x0001d439, 0x00001a58, 0x0001d43a, 0x00001a59, 0x0001d43b, 0x00001a5a, 0x0001d43c, 0x00001a5b, 0x0001d43d, 0x00001a5c, 0x0001d43e, 0x00001a5d, 0x0001d43f, 0x00001a5e, 0x0001d440, 0x00001a5f, 0x0001d441, 0x00001a60, 0x0001d442, 0x00001a61, 0x0001d443, 0x00001a62, 0x0001d444, 0x00001a63, 0x0001d445, 0x00001a64, 0x0001d446, 0x00001a65, 0x0001d447, 0x00001a66, 0x0001d448, 0x00001a67, 0x0001d449, 0x00001a68, 0x0001d44a, 0x00001a69, 0x0001d44b, 0x00001a6a, 0x0001d44c, 0x00001a6b, 0x0001d44d, 0x00001a6c, 0x0001d44e, 0x00001a6d, 0x0001d44f, 0x00001a6e, 0x0001d450, 0x00001a6f, 0x0001d451, 0x00001a70, 0x0001d452, 0x00001a71, 0x0001d453, 0x00001a72, 0x0001d454, 0x00001a73, 0x0001d456, 0x00001a74, 0x0001d457, 0x00001a75, 0x0001d458, 0x00001a76, 0x0001d459, 0x00001a77, 0x0001d45a, 0x00001a78, 0x0001d45b, 0x00001a79, 0x0001d45c, 0x00001a7a, 0x0001d45d, 0x00001a7b, 0x0001d45e, 0x00001a7c, 0x0001d45f, 0x00001a7d, 0x0001d460, 0x00001a7e, 0x0001d461, 0x00001a7f, 0x0001d462, 0x00001a80, 0x0001d463, 0x00001a81, 0x0001d464, 0x00001a82, 0x0001d465, 0x00001a83, 0x0001d466, 0x00001a84, 0x0001d467, 0x00001a85, 0x0001d468, 0x00001a86, 0x0001d469, 0x00001a87, 0x0001d46a, 0x00001a88, 0x0001d46b, 0x00001a89, 0x0001d46c, 0x00001a8a, 0x0001d46d, 0x00001a8b, 0x0001d46e, 0x00001a8c, 0x0001d46f, 0x00001a8d, 0x0001d470, 0x00001a8e, 0x0001d471, 0x00001a8f, 0x0001d472, 0x00001a90, 0x0001d473, 0x00001a91, 0x0001d474, 0x00001a92, 0x0001d475, 0x00001a93, 0x0001d476, 0x00001a94, 0x0001d477, 0x00001a95, 0x0001d478, 0x00001a96, 0x0001d479, 0x00001a97, 0x0001d47a, 0x00001a98, 0x0001d47b, 0x00001a99, 0x0001d47c, 0x00001a9a, 0x0001d47d, 0x00001a9b, 0x0001d47e, 0x00001a9c, 0x0001d47f, 0x00001a9d, 0x0001d480, 0x00001a9e, 0x0001d481, 0x00001a9f, 0x0001d482, 0x00001aa0, 0x0001d483, 0x00001aa1, 0x0001d484, 0x00001aa2, 0x0001d485, 0x00001aa3, 0x0001d486, 0x00001aa4, 0x0001d487, 0x00001aa5, 0x0001d488, 0x00001aa6, 0x0001d489, 0x00001aa7, 0x0001d48a, 0x00001aa8, 0x0001d48b, 0x00001aa9, 0x0001d48c, 0x00001aaa, 0x0001d48d, 0x00001aab, 0x0001d48e, 0x00001aac, 0x0001d48f, 0x00001aad, 0x0001d490, 0x00001aae, 0x0001d491, 0x00001aaf, 0x0001d492, 0x00001ab0, 0x0001d493, 0x00001ab1, 0x0001d494, 0x00001ab2, 0x0001d495, 0x00001ab3, 0x0001d496, 0x00001ab4, 0x0001d497, 0x00001ab5, 0x0001d498, 0x00001ab6, 0x0001d499, 0x00001ab7, 0x0001d49a, 0x00001ab8, 0x0001d49b, 0x00001ab9, 0x0001d49c, 0x00001aba, 0x0001d49e, 0x00001abb, 0x0001d49f, 0x00001abc, 0x0001d4a2, 0x00001abd, 0x0001d4a5, 0x00001abe, 0x0001d4a6, 0x00001abf, 0x0001d4a9, 0x00001ac0, 0x0001d4aa, 0x00001ac1, 0x0001d4ab, 0x00001ac2, 0x0001d4ac, 0x00001ac3, 0x0001d4ae, 0x00001ac4, 0x0001d4af, 0x00001ac5, 0x0001d4b0, 0x00001ac6, 0x0001d4b1, 0x00001ac7, 0x0001d4b2, 0x00001ac8, 0x0001d4b3, 0x00001ac9, 0x0001d4b4, 0x00001aca, 0x0001d4b5, 0x00001acb, 0x0001d4b6, 0x00001acc, 0x0001d4b7, 0x00001acd, 0x0001d4b8, 0x00001ace, 0x0001d4b9, 0x00001acf, 0x0001d4bb, 0x00001ad0, 0x0001d4bd, 0x00001ad1, 0x0001d4be, 0x00001ad2, 0x0001d4bf, 0x00001ad3, 0x0001d4c0, 0x00001ad4, 0x0001d4c2, 0x00001ad5, 0x0001d4c3, 0x00001ad6, 0x0001d4c5, 0x00001ad7, 0x0001d4c6, 0x00001ad8, 0x0001d4c7, 0x00001ad9, 0x0001d4c8, 0x00001ada, 0x0001d4c9, 0x00001adb, 0x0001d4ca, 0x00001adc, 0x0001d4cb, 0x00001add, 0x0001d4cc, 0x00001ade, 0x0001d4cd, 0x00001adf, 0x0001d4ce, 0x00001ae0, 0x0001d4cf, 0x00001ae1, 0x0001d4d0, 0x00001ae2, 0x0001d4d1, 0x00001ae3, 0x0001d4d2, 0x00001ae4, 0x0001d4d3, 0x00001ae5, 0x0001d4d4, 0x00001ae6, 0x0001d4d5, 0x00001ae7, 0x0001d4d6, 0x00001ae8, 0x0001d4d7, 0x00001ae9, 0x0001d4d8, 0x00001aea, 0x0001d4d9, 0x00001aeb, 0x0001d4da, 0x00001aec, 0x0001d4db, 0x00001aed, 0x0001d4dc, 0x00001aee, 0x0001d4dd, 0x00001aef, 0x0001d4de, 0x00001af0, 0x0001d4df, 0x00001af1, 0x0001d4e0, 0x00001af2, 0x0001d4e1, 0x00001af3, 0x0001d4e2, 0x00001af4, 0x0001d4e3, 0x00001af5, 0x0001d4e4, 0x00001af6, 0x0001d4e5, 0x00001af7, 0x0001d4e6, 0x00001af8, 0x0001d4e7, 0x00001af9, 0x0001d4e8, 0x00001afa, 0x0001d4e9, 0x00001afb, 0x0001d4ea, 0x00001afc, 0x0001d4eb, 0x00001afd, 0x0001d4ec, 0x00001afe, 0x0001d4ed, 0x00001aff, 0x0001d4ee, 0x00001b00, 0x0001d4ef, 0x00001b01, 0x0001d4f0, 0x00001b02, 0x0001d4f1, 0x00001b03, 0x0001d4f2, 0x00001b04, 0x0001d4f3, 0x00001b05, 0x0001d4f4, 0x00001b06, 0x0001d4f5, 0x00001b07, 0x0001d4f6, 0x00001b08, 0x0001d4f7, 0x00001b09, 0x0001d4f8, 0x00001b0a, 0x0001d4f9, 0x00001b0b, 0x0001d4fa, 0x00001b0c, 0x0001d4fb, 0x00001b0d, 0x0001d4fc, 0x00001b0e, 0x0001d4fd, 0x00001b0f, 0x0001d4fe, 0x00001b10, 0x0001d4ff, 0x00001b11, 0x0001d500, 0x00001b12, 0x0001d501, 0x00001b13, 0x0001d502, 0x00001b14, 0x0001d503, 0x00001b15, 0x0001d504, 0x00001b16, 0x0001d505, 0x00001b17, 0x0001d507, 0x00001b18, 0x0001d508, 0x00001b19, 0x0001d509, 0x00001b1a, 0x0001d50a, 0x00001b1b, 0x0001d50d, 0x00001b1c, 0x0001d50e, 0x00001b1d, 0x0001d50f, 0x00001b1e, 0x0001d510, 0x00001b1f, 0x0001d511, 0x00001b20, 0x0001d512, 0x00001b21, 0x0001d513, 0x00001b22, 0x0001d514, 0x00001b23, 0x0001d516, 0x00001b24, 0x0001d517, 0x00001b25, 0x0001d518, 0x00001b26, 0x0001d519, 0x00001b27, 0x0001d51a, 0x00001b28, 0x0001d51b, 0x00001b29, 0x0001d51c, 0x00001b2a, 0x0001d51e, 0x00001b2b, 0x0001d51f, 0x00001b2c, 0x0001d520, 0x00001b2d, 0x0001d521, 0x00001b2e, 0x0001d522, 0x00001b2f, 0x0001d523, 0x00001b30, 0x0001d524, 0x00001b31, 0x0001d525, 0x00001b32, 0x0001d526, 0x00001b33, 0x0001d527, 0x00001b34, 0x0001d528, 0x00001b35, 0x0001d529, 0x00001b36, 0x0001d52a, 0x00001b37, 0x0001d52b, 0x00001b38, 0x0001d52c, 0x00001b39, 0x0001d52d, 0x00001b3a, 0x0001d52e, 0x00001b3b, 0x0001d52f, 0x00001b3c, 0x0001d530, 0x00001b3d, 0x0001d531, 0x00001b3e, 0x0001d532, 0x00001b3f, 0x0001d533, 0x00001b40, 0x0001d534, 0x00001b41, 0x0001d535, 0x00001b42, 0x0001d536, 0x00001b43, 0x0001d537, 0x00001b44, 0x0001d538, 0x00001b45, 0x0001d539, 0x00001b46, 0x0001d53b, 0x00001b47, 0x0001d53c, 0x00001b48, 0x0001d53d, 0x00001b49, 0x0001d53e, 0x00001b4a, 0x0001d540, 0x00001b4b, 0x0001d541, 0x00001b4c, 0x0001d542, 0x00001b4d, 0x0001d543, 0x00001b4e, 0x0001d544, 0x00001b4f, 0x0001d546, 0x00001b50, 0x0001d54a, 0x00001b51, 0x0001d54b, 0x00001b52, 0x0001d54c, 0x00001b53, 0x0001d54d, 0x00001b54, 0x0001d54e, 0x00001b55, 0x0001d54f, 0x00001b56, 0x0001d550, 0x00001b57, 0x0001d552, 0x00001b58, 0x0001d553, 0x00001b59, 0x0001d554, 0x00001b5a, 0x0001d555, 0x00001b5b, 0x0001d556, 0x00001b5c, 0x0001d557, 0x00001b5d, 0x0001d558, 0x00001b5e, 0x0001d559, 0x00001b5f, 0x0001d55a, 0x00001b60, 0x0001d55b, 0x00001b61, 0x0001d55c, 0x00001b62, 0x0001d55d, 0x00001b63, 0x0001d55e, 0x00001b64, 0x0001d55f, 0x00001b65, 0x0001d560, 0x00001b66, 0x0001d561, 0x00001b67, 0x0001d562, 0x00001b68, 0x0001d563, 0x00001b69, 0x0001d564, 0x00001b6a, 0x0001d565, 0x00001b6b, 0x0001d566, 0x00001b6c, 0x0001d567, 0x00001b6d, 0x0001d568, 0x00001b6e, 0x0001d569, 0x00001b6f, 0x0001d56a, 0x00001b70, 0x0001d56b, 0x00001b71, 0x0001d56c, 0x00001b72, 0x0001d56d, 0x00001b73, 0x0001d56e, 0x00001b74, 0x0001d56f, 0x00001b75, 0x0001d570, 0x00001b76, 0x0001d571, 0x00001b77, 0x0001d572, 0x00001b78, 0x0001d573, 0x00001b79, 0x0001d574, 0x00001b7a, 0x0001d575, 0x00001b7b, 0x0001d576, 0x00001b7c, 0x0001d577, 0x00001b7d, 0x0001d578, 0x00001b7e, 0x0001d579, 0x00001b7f, 0x0001d57a, 0x00001b80, 0x0001d57b, 0x00001b81, 0x0001d57c, 0x00001b82, 0x0001d57d, 0x00001b83, 0x0001d57e, 0x00001b84, 0x0001d57f, 0x00001b85, 0x0001d580, 0x00001b86, 0x0001d581, 0x00001b87, 0x0001d582, 0x00001b88, 0x0001d583, 0x00001b89, 0x0001d584, 0x00001b8a, 0x0001d585, 0x00001b8b, 0x0001d586, 0x00001b8c, 0x0001d587, 0x00001b8d, 0x0001d588, 0x00001b8e, 0x0001d589, 0x00001b8f, 0x0001d58a, 0x00001b90, 0x0001d58b, 0x00001b91, 0x0001d58c, 0x00001b92, 0x0001d58d, 0x00001b93, 0x0001d58e, 0x00001b94, 0x0001d58f, 0x00001b95, 0x0001d590, 0x00001b96, 0x0001d591, 0x00001b97, 0x0001d592, 0x00001b98, 0x0001d593, 0x00001b99, 0x0001d594, 0x00001b9a, 0x0001d595, 0x00001b9b, 0x0001d596, 0x00001b9c, 0x0001d597, 0x00001b9d, 0x0001d598, 0x00001b9e, 0x0001d599, 0x00001b9f, 0x0001d59a, 0x00001ba0, 0x0001d59b, 0x00001ba1, 0x0001d59c, 0x00001ba2, 0x0001d59d, 0x00001ba3, 0x0001d59e, 0x00001ba4, 0x0001d59f, 0x00001ba5, 0x0001d5a0, 0x00001ba6, 0x0001d5a1, 0x00001ba7, 0x0001d5a2, 0x00001ba8, 0x0001d5a3, 0x00001ba9, 0x0001d5a4, 0x00001baa, 0x0001d5a5, 0x00001bab, 0x0001d5a6, 0x00001bac, 0x0001d5a7, 0x00001bad, 0x0001d5a8, 0x00001bae, 0x0001d5a9, 0x00001baf, 0x0001d5aa, 0x00001bb0, 0x0001d5ab, 0x00001bb1, 0x0001d5ac, 0x00001bb2, 0x0001d5ad, 0x00001bb3, 0x0001d5ae, 0x00001bb4, 0x0001d5af, 0x00001bb5, 0x0001d5b0, 0x00001bb6, 0x0001d5b1, 0x00001bb7, 0x0001d5b2, 0x00001bb8, 0x0001d5b3, 0x00001bb9, 0x0001d5b4, 0x00001bba, 0x0001d5b5, 0x00001bbb, 0x0001d5b6, 0x00001bbc, 0x0001d5b7, 0x00001bbd, 0x0001d5b8, 0x00001bbe, 0x0001d5b9, 0x00001bbf, 0x0001d5ba, 0x00001bc0, 0x0001d5bb, 0x00001bc1, 0x0001d5bc, 0x00001bc2, 0x0001d5bd, 0x00001bc3, 0x0001d5be, 0x00001bc4, 0x0001d5bf, 0x00001bc5, 0x0001d5c0, 0x00001bc6, 0x0001d5c1, 0x00001bc7, 0x0001d5c2, 0x00001bc8, 0x0001d5c3, 0x00001bc9, 0x0001d5c4, 0x00001bca, 0x0001d5c5, 0x00001bcb, 0x0001d5c6, 0x00001bcc, 0x0001d5c7, 0x00001bcd, 0x0001d5c8, 0x00001bce, 0x0001d5c9, 0x00001bcf, 0x0001d5ca, 0x00001bd0, 0x0001d5cb, 0x00001bd1, 0x0001d5cc, 0x00001bd2, 0x0001d5cd, 0x00001bd3, 0x0001d5ce, 0x00001bd4, 0x0001d5cf, 0x00001bd5, 0x0001d5d0, 0x00001bd6, 0x0001d5d1, 0x00001bd7, 0x0001d5d2, 0x00001bd8, 0x0001d5d3, 0x00001bd9, 0x0001d5d4, 0x00001bda, 0x0001d5d5, 0x00001bdb, 0x0001d5d6, 0x00001bdc, 0x0001d5d7, 0x00001bdd, 0x0001d5d8, 0x00001bde, 0x0001d5d9, 0x00001bdf, 0x0001d5da, 0x00001be0, 0x0001d5db, 0x00001be1, 0x0001d5dc, 0x00001be2, 0x0001d5dd, 0x00001be3, 0x0001d5de, 0x00001be4, 0x0001d5df, 0x00001be5, 0x0001d5e0, 0x00001be6, 0x0001d5e1, 0x00001be7, 0x0001d5e2, 0x00001be8, 0x0001d5e3, 0x00001be9, 0x0001d5e4, 0x00001bea, 0x0001d5e5, 0x00001beb, 0x0001d5e6, 0x00001bec, 0x0001d5e7, 0x00001bed, 0x0001d5e8, 0x00001bee, 0x0001d5e9, 0x00001bef, 0x0001d5ea, 0x00001bf0, 0x0001d5eb, 0x00001bf1, 0x0001d5ec, 0x00001bf2, 0x0001d5ed, 0x00001bf3, 0x0001d5ee, 0x00001bf4, 0x0001d5ef, 0x00001bf5, 0x0001d5f0, 0x00001bf6, 0x0001d5f1, 0x00001bf7, 0x0001d5f2, 0x00001bf8, 0x0001d5f3, 0x00001bf9, 0x0001d5f4, 0x00001bfa, 0x0001d5f5, 0x00001bfb, 0x0001d5f6, 0x00001bfc, 0x0001d5f7, 0x00001bfd, 0x0001d5f8, 0x00001bfe, 0x0001d5f9, 0x00001bff, 0x0001d5fa, 0x00001c00, 0x0001d5fb, 0x00001c01, 0x0001d5fc, 0x00001c02, 0x0001d5fd, 0x00001c03, 0x0001d5fe, 0x00001c04, 0x0001d5ff, 0x00001c05, 0x0001d600, 0x00001c06, 0x0001d601, 0x00001c07, 0x0001d602, 0x00001c08, 0x0001d603, 0x00001c09, 0x0001d604, 0x00001c0a, 0x0001d605, 0x00001c0b, 0x0001d606, 0x00001c0c, 0x0001d607, 0x00001c0d, 0x0001d608, 0x00001c0e, 0x0001d609, 0x00001c0f, 0x0001d60a, 0x00001c10, 0x0001d60b, 0x00001c11, 0x0001d60c, 0x00001c12, 0x0001d60d, 0x00001c13, 0x0001d60e, 0x00001c14, 0x0001d60f, 0x00001c15, 0x0001d610, 0x00001c16, 0x0001d611, 0x00001c17, 0x0001d612, 0x00001c18, 0x0001d613, 0x00001c19, 0x0001d614, 0x00001c1a, 0x0001d615, 0x00001c1b, 0x0001d616, 0x00001c1c, 0x0001d617, 0x00001c1d, 0x0001d618, 0x00001c1e, 0x0001d619, 0x00001c1f, 0x0001d61a, 0x00001c20, 0x0001d61b, 0x00001c21, 0x0001d61c, 0x00001c22, 0x0001d61d, 0x00001c23, 0x0001d61e, 0x00001c24, 0x0001d61f, 0x00001c25, 0x0001d620, 0x00001c26, 0x0001d621, 0x00001c27, 0x0001d622, 0x00001c28, 0x0001d623, 0x00001c29, 0x0001d624, 0x00001c2a, 0x0001d625, 0x00001c2b, 0x0001d626, 0x00001c2c, 0x0001d627, 0x00001c2d, 0x0001d628, 0x00001c2e, 0x0001d629, 0x00001c2f, 0x0001d62a, 0x00001c30, 0x0001d62b, 0x00001c31, 0x0001d62c, 0x00001c32, 0x0001d62d, 0x00001c33, 0x0001d62e, 0x00001c34, 0x0001d62f, 0x00001c35, 0x0001d630, 0x00001c36, 0x0001d631, 0x00001c37, 0x0001d632, 0x00001c38, 0x0001d633, 0x00001c39, 0x0001d634, 0x00001c3a, 0x0001d635, 0x00001c3b, 0x0001d636, 0x00001c3c, 0x0001d637, 0x00001c3d, 0x0001d638, 0x00001c3e, 0x0001d639, 0x00001c3f, 0x0001d63a, 0x00001c40, 0x0001d63b, 0x00001c41, 0x0001d63c, 0x00001c42, 0x0001d63d, 0x00001c43, 0x0001d63e, 0x00001c44, 0x0001d63f, 0x00001c45, 0x0001d640, 0x00001c46, 0x0001d641, 0x00001c47, 0x0001d642, 0x00001c48, 0x0001d643, 0x00001c49, 0x0001d644, 0x00001c4a, 0x0001d645, 0x00001c4b, 0x0001d646, 0x00001c4c, 0x0001d647, 0x00001c4d, 0x0001d648, 0x00001c4e, 0x0001d649, 0x00001c4f, 0x0001d64a, 0x00001c50, 0x0001d64b, 0x00001c51, 0x0001d64c, 0x00001c52, 0x0001d64d, 0x00001c53, 0x0001d64e, 0x00001c54, 0x0001d64f, 0x00001c55, 0x0001d650, 0x00001c56, 0x0001d651, 0x00001c57, 0x0001d652, 0x00001c58, 0x0001d653, 0x00001c59, 0x0001d654, 0x00001c5a, 0x0001d655, 0x00001c5b, 0x0001d656, 0x00001c5c, 0x0001d657, 0x00001c5d, 0x0001d658, 0x00001c5e, 0x0001d659, 0x00001c5f, 0x0001d65a, 0x00001c60, 0x0001d65b, 0x00001c61, 0x0001d65c, 0x00001c62, 0x0001d65d, 0x00001c63, 0x0001d65e, 0x00001c64, 0x0001d65f, 0x00001c65, 0x0001d660, 0x00001c66, 0x0001d661, 0x00001c67, 0x0001d662, 0x00001c68, 0x0001d663, 0x00001c69, 0x0001d664, 0x00001c6a, 0x0001d665, 0x00001c6b, 0x0001d666, 0x00001c6c, 0x0001d667, 0x00001c6d, 0x0001d668, 0x00001c6e, 0x0001d669, 0x00001c6f, 0x0001d66a, 0x00001c70, 0x0001d66b, 0x00001c71, 0x0001d66c, 0x00001c72, 0x0001d66d, 0x00001c73, 0x0001d66e, 0x00001c74, 0x0001d66f, 0x00001c75, 0x0001d670, 0x00001c76, 0x0001d671, 0x00001c77, 0x0001d672, 0x00001c78, 0x0001d673, 0x00001c79, 0x0001d674, 0x00001c7a, 0x0001d675, 0x00001c7b, 0x0001d676, 0x00001c7c, 0x0001d677, 0x00001c7d, 0x0001d678, 0x00001c7e, 0x0001d679, 0x00001c7f, 0x0001d67a, 0x00001c80, 0x0001d67b, 0x00001c81, 0x0001d67c, 0x00001c82, 0x0001d67d, 0x00001c83, 0x0001d67e, 0x00001c84, 0x0001d67f, 0x00001c85, 0x0001d680, 0x00001c86, 0x0001d681, 0x00001c87, 0x0001d682, 0x00001c88, 0x0001d683, 0x00001c89, 0x0001d684, 0x00001c8a, 0x0001d685, 0x00001c8b, 0x0001d686, 0x00001c8c, 0x0001d687, 0x00001c8d, 0x0001d688, 0x00001c8e, 0x0001d689, 0x00001c8f, 0x0001d68a, 0x00001c90, 0x0001d68b, 0x00001c91, 0x0001d68c, 0x00001c92, 0x0001d68d, 0x00001c93, 0x0001d68e, 0x00001c94, 0x0001d68f, 0x00001c95, 0x0001d690, 0x00001c96, 0x0001d691, 0x00001c97, 0x0001d692, 0x00001c98, 0x0001d693, 0x00001c99, 0x0001d694, 0x00001c9a, 0x0001d695, 0x00001c9b, 0x0001d696, 0x00001c9c, 0x0001d697, 0x00001c9d, 0x0001d698, 0x00001c9e, 0x0001d699, 0x00001c9f, 0x0001d69a, 0x00001ca0, 0x0001d69b, 0x00001ca1, 0x0001d69c, 0x00001ca2, 0x0001d69d, 0x00001ca3, 0x0001d69e, 0x00001ca4, 0x0001d69f, 0x00001ca5, 0x0001d6a0, 0x00001ca6, 0x0001d6a1, 0x00001ca7, 0x0001d6a2, 0x00001ca8, 0x0001d6a3, 0x00001ca9, 0x0001d6a8, 0x00001caa, 0x0001d6a9, 0x00001cab, 0x0001d6aa, 0x00001cac, 0x0001d6ab, 0x00001cad, 0x0001d6ac, 0x00001cae, 0x0001d6ad, 0x00001caf, 0x0001d6ae, 0x00001cb0, 0x0001d6af, 0x00001cb1, 0x0001d6b0, 0x00001cb2, 0x0001d6b1, 0x00001cb3, 0x0001d6b2, 0x00001cb4, 0x0001d6b3, 0x00001cb5, 0x0001d6b4, 0x00001cb6, 0x0001d6b5, 0x00001cb7, 0x0001d6b6, 0x00001cb8, 0x0001d6b7, 0x00001cb9, 0x0001d6b8, 0x00001cba, 0x0001d6b9, 0x00001cbb, 0x0001d6ba, 0x00001cbc, 0x0001d6bb, 0x00001cbd, 0x0001d6bc, 0x00001cbe, 0x0001d6bd, 0x00001cbf, 0x0001d6be, 0x00001cc0, 0x0001d6bf, 0x00001cc1, 0x0001d6c0, 0x00001cc2, 0x0001d6c1, 0x00001cc3, 0x0001d6c2, 0x00001cc4, 0x0001d6c3, 0x00001cc5, 0x0001d6c4, 0x00001cc6, 0x0001d6c5, 0x00001cc7, 0x0001d6c6, 0x00001cc8, 0x0001d6c7, 0x00001cc9, 0x0001d6c8, 0x00001cca, 0x0001d6c9, 0x00001ccb, 0x0001d6ca, 0x00001ccc, 0x0001d6cb, 0x00001ccd, 0x0001d6cc, 0x00001cce, 0x0001d6cd, 0x00001ccf, 0x0001d6ce, 0x00001cd0, 0x0001d6cf, 0x00001cd1, 0x0001d6d0, 0x00001cd2, 0x0001d6d1, 0x00001cd3, 0x0001d6d2, 0x00001cd4, 0x0001d6d3, 0x00001cd5, 0x0001d6d4, 0x00001cd6, 0x0001d6d5, 0x00001cd7, 0x0001d6d6, 0x00001cd8, 0x0001d6d7, 0x00001cd9, 0x0001d6d8, 0x00001cda, 0x0001d6d9, 0x00001cdb, 0x0001d6da, 0x00001cdc, 0x0001d6db, 0x00001cdd, 0x0001d6dc, 0x00001cde, 0x0001d6dd, 0x00001cdf, 0x0001d6de, 0x00001ce0, 0x0001d6df, 0x00001ce1, 0x0001d6e0, 0x00001ce2, 0x0001d6e1, 0x00001ce3, 0x0001d6e2, 0x00001ce4, 0x0001d6e3, 0x00001ce5, 0x0001d6e4, 0x00001ce6, 0x0001d6e5, 0x00001ce7, 0x0001d6e6, 0x00001ce8, 0x0001d6e7, 0x00001ce9, 0x0001d6e8, 0x00001cea, 0x0001d6e9, 0x00001ceb, 0x0001d6ea, 0x00001cec, 0x0001d6eb, 0x00001ced, 0x0001d6ec, 0x00001cee, 0x0001d6ed, 0x00001cef, 0x0001d6ee, 0x00001cf0, 0x0001d6ef, 0x00001cf1, 0x0001d6f0, 0x00001cf2, 0x0001d6f1, 0x00001cf3, 0x0001d6f2, 0x00001cf4, 0x0001d6f3, 0x00001cf5, 0x0001d6f4, 0x00001cf6, 0x0001d6f5, 0x00001cf7, 0x0001d6f6, 0x00001cf8, 0x0001d6f7, 0x00001cf9, 0x0001d6f8, 0x00001cfa, 0x0001d6f9, 0x00001cfb, 0x0001d6fa, 0x00001cfc, 0x0001d6fb, 0x00001cfd, 0x0001d6fc, 0x00001cfe, 0x0001d6fd, 0x00001cff, 0x0001d6fe, 0x00001d00, 0x0001d6ff, 0x00001d01, 0x0001d700, 0x00001d02, 0x0001d701, 0x00001d03, 0x0001d702, 0x00001d04, 0x0001d703, 0x00001d05, 0x0001d704, 0x00001d06, 0x0001d705, 0x00001d07, 0x0001d706, 0x00001d08, 0x0001d707, 0x00001d09, 0x0001d708, 0x00001d0a, 0x0001d709, 0x00001d0b, 0x0001d70a, 0x00001d0c, 0x0001d70b, 0x00001d0d, 0x0001d70c, 0x00001d0e, 0x0001d70d, 0x00001d0f, 0x0001d70e, 0x00001d10, 0x0001d70f, 0x00001d11, 0x0001d710, 0x00001d12, 0x0001d711, 0x00001d13, 0x0001d712, 0x00001d14, 0x0001d713, 0x00001d15, 0x0001d714, 0x00001d16, 0x0001d715, 0x00001d17, 0x0001d716, 0x00001d18, 0x0001d717, 0x00001d19, 0x0001d718, 0x00001d1a, 0x0001d719, 0x00001d1b, 0x0001d71a, 0x00001d1c, 0x0001d71b, 0x00001d1d, 0x0001d71c, 0x00001d1e, 0x0001d71d, 0x00001d1f, 0x0001d71e, 0x00001d20, 0x0001d71f, 0x00001d21, 0x0001d720, 0x00001d22, 0x0001d721, 0x00001d23, 0x0001d722, 0x00001d24, 0x0001d723, 0x00001d25, 0x0001d724, 0x00001d26, 0x0001d725, 0x00001d27, 0x0001d726, 0x00001d28, 0x0001d727, 0x00001d29, 0x0001d728, 0x00001d2a, 0x0001d729, 0x00001d2b, 0x0001d72a, 0x00001d2c, 0x0001d72b, 0x00001d2d, 0x0001d72c, 0x00001d2e, 0x0001d72d, 0x00001d2f, 0x0001d72e, 0x00001d30, 0x0001d72f, 0x00001d31, 0x0001d730, 0x00001d32, 0x0001d731, 0x00001d33, 0x0001d732, 0x00001d34, 0x0001d733, 0x00001d35, 0x0001d734, 0x00001d36, 0x0001d735, 0x00001d37, 0x0001d736, 0x00001d38, 0x0001d737, 0x00001d39, 0x0001d738, 0x00001d3a, 0x0001d739, 0x00001d3b, 0x0001d73a, 0x00001d3c, 0x0001d73b, 0x00001d3d, 0x0001d73c, 0x00001d3e, 0x0001d73d, 0x00001d3f, 0x0001d73e, 0x00001d40, 0x0001d73f, 0x00001d41, 0x0001d740, 0x00001d42, 0x0001d741, 0x00001d43, 0x0001d742, 0x00001d44, 0x0001d743, 0x00001d45, 0x0001d744, 0x00001d46, 0x0001d745, 0x00001d47, 0x0001d746, 0x00001d48, 0x0001d747, 0x00001d49, 0x0001d748, 0x00001d4a, 0x0001d749, 0x00001d4b, 0x0001d74a, 0x00001d4c, 0x0001d74b, 0x00001d4d, 0x0001d74c, 0x00001d4e, 0x0001d74d, 0x00001d4f, 0x0001d74e, 0x00001d50, 0x0001d74f, 0x00001d51, 0x0001d750, 0x00001d52, 0x0001d751, 0x00001d53, 0x0001d752, 0x00001d54, 0x0001d753, 0x00001d55, 0x0001d754, 0x00001d56, 0x0001d755, 0x00001d57, 0x0001d756, 0x00001d58, 0x0001d757, 0x00001d59, 0x0001d758, 0x00001d5a, 0x0001d759, 0x00001d5b, 0x0001d75a, 0x00001d5c, 0x0001d75b, 0x00001d5d, 0x0001d75c, 0x00001d5e, 0x0001d75d, 0x00001d5f, 0x0001d75e, 0x00001d60, 0x0001d75f, 0x00001d61, 0x0001d760, 0x00001d62, 0x0001d761, 0x00001d63, 0x0001d762, 0x00001d64, 0x0001d763, 0x00001d65, 0x0001d764, 0x00001d66, 0x0001d765, 0x00001d67, 0x0001d766, 0x00001d68, 0x0001d767, 0x00001d69, 0x0001d768, 0x00001d6a, 0x0001d769, 0x00001d6b, 0x0001d76a, 0x00001d6c, 0x0001d76b, 0x00001d6d, 0x0001d76c, 0x00001d6e, 0x0001d76d, 0x00001d6f, 0x0001d76e, 0x00001d70, 0x0001d76f, 0x00001d71, 0x0001d770, 0x00001d72, 0x0001d771, 0x00001d73, 0x0001d772, 0x00001d74, 0x0001d773, 0x00001d75, 0x0001d774, 0x00001d76, 0x0001d775, 0x00001d77, 0x0001d776, 0x00001d78, 0x0001d777, 0x00001d79, 0x0001d778, 0x00001d7a, 0x0001d779, 0x00001d7b, 0x0001d77a, 0x00001d7c, 0x0001d77b, 0x00001d7d, 0x0001d77c, 0x00001d7e, 0x0001d77d, 0x00001d7f, 0x0001d77e, 0x00001d80, 0x0001d77f, 0x00001d81, 0x0001d780, 0x00001d82, 0x0001d781, 0x00001d83, 0x0001d782, 0x00001d84, 0x0001d783, 0x00001d85, 0x0001d784, 0x00001d86, 0x0001d785, 0x00001d87, 0x0001d786, 0x00001d88, 0x0001d787, 0x00001d89, 0x0001d788, 0x00001d8a, 0x0001d789, 0x00001d8b, 0x0001d78a, 0x00001d8c, 0x0001d78b, 0x00001d8d, 0x0001d78c, 0x00001d8e, 0x0001d78d, 0x00001d8f, 0x0001d78e, 0x00001d90, 0x0001d78f, 0x00001d91, 0x0001d790, 0x00001d92, 0x0001d791, 0x00001d93, 0x0001d792, 0x00001d94, 0x0001d793, 0x00001d95, 0x0001d794, 0x00001d96, 0x0001d795, 0x00001d97, 0x0001d796, 0x00001d98, 0x0001d797, 0x00001d99, 0x0001d798, 0x00001d9a, 0x0001d799, 0x00001d9b, 0x0001d79a, 0x00001d9c, 0x0001d79b, 0x00001d9d, 0x0001d79c, 0x00001d9e, 0x0001d79d, 0x00001d9f, 0x0001d79e, 0x00001da0, 0x0001d79f, 0x00001da1, 0x0001d7a0, 0x00001da2, 0x0001d7a1, 0x00001da3, 0x0001d7a2, 0x00001da4, 0x0001d7a3, 0x00001da5, 0x0001d7a4, 0x00001da6, 0x0001d7a5, 0x00001da7, 0x0001d7a6, 0x00001da8, 0x0001d7a7, 0x00001da9, 0x0001d7a8, 0x00001daa, 0x0001d7a9, 0x00001dab, 0x0001d7aa, 0x00001dac, 0x0001d7ab, 0x00001dad, 0x0001d7ac, 0x00001dae, 0x0001d7ad, 0x00001daf, 0x0001d7ae, 0x00001db0, 0x0001d7af, 0x00001db1, 0x0001d7b0, 0x00001db2, 0x0001d7b1, 0x00001db3, 0x0001d7b2, 0x00001db4, 0x0001d7b3, 0x00001db5, 0x0001d7b4, 0x00001db6, 0x0001d7b5, 0x00001db7, 0x0001d7b6, 0x00001db8, 0x0001d7b7, 0x00001db9, 0x0001d7b8, 0x00001dba, 0x0001d7b9, 0x00001dbb, 0x0001d7ba, 0x00001dbc, 0x0001d7bb, 0x00001dbd, 0x0001d7bc, 0x00001dbe, 0x0001d7bd, 0x00001dbf, 0x0001d7be, 0x00001dc0, 0x0001d7bf, 0x00001dc1, 0x0001d7c0, 0x00001dc2, 0x0001d7c1, 0x00001dc3, 0x0001d7c2, 0x00001dc4, 0x0001d7c3, 0x00001dc5, 0x0001d7c4, 0x00001dc6, 0x0001d7c5, 0x00001dc7, 0x0001d7c6, 0x00001dc8, 0x0001d7c7, 0x00001dc9, 0x0001d7c8, 0x00001dca, 0x0001d7c9, 0x00001dcb, 0x0001d7ce, 0x00001dcc, 0x0001d7cf, 0x00001dcd, 0x0001d7d0, 0x00001dce, 0x0001d7d1, 0x00001dcf, 0x0001d7d2, 0x00001dd0, 0x0001d7d3, 0x00001dd1, 0x0001d7d4, 0x00001dd2, 0x0001d7d5, 0x00001dd3, 0x0001d7d6, 0x00001dd4, 0x0001d7d7, 0x00001dd5, 0x0001d7d8, 0x00001dd6, 0x0001d7d9, 0x00001dd7, 0x0001d7da, 0x00001dd8, 0x0001d7db, 0x00001dd9, 0x0001d7dc, 0x00001dda, 0x0001d7dd, 0x00001ddb, 0x0001d7de, 0x00001ddc, 0x0001d7df, 0x00001ddd, 0x0001d7e0, 0x00001dde, 0x0001d7e1, 0x00001ddf, 0x0001d7e2, 0x00001de0, 0x0001d7e3, 0x00001de1, 0x0001d7e4, 0x00001de2, 0x0001d7e5, 0x00001de3, 0x0001d7e6, 0x00001de4, 0x0001d7e7, 0x00001de5, 0x0001d7e8, 0x00001de6, 0x0001d7e9, 0x00001de7, 0x0001d7ea, 0x00001de8, 0x0001d7eb, 0x00001de9, 0x0001d7ec, 0x00001dea, 0x0001d7ed, 0x00001deb, 0x0001d7ee, 0x00001dec, 0x0001d7ef, 0x00001ded, 0x0001d7f0, 0x00001dee, 0x0001d7f1, 0x00001def, 0x0001d7f2, 0x00001df0, 0x0001d7f3, 0x00001df1, 0x0001d7f4, 0x00001df2, 0x0001d7f5, 0x00001df3, 0x0001d7f6, 0x00001df4, 0x0001d7f7, 0x00001df5, 0x0001d7f8, 0x00001df6, 0x0001d7f9, 0x00001df7, 0x0001d7fa, 0x00001df8, 0x0001d7fb, 0x00001df9, 0x0001d7fc, 0x00001dfa, 0x0001d7fd, 0x00001dfb, 0x0001d7fe, 0x00001dfc, 0x0001d7ff, 0x00001dfd, 0x0002f800, 0x00001dfe, 0x0002f801, 0x00001dff, 0x0002f802, 0x00001e00, 0x0002f803, 0x00001e01, 0x0002f804, 0x00001e02, 0x0002f805, 0x00001e03, 0x0002f806, 0x00001e04, 0x0002f807, 0x00001e05, 0x0002f808, 0x00001e06, 0x0002f809, 0x00001e07, 0x0002f80a, 0x00001e08, 0x0002f80b, 0x00001e09, 0x0002f80c, 0x00001e0a, 0x0002f80d, 0x00001e0b, 0x0002f80e, 0x00001e0c, 0x0002f80f, 0x00001e0d, 0x0002f810, 0x00001e0e, 0x0002f811, 0x00001e0f, 0x0002f812, 0x00001e10, 0x0002f813, 0x00001e11, 0x0002f814, 0x00001e12, 0x0002f815, 0x00001e13, 0x0002f816, 0x00001e14, 0x0002f817, 0x00001e15, 0x0002f818, 0x00001e16, 0x0002f819, 0x00001e17, 0x0002f81a, 0x00001e18, 0x0002f81b, 0x00001e19, 0x0002f81c, 0x00001e1a, 0x0002f81d, 0x00001e1b, 0x0002f81e, 0x00001e1c, 0x0002f81f, 0x00001e1d, 0x0002f820, 0x00001e1e, 0x0002f821, 0x00001e1f, 0x0002f822, 0x00001e20, 0x0002f823, 0x00001e21, 0x0002f824, 0x00001e22, 0x0002f825, 0x00001e23, 0x0002f826, 0x00001e24, 0x0002f827, 0x00001e25, 0x0002f828, 0x00001e26, 0x0002f829, 0x00001e27, 0x0002f82a, 0x00001e28, 0x0002f82b, 0x00001e29, 0x0002f82c, 0x00001e2a, 0x0002f82d, 0x00001e2b, 0x0002f82e, 0x00001e2c, 0x0002f82f, 0x00001e2d, 0x0002f830, 0x00001e2e, 0x0002f831, 0x00001e2f, 0x0002f832, 0x00001e30, 0x0002f833, 0x00001e31, 0x0002f834, 0x00001e32, 0x0002f835, 0x00001e33, 0x0002f836, 0x00001e34, 0x0002f837, 0x00001e35, 0x0002f838, 0x00001e36, 0x0002f839, 0x00001e37, 0x0002f83a, 0x00001e38, 0x0002f83b, 0x00001e39, 0x0002f83c, 0x00001e3a, 0x0002f83d, 0x00001e3b, 0x0002f83e, 0x00001e3c, 0x0002f83f, 0x00001e3d, 0x0002f840, 0x00001e3e, 0x0002f841, 0x00001e3f, 0x0002f842, 0x00001e40, 0x0002f843, 0x00001e41, 0x0002f844, 0x00001e42, 0x0002f845, 0x00001e43, 0x0002f846, 0x00001e44, 0x0002f847, 0x00001e45, 0x0002f848, 0x00001e46, 0x0002f849, 0x00001e47, 0x0002f84a, 0x00001e48, 0x0002f84b, 0x00001e49, 0x0002f84c, 0x00001e4a, 0x0002f84d, 0x00001e4b, 0x0002f84e, 0x00001e4c, 0x0002f84f, 0x00001e4d, 0x0002f850, 0x00001e4e, 0x0002f851, 0x00001e4f, 0x0002f852, 0x00001e50, 0x0002f853, 0x00001e51, 0x0002f854, 0x00001e52, 0x0002f855, 0x00001e53, 0x0002f856, 0x00001e54, 0x0002f857, 0x00001e55, 0x0002f858, 0x00001e56, 0x0002f859, 0x00001e57, 0x0002f85a, 0x00001e58, 0x0002f85b, 0x00001e59, 0x0002f85c, 0x00001e5a, 0x0002f85d, 0x00001e5b, 0x0002f85e, 0x00001e5c, 0x0002f85f, 0x00001e5d, 0x0002f860, 0x00001e5e, 0x0002f861, 0x00001e5f, 0x0002f862, 0x00001e60, 0x0002f863, 0x00001e61, 0x0002f864, 0x00001e62, 0x0002f865, 0x00001e63, 0x0002f866, 0x00001e64, 0x0002f867, 0x00001e65, 0x0002f868, 0x00001e66, 0x0002f869, 0x00001e67, 0x0002f86a, 0x00001e68, 0x0002f86b, 0x00001e69, 0x0002f86c, 0x00001e6a, 0x0002f86d, 0x00001e6b, 0x0002f86e, 0x00001e6c, 0x0002f86f, 0x00001e6d, 0x0002f870, 0x00001e6e, 0x0002f871, 0x00001e6f, 0x0002f872, 0x00001e70, 0x0002f873, 0x00001e71, 0x0002f874, 0x00001e72, 0x0002f875, 0x00001e73, 0x0002f876, 0x00001e74, 0x0002f877, 0x00001e75, 0x0002f878, 0x00001e76, 0x0002f879, 0x00001e77, 0x0002f87a, 0x00001e78, 0x0002f87b, 0x00001e79, 0x0002f87c, 0x00001e7a, 0x0002f87d, 0x00001e7b, 0x0002f87e, 0x00001e7c, 0x0002f87f, 0x00001e7d, 0x0002f880, 0x00001e7e, 0x0002f881, 0x00001e7f, 0x0002f882, 0x00001e80, 0x0002f883, 0x00001e81, 0x0002f884, 0x00001e82, 0x0002f885, 0x00001e83, 0x0002f886, 0x00001e84, 0x0002f887, 0x00001e85, 0x0002f888, 0x00001e86, 0x0002f889, 0x00001e87, 0x0002f88a, 0x00001e88, 0x0002f88b, 0x00001e89, 0x0002f88c, 0x00001e8a, 0x0002f88d, 0x00001e8b, 0x0002f88e, 0x00001e8c, 0x0002f88f, 0x00001e8d, 0x0002f890, 0x00001e8e, 0x0002f891, 0x00001e8f, 0x0002f892, 0x00001e90, 0x0002f893, 0x00001e91, 0x0002f894, 0x00001e92, 0x0002f895, 0x00001e93, 0x0002f896, 0x00001e94, 0x0002f897, 0x00001e95, 0x0002f898, 0x00001e96, 0x0002f899, 0x00001e97, 0x0002f89a, 0x00001e98, 0x0002f89b, 0x00001e99, 0x0002f89c, 0x00001e9a, 0x0002f89d, 0x00001e9b, 0x0002f89e, 0x00001e9c, 0x0002f89f, 0x00001e9d, 0x0002f8a0, 0x00001e9e, 0x0002f8a1, 0x00001e9f, 0x0002f8a2, 0x00001ea0, 0x0002f8a3, 0x00001ea1, 0x0002f8a4, 0x00001ea2, 0x0002f8a5, 0x00001ea3, 0x0002f8a6, 0x00001ea4, 0x0002f8a7, 0x00001ea5, 0x0002f8a8, 0x00001ea6, 0x0002f8a9, 0x00001ea7, 0x0002f8aa, 0x00001ea8, 0x0002f8ab, 0x00001ea9, 0x0002f8ac, 0x00001eaa, 0x0002f8ad, 0x00001eab, 0x0002f8ae, 0x00001eac, 0x0002f8af, 0x00001ead, 0x0002f8b0, 0x00001eae, 0x0002f8b1, 0x00001eaf, 0x0002f8b2, 0x00001eb0, 0x0002f8b3, 0x00001eb1, 0x0002f8b4, 0x00001eb2, 0x0002f8b5, 0x00001eb3, 0x0002f8b6, 0x00001eb4, 0x0002f8b7, 0x00001eb5, 0x0002f8b8, 0x00001eb6, 0x0002f8b9, 0x00001eb7, 0x0002f8ba, 0x00001eb8, 0x0002f8bb, 0x00001eb9, 0x0002f8bc, 0x00001eba, 0x0002f8bd, 0x00001ebb, 0x0002f8be, 0x00001ebc, 0x0002f8bf, 0x00001ebd, 0x0002f8c0, 0x00001ebe, 0x0002f8c1, 0x00001ebf, 0x0002f8c2, 0x00001ec0, 0x0002f8c3, 0x00001ec1, 0x0002f8c4, 0x00001ec2, 0x0002f8c5, 0x00001ec3, 0x0002f8c6, 0x00001ec4, 0x0002f8c7, 0x00001ec5, 0x0002f8c8, 0x00001ec6, 0x0002f8c9, 0x00001ec7, 0x0002f8ca, 0x00001ec8, 0x0002f8cb, 0x00001ec9, 0x0002f8cc, 0x00001eca, 0x0002f8cd, 0x00001ecb, 0x0002f8ce, 0x00001ecc, 0x0002f8cf, 0x00001ecd, 0x0002f8d0, 0x00001ece, 0x0002f8d1, 0x00001ecf, 0x0002f8d2, 0x00001ed0, 0x0002f8d3, 0x00001ed1, 0x0002f8d4, 0x00001ed2, 0x0002f8d5, 0x00001ed3, 0x0002f8d6, 0x00001ed4, 0x0002f8d7, 0x00001ed5, 0x0002f8d8, 0x00001ed6, 0x0002f8d9, 0x00001ed7, 0x0002f8da, 0x00001ed8, 0x0002f8db, 0x00001ed9, 0x0002f8dc, 0x00001eda, 0x0002f8dd, 0x00001edb, 0x0002f8de, 0x00001edc, 0x0002f8df, 0x00001edd, 0x0002f8e0, 0x00001ede, 0x0002f8e1, 0x00001edf, 0x0002f8e2, 0x00001ee0, 0x0002f8e3, 0x00001ee1, 0x0002f8e4, 0x00001ee2, 0x0002f8e5, 0x00001ee3, 0x0002f8e6, 0x00001ee4, 0x0002f8e7, 0x00001ee5, 0x0002f8e8, 0x00001ee6, 0x0002f8e9, 0x00001ee7, 0x0002f8ea, 0x00001ee8, 0x0002f8eb, 0x00001ee9, 0x0002f8ec, 0x00001eea, 0x0002f8ed, 0x00001eeb, 0x0002f8ee, 0x00001eec, 0x0002f8ef, 0x00001eed, 0x0002f8f0, 0x00001eee, 0x0002f8f1, 0x00001eef, 0x0002f8f2, 0x00001ef0, 0x0002f8f3, 0x00001ef1, 0x0002f8f4, 0x00001ef2, 0x0002f8f5, 0x00001ef3, 0x0002f8f6, 0x00001ef4, 0x0002f8f7, 0x00001ef5, 0x0002f8f8, 0x00001ef6, 0x0002f8f9, 0x00001ef7, 0x0002f8fa, 0x00001ef8, 0x0002f8fb, 0x00001ef9, 0x0002f8fc, 0x00001efa, 0x0002f8fd, 0x00001efb, 0x0002f8fe, 0x00001efc, 0x0002f8ff, 0x00001efd, 0x0002f900, 0x00001efe, 0x0002f901, 0x00001eff, 0x0002f902, 0x00001f00, 0x0002f903, 0x00001f01, 0x0002f904, 0x00001f02, 0x0002f905, 0x00001f03, 0x0002f906, 0x00001f04, 0x0002f907, 0x00001f05, 0x0002f908, 0x00001f06, 0x0002f909, 0x00001f07, 0x0002f90a, 0x00001f08, 0x0002f90b, 0x00001f09, 0x0002f90c, 0x00001f0a, 0x0002f90d, 0x00001f0b, 0x0002f90e, 0x00001f0c, 0x0002f90f, 0x00001f0d, 0x0002f910, 0x00001f0e, 0x0002f911, 0x00001f0f, 0x0002f912, 0x00001f10, 0x0002f913, 0x00001f11, 0x0002f914, 0x00001f12, 0x0002f915, 0x00001f13, 0x0002f916, 0x00001f14, 0x0002f917, 0x00001f15, 0x0002f918, 0x00001f16, 0x0002f919, 0x00001f17, 0x0002f91a, 0x00001f18, 0x0002f91b, 0x00001f19, 0x0002f91c, 0x00001f1a, 0x0002f91d, 0x00001f1b, 0x0002f91e, 0x00001f1c, 0x0002f91f, 0x00001f1d, 0x0002f920, 0x00001f1e, 0x0002f921, 0x00001f1f, 0x0002f922, 0x00001f20, 0x0002f923, 0x00001f21, 0x0002f924, 0x00001f22, 0x0002f925, 0x00001f23, 0x0002f926, 0x00001f24, 0x0002f927, 0x00001f25, 0x0002f928, 0x00001f26, 0x0002f929, 0x00001f27, 0x0002f92a, 0x00001f28, 0x0002f92b, 0x00001f29, 0x0002f92c, 0x00001f2a, 0x0002f92d, 0x00001f2b, 0x0002f92e, 0x00001f2c, 0x0002f92f, 0x00001f2d, 0x0002f930, 0x00001f2e, 0x0002f931, 0x00001f2f, 0x0002f932, 0x00001f30, 0x0002f933, 0x00001f31, 0x0002f934, 0x00001f32, 0x0002f935, 0x00001f33, 0x0002f936, 0x00001f34, 0x0002f937, 0x00001f35, 0x0002f938, 0x00001f36, 0x0002f939, 0x00001f37, 0x0002f93a, 0x00001f38, 0x0002f93b, 0x00001f39, 0x0002f93c, 0x00001f3a, 0x0002f93d, 0x00001f3b, 0x0002f93e, 0x00001f3c, 0x0002f93f, 0x00001f3d, 0x0002f940, 0x00001f3e, 0x0002f941, 0x00001f3f, 0x0002f942, 0x00001f40, 0x0002f943, 0x00001f41, 0x0002f944, 0x00001f42, 0x0002f945, 0x00001f43, 0x0002f946, 0x00001f44, 0x0002f947, 0x00001f45, 0x0002f948, 0x00001f46, 0x0002f949, 0x00001f47, 0x0002f94a, 0x00001f48, 0x0002f94b, 0x00001f49, 0x0002f94c, 0x00001f4a, 0x0002f94d, 0x00001f4b, 0x0002f94e, 0x00001f4c, 0x0002f94f, 0x00001f4d, 0x0002f950, 0x00001f4e, 0x0002f951, 0x00001f4f, 0x0002f952, 0x00001f50, 0x0002f953, 0x00001f51, 0x0002f954, 0x00001f52, 0x0002f955, 0x00001f53, 0x0002f956, 0x00001f54, 0x0002f957, 0x00001f55, 0x0002f958, 0x00001f56, 0x0002f959, 0x00001f57, 0x0002f95a, 0x00001f58, 0x0002f95b, 0x00001f59, 0x0002f95c, 0x00001f5a, 0x0002f95d, 0x00001f5b, 0x0002f95e, 0x00001f5c, 0x0002f95f, 0x00001f5d, 0x0002f960, 0x00001f5e, 0x0002f961, 0x00001f5f, 0x0002f962, 0x00001f60, 0x0002f963, 0x00001f61, 0x0002f964, 0x00001f62, 0x0002f965, 0x00001f63, 0x0002f966, 0x00001f64, 0x0002f967, 0x00001f65, 0x0002f968, 0x00001f66, 0x0002f969, 0x00001f67, 0x0002f96a, 0x00001f68, 0x0002f96b, 0x00001f69, 0x0002f96c, 0x00001f6a, 0x0002f96d, 0x00001f6b, 0x0002f96e, 0x00001f6c, 0x0002f96f, 0x00001f6d, 0x0002f970, 0x00001f6e, 0x0002f971, 0x00001f6f, 0x0002f972, 0x00001f70, 0x0002f973, 0x00001f71, 0x0002f974, 0x00001f72, 0x0002f975, 0x00001f73, 0x0002f976, 0x00001f74, 0x0002f977, 0x00001f75, 0x0002f978, 0x00001f76, 0x0002f979, 0x00001f77, 0x0002f97a, 0x00001f78, 0x0002f97b, 0x00001f79, 0x0002f97c, 0x00001f7a, 0x0002f97d, 0x00001f7b, 0x0002f97e, 0x00001f7c, 0x0002f97f, 0x00001f7d, 0x0002f980, 0x00001f7e, 0x0002f981, 0x00001f7f, 0x0002f982, 0x00001f80, 0x0002f983, 0x00001f81, 0x0002f984, 0x00001f82, 0x0002f985, 0x00001f83, 0x0002f986, 0x00001f84, 0x0002f987, 0x00001f85, 0x0002f988, 0x00001f86, 0x0002f989, 0x00001f87, 0x0002f98a, 0x00001f88, 0x0002f98b, 0x00001f89, 0x0002f98c, 0x00001f8a, 0x0002f98d, 0x00001f8b, 0x0002f98e, 0x00001f8c, 0x0002f98f, 0x00001f8d, 0x0002f990, 0x00001f8e, 0x0002f991, 0x00001f8f, 0x0002f992, 0x00001f90, 0x0002f993, 0x00001f91, 0x0002f994, 0x00001f92, 0x0002f995, 0x00001f93, 0x0002f996, 0x00001f94, 0x0002f997, 0x00001f95, 0x0002f998, 0x00001f96, 0x0002f999, 0x00001f97, 0x0002f99a, 0x00001f98, 0x0002f99b, 0x00001f99, 0x0002f99c, 0x00001f9a, 0x0002f99d, 0x00001f9b, 0x0002f99e, 0x00001f9c, 0x0002f99f, 0x00001f9d, 0x0002f9a0, 0x00001f9e, 0x0002f9a1, 0x00001f9f, 0x0002f9a2, 0x00001fa0, 0x0002f9a3, 0x00001fa1, 0x0002f9a4, 0x00001fa2, 0x0002f9a5, 0x00001fa3, 0x0002f9a6, 0x00001fa4, 0x0002f9a7, 0x00001fa5, 0x0002f9a8, 0x00001fa6, 0x0002f9a9, 0x00001fa7, 0x0002f9aa, 0x00001fa8, 0x0002f9ab, 0x00001fa9, 0x0002f9ac, 0x00001faa, 0x0002f9ad, 0x00001fab, 0x0002f9ae, 0x00001fac, 0x0002f9af, 0x00001fad, 0x0002f9b0, 0x00001fae, 0x0002f9b1, 0x00001faf, 0x0002f9b2, 0x00001fb0, 0x0002f9b3, 0x00001fb1, 0x0002f9b4, 0x00001fb2, 0x0002f9b5, 0x00001fb3, 0x0002f9b6, 0x00001fb4, 0x0002f9b7, 0x00001fb5, 0x0002f9b8, 0x00001fb6, 0x0002f9b9, 0x00001fb7, 0x0002f9ba, 0x00001fb8, 0x0002f9bb, 0x00001fb9, 0x0002f9bc, 0x00001fba, 0x0002f9bd, 0x00001fbb, 0x0002f9be, 0x00001fbc, 0x0002f9bf, 0x00001fbd, 0x0002f9c0, 0x00001fbe, 0x0002f9c1, 0x00001fbf, 0x0002f9c2, 0x00001fc0, 0x0002f9c3, 0x00001fc1, 0x0002f9c4, 0x00001fc2, 0x0002f9c5, 0x00001fc3, 0x0002f9c6, 0x00001fc4, 0x0002f9c7, 0x00001fc5, 0x0002f9c8, 0x00001fc6, 0x0002f9c9, 0x00001fc7, 0x0002f9ca, 0x00001fc8, 0x0002f9cb, 0x00001fc9, 0x0002f9cc, 0x00001fca, 0x0002f9cd, 0x00001fcb, 0x0002f9ce, 0x00001fcc, 0x0002f9cf, 0x00001fcd, 0x0002f9d0, 0x00001fce, 0x0002f9d1, 0x00001fcf, 0x0002f9d2, 0x00001fd0, 0x0002f9d3, 0x00001fd1, 0x0002f9d4, 0x00001fd2, 0x0002f9d5, 0x00001fd3, 0x0002f9d6, 0x00001fd4, 0x0002f9d7, 0x00001fd5, 0x0002f9d8, 0x00001fd6, 0x0002f9d9, 0x00001fd7, 0x0002f9da, 0x00001fd8, 0x0002f9db, 0x00001fd9, 0x0002f9dc, 0x00001fda, 0x0002f9dd, 0x00001fdb, 0x0002f9de, 0x00001fdc, 0x0002f9df, 0x00001fdd, 0x0002f9e0, 0x00001fde, 0x0002f9e1, 0x00001fdf, 0x0002f9e2, 0x00001fe0, 0x0002f9e3, 0x00001fe1, 0x0002f9e4, 0x00001fe2, 0x0002f9e5, 0x00001fe3, 0x0002f9e6, 0x00001fe4, 0x0002f9e7, 0x00001fe5, 0x0002f9e8, 0x00001fe6, 0x0002f9e9, 0x00001fe7, 0x0002f9ea, 0x00001fe8, 0x0002f9eb, 0x00001fe9, 0x0002f9ec, 0x00001fea, 0x0002f9ed, 0x00001feb, 0x0002f9ee, 0x00001fec, 0x0002f9ef, 0x00001fed, 0x0002f9f0, 0x00001fee, 0x0002f9f1, 0x00001fef, 0x0002f9f2, 0x00001ff0, 0x0002f9f3, 0x00001ff1, 0x0002f9f4, 0x00001ff2, 0x0002f9f5, 0x00001ff3, 0x0002f9f6, 0x00001ff4, 0x0002f9f7, 0x00001ff5, 0x0002f9f8, 0x00001ff6, 0x0002f9f9, 0x00001ff7, 0x0002f9fa, 0x00001ff8, 0x0002f9fb, 0x00001ff9, 0x0002f9fc, 0x00001ffa, 0x0002f9fd, 0x00001ffb, 0x0002f9fe, 0x00001ffc, 0x0002f9ff, 0x00001ffd, 0x0002fa00, 0x00001ffe, 0x0002fa01, 0x00001fff, 0x0002fa02, 0x00002000, 0x0002fa03, 0x00002001, 0x0002fa04, 0x00002002, 0x0002fa05, 0x00002003, 0x0002fa06, 0x00002004, 0x0002fa07, 0x00002005, 0x0002fa08, 0x00002006, 0x0002fa09, 0x00002007, 0x0002fa0a, 0x00002008, 0x0002fa0b, 0x00002009, 0x0002fa0c, 0x0000200a, 0x0002fa0d, 0x0000200b, 0x0002fa0e, 0x0000200c, 0x0002fa0f, 0x0000200d, 0x0002fa10, 0x0000200e, 0x0002fa11, 0x0000200f, 0x0002fa12, 0x00002010, 0x0002fa13, 0x00002011, 0x0002fa14, 0x00002012, 0x0002fa15, 0x00002013, 0x0002fa16, 0x00002014, 0x0002fa17, 0x00002015, 0x0002fa18, 0x00002016, 0x0002fa19, 0x00002017, 0x0002fa1a, 0x00002018, 0x0002fa1b, 0x00002019, 0x0002fa1c, 0x0000201a, 0x0002fa1d, 0x0000201b, 0x0000201c }; static const ac_uint4 _uckdcmp_decomp[] = { 0x00000020, 0x00000020, 0x00000308, 0x00000061, 0x00000020, 0x00000304, 0x00000032, 0x00000033, 0x00000020, 0x00000301, 0x000003bc, 0x00000020, 0x00000327, 0x00000031, 0x0000006f, 0x00000031, 0x00002044, 0x00000034, 0x00000031, 0x00002044, 0x00000032, 0x00000033, 0x00002044, 0x00000034, 0x00000041, 0x00000300, 0x00000041, 0x00000301, 0x00000041, 0x00000302, 0x00000041, 0x00000303, 0x00000041, 0x00000308, 0x00000041, 0x0000030a, 0x00000043, 0x00000327, 0x00000045, 0x00000300, 0x00000045, 0x00000301, 0x00000045, 0x00000302, 0x00000045, 0x00000308, 0x00000049, 0x00000300, 0x00000049, 0x00000301, 0x00000049, 0x00000302, 0x00000049, 0x00000308, 0x0000004e, 0x00000303, 0x0000004f, 0x00000300, 0x0000004f, 0x00000301, 0x0000004f, 0x00000302, 0x0000004f, 0x00000303, 0x0000004f, 0x00000308, 0x00000055, 0x00000300, 0x00000055, 0x00000301, 0x00000055, 0x00000302, 0x00000055, 0x00000308, 0x00000059, 0x00000301, 0x00000061, 0x00000300, 0x00000061, 0x00000301, 0x00000061, 0x00000302, 0x00000061, 0x00000303, 0x00000061, 0x00000308, 0x00000061, 0x0000030a, 0x00000063, 0x00000327, 0x00000065, 0x00000300, 0x00000065, 0x00000301, 0x00000065, 0x00000302, 0x00000065, 0x00000308, 0x00000069, 0x00000300, 0x00000069, 0x00000301, 0x00000069, 0x00000302, 0x00000069, 0x00000308, 0x0000006e, 0x00000303, 0x0000006f, 0x00000300, 0x0000006f, 0x00000301, 0x0000006f, 0x00000302, 0x0000006f, 0x00000303, 0x0000006f, 0x00000308, 0x00000075, 0x00000300, 0x00000075, 0x00000301, 0x00000075, 0x00000302, 0x00000075, 0x00000308, 0x00000079, 0x00000301, 0x00000079, 0x00000308, 0x00000041, 0x00000304, 0x00000061, 0x00000304, 0x00000041, 0x00000306, 0x00000061, 0x00000306, 0x00000041, 0x00000328, 0x00000061, 0x00000328, 0x00000043, 0x00000301, 0x00000063, 0x00000301, 0x00000043, 0x00000302, 0x00000063, 0x00000302, 0x00000043, 0x00000307, 0x00000063, 0x00000307, 0x00000043, 0x0000030c, 0x00000063, 0x0000030c, 0x00000044, 0x0000030c, 0x00000064, 0x0000030c, 0x00000045, 0x00000304, 0x00000065, 0x00000304, 0x00000045, 0x00000306, 0x00000065, 0x00000306, 0x00000045, 0x00000307, 0x00000065, 0x00000307, 0x00000045, 0x00000328, 0x00000065, 0x00000328, 0x00000045, 0x0000030c, 0x00000065, 0x0000030c, 0x00000047, 0x00000302, 0x00000067, 0x00000302, 0x00000047, 0x00000306, 0x00000067, 0x00000306, 0x00000047, 0x00000307, 0x00000067, 0x00000307, 0x00000047, 0x00000327, 0x00000067, 0x00000327, 0x00000048, 0x00000302, 0x00000068, 0x00000302, 0x00000049, 0x00000303, 0x00000069, 0x00000303, 0x00000049, 0x00000304, 0x00000069, 0x00000304, 0x00000049, 0x00000306, 0x00000069, 0x00000306, 0x00000049, 0x00000328, 0x00000069, 0x00000328, 0x00000049, 0x00000307, 0x00000049, 0x0000004a, 0x00000069, 0x0000006a, 0x0000004a, 0x00000302, 0x0000006a, 0x00000302, 0x0000004b, 0x00000327, 0x0000006b, 0x00000327, 0x0000004c, 0x00000301, 0x0000006c, 0x00000301, 0x0000004c, 0x00000327, 0x0000006c, 0x00000327, 0x0000004c, 0x0000030c, 0x0000006c, 0x0000030c, 0x0000004c, 0x000000b7, 0x0000006c, 0x000000b7, 0x0000004e, 0x00000301, 0x0000006e, 0x00000301, 0x0000004e, 0x00000327, 0x0000006e, 0x00000327, 0x0000004e, 0x0000030c, 0x0000006e, 0x0000030c, 0x000002bc, 0x0000006e, 0x0000004f, 0x00000304, 0x0000006f, 0x00000304, 0x0000004f, 0x00000306, 0x0000006f, 0x00000306, 0x0000004f, 0x0000030b, 0x0000006f, 0x0000030b, 0x00000052, 0x00000301, 0x00000072, 0x00000301, 0x00000052, 0x00000327, 0x00000072, 0x00000327, 0x00000052, 0x0000030c, 0x00000072, 0x0000030c, 0x00000053, 0x00000301, 0x00000073, 0x00000301, 0x00000053, 0x00000302, 0x00000073, 0x00000302, 0x00000053, 0x00000327, 0x00000073, 0x00000327, 0x00000053, 0x0000030c, 0x00000073, 0x0000030c, 0x00000054, 0x00000327, 0x00000074, 0x00000327, 0x00000054, 0x0000030c, 0x00000074, 0x0000030c, 0x00000055, 0x00000303, 0x00000075, 0x00000303, 0x00000055, 0x00000304, 0x00000075, 0x00000304, 0x00000055, 0x00000306, 0x00000075, 0x00000306, 0x00000055, 0x0000030a, 0x00000075, 0x0000030a, 0x00000055, 0x0000030b, 0x00000075, 0x0000030b, 0x00000055, 0x00000328, 0x00000075, 0x00000328, 0x00000057, 0x00000302, 0x00000077, 0x00000302, 0x00000059, 0x00000302, 0x00000079, 0x00000302, 0x00000059, 0x00000308, 0x0000005a, 0x00000301, 0x0000007a, 0x00000301, 0x0000005a, 0x00000307, 0x0000007a, 0x00000307, 0x0000005a, 0x0000030c, 0x0000007a, 0x0000030c, 0x00000073, 0x0000004f, 0x0000031b, 0x0000006f, 0x0000031b, 0x00000055, 0x0000031b, 0x00000075, 0x0000031b, 0x00000044, 0x0000005a, 0x0000030c, 0x00000044, 0x0000007a, 0x0000030c, 0x00000064, 0x0000007a, 0x0000030c, 0x0000004c, 0x0000004a, 0x0000004c, 0x0000006a, 0x0000006c, 0x0000006a, 0x0000004e, 0x0000004a, 0x0000004e, 0x0000006a, 0x0000006e, 0x0000006a, 0x00000041, 0x0000030c, 0x00000061, 0x0000030c, 0x00000049, 0x0000030c, 0x00000069, 0x0000030c, 0x0000004f, 0x0000030c, 0x0000006f, 0x0000030c, 0x00000055, 0x0000030c, 0x00000075, 0x0000030c, 0x00000055, 0x00000308, 0x00000304, 0x00000075, 0x00000308, 0x00000304, 0x00000055, 0x00000308, 0x00000301, 0x00000075, 0x00000308, 0x00000301, 0x00000055, 0x00000308, 0x0000030c, 0x00000075, 0x00000308, 0x0000030c, 0x00000055, 0x00000308, 0x00000300, 0x00000075, 0x00000308, 0x00000300, 0x00000041, 0x00000308, 0x00000304, 0x00000061, 0x00000308, 0x00000304, 0x00000041, 0x00000307, 0x00000304, 0x00000061, 0x00000307, 0x00000304, 0x000000c6, 0x00000304, 0x000000e6, 0x00000304, 0x00000047, 0x0000030c, 0x00000067, 0x0000030c, 0x0000004b, 0x0000030c, 0x0000006b, 0x0000030c, 0x0000004f, 0x00000328, 0x0000006f, 0x00000328, 0x0000004f, 0x00000328, 0x00000304, 0x0000006f, 0x00000328, 0x00000304, 0x000001b7, 0x0000030c, 0x00000292, 0x0000030c, 0x0000006a, 0x0000030c, 0x00000044, 0x0000005a, 0x00000044, 0x0000007a, 0x00000064, 0x0000007a, 0x00000047, 0x00000301, 0x00000067, 0x00000301, 0x0000004e, 0x00000300, 0x0000006e, 0x00000300, 0x00000041, 0x0000030a, 0x00000301, 0x00000061, 0x0000030a, 0x00000301, 0x000000c6, 0x00000301, 0x000000e6, 0x00000301, 0x000000d8, 0x00000301, 0x000000f8, 0x00000301, 0x00000041, 0x0000030f, 0x00000061, 0x0000030f, 0x00000041, 0x00000311, 0x00000061, 0x00000311, 0x00000045, 0x0000030f, 0x00000065, 0x0000030f, 0x00000045, 0x00000311, 0x00000065, 0x00000311, 0x00000049, 0x0000030f, 0x00000069, 0x0000030f, 0x00000049, 0x00000311, 0x00000069, 0x00000311, 0x0000004f, 0x0000030f, 0x0000006f, 0x0000030f, 0x0000004f, 0x00000311, 0x0000006f, 0x00000311, 0x00000052, 0x0000030f, 0x00000072, 0x0000030f, 0x00000052, 0x00000311, 0x00000072, 0x00000311, 0x00000055, 0x0000030f, 0x00000075, 0x0000030f, 0x00000055, 0x00000311, 0x00000075, 0x00000311, 0x00000053, 0x00000326, 0x00000073, 0x00000326, 0x00000054, 0x00000326, 0x00000074, 0x00000326, 0x00000048, 0x0000030c, 0x00000068, 0x0000030c, 0x00000041, 0x00000307, 0x00000061, 0x00000307, 0x00000045, 0x00000327, 0x00000065, 0x00000327, 0x0000004f, 0x00000308, 0x00000304, 0x0000006f, 0x00000308, 0x00000304, 0x0000004f, 0x00000303, 0x00000304, 0x0000006f, 0x00000303, 0x00000304, 0x0000004f, 0x00000307, 0x0000006f, 0x00000307, 0x0000004f, 0x00000307, 0x00000304, 0x0000006f, 0x00000307, 0x00000304, 0x00000059, 0x00000304, 0x00000079, 0x00000304, 0x00000068, 0x00000266, 0x0000006a, 0x00000072, 0x00000279, 0x0000027b, 0x00000281, 0x00000077, 0x00000079, 0x00000020, 0x00000306, 0x00000020, 0x00000307, 0x00000020, 0x0000030a, 0x00000020, 0x00000328, 0x00000020, 0x00000303, 0x00000020, 0x0000030b, 0x00000263, 0x0000006c, 0x00000073, 0x00000078, 0x00000295, 0x00000300, 0x00000301, 0x00000313, 0x00000308, 0x00000301, 0x000002b9, 0x00000020, 0x00000345, 0x0000003b, 0x00000020, 0x00000301, 0x00000020, 0x00000308, 0x00000301, 0x00000391, 0x00000301, 0x000000b7, 0x00000395, 0x00000301, 0x00000397, 0x00000301, 0x00000399, 0x00000301, 0x0000039f, 0x00000301, 0x000003a5, 0x00000301, 0x000003a9, 0x00000301, 0x000003b9, 0x00000308, 0x00000301, 0x00000399, 0x00000308, 0x000003a5, 0x00000308, 0x000003b1, 0x00000301, 0x000003b5, 0x00000301, 0x000003b7, 0x00000301, 0x000003b9, 0x00000301, 0x000003c5, 0x00000308, 0x00000301, 0x000003b9, 0x00000308, 0x000003c5, 0x00000308, 0x000003bf, 0x00000301, 0x000003c5, 0x00000301, 0x000003c9, 0x00000301, 0x000003b2, 0x000003b8, 0x000003a5, 0x000003a5, 0x00000301, 0x000003a5, 0x00000308, 0x000003c6, 0x000003c0, 0x000003ba, 0x000003c1, 0x000003c2, 0x00000398, 0x000003b5, 0x00000415, 0x00000300, 0x00000415, 0x00000308, 0x00000413, 0x00000301, 0x00000406, 0x00000308, 0x0000041a, 0x00000301, 0x00000418, 0x00000300, 0x00000423, 0x00000306, 0x00000418, 0x00000306, 0x00000438, 0x00000306, 0x00000435, 0x00000300, 0x00000435, 0x00000308, 0x00000433, 0x00000301, 0x00000456, 0x00000308, 0x0000043a, 0x00000301, 0x00000438, 0x00000300, 0x00000443, 0x00000306, 0x00000474, 0x0000030f, 0x00000475, 0x0000030f, 0x00000416, 0x00000306, 0x00000436, 0x00000306, 0x00000410, 0x00000306, 0x00000430, 0x00000306, 0x00000410, 0x00000308, 0x00000430, 0x00000308, 0x00000415, 0x00000306, 0x00000435, 0x00000306, 0x000004d8, 0x00000308, 0x000004d9, 0x00000308, 0x00000416, 0x00000308, 0x00000436, 0x00000308, 0x00000417, 0x00000308, 0x00000437, 0x00000308, 0x00000418, 0x00000304, 0x00000438, 0x00000304, 0x00000418, 0x00000308, 0x00000438, 0x00000308, 0x0000041e, 0x00000308, 0x0000043e, 0x00000308, 0x000004e8, 0x00000308, 0x000004e9, 0x00000308, 0x0000042d, 0x00000308, 0x0000044d, 0x00000308, 0x00000423, 0x00000304, 0x00000443, 0x00000304, 0x00000423, 0x00000308, 0x00000443, 0x00000308, 0x00000423, 0x0000030b, 0x00000443, 0x0000030b, 0x00000427, 0x00000308, 0x00000447, 0x00000308, 0x0000042b, 0x00000308, 0x0000044b, 0x00000308, 0x00000565, 0x00000582, 0x00000627, 0x00000653, 0x00000627, 0x00000654, 0x00000648, 0x00000654, 0x00000627, 0x00000655, 0x0000064a, 0x00000654, 0x00000627, 0x00000674, 0x00000648, 0x00000674, 0x000006c7, 0x00000674, 0x0000064a, 0x00000674, 0x000006d5, 0x00000654, 0x000006c1, 0x00000654, 0x000006d2, 0x00000654, 0x00000928, 0x0000093c, 0x00000930, 0x0000093c, 0x00000933, 0x0000093c, 0x00000915, 0x0000093c, 0x00000916, 0x0000093c, 0x00000917, 0x0000093c, 0x0000091c, 0x0000093c, 0x00000921, 0x0000093c, 0x00000922, 0x0000093c, 0x0000092b, 0x0000093c, 0x0000092f, 0x0000093c, 0x000009c7, 0x000009be, 0x000009c7, 0x000009d7, 0x000009a1, 0x000009bc, 0x000009a2, 0x000009bc, 0x000009af, 0x000009bc, 0x00000a32, 0x00000a3c, 0x00000a38, 0x00000a3c, 0x00000a16, 0x00000a3c, 0x00000a17, 0x00000a3c, 0x00000a1c, 0x00000a3c, 0x00000a2b, 0x00000a3c, 0x00000b47, 0x00000b56, 0x00000b47, 0x00000b3e, 0x00000b47, 0x00000b57, 0x00000b21, 0x00000b3c, 0x00000b22, 0x00000b3c, 0x00000b92, 0x00000bd7, 0x00000bc6, 0x00000bbe, 0x00000bc7, 0x00000bbe, 0x00000bc6, 0x00000bd7, 0x00000c46, 0x00000c56, 0x00000cbf, 0x00000cd5, 0x00000cc6, 0x00000cd5, 0x00000cc6, 0x00000cd6, 0x00000cc6, 0x00000cc2, 0x00000cc6, 0x00000cc2, 0x00000cd5, 0x00000d46, 0x00000d3e, 0x00000d47, 0x00000d3e, 0x00000d46, 0x00000d57, 0x00000dd9, 0x00000dca, 0x00000dd9, 0x00000dcf, 0x00000dd9, 0x00000dcf, 0x00000dca, 0x00000dd9, 0x00000ddf, 0x00000e4d, 0x00000e32, 0x00000ecd, 0x00000eb2, 0x00000eab, 0x00000e99, 0x00000eab, 0x00000ea1, 0x00000f0b, 0x00000f42, 0x00000fb7, 0x00000f4c, 0x00000fb7, 0x00000f51, 0x00000fb7, 0x00000f56, 0x00000fb7, 0x00000f5b, 0x00000fb7, 0x00000f40, 0x00000fb5, 0x00000f71, 0x00000f72, 0x00000f71, 0x00000f74, 0x00000fb2, 0x00000f80, 0x00000fb2, 0x00000f71, 0x00000f80, 0x00000fb3, 0x00000f80, 0x00000fb3, 0x00000f71, 0x00000f80, 0x00000f71, 0x00000f80, 0x00000f92, 0x00000fb7, 0x00000f9c, 0x00000fb7, 0x00000fa1, 0x00000fb7, 0x00000fa6, 0x00000fb7, 0x00000fab, 0x00000fb7, 0x00000f90, 0x00000fb5, 0x00001025, 0x0000102e, 0x00000041, 0x00000325, 0x00000061, 0x00000325, 0x00000042, 0x00000307, 0x00000062, 0x00000307, 0x00000042, 0x00000323, 0x00000062, 0x00000323, 0x00000042, 0x00000331, 0x00000062, 0x00000331, 0x00000043, 0x00000327, 0x00000301, 0x00000063, 0x00000327, 0x00000301, 0x00000044, 0x00000307, 0x00000064, 0x00000307, 0x00000044, 0x00000323, 0x00000064, 0x00000323, 0x00000044, 0x00000331, 0x00000064, 0x00000331, 0x00000044, 0x00000327, 0x00000064, 0x00000327, 0x00000044, 0x0000032d, 0x00000064, 0x0000032d, 0x00000045, 0x00000304, 0x00000300, 0x00000065, 0x00000304, 0x00000300, 0x00000045, 0x00000304, 0x00000301, 0x00000065, 0x00000304, 0x00000301, 0x00000045, 0x0000032d, 0x00000065, 0x0000032d, 0x00000045, 0x00000330, 0x00000065, 0x00000330, 0x00000045, 0x00000327, 0x00000306, 0x00000065, 0x00000327, 0x00000306, 0x00000046, 0x00000307, 0x00000066, 0x00000307, 0x00000047, 0x00000304, 0x00000067, 0x00000304, 0x00000048, 0x00000307, 0x00000068, 0x00000307, 0x00000048, 0x00000323, 0x00000068, 0x00000323, 0x00000048, 0x00000308, 0x00000068, 0x00000308, 0x00000048, 0x00000327, 0x00000068, 0x00000327, 0x00000048, 0x0000032e, 0x00000068, 0x0000032e, 0x00000049, 0x00000330, 0x00000069, 0x00000330, 0x00000049, 0x00000308, 0x00000301, 0x00000069, 0x00000308, 0x00000301, 0x0000004b, 0x00000301, 0x0000006b, 0x00000301, 0x0000004b, 0x00000323, 0x0000006b, 0x00000323, 0x0000004b, 0x00000331, 0x0000006b, 0x00000331, 0x0000004c, 0x00000323, 0x0000006c, 0x00000323, 0x0000004c, 0x00000323, 0x00000304, 0x0000006c, 0x00000323, 0x00000304, 0x0000004c, 0x00000331, 0x0000006c, 0x00000331, 0x0000004c, 0x0000032d, 0x0000006c, 0x0000032d, 0x0000004d, 0x00000301, 0x0000006d, 0x00000301, 0x0000004d, 0x00000307, 0x0000006d, 0x00000307, 0x0000004d, 0x00000323, 0x0000006d, 0x00000323, 0x0000004e, 0x00000307, 0x0000006e, 0x00000307, 0x0000004e, 0x00000323, 0x0000006e, 0x00000323, 0x0000004e, 0x00000331, 0x0000006e, 0x00000331, 0x0000004e, 0x0000032d, 0x0000006e, 0x0000032d, 0x0000004f, 0x00000303, 0x00000301, 0x0000006f, 0x00000303, 0x00000301, 0x0000004f, 0x00000303, 0x00000308, 0x0000006f, 0x00000303, 0x00000308, 0x0000004f, 0x00000304, 0x00000300, 0x0000006f, 0x00000304, 0x00000300, 0x0000004f, 0x00000304, 0x00000301, 0x0000006f, 0x00000304, 0x00000301, 0x00000050, 0x00000301, 0x00000070, 0x00000301, 0x00000050, 0x00000307, 0x00000070, 0x00000307, 0x00000052, 0x00000307, 0x00000072, 0x00000307, 0x00000052, 0x00000323, 0x00000072, 0x00000323, 0x00000052, 0x00000323, 0x00000304, 0x00000072, 0x00000323, 0x00000304, 0x00000052, 0x00000331, 0x00000072, 0x00000331, 0x00000053, 0x00000307, 0x00000073, 0x00000307, 0x00000053, 0x00000323, 0x00000073, 0x00000323, 0x00000053, 0x00000301, 0x00000307, 0x00000073, 0x00000301, 0x00000307, 0x00000053, 0x0000030c, 0x00000307, 0x00000073, 0x0000030c, 0x00000307, 0x00000053, 0x00000323, 0x00000307, 0x00000073, 0x00000323, 0x00000307, 0x00000054, 0x00000307, 0x00000074, 0x00000307, 0x00000054, 0x00000323, 0x00000074, 0x00000323, 0x00000054, 0x00000331, 0x00000074, 0x00000331, 0x00000054, 0x0000032d, 0x00000074, 0x0000032d, 0x00000055, 0x00000324, 0x00000075, 0x00000324, 0x00000055, 0x00000330, 0x00000075, 0x00000330, 0x00000055, 0x0000032d, 0x00000075, 0x0000032d, 0x00000055, 0x00000303, 0x00000301, 0x00000075, 0x00000303, 0x00000301, 0x00000055, 0x00000304, 0x00000308, 0x00000075, 0x00000304, 0x00000308, 0x00000056, 0x00000303, 0x00000076, 0x00000303, 0x00000056, 0x00000323, 0x00000076, 0x00000323, 0x00000057, 0x00000300, 0x00000077, 0x00000300, 0x00000057, 0x00000301, 0x00000077, 0x00000301, 0x00000057, 0x00000308, 0x00000077, 0x00000308, 0x00000057, 0x00000307, 0x00000077, 0x00000307, 0x00000057, 0x00000323, 0x00000077, 0x00000323, 0x00000058, 0x00000307, 0x00000078, 0x00000307, 0x00000058, 0x00000308, 0x00000078, 0x00000308, 0x00000059, 0x00000307, 0x00000079, 0x00000307, 0x0000005a, 0x00000302, 0x0000007a, 0x00000302, 0x0000005a, 0x00000323, 0x0000007a, 0x00000323, 0x0000005a, 0x00000331, 0x0000007a, 0x00000331, 0x00000068, 0x00000331, 0x00000074, 0x00000308, 0x00000077, 0x0000030a, 0x00000079, 0x0000030a, 0x00000061, 0x000002be, 0x00000073, 0x00000307, 0x00000041, 0x00000323, 0x00000061, 0x00000323, 0x00000041, 0x00000309, 0x00000061, 0x00000309, 0x00000041, 0x00000302, 0x00000301, 0x00000061, 0x00000302, 0x00000301, 0x00000041, 0x00000302, 0x00000300, 0x00000061, 0x00000302, 0x00000300, 0x00000041, 0x00000302, 0x00000309, 0x00000061, 0x00000302, 0x00000309, 0x00000041, 0x00000302, 0x00000303, 0x00000061, 0x00000302, 0x00000303, 0x00000041, 0x00000323, 0x00000302, 0x00000061, 0x00000323, 0x00000302, 0x00000041, 0x00000306, 0x00000301, 0x00000061, 0x00000306, 0x00000301, 0x00000041, 0x00000306, 0x00000300, 0x00000061, 0x00000306, 0x00000300, 0x00000041, 0x00000306, 0x00000309, 0x00000061, 0x00000306, 0x00000309, 0x00000041, 0x00000306, 0x00000303, 0x00000061, 0x00000306, 0x00000303, 0x00000041, 0x00000323, 0x00000306, 0x00000061, 0x00000323, 0x00000306, 0x00000045, 0x00000323, 0x00000065, 0x00000323, 0x00000045, 0x00000309, 0x00000065, 0x00000309, 0x00000045, 0x00000303, 0x00000065, 0x00000303, 0x00000045, 0x00000302, 0x00000301, 0x00000065, 0x00000302, 0x00000301, 0x00000045, 0x00000302, 0x00000300, 0x00000065, 0x00000302, 0x00000300, 0x00000045, 0x00000302, 0x00000309, 0x00000065, 0x00000302, 0x00000309, 0x00000045, 0x00000302, 0x00000303, 0x00000065, 0x00000302, 0x00000303, 0x00000045, 0x00000323, 0x00000302, 0x00000065, 0x00000323, 0x00000302, 0x00000049, 0x00000309, 0x00000069, 0x00000309, 0x00000049, 0x00000323, 0x00000069, 0x00000323, 0x0000004f, 0x00000323, 0x0000006f, 0x00000323, 0x0000004f, 0x00000309, 0x0000006f, 0x00000309, 0x0000004f, 0x00000302, 0x00000301, 0x0000006f, 0x00000302, 0x00000301, 0x0000004f, 0x00000302, 0x00000300, 0x0000006f, 0x00000302, 0x00000300, 0x0000004f, 0x00000302, 0x00000309, 0x0000006f, 0x00000302, 0x00000309, 0x0000004f, 0x00000302, 0x00000303, 0x0000006f, 0x00000302, 0x00000303, 0x0000004f, 0x00000323, 0x00000302, 0x0000006f, 0x00000323, 0x00000302, 0x0000004f, 0x0000031b, 0x00000301, 0x0000006f, 0x0000031b, 0x00000301, 0x0000004f, 0x0000031b, 0x00000300, 0x0000006f, 0x0000031b, 0x00000300, 0x0000004f, 0x0000031b, 0x00000309, 0x0000006f, 0x0000031b, 0x00000309, 0x0000004f, 0x0000031b, 0x00000303, 0x0000006f, 0x0000031b, 0x00000303, 0x0000004f, 0x0000031b, 0x00000323, 0x0000006f, 0x0000031b, 0x00000323, 0x00000055, 0x00000323, 0x00000075, 0x00000323, 0x00000055, 0x00000309, 0x00000075, 0x00000309, 0x00000055, 0x0000031b, 0x00000301, 0x00000075, 0x0000031b, 0x00000301, 0x00000055, 0x0000031b, 0x00000300, 0x00000075, 0x0000031b, 0x00000300, 0x00000055, 0x0000031b, 0x00000309, 0x00000075, 0x0000031b, 0x00000309, 0x00000055, 0x0000031b, 0x00000303, 0x00000075, 0x0000031b, 0x00000303, 0x00000055, 0x0000031b, 0x00000323, 0x00000075, 0x0000031b, 0x00000323, 0x00000059, 0x00000300, 0x00000079, 0x00000300, 0x00000059, 0x00000323, 0x00000079, 0x00000323, 0x00000059, 0x00000309, 0x00000079, 0x00000309, 0x00000059, 0x00000303, 0x00000079, 0x00000303, 0x000003b1, 0x00000313, 0x000003b1, 0x00000314, 0x000003b1, 0x00000313, 0x00000300, 0x000003b1, 0x00000314, 0x00000300, 0x000003b1, 0x00000313, 0x00000301, 0x000003b1, 0x00000314, 0x00000301, 0x000003b1, 0x00000313, 0x00000342, 0x000003b1, 0x00000314, 0x00000342, 0x00000391, 0x00000313, 0x00000391, 0x00000314, 0x00000391, 0x00000313, 0x00000300, 0x00000391, 0x00000314, 0x00000300, 0x00000391, 0x00000313, 0x00000301, 0x00000391, 0x00000314, 0x00000301, 0x00000391, 0x00000313, 0x00000342, 0x00000391, 0x00000314, 0x00000342, 0x000003b5, 0x00000313, 0x000003b5, 0x00000314, 0x000003b5, 0x00000313, 0x00000300, 0x000003b5, 0x00000314, 0x00000300, 0x000003b5, 0x00000313, 0x00000301, 0x000003b5, 0x00000314, 0x00000301, 0x00000395, 0x00000313, 0x00000395, 0x00000314, 0x00000395, 0x00000313, 0x00000300, 0x00000395, 0x00000314, 0x00000300, 0x00000395, 0x00000313, 0x00000301, 0x00000395, 0x00000314, 0x00000301, 0x000003b7, 0x00000313, 0x000003b7, 0x00000314, 0x000003b7, 0x00000313, 0x00000300, 0x000003b7, 0x00000314, 0x00000300, 0x000003b7, 0x00000313, 0x00000301, 0x000003b7, 0x00000314, 0x00000301, 0x000003b7, 0x00000313, 0x00000342, 0x000003b7, 0x00000314, 0x00000342, 0x00000397, 0x00000313, 0x00000397, 0x00000314, 0x00000397, 0x00000313, 0x00000300, 0x00000397, 0x00000314, 0x00000300, 0x00000397, 0x00000313, 0x00000301, 0x00000397, 0x00000314, 0x00000301, 0x00000397, 0x00000313, 0x00000342, 0x00000397, 0x00000314, 0x00000342, 0x000003b9, 0x00000313, 0x000003b9, 0x00000314, 0x000003b9, 0x00000313, 0x00000300, 0x000003b9, 0x00000314, 0x00000300, 0x000003b9, 0x00000313, 0x00000301, 0x000003b9, 0x00000314, 0x00000301, 0x000003b9, 0x00000313, 0x00000342, 0x000003b9, 0x00000314, 0x00000342, 0x00000399, 0x00000313, 0x00000399, 0x00000314, 0x00000399, 0x00000313, 0x00000300, 0x00000399, 0x00000314, 0x00000300, 0x00000399, 0x00000313, 0x00000301, 0x00000399, 0x00000314, 0x00000301, 0x00000399, 0x00000313, 0x00000342, 0x00000399, 0x00000314, 0x00000342, 0x000003bf, 0x00000313, 0x000003bf, 0x00000314, 0x000003bf, 0x00000313, 0x00000300, 0x000003bf, 0x00000314, 0x00000300, 0x000003bf, 0x00000313, 0x00000301, 0x000003bf, 0x00000314, 0x00000301, 0x0000039f, 0x00000313, 0x0000039f, 0x00000314, 0x0000039f, 0x00000313, 0x00000300, 0x0000039f, 0x00000314, 0x00000300, 0x0000039f, 0x00000313, 0x00000301, 0x0000039f, 0x00000314, 0x00000301, 0x000003c5, 0x00000313, 0x000003c5, 0x00000314, 0x000003c5, 0x00000313, 0x00000300, 0x000003c5, 0x00000314, 0x00000300, 0x000003c5, 0x00000313, 0x00000301, 0x000003c5, 0x00000314, 0x00000301, 0x000003c5, 0x00000313, 0x00000342, 0x000003c5, 0x00000314, 0x00000342, 0x000003a5, 0x00000314, 0x000003a5, 0x00000314, 0x00000300, 0x000003a5, 0x00000314, 0x00000301, 0x000003a5, 0x00000314, 0x00000342, 0x000003c9, 0x00000313, 0x000003c9, 0x00000314, 0x000003c9, 0x00000313, 0x00000300, 0x000003c9, 0x00000314, 0x00000300, 0x000003c9, 0x00000313, 0x00000301, 0x000003c9, 0x00000314, 0x00000301, 0x000003c9, 0x00000313, 0x00000342, 0x000003c9, 0x00000314, 0x00000342, 0x000003a9, 0x00000313, 0x000003a9, 0x00000314, 0x000003a9, 0x00000313, 0x00000300, 0x000003a9, 0x00000314, 0x00000300, 0x000003a9, 0x00000313, 0x00000301, 0x000003a9, 0x00000314, 0x00000301, 0x000003a9, 0x00000313, 0x00000342, 0x000003a9, 0x00000314, 0x00000342, 0x000003b1, 0x00000300, 0x000003b1, 0x00000301, 0x000003b5, 0x00000300, 0x000003b5, 0x00000301, 0x000003b7, 0x00000300, 0x000003b7, 0x00000301, 0x000003b9, 0x00000300, 0x000003b9, 0x00000301, 0x000003bf, 0x00000300, 0x000003bf, 0x00000301, 0x000003c5, 0x00000300, 0x000003c5, 0x00000301, 0x000003c9, 0x00000300, 0x000003c9, 0x00000301, 0x000003b1, 0x00000313, 0x00000345, 0x000003b1, 0x00000314, 0x00000345, 0x000003b1, 0x00000313, 0x00000300, 0x00000345, 0x000003b1, 0x00000314, 0x00000300, 0x00000345, 0x000003b1, 0x00000313, 0x00000301, 0x00000345, 0x000003b1, 0x00000314, 0x00000301, 0x00000345, 0x000003b1, 0x00000313, 0x00000342, 0x00000345, 0x000003b1, 0x00000314, 0x00000342, 0x00000345, 0x00000391, 0x00000313, 0x00000345, 0x00000391, 0x00000314, 0x00000345, 0x00000391, 0x00000313, 0x00000300, 0x00000345, 0x00000391, 0x00000314, 0x00000300, 0x00000345, 0x00000391, 0x00000313, 0x00000301, 0x00000345, 0x00000391, 0x00000314, 0x00000301, 0x00000345, 0x00000391, 0x00000313, 0x00000342, 0x00000345, 0x00000391, 0x00000314, 0x00000342, 0x00000345, 0x000003b7, 0x00000313, 0x00000345, 0x000003b7, 0x00000314, 0x00000345, 0x000003b7, 0x00000313, 0x00000300, 0x00000345, 0x000003b7, 0x00000314, 0x00000300, 0x00000345, 0x000003b7, 0x00000313, 0x00000301, 0x00000345, 0x000003b7, 0x00000314, 0x00000301, 0x00000345, 0x000003b7, 0x00000313, 0x00000342, 0x00000345, 0x000003b7, 0x00000314, 0x00000342, 0x00000345, 0x00000397, 0x00000313, 0x00000345, 0x00000397, 0x00000314, 0x00000345, 0x00000397, 0x00000313, 0x00000300, 0x00000345, 0x00000397, 0x00000314, 0x00000300, 0x00000345, 0x00000397, 0x00000313, 0x00000301, 0x00000345, 0x00000397, 0x00000314, 0x00000301, 0x00000345, 0x00000397, 0x00000313, 0x00000342, 0x00000345, 0x00000397, 0x00000314, 0x00000342, 0x00000345, 0x000003c9, 0x00000313, 0x00000345, 0x000003c9, 0x00000314, 0x00000345, 0x000003c9, 0x00000313, 0x00000300, 0x00000345, 0x000003c9, 0x00000314, 0x00000300, 0x00000345, 0x000003c9, 0x00000313, 0x00000301, 0x00000345, 0x000003c9, 0x00000314, 0x00000301, 0x00000345, 0x000003c9, 0x00000313, 0x00000342, 0x00000345, 0x000003c9, 0x00000314, 0x00000342, 0x00000345, 0x000003a9, 0x00000313, 0x00000345, 0x000003a9, 0x00000314, 0x00000345, 0x000003a9, 0x00000313, 0x00000300, 0x00000345, 0x000003a9, 0x00000314, 0x00000300, 0x00000345, 0x000003a9, 0x00000313, 0x00000301, 0x00000345, 0x000003a9, 0x00000314, 0x00000301, 0x00000345, 0x000003a9, 0x00000313, 0x00000342, 0x00000345, 0x000003a9, 0x00000314, 0x00000342, 0x00000345, 0x000003b1, 0x00000306, 0x000003b1, 0x00000304, 0x000003b1, 0x00000300, 0x00000345, 0x000003b1, 0x00000345, 0x000003b1, 0x00000301, 0x00000345, 0x000003b1, 0x00000342, 0x000003b1, 0x00000342, 0x00000345, 0x00000391, 0x00000306, 0x00000391, 0x00000304, 0x00000391, 0x00000300, 0x00000391, 0x00000301, 0x00000391, 0x00000345, 0x00000020, 0x00000313, 0x000003b9, 0x00000020, 0x00000313, 0x00000020, 0x00000342, 0x00000020, 0x00000308, 0x00000342, 0x000003b7, 0x00000300, 0x00000345, 0x000003b7, 0x00000345, 0x000003b7, 0x00000301, 0x00000345, 0x000003b7, 0x00000342, 0x000003b7, 0x00000342, 0x00000345, 0x00000395, 0x00000300, 0x00000395, 0x00000301, 0x00000397, 0x00000300, 0x00000397, 0x00000301, 0x00000397, 0x00000345, 0x00000020, 0x00000313, 0x00000300, 0x00000020, 0x00000313, 0x00000301, 0x00000020, 0x00000313, 0x00000342, 0x000003b9, 0x00000306, 0x000003b9, 0x00000304, 0x000003b9, 0x00000308, 0x00000300, 0x000003b9, 0x00000308, 0x00000301, 0x000003b9, 0x00000342, 0x000003b9, 0x00000308, 0x00000342, 0x00000399, 0x00000306, 0x00000399, 0x00000304, 0x00000399, 0x00000300, 0x00000399, 0x00000301, 0x00000020, 0x00000314, 0x00000300, 0x00000020, 0x00000314, 0x00000301, 0x00000020, 0x00000314, 0x00000342, 0x000003c5, 0x00000306, 0x000003c5, 0x00000304, 0x000003c5, 0x00000308, 0x00000300, 0x000003c5, 0x00000308, 0x00000301, 0x000003c1, 0x00000313, 0x000003c1, 0x00000314, 0x000003c5, 0x00000342, 0x000003c5, 0x00000308, 0x00000342, 0x000003a5, 0x00000306, 0x000003a5, 0x00000304, 0x000003a5, 0x00000300, 0x000003a5, 0x00000301, 0x000003a1, 0x00000314, 0x00000020, 0x00000308, 0x00000300, 0x00000020, 0x00000308, 0x00000301, 0x00000060, 0x000003c9, 0x00000300, 0x00000345, 0x000003c9, 0x00000345, 0x000003c9, 0x00000301, 0x00000345, 0x000003c9, 0x00000342, 0x000003c9, 0x00000342, 0x00000345, 0x0000039f, 0x00000300, 0x0000039f, 0x00000301, 0x000003a9, 0x00000300, 0x000003a9, 0x00000301, 0x000003a9, 0x00000345, 0x00000020, 0x00000301, 0x00000020, 0x00000314, 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00002010, 0x00000020, 0x00000333, 0x0000002e, 0x0000002e, 0x0000002e, 0x0000002e, 0x0000002e, 0x0000002e, 0x00000020, 0x00002032, 0x00002032, 0x00002032, 0x00002032, 0x00002032, 0x00002035, 0x00002035, 0x00002035, 0x00002035, 0x00002035, 0x00000021, 0x00000021, 0x00000020, 0x00000305, 0x0000003f, 0x0000003f, 0x0000003f, 0x00000021, 0x00000021, 0x0000003f, 0x00002032, 0x00002032, 0x00002032, 0x00002032, 0x00000020, 0x00000030, 0x00000069, 0x00000034, 0x00000035, 0x00000036, 0x00000037, 0x00000038, 0x00000039, 0x0000002b, 0x00002212, 0x0000003d, 0x00000028, 0x00000029, 0x0000006e, 0x00000030, 0x00000031, 0x00000032, 0x00000033, 0x00000034, 0x00000035, 0x00000036, 0x00000037, 0x00000038, 0x00000039, 0x0000002b, 0x00002212, 0x0000003d, 0x00000028, 0x00000029, 0x00000052, 0x00000073, 0x00000061, 0x0000002f, 0x00000063, 0x00000061, 0x0000002f, 0x00000073, 0x00000043, 0x000000b0, 0x00000043, 0x00000063, 0x0000002f, 0x0000006f, 0x00000063, 0x0000002f, 0x00000075, 0x00000190, 0x000000b0, 0x00000046, 0x00000067, 0x00000048, 0x00000048, 0x00000048, 0x00000068, 0x00000127, 0x00000049, 0x00000049, 0x0000004c, 0x0000006c, 0x0000004e, 0x0000004e, 0x0000006f, 0x00000050, 0x00000051, 0x00000052, 0x00000052, 0x00000052, 0x00000053, 0x0000004d, 0x00000054, 0x00000045, 0x0000004c, 0x00000054, 0x0000004d, 0x0000005a, 0x000003a9, 0x0000005a, 0x0000004b, 0x00000041, 0x0000030a, 0x00000042, 0x00000043, 0x00000065, 0x00000045, 0x00000046, 0x0000004d, 0x0000006f, 0x000005d0, 0x000005d1, 0x000005d2, 0x000005d3, 0x00000069, 0x000003b3, 0x00000393, 0x000003a0, 0x00002211, 0x00000044, 0x00000064, 0x00000065, 0x00000069, 0x0000006a, 0x00000031, 0x00002044, 0x00000033, 0x00000032, 0x00002044, 0x00000033, 0x00000031, 0x00002044, 0x00000035, 0x00000032, 0x00002044, 0x00000035, 0x00000033, 0x00002044, 0x00000035, 0x00000034, 0x00002044, 0x00000035, 0x00000031, 0x00002044, 0x00000036, 0x00000035, 0x00002044, 0x00000036, 0x00000031, 0x00002044, 0x00000038, 0x00000033, 0x00002044, 0x00000038, 0x00000035, 0x00002044, 0x00000038, 0x00000037, 0x00002044, 0x00000038, 0x00000031, 0x00002044, 0x00000049, 0x00000049, 0x00000049, 0x00000049, 0x00000049, 0x00000049, 0x00000049, 0x00000056, 0x00000056, 0x00000056, 0x00000049, 0x00000056, 0x00000049, 0x00000049, 0x00000056, 0x00000049, 0x00000049, 0x00000049, 0x00000049, 0x00000058, 0x00000058, 0x00000058, 0x00000049, 0x00000058, 0x00000049, 0x00000049, 0x0000004c, 0x00000043, 0x00000044, 0x0000004d, 0x00000069, 0x00000069, 0x00000069, 0x00000069, 0x00000069, 0x00000069, 0x00000069, 0x00000076, 0x00000076, 0x00000076, 0x00000069, 0x00000076, 0x00000069, 0x00000069, 0x00000076, 0x00000069, 0x00000069, 0x00000069, 0x00000069, 0x00000078, 0x00000078, 0x00000078, 0x00000069, 0x00000078, 0x00000069, 0x00000069, 0x0000006c, 0x00000063, 0x00000064, 0x0000006d, 0x00002190, 0x00000338, 0x00002192, 0x00000338, 0x00002194, 0x00000338, 0x000021d0, 0x00000338, 0x000021d4, 0x00000338, 0x000021d2, 0x00000338, 0x00002203, 0x00000338, 0x00002208, 0x00000338, 0x0000220b, 0x00000338, 0x00002223, 0x00000338, 0x00002225, 0x00000338, 0x0000222b, 0x0000222b, 0x0000222b, 0x0000222b, 0x0000222b, 0x0000222e, 0x0000222e, 0x0000222e, 0x0000222e, 0x0000222e, 0x0000223c, 0x00000338, 0x00002243, 0x00000338, 0x00002245, 0x00000338, 0x00002248, 0x00000338, 0x0000003d, 0x00000338, 0x00002261, 0x00000338, 0x0000224d, 0x00000338, 0x0000003c, 0x00000338, 0x0000003e, 0x00000338, 0x00002264, 0x00000338, 0x00002265, 0x00000338, 0x00002272, 0x00000338, 0x00002273, 0x00000338, 0x00002276, 0x00000338, 0x00002277, 0x00000338, 0x0000227a, 0x00000338, 0x0000227b, 0x00000338, 0x00002282, 0x00000338, 0x00002283, 0x00000338, 0x00002286, 0x00000338, 0x00002287, 0x00000338, 0x000022a2, 0x00000338, 0x000022a8, 0x00000338, 0x000022a9, 0x00000338, 0x000022ab, 0x00000338, 0x0000227c, 0x00000338, 0x0000227d, 0x00000338, 0x00002291, 0x00000338, 0x00002292, 0x00000338, 0x000022b2, 0x00000338, 0x000022b3, 0x00000338, 0x000022b4, 0x00000338, 0x000022b5, 0x00000338, 0x00003008, 0x00003009, 0x00000031, 0x00000032, 0x00000033, 0x00000034, 0x00000035, 0x00000036, 0x00000037, 0x00000038, 0x00000039, 0x00000031, 0x00000030, 0x00000031, 0x00000031, 0x00000031, 0x00000032, 0x00000031, 0x00000033, 0x00000031, 0x00000034, 0x00000031, 0x00000035, 0x00000031, 0x00000036, 0x00000031, 0x00000037, 0x00000031, 0x00000038, 0x00000031, 0x00000039, 0x00000032, 0x00000030, 0x00000028, 0x00000031, 0x00000029, 0x00000028, 0x00000032, 0x00000029, 0x00000028, 0x00000033, 0x00000029, 0x00000028, 0x00000034, 0x00000029, 0x00000028, 0x00000035, 0x00000029, 0x00000028, 0x00000036, 0x00000029, 0x00000028, 0x00000037, 0x00000029, 0x00000028, 0x00000038, 0x00000029, 0x00000028, 0x00000039, 0x00000029, 0x00000028, 0x00000031, 0x00000030, 0x00000029, 0x00000028, 0x00000031, 0x00000031, 0x00000029, 0x00000028, 0x00000031, 0x00000032, 0x00000029, 0x00000028, 0x00000031, 0x00000033, 0x00000029, 0x00000028, 0x00000031, 0x00000034, 0x00000029, 0x00000028, 0x00000031, 0x00000035, 0x00000029, 0x00000028, 0x00000031, 0x00000036, 0x00000029, 0x00000028, 0x00000031, 0x00000037, 0x00000029, 0x00000028, 0x00000031, 0x00000038, 0x00000029, 0x00000028, 0x00000031, 0x00000039, 0x00000029, 0x00000028, 0x00000032, 0x00000030, 0x00000029, 0x00000031, 0x0000002e, 0x00000032, 0x0000002e, 0x00000033, 0x0000002e, 0x00000034, 0x0000002e, 0x00000035, 0x0000002e, 0x00000036, 0x0000002e, 0x00000037, 0x0000002e, 0x00000038, 0x0000002e, 0x00000039, 0x0000002e, 0x00000031, 0x00000030, 0x0000002e, 0x00000031, 0x00000031, 0x0000002e, 0x00000031, 0x00000032, 0x0000002e, 0x00000031, 0x00000033, 0x0000002e, 0x00000031, 0x00000034, 0x0000002e, 0x00000031, 0x00000035, 0x0000002e, 0x00000031, 0x00000036, 0x0000002e, 0x00000031, 0x00000037, 0x0000002e, 0x00000031, 0x00000038, 0x0000002e, 0x00000031, 0x00000039, 0x0000002e, 0x00000032, 0x00000030, 0x0000002e, 0x00000028, 0x00000061, 0x00000029, 0x00000028, 0x00000062, 0x00000029, 0x00000028, 0x00000063, 0x00000029, 0x00000028, 0x00000064, 0x00000029, 0x00000028, 0x00000065, 0x00000029, 0x00000028, 0x00000066, 0x00000029, 0x00000028, 0x00000067, 0x00000029, 0x00000028, 0x00000068, 0x00000029, 0x00000028, 0x00000069, 0x00000029, 0x00000028, 0x0000006a, 0x00000029, 0x00000028, 0x0000006b, 0x00000029, 0x00000028, 0x0000006c, 0x00000029, 0x00000028, 0x0000006d, 0x00000029, 0x00000028, 0x0000006e, 0x00000029, 0x00000028, 0x0000006f, 0x00000029, 0x00000028, 0x00000070, 0x00000029, 0x00000028, 0x00000071, 0x00000029, 0x00000028, 0x00000072, 0x00000029, 0x00000028, 0x00000073, 0x00000029, 0x00000028, 0x00000074, 0x00000029, 0x00000028, 0x00000075, 0x00000029, 0x00000028, 0x00000076, 0x00000029, 0x00000028, 0x00000077, 0x00000029, 0x00000028, 0x00000078, 0x00000029, 0x00000028, 0x00000079, 0x00000029, 0x00000028, 0x0000007a, 0x00000029, 0x00000041, 0x00000042, 0x00000043, 0x00000044, 0x00000045, 0x00000046, 0x00000047, 0x00000048, 0x00000049, 0x0000004a, 0x0000004b, 0x0000004c, 0x0000004d, 0x0000004e, 0x0000004f, 0x00000050, 0x00000051, 0x00000052, 0x00000053, 0x00000054, 0x00000055, 0x00000056, 0x00000057, 0x00000058, 0x00000059, 0x0000005a, 0x00000061, 0x00000062, 0x00000063, 0x00000064, 0x00000065, 0x00000066, 0x00000067, 0x00000068, 0x00000069, 0x0000006a, 0x0000006b, 0x0000006c, 0x0000006d, 0x0000006e, 0x0000006f, 0x00000070, 0x00000071, 0x00000072, 0x00000073, 0x00000074, 0x00000075, 0x00000076, 0x00000077, 0x00000078, 0x00000079, 0x0000007a, 0x00000030, 0x0000222b, 0x0000222b, 0x0000222b, 0x0000222b, 0x0000003a, 0x0000003a, 0x0000003d, 0x0000003d, 0x0000003d, 0x0000003d, 0x0000003d, 0x0000003d, 0x00002add, 0x00000338, 0x00006bcd, 0x00009f9f, 0x00004e00, 0x00004e28, 0x00004e36, 0x00004e3f, 0x00004e59, 0x00004e85, 0x00004e8c, 0x00004ea0, 0x00004eba, 0x0000513f, 0x00005165, 0x0000516b, 0x00005182, 0x00005196, 0x000051ab, 0x000051e0, 0x000051f5, 0x00005200, 0x0000529b, 0x000052f9, 0x00005315, 0x0000531a, 0x00005338, 0x00005341, 0x0000535c, 0x00005369, 0x00005382, 0x000053b6, 0x000053c8, 0x000053e3, 0x000056d7, 0x0000571f, 0x000058eb, 0x00005902, 0x0000590a, 0x00005915, 0x00005927, 0x00005973, 0x00005b50, 0x00005b80, 0x00005bf8, 0x00005c0f, 0x00005c22, 0x00005c38, 0x00005c6e, 0x00005c71, 0x00005ddb, 0x00005de5, 0x00005df1, 0x00005dfe, 0x00005e72, 0x00005e7a, 0x00005e7f, 0x00005ef4, 0x00005efe, 0x00005f0b, 0x00005f13, 0x00005f50, 0x00005f61, 0x00005f73, 0x00005fc3, 0x00006208, 0x00006236, 0x0000624b, 0x0000652f, 0x00006534, 0x00006587, 0x00006597, 0x000065a4, 0x000065b9, 0x000065e0, 0x000065e5, 0x000066f0, 0x00006708, 0x00006728, 0x00006b20, 0x00006b62, 0x00006b79, 0x00006bb3, 0x00006bcb, 0x00006bd4, 0x00006bdb, 0x00006c0f, 0x00006c14, 0x00006c34, 0x0000706b, 0x0000722a, 0x00007236, 0x0000723b, 0x0000723f, 0x00007247, 0x00007259, 0x0000725b, 0x000072ac, 0x00007384, 0x00007389, 0x000074dc, 0x000074e6, 0x00007518, 0x0000751f, 0x00007528, 0x00007530, 0x0000758b, 0x00007592, 0x00007676, 0x0000767d, 0x000076ae, 0x000076bf, 0x000076ee, 0x000077db, 0x000077e2, 0x000077f3, 0x0000793a, 0x000079b8, 0x000079be, 0x00007a74, 0x00007acb, 0x00007af9, 0x00007c73, 0x00007cf8, 0x00007f36, 0x00007f51, 0x00007f8a, 0x00007fbd, 0x00008001, 0x0000800c, 0x00008012, 0x00008033, 0x0000807f, 0x00008089, 0x000081e3, 0x000081ea, 0x000081f3, 0x000081fc, 0x0000820c, 0x0000821b, 0x0000821f, 0x0000826e, 0x00008272, 0x00008278, 0x0000864d, 0x0000866b, 0x00008840, 0x0000884c, 0x00008863, 0x0000897e, 0x0000898b, 0x000089d2, 0x00008a00, 0x00008c37, 0x00008c46, 0x00008c55, 0x00008c78, 0x00008c9d, 0x00008d64, 0x00008d70, 0x00008db3, 0x00008eab, 0x00008eca, 0x00008f9b, 0x00008fb0, 0x00008fb5, 0x00009091, 0x00009149, 0x000091c6, 0x000091cc, 0x000091d1, 0x00009577, 0x00009580, 0x0000961c, 0x000096b6, 0x000096b9, 0x000096e8, 0x00009751, 0x0000975e, 0x00009762, 0x00009769, 0x000097cb, 0x000097ed, 0x000097f3, 0x00009801, 0x000098a8, 0x000098db, 0x000098df, 0x00009996, 0x00009999, 0x000099ac, 0x00009aa8, 0x00009ad8, 0x00009adf, 0x00009b25, 0x00009b2f, 0x00009b32, 0x00009b3c, 0x00009b5a, 0x00009ce5, 0x00009e75, 0x00009e7f, 0x00009ea5, 0x00009ebb, 0x00009ec3, 0x00009ecd, 0x00009ed1, 0x00009ef9, 0x00009efd, 0x00009f0e, 0x00009f13, 0x00009f20, 0x00009f3b, 0x00009f4a, 0x00009f52, 0x00009f8d, 0x00009f9c, 0x00009fa0, 0x00000020, 0x00003012, 0x00005341, 0x00005344, 0x00005345, 0x0000304b, 0x00003099, 0x0000304d, 0x00003099, 0x0000304f, 0x00003099, 0x00003051, 0x00003099, 0x00003053, 0x00003099, 0x00003055, 0x00003099, 0x00003057, 0x00003099, 0x00003059, 0x00003099, 0x0000305b, 0x00003099, 0x0000305d, 0x00003099, 0x0000305f, 0x00003099, 0x00003061, 0x00003099, 0x00003064, 0x00003099, 0x00003066, 0x00003099, 0x00003068, 0x00003099, 0x0000306f, 0x00003099, 0x0000306f, 0x0000309a, 0x00003072, 0x00003099, 0x00003072, 0x0000309a, 0x00003075, 0x00003099, 0x00003075, 0x0000309a, 0x00003078, 0x00003099, 0x00003078, 0x0000309a, 0x0000307b, 0x00003099, 0x0000307b, 0x0000309a, 0x00003046, 0x00003099, 0x00000020, 0x00003099, 0x00000020, 0x0000309a, 0x0000309d, 0x00003099, 0x00003088, 0x0000308a, 0x000030ab, 0x00003099, 0x000030ad, 0x00003099, 0x000030af, 0x00003099, 0x000030b1, 0x00003099, 0x000030b3, 0x00003099, 0x000030b5, 0x00003099, 0x000030b7, 0x00003099, 0x000030b9, 0x00003099, 0x000030bb, 0x00003099, 0x000030bd, 0x00003099, 0x000030bf, 0x00003099, 0x000030c1, 0x00003099, 0x000030c4, 0x00003099, 0x000030c6, 0x00003099, 0x000030c8, 0x00003099, 0x000030cf, 0x00003099, 0x000030cf, 0x0000309a, 0x000030d2, 0x00003099, 0x000030d2, 0x0000309a, 0x000030d5, 0x00003099, 0x000030d5, 0x0000309a, 0x000030d8, 0x00003099, 0x000030d8, 0x0000309a, 0x000030db, 0x00003099, 0x000030db, 0x0000309a, 0x000030a6, 0x00003099, 0x000030ef, 0x00003099, 0x000030f0, 0x00003099, 0x000030f1, 0x00003099, 0x000030f2, 0x00003099, 0x000030fd, 0x00003099, 0x000030b3, 0x000030c8, 0x00001100, 0x00001101, 0x000011aa, 0x00001102, 0x000011ac, 0x000011ad, 0x00001103, 0x00001104, 0x00001105, 0x000011b0, 0x000011b1, 0x000011b2, 0x000011b3, 0x000011b4, 0x000011b5, 0x0000111a, 0x00001106, 0x00001107, 0x00001108, 0x00001121, 0x00001109, 0x0000110a, 0x0000110b, 0x0000110c, 0x0000110d, 0x0000110e, 0x0000110f, 0x00001110, 0x00001111, 0x00001112, 0x00001161, 0x00001162, 0x00001163, 0x00001164, 0x00001165, 0x00001166, 0x00001167, 0x00001168, 0x00001169, 0x0000116a, 0x0000116b, 0x0000116c, 0x0000116d, 0x0000116e, 0x0000116f, 0x00001170, 0x00001171, 0x00001172, 0x00001173, 0x00001174, 0x00001175, 0x00001160, 0x00001114, 0x00001115, 0x000011c7, 0x000011c8, 0x000011cc, 0x000011ce, 0x000011d3, 0x000011d7, 0x000011d9, 0x0000111c, 0x000011dd, 0x000011df, 0x0000111d, 0x0000111e, 0x00001120, 0x00001122, 0x00001123, 0x00001127, 0x00001129, 0x0000112b, 0x0000112c, 0x0000112d, 0x0000112e, 0x0000112f, 0x00001132, 0x00001136, 0x00001140, 0x00001147, 0x0000114c, 0x000011f1, 0x000011f2, 0x00001157, 0x00001158, 0x00001159, 0x00001184, 0x00001185, 0x00001188, 0x00001191, 0x00001192, 0x00001194, 0x0000119e, 0x000011a1, 0x00004e00, 0x00004e8c, 0x00004e09, 0x000056db, 0x00004e0a, 0x00004e2d, 0x00004e0b, 0x00007532, 0x00004e59, 0x00004e19, 0x00004e01, 0x00005929, 0x00005730, 0x00004eba, 0x00000028, 0x00001100, 0x00000029, 0x00000028, 0x00001102, 0x00000029, 0x00000028, 0x00001103, 0x00000029, 0x00000028, 0x00001105, 0x00000029, 0x00000028, 0x00001106, 0x00000029, 0x00000028, 0x00001107, 0x00000029, 0x00000028, 0x00001109, 0x00000029, 0x00000028, 0x0000110b, 0x00000029, 0x00000028, 0x0000110c, 0x00000029, 0x00000028, 0x0000110e, 0x00000029, 0x00000028, 0x0000110f, 0x00000029, 0x00000028, 0x00001110, 0x00000029, 0x00000028, 0x00001111, 0x00000029, 0x00000028, 0x00001112, 0x00000029, 0x00000028, 0x00001100, 0x00001161, 0x00000029, 0x00000028, 0x00001102, 0x00001161, 0x00000029, 0x00000028, 0x00001103, 0x00001161, 0x00000029, 0x00000028, 0x00001105, 0x00001161, 0x00000029, 0x00000028, 0x00001106, 0x00001161, 0x00000029, 0x00000028, 0x00001107, 0x00001161, 0x00000029, 0x00000028, 0x00001109, 0x00001161, 0x00000029, 0x00000028, 0x0000110b, 0x00001161, 0x00000029, 0x00000028, 0x0000110c, 0x00001161, 0x00000029, 0x00000028, 0x0000110e, 0x00001161, 0x00000029, 0x00000028, 0x0000110f, 0x00001161, 0x00000029, 0x00000028, 0x00001110, 0x00001161, 0x00000029, 0x00000028, 0x00001111, 0x00001161, 0x00000029, 0x00000028, 0x00001112, 0x00001161, 0x00000029, 0x00000028, 0x0000110c, 0x0000116e, 0x00000029, 0x00000028, 0x00004e00, 0x00000029, 0x00000028, 0x00004e8c, 0x00000029, 0x00000028, 0x00004e09, 0x00000029, 0x00000028, 0x000056db, 0x00000029, 0x00000028, 0x00004e94, 0x00000029, 0x00000028, 0x0000516d, 0x00000029, 0x00000028, 0x00004e03, 0x00000029, 0x00000028, 0x0000516b, 0x00000029, 0x00000028, 0x00004e5d, 0x00000029, 0x00000028, 0x00005341, 0x00000029, 0x00000028, 0x00006708, 0x00000029, 0x00000028, 0x0000706b, 0x00000029, 0x00000028, 0x00006c34, 0x00000029, 0x00000028, 0x00006728, 0x00000029, 0x00000028, 0x000091d1, 0x00000029, 0x00000028, 0x0000571f, 0x00000029, 0x00000028, 0x000065e5, 0x00000029, 0x00000028, 0x0000682a, 0x00000029, 0x00000028, 0x00006709, 0x00000029, 0x00000028, 0x0000793e, 0x00000029, 0x00000028, 0x0000540d, 0x00000029, 0x00000028, 0x00007279, 0x00000029, 0x00000028, 0x00008ca1, 0x00000029, 0x00000028, 0x0000795d, 0x00000029, 0x00000028, 0x000052b4, 0x00000029, 0x00000028, 0x00004ee3, 0x00000029, 0x00000028, 0x0000547c, 0x00000029, 0x00000028, 0x00005b66, 0x00000029, 0x00000028, 0x000076e3, 0x00000029, 0x00000028, 0x00004f01, 0x00000029, 0x00000028, 0x00008cc7, 0x00000029, 0x00000028, 0x00005354, 0x00000029, 0x00000028, 0x0000796d, 0x00000029, 0x00000028, 0x00004f11, 0x00000029, 0x00000028, 0x000081ea, 0x00000029, 0x00000028, 0x000081f3, 0x00000029, 0x00000032, 0x00000031, 0x00000032, 0x00000032, 0x00000032, 0x00000033, 0x00000032, 0x00000034, 0x00000032, 0x00000035, 0x00000032, 0x00000036, 0x00000032, 0x00000037, 0x00000032, 0x00000038, 0x00000032, 0x00000039, 0x00000033, 0x00000030, 0x00000033, 0x00000031, 0x00000033, 0x00000032, 0x00000033, 0x00000033, 0x00000033, 0x00000034, 0x00000033, 0x00000035, 0x00001100, 0x00001102, 0x00001103, 0x00001105, 0x00001106, 0x00001107, 0x00001109, 0x0000110b, 0x0000110c, 0x0000110e, 0x0000110f, 0x00001110, 0x00001111, 0x00001112, 0x00001100, 0x00001161, 0x00001102, 0x00001161, 0x00001103, 0x00001161, 0x00001105, 0x00001161, 0x00001106, 0x00001161, 0x00001107, 0x00001161, 0x00001109, 0x00001161, 0x0000110b, 0x00001161, 0x0000110c, 0x00001161, 0x0000110e, 0x00001161, 0x0000110f, 0x00001161, 0x00001110, 0x00001161, 0x00001111, 0x00001161, 0x00001112, 0x00001161, 0x00004e00, 0x00004e8c, 0x00004e09, 0x000056db, 0x00004e94, 0x0000516d, 0x00004e03, 0x0000516b, 0x00004e5d, 0x00005341, 0x00006708, 0x0000706b, 0x00006c34, 0x00006728, 0x000091d1, 0x0000571f, 0x000065e5, 0x0000682a, 0x00006709, 0x0000793e, 0x0000540d, 0x00007279, 0x00008ca1, 0x0000795d, 0x000052b4, 0x000079d8, 0x00007537, 0x00005973, 0x00009069, 0x0000512a, 0x00005370, 0x00006ce8, 0x00009805, 0x00004f11, 0x00005199, 0x00006b63, 0x00004e0a, 0x00004e2d, 0x00004e0b, 0x00005de6, 0x000053f3, 0x0000533b, 0x00005b97, 0x00005b66, 0x000076e3, 0x00004f01, 0x00008cc7, 0x00005354, 0x0000591c, 0x00000033, 0x00000036, 0x00000033, 0x00000037, 0x00000033, 0x00000038, 0x00000033, 0x00000039, 0x00000034, 0x00000030, 0x00000034, 0x00000031, 0x00000034, 0x00000032, 0x00000034, 0x00000033, 0x00000034, 0x00000034, 0x00000034, 0x00000035, 0x00000034, 0x00000036, 0x00000034, 0x00000037, 0x00000034, 0x00000038, 0x00000034, 0x00000039, 0x00000035, 0x00000030, 0x00000031, 0x00006708, 0x00000032, 0x00006708, 0x00000033, 0x00006708, 0x00000034, 0x00006708, 0x00000035, 0x00006708, 0x00000036, 0x00006708, 0x00000037, 0x00006708, 0x00000038, 0x00006708, 0x00000039, 0x00006708, 0x00000031, 0x00000030, 0x00006708, 0x00000031, 0x00000031, 0x00006708, 0x00000031, 0x00000032, 0x00006708, 0x000030a2, 0x000030a4, 0x000030a6, 0x000030a8, 0x000030aa, 0x000030ab, 0x000030ad, 0x000030af, 0x000030b1, 0x000030b3, 0x000030b5, 0x000030b7, 0x000030b9, 0x000030bb, 0x000030bd, 0x000030bf, 0x000030c1, 0x000030c4, 0x000030c6, 0x000030c8, 0x000030ca, 0x000030cb, 0x000030cc, 0x000030cd, 0x000030ce, 0x000030cf, 0x000030d2, 0x000030d5, 0x000030d8, 0x000030db, 0x000030de, 0x000030df, 0x000030e0, 0x000030e1, 0x000030e2, 0x000030e4, 0x000030e6, 0x000030e8, 0x000030e9, 0x000030ea, 0x000030eb, 0x000030ec, 0x000030ed, 0x000030ef, 0x000030f0, 0x000030f1, 0x000030f2, 0x000030a2, 0x000030cf, 0x0000309a, 0x000030fc, 0x000030c8, 0x000030a2, 0x000030eb, 0x000030d5, 0x000030a1, 0x000030a2, 0x000030f3, 0x000030d8, 0x0000309a, 0x000030a2, 0x000030a2, 0x000030fc, 0x000030eb, 0x000030a4, 0x000030cb, 0x000030f3, 0x000030af, 0x00003099, 0x000030a4, 0x000030f3, 0x000030c1, 0x000030a6, 0x000030a9, 0x000030f3, 0x000030a8, 0x000030b9, 0x000030af, 0x000030fc, 0x000030c8, 0x00003099, 0x000030a8, 0x000030fc, 0x000030ab, 0x000030fc, 0x000030aa, 0x000030f3, 0x000030b9, 0x000030aa, 0x000030fc, 0x000030e0, 0x000030ab, 0x000030a4, 0x000030ea, 0x000030ab, 0x000030e9, 0x000030c3, 0x000030c8, 0x000030ab, 0x000030ed, 0x000030ea, 0x000030fc, 0x000030ab, 0x00003099, 0x000030ed, 0x000030f3, 0x000030ab, 0x00003099, 0x000030f3, 0x000030de, 0x000030ad, 0x00003099, 0x000030ab, 0x00003099, 0x000030ad, 0x00003099, 0x000030cb, 0x000030fc, 0x000030ad, 0x000030e5, 0x000030ea, 0x000030fc, 0x000030ad, 0x00003099, 0x000030eb, 0x000030bf, 0x00003099, 0x000030fc, 0x000030ad, 0x000030ed, 0x000030ad, 0x000030ed, 0x000030af, 0x00003099, 0x000030e9, 0x000030e0, 0x000030ad, 0x000030ed, 0x000030e1, 0x000030fc, 0x000030c8, 0x000030eb, 0x000030ad, 0x000030ed, 0x000030ef, 0x000030c3, 0x000030c8, 0x000030af, 0x00003099, 0x000030e9, 0x000030e0, 0x000030af, 0x00003099, 0x000030e9, 0x000030e0, 0x000030c8, 0x000030f3, 0x000030af, 0x000030eb, 0x000030bb, 0x00003099, 0x000030a4, 0x000030ed, 0x000030af, 0x000030ed, 0x000030fc, 0x000030cd, 0x000030b1, 0x000030fc, 0x000030b9, 0x000030b3, 0x000030eb, 0x000030ca, 0x000030b3, 0x000030fc, 0x000030db, 0x0000309a, 0x000030b5, 0x000030a4, 0x000030af, 0x000030eb, 0x000030b5, 0x000030f3, 0x000030c1, 0x000030fc, 0x000030e0, 0x000030b7, 0x000030ea, 0x000030f3, 0x000030af, 0x00003099, 0x000030bb, 0x000030f3, 0x000030c1, 0x000030bb, 0x000030f3, 0x000030c8, 0x000030bf, 0x00003099, 0x000030fc, 0x000030b9, 0x000030c6, 0x00003099, 0x000030b7, 0x000030c8, 0x00003099, 0x000030eb, 0x000030c8, 0x000030f3, 0x000030ca, 0x000030ce, 0x000030ce, 0x000030c3, 0x000030c8, 0x000030cf, 0x000030a4, 0x000030c4, 0x000030cf, 0x0000309a, 0x000030fc, 0x000030bb, 0x000030f3, 0x000030c8, 0x000030cf, 0x0000309a, 0x000030fc, 0x000030c4, 0x000030cf, 0x00003099, 0x000030fc, 0x000030ec, 0x000030eb, 0x000030d2, 0x0000309a, 0x000030a2, 0x000030b9, 0x000030c8, 0x000030eb, 0x000030d2, 0x0000309a, 0x000030af, 0x000030eb, 0x000030d2, 0x0000309a, 0x000030b3, 0x000030d2, 0x00003099, 0x000030eb, 0x000030d5, 0x000030a1, 0x000030e9, 0x000030c3, 0x000030c8, 0x00003099, 0x000030d5, 0x000030a3, 0x000030fc, 0x000030c8, 0x000030d5, 0x00003099, 0x000030c3, 0x000030b7, 0x000030a7, 0x000030eb, 0x000030d5, 0x000030e9, 0x000030f3, 0x000030d8, 0x000030af, 0x000030bf, 0x000030fc, 0x000030eb, 0x000030d8, 0x0000309a, 0x000030bd, 0x000030d8, 0x0000309a, 0x000030cb, 0x000030d2, 0x000030d8, 0x000030eb, 0x000030c4, 0x000030d8, 0x0000309a, 0x000030f3, 0x000030b9, 0x000030d8, 0x0000309a, 0x000030fc, 0x000030b7, 0x00003099, 0x000030d8, 0x00003099, 0x000030fc, 0x000030bf, 0x000030db, 0x0000309a, 0x000030a4, 0x000030f3, 0x000030c8, 0x000030db, 0x00003099, 0x000030eb, 0x000030c8, 0x000030db, 0x000030f3, 0x000030db, 0x0000309a, 0x000030f3, 0x000030c8, 0x00003099, 0x000030db, 0x000030fc, 0x000030eb, 0x000030db, 0x000030fc, 0x000030f3, 0x000030de, 0x000030a4, 0x000030af, 0x000030ed, 0x000030de, 0x000030a4, 0x000030eb, 0x000030de, 0x000030c3, 0x000030cf, 0x000030de, 0x000030eb, 0x000030af, 0x000030de, 0x000030f3, 0x000030b7, 0x000030e7, 0x000030f3, 0x000030df, 0x000030af, 0x000030ed, 0x000030f3, 0x000030df, 0x000030ea, 0x000030df, 0x000030ea, 0x000030cf, 0x00003099, 0x000030fc, 0x000030eb, 0x000030e1, 0x000030ab, 0x00003099, 0x000030e1, 0x000030ab, 0x00003099, 0x000030c8, 0x000030f3, 0x000030e1, 0x000030fc, 0x000030c8, 0x000030eb, 0x000030e4, 0x000030fc, 0x000030c8, 0x00003099, 0x000030e4, 0x000030fc, 0x000030eb, 0x000030e6, 0x000030a2, 0x000030f3, 0x000030ea, 0x000030c3, 0x000030c8, 0x000030eb, 0x000030ea, 0x000030e9, 0x000030eb, 0x000030d2, 0x0000309a, 0x000030fc, 0x000030eb, 0x000030fc, 0x000030d5, 0x00003099, 0x000030eb, 0x000030ec, 0x000030e0, 0x000030ec, 0x000030f3, 0x000030c8, 0x000030b1, 0x00003099, 0x000030f3, 0x000030ef, 0x000030c3, 0x000030c8, 0x00000030, 0x000070b9, 0x00000031, 0x000070b9, 0x00000032, 0x000070b9, 0x00000033, 0x000070b9, 0x00000034, 0x000070b9, 0x00000035, 0x000070b9, 0x00000036, 0x000070b9, 0x00000037, 0x000070b9, 0x00000038, 0x000070b9, 0x00000039, 0x000070b9, 0x00000031, 0x00000030, 0x000070b9, 0x00000031, 0x00000031, 0x000070b9, 0x00000031, 0x00000032, 0x000070b9, 0x00000031, 0x00000033, 0x000070b9, 0x00000031, 0x00000034, 0x000070b9, 0x00000031, 0x00000035, 0x000070b9, 0x00000031, 0x00000036, 0x000070b9, 0x00000031, 0x00000037, 0x000070b9, 0x00000031, 0x00000038, 0x000070b9, 0x00000031, 0x00000039, 0x000070b9, 0x00000032, 0x00000030, 0x000070b9, 0x00000032, 0x00000031, 0x000070b9, 0x00000032, 0x00000032, 0x000070b9, 0x00000032, 0x00000033, 0x000070b9, 0x00000032, 0x00000034, 0x000070b9, 0x00000068, 0x00000050, 0x00000061, 0x00000064, 0x00000061, 0x00000041, 0x00000055, 0x00000062, 0x00000061, 0x00000072, 0x0000006f, 0x00000056, 0x00000070, 0x00000063, 0x00005e73, 0x00006210, 0x0000662d, 0x0000548c, 0x00005927, 0x00006b63, 0x0000660e, 0x00006cbb, 0x0000682a, 0x00005f0f, 0x00004f1a, 0x0000793e, 0x00000070, 0x00000041, 0x0000006e, 0x00000041, 0x000003bc, 0x00000041, 0x0000006d, 0x00000041, 0x0000006b, 0x00000041, 0x0000004b, 0x00000042, 0x0000004d, 0x00000042, 0x00000047, 0x00000042, 0x00000063, 0x00000061, 0x0000006c, 0x0000006b, 0x00000063, 0x00000061, 0x0000006c, 0x00000070, 0x00000046, 0x0000006e, 0x00000046, 0x000003bc, 0x00000046, 0x000003bc, 0x00000067, 0x0000006d, 0x00000067, 0x0000006b, 0x00000067, 0x00000048, 0x0000007a, 0x0000006b, 0x00000048, 0x0000007a, 0x0000004d, 0x00000048, 0x0000007a, 0x00000047, 0x00000048, 0x0000007a, 0x00000054, 0x00000048, 0x0000007a, 0x000003bc, 0x0000006c, 0x0000006d, 0x0000006c, 0x00000064, 0x0000006c, 0x0000006b, 0x0000006c, 0x00000066, 0x0000006d, 0x0000006e, 0x0000006d, 0x000003bc, 0x0000006d, 0x0000006d, 0x0000006d, 0x00000063, 0x0000006d, 0x0000006b, 0x0000006d, 0x0000006d, 0x0000006d, 0x00000032, 0x00000063, 0x0000006d, 0x00000032, 0x0000006d, 0x00000032, 0x0000006b, 0x0000006d, 0x00000032, 0x0000006d, 0x0000006d, 0x00000033, 0x00000063, 0x0000006d, 0x00000033, 0x0000006d, 0x00000033, 0x0000006b, 0x0000006d, 0x00000033, 0x0000006d, 0x00002215, 0x00000073, 0x0000006d, 0x00002215, 0x00000073, 0x00000032, 0x00000050, 0x00000061, 0x0000006b, 0x00000050, 0x00000061, 0x0000004d, 0x00000050, 0x00000061, 0x00000047, 0x00000050, 0x00000061, 0x00000072, 0x00000061, 0x00000064, 0x00000072, 0x00000061, 0x00000064, 0x00002215, 0x00000073, 0x00000072, 0x00000061, 0x00000064, 0x00002215, 0x00000073, 0x00000032, 0x00000070, 0x00000073, 0x0000006e, 0x00000073, 0x000003bc, 0x00000073, 0x0000006d, 0x00000073, 0x00000070, 0x00000056, 0x0000006e, 0x00000056, 0x000003bc, 0x00000056, 0x0000006d, 0x00000056, 0x0000006b, 0x00000056, 0x0000004d, 0x00000056, 0x00000070, 0x00000057, 0x0000006e, 0x00000057, 0x000003bc, 0x00000057, 0x0000006d, 0x00000057, 0x0000006b, 0x00000057, 0x0000004d, 0x00000057, 0x0000006b, 0x000003a9, 0x0000004d, 0x000003a9, 0x00000061, 0x0000002e, 0x0000006d, 0x0000002e, 0x00000042, 0x00000071, 0x00000063, 0x00000063, 0x00000063, 0x00000064, 0x00000043, 0x00002215, 0x0000006b, 0x00000067, 0x00000043, 0x0000006f, 0x0000002e, 0x00000064, 0x00000042, 0x00000047, 0x00000079, 0x00000068, 0x00000061, 0x00000048, 0x00000050, 0x00000069, 0x0000006e, 0x0000004b, 0x0000004b, 0x0000004b, 0x0000004d, 0x0000006b, 0x00000074, 0x0000006c, 0x0000006d, 0x0000006c, 0x0000006e, 0x0000006c, 0x0000006f, 0x00000067, 0x0000006c, 0x00000078, 0x0000006d, 0x00000062, 0x0000006d, 0x00000069, 0x0000006c, 0x0000006d, 0x0000006f, 0x0000006c, 0x00000050, 0x00000048, 0x00000070, 0x0000002e, 0x0000006d, 0x0000002e, 0x00000050, 0x00000050, 0x0000004d, 0x00000050, 0x00000052, 0x00000073, 0x00000072, 0x00000053, 0x00000076, 0x00000057, 0x00000062, 0x00000031, 0x000065e5, 0x00000032, 0x000065e5, 0x00000033, 0x000065e5, 0x00000034, 0x000065e5, 0x00000035, 0x000065e5, 0x00000036, 0x000065e5, 0x00000037, 0x000065e5, 0x00000038, 0x000065e5, 0x00000039, 0x000065e5, 0x00000031, 0x00000030, 0x000065e5, 0x00000031, 0x00000031, 0x000065e5, 0x00000031, 0x00000032, 0x000065e5, 0x00000031, 0x00000033, 0x000065e5, 0x00000031, 0x00000034, 0x000065e5, 0x00000031, 0x00000035, 0x000065e5, 0x00000031, 0x00000036, 0x000065e5, 0x00000031, 0x00000037, 0x000065e5, 0x00000031, 0x00000038, 0x000065e5, 0x00000031, 0x00000039, 0x000065e5, 0x00000032, 0x00000030, 0x000065e5, 0x00000032, 0x00000031, 0x000065e5, 0x00000032, 0x00000032, 0x000065e5, 0x00000032, 0x00000033, 0x000065e5, 0x00000032, 0x00000034, 0x000065e5, 0x00000032, 0x00000035, 0x000065e5, 0x00000032, 0x00000036, 0x000065e5, 0x00000032, 0x00000037, 0x000065e5, 0x00000032, 0x00000038, 0x000065e5, 0x00000032, 0x00000039, 0x000065e5, 0x00000033, 0x00000030, 0x000065e5, 0x00000033, 0x00000031, 0x000065e5, 0x00008eca, 0x00008cc8, 0x00006ed1, 0x00004e32, 0x000053e5, 0x00009f9c, 0x00009f9c, 0x00005951, 0x000091d1, 0x00005587, 0x00005948, 0x000061f6, 0x00007669, 0x00007f85, 0x0000863f, 0x000087ba, 0x000088f8, 0x0000908f, 0x00006a02, 0x00006d1b, 0x000070d9, 0x000073de, 0x0000843d, 0x0000916a, 0x000099f1, 0x00004e82, 0x00005375, 0x00006b04, 0x0000721b, 0x0000862d, 0x00009e1e, 0x00005d50, 0x00006feb, 0x000085cd, 0x00008964, 0x000062c9, 0x000081d8, 0x0000881f, 0x00005eca, 0x00006717, 0x00006d6a, 0x000072fc, 0x000090ce, 0x00004f86, 0x000051b7, 0x000052de, 0x000064c4, 0x00006ad3, 0x00007210, 0x000076e7, 0x00008001, 0x00008606, 0x0000865c, 0x00008def, 0x00009732, 0x00009b6f, 0x00009dfa, 0x0000788c, 0x0000797f, 0x00007da0, 0x000083c9, 0x00009304, 0x00009e7f, 0x00008ad6, 0x000058df, 0x00005f04, 0x00007c60, 0x0000807e, 0x00007262, 0x000078ca, 0x00008cc2, 0x000096f7, 0x000058d8, 0x00005c62, 0x00006a13, 0x00006dda, 0x00006f0f, 0x00007d2f, 0x00007e37, 0x0000964b, 0x000052d2, 0x0000808b, 0x000051dc, 0x000051cc, 0x00007a1c, 0x00007dbe, 0x000083f1, 0x00009675, 0x00008b80, 0x000062cf, 0x00006a02, 0x00008afe, 0x00004e39, 0x00005be7, 0x00006012, 0x00007387, 0x00007570, 0x00005317, 0x000078fb, 0x00004fbf, 0x00005fa9, 0x00004e0d, 0x00006ccc, 0x00006578, 0x00007d22, 0x000053c3, 0x0000585e, 0x00007701, 0x00008449, 0x00008aaa, 0x00006bba, 0x00008fb0, 0x00006c88, 0x000062fe, 0x000082e5, 0x000063a0, 0x00007565, 0x00004eae, 0x00005169, 0x000051c9, 0x00006881, 0x00007ce7, 0x0000826f, 0x00008ad2, 0x000091cf, 0x000052f5, 0x00005442, 0x00005973, 0x00005eec, 0x000065c5, 0x00006ffe, 0x0000792a, 0x000095ad, 0x00009a6a, 0x00009e97, 0x00009ece, 0x0000529b, 0x000066c6, 0x00006b77, 0x00008f62, 0x00005e74, 0x00006190, 0x00006200, 0x0000649a, 0x00006f23, 0x00007149, 0x00007489, 0x000079ca, 0x00007df4, 0x0000806f, 0x00008f26, 0x000084ee, 0x00009023, 0x0000934a, 0x00005217, 0x000052a3, 0x000054bd, 0x000070c8, 0x000088c2, 0x00008aaa, 0x00005ec9, 0x00005ff5, 0x0000637b, 0x00006bae, 0x00007c3e, 0x00007375, 0x00004ee4, 0x000056f9, 0x00005be7, 0x00005dba, 0x0000601c, 0x000073b2, 0x00007469, 0x00007f9a, 0x00008046, 0x00009234, 0x000096f6, 0x00009748, 0x00009818, 0x00004f8b, 0x000079ae, 0x000091b4, 0x000096b8, 0x000060e1, 0x00004e86, 0x000050da, 0x00005bee, 0x00005c3f, 0x00006599, 0x00006a02, 0x000071ce, 0x00007642, 0x000084fc, 0x0000907c, 0x00009f8d, 0x00006688, 0x0000962e, 0x00005289, 0x0000677b, 0x000067f3, 0x00006d41, 0x00006e9c, 0x00007409, 0x00007559, 0x0000786b, 0x00007d10, 0x0000985e, 0x0000516d, 0x0000622e, 0x00009678, 0x0000502b, 0x00005d19, 0x00006dea, 0x00008f2a, 0x00005f8b, 0x00006144, 0x00006817, 0x00007387, 0x00009686, 0x00005229, 0x0000540f, 0x00005c65, 0x00006613, 0x0000674e, 0x000068a8, 0x00006ce5, 0x00007406, 0x000075e2, 0x00007f79, 0x000088cf, 0x000088e1, 0x000091cc, 0x000096e2, 0x0000533f, 0x00006eba, 0x0000541d, 0x000071d0, 0x00007498, 0x000085fa, 0x000096a3, 0x00009c57, 0x00009e9f, 0x00006797, 0x00006dcb, 0x000081e8, 0x00007acb, 0x00007b20, 0x00007c92, 0x000072c0, 0x00007099, 0x00008b58, 0x00004ec0, 0x00008336, 0x0000523a, 0x00005207, 0x00005ea6, 0x000062d3, 0x00007cd6, 0x00005b85, 0x00006d1e, 0x000066b4, 0x00008f3b, 0x0000884c, 0x0000964d, 0x0000898b, 0x00005ed3, 0x00005140, 0x000055c0, 0x0000585a, 0x00006674, 0x000051de, 0x0000732a, 0x000076ca, 0x0000793c, 0x0000795e, 0x00007965, 0x0000798f, 0x00009756, 0x00007cbe, 0x00007fbd, 0x00008612, 0x00008af8, 0x00009038, 0x000090fd, 0x000098ef, 0x000098fc, 0x00009928, 0x00009db4, 0x00004fae, 0x000050e7, 0x0000514d, 0x000052c9, 0x000052e4, 0x00005351, 0x0000559d, 0x00005606, 0x00005668, 0x00005840, 0x000058a8, 0x00005c64, 0x00005c6e, 0x00006094, 0x00006168, 0x0000618e, 0x000061f2, 0x0000654f, 0x000065e2, 0x00006691, 0x00006885, 0x00006d77, 0x00006e1a, 0x00006f22, 0x0000716e, 0x0000722b, 0x00007422, 0x00007891, 0x0000793e, 0x00007949, 0x00007948, 0x00007950, 0x00007956, 0x0000795d, 0x0000798d, 0x0000798e, 0x00007a40, 0x00007a81, 0x00007bc0, 0x00007df4, 0x00007e09, 0x00007e41, 0x00007f72, 0x00008005, 0x000081ed, 0x00008279, 0x00008279, 0x00008457, 0x00008910, 0x00008996, 0x00008b01, 0x00008b39, 0x00008cd3, 0x00008d08, 0x00008fb6, 0x00009038, 0x000096e3, 0x000097ff, 0x0000983b, 0x00000066, 0x00000066, 0x00000066, 0x00000069, 0x00000066, 0x0000006c, 0x00000066, 0x00000066, 0x00000069, 0x00000066, 0x00000066, 0x0000006c, 0x00000073, 0x00000074, 0x00000073, 0x00000074, 0x00000574, 0x00000576, 0x00000574, 0x00000565, 0x00000574, 0x0000056b, 0x0000057e, 0x00000576, 0x00000574, 0x0000056d, 0x000005d9, 0x000005b4, 0x000005f2, 0x000005b7, 0x000005e2, 0x000005d0, 0x000005d3, 0x000005d4, 0x000005db, 0x000005dc, 0x000005dd, 0x000005e8, 0x000005ea, 0x0000002b, 0x000005e9, 0x000005c1, 0x000005e9, 0x000005c2, 0x000005e9, 0x000005bc, 0x000005c1, 0x000005e9, 0x000005bc, 0x000005c2, 0x000005d0, 0x000005b7, 0x000005d0, 0x000005b8, 0x000005d0, 0x000005bc, 0x000005d1, 0x000005bc, 0x000005d2, 0x000005bc, 0x000005d3, 0x000005bc, 0x000005d4, 0x000005bc, 0x000005d5, 0x000005bc, 0x000005d6, 0x000005bc, 0x000005d8, 0x000005bc, 0x000005d9, 0x000005bc, 0x000005da, 0x000005bc, 0x000005db, 0x000005bc, 0x000005dc, 0x000005bc, 0x000005de, 0x000005bc, 0x000005e0, 0x000005bc, 0x000005e1, 0x000005bc, 0x000005e3, 0x000005bc, 0x000005e4, 0x000005bc, 0x000005e6, 0x000005bc, 0x000005e7, 0x000005bc, 0x000005e8, 0x000005bc, 0x000005e9, 0x000005bc, 0x000005ea, 0x000005bc, 0x000005d5, 0x000005b9, 0x000005d1, 0x000005bf, 0x000005db, 0x000005bf, 0x000005e4, 0x000005bf, 0x000005d0, 0x000005dc, 0x00000671, 0x00000671, 0x0000067b, 0x0000067b, 0x0000067b, 0x0000067b, 0x0000067e, 0x0000067e, 0x0000067e, 0x0000067e, 0x00000680, 0x00000680, 0x00000680, 0x00000680, 0x0000067a, 0x0000067a, 0x0000067a, 0x0000067a, 0x0000067f, 0x0000067f, 0x0000067f, 0x0000067f, 0x00000679, 0x00000679, 0x00000679, 0x00000679, 0x000006a4, 0x000006a4, 0x000006a4, 0x000006a4, 0x000006a6, 0x000006a6, 0x000006a6, 0x000006a6, 0x00000684, 0x00000684, 0x00000684, 0x00000684, 0x00000683, 0x00000683, 0x00000683, 0x00000683, 0x00000686, 0x00000686, 0x00000686, 0x00000686, 0x00000687, 0x00000687, 0x00000687, 0x00000687, 0x0000068d, 0x0000068d, 0x0000068c, 0x0000068c, 0x0000068e, 0x0000068e, 0x00000688, 0x00000688, 0x00000698, 0x00000698, 0x00000691, 0x00000691, 0x000006a9, 0x000006a9, 0x000006a9, 0x000006a9, 0x000006af, 0x000006af, 0x000006af, 0x000006af, 0x000006b3, 0x000006b3, 0x000006b3, 0x000006b3, 0x000006b1, 0x000006b1, 0x000006b1, 0x000006b1, 0x000006ba, 0x000006ba, 0x000006bb, 0x000006bb, 0x000006bb, 0x000006bb, 0x000006d5, 0x00000654, 0x000006d5, 0x00000654, 0x000006c1, 0x000006c1, 0x000006c1, 0x000006c1, 0x000006be, 0x000006be, 0x000006be, 0x000006be, 0x000006d2, 0x000006d2, 0x000006d2, 0x00000654, 0x000006d2, 0x00000654, 0x000006ad, 0x000006ad, 0x000006ad, 0x000006ad, 0x000006c7, 0x000006c7, 0x000006c6, 0x000006c6, 0x000006c8, 0x000006c8, 0x000006c7, 0x00000674, 0x000006cb, 0x000006cb, 0x000006c5, 0x000006c5, 0x000006c9, 0x000006c9, 0x000006d0, 0x000006d0, 0x000006d0, 0x000006d0, 0x00000649, 0x00000649, 0x0000064a, 0x00000654, 0x00000627, 0x0000064a, 0x00000654, 0x00000627, 0x0000064a, 0x00000654, 0x000006d5, 0x0000064a, 0x00000654, 0x000006d5, 0x0000064a, 0x00000654, 0x00000648, 0x0000064a, 0x00000654, 0x00000648, 0x0000064a, 0x00000654, 0x000006c7, 0x0000064a, 0x00000654, 0x000006c7, 0x0000064a, 0x00000654, 0x000006c6, 0x0000064a, 0x00000654, 0x000006c6, 0x0000064a, 0x00000654, 0x000006c8, 0x0000064a, 0x00000654, 0x000006c8, 0x0000064a, 0x00000654, 0x000006d0, 0x0000064a, 0x00000654, 0x000006d0, 0x0000064a, 0x00000654, 0x000006d0, 0x0000064a, 0x00000654, 0x00000649, 0x0000064a, 0x00000654, 0x00000649, 0x0000064a, 0x00000654, 0x00000649, 0x000006cc, 0x000006cc, 0x000006cc, 0x000006cc, 0x0000064a, 0x00000654, 0x0000062c, 0x0000064a, 0x00000654, 0x0000062d, 0x0000064a, 0x00000654, 0x00000645, 0x0000064a, 0x00000654, 0x00000649, 0x0000064a, 0x00000654, 0x0000064a, 0x00000628, 0x0000062c, 0x00000628, 0x0000062d, 0x00000628, 0x0000062e, 0x00000628, 0x00000645, 0x00000628, 0x00000649, 0x00000628, 0x0000064a, 0x0000062a, 0x0000062c, 0x0000062a, 0x0000062d, 0x0000062a, 0x0000062e, 0x0000062a, 0x00000645, 0x0000062a, 0x00000649, 0x0000062a, 0x0000064a, 0x0000062b, 0x0000062c, 0x0000062b, 0x00000645, 0x0000062b, 0x00000649, 0x0000062b, 0x0000064a, 0x0000062c, 0x0000062d, 0x0000062c, 0x00000645, 0x0000062d, 0x0000062c, 0x0000062d, 0x00000645, 0x0000062e, 0x0000062c, 0x0000062e, 0x0000062d, 0x0000062e, 0x00000645, 0x00000633, 0x0000062c, 0x00000633, 0x0000062d, 0x00000633, 0x0000062e, 0x00000633, 0x00000645, 0x00000635, 0x0000062d, 0x00000635, 0x00000645, 0x00000636, 0x0000062c, 0x00000636, 0x0000062d, 0x00000636, 0x0000062e, 0x00000636, 0x00000645, 0x00000637, 0x0000062d, 0x00000637, 0x00000645, 0x00000638, 0x00000645, 0x00000639, 0x0000062c, 0x00000639, 0x00000645, 0x0000063a, 0x0000062c, 0x0000063a, 0x00000645, 0x00000641, 0x0000062c, 0x00000641, 0x0000062d, 0x00000641, 0x0000062e, 0x00000641, 0x00000645, 0x00000641, 0x00000649, 0x00000641, 0x0000064a, 0x00000642, 0x0000062d, 0x00000642, 0x00000645, 0x00000642, 0x00000649, 0x00000642, 0x0000064a, 0x00000643, 0x00000627, 0x00000643, 0x0000062c, 0x00000643, 0x0000062d, 0x00000643, 0x0000062e, 0x00000643, 0x00000644, 0x00000643, 0x00000645, 0x00000643, 0x00000649, 0x00000643, 0x0000064a, 0x00000644, 0x0000062c, 0x00000644, 0x0000062d, 0x00000644, 0x0000062e, 0x00000644, 0x00000645, 0x00000644, 0x00000649, 0x00000644, 0x0000064a, 0x00000645, 0x0000062c, 0x00000645, 0x0000062d, 0x00000645, 0x0000062e, 0x00000645, 0x00000645, 0x00000645, 0x00000649, 0x00000645, 0x0000064a, 0x00000646, 0x0000062c, 0x00000646, 0x0000062d, 0x00000646, 0x0000062e, 0x00000646, 0x00000645, 0x00000646, 0x00000649, 0x00000646, 0x0000064a, 0x00000647, 0x0000062c, 0x00000647, 0x00000645, 0x00000647, 0x00000649, 0x00000647, 0x0000064a, 0x0000064a, 0x0000062c, 0x0000064a, 0x0000062d, 0x0000064a, 0x0000062e, 0x0000064a, 0x00000645, 0x0000064a, 0x00000649, 0x0000064a, 0x0000064a, 0x00000630, 0x00000670, 0x00000631, 0x00000670, 0x00000649, 0x00000670, 0x00000020, 0x0000064c, 0x00000651, 0x00000020, 0x0000064d, 0x00000651, 0x00000020, 0x0000064e, 0x00000651, 0x00000020, 0x0000064f, 0x00000651, 0x00000020, 0x00000650, 0x00000651, 0x00000020, 0x00000651, 0x00000670, 0x0000064a, 0x00000654, 0x00000631, 0x0000064a, 0x00000654, 0x00000632, 0x0000064a, 0x00000654, 0x00000645, 0x0000064a, 0x00000654, 0x00000646, 0x0000064a, 0x00000654, 0x00000649, 0x0000064a, 0x00000654, 0x0000064a, 0x00000628, 0x00000631, 0x00000628, 0x00000632, 0x00000628, 0x00000645, 0x00000628, 0x00000646, 0x00000628, 0x00000649, 0x00000628, 0x0000064a, 0x0000062a, 0x00000631, 0x0000062a, 0x00000632, 0x0000062a, 0x00000645, 0x0000062a, 0x00000646, 0x0000062a, 0x00000649, 0x0000062a, 0x0000064a, 0x0000062b, 0x00000631, 0x0000062b, 0x00000632, 0x0000062b, 0x00000645, 0x0000062b, 0x00000646, 0x0000062b, 0x00000649, 0x0000062b, 0x0000064a, 0x00000641, 0x00000649, 0x00000641, 0x0000064a, 0x00000642, 0x00000649, 0x00000642, 0x0000064a, 0x00000643, 0x00000627, 0x00000643, 0x00000644, 0x00000643, 0x00000645, 0x00000643, 0x00000649, 0x00000643, 0x0000064a, 0x00000644, 0x00000645, 0x00000644, 0x00000649, 0x00000644, 0x0000064a, 0x00000645, 0x00000627, 0x00000645, 0x00000645, 0x00000646, 0x00000631, 0x00000646, 0x00000632, 0x00000646, 0x00000645, 0x00000646, 0x00000646, 0x00000646, 0x00000649, 0x00000646, 0x0000064a, 0x00000649, 0x00000670, 0x0000064a, 0x00000631, 0x0000064a, 0x00000632, 0x0000064a, 0x00000645, 0x0000064a, 0x00000646, 0x0000064a, 0x00000649, 0x0000064a, 0x0000064a, 0x0000064a, 0x00000654, 0x0000062c, 0x0000064a, 0x00000654, 0x0000062d, 0x0000064a, 0x00000654, 0x0000062e, 0x0000064a, 0x00000654, 0x00000645, 0x0000064a, 0x00000654, 0x00000647, 0x00000628, 0x0000062c, 0x00000628, 0x0000062d, 0x00000628, 0x0000062e, 0x00000628, 0x00000645, 0x00000628, 0x00000647, 0x0000062a, 0x0000062c, 0x0000062a, 0x0000062d, 0x0000062a, 0x0000062e, 0x0000062a, 0x00000645, 0x0000062a, 0x00000647, 0x0000062b, 0x00000645, 0x0000062c, 0x0000062d, 0x0000062c, 0x00000645, 0x0000062d, 0x0000062c, 0x0000062d, 0x00000645, 0x0000062e, 0x0000062c, 0x0000062e, 0x00000645, 0x00000633, 0x0000062c, 0x00000633, 0x0000062d, 0x00000633, 0x0000062e, 0x00000633, 0x00000645, 0x00000635, 0x0000062d, 0x00000635, 0x0000062e, 0x00000635, 0x00000645, 0x00000636, 0x0000062c, 0x00000636, 0x0000062d, 0x00000636, 0x0000062e, 0x00000636, 0x00000645, 0x00000637, 0x0000062d, 0x00000638, 0x00000645, 0x00000639, 0x0000062c, 0x00000639, 0x00000645, 0x0000063a, 0x0000062c, 0x0000063a, 0x00000645, 0x00000641, 0x0000062c, 0x00000641, 0x0000062d, 0x00000641, 0x0000062e, 0x00000641, 0x00000645, 0x00000642, 0x0000062d, 0x00000642, 0x00000645, 0x00000643, 0x0000062c, 0x00000643, 0x0000062d, 0x00000643, 0x0000062e, 0x00000643, 0x00000644, 0x00000643, 0x00000645, 0x00000644, 0x0000062c, 0x00000644, 0x0000062d, 0x00000644, 0x0000062e, 0x00000644, 0x00000645, 0x00000644, 0x00000647, 0x00000645, 0x0000062c, 0x00000645, 0x0000062d, 0x00000645, 0x0000062e, 0x00000645, 0x00000645, 0x00000646, 0x0000062c, 0x00000646, 0x0000062d, 0x00000646, 0x0000062e, 0x00000646, 0x00000645, 0x00000646, 0x00000647, 0x00000647, 0x0000062c, 0x00000647, 0x00000645, 0x00000647, 0x00000670, 0x0000064a, 0x0000062c, 0x0000064a, 0x0000062d, 0x0000064a, 0x0000062e, 0x0000064a, 0x00000645, 0x0000064a, 0x00000647, 0x0000064a, 0x00000654, 0x00000645, 0x0000064a, 0x00000654, 0x00000647, 0x00000628, 0x00000645, 0x00000628, 0x00000647, 0x0000062a, 0x00000645, 0x0000062a, 0x00000647, 0x0000062b, 0x00000645, 0x0000062b, 0x00000647, 0x00000633, 0x00000645, 0x00000633, 0x00000647, 0x00000634, 0x00000645, 0x00000634, 0x00000647, 0x00000643, 0x00000644, 0x00000643, 0x00000645, 0x00000644, 0x00000645, 0x00000646, 0x00000645, 0x00000646, 0x00000647, 0x0000064a, 0x00000645, 0x0000064a, 0x00000647, 0x00000640, 0x0000064e, 0x00000651, 0x00000640, 0x0000064f, 0x00000651, 0x00000640, 0x00000650, 0x00000651, 0x00000637, 0x00000649, 0x00000637, 0x0000064a, 0x00000639, 0x00000649, 0x00000639, 0x0000064a, 0x0000063a, 0x00000649, 0x0000063a, 0x0000064a, 0x00000633, 0x00000649, 0x00000633, 0x0000064a, 0x00000634, 0x00000649, 0x00000634, 0x0000064a, 0x0000062d, 0x00000649, 0x0000062d, 0x0000064a, 0x0000062c, 0x00000649, 0x0000062c, 0x0000064a, 0x0000062e, 0x00000649, 0x0000062e, 0x0000064a, 0x00000635, 0x00000649, 0x00000635, 0x0000064a, 0x00000636, 0x00000649, 0x00000636, 0x0000064a, 0x00000634, 0x0000062c, 0x00000634, 0x0000062d, 0x00000634, 0x0000062e, 0x00000634, 0x00000645, 0x00000634, 0x00000631, 0x00000633, 0x00000631, 0x00000635, 0x00000631, 0x00000636, 0x00000631, 0x00000637, 0x00000649, 0x00000637, 0x0000064a, 0x00000639, 0x00000649, 0x00000639, 0x0000064a, 0x0000063a, 0x00000649, 0x0000063a, 0x0000064a, 0x00000633, 0x00000649, 0x00000633, 0x0000064a, 0x00000634, 0x00000649, 0x00000634, 0x0000064a, 0x0000062d, 0x00000649, 0x0000062d, 0x0000064a, 0x0000062c, 0x00000649, 0x0000062c, 0x0000064a, 0x0000062e, 0x00000649, 0x0000062e, 0x0000064a, 0x00000635, 0x00000649, 0x00000635, 0x0000064a, 0x00000636, 0x00000649, 0x00000636, 0x0000064a, 0x00000634, 0x0000062c, 0x00000634, 0x0000062d, 0x00000634, 0x0000062e, 0x00000634, 0x00000645, 0x00000634, 0x00000631, 0x00000633, 0x00000631, 0x00000635, 0x00000631, 0x00000636, 0x00000631, 0x00000634, 0x0000062c, 0x00000634, 0x0000062d, 0x00000634, 0x0000062e, 0x00000634, 0x00000645, 0x00000633, 0x00000647, 0x00000634, 0x00000647, 0x00000637, 0x00000645, 0x00000633, 0x0000062c, 0x00000633, 0x0000062d, 0x00000633, 0x0000062e, 0x00000634, 0x0000062c, 0x00000634, 0x0000062d, 0x00000634, 0x0000062e, 0x00000637, 0x00000645, 0x00000638, 0x00000645, 0x00000627, 0x0000064b, 0x00000627, 0x0000064b, 0x0000062a, 0x0000062c, 0x00000645, 0x0000062a, 0x0000062d, 0x0000062c, 0x0000062a, 0x0000062d, 0x0000062c, 0x0000062a, 0x0000062d, 0x00000645, 0x0000062a, 0x0000062e, 0x00000645, 0x0000062a, 0x00000645, 0x0000062c, 0x0000062a, 0x00000645, 0x0000062d, 0x0000062a, 0x00000645, 0x0000062e, 0x0000062c, 0x00000645, 0x0000062d, 0x0000062c, 0x00000645, 0x0000062d, 0x0000062d, 0x00000645, 0x0000064a, 0x0000062d, 0x00000645, 0x00000649, 0x00000633, 0x0000062d, 0x0000062c, 0x00000633, 0x0000062c, 0x0000062d, 0x00000633, 0x0000062c, 0x00000649, 0x00000633, 0x00000645, 0x0000062d, 0x00000633, 0x00000645, 0x0000062d, 0x00000633, 0x00000645, 0x0000062c, 0x00000633, 0x00000645, 0x00000645, 0x00000633, 0x00000645, 0x00000645, 0x00000635, 0x0000062d, 0x0000062d, 0x00000635, 0x0000062d, 0x0000062d, 0x00000635, 0x00000645, 0x00000645, 0x00000634, 0x0000062d, 0x00000645, 0x00000634, 0x0000062d, 0x00000645, 0x00000634, 0x0000062c, 0x0000064a, 0x00000634, 0x00000645, 0x0000062e, 0x00000634, 0x00000645, 0x0000062e, 0x00000634, 0x00000645, 0x00000645, 0x00000634, 0x00000645, 0x00000645, 0x00000636, 0x0000062d, 0x00000649, 0x00000636, 0x0000062e, 0x00000645, 0x00000636, 0x0000062e, 0x00000645, 0x00000637, 0x00000645, 0x0000062d, 0x00000637, 0x00000645, 0x0000062d, 0x00000637, 0x00000645, 0x00000645, 0x00000637, 0x00000645, 0x0000064a, 0x00000639, 0x0000062c, 0x00000645, 0x00000639, 0x00000645, 0x00000645, 0x00000639, 0x00000645, 0x00000645, 0x00000639, 0x00000645, 0x00000649, 0x0000063a, 0x00000645, 0x00000645, 0x0000063a, 0x00000645, 0x0000064a, 0x0000063a, 0x00000645, 0x00000649, 0x00000641, 0x0000062e, 0x00000645, 0x00000641, 0x0000062e, 0x00000645, 0x00000642, 0x00000645, 0x0000062d, 0x00000642, 0x00000645, 0x00000645, 0x00000644, 0x0000062d, 0x00000645, 0x00000644, 0x0000062d, 0x0000064a, 0x00000644, 0x0000062d, 0x00000649, 0x00000644, 0x0000062c, 0x0000062c, 0x00000644, 0x0000062c, 0x0000062c, 0x00000644, 0x0000062e, 0x00000645, 0x00000644, 0x0000062e, 0x00000645, 0x00000644, 0x00000645, 0x0000062d, 0x00000644, 0x00000645, 0x0000062d, 0x00000645, 0x0000062d, 0x0000062c, 0x00000645, 0x0000062d, 0x00000645, 0x00000645, 0x0000062d, 0x0000064a, 0x00000645, 0x0000062c, 0x0000062d, 0x00000645, 0x0000062c, 0x00000645, 0x00000645, 0x0000062e, 0x0000062c, 0x00000645, 0x0000062e, 0x00000645, 0x00000645, 0x0000062c, 0x0000062e, 0x00000647, 0x00000645, 0x0000062c, 0x00000647, 0x00000645, 0x00000645, 0x00000646, 0x0000062d, 0x00000645, 0x00000646, 0x0000062d, 0x00000649, 0x00000646, 0x0000062c, 0x00000645, 0x00000646, 0x0000062c, 0x00000645, 0x00000646, 0x0000062c, 0x00000649, 0x00000646, 0x00000645, 0x0000064a, 0x00000646, 0x00000645, 0x00000649, 0x0000064a, 0x00000645, 0x00000645, 0x0000064a, 0x00000645, 0x00000645, 0x00000628, 0x0000062e, 0x0000064a, 0x0000062a, 0x0000062c, 0x0000064a, 0x0000062a, 0x0000062c, 0x00000649, 0x0000062a, 0x0000062e, 0x0000064a, 0x0000062a, 0x0000062e, 0x00000649, 0x0000062a, 0x00000645, 0x0000064a, 0x0000062a, 0x00000645, 0x00000649, 0x0000062c, 0x00000645, 0x0000064a, 0x0000062c, 0x0000062d, 0x00000649, 0x0000062c, 0x00000645, 0x00000649, 0x00000633, 0x0000062e, 0x00000649, 0x00000635, 0x0000062d, 0x0000064a, 0x00000634, 0x0000062d, 0x0000064a, 0x00000636, 0x0000062d, 0x0000064a, 0x00000644, 0x0000062c, 0x0000064a, 0x00000644, 0x00000645, 0x0000064a, 0x0000064a, 0x0000062d, 0x0000064a, 0x0000064a, 0x0000062c, 0x0000064a, 0x0000064a, 0x00000645, 0x0000064a, 0x00000645, 0x00000645, 0x0000064a, 0x00000642, 0x00000645, 0x0000064a, 0x00000646, 0x0000062d, 0x0000064a, 0x00000642, 0x00000645, 0x0000062d, 0x00000644, 0x0000062d, 0x00000645, 0x00000639, 0x00000645, 0x0000064a, 0x00000643, 0x00000645, 0x0000064a, 0x00000646, 0x0000062c, 0x0000062d, 0x00000645, 0x0000062e, 0x0000064a, 0x00000644, 0x0000062c, 0x00000645, 0x00000643, 0x00000645, 0x00000645, 0x00000644, 0x0000062c, 0x00000645, 0x00000646, 0x0000062c, 0x0000062d, 0x0000062c, 0x0000062d, 0x0000064a, 0x0000062d, 0x0000062c, 0x0000064a, 0x00000645, 0x0000062c, 0x0000064a, 0x00000641, 0x00000645, 0x0000064a, 0x00000628, 0x0000062d, 0x0000064a, 0x00000643, 0x00000645, 0x00000645, 0x00000639, 0x0000062c, 0x00000645, 0x00000635, 0x00000645, 0x00000645, 0x00000633, 0x0000062e, 0x0000064a, 0x00000646, 0x0000062c, 0x0000064a, 0x00000635, 0x00000644, 0x000006d2, 0x00000642, 0x00000644, 0x000006d2, 0x00000627, 0x00000644, 0x00000644, 0x00000647, 0x00000627, 0x00000643, 0x00000628, 0x00000631, 0x00000645, 0x0000062d, 0x00000645, 0x0000062f, 0x00000635, 0x00000644, 0x00000639, 0x00000645, 0x00000631, 0x00000633, 0x00000648, 0x00000644, 0x00000639, 0x00000644, 0x0000064a, 0x00000647, 0x00000648, 0x00000633, 0x00000644, 0x00000645, 0x00000635, 0x00000644, 0x00000649, 0x00000635, 0x00000644, 0x00000649, 0x00000020, 0x00000627, 0x00000644, 0x00000644, 0x00000647, 0x00000020, 0x00000639, 0x00000644, 0x0000064a, 0x00000647, 0x00000020, 0x00000648, 0x00000633, 0x00000644, 0x00000645, 0x0000062c, 0x00000644, 0x00000020, 0x0000062c, 0x00000644, 0x00000627, 0x00000644, 0x00000647, 0x00000631, 0x000006cc, 0x00000627, 0x00000644, 0x0000002e, 0x0000002e, 0x00002014, 0x00002013, 0x0000005f, 0x0000005f, 0x00000028, 0x00000029, 0x0000007b, 0x0000007d, 0x00003014, 0x00003015, 0x00003010, 0x00003011, 0x0000300a, 0x0000300b, 0x00003008, 0x00003009, 0x0000300c, 0x0000300d, 0x0000300e, 0x0000300f, 0x00000020, 0x00000305, 0x00000020, 0x00000305, 0x00000020, 0x00000305, 0x00000020, 0x00000305, 0x0000005f, 0x0000005f, 0x0000005f, 0x0000002c, 0x00003001, 0x0000002e, 0x0000003b, 0x0000003a, 0x0000003f, 0x00000021, 0x00002014, 0x00000028, 0x00000029, 0x0000007b, 0x0000007d, 0x00003014, 0x00003015, 0x00000023, 0x00000026, 0x0000002a, 0x0000002b, 0x0000002d, 0x0000003c, 0x0000003e, 0x0000003d, 0x0000005c, 0x00000024, 0x00000025, 0x00000040, 0x00000020, 0x0000064b, 0x00000640, 0x0000064b, 0x00000020, 0x0000064c, 0x00000020, 0x0000064d, 0x00000020, 0x0000064e, 0x00000640, 0x0000064e, 0x00000020, 0x0000064f, 0x00000640, 0x0000064f, 0x00000020, 0x00000650, 0x00000640, 0x00000650, 0x00000020, 0x00000651, 0x00000640, 0x00000651, 0x00000020, 0x00000652, 0x00000640, 0x00000652, 0x00000621, 0x00000627, 0x00000653, 0x00000627, 0x00000653, 0x00000627, 0x00000654, 0x00000627, 0x00000654, 0x00000648, 0x00000654, 0x00000648, 0x00000654, 0x00000627, 0x00000655, 0x00000627, 0x00000655, 0x0000064a, 0x00000654, 0x0000064a, 0x00000654, 0x0000064a, 0x00000654, 0x0000064a, 0x00000654, 0x00000627, 0x00000627, 0x00000628, 0x00000628, 0x00000628, 0x00000628, 0x00000629, 0x00000629, 0x0000062a, 0x0000062a, 0x0000062a, 0x0000062a, 0x0000062b, 0x0000062b, 0x0000062b, 0x0000062b, 0x0000062c, 0x0000062c, 0x0000062c, 0x0000062c, 0x0000062d, 0x0000062d, 0x0000062d, 0x0000062d, 0x0000062e, 0x0000062e, 0x0000062e, 0x0000062e, 0x0000062f, 0x0000062f, 0x00000630, 0x00000630, 0x00000631, 0x00000631, 0x00000632, 0x00000632, 0x00000633, 0x00000633, 0x00000633, 0x00000633, 0x00000634, 0x00000634, 0x00000634, 0x00000634, 0x00000635, 0x00000635, 0x00000635, 0x00000635, 0x00000636, 0x00000636, 0x00000636, 0x00000636, 0x00000637, 0x00000637, 0x00000637, 0x00000637, 0x00000638, 0x00000638, 0x00000638, 0x00000638, 0x00000639, 0x00000639, 0x00000639, 0x00000639, 0x0000063a, 0x0000063a, 0x0000063a, 0x0000063a, 0x00000641, 0x00000641, 0x00000641, 0x00000641, 0x00000642, 0x00000642, 0x00000642, 0x00000642, 0x00000643, 0x00000643, 0x00000643, 0x00000643, 0x00000644, 0x00000644, 0x00000644, 0x00000644, 0x00000645, 0x00000645, 0x00000645, 0x00000645, 0x00000646, 0x00000646, 0x00000646, 0x00000646, 0x00000647, 0x00000647, 0x00000647, 0x00000647, 0x00000648, 0x00000648, 0x00000649, 0x00000649, 0x0000064a, 0x0000064a, 0x0000064a, 0x0000064a, 0x00000644, 0x00000627, 0x00000653, 0x00000644, 0x00000627, 0x00000653, 0x00000644, 0x00000627, 0x00000654, 0x00000644, 0x00000627, 0x00000654, 0x00000644, 0x00000627, 0x00000655, 0x00000644, 0x00000627, 0x00000655, 0x00000644, 0x00000627, 0x00000644, 0x00000627, 0x00000021, 0x00000022, 0x00000023, 0x00000024, 0x00000025, 0x00000026, 0x00000027, 0x00000028, 0x00000029, 0x0000002a, 0x0000002b, 0x0000002c, 0x0000002d, 0x0000002e, 0x0000002f, 0x00000030, 0x00000031, 0x00000032, 0x00000033, 0x00000034, 0x00000035, 0x00000036, 0x00000037, 0x00000038, 0x00000039, 0x0000003a, 0x0000003b, 0x0000003c, 0x0000003d, 0x0000003e, 0x0000003f, 0x00000040, 0x00000041, 0x00000042, 0x00000043, 0x00000044, 0x00000045, 0x00000046, 0x00000047, 0x00000048, 0x00000049, 0x0000004a, 0x0000004b, 0x0000004c, 0x0000004d, 0x0000004e, 0x0000004f, 0x00000050, 0x00000051, 0x00000052, 0x00000053, 0x00000054, 0x00000055, 0x00000056, 0x00000057, 0x00000058, 0x00000059, 0x0000005a, 0x0000005b, 0x0000005c, 0x0000005d, 0x0000005e, 0x0000005f, 0x00000060, 0x00000061, 0x00000062, 0x00000063, 0x00000064, 0x00000065, 0x00000066, 0x00000067, 0x00000068, 0x00000069, 0x0000006a, 0x0000006b, 0x0000006c, 0x0000006d, 0x0000006e, 0x0000006f, 0x00000070, 0x00000071, 0x00000072, 0x00000073, 0x00000074, 0x00000075, 0x00000076, 0x00000077, 0x00000078, 0x00000079, 0x0000007a, 0x0000007b, 0x0000007c, 0x0000007d, 0x0000007e, 0x00002985, 0x00002986, 0x00003002, 0x0000300c, 0x0000300d, 0x00003001, 0x000030fb, 0x000030f2, 0x000030a1, 0x000030a3, 0x000030a5, 0x000030a7, 0x000030a9, 0x000030e3, 0x000030e5, 0x000030e7, 0x000030c3, 0x000030fc, 0x000030a2, 0x000030a4, 0x000030a6, 0x000030a8, 0x000030aa, 0x000030ab, 0x000030ad, 0x000030af, 0x000030b1, 0x000030b3, 0x000030b5, 0x000030b7, 0x000030b9, 0x000030bb, 0x000030bd, 0x000030bf, 0x000030c1, 0x000030c4, 0x000030c6, 0x000030c8, 0x000030ca, 0x000030cb, 0x000030cc, 0x000030cd, 0x000030ce, 0x000030cf, 0x000030d2, 0x000030d5, 0x000030d8, 0x000030db, 0x000030de, 0x000030df, 0x000030e0, 0x000030e1, 0x000030e2, 0x000030e4, 0x000030e6, 0x000030e8, 0x000030e9, 0x000030ea, 0x000030eb, 0x000030ec, 0x000030ed, 0x000030ef, 0x000030f3, 0x00003099, 0x0000309a, 0x00001160, 0x00001100, 0x00001101, 0x000011aa, 0x00001102, 0x000011ac, 0x000011ad, 0x00001103, 0x00001104, 0x00001105, 0x000011b0, 0x000011b1, 0x000011b2, 0x000011b3, 0x000011b4, 0x000011b5, 0x0000111a, 0x00001106, 0x00001107, 0x00001108, 0x00001121, 0x00001109, 0x0000110a, 0x0000110b, 0x0000110c, 0x0000110d, 0x0000110e, 0x0000110f, 0x00001110, 0x00001111, 0x00001112, 0x00001161, 0x00001162, 0x00001163, 0x00001164, 0x00001165, 0x00001166, 0x00001167, 0x00001168, 0x00001169, 0x0000116a, 0x0000116b, 0x0000116c, 0x0000116d, 0x0000116e, 0x0000116f, 0x00001170, 0x00001171, 0x00001172, 0x00001173, 0x00001174, 0x00001175, 0x000000a2, 0x000000a3, 0x000000ac, 0x00000020, 0x00000304, 0x000000a6, 0x000000a5, 0x000020a9, 0x00002502, 0x00002190, 0x00002191, 0x00002192, 0x00002193, 0x000025a0, 0x000025cb, 0x0001d157, 0x0001d165, 0x0001d158, 0x0001d165, 0x0001d158, 0x0001d165, 0x0001d16e, 0x0001d158, 0x0001d165, 0x0001d16f, 0x0001d158, 0x0001d165, 0x0001d170, 0x0001d158, 0x0001d165, 0x0001d171, 0x0001d158, 0x0001d165, 0x0001d172, 0x0001d1b9, 0x0001d165, 0x0001d1ba, 0x0001d165, 0x0001d1b9, 0x0001d165, 0x0001d16e, 0x0001d1ba, 0x0001d165, 0x0001d16e, 0x0001d1b9, 0x0001d165, 0x0001d16f, 0x0001d1ba, 0x0001d165, 0x0001d16f, 0x00000041, 0x00000042, 0x00000043, 0x00000044, 0x00000045, 0x00000046, 0x00000047, 0x00000048, 0x00000049, 0x0000004a, 0x0000004b, 0x0000004c, 0x0000004d, 0x0000004e, 0x0000004f, 0x00000050, 0x00000051, 0x00000052, 0x00000053, 0x00000054, 0x00000055, 0x00000056, 0x00000057, 0x00000058, 0x00000059, 0x0000005a, 0x00000061, 0x00000062, 0x00000063, 0x00000064, 0x00000065, 0x00000066, 0x00000067, 0x00000068, 0x00000069, 0x0000006a, 0x0000006b, 0x0000006c, 0x0000006d, 0x0000006e, 0x0000006f, 0x00000070, 0x00000071, 0x00000072, 0x00000073, 0x00000074, 0x00000075, 0x00000076, 0x00000077, 0x00000078, 0x00000079, 0x0000007a, 0x00000041, 0x00000042, 0x00000043, 0x00000044, 0x00000045, 0x00000046, 0x00000047, 0x00000048, 0x00000049, 0x0000004a, 0x0000004b, 0x0000004c, 0x0000004d, 0x0000004e, 0x0000004f, 0x00000050, 0x00000051, 0x00000052, 0x00000053, 0x00000054, 0x00000055, 0x00000056, 0x00000057, 0x00000058, 0x00000059, 0x0000005a, 0x00000061, 0x00000062, 0x00000063, 0x00000064, 0x00000065, 0x00000066, 0x00000067, 0x00000069, 0x0000006a, 0x0000006b, 0x0000006c, 0x0000006d, 0x0000006e, 0x0000006f, 0x00000070, 0x00000071, 0x00000072, 0x00000073, 0x00000074, 0x00000075, 0x00000076, 0x00000077, 0x00000078, 0x00000079, 0x0000007a, 0x00000041, 0x00000042, 0x00000043, 0x00000044, 0x00000045, 0x00000046, 0x00000047, 0x00000048, 0x00000049, 0x0000004a, 0x0000004b, 0x0000004c, 0x0000004d, 0x0000004e, 0x0000004f, 0x00000050, 0x00000051, 0x00000052, 0x00000053, 0x00000054, 0x00000055, 0x00000056, 0x00000057, 0x00000058, 0x00000059, 0x0000005a, 0x00000061, 0x00000062, 0x00000063, 0x00000064, 0x00000065, 0x00000066, 0x00000067, 0x00000068, 0x00000069, 0x0000006a, 0x0000006b, 0x0000006c, 0x0000006d, 0x0000006e, 0x0000006f, 0x00000070, 0x00000071, 0x00000072, 0x00000073, 0x00000074, 0x00000075, 0x00000076, 0x00000077, 0x00000078, 0x00000079, 0x0000007a, 0x00000041, 0x00000043, 0x00000044, 0x00000047, 0x0000004a, 0x0000004b, 0x0000004e, 0x0000004f, 0x00000050, 0x00000051, 0x00000053, 0x00000054, 0x00000055, 0x00000056, 0x00000057, 0x00000058, 0x00000059, 0x0000005a, 0x00000061, 0x00000062, 0x00000063, 0x00000064, 0x00000066, 0x00000068, 0x00000069, 0x0000006a, 0x0000006b, 0x0000006d, 0x0000006e, 0x00000070, 0x00000071, 0x00000072, 0x00000073, 0x00000074, 0x00000075, 0x00000076, 0x00000077, 0x00000078, 0x00000079, 0x0000007a, 0x00000041, 0x00000042, 0x00000043, 0x00000044, 0x00000045, 0x00000046, 0x00000047, 0x00000048, 0x00000049, 0x0000004a, 0x0000004b, 0x0000004c, 0x0000004d, 0x0000004e, 0x0000004f, 0x00000050, 0x00000051, 0x00000052, 0x00000053, 0x00000054, 0x00000055, 0x00000056, 0x00000057, 0x00000058, 0x00000059, 0x0000005a, 0x00000061, 0x00000062, 0x00000063, 0x00000064, 0x00000065, 0x00000066, 0x00000067, 0x00000068, 0x00000069, 0x0000006a, 0x0000006b, 0x0000006c, 0x0000006d, 0x0000006e, 0x0000006f, 0x00000070, 0x00000071, 0x00000072, 0x00000073, 0x00000074, 0x00000075, 0x00000076, 0x00000077, 0x00000078, 0x00000079, 0x0000007a, 0x00000041, 0x00000042, 0x00000044, 0x00000045, 0x00000046, 0x00000047, 0x0000004a, 0x0000004b, 0x0000004c, 0x0000004d, 0x0000004e, 0x0000004f, 0x00000050, 0x00000051, 0x00000053, 0x00000054, 0x00000055, 0x00000056, 0x00000057, 0x00000058, 0x00000059, 0x00000061, 0x00000062, 0x00000063, 0x00000064, 0x00000065, 0x00000066, 0x00000067, 0x00000068, 0x00000069, 0x0000006a, 0x0000006b, 0x0000006c, 0x0000006d, 0x0000006e, 0x0000006f, 0x00000070, 0x00000071, 0x00000072, 0x00000073, 0x00000074, 0x00000075, 0x00000076, 0x00000077, 0x00000078, 0x00000079, 0x0000007a, 0x00000041, 0x00000042, 0x00000044, 0x00000045, 0x00000046, 0x00000047, 0x00000049, 0x0000004a, 0x0000004b, 0x0000004c, 0x0000004d, 0x0000004f, 0x00000053, 0x00000054, 0x00000055, 0x00000056, 0x00000057, 0x00000058, 0x00000059, 0x00000061, 0x00000062, 0x00000063, 0x00000064, 0x00000065, 0x00000066, 0x00000067, 0x00000068, 0x00000069, 0x0000006a, 0x0000006b, 0x0000006c, 0x0000006d, 0x0000006e, 0x0000006f, 0x00000070, 0x00000071, 0x00000072, 0x00000073, 0x00000074, 0x00000075, 0x00000076, 0x00000077, 0x00000078, 0x00000079, 0x0000007a, 0x00000041, 0x00000042, 0x00000043, 0x00000044, 0x00000045, 0x00000046, 0x00000047, 0x00000048, 0x00000049, 0x0000004a, 0x0000004b, 0x0000004c, 0x0000004d, 0x0000004e, 0x0000004f, 0x00000050, 0x00000051, 0x00000052, 0x00000053, 0x00000054, 0x00000055, 0x00000056, 0x00000057, 0x00000058, 0x00000059, 0x0000005a, 0x00000061, 0x00000062, 0x00000063, 0x00000064, 0x00000065, 0x00000066, 0x00000067, 0x00000068, 0x00000069, 0x0000006a, 0x0000006b, 0x0000006c, 0x0000006d, 0x0000006e, 0x0000006f, 0x00000070, 0x00000071, 0x00000072, 0x00000073, 0x00000074, 0x00000075, 0x00000076, 0x00000077, 0x00000078, 0x00000079, 0x0000007a, 0x00000041, 0x00000042, 0x00000043, 0x00000044, 0x00000045, 0x00000046, 0x00000047, 0x00000048, 0x00000049, 0x0000004a, 0x0000004b, 0x0000004c, 0x0000004d, 0x0000004e, 0x0000004f, 0x00000050, 0x00000051, 0x00000052, 0x00000053, 0x00000054, 0x00000055, 0x00000056, 0x00000057, 0x00000058, 0x00000059, 0x0000005a, 0x00000061, 0x00000062, 0x00000063, 0x00000064, 0x00000065, 0x00000066, 0x00000067, 0x00000068, 0x00000069, 0x0000006a, 0x0000006b, 0x0000006c, 0x0000006d, 0x0000006e, 0x0000006f, 0x00000070, 0x00000071, 0x00000072, 0x00000073, 0x00000074, 0x00000075, 0x00000076, 0x00000077, 0x00000078, 0x00000079, 0x0000007a, 0x00000041, 0x00000042, 0x00000043, 0x00000044, 0x00000045, 0x00000046, 0x00000047, 0x00000048, 0x00000049, 0x0000004a, 0x0000004b, 0x0000004c, 0x0000004d, 0x0000004e, 0x0000004f, 0x00000050, 0x00000051, 0x00000052, 0x00000053, 0x00000054, 0x00000055, 0x00000056, 0x00000057, 0x00000058, 0x00000059, 0x0000005a, 0x00000061, 0x00000062, 0x00000063, 0x00000064, 0x00000065, 0x00000066, 0x00000067, 0x00000068, 0x00000069, 0x0000006a, 0x0000006b, 0x0000006c, 0x0000006d, 0x0000006e, 0x0000006f, 0x00000070, 0x00000071, 0x00000072, 0x00000073, 0x00000074, 0x00000075, 0x00000076, 0x00000077, 0x00000078, 0x00000079, 0x0000007a, 0x00000041, 0x00000042, 0x00000043, 0x00000044, 0x00000045, 0x00000046, 0x00000047, 0x00000048, 0x00000049, 0x0000004a, 0x0000004b, 0x0000004c, 0x0000004d, 0x0000004e, 0x0000004f, 0x00000050, 0x00000051, 0x00000052, 0x00000053, 0x00000054, 0x00000055, 0x00000056, 0x00000057, 0x00000058, 0x00000059, 0x0000005a, 0x00000061, 0x00000062, 0x00000063, 0x00000064, 0x00000065, 0x00000066, 0x00000067, 0x00000068, 0x00000069, 0x0000006a, 0x0000006b, 0x0000006c, 0x0000006d, 0x0000006e, 0x0000006f, 0x00000070, 0x00000071, 0x00000072, 0x00000073, 0x00000074, 0x00000075, 0x00000076, 0x00000077, 0x00000078, 0x00000079, 0x0000007a, 0x00000041, 0x00000042, 0x00000043, 0x00000044, 0x00000045, 0x00000046, 0x00000047, 0x00000048, 0x00000049, 0x0000004a, 0x0000004b, 0x0000004c, 0x0000004d, 0x0000004e, 0x0000004f, 0x00000050, 0x00000051, 0x00000052, 0x00000053, 0x00000054, 0x00000055, 0x00000056, 0x00000057, 0x00000058, 0x00000059, 0x0000005a, 0x00000061, 0x00000062, 0x00000063, 0x00000064, 0x00000065, 0x00000066, 0x00000067, 0x00000068, 0x00000069, 0x0000006a, 0x0000006b, 0x0000006c, 0x0000006d, 0x0000006e, 0x0000006f, 0x00000070, 0x00000071, 0x00000072, 0x00000073, 0x00000074, 0x00000075, 0x00000076, 0x00000077, 0x00000078, 0x00000079, 0x0000007a, 0x00000041, 0x00000042, 0x00000043, 0x00000044, 0x00000045, 0x00000046, 0x00000047, 0x00000048, 0x00000049, 0x0000004a, 0x0000004b, 0x0000004c, 0x0000004d, 0x0000004e, 0x0000004f, 0x00000050, 0x00000051, 0x00000052, 0x00000053, 0x00000054, 0x00000055, 0x00000056, 0x00000057, 0x00000058, 0x00000059, 0x0000005a, 0x00000061, 0x00000062, 0x00000063, 0x00000064, 0x00000065, 0x00000066, 0x00000067, 0x00000068, 0x00000069, 0x0000006a, 0x0000006b, 0x0000006c, 0x0000006d, 0x0000006e, 0x0000006f, 0x00000070, 0x00000071, 0x00000072, 0x00000073, 0x00000074, 0x00000075, 0x00000076, 0x00000077, 0x00000078, 0x00000079, 0x0000007a, 0x00000391, 0x00000392, 0x00000393, 0x00000394, 0x00000395, 0x00000396, 0x00000397, 0x00000398, 0x00000399, 0x0000039a, 0x0000039b, 0x0000039c, 0x0000039d, 0x0000039e, 0x0000039f, 0x000003a0, 0x000003a1, 0x00000398, 0x000003a3, 0x000003a4, 0x000003a5, 0x000003a6, 0x000003a7, 0x000003a8, 0x000003a9, 0x00002207, 0x000003b1, 0x000003b2, 0x000003b3, 0x000003b4, 0x000003b5, 0x000003b6, 0x000003b7, 0x000003b8, 0x000003b9, 0x000003ba, 0x000003bb, 0x000003bc, 0x000003bd, 0x000003be, 0x000003bf, 0x000003c0, 0x000003c1, 0x000003c2, 0x000003c3, 0x000003c4, 0x000003c5, 0x000003c6, 0x000003c7, 0x000003c8, 0x000003c9, 0x00002202, 0x000003b5, 0x000003b8, 0x000003ba, 0x000003c6, 0x000003c1, 0x000003c0, 0x00000391, 0x00000392, 0x00000393, 0x00000394, 0x00000395, 0x00000396, 0x00000397, 0x00000398, 0x00000399, 0x0000039a, 0x0000039b, 0x0000039c, 0x0000039d, 0x0000039e, 0x0000039f, 0x000003a0, 0x000003a1, 0x00000398, 0x000003a3, 0x000003a4, 0x000003a5, 0x000003a6, 0x000003a7, 0x000003a8, 0x000003a9, 0x00002207, 0x000003b1, 0x000003b2, 0x000003b3, 0x000003b4, 0x000003b5, 0x000003b6, 0x000003b7, 0x000003b8, 0x000003b9, 0x000003ba, 0x000003bb, 0x000003bc, 0x000003bd, 0x000003be, 0x000003bf, 0x000003c0, 0x000003c1, 0x000003c2, 0x000003c3, 0x000003c4, 0x000003c5, 0x000003c6, 0x000003c7, 0x000003c8, 0x000003c9, 0x00002202, 0x000003b5, 0x000003b8, 0x000003ba, 0x000003c6, 0x000003c1, 0x000003c0, 0x00000391, 0x00000392, 0x00000393, 0x00000394, 0x00000395, 0x00000396, 0x00000397, 0x00000398, 0x00000399, 0x0000039a, 0x0000039b, 0x0000039c, 0x0000039d, 0x0000039e, 0x0000039f, 0x000003a0, 0x000003a1, 0x00000398, 0x000003a3, 0x000003a4, 0x000003a5, 0x000003a6, 0x000003a7, 0x000003a8, 0x000003a9, 0x00002207, 0x000003b1, 0x000003b2, 0x000003b3, 0x000003b4, 0x000003b5, 0x000003b6, 0x000003b7, 0x000003b8, 0x000003b9, 0x000003ba, 0x000003bb, 0x000003bc, 0x000003bd, 0x000003be, 0x000003bf, 0x000003c0, 0x000003c1, 0x000003c2, 0x000003c3, 0x000003c4, 0x000003c5, 0x000003c6, 0x000003c7, 0x000003c8, 0x000003c9, 0x00002202, 0x000003b5, 0x000003b8, 0x000003ba, 0x000003c6, 0x000003c1, 0x000003c0, 0x00000391, 0x00000392, 0x00000393, 0x00000394, 0x00000395, 0x00000396, 0x00000397, 0x00000398, 0x00000399, 0x0000039a, 0x0000039b, 0x0000039c, 0x0000039d, 0x0000039e, 0x0000039f, 0x000003a0, 0x000003a1, 0x00000398, 0x000003a3, 0x000003a4, 0x000003a5, 0x000003a6, 0x000003a7, 0x000003a8, 0x000003a9, 0x00002207, 0x000003b1, 0x000003b2, 0x000003b3, 0x000003b4, 0x000003b5, 0x000003b6, 0x000003b7, 0x000003b8, 0x000003b9, 0x000003ba, 0x000003bb, 0x000003bc, 0x000003bd, 0x000003be, 0x000003bf, 0x000003c0, 0x000003c1, 0x000003c2, 0x000003c3, 0x000003c4, 0x000003c5, 0x000003c6, 0x000003c7, 0x000003c8, 0x000003c9, 0x00002202, 0x000003b5, 0x000003b8, 0x000003ba, 0x000003c6, 0x000003c1, 0x000003c0, 0x00000391, 0x00000392, 0x00000393, 0x00000394, 0x00000395, 0x00000396, 0x00000397, 0x00000398, 0x00000399, 0x0000039a, 0x0000039b, 0x0000039c, 0x0000039d, 0x0000039e, 0x0000039f, 0x000003a0, 0x000003a1, 0x00000398, 0x000003a3, 0x000003a4, 0x000003a5, 0x000003a6, 0x000003a7, 0x000003a8, 0x000003a9, 0x00002207, 0x000003b1, 0x000003b2, 0x000003b3, 0x000003b4, 0x000003b5, 0x000003b6, 0x000003b7, 0x000003b8, 0x000003b9, 0x000003ba, 0x000003bb, 0x000003bc, 0x000003bd, 0x000003be, 0x000003bf, 0x000003c0, 0x000003c1, 0x000003c2, 0x000003c3, 0x000003c4, 0x000003c5, 0x000003c6, 0x000003c7, 0x000003c8, 0x000003c9, 0x00002202, 0x000003b5, 0x000003b8, 0x000003ba, 0x000003c6, 0x000003c1, 0x000003c0, 0x00000030, 0x00000031, 0x00000032, 0x00000033, 0x00000034, 0x00000035, 0x00000036, 0x00000037, 0x00000038, 0x00000039, 0x00000030, 0x00000031, 0x00000032, 0x00000033, 0x00000034, 0x00000035, 0x00000036, 0x00000037, 0x00000038, 0x00000039, 0x00000030, 0x00000031, 0x00000032, 0x00000033, 0x00000034, 0x00000035, 0x00000036, 0x00000037, 0x00000038, 0x00000039, 0x00000030, 0x00000031, 0x00000032, 0x00000033, 0x00000034, 0x00000035, 0x00000036, 0x00000037, 0x00000038, 0x00000039, 0x00000030, 0x00000031, 0x00000032, 0x00000033, 0x00000034, 0x00000035, 0x00000036, 0x00000037, 0x00000038, 0x00000039, 0x00004e3d, 0x00004e38, 0x00004e41, 0x00020122, 0x00004f60, 0x00004fae, 0x00004fbb, 0x00005002, 0x0000507a, 0x00005099, 0x000050e7, 0x000050cf, 0x0000349e, 0x0002063a, 0x0000514d, 0x00005154, 0x00005164, 0x00005177, 0x0002051c, 0x000034b9, 0x00005167, 0x0000518d, 0x0002054b, 0x00005197, 0x000051a4, 0x00004ecc, 0x000051ac, 0x000051b5, 0x000291df, 0x000051f5, 0x00005203, 0x000034df, 0x0000523b, 0x00005246, 0x00005272, 0x00005277, 0x00003515, 0x000052c7, 0x000052c9, 0x000052e4, 0x000052fa, 0x00005305, 0x00005306, 0x00005317, 0x00005349, 0x00005351, 0x0000535a, 0x00005373, 0x0000537d, 0x0000537f, 0x0000537f, 0x0000537f, 0x00020a2c, 0x00007070, 0x000053ca, 0x000053df, 0x00020b63, 0x000053eb, 0x000053f1, 0x00005406, 0x0000549e, 0x00005438, 0x00005448, 0x00005468, 0x000054a2, 0x000054f6, 0x00005510, 0x00005553, 0x00005563, 0x00005584, 0x00005584, 0x00005599, 0x000055ab, 0x000055b3, 0x000055c2, 0x00005716, 0x00005606, 0x00005717, 0x00005651, 0x00005674, 0x00005207, 0x000058ee, 0x000057ce, 0x000057f4, 0x0000580d, 0x0000578b, 0x00005832, 0x00005831, 0x000058ac, 0x000214e4, 0x000058f2, 0x000058f7, 0x00005906, 0x0000591a, 0x00005922, 0x00005962, 0x000216a8, 0x000216ea, 0x000059ec, 0x00005a1b, 0x00005a27, 0x000059d8, 0x00005a66, 0x000036ee, 0x0002136a, 0x00005b08, 0x00005b3e, 0x00005b3e, 0x000219c8, 0x00005bc3, 0x00005bd8, 0x00005be7, 0x00005bf3, 0x00021b18, 0x00005bff, 0x00005c06, 0x00005f33, 0x00005c22, 0x00003781, 0x00005c60, 0x00005c6e, 0x00005cc0, 0x00005c8d, 0x00021de4, 0x00005d43, 0x00021de6, 0x00005d6e, 0x00005d6b, 0x00005d7c, 0x00005de1, 0x00005de2, 0x0000382f, 0x00005dfd, 0x00005e28, 0x00005e3d, 0x00005e69, 0x00003862, 0x00022183, 0x0000387c, 0x00005eb0, 0x00005eb3, 0x00005eb6, 0x00005eca, 0x0002a392, 0x00005efe, 0x00022331, 0x00022331, 0x00008201, 0x00005f22, 0x00005f22, 0x000038c7, 0x000232b8, 0x000261da, 0x00005f62, 0x00005f6b, 0x000038e3, 0x00005f9a, 0x00005fcd, 0x00005fd7, 0x00005ff9, 0x00006081, 0x0000393a, 0x0000391c, 0x00006094, 0x000226d4, 0x000060c7, 0x00006148, 0x0000614c, 0x0000614e, 0x0000614c, 0x0000617a, 0x0000618e, 0x000061b2, 0x000061a4, 0x000061af, 0x000061de, 0x000061f2, 0x000061f6, 0x00006210, 0x0000621b, 0x0000625d, 0x000062b1, 0x000062d4, 0x00006350, 0x00022b0c, 0x0000633d, 0x000062fc, 0x00006368, 0x00006383, 0x000063e4, 0x00022bf1, 0x00006422, 0x000063c5, 0x000063a9, 0x00003a2e, 0x00006469, 0x0000647e, 0x0000649d, 0x00006477, 0x00003a6c, 0x0000654f, 0x0000656c, 0x0002300a, 0x000065e3, 0x000066f8, 0x00006649, 0x00003b19, 0x00006691, 0x00003b08, 0x00003ae4, 0x00005192, 0x00005195, 0x00006700, 0x0000669c, 0x000080ad, 0x000043d9, 0x00006717, 0x0000671b, 0x00006721, 0x0000675e, 0x00006753, 0x000233c3, 0x00003b49, 0x000067fa, 0x00006785, 0x00006852, 0x00006885, 0x0002346d, 0x0000688e, 0x0000681f, 0x00006914, 0x00003b9d, 0x00006942, 0x000069a3, 0x000069ea, 0x00006aa8, 0x000236a3, 0x00006adb, 0x00003c18, 0x00006b21, 0x000238a7, 0x00006b54, 0x00003c4e, 0x00006b72, 0x00006b9f, 0x00006bba, 0x00006bbb, 0x00023a8d, 0x00021d0b, 0x00023afa, 0x00006c4e, 0x00023cbc, 0x00006cbf, 0x00006ccd, 0x00006c67, 0x00006d16, 0x00006d3e, 0x00006d77, 0x00006d41, 0x00006d69, 0x00006d78, 0x00006d85, 0x00023d1e, 0x00006d34, 0x00006e2f, 0x00006e6e, 0x00003d33, 0x00006ecb, 0x00006ec7, 0x00023ed1, 0x00006df9, 0x00006f6e, 0x00023f5e, 0x00023f8e, 0x00006fc6, 0x00007039, 0x0000701e, 0x0000701b, 0x00003d96, 0x0000704a, 0x0000707d, 0x00007077, 0x000070ad, 0x00020525, 0x00007145, 0x00024263, 0x0000719c, 0x000043ab, 0x00007228, 0x00007235, 0x00007250, 0x00024608, 0x00007280, 0x00007295, 0x00024735, 0x00024814, 0x0000737a, 0x0000738b, 0x00003eac, 0x000073a5, 0x00003eb8, 0x00003eb8, 0x00007447, 0x0000745c, 0x00007471, 0x00007485, 0x000074ca, 0x00003f1b, 0x00007524, 0x00024c36, 0x0000753e, 0x00024c92, 0x00007570, 0x0002219f, 0x00007610, 0x00024fa1, 0x00024fb8, 0x00025044, 0x00003ffc, 0x00004008, 0x000076f4, 0x000250f3, 0x000250f2, 0x00025119, 0x00025133, 0x0000771e, 0x0000771f, 0x0000771f, 0x0000774a, 0x00004039, 0x0000778b, 0x00004046, 0x00004096, 0x0002541d, 0x0000784e, 0x0000788c, 0x000078cc, 0x000040e3, 0x00025626, 0x00007956, 0x0002569a, 0x000256c5, 0x0000798f, 0x000079eb, 0x0000412f, 0x00007a40, 0x00007a4a, 0x00007a4f, 0x0002597c, 0x00025aa7, 0x00025aa7, 0x00007aae, 0x00004202, 0x00025bab, 0x00007bc6, 0x00007bc9, 0x00004227, 0x00025c80, 0x00007cd2, 0x000042a0, 0x00007ce8, 0x00007ce3, 0x00007d00, 0x00025f86, 0x00007d63, 0x00004301, 0x00007dc7, 0x00007e02, 0x00007e45, 0x00004334, 0x00026228, 0x00026247, 0x00004359, 0x000262d9, 0x00007f7a, 0x0002633e, 0x00007f95, 0x00007ffa, 0x00008005, 0x000264da, 0x00026523, 0x00008060, 0x000265a8, 0x00008070, 0x0002335f, 0x000043d5, 0x000080b2, 0x00008103, 0x0000440b, 0x0000813e, 0x00005ab5, 0x000267a7, 0x000267b5, 0x00023393, 0x0002339c, 0x00008201, 0x00008204, 0x00008f9e, 0x0000446b, 0x00008291, 0x0000828b, 0x0000829d, 0x000052b3, 0x000082b1, 0x000082b3, 0x000082bd, 0x000082e6, 0x00026b3c, 0x000082e5, 0x0000831d, 0x00008363, 0x000083ad, 0x00008323, 0x000083bd, 0x000083e7, 0x00008457, 0x00008353, 0x000083ca, 0x000083cc, 0x000083dc, 0x00026c36, 0x00026d6b, 0x00026cd5, 0x0000452b, 0x000084f1, 0x000084f3, 0x00008516, 0x000273ca, 0x00008564, 0x00026f2c, 0x0000455d, 0x00004561, 0x00026fb1, 0x000270d2, 0x0000456b, 0x00008650, 0x0000865c, 0x00008667, 0x00008669, 0x000086a9, 0x00008688, 0x0000870e, 0x000086e2, 0x00008779, 0x00008728, 0x0000876b, 0x00008786, 0x00004d57, 0x000087e1, 0x00008801, 0x000045f9, 0x00008860, 0x00008863, 0x00027667, 0x000088d7, 0x000088de, 0x00004635, 0x000088fa, 0x000034bb, 0x000278ae, 0x00027966, 0x000046be, 0x000046c7, 0x00008aa0, 0x00008aed, 0x00008b8a, 0x00008c55, 0x00027ca8, 0x00008cab, 0x00008cc1, 0x00008d1b, 0x00008d77, 0x00027f2f, 0x00020804, 0x00008dcb, 0x00008dbc, 0x00008df0, 0x000208de, 0x00008ed4, 0x00008f38, 0x000285d2, 0x000285ed, 0x00009094, 0x000090f1, 0x00009111, 0x0002872e, 0x0000911b, 0x00009238, 0x000092d7, 0x000092d8, 0x0000927c, 0x000093f9, 0x00009415, 0x00028bfa, 0x0000958b, 0x00004995, 0x000095b7, 0x00028d77, 0x000049e6, 0x000096c3, 0x00005db2, 0x00009723, 0x00029145, 0x0002921a, 0x00004a6e, 0x00004a76, 0x000097e0, 0x0002940a, 0x00004ab2, 0x00029496, 0x0000980b, 0x0000980b, 0x00009829, 0x000295b6, 0x000098e2, 0x00004b33, 0x00009929, 0x000099a7, 0x000099c2, 0x000099fe, 0x00004bce, 0x00029b30, 0x00009b12, 0x00009c40, 0x00009cfd, 0x00004cce, 0x00004ced, 0x00009d67, 0x0002a0ce, 0x00004cf8, 0x0002a105, 0x0002a20e, 0x0002a291, 0x00009ebb, 0x00004d56, 0x00009ef9, 0x00009efe, 0x00009f05, 0x00009f0f, 0x00009f16, 0x00009f3b, 0x0002a600 }; static const ac_uint4 _uccmcl_size = 489; static const ac_uint4 _uccmcl_nodes[] = { 0x00000300, 0x00000314, 0x000000e6, 0x00000315, 0x00000315, 0x000000e8, 0x00000316, 0x00000319, 0x000000dc, 0x0000031a, 0x0000031a, 0x000000e8, 0x0000031b, 0x0000031b, 0x000000d8, 0x0000031c, 0x00000320, 0x000000dc, 0x00000321, 0x00000322, 0x000000ca, 0x00000323, 0x00000326, 0x000000dc, 0x00000327, 0x00000328, 0x000000ca, 0x00000329, 0x00000333, 0x000000dc, 0x00000334, 0x00000338, 0x00000001, 0x00000339, 0x0000033c, 0x000000dc, 0x0000033d, 0x00000344, 0x000000e6, 0x00000345, 0x00000345, 0x000000f0, 0x00000346, 0x00000346, 0x000000e6, 0x00000347, 0x00000349, 0x000000dc, 0x0000034a, 0x0000034c, 0x000000e6, 0x0000034d, 0x0000034e, 0x000000dc, 0x00000360, 0x00000361, 0x000000ea, 0x00000362, 0x00000362, 0x000000e9, 0x00000363, 0x0000036f, 0x000000e6, 0x00000483, 0x00000486, 0x000000e6, 0x00000591, 0x00000591, 0x000000dc, 0x00000592, 0x00000595, 0x000000e6, 0x00000596, 0x00000596, 0x000000dc, 0x00000597, 0x00000599, 0x000000e6, 0x0000059a, 0x0000059a, 0x000000de, 0x0000059b, 0x0000059b, 0x000000dc, 0x0000059c, 0x000005a1, 0x000000e6, 0x000005a3, 0x000005a7, 0x000000dc, 0x000005a8, 0x000005a9, 0x000000e6, 0x000005aa, 0x000005aa, 0x000000dc, 0x000005ab, 0x000005ac, 0x000000e6, 0x000005ad, 0x000005ad, 0x000000de, 0x000005ae, 0x000005ae, 0x000000e4, 0x000005af, 0x000005af, 0x000000e6, 0x000005b0, 0x000005b0, 0x0000000a, 0x000005b1, 0x000005b1, 0x0000000b, 0x000005b2, 0x000005b2, 0x0000000c, 0x000005b3, 0x000005b3, 0x0000000d, 0x000005b4, 0x000005b4, 0x0000000e, 0x000005b5, 0x000005b5, 0x0000000f, 0x000005b6, 0x000005b6, 0x00000010, 0x000005b7, 0x000005b7, 0x00000011, 0x000005b8, 0x000005b8, 0x00000012, 0x000005b9, 0x000005b9, 0x00000013, 0x000005bb, 0x000005bb, 0x00000014, 0x000005bc, 0x000005bc, 0x00000015, 0x000005bd, 0x000005bd, 0x00000016, 0x000005bf, 0x000005bf, 0x00000017, 0x000005c1, 0x000005c1, 0x00000018, 0x000005c2, 0x000005c2, 0x00000019, 0x000005c4, 0x000005c4, 0x000000e6, 0x0000064b, 0x0000064b, 0x0000001b, 0x0000064c, 0x0000064c, 0x0000001c, 0x0000064d, 0x0000064d, 0x0000001d, 0x0000064e, 0x0000064e, 0x0000001e, 0x0000064f, 0x0000064f, 0x0000001f, 0x00000650, 0x00000650, 0x00000020, 0x00000651, 0x00000651, 0x00000021, 0x00000652, 0x00000652, 0x00000022, 0x00000653, 0x00000654, 0x000000e6, 0x00000655, 0x00000655, 0x000000dc, 0x00000670, 0x00000670, 0x00000023, 0x000006d6, 0x000006dc, 0x000000e6, 0x000006df, 0x000006e2, 0x000000e6, 0x000006e3, 0x000006e3, 0x000000dc, 0x000006e4, 0x000006e4, 0x000000e6, 0x000006e7, 0x000006e8, 0x000000e6, 0x000006ea, 0x000006ea, 0x000000dc, 0x000006eb, 0x000006ec, 0x000000e6, 0x000006ed, 0x000006ed, 0x000000dc, 0x00000711, 0x00000711, 0x00000024, 0x00000730, 0x00000730, 0x000000e6, 0x00000731, 0x00000731, 0x000000dc, 0x00000732, 0x00000733, 0x000000e6, 0x00000734, 0x00000734, 0x000000dc, 0x00000735, 0x00000736, 0x000000e6, 0x00000737, 0x00000739, 0x000000dc, 0x0000073a, 0x0000073a, 0x000000e6, 0x0000073b, 0x0000073c, 0x000000dc, 0x0000073d, 0x0000073d, 0x000000e6, 0x0000073e, 0x0000073e, 0x000000dc, 0x0000073f, 0x00000741, 0x000000e6, 0x00000742, 0x00000742, 0x000000dc, 0x00000743, 0x00000743, 0x000000e6, 0x00000744, 0x00000744, 0x000000dc, 0x00000745, 0x00000745, 0x000000e6, 0x00000746, 0x00000746, 0x000000dc, 0x00000747, 0x00000747, 0x000000e6, 0x00000748, 0x00000748, 0x000000dc, 0x00000749, 0x0000074a, 0x000000e6, 0x0000093c, 0x0000093c, 0x00000007, 0x0000094d, 0x0000094d, 0x00000009, 0x00000951, 0x00000951, 0x000000e6, 0x00000952, 0x00000952, 0x000000dc, 0x00000953, 0x00000954, 0x000000e6, 0x000009bc, 0x000009bc, 0x00000007, 0x000009cd, 0x000009cd, 0x00000009, 0x00000a3c, 0x00000a3c, 0x00000007, 0x00000a4d, 0x00000a4d, 0x00000009, 0x00000abc, 0x00000abc, 0x00000007, 0x00000acd, 0x00000acd, 0x00000009, 0x00000b3c, 0x00000b3c, 0x00000007, 0x00000b4d, 0x00000b4d, 0x00000009, 0x00000bcd, 0x00000bcd, 0x00000009, 0x00000c4d, 0x00000c4d, 0x00000009, 0x00000c55, 0x00000c55, 0x00000054, 0x00000c56, 0x00000c56, 0x0000005b, 0x00000ccd, 0x00000ccd, 0x00000009, 0x00000d4d, 0x00000d4d, 0x00000009, 0x00000dca, 0x00000dca, 0x00000009, 0x00000e38, 0x00000e39, 0x00000067, 0x00000e3a, 0x00000e3a, 0x00000009, 0x00000e48, 0x00000e4b, 0x0000006b, 0x00000eb8, 0x00000eb9, 0x00000076, 0x00000ec8, 0x00000ecb, 0x0000007a, 0x00000f18, 0x00000f19, 0x000000dc, 0x00000f35, 0x00000f35, 0x000000dc, 0x00000f37, 0x00000f37, 0x000000dc, 0x00000f39, 0x00000f39, 0x000000d8, 0x00000f71, 0x00000f71, 0x00000081, 0x00000f72, 0x00000f72, 0x00000082, 0x00000f74, 0x00000f74, 0x00000084, 0x00000f7a, 0x00000f7d, 0x00000082, 0x00000f80, 0x00000f80, 0x00000082, 0x00000f82, 0x00000f83, 0x000000e6, 0x00000f84, 0x00000f84, 0x00000009, 0x00000f86, 0x00000f87, 0x000000e6, 0x00000fc6, 0x00000fc6, 0x000000dc, 0x00001037, 0x00001037, 0x00000007, 0x00001039, 0x00001039, 0x00000009, 0x00001714, 0x00001714, 0x00000009, 0x00001734, 0x00001734, 0x00000009, 0x000017d2, 0x000017d2, 0x00000009, 0x000018a9, 0x000018a9, 0x000000e4, 0x000020d0, 0x000020d1, 0x000000e6, 0x000020d2, 0x000020d3, 0x00000001, 0x000020d4, 0x000020d7, 0x000000e6, 0x000020d8, 0x000020da, 0x00000001, 0x000020db, 0x000020dc, 0x000000e6, 0x000020e1, 0x000020e1, 0x000000e6, 0x000020e5, 0x000020e6, 0x00000001, 0x000020e7, 0x000020e7, 0x000000e6, 0x000020e8, 0x000020e8, 0x000000dc, 0x000020e9, 0x000020e9, 0x000000e6, 0x000020ea, 0x000020ea, 0x00000001, 0x0000302a, 0x0000302a, 0x000000da, 0x0000302b, 0x0000302b, 0x000000e4, 0x0000302c, 0x0000302c, 0x000000e8, 0x0000302d, 0x0000302d, 0x000000de, 0x0000302e, 0x0000302f, 0x000000e0, 0x00003099, 0x0000309a, 0x00000008, 0x0000fb1e, 0x0000fb1e, 0x0000001a, 0x0000fe20, 0x0000fe23, 0x000000e6, 0x0001d165, 0x0001d166, 0x000000d8, 0x0001d167, 0x0001d169, 0x00000001, 0x0001d16d, 0x0001d16d, 0x000000e2, 0x0001d16e, 0x0001d172, 0x000000d8, 0x0001d17b, 0x0001d182, 0x000000dc, 0x0001d185, 0x0001d189, 0x000000e6, 0x0001d18a, 0x0001d18b, 0x000000dc, 0x0001d1aa, 0x0001d1ad, 0x000000e6 }; static const ac_uint4 _ucnum_size = 1066; static const ac_uint4 _ucnum_nodes[] = { 0x00000030, 0x00000000, 0x00000031, 0x00000002, 0x00000032, 0x00000004, 0x00000033, 0x00000006, 0x00000034, 0x00000008, 0x00000035, 0x0000000a, 0x00000036, 0x0000000c, 0x00000037, 0x0000000e, 0x00000038, 0x00000010, 0x00000039, 0x00000012, 0x000000b2, 0x00000004, 0x000000b3, 0x00000006, 0x000000b9, 0x00000002, 0x000000bc, 0x00000014, 0x000000bd, 0x00000016, 0x000000be, 0x00000018, 0x00000660, 0x00000000, 0x00000661, 0x00000002, 0x00000662, 0x00000004, 0x00000663, 0x00000006, 0x00000664, 0x00000008, 0x00000665, 0x0000000a, 0x00000666, 0x0000000c, 0x00000667, 0x0000000e, 0x00000668, 0x00000010, 0x00000669, 0x00000012, 0x000006f0, 0x00000000, 0x000006f1, 0x00000002, 0x000006f2, 0x00000004, 0x000006f3, 0x00000006, 0x000006f4, 0x00000008, 0x000006f5, 0x0000000a, 0x000006f6, 0x0000000c, 0x000006f7, 0x0000000e, 0x000006f8, 0x00000010, 0x000006f9, 0x00000012, 0x00000966, 0x00000000, 0x00000967, 0x00000002, 0x00000968, 0x00000004, 0x00000969, 0x00000006, 0x0000096a, 0x00000008, 0x0000096b, 0x0000000a, 0x0000096c, 0x0000000c, 0x0000096d, 0x0000000e, 0x0000096e, 0x00000010, 0x0000096f, 0x00000012, 0x000009e6, 0x00000000, 0x000009e7, 0x00000002, 0x000009e8, 0x00000004, 0x000009e9, 0x00000006, 0x000009ea, 0x00000008, 0x000009eb, 0x0000000a, 0x000009ec, 0x0000000c, 0x000009ed, 0x0000000e, 0x000009ee, 0x00000010, 0x000009ef, 0x00000012, 0x000009f4, 0x00000002, 0x000009f5, 0x00000004, 0x000009f6, 0x00000006, 0x000009f7, 0x00000008, 0x000009f9, 0x0000001a, 0x00000a66, 0x00000000, 0x00000a67, 0x00000002, 0x00000a68, 0x00000004, 0x00000a69, 0x00000006, 0x00000a6a, 0x00000008, 0x00000a6b, 0x0000000a, 0x00000a6c, 0x0000000c, 0x00000a6d, 0x0000000e, 0x00000a6e, 0x00000010, 0x00000a6f, 0x00000012, 0x00000ae6, 0x00000000, 0x00000ae7, 0x00000002, 0x00000ae8, 0x00000004, 0x00000ae9, 0x00000006, 0x00000aea, 0x00000008, 0x00000aeb, 0x0000000a, 0x00000aec, 0x0000000c, 0x00000aed, 0x0000000e, 0x00000aee, 0x00000010, 0x00000aef, 0x00000012, 0x00000b66, 0x00000000, 0x00000b67, 0x00000002, 0x00000b68, 0x00000004, 0x00000b69, 0x00000006, 0x00000b6a, 0x00000008, 0x00000b6b, 0x0000000a, 0x00000b6c, 0x0000000c, 0x00000b6d, 0x0000000e, 0x00000b6e, 0x00000010, 0x00000b6f, 0x00000012, 0x00000be7, 0x00000002, 0x00000be8, 0x00000004, 0x00000be9, 0x00000006, 0x00000bea, 0x00000008, 0x00000beb, 0x0000000a, 0x00000bec, 0x0000000c, 0x00000bed, 0x0000000e, 0x00000bee, 0x00000010, 0x00000bef, 0x00000012, 0x00000bf0, 0x0000001c, 0x00000bf1, 0x0000001e, 0x00000bf2, 0x00000020, 0x00000c66, 0x00000000, 0x00000c67, 0x00000002, 0x00000c68, 0x00000004, 0x00000c69, 0x00000006, 0x00000c6a, 0x00000008, 0x00000c6b, 0x0000000a, 0x00000c6c, 0x0000000c, 0x00000c6d, 0x0000000e, 0x00000c6e, 0x00000010, 0x00000c6f, 0x00000012, 0x00000ce6, 0x00000000, 0x00000ce7, 0x00000002, 0x00000ce8, 0x00000004, 0x00000ce9, 0x00000006, 0x00000cea, 0x00000008, 0x00000ceb, 0x0000000a, 0x00000cec, 0x0000000c, 0x00000ced, 0x0000000e, 0x00000cee, 0x00000010, 0x00000cef, 0x00000012, 0x00000d66, 0x00000000, 0x00000d67, 0x00000002, 0x00000d68, 0x00000004, 0x00000d69, 0x00000006, 0x00000d6a, 0x00000008, 0x00000d6b, 0x0000000a, 0x00000d6c, 0x0000000c, 0x00000d6d, 0x0000000e, 0x00000d6e, 0x00000010, 0x00000d6f, 0x00000012, 0x00000e50, 0x00000000, 0x00000e51, 0x00000002, 0x00000e52, 0x00000004, 0x00000e53, 0x00000006, 0x00000e54, 0x00000008, 0x00000e55, 0x0000000a, 0x00000e56, 0x0000000c, 0x00000e57, 0x0000000e, 0x00000e58, 0x00000010, 0x00000e59, 0x00000012, 0x00000ed0, 0x00000000, 0x00000ed1, 0x00000002, 0x00000ed2, 0x00000004, 0x00000ed3, 0x00000006, 0x00000ed4, 0x00000008, 0x00000ed5, 0x0000000a, 0x00000ed6, 0x0000000c, 0x00000ed7, 0x0000000e, 0x00000ed8, 0x00000010, 0x00000ed9, 0x00000012, 0x00000f20, 0x00000000, 0x00000f21, 0x00000002, 0x00000f22, 0x00000004, 0x00000f23, 0x00000006, 0x00000f24, 0x00000008, 0x00000f25, 0x0000000a, 0x00000f26, 0x0000000c, 0x00000f27, 0x0000000e, 0x00000f28, 0x00000010, 0x00000f29, 0x00000012, 0x00000f2a, 0x00000016, 0x00000f2b, 0x00000022, 0x00000f2c, 0x00000024, 0x00000f2d, 0x00000026, 0x00000f2e, 0x00000028, 0x00000f2f, 0x0000002a, 0x00000f30, 0x0000002c, 0x00000f31, 0x0000002e, 0x00000f32, 0x00000030, 0x00000f33, 0x00000032, 0x00001040, 0x00000000, 0x00001041, 0x00000002, 0x00001042, 0x00000004, 0x00001043, 0x00000006, 0x00001044, 0x00000008, 0x00001045, 0x0000000a, 0x00001046, 0x0000000c, 0x00001047, 0x0000000e, 0x00001048, 0x00000010, 0x00001049, 0x00000012, 0x00001369, 0x00000002, 0x0000136a, 0x00000004, 0x0000136b, 0x00000006, 0x0000136c, 0x00000008, 0x0000136d, 0x0000000a, 0x0000136e, 0x0000000c, 0x0000136f, 0x0000000e, 0x00001370, 0x00000010, 0x00001371, 0x00000012, 0x00001372, 0x0000001c, 0x00001373, 0x00000034, 0x00001374, 0x00000036, 0x00001375, 0x00000038, 0x00001376, 0x0000003a, 0x00001377, 0x0000003c, 0x00001378, 0x0000003e, 0x00001379, 0x00000040, 0x0000137a, 0x00000042, 0x0000137b, 0x0000001e, 0x0000137c, 0x00000044, 0x000016ee, 0x00000046, 0x000016ef, 0x00000048, 0x000016f0, 0x0000004a, 0x000017e0, 0x00000000, 0x000017e1, 0x00000002, 0x000017e2, 0x00000004, 0x000017e3, 0x00000006, 0x000017e4, 0x00000008, 0x000017e5, 0x0000000a, 0x000017e6, 0x0000000c, 0x000017e7, 0x0000000e, 0x000017e8, 0x00000010, 0x000017e9, 0x00000012, 0x00001810, 0x00000000, 0x00001811, 0x00000002, 0x00001812, 0x00000004, 0x00001813, 0x00000006, 0x00001814, 0x00000008, 0x00001815, 0x0000000a, 0x00001816, 0x0000000c, 0x00001817, 0x0000000e, 0x00001818, 0x00000010, 0x00001819, 0x00000012, 0x00002070, 0x00000000, 0x00002074, 0x00000008, 0x00002075, 0x0000000a, 0x00002076, 0x0000000c, 0x00002077, 0x0000000e, 0x00002078, 0x00000010, 0x00002079, 0x00000012, 0x00002080, 0x00000000, 0x00002081, 0x00000002, 0x00002082, 0x00000004, 0x00002083, 0x00000006, 0x00002084, 0x00000008, 0x00002085, 0x0000000a, 0x00002086, 0x0000000c, 0x00002087, 0x0000000e, 0x00002088, 0x00000010, 0x00002089, 0x00000012, 0x00002153, 0x0000004c, 0x00002154, 0x0000004e, 0x00002155, 0x00000050, 0x00002156, 0x00000052, 0x00002157, 0x00000054, 0x00002158, 0x00000056, 0x00002159, 0x00000058, 0x0000215a, 0x0000005a, 0x0000215b, 0x0000005c, 0x0000215c, 0x0000005e, 0x0000215d, 0x00000060, 0x0000215e, 0x00000062, 0x0000215f, 0x00000002, 0x00002160, 0x00000002, 0x00002161, 0x00000004, 0x00002162, 0x00000006, 0x00002163, 0x00000008, 0x00002164, 0x0000000a, 0x00002165, 0x0000000c, 0x00002166, 0x0000000e, 0x00002167, 0x00000010, 0x00002168, 0x00000012, 0x00002169, 0x0000001c, 0x0000216a, 0x00000064, 0x0000216b, 0x00000066, 0x0000216c, 0x0000003a, 0x0000216d, 0x0000001e, 0x0000216e, 0x00000068, 0x0000216f, 0x00000020, 0x00002170, 0x00000002, 0x00002171, 0x00000004, 0x00002172, 0x00000006, 0x00002173, 0x00000008, 0x00002174, 0x0000000a, 0x00002175, 0x0000000c, 0x00002176, 0x0000000e, 0x00002177, 0x00000010, 0x00002178, 0x00000012, 0x00002179, 0x0000001c, 0x0000217a, 0x00000064, 0x0000217b, 0x00000066, 0x0000217c, 0x0000003a, 0x0000217d, 0x0000001e, 0x0000217e, 0x00000068, 0x0000217f, 0x00000020, 0x00002180, 0x00000020, 0x00002181, 0x0000006a, 0x00002182, 0x00000044, 0x00002460, 0x00000002, 0x00002461, 0x00000004, 0x00002462, 0x00000006, 0x00002463, 0x00000008, 0x00002464, 0x0000000a, 0x00002465, 0x0000000c, 0x00002466, 0x0000000e, 0x00002467, 0x00000010, 0x00002468, 0x00000012, 0x00002469, 0x0000001c, 0x0000246a, 0x00000064, 0x0000246b, 0x00000066, 0x0000246c, 0x0000006c, 0x0000246d, 0x0000006e, 0x0000246e, 0x00000070, 0x0000246f, 0x0000001a, 0x00002470, 0x00000046, 0x00002471, 0x00000048, 0x00002472, 0x0000004a, 0x00002473, 0x00000034, 0x00002474, 0x00000002, 0x00002475, 0x00000004, 0x00002476, 0x00000006, 0x00002477, 0x00000008, 0x00002478, 0x0000000a, 0x00002479, 0x0000000c, 0x0000247a, 0x0000000e, 0x0000247b, 0x00000010, 0x0000247c, 0x00000012, 0x0000247d, 0x0000001c, 0x0000247e, 0x00000064, 0x0000247f, 0x00000066, 0x00002480, 0x0000006c, 0x00002481, 0x0000006e, 0x00002482, 0x00000070, 0x00002483, 0x0000001a, 0x00002484, 0x00000046, 0x00002485, 0x00000048, 0x00002486, 0x0000004a, 0x00002487, 0x00000034, 0x00002488, 0x00000002, 0x00002489, 0x00000004, 0x0000248a, 0x00000006, 0x0000248b, 0x00000008, 0x0000248c, 0x0000000a, 0x0000248d, 0x0000000c, 0x0000248e, 0x0000000e, 0x0000248f, 0x00000010, 0x00002490, 0x00000012, 0x00002491, 0x0000001c, 0x00002492, 0x00000064, 0x00002493, 0x00000066, 0x00002494, 0x0000006c, 0x00002495, 0x0000006e, 0x00002496, 0x00000070, 0x00002497, 0x0000001a, 0x00002498, 0x00000046, 0x00002499, 0x00000048, 0x0000249a, 0x0000004a, 0x0000249b, 0x00000034, 0x000024ea, 0x00000000, 0x000024eb, 0x00000064, 0x000024ec, 0x00000066, 0x000024ed, 0x0000006c, 0x000024ee, 0x0000006e, 0x000024ef, 0x00000070, 0x000024f0, 0x0000001a, 0x000024f1, 0x00000046, 0x000024f2, 0x00000048, 0x000024f3, 0x0000004a, 0x000024f4, 0x00000034, 0x000024f5, 0x00000002, 0x000024f6, 0x00000004, 0x000024f7, 0x00000006, 0x000024f8, 0x00000008, 0x000024f9, 0x0000000a, 0x000024fa, 0x0000000c, 0x000024fb, 0x0000000e, 0x000024fc, 0x00000010, 0x000024fd, 0x00000012, 0x000024fe, 0x0000001c, 0x00002776, 0x00000002, 0x00002777, 0x00000004, 0x00002778, 0x00000006, 0x00002779, 0x00000008, 0x0000277a, 0x0000000a, 0x0000277b, 0x0000000c, 0x0000277c, 0x0000000e, 0x0000277d, 0x00000010, 0x0000277e, 0x00000012, 0x0000277f, 0x0000001c, 0x00002780, 0x00000002, 0x00002781, 0x00000004, 0x00002782, 0x00000006, 0x00002783, 0x00000008, 0x00002784, 0x0000000a, 0x00002785, 0x0000000c, 0x00002786, 0x0000000e, 0x00002787, 0x00000010, 0x00002788, 0x00000012, 0x00002789, 0x0000001c, 0x0000278a, 0x00000002, 0x0000278b, 0x00000004, 0x0000278c, 0x00000006, 0x0000278d, 0x00000008, 0x0000278e, 0x0000000a, 0x0000278f, 0x0000000c, 0x00002790, 0x0000000e, 0x00002791, 0x00000010, 0x00002792, 0x00000012, 0x00002793, 0x0000001c, 0x00003007, 0x00000000, 0x00003021, 0x00000002, 0x00003022, 0x00000004, 0x00003023, 0x00000006, 0x00003024, 0x00000008, 0x00003025, 0x0000000a, 0x00003026, 0x0000000c, 0x00003027, 0x0000000e, 0x00003028, 0x00000010, 0x00003029, 0x00000012, 0x00003038, 0x0000001c, 0x00003039, 0x00000034, 0x0000303a, 0x00000036, 0x00003192, 0x00000002, 0x00003193, 0x00000004, 0x00003194, 0x00000006, 0x00003195, 0x00000008, 0x00003220, 0x00000002, 0x00003221, 0x00000004, 0x00003222, 0x00000006, 0x00003223, 0x00000008, 0x00003224, 0x0000000a, 0x00003225, 0x0000000c, 0x00003226, 0x0000000e, 0x00003227, 0x00000010, 0x00003228, 0x00000012, 0x00003229, 0x0000001c, 0x00003251, 0x00000072, 0x00003252, 0x00000074, 0x00003253, 0x00000076, 0x00003254, 0x00000078, 0x00003255, 0x0000007a, 0x00003256, 0x0000007c, 0x00003257, 0x0000007e, 0x00003258, 0x00000080, 0x00003259, 0x00000082, 0x0000325a, 0x00000036, 0x0000325b, 0x00000084, 0x0000325c, 0x00000086, 0x0000325d, 0x00000088, 0x0000325e, 0x0000008a, 0x0000325f, 0x0000008c, 0x00003280, 0x00000002, 0x00003281, 0x00000004, 0x00003282, 0x00000006, 0x00003283, 0x00000008, 0x00003284, 0x0000000a, 0x00003285, 0x0000000c, 0x00003286, 0x0000000e, 0x00003287, 0x00000010, 0x00003288, 0x00000012, 0x00003289, 0x0000001c, 0x000032b1, 0x0000008e, 0x000032b2, 0x00000090, 0x000032b3, 0x00000092, 0x000032b4, 0x00000094, 0x000032b5, 0x00000038, 0x000032b6, 0x00000096, 0x000032b7, 0x00000098, 0x000032b8, 0x0000009a, 0x000032b9, 0x0000009c, 0x000032ba, 0x0000009e, 0x000032bb, 0x000000a0, 0x000032bc, 0x000000a2, 0x000032bd, 0x000000a4, 0x000032be, 0x000000a6, 0x000032bf, 0x0000003a, 0x0000ff10, 0x00000000, 0x0000ff11, 0x00000002, 0x0000ff12, 0x00000004, 0x0000ff13, 0x00000006, 0x0000ff14, 0x00000008, 0x0000ff15, 0x0000000a, 0x0000ff16, 0x0000000c, 0x0000ff17, 0x0000000e, 0x0000ff18, 0x00000010, 0x0000ff19, 0x00000012, 0x00010320, 0x00000002, 0x00010321, 0x0000000a, 0x00010322, 0x0000001c, 0x00010323, 0x0000003a, 0x0001d7ce, 0x00000000, 0x0001d7cf, 0x00000002, 0x0001d7d0, 0x00000004, 0x0001d7d1, 0x00000006, 0x0001d7d2, 0x00000008, 0x0001d7d3, 0x0000000a, 0x0001d7d4, 0x0000000c, 0x0001d7d5, 0x0000000e, 0x0001d7d6, 0x00000010, 0x0001d7d7, 0x00000012, 0x0001d7d8, 0x00000000, 0x0001d7d9, 0x00000002, 0x0001d7da, 0x00000004, 0x0001d7db, 0x00000006, 0x0001d7dc, 0x00000008, 0x0001d7dd, 0x0000000a, 0x0001d7de, 0x0000000c, 0x0001d7df, 0x0000000e, 0x0001d7e0, 0x00000010, 0x0001d7e1, 0x00000012, 0x0001d7e2, 0x00000000, 0x0001d7e3, 0x00000002, 0x0001d7e4, 0x00000004, 0x0001d7e5, 0x00000006, 0x0001d7e6, 0x00000008, 0x0001d7e7, 0x0000000a, 0x0001d7e8, 0x0000000c, 0x0001d7e9, 0x0000000e, 0x0001d7ea, 0x00000010, 0x0001d7eb, 0x00000012, 0x0001d7ec, 0x00000000, 0x0001d7ed, 0x00000002, 0x0001d7ee, 0x00000004, 0x0001d7ef, 0x00000006, 0x0001d7f0, 0x00000008, 0x0001d7f1, 0x0000000a, 0x0001d7f2, 0x0000000c, 0x0001d7f3, 0x0000000e, 0x0001d7f4, 0x00000010, 0x0001d7f5, 0x00000012, 0x0001d7f6, 0x00000000, 0x0001d7f7, 0x00000002, 0x0001d7f8, 0x00000004, 0x0001d7f9, 0x00000006, 0x0001d7fa, 0x00000008, 0x0001d7fb, 0x0000000a, 0x0001d7fc, 0x0000000c, 0x0001d7fd, 0x0000000e, 0x0001d7fe, 0x00000010, 0x0001d7ff, 0x00000012 }; static const short _ucnum_vals[] = { 0x0000, 0x0001, 0x0001, 0x0001, 0x0002, 0x0001, 0x0003, 0x0001, 0x0004, 0x0001, 0x0005, 0x0001, 0x0006, 0x0001, 0x0007, 0x0001, 0x0008, 0x0001, 0x0009, 0x0001, 0x0001, 0x0004, 0x0001, 0x0002, 0x0003, 0x0004, 0x0010, 0x0001, 0x000a, 0x0001, 0x0064, 0x0001, 0x03e8, 0x0001, 0x0003, 0x0002, 0x0005, 0x0002, 0x0007, 0x0002, 0x0009, 0x0002, 0x000b, 0x0002, 0x000d, 0x0002, 0x000f, 0x0002, 0x0011, 0x0002, -1, 0x0002, 0x0014, 0x0001, 0x001e, 0x0001, 0x0028, 0x0001, 0x0032, 0x0001, 0x003c, 0x0001, 0x0046, 0x0001, 0x0050, 0x0001, 0x005a, 0x0001, 0x2710, 0x0001, 0x0011, 0x0001, 0x0012, 0x0001, 0x0013, 0x0001, 0x0001, 0x0003, 0x0002, 0x0003, 0x0001, 0x0005, 0x0002, 0x0005, 0x0003, 0x0005, 0x0004, 0x0005, 0x0001, 0x0006, 0x0005, 0x0006, 0x0001, 0x0008, 0x0003, 0x0008, 0x0005, 0x0008, 0x0007, 0x0008, 0x000b, 0x0001, 0x000c, 0x0001, 0x01f4, 0x0001, 0x1388, 0x0001, 0x000d, 0x0001, 0x000e, 0x0001, 0x000f, 0x0001, 0x0015, 0x0001, 0x0016, 0x0001, 0x0017, 0x0001, 0x0018, 0x0001, 0x0019, 0x0001, 0x001a, 0x0001, 0x001b, 0x0001, 0x001c, 0x0001, 0x001d, 0x0001, 0x001f, 0x0001, 0x0020, 0x0001, 0x0021, 0x0001, 0x0022, 0x0001, 0x0023, 0x0001, 0x0024, 0x0001, 0x0025, 0x0001, 0x0026, 0x0001, 0x0027, 0x0001, 0x0029, 0x0001, 0x002a, 0x0001, 0x002b, 0x0001, 0x002c, 0x0001, 0x002d, 0x0001, 0x002e, 0x0001, 0x002f, 0x0001, 0x0030, 0x0001, 0x0031, 0x0001 }; openldap-2.4.42+dfsg/libraries/liblunicode/ucdata/ucpgba.c0000644000175000017500000005567712563404150022167 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Copyright 2001 Computing Research Labs, New Mexico State University * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* $Id: ucpgba.c,v 1.5 2001/01/02 18:46:20 mleisher Exp $ */ #include "portable.h" #include #include #include "ucdata.h" #include "ucpgba.h" /* * These macros are used while reordering of RTL runs of text for the * special case of non-spacing characters being in runs of weakly * directional text. They check for weak and non-spacing, and digits and * non-spacing. */ #define ISWEAKSPECIAL(cc) ucisprop(cc, UC_EN|UC_ES|UC_MN, UC_ET|UC_AN|UC_CS) #define ISDIGITSPECIAL(cc) ucisprop(cc, UC_ND|UC_MN, 0) /* * These macros are used while breaking a string into runs of text in * different directions. Descriptions: * * ISLTR_LTR - Test for members of an LTR run in an LTR context. This looks * for characters with ltr, non-spacing, weak, and neutral * properties. * * ISRTL_RTL - Test for members of an RTL run in an RTL context. This looks * for characters with rtl, non-spacing, weak, and neutral * properties. * * ISRTL_NEUTRAL - Test for RTL or neutral characters. * * ISWEAK_NEUTRAL - Test for weak or neutral characters. */ #define ISLTR_LTR(cc) ucisprop(cc, UC_L|UC_MN|UC_EN|UC_ES,\ UC_ET|UC_CS|UC_B|UC_S|UC_WS|UC_ON) #define ISRTL_RTL(cc) ucisprop(cc, UC_R|UC_MN|UC_EN|UC_ES,\ UC_ET|UC_AN|UC_CS|UC_B|UC_S|UC_WS|UC_ON) #define ISRTL_NEUTRAL(cc) ucisprop(cc, UC_R, UC_B|UC_S|UC_WS|UC_ON) #define ISWEAK_NEUTRAL(cc) ucisprop(cc, UC_EN|UC_ES, \ UC_B|UC_S|UC_WS|UC_ON|UC_ET|UC_AN|UC_CS) /* * This table is temporarily hard-coded here until it can be constructed * automatically somehow. */ static unsigned long _symmetric_pairs[] = { 0x0028, 0x0029, 0x0029, 0x0028, 0x003C, 0x003E, 0x003E, 0x003C, 0x005B, 0x005D, 0x005D, 0x005B, 0x007B, 0x007D, 0x007D, 0x007B, 0x2045, 0x2046, 0x2046, 0x2045, 0x207D, 0x207E, 0x207E, 0x207D, 0x208D, 0x208E, 0x208E, 0x208D, 0x3008, 0x3009, 0x3009, 0x3008, 0x300A, 0x300B, 0x300B, 0x300A, 0x300C, 0x300D, 0x300D, 0x300C, 0x300E, 0x300F, 0x300F, 0x300E, 0x3010, 0x3011, 0x3011, 0x3010, 0x3014, 0x3015, 0x3015, 0x3014, 0x3016, 0x3017, 0x3017, 0x3016, 0x3018, 0x3019, 0x3019, 0x3018, 0x301A, 0x301B, 0x301B, 0x301A, 0xFD3E, 0xFD3F, 0xFD3F, 0xFD3E, 0xFE59, 0xFE5A, 0xFE5A, 0xFE59, 0xFE5B, 0xFE5C, 0xFE5C, 0xFE5B, 0xFE5D, 0xFE5E, 0xFE5E, 0xFE5D, 0xFF08, 0xFF09, 0xFF09, 0xFF08, 0xFF3B, 0xFF3D, 0xFF3D, 0xFF3B, 0xFF5B, 0xFF5D, 0xFF5D, 0xFF5B, 0xFF62, 0xFF63, 0xFF63, 0xFF62, }; static int _symmetric_pairs_size = sizeof(_symmetric_pairs)/sizeof(_symmetric_pairs[0]); /* * This routine looks up the other form of a symmetric pair. */ static unsigned long _ucsymmetric_pair(unsigned long c) { int i; for (i = 0; i < _symmetric_pairs_size; i += 2) { if (_symmetric_pairs[i] == c) return _symmetric_pairs[i+1]; } return c; } /* * This routine creates a new run, copies the text into it, links it into the * logical text order chain and returns it to the caller to be linked into * the visual text order chain. */ static ucrun_t * _add_run(ucstring_t *str, unsigned long *src, unsigned long start, unsigned long end, int direction) { long i, t; ucrun_t *run; run = (ucrun_t *) malloc(sizeof(ucrun_t)); run->visual_next = run->visual_prev = 0; run->direction = direction; run->cursor = ~0; run->chars = (unsigned long *) malloc(sizeof(unsigned long) * ((end - start) << 1)); run->positions = run->chars + (end - start); run->source = src; run->start = start; run->end = end; if (direction == UCPGBA_RTL) { /* * Copy the source text into the run in reverse order and select * replacements for the pairwise punctuation and the <> characters. */ for (i = 0, t = end - 1; start < end; start++, t--, i++) { run->positions[i] = t; if (ucissymmetric(src[t]) || src[t] == '<' || src[t] == '>') run->chars[i] = _ucsymmetric_pair(src[t]); else run->chars[i] = src[t]; } } else { /* * Copy the source text into the run directly. */ for (i = start; i < end; i++) { run->positions[i - start] = i; run->chars[i - start] = src[i]; } } /* * Add the run to the logical list for cursor traversal. */ if (str->logical_first == 0) str->logical_first = str->logical_last = run; else { run->logical_prev = str->logical_last; str->logical_last->logical_next = run; str->logical_last = run; } return run; } static void _ucadd_rtl_segment(ucstring_t *str, unsigned long *source, unsigned long start, unsigned long end) { unsigned long s, e; ucrun_t *run, *lrun; /* * This is used to splice runs into strings with overall LTR direction. * The `lrun' variable will never be NULL because at least one LTR run was * added before this RTL run. */ lrun = str->visual_last; for (e = s = start; s < end;) { for (; e < end && ISRTL_NEUTRAL(source[e]); e++) ; if (e > s) { run = _add_run(str, source, s, e, UCPGBA_RTL); /* * Add the run to the visual list for cursor traversal. */ if (str->visual_first != 0) { if (str->direction == UCPGBA_LTR) { run->visual_prev = lrun; run->visual_next = lrun->visual_next; if (lrun->visual_next != 0) lrun->visual_next->visual_prev = run; lrun->visual_next = run; if (lrun == str->visual_last) str->visual_last = run; } else { run->visual_next = str->visual_first; str->visual_first->visual_prev = run; str->visual_first = run; } } else str->visual_first = str->visual_last = run; } /* * Handle digits in a special way. This makes sure the weakly * directional characters appear on the expected sides of a number * depending on whether that number is Arabic or not. */ for (s = e; e < end && ISWEAKSPECIAL(source[e]); e++) { if (!ISDIGITSPECIAL(source[e]) && (e + 1 == end || !ISDIGITSPECIAL(source[e + 1]))) break; } if (e > s) { run = _add_run(str, source, s, e, UCPGBA_LTR); /* * Add the run to the visual list for cursor traversal. */ if (str->visual_first != 0) { if (str->direction == UCPGBA_LTR) { run->visual_prev = lrun; run->visual_next = lrun->visual_next; if (lrun->visual_next != 0) lrun->visual_next->visual_prev = run; lrun->visual_next = run; if (lrun == str->visual_last) str->visual_last = run; } else { run->visual_next = str->visual_first; str->visual_first->visual_prev = run; str->visual_first = run; } } else str->visual_first = str->visual_last = run; } /* * Collect all weak non-digit sequences for an RTL segment. These * will appear as part of the next RTL segment or will be added as * an RTL segment by themselves. */ for (s = e; e < end && ucisweak(source[e]) && !ucisdigit(source[e]); e++) ; } /* * Capture any weak non-digit sequences that occur at the end of the RTL * run. */ if (e > s) { run = _add_run(str, source, s, e, UCPGBA_RTL); /* * Add the run to the visual list for cursor traversal. */ if (str->visual_first != 0) { if (str->direction == UCPGBA_LTR) { run->visual_prev = lrun; run->visual_next = lrun->visual_next; if (lrun->visual_next != 0) lrun->visual_next->visual_prev = run; lrun->visual_next = run; if (lrun == str->visual_last) str->visual_last = run; } else { run->visual_next = str->visual_first; str->visual_first->visual_prev = run; str->visual_first = run; } } else str->visual_first = str->visual_last = run; } } static void _ucadd_ltr_segment(ucstring_t *str, unsigned long *source, unsigned long start, unsigned long end) { ucrun_t *run; run = _add_run(str, source, start, end, UCPGBA_LTR); /* * Add the run to the visual list for cursor traversal. */ if (str->visual_first != 0) { if (str->direction == UCPGBA_LTR) { run->visual_prev = str->visual_last; str->visual_last->visual_next = run; str->visual_last = run; } else { run->visual_next = str->visual_first; str->visual_first->visual_prev = run; str->visual_first = run; } } else str->visual_first = str->visual_last = run; } ucstring_t * ucstring_create(unsigned long *source, unsigned long start, unsigned long end, int default_direction, int cursor_motion) { int rtl_first; unsigned long s, e, ld; ucstring_t *str; str = (ucstring_t *) malloc(sizeof(ucstring_t)); /* * Set the initial values. */ str->cursor_motion = cursor_motion; str->logical_first = str->logical_last = 0; str->visual_first = str->visual_last = str->cursor = 0; str->source = source; str->start = start; str->end = end; /* * If the length of the string is 0, then just return it at this point. */ if (start == end) return str; /* * This flag indicates whether the collection loop for RTL is called * before the LTR loop the first time. */ rtl_first = 0; /* * Look for the first character in the string that has strong * directionality. */ for (s = start; s < end && !ucisstrong(source[s]); s++) ; if (s == end) /* * If the string contains no characters with strong directionality, use * the default direction. */ str->direction = default_direction; else str->direction = ucisrtl(source[s]) ? UCPGBA_RTL : UCPGBA_LTR; if (str->direction == UCPGBA_RTL) /* * Set the flag that causes the RTL collection loop to run first. */ rtl_first = 1; /* * This loop now separates the string into runs based on directionality. */ for (s = e = 0; s < end; s = e) { if (!rtl_first) { /* * Determine the next run of LTR text. */ ld = s; while (e < end && ISLTR_LTR(source[e])) { if (ucisdigit(source[e]) && !(0x660 <= source[e] && source[e] <= 0x669)) ld = e; e++; } if (str->direction != UCPGBA_LTR) { while (e > ld && ISWEAK_NEUTRAL(source[e - 1])) e--; } /* * Add the LTR segment to the string. */ if (e > s) _ucadd_ltr_segment(str, source, s, e); } /* * Determine the next run of RTL text. */ ld = s = e; while (e < end && ISRTL_RTL(source[e])) { if (ucisdigit(source[e]) && !(0x660 <= source[e] && source[e] <= 0x669)) ld = e; e++; } if (str->direction != UCPGBA_RTL) { while (e > ld && ISWEAK_NEUTRAL(source[e - 1])) e--; } /* * Add the RTL segment to the string. */ if (e > s) _ucadd_rtl_segment(str, source, s, e); /* * Clear the flag that allowed the RTL collection loop to run first * for strings with overall RTL directionality. */ rtl_first = 0; } /* * Set up the initial cursor run. */ str->cursor = str->logical_first; if (str != 0) str->cursor->cursor = (str->cursor->direction == UCPGBA_RTL) ? str->cursor->end - str->cursor->start : 0; return str; } void ucstring_free(ucstring_t *s) { ucrun_t *l, *r; if (s == 0) return; for (l = 0, r = s->visual_first; r != 0; r = r->visual_next) { if (r->end > r->start) free((char *) r->chars); if (l) free((char *) l); l = r; } if (l) free((char *) l); free((char *) s); } int ucstring_set_cursor_motion(ucstring_t *str, int cursor_motion) { int n; if (str == 0) return -1; n = str->cursor_motion; str->cursor_motion = cursor_motion; return n; } static int _ucstring_visual_cursor_right(ucstring_t *str, int count) { int cnt = count; unsigned long size; ucrun_t *cursor; if (str == 0) return 0; cursor = str->cursor; while (cnt > 0) { size = cursor->end - cursor->start; if ((cursor->direction == UCPGBA_RTL && cursor->cursor + 1 == size) || cursor->cursor + 1 > size) { /* * If the next run is NULL, then the cursor is already on the * far right end already. */ if (cursor->visual_next == 0) /* * If movement occured, then report it. */ return (cnt != count); /* * Move to the next run. */ str->cursor = cursor = cursor->visual_next; cursor->cursor = (cursor->direction == UCPGBA_RTL) ? -1 : 0; size = cursor->end - cursor->start; } else cursor->cursor++; cnt--; } return 1; } static int _ucstring_logical_cursor_right(ucstring_t *str, int count) { int cnt = count; unsigned long size; ucrun_t *cursor; if (str == 0) return 0; cursor = str->cursor; while (cnt > 0) { size = cursor->end - cursor->start; if (str->direction == UCPGBA_RTL) { if (cursor->direction == UCPGBA_RTL) { if (cursor->cursor + 1 == size) { if (cursor == str->logical_first) /* * Already at the beginning of the string. */ return (cnt != count); str->cursor = cursor = cursor->logical_prev; size = cursor->end - cursor->start; cursor->cursor = (cursor->direction == UCPGBA_LTR) ? size : 0; } else cursor->cursor++; } else { if (cursor->cursor == 0) { if (cursor == str->logical_first) /* * At the beginning of the string already. */ return (cnt != count); str->cursor = cursor = cursor->logical_prev; size = cursor->end - cursor->start; cursor->cursor = (cursor->direction == UCPGBA_LTR) ? size : 0; } else cursor->cursor--; } } else { if (cursor->direction == UCPGBA_RTL) { if (cursor->cursor == 0) { if (cursor == str->logical_last) /* * Already at the end of the string. */ return (cnt != count); str->cursor = cursor = cursor->logical_next; size = cursor->end - cursor->start; cursor->cursor = (cursor->direction == UCPGBA_LTR) ? 0 : size - 1; } else cursor->cursor--; } else { if (cursor->cursor + 1 > size) { if (cursor == str->logical_last) /* * Already at the end of the string. */ return (cnt != count); str->cursor = cursor = cursor->logical_next; cursor->cursor = (cursor->direction == UCPGBA_LTR) ? 0 : size - 1; } else cursor->cursor++; } } cnt--; } return 1; } int ucstring_cursor_right(ucstring_t *str, int count) { if (str == 0) return 0; return (str->cursor_motion == UCPGBA_CURSOR_VISUAL) ? _ucstring_visual_cursor_right(str, count) : _ucstring_logical_cursor_right(str, count); } static int _ucstring_visual_cursor_left(ucstring_t *str, int count) { int cnt = count; unsigned long size; ucrun_t *cursor; if (str == 0) return 0; cursor = str->cursor; while (cnt > 0) { size = cursor->end - cursor->start; if ((cursor->direction == UCPGBA_LTR && cursor->cursor == 0) || cursor->cursor - 1 < -1) { /* * If the preceding run is NULL, then the cursor is already on the * far left end already. */ if (cursor->visual_prev == 0) /* * If movement occured, then report it. */ return (cnt != count); /* * Move to the previous run. */ str->cursor = cursor = cursor->visual_prev; size = cursor->end - cursor->start; cursor->cursor = (cursor->direction == UCPGBA_RTL) ? size : size - 1; } else cursor->cursor--; cnt--; } return 1; } static int _ucstring_logical_cursor_left(ucstring_t *str, int count) { int cnt = count; unsigned long size; ucrun_t *cursor; if (str == 0) return 0; cursor = str->cursor; while (cnt > 0) { size = cursor->end - cursor->start; if (str->direction == UCPGBA_RTL) { if (cursor->direction == UCPGBA_RTL) { if (cursor->cursor == -1) { if (cursor == str->logical_last) /* * Already at the end of the string. */ return (cnt != count); str->cursor = cursor = cursor->logical_next; size = cursor->end - cursor->start; cursor->cursor = (cursor->direction == UCPGBA_LTR) ? 0 : size - 1; } else cursor->cursor--; } else { if (cursor->cursor + 1 > size) { if (cursor == str->logical_last) /* * At the end of the string already. */ return (cnt != count); str->cursor = cursor = cursor->logical_next; size = cursor->end - cursor->start; cursor->cursor = (cursor->direction == UCPGBA_LTR) ? 0 : size - 1; } else cursor->cursor++; } } else { if (cursor->direction == UCPGBA_RTL) { if (cursor->cursor + 1 == size) { if (cursor == str->logical_first) /* * Already at the beginning of the string. */ return (cnt != count); str->cursor = cursor = cursor->logical_prev; size = cursor->end - cursor->start; cursor->cursor = (cursor->direction == UCPGBA_LTR) ? size : 0; } else cursor->cursor++; } else { if (cursor->cursor == 0) { if (cursor == str->logical_first) /* * Already at the beginning of the string. */ return (cnt != count); str->cursor = cursor = cursor->logical_prev; cursor->cursor = (cursor->direction == UCPGBA_LTR) ? size : 0; } else cursor->cursor--; } } cnt--; } return 1; } int ucstring_cursor_left(ucstring_t *str, int count) { if (str == 0) return 0; return (str->cursor_motion == UCPGBA_CURSOR_VISUAL) ? _ucstring_visual_cursor_left(str, count) : _ucstring_logical_cursor_left(str, count); } void ucstring_cursor_info(ucstring_t *str, int *direction, unsigned long *position) { long c; unsigned long size; ucrun_t *cursor; if (str == 0 || direction == 0 || position == 0) return; cursor = str->cursor; *direction = cursor->direction; c = cursor->cursor; size = cursor->end - cursor->start; if (c == size) *position = (cursor->direction == UCPGBA_RTL) ? cursor->start : cursor->positions[c - 1]; else if (c == -1) *position = (cursor->direction == UCPGBA_RTL) ? cursor->end : cursor->start; else *position = cursor->positions[c]; } openldap-2.4.42+dfsg/libraries/liblunicode/ucdata/ucdata.c0000644000175000017500000010713312563404150022150 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Copyright 2001 Computing Research Labs, New Mexico State University * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* $Id: ucdata.c,v 1.4 2001/01/02 18:46:20 mleisher Exp $" */ #include "portable.h" #include "ldap_config.h" #include #include #include #include #include #include "lber_pvt.h" #include "ucdata.h" #ifndef HARDCODE_DATA #define HARDCODE_DATA 1 #endif #if HARDCODE_DATA #include "uctable.h" #endif /************************************************************************** * * Miscellaneous types, data, and support functions. * **************************************************************************/ typedef struct { ac_uint2 bom; ac_uint2 cnt; union { ac_uint4 bytes; ac_uint2 len[2]; } size; } _ucheader_t; /* * A simple array of 32-bit masks for lookup. */ static ac_uint4 masks32[32] = { 0x00000001UL, 0x00000002UL, 0x00000004UL, 0x00000008UL, 0x00000010UL, 0x00000020UL, 0x00000040UL, 0x00000080UL, 0x00000100UL, 0x00000200UL, 0x00000400UL, 0x00000800UL, 0x00001000UL, 0x00002000UL, 0x00004000UL, 0x00008000UL, 0x00010000UL, 0x00020000UL, 0x00040000UL, 0x00080000UL, 0x00100000UL, 0x00200000UL, 0x00400000UL, 0x00800000UL, 0x01000000UL, 0x02000000UL, 0x04000000UL, 0x08000000UL, 0x10000000UL, 0x20000000UL, 0x40000000UL, 0x80000000UL }; #define endian_short(cc) (((cc) >> 8) | (((cc) & 0xff) << 8)) #define endian_long(cc) ((((cc) & 0xff) << 24)|((((cc) >> 8) & 0xff) << 16)|\ ((((cc) >> 16) & 0xff) << 8)|((cc) >> 24)) #if !HARDCODE_DATA static FILE * _ucopenfile(char *paths, char *filename, char *mode) { FILE *f; char *fp, *dp, *pp, path[BUFSIZ]; if (filename == 0 || *filename == 0) return 0; dp = paths; while (dp && *dp) { pp = path; while (*dp && *dp != ':') *pp++ = *dp++; *pp++ = *LDAP_DIRSEP; fp = filename; while (*fp) *pp++ = *fp++; *pp = 0; if ((f = fopen(path, mode)) != 0) return f; if (*dp == ':') dp++; } return 0; } #endif /************************************************************************** * * Support for the character properties. * **************************************************************************/ #if !HARDCODE_DATA static ac_uint4 _ucprop_size; static ac_uint2 *_ucprop_offsets; static ac_uint4 *_ucprop_ranges; /* * Return -1 on error, 0 if okay */ static int _ucprop_load(char *paths, int reload) { FILE *in; ac_uint4 size, i; _ucheader_t hdr; if (_ucprop_size > 0) { if (!reload) /* * The character properties have already been loaded. */ return 0; /* * Unload the current character property data in preparation for * loading a new copy. Only the first array has to be deallocated * because all the memory for the arrays is allocated as a single * block. */ free((char *) _ucprop_offsets); _ucprop_size = 0; } if ((in = _ucopenfile(paths, "ctype.dat", "rb")) == 0) return -1; /* * Load the header. */ fread((char *) &hdr, sizeof(_ucheader_t), 1, in); if (hdr.bom == 0xfffe) { hdr.cnt = endian_short(hdr.cnt); hdr.size.bytes = endian_long(hdr.size.bytes); } if ((_ucprop_size = hdr.cnt) == 0) { fclose(in); return -1; } /* * Allocate all the storage needed for the lookup table. */ _ucprop_offsets = (ac_uint2 *) malloc(hdr.size.bytes); /* * Calculate the offset into the storage for the ranges. The offsets * array is on a 4-byte boundary and one larger than the value provided in * the header count field. This means the offset to the ranges must be * calculated after aligning the count to a 4-byte boundary. */ if ((size = ((hdr.cnt + 1) * sizeof(ac_uint2))) & 3) size += 4 - (size & 3); size >>= 1; _ucprop_ranges = (ac_uint4 *) (_ucprop_offsets + size); /* * Load the offset array. */ fread((char *) _ucprop_offsets, sizeof(ac_uint2), size, in); /* * Do an endian swap if necessary. Don't forget there is an extra node on * the end with the final index. */ if (hdr.bom == 0xfffe) { for (i = 0; i <= _ucprop_size; i++) _ucprop_offsets[i] = endian_short(_ucprop_offsets[i]); } /* * Load the ranges. The number of elements is in the last array position * of the offsets. */ fread((char *) _ucprop_ranges, sizeof(ac_uint4), _ucprop_offsets[_ucprop_size], in); fclose(in); /* * Do an endian swap if necessary. */ if (hdr.bom == 0xfffe) { for (i = 0; i < _ucprop_offsets[_ucprop_size]; i++) _ucprop_ranges[i] = endian_long(_ucprop_ranges[i]); } return 0; } static void _ucprop_unload(void) { if (_ucprop_size == 0) return; /* * Only need to free the offsets because the memory is allocated as a * single block. */ free((char *) _ucprop_offsets); _ucprop_size = 0; } #endif static int _ucprop_lookup(ac_uint4 code, ac_uint4 n) { long l, r, m; if (_ucprop_size == 0) return 0; /* * There is an extra node on the end of the offsets to allow this routine * to work right. If the index is 0xffff, then there are no nodes for the * property. */ if ((l = _ucprop_offsets[n]) == 0xffff) return 0; /* * Locate the next offset that is not 0xffff. The sentinel at the end of * the array is the max index value. */ for (m = 1; n + m < _ucprop_size && _ucprop_offsets[n + m] == 0xffff; m++) ; r = _ucprop_offsets[n + m] - 1; while (l <= r) { /* * Determine a "mid" point and adjust to make sure the mid point is at * the beginning of a range pair. */ m = (l + r) >> 1; m -= (m & 1); if (code > _ucprop_ranges[m + 1]) l = m + 2; else if (code < _ucprop_ranges[m]) r = m - 2; else if (code >= _ucprop_ranges[m] && code <= _ucprop_ranges[m + 1]) return 1; } return 0; } int ucisprop(ac_uint4 code, ac_uint4 mask1, ac_uint4 mask2) { ac_uint4 i; if (mask1 == 0 && mask2 == 0) return 0; for (i = 0; mask1 && i < 32; i++) { if ((mask1 & masks32[i]) && _ucprop_lookup(code, i)) return 1; } for (i = 32; mask2 && i < _ucprop_size; i++) { if ((mask2 & masks32[i & 31]) && _ucprop_lookup(code, i)) return 1; } return 0; } /************************************************************************** * * Support for case mapping. * **************************************************************************/ #if !HARDCODE_DATA /* These record the number of slots in the map. * There are 3 words per slot. */ static ac_uint4 _uccase_size; static ac_uint2 _uccase_len[2]; static ac_uint4 *_uccase_map; /* * Return -1 on error, 0 if okay */ static int _uccase_load(char *paths, int reload) { FILE *in; ac_uint4 i; _ucheader_t hdr; if (_uccase_size > 0) { if (!reload) /* * The case mappings have already been loaded. */ return 0; free((char *) _uccase_map); _uccase_size = 0; } if ((in = _ucopenfile(paths, "case.dat", "rb")) == 0) return -1; /* * Load the header. */ fread((char *) &hdr, sizeof(_ucheader_t), 1, in); if (hdr.bom == 0xfffe) { hdr.cnt = endian_short(hdr.cnt); hdr.size.len[0] = endian_short(hdr.size.len[0]); hdr.size.len[1] = endian_short(hdr.size.len[1]); } /* * Set the node count and lengths of the upper and lower case mapping * tables. */ _uccase_size = hdr.cnt; _uccase_len[0] = hdr.size.len[0]; _uccase_len[1] = hdr.size.len[1]; _uccase_map = (ac_uint4 *) malloc(_uccase_size * 3 * sizeof(ac_uint4)); /* * Load the case mapping table. */ fread((char *) _uccase_map, sizeof(ac_uint4), _uccase_size * 3, in); /* * Do an endian swap if necessary. */ if (hdr.bom == 0xfffe) { for (i = 0; i < _uccase_size * 3; i++) _uccase_map[i] = endian_long(_uccase_map[i]); } fclose(in); return 0; } static void _uccase_unload(void) { if (_uccase_size == 0) return; free((char *) _uccase_map); _uccase_size = 0; } #endif static ac_uint4 _uccase_lookup(ac_uint4 code, long l, long r, int field) { long m; const ac_uint4 *tmp; /* * Do the binary search. */ while (l <= r) { /* * Determine a "mid" point and adjust to make sure the mid point is at * the beginning of a case mapping triple. */ m = (l + r) >> 1; tmp = &_uccase_map[m*3]; if (code > *tmp) l = m + 1; else if (code < *tmp) r = m - 1; else if (code == *tmp) return tmp[field]; } return code; } ac_uint4 uctoupper(ac_uint4 code) { int field; long l, r; if (ucisupper(code)) return code; if (ucislower(code)) { /* * The character is lower case. */ field = 2; l = _uccase_len[0]; r = (l + _uccase_len[1]) - 1; } else { /* * The character is title case. */ field = 1; l = _uccase_len[0] + _uccase_len[1]; r = _uccase_size - 1; } return _uccase_lookup(code, l, r, field); } ac_uint4 uctolower(ac_uint4 code) { int field; long l, r; if (ucislower(code)) return code; if (ucisupper(code)) { /* * The character is upper case. */ field = 1; l = 0; r = _uccase_len[0] - 1; } else { /* * The character is title case. */ field = 2; l = _uccase_len[0] + _uccase_len[1]; r = _uccase_size - 1; } return _uccase_lookup(code, l, r, field); } ac_uint4 uctotitle(ac_uint4 code) { int field; long l, r; if (ucistitle(code)) return code; /* * The offset will always be the same for converting to title case. */ field = 2; if (ucisupper(code)) { /* * The character is upper case. */ l = 0; r = _uccase_len[0] - 1; } else { /* * The character is lower case. */ l = _uccase_len[0]; r = (l + _uccase_len[1]) - 1; } return _uccase_lookup(code, l, r, field); } /************************************************************************** * * Support for compositions. * **************************************************************************/ #if !HARDCODE_DATA static ac_uint4 _uccomp_size; static ac_uint4 *_uccomp_data; /* * Return -1 on error, 0 if okay */ static int _uccomp_load(char *paths, int reload) { FILE *in; ac_uint4 size, i; _ucheader_t hdr; if (_uccomp_size > 0) { if (!reload) /* * The compositions have already been loaded. */ return 0; free((char *) _uccomp_data); _uccomp_size = 0; } if ((in = _ucopenfile(paths, "comp.dat", "rb")) == 0) return -1; /* * Load the header. */ fread((char *) &hdr, sizeof(_ucheader_t), 1, in); if (hdr.bom == 0xfffe) { hdr.cnt = endian_short(hdr.cnt); hdr.size.bytes = endian_long(hdr.size.bytes); } _uccomp_size = hdr.cnt; _uccomp_data = (ac_uint4 *) malloc(hdr.size.bytes); /* * Read the composition data in. */ size = hdr.size.bytes / sizeof(ac_uint4); fread((char *) _uccomp_data, sizeof(ac_uint4), size, in); /* * Do an endian swap if necessary. */ if (hdr.bom == 0xfffe) { for (i = 0; i < size; i++) _uccomp_data[i] = endian_long(_uccomp_data[i]); } /* * Assume that the data is ordered on count, so that all compositions * of length 2 come first. Only handling length 2 for now. */ for (i = 1; i < size; i += 4) if (_uccomp_data[i] != 2) break; _uccomp_size = i - 1; fclose(in); return 0; } static void _uccomp_unload(void) { if (_uccomp_size == 0) return; free((char *) _uccomp_data); _uccomp_size = 0; } #endif int uccomp(ac_uint4 node1, ac_uint4 node2, ac_uint4 *comp) { int l, r, m; l = 0; r = _uccomp_size - 1; while (l <= r) { m = ((r + l) >> 1); m -= m & 3; if (node1 > _uccomp_data[m+2]) l = m + 4; else if (node1 < _uccomp_data[m+2]) r = m - 4; else if (node2 > _uccomp_data[m+3]) l = m + 4; else if (node2 < _uccomp_data[m+3]) r = m - 4; else { *comp = _uccomp_data[m]; return 1; } } return 0; } int uccomp_hangul(ac_uint4 *str, int len) { const int SBase = 0xAC00, LBase = 0x1100, VBase = 0x1161, TBase = 0x11A7, LCount = 19, VCount = 21, TCount = 28, NCount = VCount * TCount, /* 588 */ SCount = LCount * NCount; /* 11172 */ int i, rlen; ac_uint4 ch, last, lindex, sindex; last = str[0]; rlen = 1; for ( i = 1; i < len; i++ ) { ch = str[i]; /* check if two current characters are L and V */ lindex = last - LBase; if (lindex < (ac_uint4) LCount) { ac_uint4 vindex = ch - VBase; if (vindex < (ac_uint4) VCount) { /* make syllable of form LV */ last = SBase + (lindex * VCount + vindex) * TCount; str[rlen-1] = last; /* reset last */ continue; } } /* check if two current characters are LV and T */ sindex = last - SBase; if (sindex < (ac_uint4) SCount && (sindex % TCount) == 0) { ac_uint4 tindex = ch - TBase; if (tindex <= (ac_uint4) TCount) { /* make syllable of form LVT */ last += tindex; str[rlen-1] = last; /* reset last */ continue; } } /* if neither case was true, just add the character */ last = ch; str[rlen] = ch; rlen++; } return rlen; } int uccanoncomp(ac_uint4 *str, int len) { int i, stpos, copos; ac_uint4 cl, prevcl, st, ch, co; st = str[0]; stpos = 0; copos = 1; prevcl = uccombining_class(st) == 0 ? 0 : 256; for (i = 1; i < len; i++) { ch = str[i]; cl = uccombining_class(ch); if (uccomp(st, ch, &co) && (prevcl < cl || prevcl == 0)) st = str[stpos] = co; else { if (cl == 0) { stpos = copos; st = ch; } prevcl = cl; str[copos++] = ch; } } return uccomp_hangul(str, copos); } /************************************************************************** * * Support for decompositions. * **************************************************************************/ #if !HARDCODE_DATA static ac_uint4 _ucdcmp_size; static ac_uint4 *_ucdcmp_nodes; static ac_uint4 *_ucdcmp_decomp; static ac_uint4 _uckdcmp_size; static ac_uint4 *_uckdcmp_nodes; static ac_uint4 *_uckdcmp_decomp; /* * Return -1 on error, 0 if okay */ static int _ucdcmp_load(char *paths, int reload) { FILE *in; ac_uint4 size, i; _ucheader_t hdr; if (_ucdcmp_size > 0) { if (!reload) /* * The decompositions have already been loaded. */ return 0; free((char *) _ucdcmp_nodes); _ucdcmp_size = 0; } if ((in = _ucopenfile(paths, "decomp.dat", "rb")) == 0) return -1; /* * Load the header. */ fread((char *) &hdr, sizeof(_ucheader_t), 1, in); if (hdr.bom == 0xfffe) { hdr.cnt = endian_short(hdr.cnt); hdr.size.bytes = endian_long(hdr.size.bytes); } _ucdcmp_size = hdr.cnt << 1; _ucdcmp_nodes = (ac_uint4 *) malloc(hdr.size.bytes); _ucdcmp_decomp = _ucdcmp_nodes + (_ucdcmp_size + 1); /* * Read the decomposition data in. */ size = hdr.size.bytes / sizeof(ac_uint4); fread((char *) _ucdcmp_nodes, sizeof(ac_uint4), size, in); /* * Do an endian swap if necessary. */ if (hdr.bom == 0xfffe) { for (i = 0; i < size; i++) _ucdcmp_nodes[i] = endian_long(_ucdcmp_nodes[i]); } fclose(in); return 0; } /* * Return -1 on error, 0 if okay */ static int _uckdcmp_load(char *paths, int reload) { FILE *in; ac_uint4 size, i; _ucheader_t hdr; if (_uckdcmp_size > 0) { if (!reload) /* * The decompositions have already been loaded. */ return 0; free((char *) _uckdcmp_nodes); _uckdcmp_size = 0; } if ((in = _ucopenfile(paths, "kdecomp.dat", "rb")) == 0) return -1; /* * Load the header. */ fread((char *) &hdr, sizeof(_ucheader_t), 1, in); if (hdr.bom == 0xfffe) { hdr.cnt = endian_short(hdr.cnt); hdr.size.bytes = endian_long(hdr.size.bytes); } _uckdcmp_size = hdr.cnt << 1; _uckdcmp_nodes = (ac_uint4 *) malloc(hdr.size.bytes); _uckdcmp_decomp = _uckdcmp_nodes + (_uckdcmp_size + 1); /* * Read the decomposition data in. */ size = hdr.size.bytes / sizeof(ac_uint4); fread((char *) _uckdcmp_nodes, sizeof(ac_uint4), size, in); /* * Do an endian swap if necessary. */ if (hdr.bom == 0xfffe) { for (i = 0; i < size; i++) _uckdcmp_nodes[i] = endian_long(_uckdcmp_nodes[i]); } fclose(in); return 0; } static void _ucdcmp_unload(void) { if (_ucdcmp_size == 0) return; /* * Only need to free the offsets because the memory is allocated as a * single block. */ free((char *) _ucdcmp_nodes); _ucdcmp_size = 0; } static void _uckdcmp_unload(void) { if (_uckdcmp_size == 0) return; /* * Only need to free the offsets because the memory is allocated as a * single block. */ free((char *) _uckdcmp_nodes); _uckdcmp_size = 0; } #endif int ucdecomp(ac_uint4 code, ac_uint4 *num, ac_uint4 **decomp) { long l, r, m; if (code < _ucdcmp_nodes[0]) { return 0; } l = 0; r = _ucdcmp_nodes[_ucdcmp_size] - 1; while (l <= r) { /* * Determine a "mid" point and adjust to make sure the mid point is at * the beginning of a code+offset pair. */ m = (l + r) >> 1; m -= (m & 1); if (code > _ucdcmp_nodes[m]) l = m + 2; else if (code < _ucdcmp_nodes[m]) r = m - 2; else if (code == _ucdcmp_nodes[m]) { *num = _ucdcmp_nodes[m + 3] - _ucdcmp_nodes[m + 1]; *decomp = (ac_uint4*)&_ucdcmp_decomp[_ucdcmp_nodes[m + 1]]; return 1; } } return 0; } int uckdecomp(ac_uint4 code, ac_uint4 *num, ac_uint4 **decomp) { long l, r, m; if (code < _uckdcmp_nodes[0]) { return 0; } l = 0; r = _uckdcmp_nodes[_uckdcmp_size] - 1; while (l <= r) { /* * Determine a "mid" point and adjust to make sure the mid point is at * the beginning of a code+offset pair. */ m = (l + r) >> 1; m -= (m & 1); if (code > _uckdcmp_nodes[m]) l = m + 2; else if (code < _uckdcmp_nodes[m]) r = m - 2; else if (code == _uckdcmp_nodes[m]) { *num = _uckdcmp_nodes[m + 3] - _uckdcmp_nodes[m + 1]; *decomp = (ac_uint4*)&_uckdcmp_decomp[_uckdcmp_nodes[m + 1]]; return 1; } } return 0; } int ucdecomp_hangul(ac_uint4 code, ac_uint4 *num, ac_uint4 decomp[]) { if (!ucishangul(code)) return 0; code -= 0xac00; decomp[0] = 0x1100 + (ac_uint4) (code / 588); decomp[1] = 0x1161 + (ac_uint4) ((code % 588) / 28); decomp[2] = 0x11a7 + (ac_uint4) (code % 28); *num = (decomp[2] != 0x11a7) ? 3 : 2; return 1; } /* mode == 0 for canonical, mode == 1 for compatibility */ static int uccanoncompatdecomp(const ac_uint4 *in, int inlen, ac_uint4 **out, int *outlen, short mode, void *ctx) { int l, size; unsigned i, j, k; ac_uint4 num, class, *decomp, hangdecomp[3]; size = inlen * 2; *out = (ac_uint4 *) ber_memalloc_x(size * sizeof(**out), ctx); if (*out == NULL) return *outlen = -1; i = 0; for (j = 0; j < (unsigned) inlen; j++) { if (mode ? uckdecomp(in[j], &num, &decomp) : ucdecomp(in[j], &num, &decomp)) { if ( size - i < num) { size = inlen + i - j + num - 1; *out = (ac_uint4 *) ber_memrealloc_x(*out, size * sizeof(**out), ctx ); if (*out == NULL) return *outlen = -1; } for (k = 0; k < num; k++) { class = uccombining_class(decomp[k]); if (class == 0) { (*out)[i] = decomp[k]; } else { for (l = i; l > 0; l--) if (class >= uccombining_class((*out)[l-1])) break; AC_MEMCPY(*out + l + 1, *out + l, (i - l) * sizeof(**out)); (*out)[l] = decomp[k]; } i++; } } else if (ucdecomp_hangul(in[j], &num, hangdecomp)) { if (size - i < num) { size = inlen + i - j + num - 1; *out = (ac_uint4 *) ber_memrealloc_x(*out, size * sizeof(**out), ctx); if (*out == NULL) return *outlen = -1; } for (k = 0; k < num; k++) { (*out)[i] = hangdecomp[k]; i++; } } else { if (size - i < 1) { size = inlen + i - j; *out = (ac_uint4 *) ber_memrealloc_x(*out, size * sizeof(**out), ctx); if (*out == NULL) return *outlen = -1; } class = uccombining_class(in[j]); if (class == 0) { (*out)[i] = in[j]; } else { for (l = i; l > 0; l--) if (class >= uccombining_class((*out)[l-1])) break; AC_MEMCPY(*out + l + 1, *out + l, (i - l) * sizeof(**out)); (*out)[l] = in[j]; } i++; } } return *outlen = i; } int uccanondecomp(const ac_uint4 *in, int inlen, ac_uint4 **out, int *outlen, void *ctx) { return uccanoncompatdecomp(in, inlen, out, outlen, 0, ctx); } int uccompatdecomp(const ac_uint4 *in, int inlen, ac_uint4 **out, int *outlen, void *ctx) { return uccanoncompatdecomp(in, inlen, out, outlen, 1, ctx); } /************************************************************************** * * Support for combining classes. * **************************************************************************/ #if !HARDCODE_DATA static ac_uint4 _uccmcl_size; static ac_uint4 *_uccmcl_nodes; /* * Return -1 on error, 0 if okay */ static int _uccmcl_load(char *paths, int reload) { FILE *in; ac_uint4 i; _ucheader_t hdr; if (_uccmcl_size > 0) { if (!reload) /* * The combining classes have already been loaded. */ return 0; free((char *) _uccmcl_nodes); _uccmcl_size = 0; } if ((in = _ucopenfile(paths, "cmbcl.dat", "rb")) == 0) return -1; /* * Load the header. */ fread((char *) &hdr, sizeof(_ucheader_t), 1, in); if (hdr.bom == 0xfffe) { hdr.cnt = endian_short(hdr.cnt); hdr.size.bytes = endian_long(hdr.size.bytes); } _uccmcl_size = hdr.cnt * 3; _uccmcl_nodes = (ac_uint4 *) malloc(hdr.size.bytes); /* * Read the combining classes in. */ fread((char *) _uccmcl_nodes, sizeof(ac_uint4), _uccmcl_size, in); /* * Do an endian swap if necessary. */ if (hdr.bom == 0xfffe) { for (i = 0; i < _uccmcl_size; i++) _uccmcl_nodes[i] = endian_long(_uccmcl_nodes[i]); } fclose(in); return 0; } static void _uccmcl_unload(void) { if (_uccmcl_size == 0) return; free((char *) _uccmcl_nodes); _uccmcl_size = 0; } #endif ac_uint4 uccombining_class(ac_uint4 code) { long l, r, m; l = 0; r = _uccmcl_size - 1; while (l <= r) { m = (l + r) >> 1; m -= (m % 3); if (code > _uccmcl_nodes[m + 1]) l = m + 3; else if (code < _uccmcl_nodes[m]) r = m - 3; else if (code >= _uccmcl_nodes[m] && code <= _uccmcl_nodes[m + 1]) return _uccmcl_nodes[m + 2]; } return 0; } /************************************************************************** * * Support for numeric values. * **************************************************************************/ #if !HARDCODE_DATA static ac_uint4 *_ucnum_nodes; static ac_uint4 _ucnum_size; static short *_ucnum_vals; /* * Return -1 on error, 0 if okay */ static int _ucnumb_load(char *paths, int reload) { FILE *in; ac_uint4 size, i; _ucheader_t hdr; if (_ucnum_size > 0) { if (!reload) /* * The numbers have already been loaded. */ return 0; free((char *) _ucnum_nodes); _ucnum_size = 0; } if ((in = _ucopenfile(paths, "num.dat", "rb")) == 0) return -1; /* * Load the header. */ fread((char *) &hdr, sizeof(_ucheader_t), 1, in); if (hdr.bom == 0xfffe) { hdr.cnt = endian_short(hdr.cnt); hdr.size.bytes = endian_long(hdr.size.bytes); } _ucnum_size = hdr.cnt; _ucnum_nodes = (ac_uint4 *) malloc(hdr.size.bytes); _ucnum_vals = (short *) (_ucnum_nodes + _ucnum_size); /* * Read the combining classes in. */ fread((char *) _ucnum_nodes, sizeof(unsigned char), hdr.size.bytes, in); /* * Do an endian swap if necessary. */ if (hdr.bom == 0xfffe) { for (i = 0; i < _ucnum_size; i++) _ucnum_nodes[i] = endian_long(_ucnum_nodes[i]); /* * Determine the number of values that have to be adjusted. */ size = (hdr.size.bytes - (_ucnum_size * (sizeof(ac_uint4) << 1))) / sizeof(short); for (i = 0; i < size; i++) _ucnum_vals[i] = endian_short(_ucnum_vals[i]); } fclose(in); return 0; } static void _ucnumb_unload(void) { if (_ucnum_size == 0) return; free((char *) _ucnum_nodes); _ucnum_size = 0; } #endif int ucnumber_lookup(ac_uint4 code, struct ucnumber *num) { long l, r, m; short *vp; l = 0; r = _ucnum_size - 1; while (l <= r) { /* * Determine a "mid" point and adjust to make sure the mid point is at * the beginning of a code+offset pair. */ m = (l + r) >> 1; m -= (m & 1); if (code > _ucnum_nodes[m]) l = m + 2; else if (code < _ucnum_nodes[m]) r = m - 2; else { vp = (short *)_ucnum_vals + _ucnum_nodes[m + 1]; num->numerator = (int) *vp++; num->denominator = (int) *vp; return 1; } } return 0; } int ucdigit_lookup(ac_uint4 code, int *digit) { long l, r, m; short *vp; l = 0; r = _ucnum_size - 1; while (l <= r) { /* * Determine a "mid" point and adjust to make sure the mid point is at * the beginning of a code+offset pair. */ m = (l + r) >> 1; m -= (m & 1); if (code > _ucnum_nodes[m]) l = m + 2; else if (code < _ucnum_nodes[m]) r = m - 2; else { vp = (short *)_ucnum_vals + _ucnum_nodes[m + 1]; if (*vp == *(vp + 1)) { *digit = *vp; return 1; } return 0; } } return 0; } struct ucnumber ucgetnumber(ac_uint4 code) { struct ucnumber num; /* * Initialize with some arbitrary value, because the caller simply cannot * tell for sure if the code is a number without calling the ucisnumber() * macro before calling this function. */ num.numerator = num.denominator = -111; (void) ucnumber_lookup(code, &num); return num; } int ucgetdigit(ac_uint4 code) { int dig; /* * Initialize with some arbitrary value, because the caller simply cannot * tell for sure if the code is a number without calling the ucisdigit() * macro before calling this function. */ dig = -111; (void) ucdigit_lookup(code, &dig); return dig; } /************************************************************************** * * Setup and cleanup routines. * **************************************************************************/ #if HARDCODE_DATA int ucdata_load(char *paths, int masks) { return 0; } void ucdata_unload(int masks) { } int ucdata_reload(char *paths, int masks) { return 0; } #else /* * Return 0 if okay, negative on error */ int ucdata_load(char *paths, int masks) { int error = 0; if (masks & UCDATA_CTYPE) error |= _ucprop_load(paths, 0) < 0 ? UCDATA_CTYPE : 0; if (masks & UCDATA_CASE) error |= _uccase_load(paths, 0) < 0 ? UCDATA_CASE : 0; if (masks & UCDATA_DECOMP) error |= _ucdcmp_load(paths, 0) < 0 ? UCDATA_DECOMP : 0; if (masks & UCDATA_CMBCL) error |= _uccmcl_load(paths, 0) < 0 ? UCDATA_CMBCL : 0; if (masks & UCDATA_NUM) error |= _ucnumb_load(paths, 0) < 0 ? UCDATA_NUM : 0; if (masks & UCDATA_COMP) error |= _uccomp_load(paths, 0) < 0 ? UCDATA_COMP : 0; if (masks & UCDATA_KDECOMP) error |= _uckdcmp_load(paths, 0) < 0 ? UCDATA_KDECOMP : 0; return -error; } void ucdata_unload(int masks) { if (masks & UCDATA_CTYPE) _ucprop_unload(); if (masks & UCDATA_CASE) _uccase_unload(); if (masks & UCDATA_DECOMP) _ucdcmp_unload(); if (masks & UCDATA_CMBCL) _uccmcl_unload(); if (masks & UCDATA_NUM) _ucnumb_unload(); if (masks & UCDATA_COMP) _uccomp_unload(); if (masks & UCDATA_KDECOMP) _uckdcmp_unload(); } /* * Return 0 if okay, negative on error */ int ucdata_reload(char *paths, int masks) { int error = 0; if (masks & UCDATA_CTYPE) error |= _ucprop_load(paths, 1) < 0 ? UCDATA_CTYPE : 0; if (masks & UCDATA_CASE) error |= _uccase_load(paths, 1) < 0 ? UCDATA_CASE : 0; if (masks & UCDATA_DECOMP) error |= _ucdcmp_load(paths, 1) < 0 ? UCDATA_DECOMP : 0; if (masks & UCDATA_CMBCL) error |= _uccmcl_load(paths, 1) < 0 ? UCDATA_CMBCL : 0; if (masks & UCDATA_NUM) error |= _ucnumb_load(paths, 1) < 0 ? UCDATA_NUM : 0; if (masks & UCDATA_COMP) error |= _uccomp_load(paths, 1) < 0 ? UCDATA_COMP : 0; if (masks & UCDATA_KDECOMP) error |= _uckdcmp_load(paths, 1) < 0 ? UCDATA_KDECOMP : 0; return -error; } #endif #ifdef TEST void main(void) { int dig; ac_uint4 i, lo, *dec; struct ucnumber num; /* ucdata_setup("."); */ if (ucisweak(0x30)) printf("WEAK\n"); else printf("NOT WEAK\n"); printf("LOWER 0x%04lX\n", uctolower(0xff3a)); printf("UPPER 0x%04lX\n", uctoupper(0xff5a)); if (ucisalpha(0x1d5)) printf("ALPHA\n"); else printf("NOT ALPHA\n"); if (ucisupper(0x1d5)) { printf("UPPER\n"); lo = uctolower(0x1d5); printf("0x%04lx\n", lo); lo = uctotitle(0x1d5); printf("0x%04lx\n", lo); } else printf("NOT UPPER\n"); if (ucistitle(0x1d5)) printf("TITLE\n"); else printf("NOT TITLE\n"); if (uciscomposite(0x1d5)) printf("COMPOSITE\n"); else printf("NOT COMPOSITE\n"); if (ucdecomp(0x1d5, &lo, &dec)) { for (i = 0; i < lo; i++) printf("0x%04lx ", dec[i]); putchar('\n'); } if ((lo = uccombining_class(0x41)) != 0) printf("0x41 CCL %ld\n", lo); if (ucisxdigit(0xfeff)) printf("0xFEFF HEX DIGIT\n"); else printf("0xFEFF NOT HEX DIGIT\n"); if (ucisdefined(0x10000)) printf("0x10000 DEFINED\n"); else printf("0x10000 NOT DEFINED\n"); if (ucnumber_lookup(0x30, &num)) { if (num.denominator != 1) printf("UCNUMBER: 0x30 = %d/%d\n", num.numerator, num.denominator); else printf("UCNUMBER: 0x30 = %d\n", num.numerator); } else printf("UCNUMBER: 0x30 NOT A NUMBER\n"); if (ucnumber_lookup(0xbc, &num)) { if (num.denominator != 1) printf("UCNUMBER: 0xbc = %d/%d\n", num.numerator, num.denominator); else printf("UCNUMBER: 0xbc = %d\n", num.numerator); } else printf("UCNUMBER: 0xbc NOT A NUMBER\n"); if (ucnumber_lookup(0xff19, &num)) { if (num.denominator != 1) printf("UCNUMBER: 0xff19 = %d/%d\n", num.numerator, num.denominator); else printf("UCNUMBER: 0xff19 = %d\n", num.numerator); } else printf("UCNUMBER: 0xff19 NOT A NUMBER\n"); if (ucnumber_lookup(0x4e00, &num)) { if (num.denominator != 1) printf("UCNUMBER: 0x4e00 = %d/%d\n", num.numerator, num.denominator); else printf("UCNUMBER: 0x4e00 = %d\n", num.numerator); } else printf("UCNUMBER: 0x4e00 NOT A NUMBER\n"); if (ucdigit_lookup(0x06f9, &dig)) printf("UCDIGIT: 0x6f9 = %d\n", dig); else printf("UCDIGIT: 0x6f9 NOT A NUMBER\n"); dig = ucgetdigit(0x0969); printf("UCGETDIGIT: 0x969 = %d\n", dig); num = ucgetnumber(0x30); if (num.denominator != 1) printf("UCGETNUMBER: 0x30 = %d/%d\n", num.numerator, num.denominator); else printf("UCGETNUMBER: 0x30 = %d\n", num.numerator); num = ucgetnumber(0xbc); if (num.denominator != 1) printf("UCGETNUMBER: 0xbc = %d/%d\n", num.numerator, num.denominator); else printf("UCGETNUMBER: 0xbc = %d\n", num.numerator); num = ucgetnumber(0xff19); if (num.denominator != 1) printf("UCGETNUMBER: 0xff19 = %d/%d\n", num.numerator, num.denominator); else printf("UCGETNUMBER: 0xff19 = %d\n", num.numerator); /* ucdata_cleanup(); */ exit(0); } #endif /* TEST */ openldap-2.4.42+dfsg/libraries/liblunicode/ucdata/ucdata.h0000644000175000017500000003323012563404150022151 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Copyright 2001 Computing Research Labs, New Mexico State University * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* $Id: ucdata.h,v 1.6 2001/01/02 18:46:20 mleisher Exp $ */ #ifndef _h_ucdata #define _h_ucdata LDAP_BEGIN_DECL #define UCDATA_VERSION "2.4" /************************************************************************** * * Masks and macros for character properties. * **************************************************************************/ /* * Values that can appear in the `mask1' parameter of the ucisprop() * function. */ #define UC_MN 0x00000001 /* Mark, Non-Spacing */ #define UC_MC 0x00000002 /* Mark, Spacing Combining */ #define UC_ME 0x00000004 /* Mark, Enclosing */ #define UC_ND 0x00000008 /* Number, Decimal Digit */ #define UC_NL 0x00000010 /* Number, Letter */ #define UC_NO 0x00000020 /* Number, Other */ #define UC_ZS 0x00000040 /* Separator, Space */ #define UC_ZL 0x00000080 /* Separator, Line */ #define UC_ZP 0x00000100 /* Separator, Paragraph */ #define UC_CC 0x00000200 /* Other, Control */ #define UC_CF 0x00000400 /* Other, Format */ #define UC_OS 0x00000800 /* Other, Surrogate */ #define UC_CO 0x00001000 /* Other, Private Use */ #define UC_CN 0x00002000 /* Other, Not Assigned */ #define UC_LU 0x00004000 /* Letter, Uppercase */ #define UC_LL 0x00008000 /* Letter, Lowercase */ #define UC_LT 0x00010000 /* Letter, Titlecase */ #define UC_LM 0x00020000 /* Letter, Modifier */ #define UC_LO 0x00040000 /* Letter, Other */ #define UC_PC 0x00080000 /* Punctuation, Connector */ #define UC_PD 0x00100000 /* Punctuation, Dash */ #define UC_PS 0x00200000 /* Punctuation, Open */ #define UC_PE 0x00400000 /* Punctuation, Close */ #define UC_PO 0x00800000 /* Punctuation, Other */ #define UC_SM 0x01000000 /* Symbol, Math */ #define UC_SC 0x02000000 /* Symbol, Currency */ #define UC_SK 0x04000000 /* Symbol, Modifier */ #define UC_SO 0x08000000 /* Symbol, Other */ #define UC_L 0x10000000 /* Left-To-Right */ #define UC_R 0x20000000 /* Right-To-Left */ #define UC_EN 0x40000000 /* European Number */ #define UC_ES 0x80000000 /* European Number Separator */ /* * Values that can appear in the `mask2' parameter of the ucisprop() * function. */ #define UC_ET 0x00000001 /* European Number Terminator */ #define UC_AN 0x00000002 /* Arabic Number */ #define UC_CS 0x00000004 /* Common Number Separator */ #define UC_B 0x00000008 /* Block Separator */ #define UC_S 0x00000010 /* Segment Separator */ #define UC_WS 0x00000020 /* Whitespace */ #define UC_ON 0x00000040 /* Other Neutrals */ /* * Implementation specific character properties. */ #define UC_CM 0x00000080 /* Composite */ #define UC_NB 0x00000100 /* Non-Breaking */ #define UC_SY 0x00000200 /* Symmetric */ #define UC_HD 0x00000400 /* Hex Digit */ #define UC_QM 0x00000800 /* Quote Mark */ #define UC_MR 0x00001000 /* Mirroring */ #define UC_SS 0x00002000 /* Space, other */ #define UC_CP 0x00004000 /* Defined */ /* * Added for UnicodeData-2.1.3. */ #define UC_PI 0x00008000 /* Punctuation, Initial */ #define UC_PF 0x00010000 /* Punctuation, Final */ /* * This is the primary function for testing to see if a character has some set * of properties. The macros that test for various character properties all * call this function with some set of masks. */ LDAP_LUNICODE_F (int) ucisprop LDAP_P((ac_uint4 code, ac_uint4 mask1, ac_uint4 mask2)); #define ucisalpha(cc) ucisprop(cc, UC_LU|UC_LL|UC_LM|UC_LO|UC_LT, 0) #define ucisdigit(cc) ucisprop(cc, UC_ND, 0) #define ucisalnum(cc) ucisprop(cc, UC_LU|UC_LL|UC_LM|UC_LO|UC_LT|UC_ND, 0) #define uciscntrl(cc) ucisprop(cc, UC_CC|UC_CF, 0) #define ucisspace(cc) ucisprop(cc, UC_ZS|UC_SS, 0) #define ucisblank(cc) ucisprop(cc, UC_ZS, 0) #define ucispunct(cc) ucisprop(cc, UC_PD|UC_PS|UC_PE|UC_PO, UC_PI|UC_PF) #define ucisgraph(cc) ucisprop(cc, UC_MN|UC_MC|UC_ME|UC_ND|UC_NL|UC_NO|\ UC_LU|UC_LL|UC_LT|UC_LM|UC_LO|UC_PC|UC_PD|\ UC_PS|UC_PE|UC_PO|UC_SM|UC_SM|UC_SC|UC_SK|\ UC_SO, UC_PI|UC_PF) #define ucisprint(cc) ucisprop(cc, UC_MN|UC_MC|UC_ME|UC_ND|UC_NL|UC_NO|\ UC_LU|UC_LL|UC_LT|UC_LM|UC_LO|UC_PC|UC_PD|\ UC_PS|UC_PE|UC_PO|UC_SM|UC_SM|UC_SC|UC_SK|\ UC_SO|UC_ZS, UC_PI|UC_PF) #define ucisupper(cc) ucisprop(cc, UC_LU, 0) #define ucislower(cc) ucisprop(cc, UC_LL, 0) #define ucistitle(cc) ucisprop(cc, UC_LT, 0) #define ucisxdigit(cc) ucisprop(cc, 0, UC_HD) #define ucisisocntrl(cc) ucisprop(cc, UC_CC, 0) #define ucisfmtcntrl(cc) ucisprop(cc, UC_CF, 0) #define ucissymbol(cc) ucisprop(cc, UC_SM|UC_SC|UC_SO|UC_SK, 0) #define ucisnumber(cc) ucisprop(cc, UC_ND|UC_NO|UC_NL, 0) #define ucisnonspacing(cc) ucisprop(cc, UC_MN, 0) #define ucisopenpunct(cc) ucisprop(cc, UC_PS, 0) #define ucisclosepunct(cc) ucisprop(cc, UC_PE, 0) #define ucisinitialpunct(cc) ucisprop(cc, 0, UC_PI) #define ucisfinalpunct(cc) ucisprop(cc, 0, UC_PF) #define uciscomposite(cc) ucisprop(cc, 0, UC_CM) #define ucishex(cc) ucisprop(cc, 0, UC_HD) #define ucisquote(cc) ucisprop(cc, 0, UC_QM) #define ucissymmetric(cc) ucisprop(cc, 0, UC_SY) #define ucismirroring(cc) ucisprop(cc, 0, UC_MR) #define ucisnonbreaking(cc) ucisprop(cc, 0, UC_NB) /* * Directionality macros. */ #define ucisrtl(cc) ucisprop(cc, UC_R, 0) #define ucisltr(cc) ucisprop(cc, UC_L, 0) #define ucisstrong(cc) ucisprop(cc, UC_L|UC_R, 0) #define ucisweak(cc) ucisprop(cc, UC_EN|UC_ES, UC_ET|UC_AN|UC_CS) #define ucisneutral(cc) ucisprop(cc, 0, UC_B|UC_S|UC_WS|UC_ON) #define ucisseparator(cc) ucisprop(cc, 0, UC_B|UC_S) /* * Other macros inspired by John Cowan. */ #define ucismark(cc) ucisprop(cc, UC_MN|UC_MC|UC_ME, 0) #define ucismodif(cc) ucisprop(cc, UC_LM, 0) #define ucisletnum(cc) ucisprop(cc, UC_NL, 0) #define ucisconnect(cc) ucisprop(cc, UC_PC, 0) #define ucisdash(cc) ucisprop(cc, UC_PD, 0) #define ucismath(cc) ucisprop(cc, UC_SM, 0) #define uciscurrency(cc) ucisprop(cc, UC_SC, 0) #define ucismodifsymbol(cc) ucisprop(cc, UC_SK, 0) #define ucisnsmark(cc) ucisprop(cc, UC_MN, 0) #define ucisspmark(cc) ucisprop(cc, UC_MC, 0) #define ucisenclosing(cc) ucisprop(cc, UC_ME, 0) #define ucisprivate(cc) ucisprop(cc, UC_CO, 0) #define ucissurrogate(cc) ucisprop(cc, UC_OS, 0) #define ucislsep(cc) ucisprop(cc, UC_ZL, 0) #define ucispsep(cc) ucisprop(cc, UC_ZP, 0) #define ucisidentstart(cc) ucisprop(cc, UC_LU|UC_LL|UC_LT|UC_LO|UC_NL, 0) #define ucisidentpart(cc) ucisprop(cc, UC_LU|UC_LL|UC_LT|UC_LO|UC_NL|\ UC_MN|UC_MC|UC_ND|UC_PC|UC_CF, 0) #define ucisdefined(cc) ucisprop(cc, 0, UC_CP) #define ucisundefined(cc) !ucisprop(cc, 0, UC_CP) /* * Other miscellaneous character property macros. */ #define ucishan(cc) (((cc) >= 0x4e00 && (cc) <= 0x9fff) ||\ ((cc) >= 0xf900 && (cc) <= 0xfaff)) #define ucishangul(cc) ((cc) >= 0xac00 && (cc) <= 0xd7ff) /************************************************************************** * * Functions for case conversion. * **************************************************************************/ LDAP_LUNICODE_F (ac_uint4) uctoupper LDAP_P((ac_uint4 code)); LDAP_LUNICODE_F (ac_uint4) uctolower LDAP_P((ac_uint4 code)); LDAP_LUNICODE_F (ac_uint4) uctotitle LDAP_P((ac_uint4 code)); /************************************************************************** * * Functions for getting compositions. * **************************************************************************/ /* * This routine determines if there exists a composition of node1 and node2. * If it returns 0, there is no composition. Any other value indicates a * composition was returned in comp. */ LDAP_LUNICODE_F (int) uccomp LDAP_P((ac_uint4 node1, ac_uint4 node2, ac_uint4 *comp)); /* * Does Hangul composition on the string str with length len, and returns * the length of the composed string. */ LDAP_LUNICODE_F (int) uccomp_hangul LDAP_P((ac_uint4 *str, int len)); /* * Does canonical composition on the string str with length len, and returns * the length of the composed string. */ LDAP_LUNICODE_F (int) uccanoncomp LDAP_P((ac_uint4 *str, int len)); /************************************************************************** * * Functions for getting decompositions. * **************************************************************************/ /* * This routine determines if the code has a decomposition. If it returns 0, * there is no decomposition. Any other value indicates a decomposition was * returned. */ LDAP_LUNICODE_F (int) ucdecomp LDAP_P((ac_uint4 code, ac_uint4 *num, ac_uint4 **decomp)); /* * Equivalent to ucdecomp() except that it includes compatibility * decompositions. */ LDAP_LUNICODE_F (int) uckdecomp LDAP_P((ac_uint4 code, ac_uint4 *num, ac_uint4 **decomp)); /* * If the code is a Hangul syllable, this routine decomposes it into the array * passed. The array size should be at least 3. */ LDAP_LUNICODE_F (int) ucdecomp_hangul LDAP_P((ac_uint4 code, ac_uint4 *num, ac_uint4 decomp[])); /* * This routine does canonical decomposition of the string in of length * inlen, and returns the decomposed string in out with length outlen. * The memory for out is allocated by this routine. It returns the length * of the decomposed string if okay, and -1 on error. */ LDAP_LUNICODE_F (int) uccanondecomp LDAP_P((const ac_uint4 *in, int inlen, ac_uint4 **out, int *outlen, void *ctx)); /* * Equivalent to uccanondecomp() except that it includes compatibility * decompositions. */ LDAP_LUNICODE_F (int) uccompatdecomp LDAP_P((const ac_uint4 *in, int inlen, ac_uint4 **out, int *outlen, void *ctx)); /************************************************************************** * * Functions for getting combining classes. * **************************************************************************/ /* * This will return the combining class for a character to be used with the * Canonical Ordering algorithm. */ LDAP_LUNICODE_F (ac_uint4) uccombining_class LDAP_P((ac_uint4 code)); /************************************************************************** * * Functions for getting numbers and digits. * **************************************************************************/ struct ucnumber { int numerator; int denominator; }; LDAP_LUNICODE_F (int) ucnumber_lookup LDAP_P((ac_uint4 code, struct ucnumber *num)); LDAP_LUNICODE_F (int) ucdigit_lookup LDAP_P((ac_uint4 code, int *digit)); /* * For compatibility with John Cowan's "uctype" package. */ LDAP_LUNICODE_F (struct ucnumber) ucgetnumber LDAP_P((ac_uint4 code)); LDAP_LUNICODE_F (int) ucgetdigit LDAP_P((ac_uint4 code)); /************************************************************************** * * Functions library initialization and cleanup. * **************************************************************************/ /* * Macros for specifying the data tables to be loaded, unloaded, or reloaded * by the ucdata_load(), ucdata_unload(), and ucdata_reload() routines. */ #define UCDATA_CASE 0x01 #define UCDATA_CTYPE 0x02 #define UCDATA_DECOMP 0x04 #define UCDATA_CMBCL 0x08 #define UCDATA_NUM 0x10 #define UCDATA_COMP 0x20 #define UCDATA_KDECOMP 0x40 #define UCDATA_ALL (UCDATA_CASE|UCDATA_CTYPE|UCDATA_DECOMP|\ UCDATA_CMBCL|UCDATA_NUM|UCDATA_COMP|UCDATA_KDECOMP) /* * Functions to load, unload, and reload specific data files. */ LDAP_LUNICODE_F (int) ucdata_load LDAP_P((char *paths, int mask)); LDAP_LUNICODE_F (void) ucdata_unload LDAP_P((int mask)); LDAP_LUNICODE_F (int) ucdata_reload LDAP_P((char *paths, int mask)); #ifdef UCDATA_DEPRECATED /* * Deprecated functions, now just compatibility macros. */ #define ucdata_setup(p) ucdata_load(p, UCDATA_ALL) #define ucdata_cleanup() ucdata_unload(UCDATA_ALL) #endif LDAP_END_DECL #endif /* _h_ucdata */ openldap-2.4.42+dfsg/libraries/liblunicode/ucdata/MUTTUCData.txt0000644000175000017500000002346612563404150023125 0ustar ryanryan# # $Id: MUTTUCData.txt,v 1.3 1999/10/29 00:04:35 mleisher Exp $ # # Copyright 1999 Computing Research Labs, New Mexico State University # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT # OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR # THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # # Implementation specific character properties. # # # Space, other. # 0009;;Ss;;;;;;;;;;;; 000A;;Ss;;;;;;;;;;;; 000B;;Ss;;;;;;;;;;;; 000C;;Ss;;;;;;;;;;;; 000D;;Ss;;;;;;;;;;;; # # Non-breaking. # 00A0;;Nb;;;;;;;;;;;; 2007;;Nb;;;;;;;;;;;; 2011;;Nb;;;;;;;;;;;; FEFF;;Nb;;;;;;;;;;;; # # Symmetric. # 0028;;Sy;;;;;;;;;;;; 0029;;Sy;;;;;;;;;;;; 005B;;Sy;;;;;;;;;;;; 005D;;Sy;;;;;;;;;;;; 007B;;Sy;;;;;;;;;;;; 007D;;Sy;;;;;;;;;;;; 00AB;;Sy;;;;;;;;;;;; 00BB;;Sy;;;;;;;;;;;; 0F3A;;Sy;;;;;;;;;;;; 0F3B;;Sy;;;;;;;;;;;; 0F3C;;Sy;;;;;;;;;;;; 0F3D;;Sy;;;;;;;;;;;; 0F3E;;Sy;;;;;;;;;;;; 0F3F;;Sy;;;;;;;;;;;; 2018;;Sy;;;;;;;;;;;; 2019;;Sy;;;;;;;;;;;; 201A;;Sy;;;;;;;;;;;; 201B;;Sy;;;;;;;;;;;; 201C;;Sy;;;;;;;;;;;; 201D;;Sy;;;;;;;;;;;; 201E;;Sy;;;;;;;;;;;; 201F;;Sy;;;;;;;;;;;; 2039;;Sy;;;;;;;;;;;; 203A;;Sy;;;;;;;;;;;; 2045;;Sy;;;;;;;;;;;; 2046;;Sy;;;;;;;;;;;; 207D;;Sy;;;;;;;;;;;; 207E;;Sy;;;;;;;;;;;; 208D;;Sy;;;;;;;;;;;; 208E;;Sy;;;;;;;;;;;; 2329;;Sy;;;;;;;;;;;; 232A;;Sy;;;;;;;;;;;; 3008;;Sy;;;;;;;;;;;; 3009;;Sy;;;;;;;;;;;; 300A;;Sy;;;;;;;;;;;; 300B;;Sy;;;;;;;;;;;; 300C;;Sy;;;;;;;;;;;; 300D;;Sy;;;;;;;;;;;; 300E;;Sy;;;;;;;;;;;; 300F;;Sy;;;;;;;;;;;; 3010;;Sy;;;;;;;;;;;; 3011;;Sy;;;;;;;;;;;; 3014;;Sy;;;;;;;;;;;; 3015;;Sy;;;;;;;;;;;; 3016;;Sy;;;;;;;;;;;; 3017;;Sy;;;;;;;;;;;; 3018;;Sy;;;;;;;;;;;; 3019;;Sy;;;;;;;;;;;; 301A;;Sy;;;;;;;;;;;; 301B;;Sy;;;;;;;;;;;; 301D;;Sy;;;;;;;;;;;; 301E;;Sy;;;;;;;;;;;; 301F;;Sy;;;;;;;;;;;; FD3E;;Sy;;;;;;;;;;;; FD3F;;Sy;;;;;;;;;;;; FE35;;Sy;;;;;;;;;;;; FE36;;Sy;;;;;;;;;;;; FE37;;Sy;;;;;;;;;;;; FE38;;Sy;;;;;;;;;;;; FE39;;Sy;;;;;;;;;;;; FE3A;;Sy;;;;;;;;;;;; FE3B;;Sy;;;;;;;;;;;; FE3C;;Sy;;;;;;;;;;;; FE3D;;Sy;;;;;;;;;;;; FE3E;;Sy;;;;;;;;;;;; FE3F;;Sy;;;;;;;;;;;; FE40;;Sy;;;;;;;;;;;; FE41;;Sy;;;;;;;;;;;; FE42;;Sy;;;;;;;;;;;; FE43;;Sy;;;;;;;;;;;; FE44;;Sy;;;;;;;;;;;; FE59;;Sy;;;;;;;;;;;; FE5A;;Sy;;;;;;;;;;;; FE5B;;Sy;;;;;;;;;;;; FE5C;;Sy;;;;;;;;;;;; FE5D;;Sy;;;;;;;;;;;; FE5E;;Sy;;;;;;;;;;;; FF08;;Sy;;;;;;;;;;;; FF09;;Sy;;;;;;;;;;;; FF3B;;Sy;;;;;;;;;;;; FF3D;;Sy;;;;;;;;;;;; FF5B;;Sy;;;;;;;;;;;; FF5D;;Sy;;;;;;;;;;;; FF62;;Sy;;;;;;;;;;;; FF63;;Sy;;;;;;;;;;;; # # Hex digit. # 0030;;Hd;;;;;;;;;;;; 0031;;Hd;;;;;;;;;;;; 0032;;Hd;;;;;;;;;;;; 0033;;Hd;;;;;;;;;;;; 0034;;Hd;;;;;;;;;;;; 0035;;Hd;;;;;;;;;;;; 0036;;Hd;;;;;;;;;;;; 0037;;Hd;;;;;;;;;;;; 0038;;Hd;;;;;;;;;;;; 0039;;Hd;;;;;;;;;;;; 0041;;Hd;;;;;;;;;;;; 0042;;Hd;;;;;;;;;;;; 0043;;Hd;;;;;;;;;;;; 0044;;Hd;;;;;;;;;;;; 0045;;Hd;;;;;;;;;;;; 0046;;Hd;;;;;;;;;;;; 0061;;Hd;;;;;;;;;;;; 0062;;Hd;;;;;;;;;;;; 0063;;Hd;;;;;;;;;;;; 0064;;Hd;;;;;;;;;;;; 0065;;Hd;;;;;;;;;;;; 0066;;Hd;;;;;;;;;;;; FF10;;Hd;;;;;;;;;;;; FF11;;Hd;;;;;;;;;;;; FF12;;Hd;;;;;;;;;;;; FF13;;Hd;;;;;;;;;;;; FF14;;Hd;;;;;;;;;;;; FF15;;Hd;;;;;;;;;;;; FF16;;Hd;;;;;;;;;;;; FF17;;Hd;;;;;;;;;;;; FF18;;Hd;;;;;;;;;;;; FF19;;Hd;;;;;;;;;;;; FF21;;Hd;;;;;;;;;;;; FF22;;Hd;;;;;;;;;;;; FF23;;Hd;;;;;;;;;;;; FF24;;Hd;;;;;;;;;;;; FF25;;Hd;;;;;;;;;;;; FF26;;Hd;;;;;;;;;;;; FF41;;Hd;;;;;;;;;;;; FF42;;Hd;;;;;;;;;;;; FF43;;Hd;;;;;;;;;;;; FF44;;Hd;;;;;;;;;;;; FF45;;Hd;;;;;;;;;;;; FF46;;Hd;;;;;;;;;;;; # # Quote marks. # 0022;;Qm;;;;;;;;;;;; 0027;;Qm;;;;;;;;;;;; 00AB;;Qm;;;;;;;;;;;; 00BB;;Qm;;;;;;;;;;;; 2018;;Qm;;;;;;;;;;;; 2019;;Qm;;;;;;;;;;;; 201A;;Qm;;;;;;;;;;;; 201B;;Qm;;;;;;;;;;;; 201C;;Qm;;;;;;;;;;;; 201D;;Qm;;;;;;;;;;;; 201E;;Qm;;;;;;;;;;;; 201F;;Qm;;;;;;;;;;;; 2039;;Qm;;;;;;;;;;;; 203A;;Qm;;;;;;;;;;;; 300C;;Qm;;;;;;;;;;;; 300D;;Qm;;;;;;;;;;;; 300E;;Qm;;;;;;;;;;;; 300F;;Qm;;;;;;;;;;;; 301D;;Qm;;;;;;;;;;;; 301E;;Qm;;;;;;;;;;;; 301F;;Qm;;;;;;;;;;;; FE41;;Qm;;;;;;;;;;;; FE42;;Qm;;;;;;;;;;;; FE43;;Qm;;;;;;;;;;;; FE44;;Qm;;;;;;;;;;;; FF02;;Qm;;;;;;;;;;;; FF07;;Qm;;;;;;;;;;;; FF62;;Qm;;;;;;;;;;;; FF63;;Qm;;;;;;;;;;;; # # Special Devanagari forms # E900;DEVANAGARI KSHA LIGATURE;Lo;0;L;0915 094D 0937;;;;N;;;;; E901;DEVANAGARI GNYA LIGATURE;Lo;0;L;091C 094D 091E;;;;N;;;;; E902;DEVANAGARI TTA LIGATURE;Lo;0;L;0924 094D 0924;;;;N;;;;; E903;DEVANAGARI TRA LIGATURE;Lo;0;L;0924 094D 0930;;;;N;;;;; E904;DEVANAGARI SHCHA LIGATURE;Lo;0;L;0936 094D 091B;;;;N;;;;; E905;DEVANAGARI SHRA LIGATURE;Lo;0;L;0936 094D 0930;;;;N;;;;; E906;DEVANAGARI SHVA LIGATURE;Lo;0;L;0936 094D 0935;;;;N;;;;; E907;DEVANAGARI KRA LIGATURE;Lo;0;L;;;;;N;;;;; E908;DEVANAGARI JRA LIGATURE;Lo;0;L;;;;;N;;;;; E909;DEVANAGARI ZRA LIGATURE;Lo;0;L;;;;;N;;;;; E90A;DEVANAGARI PHRA LIGATURE;Lo;0;L;;;;;N;;;;; E90B;DEVANAGARI FRA LIGATURE;Lo;0;L;;;;;N;;;;; E90C;DEVANAGARI PRA LIGATURE;Lo;0;L;;;;;N;;;;; E90D;DEVANAGARI SRA LIGATURE;Lo;0;L;;;;;N;;;;; E90E;DEVANAGARI RU LIGATURE;Lo;0;L;;;;;N;;;;; E90F;DEVANAGARI RUU LIGATURE;Lo;0;L;;;;;N;;;;; E915;DEVANAGARI HALF LETTER KA;Lo;0;L;;;;;N;;;;; E916;DEVANAGARI HALF LETTER KHA;Lo;0;L;;;;;N;;;;; E917;DEVANAGARI HALF LETTER GA;Lo;0;L;;;;;N;;;;; E918;DEVANAGARI HALF LETTER GHA;Lo;0;L;;;;;N;;;;; E919;DEVANAGARI HALF LETTER NGA;Lo;0;L;;;;;N;;;;; E91A;DEVANAGARI HALF LETTER CA;Lo;0;L;;;;;N;;;;; E91B;DEVANAGARI HALF LETTER CHA;Lo;0;L;;;;;N;;;;; E91C;DEVANAGARI HALF LETTER JA;Lo;0;L;;;;;N;;;;; E91D;DEVANAGARI HALF LETTER JHA;Lo;0;L;;;;;N;;;;; E91E;DEVANAGARI HALF LETTER NYA;Lo;0;L;;;;;N;;;;; E91F;DEVANAGARI HALF LETTER TTA;Lo;0;L;;;;;N;;;;; E920;DEVANAGARI HALF LETTER TTHA;Lo;0;L;;;;;N;;;;; E921;DEVANAGARI HALF LETTER DDA;Lo;0;L;;;;;N;;;;; E922;DEVANAGARI HALF LETTER DDHA;Lo;0;L;;;;;N;;;;; E923;DEVANAGARI HALF LETTER NNA;Lo;0;L;;;;;N;;;;; E924;DEVANAGARI HALF LETTER TA;Lo;0;L;;;;;N;;;;; E925;DEVANAGARI HALF LETTER THA;Lo;0;L;;;;;N;;;;; E926;DEVANAGARI HALF LETTER DA;Lo;0;L;;;;;N;;;;; E927;DEVANAGARI HALF LETTER DHA;Lo;0;L;;;;;N;;;;; E928;DEVANAGARI HALF LETTER NA;Lo;0;L;;;;;N;;;;; E929;DEVANAGARI HALF LETTER NNNA;Lo;0;L;0928 093C;;;;N;;;;; E92A;DEVANAGARI HALF LETTER PA;Lo;0;L;;;;;N;;;;; E92B;DEVANAGARI HALF LETTER PHA;Lo;0;L;;;;;N;;;;; E92C;DEVANAGARI HALF LETTER BA;Lo;0;L;;;;;N;;;;; E92D;DEVANAGARI HALF LETTER BHA;Lo;0;L;;;;;N;;;;; E92E;DEVANAGARI HALF LETTER MA;Lo;0;L;;;;;N;;;;; E92F;DEVANAGARI HALF LETTER YA;Lo;0;L;;;;;N;;;;; E930;DEVANAGARI HALF LETTER RA;Lo;0;L;;;;;N;;;;; E931;DEVANAGARI HALF LETTER RRA;Lo;0;L;0930 093C;;;;N;;;;; E932;DEVANAGARI HALF LETTER LA;Lo;0;L;;;;;N;;;;; E933;DEVANAGARI HALF LETTER LLA;Lo;0;L;;;;;N;;;;; E934;DEVANAGARI HALF LETTER LLLA;Lo;0;L;0933 093C;;;;N;;;;; E935;DEVANAGARI HALF LETTER VA;Lo;0;L;;;;;N;;;;; E936;DEVANAGARI HALF LETTER SHA;Lo;0;L;;;;;N;;;;; E937;DEVANAGARI HALF LETTER SSA;Lo;0;L;;;;;N;;;;; E938;DEVANAGARI HALF LETTER SA;Lo;0;L;;;;;N;;;;; E939;DEVANAGARI HALF LETTER HA;Lo;0;L;;;;;N;;;;; E940;DEVANAGARI KKA LIGATURE;Lo;0;L;0915 094D 0915;;;;N;;;;; E941;DEVANAGARI KTA LIGATURE;Lo;0;L;0915 094D 0924;;;;N;;;;; E942;DEVANAGARI NGKA LIGATURE;Lo;0;L;0919 094D 0915;;;;N;;;;; E943;DEVANAGARI NGKHA LIGATURE;Lo;0;L;0919 094D 0916;;;;N;;;;; E944;DEVANAGARI NGGA LIGATURE;Lo;0;L;0919 094D 0917;;;;N;;;;; E945;DEVANAGARI NGGHA LIGATURE;Lo;0;L;0919 094D 0918;;;;N;;;;; E946;DEVANAGARI NYJA LIGATURE;Lo;0;L;091E 094D 091C;;;;N;;;;; E947;DEVANAGARI DGHA LIGATURE;Lo;0;L;0926 094D 0918;;;;N;;;;; E948;DEVANAGARI DDA LIGATURE;Lo;0;L;0926 094D 0926;;;;N;;;;; E949;DEVANAGARI DDHA LIGATURE;Lo;0;L;0926 094D 0927;;;;N;;;;; E94A;DEVANAGARI DBA LIGATURE;Lo;0;L;0926 094D 092C;;;;N;;;;; E94B;DEVANAGARI DBHA LIGATURE;Lo;0;L;0926 094D 092D;;;;N;;;;; E94C;DEVANAGARI DMA LIGATURE;Lo;0;L;0926 094D 092E;;;;N;;;;; E94D;DEVANAGARI DYA LIGATURE;Lo;0;L;0926 094D 092F;;;;N;;;;; E94E;DEVANAGARI DVA LIGATURE;Lo;0;L;0926 094D 0935;;;;N;;;;; E94F;DEVANAGARI TT-TTA LIGATURE;Lo;0;L;091F 094D 091F;;;;N;;;;; E950;DEVANAGARI TT-TTHA LIGATURE;Lo;0;L;091F 094D 0920;;;;N;;;;; E951;DEVANAGARI TTH-TTHA LIGATURE;Lo;0;L;0920 094D 0920;;;;N;;;;; E952;DEVANAGARI DD-GA LIGATURE;Lo;0;L;0921 094D 0917;;;;N;;;;; E953;DEVANAGARI DD-DDA LIGATURE;Lo;0;L;0921 094D 0921;;;;N;;;;; E954;DEVANAGARI DD-DDHA LIGATURE;Lo;0;L;0921 094D 0922;;;;N;;;;; E955;DEVANAGARI NNA LIGATURE;Lo;0;L;0928 094D 0928;;;;N;;;;; E956;DEVANAGARI HMA LIGATURE;Lo;0;L;0939 094D 092E;;;;N;;;;; E957;DEVANAGARI HYA LIGATURE;Lo;0;L;0939 094D 092F;;;;N;;;;; E958;DEVANAGARI HLA LIGATURE;Lo;0;L;0939 094D 0932;;;;N;;;;; E959;DEVANAGARI HVA LIGATURE;Lo;0;L;0939 094D 0935;;;;N;;;;; E95A;DEVANAGARI STRA LIGATURE;Lo;0;L;0938 094D 0924 094D 0930;;;;N;;;;; E970;DEVANAGARI HALF KSHA LIGATURE;Lo;0;L;0915 094D 0937;;;;N;;;;; E971;DEVANAGARI HALF GNYA LIGATURE;Lo;0;L;091C 094D 091E;;;;N;;;;; E972;DEVANAGARI HALF TTA LIGATURE;Lo;0;L;0924 094D 0924;;;;N;;;;; E973;DEVANAGARI HALF TRA LIGATURE;Lo;0;L;0924 094D 0930;;;;N;;;;; E974;DEVANAGARI HALF SHCHA LIGATURE;Lo;0;L;0936 094D 091B;;;;N;;;;; E975;DEVANAGARI HALF SHRA LIGATURE;Lo;0;L;0936 094D 0930;;;;N;;;;; E976;DEVANAGARI HALF SHVA LIGATURE;Lo;0;L;0936 094D 0935;;;;N;;;;; E97B;DEVANAGARI SIGN RRA-REPHA;Mn;36;L;;;;;N;;;;; E97C;DEVANAGARI HAR LIGATURE;Lo;0;L;0939 0943;;;;N;;;;; E97D;DEVANAGARI SIGN EYELASH RA;Lo;0;L;;;;;N;;;;; E97E;DEVANAGARI SIGN REPHA;Mn;36;L;;;;;N;;;;; E97F;DEVANAGARI SIGN SUBJOINED RA;Mn;36;L;;;;;N;;;;; openldap-2.4.42+dfsg/libraries/liblunicode/ucdata/ucpgba.man0000644000175000017500000000516512563404150022503 0ustar ryanryan.\" .\" $Id: ucpgba.man,v 1.1 1999/11/19 16:08:34 mleisher Exp $ .\" .TH ucpgba 3 "19 November 1999" .SH NAME ucpgba \- functions for doing bidirectional reordering of Unicode text and logical and visual cursor motion .SH SYNOPSIS .nf #include #include ucstring_t *ucstring_create(unsigned long *source, unsigned long start, unsigned long end, int default_direction, int cursor_motion) .sp void ucstring_free(ucstring_t *string) .sp int ucstring_set_cursor_motion(ucstring_t *string, int cursor_motion) .sp int ucstring_cursor_right(ucstring_t *string, int count) .sp int ucstring_cursor_left(ucstring_t *string, int count) .sp void ucstring_cursor_info(ucstring_t *string, int *direction, unsigned long *position) .SH DESCRIPTION .TP 4 .BR Macros UCPGBA_LTR .br UCPGBA_RTL .br UCPGBA_CURSOR_VISUAL .br UCPGBA_CURSOR_LOGICAL .TP 4 .BR ucstring_create() This function will create a reordered string by using the implicit directionality of the characters in the specified substring. .sp The `default_direction' parameter should be one of UCPGBA_LTR or UCPGBA_RTL and is used only in cases where a string contains no characters with strong directionality. .sp The `cursor_motion' parameter should be one of UCPGBA_CURSOR_VISUAL or UCPGBA_CURSOR_LOGICAL, and is used to specify the initial cursor motion behavior. This behavior can be switched at any time using ustring_set_cursor_motion(). .TP 4 .BR ucstring_free() This function will deallocate the memory used by the string, incuding the string itself. .TP 4 .BR ucstring_cursor_info() This function will return the text position of the internal cursor and the directionality of the text at that position. The position returned is the original text position of the character. .TP 4 .BR ucstring_set_cursor_motion() This function will change the cursor motion type and return the previous cursor motion type. .TP 4 .BR ucstring_cursor_right() This function will move the internal cursor to the right according to the type of cursor motion set for the string. .sp If no cursor motion is performed, it returns 0. Otherwise it will return a 1. .TP 4 .BR ucstring_cursor_left() This function will move the internal cursor to the left according to the type of cursor motion set for the string. .sp If no cursor motion is performed, it returns 0. Otherwise it will return a 1. .SH "SEE ALSO" ucdata(3) .SH ACKNOWLEDGMENTS These are people who have helped with patches or alerted me about problems. .SH AUTHOR Mark Leisher .br Computing Research Lab .br New Mexico State University .br Email: mleisher@crl.nmsu.edu openldap-2.4.42+dfsg/libraries/liblunicode/utbm/0000755000175000017500000000000012563404150020244 5ustar ryanryanopenldap-2.4.42+dfsg/libraries/liblunicode/utbm/README0000644000175000017500000001001612563404150021122 0ustar ryanryan# # $Id: README,v 1.1 1999/09/21 15:45:17 mleisher Exp $ # # Copyright 1997, 1998, 1999 Computing Research Labs, # New Mexico State University # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT # OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR # THE USE OR OTHER DEALINGS IN THE SOFTWARE. # Unicode and Boyer-Moore Searching Version 0.2 UTBM (Unicode Tuned Boyer-Moore) is a simple package that provides tuned Boyer-Moore searches on Unicode UCS2 text (handles high and low surrogates). --------------------------------------------------------------------------- Assumptions: o Search pattern and text already normalized in some fasion. o Upper, lower, and title case conversions are one-to-one. o For conversions between upper, lower, and title case, UCS2 characters always convert to other UCS2 characters, and UTF-16 characters always convert to other UTF-16 characters. Flags: UTBM provides three processing flags: o UTBM_CASEFOLD - search in a case-insensitive manner. o UTBM_IGNORE_NONSPACING - ignore non-spacing characters in the pattern and the text. o UTBM_SPACE_COMPRESS - view as a *single space*, sequential groups of U+2028, U+2029, '\n', '\r', '\t', and any character identified as a space by the Unicode support on the platform. This flag also causes all characters identified as control by the Unicode support on the platform to be ignored (except for '\n', '\r', and '\t'). --------------------------------------------------------------------------- Before using UTBM ----------------- Before UTBM is used, some functions need to be created. The "utbmstub.c" file contains stubs that need to be rewritten so they work with the Unicode support on the platform on which this package is being used. Using UTBM ---------- Sample pseudo-code fragment. utbm_pattern_t pat; ucs2_t *pattern, *text; unsigned long patternlen, textlen; unsigned long flags, match_start, match_end; /* * Allocate the dynamic storage needed for a search pattern. */ pat = utbm_create_pattern(); /* * Set the search flags desired. */ flags = UTBM_CASEFOLD|UTBM_IGNORE_NONSPACING; /* * Compile the search pattern. */ utbm_compile(pattern, patternlen, flags, pat); /* * Find the first occurance of the search pattern in the text. */ if (utbm_exec(pat, text, textlen, &match_start, &match_end)) printf("MATCH: %ld %ld\n", match_start, match_end); /* * Free the dynamic storage used for the search pattern. */ ure_free_pattern(pat); --------------------------------------------------------------------------- Mark Leisher 2 May 1997 =========================================================================== CHANGES ------- Version: 0.2 Date : 21 September 1999 ========================== 1. Added copyright stuff and put in CVS. openldap-2.4.42+dfsg/libraries/liblunicode/utbm/utbmstub.c0000644000175000017500000000547412563404150022267 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Copyright 1997, 1998, 1999 Computing Research Labs, * New Mexico State University * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* $Id: utbmstub.c,v 1.1 1999/09/21 15:45:18 mleisher Exp $ */ #include "utbm.h" /* * This should be redefined to use the `isspace' function available in the * Unicode support on the platform where this is being used. */ #define _platform_isspace(x) 0 /* * Return non-zero for any character that should be considered the equivalent * of a space character. Return zero otherwise. */ int _utbm_isspace(ucs4_t c, int compress) { if (compress) return (c == 0x09 || c == 0x0a || c == 0x0d || c == 0x2028 || c == 0x2029 || _platform_isspace(c)) ? 1 : 0; return _platform_isspace(c); } /* * Return non-zero if the character is a control character, or zero otherwise. */ int _utbm_iscntrl(ucs4_t c) { return 0; } /* * Return non-zero if the character is a non-spacing character, or zero * otherwise. */ int _utbm_nonspacing(ucs4_t c) { return 0; } /* * Convert a character to lower case. */ ucs4_t _utbm_tolower(ucs4_t c) { return c; } /* * Convert a character to upper case. */ ucs4_t _utbm_toupper(ucs4_t c) { return c; } /* * Convert a character to title case. */ ucs4_t _utbm_totitle(ucs4_t c) { return c; } openldap-2.4.42+dfsg/libraries/liblunicode/utbm/utbm.h0000644000175000017500000000715612563404150021375 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Copyright 1997, 1998, 1999 Computing Research Labs, * New Mexico State University * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* $Id: utbm.h,v 1.1 1999/09/21 15:45:18 mleisher Exp $ */ #ifndef _h_utbm #define _h_utbm #include "portable.h" LDAP_BEGIN_DECL /************************************************************************* * * Types. * *************************************************************************/ /* * Fundamental character types. */ typedef unsigned long ucs4_t; typedef unsigned short ucs2_t; /* * An opaque type used for the search pattern. */ typedef struct _utbm_pattern_t *utbm_pattern_t; /************************************************************************* * * Flags. * *************************************************************************/ #define UTBM_CASEFOLD 0x01 #define UTBM_IGNORE_NONSPACING 0x02 #define UTBM_SPACE_COMPRESS 0x04 /************************************************************************* * * API. * *************************************************************************/ LDAP_LUNICODE_F (utbm_pattern_t) utbm_create_pattern LDAP_P((void)); LDAP_LUNICODE_F (void) utbm_free_pattern LDAP_P((utbm_pattern_t pattern)); LDAP_LUNICODE_F (void) utbm_compile LDAP_P((ucs2_t *pat, unsigned long patlen, unsigned long flags, utbm_pattern_t pattern)); LDAP_LUNICODE_F (int) utbm_exec LDAP_P((utbm_pattern_t pat, ucs2_t *text, unsigned long textlen, unsigned long *match_start, unsigned long *match_end)); /************************************************************************* * * Prototypes for the stub functions needed. * *************************************************************************/ LDAP_LUNICODE_F (int) _utbm_isspace LDAP_P((ucs4_t c, int compress)); LDAP_LUNICODE_F (int) _utbm_iscntrl LDAP_P((ucs4_t c)); LDAP_LUNICODE_F (int) _utbm_nonspacing LDAP_P((ucs4_t c)); LDAP_LUNICODE_F (ucs4_t) _utbm_tolower LDAP_P((ucs4_t c)); LDAP_LUNICODE_F (ucs4_t) _utbm_toupper LDAP_P((ucs4_t c)); LDAP_LUNICODE_F (ucs4_t) _utbm_totitle LDAP_P((ucs4_t c)); LDAP_END_DECL #endif #endif /* _h_utbm */ openldap-2.4.42+dfsg/libraries/liblunicode/utbm/utbm.c0000644000175000017500000003167512563404150021373 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Copyright 1997, 1998, 1999 Computing Research Labs, * New Mexico State University * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* $Id: utbm.c,v 1.1 1999/09/21 15:45:17 mleisher Exp $ */ /* * Assumptions: * 1. Case conversions of UTF-16 characters must also be UTF-16 characters. * 2. Case conversions are all one-to-one. * 3. Text and pattern have already been normalized in some fashion. */ #include #include #include #include "utbm.h" /* * Single pattern character. */ typedef struct { ucs4_t lc; ucs4_t uc; ucs4_t tc; } _utbm_char_t; typedef struct { _utbm_char_t *ch; unsigned long skip; } _utbm_skip_t; typedef struct _utbm_pattern_t { unsigned long flags; _utbm_char_t *pat; unsigned long pat_used; unsigned long pat_size; unsigned long patlen; _utbm_skip_t *skip; unsigned long skip_used; unsigned long skip_size; unsigned long md4; } _utbm_pattern_t; /************************************************************************* * * Support functions. * *************************************************************************/ /* * Routine to look up the skip value for a character. */ static unsigned long _utbm_skip(utbm_pattern_t p, ucs2_t *start, ucs2_t *end) { unsigned long i; ucs4_t c1, c2; _utbm_skip_t *sp; if (start >= end) return 0; c1 = *start; c2 = (start + 1 < end) ? *(start + 1) : ~0; if (0xd800 <= c1 && c1 <= 0xdbff && 0xdc00 <= c2 && c2 <= 0xdfff) c1 = 0x10000 + (((c1 & 0x03ff) << 10) | (c2 & 0x03ff)); for (i = 0, sp = p->skip; i < p->skip_used; i++, sp++) { if (!((c1 ^ sp->ch->uc) & (c1 ^ sp->ch->lc) & (c1 ^ sp->ch->tc))) { return ((unsigned long) (end - start) < sp->skip) ? end - start : sp->skip; } } return p->patlen; } static int _utbm_match(utbm_pattern_t pat, ucs2_t *text, ucs2_t *start, ucs2_t *end, unsigned long *match_start, unsigned long *match_end) { int check_space; ucs4_t c1, c2; unsigned long count; _utbm_char_t *cp; /* * Set the potential match endpoint first. */ *match_end = (start - text) + 1; c1 = *start; c2 = (start + 1 < end) ? *(start + 1) : ~0; if (0xd800 <= c1 && c1 <= 0xdbff && 0xdc00 <= c2 && c2 <= 0xdfff) { c1 = 0x10000 + (((c1 & 0x03ff) << 10) | (c2 & 0x03ff)); /* * Adjust the match end point to occur after the UTF-16 character. */ *match_end = *match_end + 1; } if (pat->pat_used == 1) { *match_start = start - text; return 1; } /* * Compare backward. */ cp = pat->pat + (pat->pat_used - 1); for (count = pat->patlen; start > text && count > 0;) { /* * Ignore non-spacing characters if indicated. */ if (pat->flags & UTBM_IGNORE_NONSPACING) { while (start > text && _utbm_nonspacing(c1)) { c2 = *--start; c1 = (start - 1 > text) ? *(start - 1) : ~0; if (0xdc00 <= c2 && c2 <= 0xdfff && 0xd800 <= c1 && c1 <= 0xdbff) { c1 = 0x10000 + (((c1 & 0x03ff) << 10) | (c2 & 0x03ff)); start--; } else c1 = c2; } } /* * Handle space compression if indicated. */ if (pat->flags & UTBM_SPACE_COMPRESS) { check_space = 0; while (start > text && (_utbm_isspace(c1, 1) || _utbm_iscntrl(c1))) { check_space = _utbm_isspace(c1, 1); c2 = *--start; c1 = (start - 1 > text) ? *(start - 1) : ~0; if (0xdc00 <= c2 && c2 <= 0xdfff && 0xd800 <= c1 && c1 <= 0xdbff) { c1 = 0x10000 + (((c1 & 0x03ff) << 10) | (c2 & 0x03ff)); start--; } else c1 = c2; } /* * Handle things if space compression was indicated and one or * more member characters were found. */ if (check_space) { if (cp->uc != ' ') return 0; cp--; count--; } } /* * Handle the normal comparison cases. */ if (count > 0 && ((c1 ^ cp->uc) & (c1 ^ cp->lc) & (c1 ^ cp->tc))) return 0; count -= (c1 >= 0x10000) ? 2 : 1; if (count > 0) { cp--; /* * Get the next preceding character. */ if (start > text) { c2 = *--start; c1 = (start - 1 > text) ? *(start - 1) : ~0; if (0xdc00 <= c2 && c2 <= 0xdfff && 0xd800 <= c1 && c1 <= 0xdbff) { c1 = 0x10000 + (((c1 & 0x03ff) << 10) | (c2 & 0x03ff)); start--; } else c1 = c2; } } } /* * Set the match start position. */ *match_start = start - text; return 1; } /************************************************************************* * * API. * *************************************************************************/ utbm_pattern_t utbm_create_pattern(void) { utbm_pattern_t p; p = (utbm_pattern_t) malloc(sizeof(_utbm_pattern_t)); (void) memset((char *) p, '\0', sizeof(_utbm_pattern_t)); return p; } void utbm_free_pattern(utbm_pattern_t pattern) { if (pattern == 0) return; if (pattern->pat_size > 0) free((char *) pattern->pat); if (pattern->skip_size > 0) free((char *) pattern->skip); free((char *) pattern); } void utbm_compile(ucs2_t *pat, unsigned long patlen, unsigned long flags, utbm_pattern_t p) { int have_space; unsigned long i, j, k, slen; _utbm_char_t *cp; _utbm_skip_t *sp; ucs4_t c1, c2, sentinel; if (p == 0 || pat == 0 || *pat == 0 || patlen == 0) return; /* * Reset the pattern buffer. */ p->patlen = p->pat_used = p->skip_used = 0; /* * Set the flags. */ p->flags = flags; /* * Initialize the extra skip flag. */ p->md4 = 1; /* * Allocate more storage if necessary. */ if (patlen > p->pat_size) { if (p->pat_size == 0) { p->pat = (_utbm_char_t *) malloc(sizeof(_utbm_char_t) * patlen); p->skip = (_utbm_skip_t *) malloc(sizeof(_utbm_skip_t) * patlen); } else { p->pat = (_utbm_char_t *) realloc((char *) p->pat, sizeof(_utbm_char_t) * patlen); p->skip = (_utbm_skip_t *) realloc((char *) p->skip, sizeof(_utbm_skip_t) * patlen); } p->pat_size = p->skip_size = patlen; } /* * Preprocess the pattern to remove controls (if specified) and determine * case. */ for (have_space = 0, cp = p->pat, i = 0; i < patlen; i++) { c1 = pat[i]; c2 = (i + 1 < patlen) ? pat[i + 1] : ~0; if (0xd800 <= c1 && c1 <= 0xdbff && 0xdc00 <= c2 && c2 <= 0xdfff) c1 = 0x10000 + (((c1 & 0x03ff) << 10) | (c2 & 0x03ff)); /* * Make sure the `have_space' flag is turned off if the character * is not an appropriate one. */ if (!_utbm_isspace(c1, flags & UTBM_SPACE_COMPRESS)) have_space = 0; /* * If non-spacing characters should be ignored, do it here. */ if ((flags & UTBM_IGNORE_NONSPACING) && _utbm_nonspacing(c1)) continue; /* * Check if spaces and controls need to be compressed. */ if (flags & UTBM_SPACE_COMPRESS) { if (_utbm_isspace(c1, 1)) { if (!have_space) { /* * Add a space and set the flag. */ cp->uc = cp->lc = cp->tc = ' '; cp++; /* * Increase the real pattern length. */ p->patlen++; sentinel = ' '; have_space = 1; } continue; } /* * Ignore all control characters. */ if (_utbm_iscntrl(c1)) continue; } /* * Add the character. */ if (flags & UTBM_CASEFOLD) { cp->uc = _utbm_toupper(c1); cp->lc = _utbm_tolower(c1); cp->tc = _utbm_totitle(c1); } else cp->uc = cp->lc = cp->tc = c1; /* * Set the sentinel character. */ sentinel = cp->uc; /* * Move to the next character. */ cp++; /* * Increase the real pattern length appropriately. */ p->patlen += (c1 >= 0x10000) ? 2 : 1; /* * Increment the loop index for UTF-16 characters. */ i += (c1 >= 0x10000) ? 1 : 0; } /* * Set the number of characters actually used. */ p->pat_used = cp - p->pat; /* * Go through and construct the skip array and determine the actual length * of the pattern in UCS2 terms. */ slen = p->patlen - 1; cp = p->pat; for (i = k = 0; i < p->pat_used; i++, cp++) { /* * Locate the character in the skip array. */ for (sp = p->skip, j = 0; j < p->skip_used && sp->ch->uc != cp->uc; j++, sp++) ; /* * If the character is not found, set the new skip element and * increase the number of skip elements. */ if (j == p->skip_used) { sp->ch = cp; p->skip_used++; } /* * Set the updated skip value. If the character is UTF-16 and is * not the last one in the pattern, add one to its skip value. */ sp->skip = slen - k; if (cp->uc >= 0x10000 && k + 2 < slen) sp->skip++; /* * Set the new extra skip for the sentinel character. */ if (((cp->uc >= 0x10000 && k + 2 <= slen) || k + 1 <= slen) && cp->uc == sentinel) p->md4 = slen - k; /* * Increase the actual index. */ k += (cp->uc >= 0x10000) ? 2 : 1; } } int utbm_exec(utbm_pattern_t pat, ucs2_t *text, unsigned long textlen, unsigned long *match_start, unsigned long *match_end) { unsigned long k; ucs2_t *start, *end; if (pat == 0 || pat->pat_used == 0 || text == 0 || textlen == 0 || textlen < pat->patlen) return 0; start = text + pat->patlen; end = text + textlen; /* * Adjust the start point if it points to a low surrogate. */ if (0xdc00 <= *start && *start <= 0xdfff && 0xd800 <= *(start - 1) && *(start - 1) <= 0xdbff) start--; while (start < end) { while ((k = _utbm_skip(pat, start, end))) { start += k; if (start < end && 0xdc00 <= *start && *start <= 0xdfff && 0xd800 <= *(start - 1) && *(start - 1) <= 0xdbff) start--; } if (start < end && _utbm_match(pat, text, start, end, match_start, match_end)) return 1; start += pat->md4; if (start < end && 0xdc00 <= *start && *start <= 0xdfff && 0xd800 <= *(start - 1) && *(start - 1) <= 0xdbff) start--; } return 0; } openldap-2.4.42+dfsg/libraries/libldap_r/0000755000175000017500000000000012563404150016734 5ustar ryanryanopenldap-2.4.42+dfsg/libraries/libldap_r/threads.c0000644000175000017500000000463212563404150020537 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #include "portable.h" #include #include #include #include #include #include "ldap_pvt_thread.h" /* Get the thread interface */ #include "ldap_thr_debug.h" /* May redirect thread initialize/destroy calls */ /* * Common LDAP thread routines * see thr_*.c for implementation specific routines * see rdwr.c for generic reader/writer lock implementation * see tpool.c for generic thread pool implementation */ int ldap_pvt_thread_initialize( void ) { int rc; static int init = 0; ldap_pvt_thread_rmutex_t rm; ldap_pvt_thread_t tid; /* we only get one shot at this */ if( init++ ) return -1; rc = ldap_int_thread_initialize(); if( rc ) return rc; #ifndef LDAP_THREAD_HAVE_TPOOL rc = ldap_int_thread_pool_startup(); if( rc ) return rc; #endif /* kludge to pull symbol definitions in */ ldap_pvt_thread_rmutex_init( &rm ); tid = ldap_pvt_thread_self(); ldap_pvt_thread_rmutex_lock( &rm, tid ); ldap_pvt_thread_rmutex_trylock( &rm, tid ); ldap_pvt_thread_rmutex_unlock( &rm, tid ); ldap_pvt_thread_rmutex_unlock( &rm, tid ); ldap_pvt_thread_rmutex_destroy( &rm ); return 0; } int ldap_pvt_thread_destroy( void ) { #ifndef LDAP_THREAD_HAVE_TPOOL (void) ldap_int_thread_pool_shutdown(); #endif return ldap_int_thread_destroy(); } /* * Default implementations of some LDAP thread routines */ #define LDAP_THREAD_IMPLEMENTATION #include "ldap_thr_debug.h" /* May rename the symbols defined below */ #ifndef LDAP_THREAD_HAVE_GETCONCURRENCY int ldap_pvt_thread_get_concurrency ( void ) { return 1; } #endif #ifndef LDAP_THREAD_HAVE_SETCONCURRENCY int ldap_pvt_thread_set_concurrency ( int concurrency ) { return 1; } #endif #ifndef LDAP_THREAD_HAVE_SLEEP /* * Here we assume we have fully preemptive threads and that sleep() * does the right thing. */ unsigned int ldap_pvt_thread_sleep( unsigned int interval ) { sleep( interval ); return 0; } #endif openldap-2.4.42+dfsg/libraries/libldap_r/rdwr.c0000644000175000017500000002561312563404150020065 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* This work was initially developed by Kurt D. Zeilenga for inclusion * in OpenLDAP Software. Additional significant contributors include: * Stuart Lynne */ /* * This is an improved implementation of Reader/Writer locks does * not protect writers from starvation. That is, if a writer is * currently waiting on a reader, any new reader will get * the lock before the writer. * * Does not support cancellation nor does any status checking. */ /* Adapted from publically available examples for: * "Programming with Posix Threads" * by David R Butenhof, Addison-Wesley * http://cseng.aw.com/bookpage.taf?ISBN=0-201-63392-2 */ #include "portable.h" #include #include #include #include #include "ldap-int.h" #include "ldap_pvt_thread.h" /* Get the thread interface */ #define LDAP_THREAD_RDWR_IMPLEMENTATION #include "ldap_thr_debug.h" /* May rename the symbols defined below */ /* * implementations that provide their own compatible * reader/writer locks define LDAP_THREAD_HAVE_RDWR * in ldap_pvt_thread.h */ #ifndef LDAP_THREAD_HAVE_RDWR struct ldap_int_thread_rdwr_s { ldap_pvt_thread_mutex_t ltrw_mutex; ldap_pvt_thread_cond_t ltrw_read; /* wait for read */ ldap_pvt_thread_cond_t ltrw_write; /* wait for write */ int ltrw_valid; #define LDAP_PVT_THREAD_RDWR_VALID 0x0bad int ltrw_r_active; int ltrw_w_active; int ltrw_r_wait; int ltrw_w_wait; #ifdef LDAP_RDWR_DEBUG /* keep track of who has these locks */ #define MAX_READERS 32 int ltrw_more_readers; /* Set if ltrw_readers[] is incomplete */ ldap_pvt_thread_t ltrw_readers[MAX_READERS]; ldap_pvt_thread_t ltrw_writer; #endif }; int ldap_pvt_thread_rdwr_init( ldap_pvt_thread_rdwr_t *rwlock ) { struct ldap_int_thread_rdwr_s *rw; assert( rwlock != NULL ); rw = (struct ldap_int_thread_rdwr_s *) LDAP_CALLOC( 1, sizeof( struct ldap_int_thread_rdwr_s ) ); if ( !rw ) return LDAP_NO_MEMORY; /* we should check return results */ ldap_pvt_thread_mutex_init( &rw->ltrw_mutex ); ldap_pvt_thread_cond_init( &rw->ltrw_read ); ldap_pvt_thread_cond_init( &rw->ltrw_write ); rw->ltrw_valid = LDAP_PVT_THREAD_RDWR_VALID; *rwlock = rw; return 0; } int ldap_pvt_thread_rdwr_destroy( ldap_pvt_thread_rdwr_t *rwlock ) { struct ldap_int_thread_rdwr_s *rw; assert( rwlock != NULL ); rw = *rwlock; assert( rw != NULL ); assert( rw->ltrw_valid == LDAP_PVT_THREAD_RDWR_VALID ); if( rw->ltrw_valid != LDAP_PVT_THREAD_RDWR_VALID ) return LDAP_PVT_THREAD_EINVAL; ldap_pvt_thread_mutex_lock( &rw->ltrw_mutex ); assert( rw->ltrw_w_active >= 0 ); assert( rw->ltrw_w_wait >= 0 ); assert( rw->ltrw_r_active >= 0 ); assert( rw->ltrw_r_wait >= 0 ); /* active threads? */ if( rw->ltrw_r_active > 0 || rw->ltrw_w_active > 0) { ldap_pvt_thread_mutex_unlock( &rw->ltrw_mutex ); return LDAP_PVT_THREAD_EBUSY; } /* waiting threads? */ if( rw->ltrw_r_wait > 0 || rw->ltrw_w_wait > 0) { ldap_pvt_thread_mutex_unlock( &rw->ltrw_mutex ); return LDAP_PVT_THREAD_EBUSY; } rw->ltrw_valid = 0; ldap_pvt_thread_mutex_unlock( &rw->ltrw_mutex ); ldap_pvt_thread_mutex_destroy( &rw->ltrw_mutex ); ldap_pvt_thread_cond_destroy( &rw->ltrw_read ); ldap_pvt_thread_cond_destroy( &rw->ltrw_write ); LDAP_FREE(rw); *rwlock = NULL; return 0; } int ldap_pvt_thread_rdwr_rlock( ldap_pvt_thread_rdwr_t *rwlock ) { struct ldap_int_thread_rdwr_s *rw; assert( rwlock != NULL ); rw = *rwlock; assert( rw != NULL ); assert( rw->ltrw_valid == LDAP_PVT_THREAD_RDWR_VALID ); if( rw->ltrw_valid != LDAP_PVT_THREAD_RDWR_VALID ) return LDAP_PVT_THREAD_EINVAL; ldap_pvt_thread_mutex_lock( &rw->ltrw_mutex ); assert( rw->ltrw_w_active >= 0 ); assert( rw->ltrw_w_wait >= 0 ); assert( rw->ltrw_r_active >= 0 ); assert( rw->ltrw_r_wait >= 0 ); if( rw->ltrw_w_active > 0 ) { /* writer is active */ rw->ltrw_r_wait++; do { ldap_pvt_thread_cond_wait( &rw->ltrw_read, &rw->ltrw_mutex ); } while( rw->ltrw_w_active > 0 ); rw->ltrw_r_wait--; assert( rw->ltrw_r_wait >= 0 ); } #ifdef LDAP_RDWR_DEBUG if( rw->ltrw_r_active < MAX_READERS ) rw->ltrw_readers[rw->ltrw_r_active] = ldap_pvt_thread_self(); else rw->ltrw_more_readers = 1; #endif rw->ltrw_r_active++; ldap_pvt_thread_mutex_unlock( &rw->ltrw_mutex ); return 0; } int ldap_pvt_thread_rdwr_rtrylock( ldap_pvt_thread_rdwr_t *rwlock ) { struct ldap_int_thread_rdwr_s *rw; assert( rwlock != NULL ); rw = *rwlock; assert( rw != NULL ); assert( rw->ltrw_valid == LDAP_PVT_THREAD_RDWR_VALID ); if( rw->ltrw_valid != LDAP_PVT_THREAD_RDWR_VALID ) return LDAP_PVT_THREAD_EINVAL; ldap_pvt_thread_mutex_lock( &rw->ltrw_mutex ); assert( rw->ltrw_w_active >= 0 ); assert( rw->ltrw_w_wait >= 0 ); assert( rw->ltrw_r_active >= 0 ); assert( rw->ltrw_r_wait >= 0 ); if( rw->ltrw_w_active > 0) { ldap_pvt_thread_mutex_unlock( &rw->ltrw_mutex ); return LDAP_PVT_THREAD_EBUSY; } #ifdef LDAP_RDWR_DEBUG if( rw->ltrw_r_active < MAX_READERS ) rw->ltrw_readers[rw->ltrw_r_active] = ldap_pvt_thread_self(); else rw->ltrw_more_readers = 1; #endif rw->ltrw_r_active++; ldap_pvt_thread_mutex_unlock( &rw->ltrw_mutex ); return 0; } int ldap_pvt_thread_rdwr_runlock( ldap_pvt_thread_rdwr_t *rwlock ) { struct ldap_int_thread_rdwr_s *rw; assert( rwlock != NULL ); rw = *rwlock; assert( rw != NULL ); assert( rw->ltrw_valid == LDAP_PVT_THREAD_RDWR_VALID ); if( rw->ltrw_valid != LDAP_PVT_THREAD_RDWR_VALID ) return LDAP_PVT_THREAD_EINVAL; ldap_pvt_thread_mutex_lock( &rw->ltrw_mutex ); rw->ltrw_r_active--; #ifdef LDAP_RDWR_DEBUG /* Remove us from the list of readers */ { ldap_pvt_thread_t self = ldap_pvt_thread_self(); int i, j; for( i = j = rw->ltrw_r_active; i >= 0; i--) { if (rw->ltrw_readers[i] == self) { rw->ltrw_readers[i] = rw->ltrw_readers[j]; rw->ltrw_readers[j] = 0; break; } } if( !rw->ltrw_more_readers ) assert( i >= 0 ); else if( j == 0 ) rw->ltrw_more_readers = 0; } #endif assert( rw->ltrw_w_active >= 0 ); assert( rw->ltrw_w_wait >= 0 ); assert( rw->ltrw_r_active >= 0 ); assert( rw->ltrw_r_wait >= 0 ); if (rw->ltrw_r_active == 0 && rw->ltrw_w_wait > 0 ) { ldap_pvt_thread_cond_signal( &rw->ltrw_write ); } ldap_pvt_thread_mutex_unlock( &rw->ltrw_mutex ); return 0; } int ldap_pvt_thread_rdwr_wlock( ldap_pvt_thread_rdwr_t *rwlock ) { struct ldap_int_thread_rdwr_s *rw; assert( rwlock != NULL ); rw = *rwlock; assert( rw != NULL ); assert( rw->ltrw_valid == LDAP_PVT_THREAD_RDWR_VALID ); if( rw->ltrw_valid != LDAP_PVT_THREAD_RDWR_VALID ) return LDAP_PVT_THREAD_EINVAL; ldap_pvt_thread_mutex_lock( &rw->ltrw_mutex ); assert( rw->ltrw_w_active >= 0 ); assert( rw->ltrw_w_wait >= 0 ); assert( rw->ltrw_r_active >= 0 ); assert( rw->ltrw_r_wait >= 0 ); if ( rw->ltrw_w_active > 0 || rw->ltrw_r_active > 0 ) { rw->ltrw_w_wait++; do { ldap_pvt_thread_cond_wait( &rw->ltrw_write, &rw->ltrw_mutex ); } while ( rw->ltrw_w_active > 0 || rw->ltrw_r_active > 0 ); rw->ltrw_w_wait--; assert( rw->ltrw_w_wait >= 0 ); } #ifdef LDAP_RDWR_DEBUG rw->ltrw_writer = ldap_pvt_thread_self(); #endif rw->ltrw_w_active++; ldap_pvt_thread_mutex_unlock( &rw->ltrw_mutex ); return 0; } int ldap_pvt_thread_rdwr_wtrylock( ldap_pvt_thread_rdwr_t *rwlock ) { struct ldap_int_thread_rdwr_s *rw; assert( rwlock != NULL ); rw = *rwlock; assert( rw != NULL ); assert( rw->ltrw_valid == LDAP_PVT_THREAD_RDWR_VALID ); if( rw->ltrw_valid != LDAP_PVT_THREAD_RDWR_VALID ) return LDAP_PVT_THREAD_EINVAL; ldap_pvt_thread_mutex_lock( &rw->ltrw_mutex ); assert( rw->ltrw_w_active >= 0 ); assert( rw->ltrw_w_wait >= 0 ); assert( rw->ltrw_r_active >= 0 ); assert( rw->ltrw_r_wait >= 0 ); if ( rw->ltrw_w_active > 0 || rw->ltrw_r_active > 0 ) { ldap_pvt_thread_mutex_unlock( &rw->ltrw_mutex ); return LDAP_PVT_THREAD_EBUSY; } #ifdef LDAP_RDWR_DEBUG rw->ltrw_writer = ldap_pvt_thread_self(); #endif rw->ltrw_w_active++; ldap_pvt_thread_mutex_unlock( &rw->ltrw_mutex ); return 0; } int ldap_pvt_thread_rdwr_wunlock( ldap_pvt_thread_rdwr_t *rwlock ) { struct ldap_int_thread_rdwr_s *rw; assert( rwlock != NULL ); rw = *rwlock; assert( rw != NULL ); assert( rw->ltrw_valid == LDAP_PVT_THREAD_RDWR_VALID ); if( rw->ltrw_valid != LDAP_PVT_THREAD_RDWR_VALID ) return LDAP_PVT_THREAD_EINVAL; ldap_pvt_thread_mutex_lock( &rw->ltrw_mutex ); rw->ltrw_w_active--; assert( rw->ltrw_w_active >= 0 ); assert( rw->ltrw_w_wait >= 0 ); assert( rw->ltrw_r_active >= 0 ); assert( rw->ltrw_r_wait >= 0 ); if (rw->ltrw_r_wait > 0) { ldap_pvt_thread_cond_broadcast( &rw->ltrw_read ); } else if (rw->ltrw_w_wait > 0) { ldap_pvt_thread_cond_signal( &rw->ltrw_write ); } #ifdef LDAP_RDWR_DEBUG assert( rw->ltrw_writer == ldap_pvt_thread_self() ); rw->ltrw_writer = 0; #endif ldap_pvt_thread_mutex_unlock( &rw->ltrw_mutex ); return 0; } #ifdef LDAP_RDWR_DEBUG /* just for testing, * return 0 if false, suitable for assert(ldap_pvt_thread_rdwr_Xchk(rdwr)) * * Currently they don't check if the calling thread is the one * that has the lock, just that there is a reader or writer. * * Basically sufficent for testing that places that should have * a lock are caught. */ int ldap_pvt_thread_rdwr_readers(ldap_pvt_thread_rdwr_t *rwlock) { struct ldap_int_thread_rdwr_s *rw; assert( rwlock != NULL ); rw = *rwlock; assert( rw != NULL ); assert( rw->ltrw_valid == LDAP_PVT_THREAD_RDWR_VALID ); assert( rw->ltrw_w_active >= 0 ); assert( rw->ltrw_w_wait >= 0 ); assert( rw->ltrw_r_active >= 0 ); assert( rw->ltrw_r_wait >= 0 ); return( rw->ltrw_r_active ); } int ldap_pvt_thread_rdwr_writers(ldap_pvt_thread_rdwr_t *rwlock) { struct ldap_int_thread_rdwr_s *rw; assert( rwlock != NULL ); rw = *rwlock; assert( rw != NULL ); assert( rw->ltrw_valid == LDAP_PVT_THREAD_RDWR_VALID ); assert( rw->ltrw_w_active >= 0 ); assert( rw->ltrw_w_wait >= 0 ); assert( rw->ltrw_r_active >= 0 ); assert( rw->ltrw_r_wait >= 0 ); return( rw->ltrw_w_active ); } int ldap_pvt_thread_rdwr_active(ldap_pvt_thread_rdwr_t *rwlock) { struct ldap_int_thread_rdwr_s *rw; assert( rwlock != NULL ); rw = *rwlock; assert( rw != NULL ); assert( rw->ltrw_valid == LDAP_PVT_THREAD_RDWR_VALID ); assert( rw->ltrw_w_active >= 0 ); assert( rw->ltrw_w_wait >= 0 ); assert( rw->ltrw_r_active >= 0 ); assert( rw->ltrw_r_wait >= 0 ); return(ldap_pvt_thread_rdwr_readers(rwlock) + ldap_pvt_thread_rdwr_writers(rwlock)); } #endif /* LDAP_RDWR_DEBUG */ #endif /* LDAP_THREAD_HAVE_RDWR */ openldap-2.4.42+dfsg/libraries/libldap_r/Makefile.in0000644000175000017500000000572212563404150021007 0ustar ryanryan# Makefile.in for LDAP -lldap # $OpenLDAP$ ## This work is part of OpenLDAP Software . ## ## Copyright 1998-2015 The OpenLDAP Foundation. ## All rights reserved. ## ## Redistribution and use in source and binary forms, with or without ## modification, are permitted only as authorized by the OpenLDAP ## Public License. ## ## A copy of this license is available in the file LICENSE in the ## top-level directory of the distribution or, alternatively, at ## . LIBRARY = libldap_r.la PROGRAMS = apitest ltest XXDIR = $(srcdir)/../libldap XXSRCS = apitest.c test.c \ bind.c open.c result.c error.c compare.c search.c \ controls.c messages.c references.c extended.c cyrus.c \ modify.c add.c modrdn.c delete.c abandon.c \ sasl.c gssapi.c sbind.c unbind.c cancel.c \ filter.c free.c sort.c passwd.c whoami.c \ getdn.c getentry.c getattr.c getvalues.c addentry.c \ request.c os-ip.c url.c pagectrl.c sortctrl.c vlvctrl.c \ init.c options.c print.c string.c util-int.c schema.c \ charray.c os-local.c dnssrv.c utf-8.c utf-8-conv.c \ tls2.c tls_o.c tls_g.c tls_m.c \ turn.c ppolicy.c dds.c txn.c ldap_sync.c stctrl.c \ assertion.c deref.c ldif.c fetch.c SRCS = threads.c rdwr.c rmutex.c tpool.c rq.c \ thr_posix.c thr_cthreads.c thr_thr.c thr_nt.c \ thr_pth.c thr_stub.c thr_debug.c OBJS = threads.lo rdwr.lo rmutex.lo tpool.lo rq.lo \ thr_posix.lo thr_cthreads.lo thr_thr.lo thr_nt.lo \ thr_pth.lo thr_stub.lo thr_debug.lo \ bind.lo open.lo result.lo error.lo compare.lo search.lo \ controls.lo messages.lo references.lo extended.lo cyrus.lo \ modify.lo add.lo modrdn.lo delete.lo abandon.lo \ sasl.lo gssapi.lo sbind.lo unbind.lo cancel.lo \ filter.lo free.lo sort.lo passwd.lo whoami.lo \ getdn.lo getentry.lo getattr.lo getvalues.lo addentry.lo \ request.lo os-ip.lo url.lo pagectrl.lo sortctrl.lo vlvctrl.lo \ init.lo options.lo print.lo string.lo util-int.lo schema.lo \ charray.lo os-local.lo dnssrv.lo utf-8.lo utf-8-conv.lo \ tls2.lo tls_o.lo tls_g.lo tls_m.lo \ turn.lo ppolicy.lo dds.lo txn.lo ldap_sync.lo stctrl.lo \ assertion.lo deref.lo ldif.lo fetch.lo LDAP_INCDIR= ../../include LDAP_LIBDIR= ../../libraries LIB_DEFS = -DLDAP_LIBRARY XDEFS = -DLDAP_R_COMPILE -I$(XXDIR) XLIBS = $(LIBRARY) $(LDAP_LIBLBER_LA) $(LDAP_LIBLUTIL_A) XXLIBS = $(SECURITY_LIBS) $(LUTIL_LIBS) XXXLIBS = $(LTHREAD_LIBS) NT_LINK_LIBS = $(LDAP_LIBLBER_LA) $(AC_LIBS) $(SECURITY_LIBS) UNIX_LINK_LIBS = $(LDAP_LIBLBER_LA) $(AC_LIBS) $(SECURITY_LIBS) $(LTHREAD_LIBS) .links : Makefile @for i in $(XXSRCS); do \ $(RM) $$i ; \ $(LN_S) $(XXDIR)/$$i . ; \ done touch .links $(XXSRCS) : .links clean-local: FORCE @$(RM) .links depend-common: .links apitest: $(XLIBS) apitest.o $(LTLINK) -o $@ apitest.o $(LIBS) ltest: $(XLIBS) test.o $(LTLINK) -o $@ test.o $(LIBS) install-local: $(CFFILES) FORCE -$(MKDIR) $(DESTDIR)$(libdir) $(LTINSTALL) $(INSTALLFLAGS) -m 644 $(LIBRARY) $(DESTDIR)$(libdir) $(LTFINISH) $(DESTDIR)$(libdir) openldap-2.4.42+dfsg/libraries/libldap_r/thr_thr.c0000644000175000017500000000657712563404150020571 0ustar ryanryan/* thr_thr.c - wrappers around solaris threads */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #include "portable.h" #if defined( HAVE_THR ) #include "ldap_pvt_thread.h" /* Get the thread interface */ #define LDAP_THREAD_IMPLEMENTATION #include "ldap_thr_debug.h" /* May rename the symbols defined below */ /******************* * * * Solaris Threads * * * *******************/ int ldap_int_thread_initialize( void ) { return 0; } int ldap_int_thread_destroy( void ) { return 0; } #ifdef LDAP_THREAD_HAVE_SETCONCURRENCY int ldap_pvt_thread_set_concurrency(int n) { return thr_setconcurrency( n ); } #endif #ifdef LDAP_THREAD_HAVE_GETCONCURRENCY int ldap_pvt_thread_get_concurrency(void) { return thr_getconcurrency(); } #endif int ldap_pvt_thread_create( ldap_pvt_thread_t * thread, int detach, void *(*start_routine)( void *), void *arg) { return( thr_create( NULL, LDAP_PVT_THREAD_STACK_SIZE, start_routine, arg, detach ? THR_DETACHED : 0, thread ) ); } void ldap_pvt_thread_exit( void *retval ) { thr_exit( NULL ); } int ldap_pvt_thread_join( ldap_pvt_thread_t thread, void **thread_return ) { thr_join( thread, NULL, thread_return ); return 0; } int ldap_pvt_thread_kill( ldap_pvt_thread_t thread, int signo ) { thr_kill( thread, signo ); return 0; } int ldap_pvt_thread_yield( void ) { thr_yield(); return 0; } int ldap_pvt_thread_cond_init( ldap_pvt_thread_cond_t *cond ) { return( cond_init( cond, USYNC_THREAD, NULL ) ); } int ldap_pvt_thread_cond_signal( ldap_pvt_thread_cond_t *cond ) { return( cond_signal( cond ) ); } int ldap_pvt_thread_cond_broadcast( ldap_pvt_thread_cond_t *cv ) { return( cond_broadcast( cv ) ); } int ldap_pvt_thread_cond_wait( ldap_pvt_thread_cond_t *cond, ldap_pvt_thread_mutex_t *mutex ) { return( cond_wait( cond, mutex ) ); } int ldap_pvt_thread_cond_destroy( ldap_pvt_thread_cond_t *cv ) { return( cond_destroy( cv ) ); } int ldap_pvt_thread_mutex_init( ldap_pvt_thread_mutex_t *mutex ) { return( mutex_init( mutex, USYNC_THREAD, NULL ) ); } int ldap_pvt_thread_mutex_destroy( ldap_pvt_thread_mutex_t *mutex ) { return( mutex_destroy( mutex ) ); } int ldap_pvt_thread_mutex_lock( ldap_pvt_thread_mutex_t *mutex ) { return( mutex_lock( mutex ) ); } int ldap_pvt_thread_mutex_unlock( ldap_pvt_thread_mutex_t *mutex ) { return( mutex_unlock( mutex ) ); } int ldap_pvt_thread_mutex_trylock( ldap_pvt_thread_mutex_t *mp ) { return( mutex_trylock( mp ) ); } ldap_pvt_thread_t ldap_pvt_thread_self( void ) { return thr_self(); } int ldap_pvt_thread_key_create( ldap_pvt_thread_key_t *key ) { return thr_keycreate( key, NULL ); } int ldap_pvt_thread_key_destroy( ldap_pvt_thread_key_t key ) { return( 0 ); } int ldap_pvt_thread_key_setdata( ldap_pvt_thread_key_t key, void *data ) { return thr_setspecific( key, data ); } int ldap_pvt_thread_key_getdata( ldap_pvt_thread_key_t key, void **data ) { return thr_getspecific( key, data ); } #endif /* HAVE_THR */ openldap-2.4.42+dfsg/libraries/libldap_r/ldap_thr_debug.h0000644000175000017500000002010012563404150022041 0ustar ryanryan/* ldap_thr_debug.h - preprocessor magic for LDAP_THREAD_DEBUG */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 2005-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #ifdef LDAP_THREAD_DEBUG /* * libldap_r .c files should include this file after ldap_pvt_thread.h, * with the appropriate LDAP_THREAD*_IMPLEMENTATION macro(s) defined. */ #ifndef _LDAP_PVT_THREAD_H #error "ldap_pvt_thread.h" must be included before "ldap_thr_debug.h" #endif /* * Support for thr_debug.c: * * thr_debug.c defines ldap_pvt_thread_* as wrappers around the real * ldap_pvt_thread_* implementation, which this file renames to * ldap_int_thread_*. * * Implementation: * * This file re#defines selected ldap_pvt_thread_* names to * ldap_int_thread_*, which will be used from wrappers in thr_debug.c. * Two ldap_int_*() calls are redirected to call ldap_debug_*(): These * are wrappers around the originals, whose definitions are not renamed. * This file then #includes ldap_pvt_thread.h to declare the renamed * functions/types. If #included from thr_debug.c it finally #undefines * the macros again. * * include/ldap_pvt_thread.h declares the typedefs ldap_pvt_thread*_t as * either wrapper types ldap_debug_thread*_t or their usual definitions * ldap_int_thread*_t, depending on the LDAP_THREAD_DEBUG_WRAP option. * When defining the underlying implementation, this file then redirects * the type names back to the original ldap_int_thread*_t types. * include/ldap__thread.h also do some thr_debug magic. * * So, * libldap_r/ thus define ldap_int_thread_*() instead * of ldap_pvt_thread_*(). * thr_debug.c defines the ldap_pvt_*() and ldap_debug_*() functions. * In thread.c, ldap_pvt_thread_() will call * ldap_debug_thread_*() instead of ldap_int_thread_*(). * In tpool.c, ldap_int_thread_pool_shutdown() has explicit thr_debug.c * support which treats ldap_pvt_thread_pool_destroy() the same way. */ #ifndef LDAP_THREAD_IMPLEMENTATION /* for first part of threads.c */ #define ldap_int_thread_initialize ldap_debug_thread_initialize #define ldap_int_thread_destroy ldap_debug_thread_destroy #else /* LDAP_THREAD_IMPLEMENTATION -- for thr_*.c and end of threads.c */ #undef ldap_int_thread_initialize #undef ldap_int_thread_destroy #ifdef LDAP_THREAD_DEBUG_WRAP /* see ldap_pvt_thread.h */ #define ldap_pvt_thread_mutex_t ldap_int_thread_mutex_t #define ldap_pvt_thread_cond_t ldap_int_thread_cond_t #endif #define ldap_pvt_thread_sleep ldap_int_thread_sleep #define ldap_pvt_thread_get_concurrency ldap_int_thread_get_concurrency #define ldap_pvt_thread_set_concurrency ldap_int_thread_set_concurrency #define ldap_pvt_thread_create ldap_int_thread_create #define ldap_pvt_thread_exit ldap_int_thread_exit #define ldap_pvt_thread_join ldap_int_thread_join #define ldap_pvt_thread_kill ldap_int_thread_kill #define ldap_pvt_thread_yield ldap_int_thread_yield #define ldap_pvt_thread_cond_init ldap_int_thread_cond_init #define ldap_pvt_thread_cond_destroy ldap_int_thread_cond_destroy #define ldap_pvt_thread_cond_signal ldap_int_thread_cond_signal #define ldap_pvt_thread_cond_broadcast ldap_int_thread_cond_broadcast #define ldap_pvt_thread_cond_wait ldap_int_thread_cond_wait #define ldap_pvt_thread_mutex_init ldap_int_thread_mutex_init #define ldap_pvt_thread_mutex_destroy ldap_int_thread_mutex_destroy #define ldap_pvt_thread_mutex_lock ldap_int_thread_mutex_lock #define ldap_pvt_thread_mutex_trylock ldap_int_thread_mutex_trylock #define ldap_pvt_thread_mutex_unlock ldap_int_thread_mutex_unlock #define ldap_pvt_thread_self ldap_int_thread_self #endif /* LDAP_THREAD_IMPLEMENTATION */ #ifdef LDAP_THREAD_RDWR_IMPLEMENTATION /* rdwr.c, thr_debug.c */ #ifdef LDAP_THREAD_DEBUG_WRAP /* see ldap_pvt_thread.h */ #define ldap_pvt_thread_rdwr_t ldap_int_thread_rdwr_t #endif #define ldap_pvt_thread_rdwr_init ldap_int_thread_rdwr_init #define ldap_pvt_thread_rdwr_destroy ldap_int_thread_rdwr_destroy #define ldap_pvt_thread_rdwr_rlock ldap_int_thread_rdwr_rlock #define ldap_pvt_thread_rdwr_rtrylock ldap_int_thread_rdwr_rtrylock #define ldap_pvt_thread_rdwr_runlock ldap_int_thread_rdwr_runlock #define ldap_pvt_thread_rdwr_wlock ldap_int_thread_rdwr_wlock #define ldap_pvt_thread_rdwr_wtrylock ldap_int_thread_rdwr_wtrylock #define ldap_pvt_thread_rdwr_wunlock ldap_int_thread_rdwr_wunlock #define ldap_pvt_thread_rdwr_readers ldap_int_thread_rdwr_readers #define ldap_pvt_thread_rdwr_writers ldap_int_thread_rdwr_writers #define ldap_pvt_thread_rdwr_active ldap_int_thread_rdwr_active #endif /* LDAP_THREAD_RDWR_IMPLEMENTATION */ #ifdef LDAP_THREAD_POOL_IMPLEMENTATION /* tpool.c, thr_stub.c, thr_debug.c */ #ifdef LDAP_THREAD_DEBUG_WRAP /* see ldap_pvt_thread.h */ #define ldap_pvt_thread_pool_t ldap_int_thread_pool_t #endif #define ldap_pvt_thread_pool_init ldap_int_thread_pool_init #define ldap_pvt_thread_pool_submit ldap_int_thread_pool_submit #define ldap_pvt_thread_pool_maxthreads ldap_int_thread_pool_maxthreads #define ldap_pvt_thread_pool_backload ldap_int_thread_pool_backload #define ldap_pvt_thread_pool_pause ldap_int_thread_pool_pause #define ldap_pvt_thread_pool_resume ldap_int_thread_pool_resume #define ldap_pvt_thread_pool_destroy ldap_int_thread_pool_destroy #define ldap_pvt_thread_pool_getkey ldap_int_thread_pool_getkey #define ldap_pvt_thread_pool_setkey ldap_int_thread_pool_setkey #define ldap_pvt_thread_pool_purgekey ldap_int_thread_pool_purgekey #define ldap_pvt_thread_pool_context ldap_int_thread_pool_context #define ldap_pvt_thread_pool_context_reset ldap_int_thread_pool_context_reset #endif /* LDAP_THREAD_POOL_IMPLEMENTATION */ #undef _LDAP_PVT_THREAD_H #include "ldap_pvt_thread.h" #ifdef LDAP_THREAD_POOL_IMPLEMENTATION /* tpool.c */ /* * tpool.c:ldap_int_thread_pool_shutdown() needs this. Could not * use it for ldap_pvt_thread.h above because of its use of LDAP_P(). */ #undef ldap_pvt_thread_pool_destroy #define ldap_pvt_thread_pool_destroy(p,r) ldap_int_thread_pool_destroy(p,r) #endif #ifdef LDAP_THREAD_DEBUG_IMPLEMENTATION /* thr_debug.c */ #undef ldap_pvt_thread_mutex_t #undef ldap_pvt_thread_cond_t #undef ldap_pvt_thread_sleep #undef ldap_pvt_thread_get_concurrency #undef ldap_pvt_thread_set_concurrency #undef ldap_pvt_thread_create #undef ldap_pvt_thread_exit #undef ldap_pvt_thread_join #undef ldap_pvt_thread_kill #undef ldap_pvt_thread_yield #undef ldap_pvt_thread_cond_init #undef ldap_pvt_thread_cond_destroy #undef ldap_pvt_thread_cond_signal #undef ldap_pvt_thread_cond_broadcast #undef ldap_pvt_thread_cond_wait #undef ldap_pvt_thread_mutex_init #undef ldap_pvt_thread_mutex_destroy #undef ldap_pvt_thread_mutex_lock #undef ldap_pvt_thread_mutex_trylock #undef ldap_pvt_thread_mutex_unlock #undef ldap_pvt_thread_self /* LDAP_THREAD_RDWR_IMPLEMENTATION: */ #undef ldap_pvt_thread_rdwr_t #undef ldap_pvt_thread_rdwr_init #undef ldap_pvt_thread_rdwr_destroy #undef ldap_pvt_thread_rdwr_rlock #undef ldap_pvt_thread_rdwr_rtrylock #undef ldap_pvt_thread_rdwr_runlock #undef ldap_pvt_thread_rdwr_wlock #undef ldap_pvt_thread_rdwr_wtrylock #undef ldap_pvt_thread_rdwr_wunlock #undef ldap_pvt_thread_rdwr_readers #undef ldap_pvt_thread_rdwr_writers #undef ldap_pvt_thread_rdwr_active /* LDAP_THREAD_POOL_IMPLEMENTATION: */ #undef ldap_pvt_thread_pool_t #undef ldap_pvt_thread_pool_init #undef ldap_pvt_thread_pool_submit #undef ldap_pvt_thread_pool_maxthreads #undef ldap_pvt_thread_pool_backload #undef ldap_pvt_thread_pool_pause #undef ldap_pvt_thread_pool_resume #undef ldap_pvt_thread_pool_destroy #undef ldap_pvt_thread_pool_getkey #undef ldap_pvt_thread_pool_setkey #undef ldap_pvt_thread_pool_purgekey #undef ldap_pvt_thread_pool_context #undef ldap_pvt_thread_pool_context_reset #endif /* LDAP_THREAD_DEBUG_IMPLEMENTATION */ #endif /* LDAP_THREAD_DEBUG */ openldap-2.4.42+dfsg/libraries/libldap_r/rq.c0000644000175000017500000001062012563404150017521 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 2003-2015 The OpenLDAP Foundation. * Portions Copyright 2003 IBM Corporation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* This work was initially developed by Jong Hyuk Choi for inclusion * in OpenLDAP Software. */ #include "portable.h" #include #include #include #include #include #include #include #include "ldap-int.h" #include "ldap_pvt_thread.h" #include "ldap_queue.h" #include "ldap_rq.h" struct re_s * ldap_pvt_runqueue_insert( struct runqueue_s* rq, time_t interval, ldap_pvt_thread_start_t *routine, void *arg, char *tname, char *tspec ) { struct re_s* entry; entry = (struct re_s *) LDAP_CALLOC( 1, sizeof( struct re_s )); if ( entry ) { entry->interval.tv_sec = interval; entry->interval.tv_usec = 0; entry->next_sched.tv_sec = time( NULL ); entry->next_sched.tv_usec = 0; entry->routine = routine; entry->arg = arg; entry->tname = tname; entry->tspec = tspec; LDAP_STAILQ_INSERT_HEAD( &rq->task_list, entry, tnext ); } return entry; } struct re_s * ldap_pvt_runqueue_find( struct runqueue_s *rq, ldap_pvt_thread_start_t *routine, void *arg ) { struct re_s* e; LDAP_STAILQ_FOREACH( e, &rq->task_list, tnext ) { if ( e->routine == routine && e->arg == arg ) return e; } return NULL; } void ldap_pvt_runqueue_remove( struct runqueue_s* rq, struct re_s* entry ) { struct re_s* e; LDAP_STAILQ_FOREACH( e, &rq->task_list, tnext ) { if ( e == entry) break; } assert( e == entry ); LDAP_STAILQ_REMOVE( &rq->task_list, entry, re_s, tnext ); LDAP_FREE( entry ); } struct re_s* ldap_pvt_runqueue_next_sched( struct runqueue_s* rq, struct timeval* next_run ) { struct re_s* entry; entry = LDAP_STAILQ_FIRST( &rq->task_list ); if ( entry == NULL || entry->next_sched.tv_sec == 0 ) { return NULL; } else { *next_run = entry->next_sched; return entry; } } void ldap_pvt_runqueue_runtask( struct runqueue_s* rq, struct re_s* entry ) { LDAP_STAILQ_INSERT_TAIL( &rq->run_list, entry, rnext ); } void ldap_pvt_runqueue_stoptask( struct runqueue_s* rq, struct re_s* entry ) { LDAP_STAILQ_REMOVE( &rq->run_list, entry, re_s, rnext ); } int ldap_pvt_runqueue_isrunning( struct runqueue_s* rq, struct re_s* entry ) { struct re_s* e; LDAP_STAILQ_FOREACH( e, &rq->run_list, rnext ) { if ( e == entry ) { return 1; } } return 0; } void ldap_pvt_runqueue_resched( struct runqueue_s* rq, struct re_s* entry, int defer ) { struct re_s* prev; struct re_s* e; LDAP_STAILQ_FOREACH( e, &rq->task_list, tnext ) { if ( e == entry ) break; } assert ( e == entry ); LDAP_STAILQ_REMOVE( &rq->task_list, entry, re_s, tnext ); if ( !defer ) { entry->next_sched.tv_sec = time( NULL ) + entry->interval.tv_sec; } else { entry->next_sched.tv_sec = 0; } if ( LDAP_STAILQ_EMPTY( &rq->task_list )) { LDAP_STAILQ_INSERT_HEAD( &rq->task_list, entry, tnext ); } else if ( entry->next_sched.tv_sec == 0 ) { LDAP_STAILQ_INSERT_TAIL( &rq->task_list, entry, tnext ); } else { prev = NULL; LDAP_STAILQ_FOREACH( e, &rq->task_list, tnext ) { if ( e->next_sched.tv_sec == 0 ) { if ( prev == NULL ) { LDAP_STAILQ_INSERT_HEAD( &rq->task_list, entry, tnext ); } else { LDAP_STAILQ_INSERT_AFTER( &rq->task_list, prev, entry, tnext ); } return; } else if ( e->next_sched.tv_sec > entry->next_sched.tv_sec ) { if ( prev == NULL ) { LDAP_STAILQ_INSERT_HEAD( &rq->task_list, entry, tnext ); } else { LDAP_STAILQ_INSERT_AFTER( &rq->task_list, prev, entry, tnext ); } return; } prev = e; } LDAP_STAILQ_INSERT_TAIL( &rq->task_list, entry, tnext ); } } int ldap_pvt_runqueue_persistent_backload( struct runqueue_s* rq ) { struct re_s* e; int count = 0; ldap_pvt_thread_mutex_lock( &rq->rq_mutex ); if ( !LDAP_STAILQ_EMPTY( &rq->task_list )) { LDAP_STAILQ_FOREACH( e, &rq->task_list, tnext ) { if ( e->next_sched.tv_sec == 0 ) count++; } } ldap_pvt_thread_mutex_unlock( &rq->rq_mutex ); return count; } openldap-2.4.42+dfsg/libraries/libldap_r/thr_stub.c0000644000175000017500000001242112563404150020732 0ustar ryanryan/* thr_stub.c - stubs for the threads */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #include "portable.h" #if defined( NO_THREADS ) #include "ldap_pvt_thread.h" /* Get the thread interface */ #define LDAP_THREAD_IMPLEMENTATION #define LDAP_THREAD_POOL_IMPLEMENTATION #include "ldap_thr_debug.h" /* May rename the symbols defined below */ /*********************************************************************** * * * no threads package defined for this system - fake ok returns from * * all threads routines (making it single-threaded). * * * ***********************************************************************/ int ldap_int_thread_initialize( void ) { return 0; } int ldap_int_thread_destroy( void ) { return 0; } static void* ldap_int_status = NULL; int ldap_pvt_thread_create( ldap_pvt_thread_t * thread, int detach, void *(*start_routine)(void *), void *arg) { if( ! detach ) ldap_int_status = NULL; start_routine( arg ); return 0; } void ldap_pvt_thread_exit( void *retval ) { if( retval != NULL ) { ldap_int_status = retval; } return; } int ldap_pvt_thread_join( ldap_pvt_thread_t thread, void **status ) { if(status != NULL) *status = ldap_int_status; return 0; } int ldap_pvt_thread_kill( ldap_pvt_thread_t thread, int signo ) { return 0; } int ldap_pvt_thread_yield( void ) { return 0; } int ldap_pvt_thread_cond_init( ldap_pvt_thread_cond_t *cond ) { return 0; } int ldap_pvt_thread_cond_destroy( ldap_pvt_thread_cond_t *cond ) { return 0; } int ldap_pvt_thread_cond_signal( ldap_pvt_thread_cond_t *cond ) { return 0; } int ldap_pvt_thread_cond_broadcast( ldap_pvt_thread_cond_t *cond ) { return 0; } int ldap_pvt_thread_cond_wait( ldap_pvt_thread_cond_t *cond, ldap_pvt_thread_mutex_t *mutex ) { return 0; } int ldap_pvt_thread_mutex_init( ldap_pvt_thread_mutex_t *mutex ) { return 0; } int ldap_pvt_thread_mutex_destroy( ldap_pvt_thread_mutex_t *mutex ) { return 0; } int ldap_pvt_thread_mutex_lock( ldap_pvt_thread_mutex_t *mutex ) { return 0; } int ldap_pvt_thread_mutex_trylock( ldap_pvt_thread_mutex_t *mutex ) { return 0; } int ldap_pvt_thread_mutex_unlock( ldap_pvt_thread_mutex_t *mutex ) { return 0; } /* * NO_THREADS requires a separate tpool implementation since * generic ldap_pvt_thread_pool_wrapper loops forever. */ int ldap_pvt_thread_pool_init ( ldap_pvt_thread_pool_t *pool_out, int max_concurrency, int max_pending ) { *pool_out = (ldap_pvt_thread_pool_t) 0; return(0); } int ldap_pvt_thread_pool_submit ( ldap_pvt_thread_pool_t *pool, ldap_pvt_thread_start_t *start_routine, void *arg ) { (start_routine)(NULL, arg); return(0); } int ldap_pvt_thread_pool_retract ( ldap_pvt_thread_pool_t *pool, ldap_pvt_thread_start_t *start_routine, void *arg ) { return(0); } int ldap_pvt_thread_pool_maxthreads ( ldap_pvt_thread_pool_t *tpool, int max_threads ) { return(0); } int ldap_pvt_thread_pool_query( ldap_pvt_thread_pool_t *tpool, ldap_pvt_thread_pool_param_t param, void *value ) { *(int *)value = -1; return(-1); } int ldap_pvt_thread_pool_backload ( ldap_pvt_thread_pool_t *pool ) { return(0); } int ldap_pvt_thread_pool_destroy ( ldap_pvt_thread_pool_t *pool, int run_pending ) { return(0); } void ldap_pvt_thread_pool_idle ( ldap_pvt_thread_pool_t *pool ) { return; } void ldap_pvt_thread_pool_unidle ( ldap_pvt_thread_pool_t *pool ) { return; } int ldap_pvt_thread_pool_getkey ( void *ctx, void *key, void **data, ldap_pvt_thread_pool_keyfree_t **kfree ) { return(0); } int ldap_pvt_thread_pool_setkey ( void *ctx, void *key, void *data, ldap_pvt_thread_pool_keyfree_t *kfree, void **olddatap, ldap_pvt_thread_pool_keyfree_t **oldkfreep ) { if ( olddatap ) *olddatap = NULL; if ( oldkfreep ) *oldkfreep = 0; return(0); } void ldap_pvt_thread_pool_purgekey( void *key ) { } int ldap_pvt_thread_pool_pause ( ldap_pvt_thread_pool_t *tpool ) { return(0); } int ldap_pvt_thread_pool_resume ( ldap_pvt_thread_pool_t *tpool ) { return(0); } int ldap_pvt_thread_pool_pausing( ldap_pvt_thread_pool_t *tpool ) { return(0); } ldap_pvt_thread_pool_pausecheck( ldap_pvt_thread_pool_t *tpool ) { return(0); } void *ldap_pvt_thread_pool_context( ) { return(NULL); } void ldap_pvt_thread_pool_context_reset( void *vctx ) { } ldap_pvt_thread_t ldap_pvt_thread_self( void ) { return(0); } int ldap_pvt_thread_key_create( ldap_pvt_thread_key_t *key ) { return(0); } int ldap_pvt_thread_key_destroy( ldap_pvt_thread_key_t key ) { return(0); } int ldap_pvt_thread_key_setdata( ldap_pvt_thread_key_t key, void *data ) { return(0); } int ldap_pvt_thread_key_getdata( ldap_pvt_thread_key_t key, void **data ) { return(0); } ldap_pvt_thread_t ldap_pvt_thread_pool_tid( void *vctx ) { return(0); } #endif /* NO_THREADS */ openldap-2.4.42+dfsg/libraries/libldap_r/thr_posix.c0000644000175000017500000002053612563404150021125 0ustar ryanryan/* thr_posix.c - wrapper around posix and posixish thread implementations. */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #include "portable.h" #if defined( HAVE_PTHREADS ) #include #ifdef REPLACE_BROKEN_YIELD #ifndef HAVE_NANOSLEEP #include #endif #include #endif #include "ldap_pvt_thread.h" /* Get the thread interface */ #define LDAP_THREAD_IMPLEMENTATION #define LDAP_THREAD_RDWR_IMPLEMENTATION #include "ldap_thr_debug.h" /* May rename the symbols defined below */ #include /* For pthread_kill() */ #if HAVE_PTHREADS < 6 # define LDAP_INT_THREAD_ATTR_DEFAULT pthread_attr_default # define LDAP_INT_THREAD_CONDATTR_DEFAULT pthread_condattr_default # define LDAP_INT_THREAD_MUTEXATTR_DEFAULT pthread_mutexattr_default #else # define LDAP_INT_THREAD_ATTR_DEFAULT NULL # define LDAP_INT_THREAD_CONDATTR_DEFAULT NULL # define LDAP_INT_THREAD_MUTEXATTR_DEFAULT NULL #endif #ifdef LDAP_THREAD_DEBUG # if defined LDAP_INT_THREAD_MUTEXATTR /* May be defined in CPPFLAGS */ # elif defined HAVE_PTHREAD_KILL_OTHER_THREADS_NP /* LinuxThreads hack */ # define LDAP_INT_THREAD_MUTEXATTR PTHREAD_MUTEX_ERRORCHECK_NP # else # define LDAP_INT_THREAD_MUTEXATTR PTHREAD_MUTEX_ERRORCHECK # endif static pthread_mutexattr_t mutex_attr; # undef LDAP_INT_THREAD_MUTEXATTR_DEFAULT # define LDAP_INT_THREAD_MUTEXATTR_DEFAULT &mutex_attr #endif #if HAVE_PTHREADS < 7 #define ERRVAL(val) ((val) < 0 ? errno : 0) #else #define ERRVAL(val) (val) #endif int ldap_int_thread_initialize( void ) { #ifdef LDAP_INT_THREAD_MUTEXATTR pthread_mutexattr_init( &mutex_attr ); pthread_mutexattr_settype( &mutex_attr, LDAP_INT_THREAD_MUTEXATTR ); #endif return 0; } int ldap_int_thread_destroy( void ) { #ifdef HAVE_PTHREAD_KILL_OTHER_THREADS_NP /* LinuxThreads: kill clones */ pthread_kill_other_threads_np(); #endif #ifdef LDAP_INT_THREAD_MUTEXATTR pthread_mutexattr_destroy( &mutex_attr ); #endif return 0; } #ifdef LDAP_THREAD_HAVE_SETCONCURRENCY int ldap_pvt_thread_set_concurrency(int n) { #ifdef HAVE_PTHREAD_SETCONCURRENCY return pthread_setconcurrency( n ); #elif defined(HAVE_THR_SETCONCURRENCY) return thr_setconcurrency( n ); #else return 0; #endif } #endif #ifdef LDAP_THREAD_HAVE_GETCONCURRENCY int ldap_pvt_thread_get_concurrency(void) { #ifdef HAVE_PTHREAD_GETCONCURRENCY return pthread_getconcurrency(); #elif defined(HAVE_THR_GETCONCURRENCY) return thr_getconcurrency(); #else return 0; #endif } #endif /* detachstate appeared in Draft 6, but without manifest constants. * in Draft 7 they were called PTHREAD_CREATE_UNDETACHED and ...DETACHED. * in Draft 8 on, ...UNDETACHED became ...JOINABLE. */ #ifndef PTHREAD_CREATE_JOINABLE #ifdef PTHREAD_CREATE_UNDETACHED #define PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED #else #define PTHREAD_CREATE_JOINABLE 0 #endif #endif #ifndef PTHREAD_CREATE_DETACHED #define PTHREAD_CREATE_DETACHED 1 #endif int ldap_pvt_thread_create( ldap_pvt_thread_t * thread, int detach, void *(*start_routine)( void * ), void *arg) { int rtn; pthread_attr_t attr; /* Always create the thread attrs, so we can set stacksize if we need to */ #if HAVE_PTHREADS > 5 pthread_attr_init(&attr); #else pthread_attr_create(&attr); #endif #ifdef LDAP_PVT_THREAD_SET_STACK_SIZE /* this should be tunable */ pthread_attr_setstacksize( &attr, LDAP_PVT_THREAD_STACK_SIZE ); #endif #if HAVE_PTHREADS > 5 detach = detach ? PTHREAD_CREATE_DETACHED : PTHREAD_CREATE_JOINABLE; #if HAVE_PTHREADS == 6 pthread_attr_setdetachstate(&attr, &detach); #else pthread_attr_setdetachstate(&attr, detach); #endif #endif #if HAVE_PTHREADS < 5 rtn = pthread_create( thread, attr, start_routine, arg ); #else rtn = pthread_create( thread, &attr, start_routine, arg ); #endif #if HAVE_PTHREADS > 5 pthread_attr_destroy(&attr); #else pthread_attr_delete(&attr); if( detach ) { pthread_detach( thread ); } #endif #if HAVE_PTHREADS < 7 if ( rtn < 0 ) rtn = errno; #endif return rtn; } void ldap_pvt_thread_exit( void *retval ) { pthread_exit( retval ); } int ldap_pvt_thread_join( ldap_pvt_thread_t thread, void **thread_return ) { #if HAVE_PTHREADS < 7 void *dummy; if (thread_return==NULL) thread_return=&dummy; #endif return ERRVAL( pthread_join( thread, thread_return ) ); } int ldap_pvt_thread_kill( ldap_pvt_thread_t thread, int signo ) { #if defined(HAVE_PTHREAD_KILL) && HAVE_PTHREADS > 4 /* MacOS 10.1 is detected as v10 but has no pthread_kill() */ return ERRVAL( pthread_kill( thread, signo ) ); #else /* pthread package with DCE */ if (kill( getpid(), signo )<0) return errno; return 0; #endif } int ldap_pvt_thread_yield( void ) { #ifdef REPLACE_BROKEN_YIELD #ifdef HAVE_NANOSLEEP struct timespec t = { 0, 0 }; nanosleep(&t, NULL); #else struct timeval tv = {0,0}; select( 0, NULL, NULL, NULL, &tv ); #endif return 0; #elif defined(HAVE_THR_YIELD) thr_yield(); return 0; #elif HAVE_PTHREADS == 10 return sched_yield(); #elif defined(_POSIX_THREAD_IS_GNU_PTH) sched_yield(); return 0; #elif HAVE_PTHREADS == 6 pthread_yield(NULL); return 0; #else pthread_yield(); return 0; #endif } int ldap_pvt_thread_cond_init( ldap_pvt_thread_cond_t *cond ) { return ERRVAL( pthread_cond_init( cond, LDAP_INT_THREAD_CONDATTR_DEFAULT ) ); } int ldap_pvt_thread_cond_destroy( ldap_pvt_thread_cond_t *cond ) { return ERRVAL( pthread_cond_destroy( cond ) ); } int ldap_pvt_thread_cond_signal( ldap_pvt_thread_cond_t *cond ) { return ERRVAL( pthread_cond_signal( cond ) ); } int ldap_pvt_thread_cond_broadcast( ldap_pvt_thread_cond_t *cond ) { return ERRVAL( pthread_cond_broadcast( cond ) ); } int ldap_pvt_thread_cond_wait( ldap_pvt_thread_cond_t *cond, ldap_pvt_thread_mutex_t *mutex ) { return ERRVAL( pthread_cond_wait( cond, mutex ) ); } int ldap_pvt_thread_mutex_init( ldap_pvt_thread_mutex_t *mutex ) { return ERRVAL( pthread_mutex_init( mutex, LDAP_INT_THREAD_MUTEXATTR_DEFAULT ) ); } int ldap_pvt_thread_mutex_destroy( ldap_pvt_thread_mutex_t *mutex ) { return ERRVAL( pthread_mutex_destroy( mutex ) ); } int ldap_pvt_thread_mutex_lock( ldap_pvt_thread_mutex_t *mutex ) { return ERRVAL( pthread_mutex_lock( mutex ) ); } int ldap_pvt_thread_mutex_trylock( ldap_pvt_thread_mutex_t *mutex ) { return ERRVAL( pthread_mutex_trylock( mutex ) ); } int ldap_pvt_thread_mutex_unlock( ldap_pvt_thread_mutex_t *mutex ) { return ERRVAL( pthread_mutex_unlock( mutex ) ); } ldap_pvt_thread_t ldap_pvt_thread_self( void ) { return pthread_self(); } int ldap_pvt_thread_key_create( ldap_pvt_thread_key_t *key ) { return pthread_key_create( key, NULL ); } int ldap_pvt_thread_key_destroy( ldap_pvt_thread_key_t key ) { return pthread_key_delete( key ); } int ldap_pvt_thread_key_setdata( ldap_pvt_thread_key_t key, void *data ) { return pthread_setspecific( key, data ); } int ldap_pvt_thread_key_getdata( ldap_pvt_thread_key_t key, void **data ) { *data = pthread_getspecific( key ); return 0; } #ifdef LDAP_THREAD_HAVE_RDWR #ifdef HAVE_PTHREAD_RWLOCK_DESTROY int ldap_pvt_thread_rdwr_init( ldap_pvt_thread_rdwr_t *rw ) { return ERRVAL( pthread_rwlock_init( rw, NULL ) ); } int ldap_pvt_thread_rdwr_destroy( ldap_pvt_thread_rdwr_t *rw ) { return ERRVAL( pthread_rwlock_destroy( rw ) ); } int ldap_pvt_thread_rdwr_rlock( ldap_pvt_thread_rdwr_t *rw ) { return ERRVAL( pthread_rwlock_rdlock( rw ) ); } int ldap_pvt_thread_rdwr_rtrylock( ldap_pvt_thread_rdwr_t *rw ) { return ERRVAL( pthread_rwlock_tryrdlock( rw ) ); } int ldap_pvt_thread_rdwr_runlock( ldap_pvt_thread_rdwr_t *rw ) { return ERRVAL( pthread_rwlock_unlock( rw ) ); } int ldap_pvt_thread_rdwr_wlock( ldap_pvt_thread_rdwr_t *rw ) { return ERRVAL( pthread_rwlock_wrlock( rw ) ); } int ldap_pvt_thread_rdwr_wtrylock( ldap_pvt_thread_rdwr_t *rw ) { return ERRVAL( pthread_rwlock_trywrlock( rw ) ); } int ldap_pvt_thread_rdwr_wunlock( ldap_pvt_thread_rdwr_t *rw ) { return ERRVAL( pthread_rwlock_unlock( rw ) ); } #endif /* HAVE_PTHREAD_RWLOCK_DESTROY */ #endif /* LDAP_THREAD_HAVE_RDWR */ #endif /* HAVE_PTHREADS */ openldap-2.4.42+dfsg/libraries/libldap_r/thr_nt.c0000644000175000017500000001044412563404150020401 0ustar ryanryan/* thr_nt.c - wrapper around NT threads */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #include "portable.h" #if defined( HAVE_NT_THREADS ) #define _WIN32_WINNT 0x0400 #include #include #include "ldap_pvt_thread.h" /* Get the thread interface */ #define LDAP_THREAD_IMPLEMENTATION #include "ldap_thr_debug.h" /* May rename the symbols defined below */ typedef struct ldap_int_thread_s { long tid; HANDLE thd; } ldap_int_thread_s; #ifndef NT_MAX_THREADS #define NT_MAX_THREADS 1024 #endif static ldap_int_thread_s tids[NT_MAX_THREADS]; static int ntids; /* mingw compiler very sensitive about getting prototypes right */ typedef unsigned __stdcall thrfunc_t(void *); int ldap_int_thread_initialize( void ) { return 0; } int ldap_int_thread_destroy( void ) { return 0; } int ldap_pvt_thread_create( ldap_pvt_thread_t * thread, int detach, void *(*start_routine)( void *), void *arg) { unsigned tid; HANDLE thd; int rc = -1; thd = (HANDLE) _beginthreadex(NULL, LDAP_PVT_THREAD_STACK_SIZE, (thrfunc_t *) start_routine, arg, 0, &tid); if ( thd ) { *thread = (ldap_pvt_thread_t) tid; tids[ntids].tid = tid; tids[ntids].thd = thd; ntids++; rc = 0; } return rc; } void ldap_pvt_thread_exit( void *retval ) { _endthread( ); } int ldap_pvt_thread_join( ldap_pvt_thread_t thread, void **thread_return ) { DWORD status; int i; for (i=0; i ntids ) return -1; status = WaitForSingleObject( tids[i].thd, INFINITE ); for (; i. * * Copyright 2006-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* This work was initially developed by Howard Chu for inclusion * in OpenLDAP Software. */ /* * This is an implementation of recursive mutexes. */ #include "portable.h" #include #include #include #include #include "ldap-int.h" #include "ldap_pvt_thread.h" /* Get the thread interface */ struct ldap_int_thread_rmutex_s { ldap_pvt_thread_mutex_t ltrm_mutex; ldap_pvt_thread_cond_t ltrm_cond; ldap_pvt_thread_t ltrm_owner; int ltrm_valid; #define LDAP_PVT_THREAD_RMUTEX_VALID 0x0cdb int ltrm_depth; int ltrm_waits; }; static const ldap_pvt_thread_t tid_zero; int ldap_pvt_thread_rmutex_init( ldap_pvt_thread_rmutex_t *rmutex ) { struct ldap_int_thread_rmutex_s *rm; assert( rmutex != NULL ); rm = (struct ldap_int_thread_rmutex_s *) LDAP_CALLOC( 1, sizeof( struct ldap_int_thread_rmutex_s ) ); if ( !rm ) return LDAP_NO_MEMORY; /* we should check return results */ ldap_pvt_thread_mutex_init( &rm->ltrm_mutex ); ldap_pvt_thread_cond_init( &rm->ltrm_cond ); rm->ltrm_valid = LDAP_PVT_THREAD_RMUTEX_VALID; *rmutex = rm; return 0; } int ldap_pvt_thread_rmutex_destroy( ldap_pvt_thread_rmutex_t *rmutex ) { struct ldap_int_thread_rmutex_s *rm; assert( rmutex != NULL ); rm = *rmutex; assert( rm != NULL ); assert( rm->ltrm_valid == LDAP_PVT_THREAD_RMUTEX_VALID ); if( rm->ltrm_valid != LDAP_PVT_THREAD_RMUTEX_VALID ) return LDAP_PVT_THREAD_EINVAL; ldap_pvt_thread_mutex_lock( &rm->ltrm_mutex ); assert( rm->ltrm_depth >= 0 ); assert( rm->ltrm_waits >= 0 ); /* in use? */ if( rm->ltrm_depth > 0 || rm->ltrm_waits > 0 ) { ldap_pvt_thread_mutex_unlock( &rm->ltrm_mutex ); return LDAP_PVT_THREAD_EBUSY; } rm->ltrm_valid = 0; ldap_pvt_thread_mutex_unlock( &rm->ltrm_mutex ); ldap_pvt_thread_mutex_destroy( &rm->ltrm_mutex ); ldap_pvt_thread_cond_destroy( &rm->ltrm_cond ); LDAP_FREE(rm); *rmutex = NULL; return 0; } int ldap_pvt_thread_rmutex_lock( ldap_pvt_thread_rmutex_t *rmutex, ldap_pvt_thread_t owner ) { struct ldap_int_thread_rmutex_s *rm; assert( rmutex != NULL ); rm = *rmutex; assert( rm != NULL ); assert( rm->ltrm_valid == LDAP_PVT_THREAD_RMUTEX_VALID ); if( rm->ltrm_valid != LDAP_PVT_THREAD_RMUTEX_VALID ) return LDAP_PVT_THREAD_EINVAL; ldap_pvt_thread_mutex_lock( &rm->ltrm_mutex ); assert( rm->ltrm_depth >= 0 ); assert( rm->ltrm_waits >= 0 ); if( rm->ltrm_depth > 0 ) { /* already locked */ if ( !ldap_pvt_thread_equal( rm->ltrm_owner, owner )) { rm->ltrm_waits++; do { ldap_pvt_thread_cond_wait( &rm->ltrm_cond, &rm->ltrm_mutex ); } while( rm->ltrm_depth > 0 ); rm->ltrm_waits--; assert( rm->ltrm_waits >= 0 ); rm->ltrm_owner = owner; } } else { rm->ltrm_owner = owner; } rm->ltrm_depth++; ldap_pvt_thread_mutex_unlock( &rm->ltrm_mutex ); return 0; } int ldap_pvt_thread_rmutex_trylock( ldap_pvt_thread_rmutex_t *rmutex, ldap_pvt_thread_t owner ) { struct ldap_int_thread_rmutex_s *rm; assert( rmutex != NULL ); rm = *rmutex; assert( rm != NULL ); assert( rm->ltrm_valid == LDAP_PVT_THREAD_RMUTEX_VALID ); if( rm->ltrm_valid != LDAP_PVT_THREAD_RMUTEX_VALID ) return LDAP_PVT_THREAD_EINVAL; ldap_pvt_thread_mutex_lock( &rm->ltrm_mutex ); assert( rm->ltrm_depth >= 0 ); assert( rm->ltrm_waits >= 0 ); if( rm->ltrm_depth > 0 ) { if ( !ldap_pvt_thread_equal( owner, rm->ltrm_owner )) { ldap_pvt_thread_mutex_unlock( &rm->ltrm_mutex ); return LDAP_PVT_THREAD_EBUSY; } } else { rm->ltrm_owner = owner; } rm->ltrm_depth++; ldap_pvt_thread_mutex_unlock( &rm->ltrm_mutex ); return 0; } int ldap_pvt_thread_rmutex_unlock( ldap_pvt_thread_rmutex_t *rmutex, ldap_pvt_thread_t owner ) { struct ldap_int_thread_rmutex_s *rm; assert( rmutex != NULL ); rm = *rmutex; assert( rm != NULL ); assert( rm->ltrm_valid == LDAP_PVT_THREAD_RMUTEX_VALID ); if( rm->ltrm_valid != LDAP_PVT_THREAD_RMUTEX_VALID ) return LDAP_PVT_THREAD_EINVAL; ldap_pvt_thread_mutex_lock( &rm->ltrm_mutex ); if( !ldap_pvt_thread_equal( owner, rm->ltrm_owner )) { ldap_pvt_thread_mutex_unlock( &rm->ltrm_mutex ); return LDAP_PVT_THREAD_EINVAL; } rm->ltrm_depth--; if ( !rm->ltrm_depth ) rm->ltrm_owner = tid_zero; assert( rm->ltrm_depth >= 0 ); assert( rm->ltrm_waits >= 0 ); if ( !rm->ltrm_depth && rm->ltrm_waits ) { ldap_pvt_thread_cond_signal( &rm->ltrm_cond ); } ldap_pvt_thread_mutex_unlock( &rm->ltrm_mutex ); return 0; } openldap-2.4.42+dfsg/libraries/libldap_r/thr_debug.c0000644000175000017500000010574312563404150021055 0ustar ryanryan/* thr_debug.c - wrapper around the chosen thread wrapper, for debugging. */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 2005-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* * This package provides several types of thread operation debugging: * * - Check the results of operations on threads, mutexes, condition * variables and read/write locks. Also check some thread pool * operations, but not those for which failure can happen in normal * slapd operation. * * - Wrap those types except threads and pools in structs with state * information, and check that on all operations: * * + Check that the resources are initialized and are only used at * their original address (i.e. not realloced or copied). * * + Check the owner (thread ID) on mutex operations. * * + Optionally allocate a reference to a byte of dummy memory. * This lets malloc debuggers see some incorrect use as memory * leaks, access to freed memory, etc. * * - Print an error message and by default abort() upon errors. * * - Print a count of leaked thread resources after cleanup. * * Compile-time (./configure) setup: Macros defined in CPPFLAGS. * * LDAP_THREAD_DEBUG or LDAP_THREAD_DEBUG=2 * Enables debugging, but value & 2 turns off type wrapping. * * LDAP_UINTPTR_T=integer type to hold pointers, preferably unsigned. * Used by dummy memory option "scramble". Default = unsigned long. * * LDAP_DEBUG_THREAD_NONE = initializer for a "no thread" thread ID. * * In addition, you may need to set up an implementation-specific way * to enable whatever error checking your thread library provides. * Currently only implemented for Posix threads (pthreads), where * you may need to define LDAP_INT_THREAD_MUTEXATTR. The default * is PTHREAD_MUTEX_ERRORCHECK, or PTHREAD_MUTEX_ERRORCHECK_NP for * Linux threads. See pthread_mutexattr_settype(3). * * Run-time configuration: * * Memory debugging tools: * Tools that report uninitialized memory accesses should disable * such warnings about the function debug_already_initialized(). * Alternatively, include "noreinit" (below) in $LDAP_THREAD_DEBUG. * * Environment variable $LDAP_THREAD_DEBUG: * The variable may contain a comma- or space-separated option list. * Options: * off - Disable this package. (It still slows things down). * tracethreads - Report create/join/exit/kill of threads. * noabort - Do not abort() on errors. * noerror - Do not report errors. Implies noabort. * nocount - Do not report counts of unreleased resources. * nosync - Disable tests that use synchronizaion and thus * clearly affect thread scheduling: * Implies nocount, and cancels threadID if that is set. * Note that if you turn on tracethreads or malloc * debugging, these also use library calls which may * affect thread scheduling (fprintf and malloc). * The following options do not apply if type wrapping is disabled: * nomem - Do not check memory operations. * Implies noreinit,noalloc. * noreinit - Do not catch reinitialization of existing resources. * (That test accesses uninitialized memory). * threadID - Trace thread IDs. Currently mostly useless. * Malloc debugging -- allocate dummy memory for initialized * resources, so malloc debuggers will report them as memory leaks: * noalloc - Default. Do not allocate dummy memory. * alloc - Store a pointer to dummy memory. However, leak * detectors might not catch unreleased resources in * global variables. * scramble - Store bitwise complement of dummy memory pointer. * That never escapes memory leak detectors - * but detection while the program is running will * report active resources as leaks. Do not * use this if a garbage collector is in use:-) * adjptr - Point to end of dummy memory. * Purify reports these as "potential leaks" (PLK). * I have not checked other malloc debuggers. */ #include "portable.h" #if defined( LDAP_THREAD_DEBUG ) #include #include #include #include #include "ldap_pvt_thread.h" /* Get the thread interface */ #define LDAP_THREAD_IMPLEMENTATION #define LDAP_THREAD_DEBUG_IMPLEMENTATION #define LDAP_THREAD_RDWR_IMPLEMENTATION #define LDAP_THREAD_POOL_IMPLEMENTATION #include "ldap_thr_debug.h" /* Get the underlying implementation */ #ifndef LDAP_THREAD_DEBUG_WRAP #undef LDAP_THREAD_DEBUG_THREAD_ID #elif !defined LDAP_THREAD_DEBUG_THREAD_ID #define LDAP_THREAD_DEBUG_THREAD_ID 1 #endif /* Use native malloc - the OpenLDAP wrappers may defeat malloc debuggers */ #undef malloc #undef calloc #undef realloc #undef free /* Options from environment variable $LDAP_THREAD_DEBUG */ enum { Count_no = 0, Count_yes, Count_reported, Count_reported_more }; static int count = Count_yes; #ifdef LDAP_THREAD_DEBUG_WRAP enum { Wrap_noalloc, Wrap_alloc, Wrap_scramble, Wrap_adjptr }; static int wraptype = Wrap_noalloc, wrap_offset, unwrap_offset; static int nomem, noreinit; #endif #if LDAP_THREAD_DEBUG_THREAD_ID +0 static int threadID; #else enum { threadID = 0 }; #endif static int nodebug, noabort, noerror, nosync, tracethreads; static int wrap_threads; static int options_done; /* ldap_pvt_thread_initialize() called, ldap_pvt_thread_destroy() not called */ static int threading_enabled; /* Resource counts */ enum { Idx_unexited_thread, Idx_unjoined_thread, Idx_locked_mutex, Idx_mutex, Idx_cond, Idx_rdwr, Idx_tpool, Idx_max }; static int resource_counts[Idx_max]; static const char *const resource_names[] = { "unexited threads", "unjoined threads", "locked mutexes", "mutexes", "conds", "rdwrs", "thread pools" }; static ldap_int_thread_mutex_t resource_mutexes[Idx_max]; /* Hide pointers from malloc debuggers. */ #define SCRAMBLE(ptr) (~(LDAP_UINTPTR_T) (ptr)) #define UNSCRAMBLE_usagep(num) ((ldap_debug_usage_info_t *) ~(num)) #define UNSCRAMBLE_dummyp(num) ((unsigned char *) ~(num)) #define WARN(var, msg) (warn (__FILE__, __LINE__, (msg), #var, (var))) #define WARN_IF(rc, msg) {if (rc) warn (__FILE__, __LINE__, (msg), #rc, (rc));} #define ERROR(var, msg) { \ if (!noerror) { \ errmsg(__FILE__, __LINE__, (msg), #var, (var)); \ if( !noabort ) abort(); \ } \ } #define ERROR_IF(rc, msg) { \ if (!noerror) { \ int rc_ = (rc); \ if (rc_) { \ errmsg(__FILE__, __LINE__, (msg), #rc, rc_); \ if( !noabort ) abort(); \ } \ } \ } #ifdef LDAP_THREAD_DEBUG_WRAP #define MEMERROR_IF(rc, msg, mem_act) { \ if (!noerror) { \ int rc_ = (rc); \ if (rc_) { \ errmsg(__FILE__, __LINE__, (msg), #rc, rc_); \ if( wraptype != Wrap_noalloc ) { mem_act; } \ if( !noabort ) abort(); \ } \ } \ } #endif /* LDAP_THREAD_DEBUG_WRAP */ #if 0 static void warn( const char *file, int line, const char *msg, const char *var, int val ) { fprintf( stderr, (strpbrk( var, "!=" ) ? "%s:%d: %s warning: %s\n" : "%s:%d: %s warning: %s is %d\n"), file, line, msg, var, val ); } #endif static void errmsg( const char *file, int line, const char *msg, const char *var, int val ) { fprintf( stderr, (strpbrk( var, "!=" ) ? "%s:%d: %s error: %s\n" : "%s:%d: %s error: %s is %d\n"), file, line, msg, var, val ); } static void count_resource_leaks( void ) { int i, j; char errbuf[200]; if( count == Count_yes ) { count = Count_reported; #if 0 /* Could break if there are still threads after atexit */ for( i = j = 0; i < Idx_max; i++ ) j |= ldap_int_thread_mutex_destroy( &resource_mutexes[i] ); WARN_IF( j, "ldap_debug_thread_destroy:mutexes" ); #endif for( i = j = 0; i < Idx_max; i++ ) if( resource_counts[i] ) j += sprintf( errbuf + j, ", %d %s", resource_counts[i], resource_names[i] ); if( j ) fprintf( stderr, "== thr_debug: Leaked%s. ==\n", errbuf + 1 ); } } static void get_options( void ) { static const struct option_info_s { const char *name; int *var, val; } option_info[] = { { "off", &nodebug, 1 }, { "noabort", &noabort, 1 }, { "noerror", &noerror, 1 }, { "nocount", &count, Count_no }, { "nosync", &nosync, 1 }, #if LDAP_THREAD_DEBUG_THREAD_ID +0 { "threadID", &threadID, 1 }, #endif #ifdef LDAP_THREAD_DEBUG_WRAP { "nomem", &nomem, 1 }, { "noreinit", &noreinit, 1 }, { "noalloc", &wraptype, Wrap_noalloc }, { "alloc", &wraptype, Wrap_alloc }, { "adjptr", &wraptype, Wrap_adjptr }, { "scramble", &wraptype, Wrap_scramble }, #endif { "tracethreads", &tracethreads, 1 }, { NULL, NULL, 0 } }; const char *s = getenv( "LDAP_THREAD_DEBUG" ); if( s != NULL ) { while( *(s += strspn( s, ", \t\r\n" )) != '\0' ) { size_t optlen = strcspn( s, ", \t\r\n" ); const struct option_info_s *oi = option_info; while( oi->name && (strncasecmp( oi->name, s, optlen ) || oi->name[optlen]) ) oi++; if( oi->name ) *oi->var = oi->val; else fprintf( stderr, "== thr_debug: Unknown $%s option '%.*s' ==\n", "LDAP_THREAD_DEBUG", (int) optlen, s ); s += optlen; } } if( nodebug ) { tracethreads = 0; nosync = noerror = 1; } if( nosync ) count = Count_no; if( noerror ) noabort = 1; #if LDAP_THREAD_DEBUG_THREAD_ID +0 if( nosync ) threadID = 0; #endif #ifdef LDAP_THREAD_DEBUG_WRAP if( noerror ) nomem = 1; if( !nomem ) { static const ldap_debug_usage_info_t usage; if( sizeof(LDAP_UINTPTR_T) < sizeof(unsigned char *) || sizeof(LDAP_UINTPTR_T) < sizeof(ldap_debug_usage_info_t *) || UNSCRAMBLE_usagep( SCRAMBLE( &usage ) ) != &usage || UNSCRAMBLE_dummyp( SCRAMBLE( (unsigned char *) 0 ) ) ) { fputs( "== thr_debug: Memory checks unsupported, " "adding nomem to $LDAP_THREAD_DEBUG ==\n", stderr ); nomem = 1; } } if( nomem ) { noreinit = 1; wraptype = Wrap_noalloc; } unwrap_offset = -(wrap_offset = (wraptype == Wrap_adjptr)); #endif wrap_threads = (tracethreads || threadID || count); options_done = 1; } #ifndef LDAP_THREAD_DEBUG_WRAP #define WRAPPED(ptr) (ptr) #define GET_OWNER(ptr) 0 #define SET_OWNER(ptr, thread) ((void) 0) #define RESET_OWNER(ptr) ((void) 0) #define ASSERT_OWNER(ptr, msg) ((void) 0) #define ASSERT_NO_OWNER(ptr, msg) ((void) 0) #define init_usage(ptr, msg) ((void) 0) #define check_usage(ptr, msg) ((void) 0) #define destroy_usage(ptr) ((void) 0) #else /* LDAP_THREAD_DEBUG_WRAP */ /* Specialize this if the initializer is not appropriate. */ /* The ASSERT_NO_OWNER() definition may also need an override. */ #ifndef LDAP_DEBUG_THREAD_NONE #define LDAP_DEBUG_THREAD_NONE { -1 } /* "no thread" ldap_int_thread_t value */ #endif static const ldap_int_thread_t ldap_debug_thread_none = LDAP_DEBUG_THREAD_NONE; #define THREAD_MUTEX_OWNER(mutex) \ ldap_int_thread_equal( (mutex)->owner, ldap_int_thread_self() ) void ldap_debug_thread_assert_mutex_owner( const char *file, int line, const char *msg, ldap_pvt_thread_mutex_t *mutex ) { if( !(noerror || THREAD_MUTEX_OWNER( mutex )) ) { errmsg( file, line, msg, "ASSERT_MUTEX_OWNER", 0 ); if( !noabort ) abort(); } } #define WRAPPED(ptr) (&(ptr)->wrapped) #define GET_OWNER(ptr) ((ptr)->owner) #define SET_OWNER(ptr, thread) ((ptr)->owner = (thread)) #define RESET_OWNER(ptr) ((ptr)->owner = ldap_debug_thread_none) #define ASSERT_OWNER(ptr, msg) ERROR_IF( !THREAD_MUTEX_OWNER( ptr ), msg ) #ifndef ASSERT_NO_OWNER #define ASSERT_NO_OWNER(ptr, msg) ERROR_IF( \ !ldap_int_thread_equal( (ptr)->owner, ldap_debug_thread_none ), msg ) #endif /* Try to provoke memory access error (for malloc debuggers) */ #define PEEK(mem) {if (-*(volatile const unsigned char *)(mem)) debug_noop();} static void debug_noop( void ); static int debug_already_initialized( const ldap_debug_usage_info_t *usage ); /* Name used for clearer error message */ #define IS_COPY_OR_MOVED(usage) ((usage)->self != SCRAMBLE( usage )) #define DUMMY_ADDR(usage) \ (wraptype == Wrap_scramble \ ? UNSCRAMBLE_dummyp( (usage)->mem.num ) \ : (usage)->mem.ptr + unwrap_offset) /* Mark resource as initialized */ static void init_usage( ldap_debug_usage_info_t *usage, const char *msg ) { if( !options_done ) get_options(); if( !nomem ) { if( !noreinit ) { MEMERROR_IF( debug_already_initialized( usage ), msg, { /* Provoke malloc debuggers */ unsigned char *dummy = DUMMY_ADDR( usage ); PEEK( dummy ); free( dummy ); free( dummy ); } ); } if( wraptype != Wrap_noalloc ) { unsigned char *dummy = malloc( 1 ); assert( dummy != NULL ); if( wraptype == Wrap_scramble ) { usage->mem.num = SCRAMBLE( dummy ); /* Verify that ptr<->integer casts work on this host */ assert( UNSCRAMBLE_dummyp( usage->mem.num ) == dummy ); } else { usage->mem.ptr = dummy + wrap_offset; } } } else { /* Unused, but set for readability in debugger */ usage->mem.ptr = NULL; } usage->self = SCRAMBLE( usage ); /* If nomem, only for debugger */ usage->magic = ldap_debug_magic; usage->state = ldap_debug_state_inited; } /* Check that resource is initialized and not copied/realloced */ static void check_usage( const ldap_debug_usage_info_t *usage, const char *msg ) { enum { Is_destroyed = 1 }; /* Name used for clearer error message */ if( usage->magic != ldap_debug_magic ) { ERROR( usage->magic, msg ); return; } switch( usage->state ) { case ldap_debug_state_destroyed: MEMERROR_IF( Is_destroyed, msg, { PEEK( DUMMY_ADDR( usage ) ); } ); break; default: ERROR( usage->state, msg ); break; case ldap_debug_state_inited: if( !nomem ) { MEMERROR_IF( IS_COPY_OR_MOVED( usage ), msg, { PEEK( DUMMY_ADDR( usage ) ); PEEK( UNSCRAMBLE_usagep( usage->self ) ); } ); } break; } } /* Mark resource as destroyed. */ /* Does not check for errors, call check_usage()/init_usage() first. */ static void destroy_usage( ldap_debug_usage_info_t *usage ) { if( usage->state == ldap_debug_state_inited ) { if( wraptype != Wrap_noalloc ) { free( DUMMY_ADDR( usage ) ); /* Do not reset the DUMMY_ADDR, leave it for malloc debuggers * in case the resource is used after it is freed. */ } usage->state = ldap_debug_state_destroyed; } } /* Define these after they are used, so they are hopefully not inlined */ static void debug_noop( void ) { } /* * Valid programs access uninitialized memory here unless "noreinit". * * Returns true if the resource is initialized and not copied/realloced. */ LDAP_GCCATTR((noinline)) static int debug_already_initialized( const ldap_debug_usage_info_t *usage ) { /* * 'ret' keeps the Valgrind warning "Conditional jump or move * depends on uninitialised value(s)" _inside_ this function. */ volatile int ret = 0; if( usage->state == ldap_debug_state_inited ) if( !IS_COPY_OR_MOVED( usage ) ) if( usage->magic == ldap_debug_magic ) ret = 1; return ret; } #endif /* LDAP_THREAD_DEBUG_WRAP */ #if !(LDAP_THREAD_DEBUG_THREAD_ID +0) typedef void ldap_debug_thread_t; #define init_thread_info() {} #define with_thread_info_lock(statements) { statements; } #define thread_info_detached(t) 0 #define add_thread_info(msg, thr, det) ((void) 0) #define remove_thread_info(tinfo, msg) ((void) 0) #define get_thread_info(thread, msg) NULL #else /* LDAP_THREAD_DEBUG_THREAD_ID */ /* * Thread ID tracking. Currently acieves little. * Should be either expanded or deleted. */ /* * Array of threads. Used instead of making ldap_pvt_thread_t a wrapper * around ldap_int_thread_t, which would slow down ldap_pvt_thread_self(). */ typedef struct { ldap_pvt_thread_t wrapped; ldap_debug_usage_info_t usage; int detached; int idx; } ldap_debug_thread_t; static ldap_debug_thread_t **thread_info; static unsigned int thread_info_size, thread_info_used; static ldap_int_thread_mutex_t thread_info_mutex; #define init_thread_info() { \ if( threadID ) { \ int mutex_init_rc = ldap_int_thread_mutex_init( &thread_info_mutex ); \ assert( mutex_init_rc == 0 ); \ } \ } #define with_thread_info_lock(statements) { \ int rc_wtl_ = ldap_int_thread_mutex_lock( &thread_info_mutex ); \ assert( rc_wtl_ == 0 ); \ { statements; } \ rc_wtl_ = ldap_int_thread_mutex_unlock( &thread_info_mutex ); \ assert( rc_wtl_ == 0 ); \ } #define thread_info_detached(t) ((t)->detached) static void add_thread_info( const char *msg, const ldap_pvt_thread_t *thread, int detached ) { ldap_debug_thread_t *t; if( thread_info_used >= thread_info_size ) { unsigned int more = thread_info_size + 8; unsigned int new_size = thread_info_size + more; t = calloc( more, sizeof(ldap_debug_thread_t) ); assert( t != NULL ); thread_info = realloc( thread_info, new_size * sizeof(*thread_info) ); assert( thread_info != NULL ); do { t->idx = thread_info_size; thread_info[thread_info_size++] = t++; } while( thread_info_size < new_size ); } t = thread_info[thread_info_used]; init_usage( &t->usage, msg ); t->wrapped = *thread; t->detached = detached; thread_info_used++; } static void remove_thread_info( ldap_debug_thread_t *t, const char *msg ) { ldap_debug_thread_t *last; int idx; check_usage( &t->usage, msg ); destroy_usage( &t->usage ); idx = t->idx; assert( thread_info[idx] == t ); last = thread_info[--thread_info_used]; assert( last->idx == thread_info_used ); (thread_info[idx] = last)->idx = idx; (thread_info[thread_info_used] = t )->idx = thread_info_used; } static ldap_debug_thread_t * get_thread_info( ldap_pvt_thread_t thread, const char *msg ) { unsigned int i; ldap_debug_thread_t *t; for( i = 0; i < thread_info_used; i++ ) { if( ldap_pvt_thread_equal( thread, thread_info[i]->wrapped ) ) break; } ERROR_IF( i == thread_info_used, msg ); t = thread_info[i]; check_usage( &t->usage, msg ); return t; } #endif /* LDAP_THREAD_DEBUG_THREAD_ID */ static char * thread_name( char *buf, int bufsize, ldap_pvt_thread_t thread ) { int i; --bufsize; if( bufsize > 2*sizeof(thread) ) bufsize = 2*sizeof(thread); for( i = 0; i < bufsize; i += 2 ) snprintf( buf+i, 3, "%02x", ((unsigned char *)&thread)[i/2] ); return buf; } /* Add (+/-1) to resource count unless "nocount". */ static void adjust_count( int which, int adjust ) { int rc; switch( count ) { case Count_no: break; case Count_yes: rc = ldap_int_thread_mutex_lock( &resource_mutexes[which] ); assert( rc == 0 ); resource_counts[which] += adjust; rc = ldap_int_thread_mutex_unlock( &resource_mutexes[which] ); assert( rc == 0 ); break; case Count_reported: fputs( "== thr_debug: More thread activity after exit ==\n", stderr ); count = Count_reported_more; /* FALL THROUGH */ case Count_reported_more: /* Not used, but result might be inspected with debugger */ /* (Hopefully threading is disabled by now...) */ resource_counts[which] += adjust; break; } } /* Wrappers for LDAP_THREAD_IMPLEMENTATION: */ /* Used instead of ldap_int_thread_initialize by ldap_pvt_thread_initialize */ int ldap_debug_thread_initialize( void ) { int i, rc, rc2; if( !options_done ) get_options(); ERROR_IF( threading_enabled, "ldap_debug_thread_initialize" ); threading_enabled = 1; rc = ldap_int_thread_initialize(); if( rc ) { ERROR( rc, "ldap_debug_thread_initialize:threads" ); threading_enabled = 0; } else { init_thread_info(); if( count != Count_no ) { for( i = rc2 = 0; i < Idx_max; i++ ) rc2 |= ldap_int_thread_mutex_init( &resource_mutexes[i] ); assert( rc2 == 0 ); /* FIXME: Only for static libldap_r as in init.c? If so, why? */ atexit( count_resource_leaks ); } } return rc; } /* Used instead of ldap_int_thread_destroy by ldap_pvt_thread_destroy */ int ldap_debug_thread_destroy( void ) { int rc; ERROR_IF( !threading_enabled, "ldap_debug_thread_destroy" ); /* sleep(1) -- need to wait for thread pool to finish? */ rc = ldap_int_thread_destroy(); if( rc ) { ERROR( rc, "ldap_debug_thread_destroy:threads" ); } else { threading_enabled = 0; } return rc; } int ldap_pvt_thread_set_concurrency( int n ) { int rc; ERROR_IF( !threading_enabled, "ldap_pvt_thread_set_concurrency" ); rc = ldap_int_thread_set_concurrency( n ); ERROR_IF( rc, "ldap_pvt_thread_set_concurrency" ); return rc; } int ldap_pvt_thread_get_concurrency( void ) { int rc; ERROR_IF( !threading_enabled, "ldap_pvt_thread_get_concurrency" ); rc = ldap_int_thread_get_concurrency(); ERROR_IF( rc, "ldap_pvt_thread_get_concurrency" ); return rc; } unsigned int ldap_pvt_thread_sleep( unsigned int interval ) { int rc; ERROR_IF( !threading_enabled, "ldap_pvt_thread_sleep" ); rc = ldap_int_thread_sleep( interval ); ERROR_IF( rc, "ldap_pvt_thread_sleep" ); return 0; } static void thread_exiting( const char *how, const char *msg ) { ldap_pvt_thread_t thread; #if 0 /* Detached threads may exit after ldap_debug_thread_destroy(). */ ERROR_IF( !threading_enabled, msg ); #endif thread = ldap_pvt_thread_self(); if( tracethreads ) { char buf[40]; fprintf( stderr, "== thr_debug: %s thread %s ==\n", how, thread_name( buf, sizeof(buf), thread ) ); } if( threadID ) { with_thread_info_lock({ ldap_debug_thread_t *t = get_thread_info( thread, msg ); if( thread_info_detached( t ) ) remove_thread_info( t, msg ); }); } adjust_count( Idx_unexited_thread, -1 ); } void ldap_pvt_thread_exit( void *retval ) { thread_exiting( "Exiting", "ldap_pvt_thread_exit" ); ldap_int_thread_exit( retval ); } typedef struct { void *(*start_routine)( void * ); void *arg; } ldap_debug_thread_call_t; static void * ldap_debug_thread_wrapper( void *arg ) { void *ret; ldap_debug_thread_call_t call = *(ldap_debug_thread_call_t *)arg; free( arg ); ret = call.start_routine( call.arg ); thread_exiting( "Returning from", "ldap_debug_thread_wrapper" ); return ret; } int ldap_pvt_thread_create( ldap_pvt_thread_t *thread, int detach, void *(*start_routine)( void * ), void *arg ) { int rc; if( !options_done ) get_options(); ERROR_IF( !threading_enabled, "ldap_pvt_thread_create" ); if( wrap_threads ) { ldap_debug_thread_call_t *call = malloc( sizeof( ldap_debug_thread_call_t ) ); assert( call != NULL ); call->start_routine = start_routine; call->arg = arg; start_routine = ldap_debug_thread_wrapper; arg = call; } if( threadID ) { with_thread_info_lock({ rc = ldap_int_thread_create( thread, detach, start_routine, arg ); if( rc == 0 ) add_thread_info( "ldap_pvt_thread_create", thread, detach ); }); } else { rc = ldap_int_thread_create( thread, detach, start_routine, arg ); } if( rc ) { ERROR( rc, "ldap_pvt_thread_create" ); if( wrap_threads ) free( arg ); } else { if( tracethreads ) { char buf[40], buf2[40]; fprintf( stderr, "== thr_debug: Created thread %s%s from thread %s ==\n", thread_name( buf, sizeof(buf), *thread ), detach ? " (detached)" : "", thread_name( buf2, sizeof(buf2), ldap_pvt_thread_self() ) ); } adjust_count( Idx_unexited_thread, +1 ); if( !detach ) adjust_count( Idx_unjoined_thread, +1 ); } return rc; } int ldap_pvt_thread_join( ldap_pvt_thread_t thread, void **thread_return ) { int rc; ldap_debug_thread_t *t = NULL; ERROR_IF( !threading_enabled, "ldap_pvt_thread_join" ); if( tracethreads ) { char buf[40], buf2[40]; fprintf( stderr, "== thr_debug: Joining thread %s in thread %s ==\n", thread_name( buf, sizeof(buf), thread ), thread_name( buf2, sizeof(buf2), ldap_pvt_thread_self() ) ); } if( threadID ) with_thread_info_lock( { t = get_thread_info( thread, "ldap_pvt_thread_join" ); ERROR_IF( thread_info_detached( t ), "ldap_pvt_thread_join" ); } ); rc = ldap_int_thread_join( thread, thread_return ); if( rc ) { ERROR( rc, "ldap_pvt_thread_join" ); } else { if( threadID ) with_thread_info_lock( remove_thread_info( t, "ldap_pvt_thread_join" ) ); adjust_count( Idx_unjoined_thread, -1 ); } return rc; } int ldap_pvt_thread_kill( ldap_pvt_thread_t thread, int signo ) { int rc; ERROR_IF( !threading_enabled, "ldap_pvt_thread_kill" ); if( tracethreads ) { char buf[40], buf2[40]; fprintf( stderr, "== thr_debug: Killing thread %s (sig %i) from thread %s ==\n", thread_name( buf, sizeof(buf), thread ), signo, thread_name( buf2, sizeof(buf2), ldap_pvt_thread_self() ) ); } rc = ldap_int_thread_kill( thread, signo ); ERROR_IF( rc, "ldap_pvt_thread_kill" ); return rc; } int ldap_pvt_thread_yield( void ) { int rc; ERROR_IF( !threading_enabled, "ldap_pvt_thread_yield" ); rc = ldap_int_thread_yield(); ERROR_IF( rc, "ldap_pvt_thread_yield" ); return rc; } ldap_pvt_thread_t ldap_pvt_thread_self( void ) { #if 0 /* Function is used by ch_free() via slap_sl_contxt() in slapd */ ERROR_IF( !threading_enabled, "ldap_pvt_thread_self" ); #endif return ldap_int_thread_self(); } int ldap_pvt_thread_cond_init( ldap_pvt_thread_cond_t *cond ) { int rc; init_usage( &cond->usage, "ldap_pvt_thread_cond_init" ); rc = ldap_int_thread_cond_init( WRAPPED( cond ) ); if( rc ) { ERROR( rc, "ldap_pvt_thread_cond_init" ); destroy_usage( &cond->usage ); } else { adjust_count( Idx_cond, +1 ); } return rc; } int ldap_pvt_thread_cond_destroy( ldap_pvt_thread_cond_t *cond ) { int rc; check_usage( &cond->usage, "ldap_pvt_thread_cond_destroy" ); rc = ldap_int_thread_cond_destroy( WRAPPED( cond ) ); if( rc ) { ERROR( rc, "ldap_pvt_thread_cond_destroy" ); } else { destroy_usage( &cond->usage ); adjust_count( Idx_cond, -1 ); } return rc; } int ldap_pvt_thread_cond_signal( ldap_pvt_thread_cond_t *cond ) { int rc; check_usage( &cond->usage, "ldap_pvt_thread_cond_signal" ); rc = ldap_int_thread_cond_signal( WRAPPED( cond ) ); ERROR_IF( rc, "ldap_pvt_thread_cond_signal" ); return rc; } int ldap_pvt_thread_cond_broadcast( ldap_pvt_thread_cond_t *cond ) { int rc; check_usage( &cond->usage, "ldap_pvt_thread_cond_broadcast" ); rc = ldap_int_thread_cond_broadcast( WRAPPED( cond ) ); ERROR_IF( rc, "ldap_pvt_thread_cond_broadcast" ); return rc; } int ldap_pvt_thread_cond_wait( ldap_pvt_thread_cond_t *cond, ldap_pvt_thread_mutex_t *mutex ) { int rc; ldap_int_thread_t owner; check_usage( &cond->usage, "ldap_pvt_thread_cond_wait:cond" ); check_usage( &mutex->usage, "ldap_pvt_thread_cond_wait:mutex" ); adjust_count( Idx_locked_mutex, -1 ); owner = GET_OWNER( mutex ); ASSERT_OWNER( mutex, "ldap_pvt_thread_cond_wait" ); RESET_OWNER( mutex ); rc = ldap_int_thread_cond_wait( WRAPPED( cond ), WRAPPED( mutex ) ); ASSERT_NO_OWNER( mutex, "ldap_pvt_thread_cond_wait" ); SET_OWNER( mutex, rc ? owner : ldap_int_thread_self() ); adjust_count( Idx_locked_mutex, +1 ); ERROR_IF( rc, "ldap_pvt_thread_cond_wait" ); return rc; } int ldap_pvt_thread_mutex_init( ldap_pvt_thread_mutex_t *mutex ) { int rc; init_usage( &mutex->usage, "ldap_pvt_thread_mutex_init" ); rc = ldap_int_thread_mutex_init( WRAPPED( mutex ) ); if( rc ) { ERROR( rc, "ldap_pvt_thread_mutex_init" ); destroy_usage( &mutex->usage ); } else { RESET_OWNER( mutex ); adjust_count( Idx_mutex, +1 ); } return rc; } int ldap_pvt_thread_mutex_destroy( ldap_pvt_thread_mutex_t *mutex ) { int rc; check_usage( &mutex->usage, "ldap_pvt_thread_mutex_destroy" ); ASSERT_NO_OWNER( mutex, "ldap_pvt_thread_mutex_destroy" ); rc = ldap_int_thread_mutex_destroy( WRAPPED( mutex ) ); if( rc ) { ERROR( rc, "ldap_pvt_thread_mutex_destroy" ); } else { destroy_usage( &mutex->usage ); RESET_OWNER( mutex ); adjust_count( Idx_mutex, -1 ); } return rc; } int ldap_pvt_thread_mutex_lock( ldap_pvt_thread_mutex_t *mutex ) { int rc; check_usage( &mutex->usage, "ldap_pvt_thread_mutex_lock" ); rc = ldap_int_thread_mutex_lock( WRAPPED( mutex ) ); if( rc ) { ERROR_IF( rc, "ldap_pvt_thread_mutex_lock" ); } else { ASSERT_NO_OWNER( mutex, "ldap_pvt_thread_mutex_lock" ); SET_OWNER( mutex, ldap_int_thread_self() ); adjust_count( Idx_locked_mutex, +1 ); } return rc; } int ldap_pvt_thread_mutex_trylock( ldap_pvt_thread_mutex_t *mutex ) { int rc; check_usage( &mutex->usage, "ldap_pvt_thread_mutex_trylock" ); rc = ldap_int_thread_mutex_trylock( WRAPPED( mutex ) ); if( rc == 0 ) { ASSERT_NO_OWNER( mutex, "ldap_pvt_thread_mutex_trylock" ); SET_OWNER( mutex, ldap_int_thread_self() ); adjust_count( Idx_locked_mutex, +1 ); } return rc; } int ldap_pvt_thread_mutex_unlock( ldap_pvt_thread_mutex_t *mutex ) { int rc; check_usage( &mutex->usage, "ldap_pvt_thread_mutex_unlock" ); ASSERT_OWNER( mutex, "ldap_pvt_thread_mutex_unlock" ); RESET_OWNER( mutex ); /* Breaks if this thread did not own the mutex */ rc = ldap_int_thread_mutex_unlock( WRAPPED( mutex ) ); if( rc ) { ERROR_IF( rc, "ldap_pvt_thread_mutex_unlock" ); } else { adjust_count( Idx_locked_mutex, -1 ); } return rc; } /* Wrappers for LDAP_THREAD_RDWR_IMPLEMENTATION: */ int ldap_pvt_thread_rdwr_init( ldap_pvt_thread_rdwr_t *rwlock ) { int rc; init_usage( &rwlock->usage, "ldap_pvt_thread_rdwr_init" ); rc = ldap_int_thread_rdwr_init( WRAPPED( rwlock ) ); if( rc ) { ERROR( rc, "ldap_pvt_thread_rdwr_init" ); destroy_usage( &rwlock->usage ); } else { adjust_count( Idx_rdwr, +1 ); } return rc; } int ldap_pvt_thread_rdwr_destroy( ldap_pvt_thread_rdwr_t *rwlock ) { int rc; check_usage( &rwlock->usage, "ldap_pvt_thread_rdwr_destroy" ); rc = ldap_int_thread_rdwr_destroy( WRAPPED( rwlock ) ); if( rc ) { ERROR( rc, "ldap_pvt_thread_rdwr_destroy" ); } else { destroy_usage( &rwlock->usage ); adjust_count( Idx_rdwr, -1 ); } return rc; } int ldap_pvt_thread_rdwr_rlock( ldap_pvt_thread_rdwr_t *rwlock ) { int rc; check_usage( &rwlock->usage, "ldap_pvt_thread_rdwr_rlock" ); rc = ldap_int_thread_rdwr_rlock( WRAPPED( rwlock ) ); ERROR_IF( rc, "ldap_pvt_thread_rdwr_rlock" ); return rc; } int ldap_pvt_thread_rdwr_rtrylock( ldap_pvt_thread_rdwr_t *rwlock ) { check_usage( &rwlock->usage, "ldap_pvt_thread_rdwr_rtrylock" ); return ldap_int_thread_rdwr_rtrylock( WRAPPED( rwlock ) ); } int ldap_pvt_thread_rdwr_runlock( ldap_pvt_thread_rdwr_t *rwlock ) { int rc; check_usage( &rwlock->usage, "ldap_pvt_thread_rdwr_runlock" ); rc = ldap_int_thread_rdwr_runlock( WRAPPED( rwlock ) ); ERROR_IF( rc, "ldap_pvt_thread_rdwr_runlock" ); return rc; } int ldap_pvt_thread_rdwr_wlock( ldap_pvt_thread_rdwr_t *rwlock ) { int rc; check_usage( &rwlock->usage, "ldap_pvt_thread_rdwr_wlock" ); rc = ldap_int_thread_rdwr_wlock( WRAPPED( rwlock ) ); ERROR_IF( rc, "ldap_pvt_thread_rdwr_wlock" ); return rc; } int ldap_pvt_thread_rdwr_wtrylock( ldap_pvt_thread_rdwr_t *rwlock ) { check_usage( &rwlock->usage, "ldap_pvt_thread_rdwr_wtrylock" ); return ldap_int_thread_rdwr_wtrylock( WRAPPED( rwlock ) ); } int ldap_pvt_thread_rdwr_wunlock( ldap_pvt_thread_rdwr_t *rwlock ) { int rc; check_usage( &rwlock->usage, "ldap_pvt_thread_rdwr_wunlock" ); rc = ldap_int_thread_rdwr_wunlock( WRAPPED( rwlock ) ); ERROR_IF( rc, "ldap_pvt_thread_rdwr_wunlock" ); return rc; } #if defined(LDAP_RDWR_DEBUG) && !defined(LDAP_THREAD_HAVE_RDWR) int ldap_pvt_thread_rdwr_readers( ldap_pvt_thread_rdwr_t *rwlock ) { check_usage( &rwlock->usage, "ldap_pvt_thread_rdwr_readers" ); return ldap_int_thread_rdwr_readers( WRAPPED( rwlock ) ); } int ldap_pvt_thread_rdwr_writers( ldap_pvt_thread_rdwr_t *rwlock ) { check_usage( &rwlock->usage, "ldap_pvt_thread_rdwr_writers" ); return ldap_int_thread_rdwr_writers( WRAPPED( rwlock ) ); } int ldap_pvt_thread_rdwr_active( ldap_pvt_thread_rdwr_t *rwlock ) { check_usage( &rwlock->usage, "ldap_pvt_thread_rdwr_active" ); return ldap_int_thread_rdwr_active( WRAPPED( rwlock ) ); } #endif /* LDAP_RDWR_DEBUG && !LDAP_THREAD_HAVE_RDWR */ /* Some wrappers for LDAP_THREAD_POOL_IMPLEMENTATION: */ #ifdef LDAP_THREAD_POOL_IMPLEMENTATION int ldap_pvt_thread_pool_init( ldap_pvt_thread_pool_t *tpool, int max_threads, int max_pending ) { int rc; if( !options_done ) get_options(); ERROR_IF( !threading_enabled, "ldap_pvt_thread_pool_init" ); rc = ldap_int_thread_pool_init( tpool, max_threads, max_pending ); if( rc ) { ERROR( rc, "ldap_pvt_thread_pool_init" ); } else { adjust_count( Idx_tpool, +1 ); } return rc; } int ldap_pvt_thread_pool_submit( ldap_pvt_thread_pool_t *tpool, ldap_pvt_thread_start_t *start_routine, void *arg ) { int rc, has_pool; ERROR_IF( !threading_enabled, "ldap_pvt_thread_pool_submit" ); has_pool = (tpool && *tpool); rc = ldap_int_thread_pool_submit( tpool, start_routine, arg ); if( has_pool ) ERROR_IF( rc, "ldap_pvt_thread_pool_submit" ); return rc; } int ldap_pvt_thread_pool_maxthreads( ldap_pvt_thread_pool_t *tpool, int max_threads ) { ERROR_IF( !threading_enabled, "ldap_pvt_thread_pool_maxthreads" ); return ldap_int_thread_pool_maxthreads( tpool, max_threads ); } int ldap_pvt_thread_pool_backload( ldap_pvt_thread_pool_t *tpool ) { ERROR_IF( !threading_enabled, "ldap_pvt_thread_pool_backload" ); return ldap_int_thread_pool_backload( tpool ); } int ldap_pvt_thread_pool_destroy( ldap_pvt_thread_pool_t *tpool, int run_pending ) { int rc, has_pool; ERROR_IF( !threading_enabled, "ldap_pvt_thread_pool_destroy" ); has_pool = (tpool && *tpool); rc = ldap_int_thread_pool_destroy( tpool, run_pending ); if( has_pool ) { if( rc ) { ERROR( rc, "ldap_pvt_thread_pool_destroy" ); } else { adjust_count( Idx_tpool, -1 ); } } return rc; } int ldap_pvt_thread_pool_pause( ldap_pvt_thread_pool_t *tpool ) { ERROR_IF( !threading_enabled, "ldap_pvt_thread_pool_pause" ); return ldap_int_thread_pool_pause( tpool ); } int ldap_pvt_thread_pool_resume( ldap_pvt_thread_pool_t *tpool ) { ERROR_IF( !threading_enabled, "ldap_pvt_thread_pool_resume" ); return ldap_int_thread_pool_resume( tpool ); } int ldap_pvt_thread_pool_getkey( void *xctx, void *key, void **data, ldap_pvt_thread_pool_keyfree_t **kfree ) { #if 0 /* Function is used by ch_free() via slap_sl_contxt() in slapd */ ERROR_IF( !threading_enabled, "ldap_pvt_thread_pool_getkey" ); #endif return ldap_int_thread_pool_getkey( xctx, key, data, kfree ); } int ldap_pvt_thread_pool_setkey( void *xctx, void *key, void *data, ldap_pvt_thread_pool_keyfree_t *kfree, void **olddatap, ldap_pvt_thread_pool_keyfree_t **oldkfreep ) { int rc; ERROR_IF( !threading_enabled, "ldap_pvt_thread_pool_setkey" ); rc = ldap_int_thread_pool_setkey( xctx, key, data, kfree, olddatap, oldkfreep ); ERROR_IF( rc, "ldap_pvt_thread_pool_setkey" ); return rc; } void ldap_pvt_thread_pool_purgekey( void *key ) { ERROR_IF( !threading_enabled, "ldap_pvt_thread_pool_purgekey" ); ldap_int_thread_pool_purgekey( key ); } void * ldap_pvt_thread_pool_context( void ) { #if 0 /* Function is used by ch_free() via slap_sl_contxt() in slapd */ ERROR_IF( !threading_enabled, "ldap_pvt_thread_pool_context" ); #endif return ldap_int_thread_pool_context(); } void ldap_pvt_thread_pool_context_reset( void *vctx ) { ERROR_IF( !threading_enabled, "ldap_pvt_thread_pool_context_reset" ); ldap_int_thread_pool_context_reset( vctx ); } #endif /* LDAP_THREAD_POOL_IMPLEMENTATION */ #endif /* LDAP_THREAD_DEBUG */ openldap-2.4.42+dfsg/libraries/libldap_r/thr_pth.c0000644000175000017500000001144112563404150020551 0ustar ryanryan/* thr_pth.c - wrappers around GNU Pth */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #include "portable.h" #if defined( HAVE_GNU_PTH ) #include "ldap_pvt_thread.h" /* Get the thread interface */ #define LDAP_THREAD_IMPLEMENTATION #define LDAP_THREAD_RDWR_IMPLEMENTATION #include "ldap_thr_debug.h" /* May rename the symbols defined below */ #include /******************* * * * GNU Pth Threads * * * *******************/ static pth_attr_t detach_attr; static pth_attr_t joined_attr; int ldap_int_thread_initialize( void ) { if( !pth_init() ) { return -1; } detach_attr = pth_attr_new(); joined_attr = pth_attr_new(); #ifdef LDAP_PVT_THREAD_SET_STACK_SIZE pth_attr_set( joined_attr, PTH_ATTR_STACK_SIZE, LDAP_PVT_THREAD_STACK_SIZE ); pth_attr_set( detach_attr, PTH_ATTR_STACK_SIZE, LDAP_PVT_THREAD_STACK_SIZE ); #endif return pth_attr_set( detach_attr, PTH_ATTR_JOINABLE, FALSE ); } int ldap_int_thread_destroy( void ) { pth_attr_destroy(detach_attr); pth_kill(); return 0; } int ldap_pvt_thread_create( ldap_pvt_thread_t * thread, int detach, void *(*start_routine)( void *), void *arg) { *thread = pth_spawn( detach ? detach_attr : joined_attr, start_routine, arg ); return *thread == NULL ? errno : 0; } void ldap_pvt_thread_exit( void *retval ) { pth_exit( retval ); } int ldap_pvt_thread_join( ldap_pvt_thread_t thread, void **thread_return ) { return pth_join( thread, thread_return ) ? 0 : errno; } int ldap_pvt_thread_kill( ldap_pvt_thread_t thread, int signo ) { return pth_raise( thread, signo ) ? 0 : errno; } int ldap_pvt_thread_yield( void ) { return pth_yield(NULL) ? 0 : errno; } int ldap_pvt_thread_cond_init( ldap_pvt_thread_cond_t *cond ) { return( pth_cond_init( cond ) ? 0 : errno ); } int ldap_pvt_thread_cond_signal( ldap_pvt_thread_cond_t *cond ) { return( pth_cond_notify( cond, 0 ) ? 0 : errno ); } int ldap_pvt_thread_cond_broadcast( ldap_pvt_thread_cond_t *cond ) { return( pth_cond_notify( cond, 1 ) ? 0 : errno ); } int ldap_pvt_thread_cond_wait( ldap_pvt_thread_cond_t *cond, ldap_pvt_thread_mutex_t *mutex ) { return( pth_cond_await( cond, mutex, NULL ) ? 0 : errno ); } int ldap_pvt_thread_cond_destroy( ldap_pvt_thread_cond_t *cv ) { return 0; } int ldap_pvt_thread_mutex_init( ldap_pvt_thread_mutex_t *mutex ) { return( pth_mutex_init( mutex ) ? 0 : errno ); } int ldap_pvt_thread_mutex_destroy( ldap_pvt_thread_mutex_t *mutex ) { return 0; } int ldap_pvt_thread_mutex_lock( ldap_pvt_thread_mutex_t *mutex ) { return( pth_mutex_acquire( mutex, 0, NULL ) ? 0 : errno ); } int ldap_pvt_thread_mutex_unlock( ldap_pvt_thread_mutex_t *mutex ) { return( pth_mutex_release( mutex ) ? 0 : errno ); } int ldap_pvt_thread_mutex_trylock( ldap_pvt_thread_mutex_t *mutex ) { return( pth_mutex_acquire( mutex, 1, NULL ) ? 0 : errno ); } ldap_pvt_thread_t ldap_pvt_thread_self( void ) { return pth_self(); } int ldap_pvt_thread_key_create( ldap_pvt_thread_key_t *key ) { return pth_key_create( key, NULL ); } int ldap_pvt_thread_key_destroy( ldap_pvt_thread_key_t key ) { return pth_key_delete( key ); } int ldap_pvt_thread_key_setdata( ldap_pvt_thread_key_t key, void *data ) { return pth_key_setdata( key, data ); } int ldap_pvt_thread_key_getdata( ldap_pvt_thread_key_t key, void **data ) { *data = pth_key_getdata( key ); return 0; } #ifdef LDAP_THREAD_HAVE_RDWR int ldap_pvt_thread_rdwr_init( ldap_pvt_thread_rdwr_t *rw ) { return pth_rwlock_init( rw ) ? 0 : errno; } int ldap_pvt_thread_rdwr_destroy( ldap_pvt_thread_rdwr_t *rw ) { return 0; } int ldap_pvt_thread_rdwr_rlock( ldap_pvt_thread_rdwr_t *rw ) { return pth_rwlock_acquire( rw, PTH_RWLOCK_RD, 0, NULL ) ? 0 : errno; } int ldap_pvt_thread_rdwr_rtrylock( ldap_pvt_thread_rdwr_t *rw ) { return pth_rwlock_acquire( rw, PTH_RWLOCK_RD, 1, NULL ) ? 0 : errno; } int ldap_pvt_thread_rdwr_runlock( ldap_pvt_thread_rdwr_t *rw ) { return pth_rwlock_release( rw ) ? 0 : errno; } int ldap_pvt_thread_rdwr_wlock( ldap_pvt_thread_rdwr_t *rw ) { return pth_rwlock_acquire( rw, PTH_RWLOCK_RW, 0, NULL ) ? 0 : errno; } int ldap_pvt_thread_rdwr_wtrylock( ldap_pvt_thread_rdwr_t *rw ) { return pth_rwlock_acquire( rw, PTH_RWLOCK_RW, 1, NULL ) ? 0 : errno; } int ldap_pvt_thread_rdwr_wunlock( ldap_pvt_thread_rdwr_t *rw ) { return pth_rwlock_release( rw ) ? 0 : errno; } #endif /* LDAP_THREAD_HAVE_RDWR */ #endif /* HAVE_GNU_PTH */ openldap-2.4.42+dfsg/libraries/libldap_r/thr_cthreads.c0000644000175000017500000000640612563404150021560 0ustar ryanryan/* thr_cthreads.c - wrapper for mach cthreads */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* This work was initially developed by Luke Howard for inclusion * in U-MICH LDAP 3.3. */ #include "portable.h" #if defined( HAVE_MACH_CTHREADS ) #include "ldap_pvt_thread.h" /* Get the thread interface */ #define LDAP_THREAD_IMPLEMENTATION #include "ldap_thr_debug.h" /* May rename the symbols defined below */ int ldap_int_thread_initialize( void ) { return 0; } int ldap_int_thread_destroy( void ) { return 0; } int ldap_pvt_thread_create( ldap_pvt_thread_t * thread, int detach, void *(*start_routine)( void *), void *arg) { *thread = cthread_fork( (cthread_fn_t) start_routine, arg); return ( *thread == NULL ? -1 : 0 ); } void ldap_pvt_thread_exit( void *retval ) { cthread_exit( (any_t) retval ); } int ldap_pvt_thread_join( ldap_pvt_thread_t thread, void **thread_return ) { void *status; status = (void *) cthread_join ( thread ); if (thread_return != NULL) { *thread_return = status; } return 0; } int ldap_pvt_thread_kill( ldap_pvt_thread_t thread, int signo ) { return 0; } int ldap_pvt_thread_yield( void ) { cthread_yield(); return 0; } int ldap_pvt_thread_cond_init( ldap_pvt_thread_cond_t *cond ) { condition_init( cond ); return( 0 ); } int ldap_pvt_thread_cond_destroy( ldap_pvt_thread_cond_t *cond ) { condition_clear( cond ); return( 0 ); } int ldap_pvt_thread_cond_signal( ldap_pvt_thread_cond_t *cond ) { condition_signal( cond ); return( 0 ); } int ldap_pvt_thread_cond_broadcast( ldap_pvt_thread_cond_t *cond ) { condition_broadcast( cond ); return( 0 ); } int ldap_pvt_thread_cond_wait( ldap_pvt_thread_cond_t *cond, ldap_pvt_thread_mutex_t *mutex ) { condition_wait( cond, mutex ); return( 0 ); } int ldap_pvt_thread_mutex_init( ldap_pvt_thread_mutex_t *mutex ) { mutex_init( mutex ); mutex->name = NULL; return ( 0 ); } int ldap_pvt_thread_mutex_destroy( ldap_pvt_thread_mutex_t *mutex ) { mutex_clear( mutex ); return ( 0 ); } int ldap_pvt_thread_mutex_lock( ldap_pvt_thread_mutex_t *mutex ) { mutex_lock( mutex ); return ( 0 ); } int ldap_pvt_thread_mutex_unlock( ldap_pvt_thread_mutex_t *mutex ) { mutex_unlock( mutex ); return ( 0 ); } int ldap_pvt_thread_mutex_trylock( ldap_pvt_thread_mutex_t *mutex ) { return mutex_try_lock( mutex ); } ldap_pvt_thread_t ldap_pvt_thread_self( void ) { return cthread_self(); } int ldap_pvt_thread_key_create( ldap_pvt_thread_key_t *key ) { return cthread_keycreate( key ); } int ldap_pvt_thread_key_destroy( ldap_pvt_thread_key_t key ) { return( 0 ); } int ldap_pvt_thread_key_setdata( ldap_pvt_thread_key_t key, void *data ) { return cthread_setspecific( key, data ); } int ldap_pvt_thread_key_getdata( ldap_pvt_thread_key_t key, void **data ) { return cthread_getspecific( key, data ); } #endif /* HAVE_MACH_CTHREADS */ openldap-2.4.42+dfsg/libraries/libldap_r/tpool.c0000644000175000017500000006475312563404150020254 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #include "portable.h" #include #include #include #include #include #include #include #include "ldap-int.h" #include "ldap_pvt_thread.h" /* Get the thread interface */ #include "ldap_queue.h" #define LDAP_THREAD_POOL_IMPLEMENTATION #include "ldap_thr_debug.h" /* May rename symbols defined below */ #ifndef LDAP_THREAD_HAVE_TPOOL /* Thread-specific key with data and optional free function */ typedef struct ldap_int_tpool_key_s { void *ltk_key; void *ltk_data; ldap_pvt_thread_pool_keyfree_t *ltk_free; } ldap_int_tpool_key_t; /* Max number of thread-specific keys we store per thread. * We don't expect to use many... */ #define MAXKEYS 32 /* Max number of threads */ #define LDAP_MAXTHR 1024 /* must be a power of 2 */ /* (Theoretical) max number of pending requests */ #define MAX_PENDING (INT_MAX/2) /* INT_MAX - (room to avoid overflow) */ /* pool->ltp_pause values */ enum { NOT_PAUSED = 0, WANT_PAUSE = 1, PAUSED = 2 }; /* Context: thread ID and thread-specific key/data pairs */ typedef struct ldap_int_thread_userctx_s { ldap_pvt_thread_t ltu_id; ldap_int_tpool_key_t ltu_key[MAXKEYS]; } ldap_int_thread_userctx_t; /* Simple {thread ID -> context} hash table; key=ctx->ltu_id. * Protected by ldap_pvt_thread_pool_mutex except during pauses, * when it is read-only (used by pool_purgekey and pool_context). * Protected by tpool->ltp_mutex during pauses. */ static struct { ldap_int_thread_userctx_t *ctx; /* ctx is valid when not NULL or DELETED_THREAD_CTX */ # define DELETED_THREAD_CTX (&ldap_int_main_thrctx + 1) /* dummy addr */ } thread_keys[LDAP_MAXTHR]; #define TID_HASH(tid, hash) do { \ unsigned const char *ptr_ = (unsigned const char *)&(tid); \ unsigned i_; \ for (i_ = 0, (hash) = ptr_[0]; ++i_ < sizeof(tid);) \ (hash) += ((hash) << 5) ^ ptr_[i_]; \ } while(0) /* Task for a thread to perform */ typedef struct ldap_int_thread_task_s { union { LDAP_STAILQ_ENTRY(ldap_int_thread_task_s) q; LDAP_SLIST_ENTRY(ldap_int_thread_task_s) l; } ltt_next; ldap_pvt_thread_start_t *ltt_start_routine; void *ltt_arg; } ldap_int_thread_task_t; typedef LDAP_STAILQ_HEAD(tcq, ldap_int_thread_task_s) ldap_int_tpool_plist_t; struct ldap_int_thread_pool_s { LDAP_STAILQ_ENTRY(ldap_int_thread_pool_s) ltp_next; /* protect members below, and protect thread_keys[] during pauses */ ldap_pvt_thread_mutex_t ltp_mutex; /* not paused and something to do for pool_() */ ldap_pvt_thread_cond_t ltp_cond; /* ltp_active_count <= 1 && ltp_pause */ ldap_pvt_thread_cond_t ltp_pcond; /* ltp_pause == 0 ? <p_pending_list : &empty_pending_list, * maintaned to reduce work for pool_wrapper() */ ldap_int_tpool_plist_t *ltp_work_list; /* pending tasks, and unused task objects */ ldap_int_tpool_plist_t ltp_pending_list; LDAP_SLIST_HEAD(tcl, ldap_int_thread_task_s) ltp_free_list; /* The pool is finishing, waiting for its threads to close. * They close when ltp_pending_list is done. pool_submit() * rejects new tasks. ltp_max_pending = -(its old value). */ int ltp_finishing; /* Some active task needs to be the sole active task. * Atomic variable so ldap_pvt_thread_pool_pausing() can read it. * Note: Pauses adjust ltp_, * so pool_() mostly can avoid testing ltp_pause. */ volatile sig_atomic_t ltp_pause; /* Max number of threads in pool, or 0 for default (LDAP_MAXTHR) */ int ltp_max_count; /* Max pending + paused + idle tasks, negated when ltp_finishing */ int ltp_max_pending; int ltp_pending_count; /* Pending + paused + idle tasks */ int ltp_active_count; /* Active, not paused/idle tasks */ int ltp_open_count; /* Number of threads, negated when ltp_pause */ int ltp_starting; /* Currenlty starting threads */ /* >0 if paused or we may open a thread, <0 if we should close a thread. * Updated when ltp_ change. * Maintained to reduce the time ltp_mutex must be locked in * ldap_pvt_thread_pool_(). */ int ltp_vary_open_count; # define SET_VARY_OPEN_COUNT(pool) \ ((pool)->ltp_vary_open_count = \ (pool)->ltp_pause ? 1 : \ (pool)->ltp_finishing ? -1 : \ ((pool)->ltp_max_count ? (pool)->ltp_max_count : LDAP_MAXTHR) \ - (pool)->ltp_open_count) }; static ldap_int_tpool_plist_t empty_pending_list = LDAP_STAILQ_HEAD_INITIALIZER(empty_pending_list); static int ldap_int_has_thread_pool = 0; static LDAP_STAILQ_HEAD(tpq, ldap_int_thread_pool_s) ldap_int_thread_pool_list = LDAP_STAILQ_HEAD_INITIALIZER(ldap_int_thread_pool_list); static ldap_pvt_thread_mutex_t ldap_pvt_thread_pool_mutex; static void *ldap_int_thread_pool_wrapper( void *pool ); static ldap_pvt_thread_key_t ldap_tpool_key; /* Context of the main thread */ static ldap_int_thread_userctx_t ldap_int_main_thrctx; int ldap_int_thread_pool_startup ( void ) { ldap_int_main_thrctx.ltu_id = ldap_pvt_thread_self(); ldap_pvt_thread_key_create( &ldap_tpool_key ); return ldap_pvt_thread_mutex_init(&ldap_pvt_thread_pool_mutex); } int ldap_int_thread_pool_shutdown ( void ) { struct ldap_int_thread_pool_s *pool; while ((pool = LDAP_STAILQ_FIRST(&ldap_int_thread_pool_list)) != NULL) { (ldap_pvt_thread_pool_destroy)(&pool, 0); /* ignore thr_debug macro */ } ldap_pvt_thread_mutex_destroy(&ldap_pvt_thread_pool_mutex); ldap_pvt_thread_key_destroy( ldap_tpool_key ); return(0); } /* Create a thread pool */ int ldap_pvt_thread_pool_init ( ldap_pvt_thread_pool_t *tpool, int max_threads, int max_pending ) { ldap_pvt_thread_pool_t pool; int rc; /* multiple pools are currently not supported (ITS#4943) */ assert(!ldap_int_has_thread_pool); if (! (0 <= max_threads && max_threads <= LDAP_MAXTHR)) max_threads = 0; if (! (1 <= max_pending && max_pending <= MAX_PENDING)) max_pending = MAX_PENDING; *tpool = NULL; pool = (ldap_pvt_thread_pool_t) LDAP_CALLOC(1, sizeof(struct ldap_int_thread_pool_s)); if (pool == NULL) return(-1); rc = ldap_pvt_thread_mutex_init(&pool->ltp_mutex); if (rc != 0) { fail1: LDAP_FREE(pool); return(rc); } rc = ldap_pvt_thread_cond_init(&pool->ltp_cond); if (rc != 0) { fail2: ldap_pvt_thread_mutex_destroy(&pool->ltp_mutex); goto fail1; } rc = ldap_pvt_thread_cond_init(&pool->ltp_pcond); if (rc != 0) { ldap_pvt_thread_cond_destroy(&pool->ltp_cond); goto fail2; } ldap_int_has_thread_pool = 1; pool->ltp_max_count = max_threads; SET_VARY_OPEN_COUNT(pool); pool->ltp_max_pending = max_pending; LDAP_STAILQ_INIT(&pool->ltp_pending_list); pool->ltp_work_list = &pool->ltp_pending_list; LDAP_SLIST_INIT(&pool->ltp_free_list); ldap_pvt_thread_mutex_lock(&ldap_pvt_thread_pool_mutex); LDAP_STAILQ_INSERT_TAIL(&ldap_int_thread_pool_list, pool, ltp_next); ldap_pvt_thread_mutex_unlock(&ldap_pvt_thread_pool_mutex); /* Start no threads just yet. That can break if the process forks * later, as slapd does in order to daemonize. On at least POSIX, * only the forking thread would survive in the child. Yet fork() * can't unlock/clean up other threads' locks and data structures, * unless pthread_atfork() handlers have been set up to do so. */ *tpool = pool; return(0); } /* Submit a task to be performed by the thread pool */ int ldap_pvt_thread_pool_submit ( ldap_pvt_thread_pool_t *tpool, ldap_pvt_thread_start_t *start_routine, void *arg ) { struct ldap_int_thread_pool_s *pool; ldap_int_thread_task_t *task; ldap_pvt_thread_t thr; if (tpool == NULL) return(-1); pool = *tpool; if (pool == NULL) return(-1); ldap_pvt_thread_mutex_lock(&pool->ltp_mutex); if (pool->ltp_pending_count >= pool->ltp_max_pending) goto failed; task = LDAP_SLIST_FIRST(&pool->ltp_free_list); if (task) { LDAP_SLIST_REMOVE_HEAD(&pool->ltp_free_list, ltt_next.l); } else { task = (ldap_int_thread_task_t *) LDAP_MALLOC(sizeof(*task)); if (task == NULL) goto failed; } task->ltt_start_routine = start_routine; task->ltt_arg = arg; pool->ltp_pending_count++; LDAP_STAILQ_INSERT_TAIL(&pool->ltp_pending_list, task, ltt_next.q); /* true if ltp_pause != 0 or we should open (create) a thread */ if (pool->ltp_vary_open_count > 0 && pool->ltp_open_count < pool->ltp_active_count+pool->ltp_pending_count) { if (pool->ltp_pause) goto done; pool->ltp_starting++; pool->ltp_open_count++; SET_VARY_OPEN_COUNT(pool); if (0 != ldap_pvt_thread_create( &thr, 1, ldap_int_thread_pool_wrapper, pool)) { /* couldn't create thread. back out of * ltp_open_count and check for even worse things. */ pool->ltp_starting--; pool->ltp_open_count--; SET_VARY_OPEN_COUNT(pool); if (pool->ltp_open_count == 0) { /* no open threads at all?!? */ ldap_int_thread_task_t *ptr; /* let pool_destroy know there are no more threads */ ldap_pvt_thread_cond_signal(&pool->ltp_cond); LDAP_STAILQ_FOREACH(ptr, &pool->ltp_pending_list, ltt_next.q) if (ptr == task) break; if (ptr == task) { /* no open threads, task not handled, so * back out of ltp_pending_count, free the task, * report the error. */ pool->ltp_pending_count--; LDAP_STAILQ_REMOVE(&pool->ltp_pending_list, task, ldap_int_thread_task_s, ltt_next.q); LDAP_SLIST_INSERT_HEAD(&pool->ltp_free_list, task, ltt_next.l); goto failed; } } /* there is another open thread, so this * task will be handled eventually. */ } } ldap_pvt_thread_cond_signal(&pool->ltp_cond); done: ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex); return(0); failed: ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex); return(-1); } static void * no_task( void *ctx, void *arg ) { return NULL; } /* Cancel a pending task that was previously submitted. * Return 1 if the task was successfully cancelled, 0 if * not found, -1 for invalid parameters */ int ldap_pvt_thread_pool_retract ( ldap_pvt_thread_pool_t *tpool, ldap_pvt_thread_start_t *start_routine, void *arg ) { struct ldap_int_thread_pool_s *pool; ldap_int_thread_task_t *task; if (tpool == NULL) return(-1); pool = *tpool; if (pool == NULL) return(-1); ldap_pvt_thread_mutex_lock(&pool->ltp_mutex); LDAP_STAILQ_FOREACH(task, &pool->ltp_pending_list, ltt_next.q) if (task->ltt_start_routine == start_routine && task->ltt_arg == arg) { /* Could LDAP_STAILQ_REMOVE the task, but that * walks ltp_pending_list again to find it. */ task->ltt_start_routine = no_task; task->ltt_arg = NULL; break; } ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex); return task != NULL; } /* Set max #threads. value <= 0 means max supported #threads (LDAP_MAXTHR) */ int ldap_pvt_thread_pool_maxthreads( ldap_pvt_thread_pool_t *tpool, int max_threads ) { struct ldap_int_thread_pool_s *pool; if (! (0 <= max_threads && max_threads <= LDAP_MAXTHR)) max_threads = 0; if (tpool == NULL) return(-1); pool = *tpool; if (pool == NULL) return(-1); ldap_pvt_thread_mutex_lock(&pool->ltp_mutex); pool->ltp_max_count = max_threads; SET_VARY_OPEN_COUNT(pool); ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex); return(0); } /* Inspect the pool */ int ldap_pvt_thread_pool_query( ldap_pvt_thread_pool_t *tpool, ldap_pvt_thread_pool_param_t param, void *value ) { struct ldap_int_thread_pool_s *pool; int count = -1; if ( tpool == NULL || value == NULL ) { return -1; } pool = *tpool; if ( pool == NULL ) { return 0; } ldap_pvt_thread_mutex_lock(&pool->ltp_mutex); switch ( param ) { case LDAP_PVT_THREAD_POOL_PARAM_MAX: count = pool->ltp_max_count; break; case LDAP_PVT_THREAD_POOL_PARAM_MAX_PENDING: count = pool->ltp_max_pending; if (count < 0) count = -count; if (count == MAX_PENDING) count = 0; break; case LDAP_PVT_THREAD_POOL_PARAM_OPEN: count = pool->ltp_open_count; if (count < 0) count = -count; break; case LDAP_PVT_THREAD_POOL_PARAM_STARTING: count = pool->ltp_starting; break; case LDAP_PVT_THREAD_POOL_PARAM_ACTIVE: count = pool->ltp_active_count; break; case LDAP_PVT_THREAD_POOL_PARAM_PAUSING: count = (pool->ltp_pause != 0); break; case LDAP_PVT_THREAD_POOL_PARAM_PENDING: count = pool->ltp_pending_count; break; case LDAP_PVT_THREAD_POOL_PARAM_BACKLOAD: count = pool->ltp_pending_count + pool->ltp_active_count; break; case LDAP_PVT_THREAD_POOL_PARAM_ACTIVE_MAX: break; case LDAP_PVT_THREAD_POOL_PARAM_PENDING_MAX: break; case LDAP_PVT_THREAD_POOL_PARAM_BACKLOAD_MAX: break; case LDAP_PVT_THREAD_POOL_PARAM_STATE: *((char **)value) = pool->ltp_pause ? "pausing" : !pool->ltp_finishing ? "running" : pool->ltp_pending_count ? "finishing" : "stopping"; break; case LDAP_PVT_THREAD_POOL_PARAM_UNKNOWN: break; } ldap_pvt_thread_mutex_unlock( &pool->ltp_mutex ); if ( count > -1 ) { *((int *)value) = count; } return ( count == -1 ? -1 : 0 ); } /* * true if pool is pausing; does not lock any mutex to check. * 0 if not pause, 1 if pause, -1 if error or no pool. */ int ldap_pvt_thread_pool_pausing( ldap_pvt_thread_pool_t *tpool ) { int rc = -1; struct ldap_int_thread_pool_s *pool; if ( tpool != NULL && (pool = *tpool) != NULL ) { rc = (pool->ltp_pause != 0); } return rc; } /* * wrapper for ldap_pvt_thread_pool_query(), left around * for backwards compatibility */ int ldap_pvt_thread_pool_backload ( ldap_pvt_thread_pool_t *tpool ) { int rc, count; rc = ldap_pvt_thread_pool_query( tpool, LDAP_PVT_THREAD_POOL_PARAM_BACKLOAD, (void *)&count ); if ( rc == 0 ) { return count; } return rc; } /* Destroy the pool after making its threads finish */ int ldap_pvt_thread_pool_destroy ( ldap_pvt_thread_pool_t *tpool, int run_pending ) { struct ldap_int_thread_pool_s *pool, *pptr; ldap_int_thread_task_t *task; if (tpool == NULL) return(-1); pool = *tpool; if (pool == NULL) return(-1); ldap_pvt_thread_mutex_lock(&ldap_pvt_thread_pool_mutex); LDAP_STAILQ_FOREACH(pptr, &ldap_int_thread_pool_list, ltp_next) if (pptr == pool) break; if (pptr == pool) LDAP_STAILQ_REMOVE(&ldap_int_thread_pool_list, pool, ldap_int_thread_pool_s, ltp_next); ldap_pvt_thread_mutex_unlock(&ldap_pvt_thread_pool_mutex); if (pool != pptr) return(-1); ldap_pvt_thread_mutex_lock(&pool->ltp_mutex); pool->ltp_finishing = 1; SET_VARY_OPEN_COUNT(pool); if (pool->ltp_max_pending > 0) pool->ltp_max_pending = -pool->ltp_max_pending; if (!run_pending) { while ((task = LDAP_STAILQ_FIRST(&pool->ltp_pending_list)) != NULL) { LDAP_STAILQ_REMOVE_HEAD(&pool->ltp_pending_list, ltt_next.q); LDAP_FREE(task); } pool->ltp_pending_count = 0; } while (pool->ltp_open_count) { if (!pool->ltp_pause) ldap_pvt_thread_cond_broadcast(&pool->ltp_cond); ldap_pvt_thread_cond_wait(&pool->ltp_cond, &pool->ltp_mutex); } while ((task = LDAP_SLIST_FIRST(&pool->ltp_free_list)) != NULL) { LDAP_SLIST_REMOVE_HEAD(&pool->ltp_free_list, ltt_next.l); LDAP_FREE(task); } ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex); ldap_pvt_thread_cond_destroy(&pool->ltp_pcond); ldap_pvt_thread_cond_destroy(&pool->ltp_cond); ldap_pvt_thread_mutex_destroy(&pool->ltp_mutex); LDAP_FREE(pool); *tpool = NULL; ldap_int_has_thread_pool = 0; return(0); } /* Thread loop. Accept and handle submitted tasks. */ static void * ldap_int_thread_pool_wrapper ( void *xpool ) { struct ldap_int_thread_pool_s *pool = xpool; ldap_int_thread_task_t *task; ldap_int_tpool_plist_t *work_list; ldap_int_thread_userctx_t ctx, *kctx; unsigned i, keyslot, hash; assert(pool != NULL); for ( i=0; iltp_mutex); /* thread_keys[] is read-only when paused */ while (pool->ltp_pause) ldap_pvt_thread_cond_wait(&pool->ltp_cond, &pool->ltp_mutex); /* find a key slot to give this thread ID and store a * pointer to our keys there; start at the thread ID * itself (mod LDAP_MAXTHR) and look for an empty slot. */ ldap_pvt_thread_mutex_lock(&ldap_pvt_thread_pool_mutex); for (keyslot = hash & (LDAP_MAXTHR-1); (kctx = thread_keys[keyslot].ctx) && kctx != DELETED_THREAD_CTX; keyslot = (keyslot+1) & (LDAP_MAXTHR-1)); thread_keys[keyslot].ctx = &ctx; ldap_pvt_thread_mutex_unlock(&ldap_pvt_thread_pool_mutex); pool->ltp_starting--; pool->ltp_active_count++; for (;;) { work_list = pool->ltp_work_list; /* help the compiler a bit */ task = LDAP_STAILQ_FIRST(work_list); if (task == NULL) { /* paused or no pending tasks */ if (--(pool->ltp_active_count) < 2) { /* Notify pool_pause it is the sole active thread. */ ldap_pvt_thread_cond_signal(&pool->ltp_pcond); } do { if (pool->ltp_vary_open_count < 0) { /* Not paused, and either finishing or too many * threads running (can happen if ltp_max_count * was reduced). Let this thread die. */ goto done; } /* We could check an idle timer here, and let the * thread die if it has been inactive for a while. * Only die if there are other open threads (i.e., * always have at least one thread open). * The check should be like this: * if (pool->ltp_open_count>1 && pool->ltp_starting==0) * check timer, wait if ltp_pause, leave thread; * * Just use pthread_cond_timedwait() if we want to * check idle time. */ ldap_pvt_thread_cond_wait(&pool->ltp_cond, &pool->ltp_mutex); work_list = pool->ltp_work_list; task = LDAP_STAILQ_FIRST(work_list); } while (task == NULL); pool->ltp_active_count++; } LDAP_STAILQ_REMOVE_HEAD(work_list, ltt_next.q); pool->ltp_pending_count--; ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex); task->ltt_start_routine(&ctx, task->ltt_arg); ldap_pvt_thread_mutex_lock(&pool->ltp_mutex); LDAP_SLIST_INSERT_HEAD(&pool->ltp_free_list, task, ltt_next.l); } done: assert(!pool->ltp_pause); /* thread_keys writable, ltp_open_count >= 0 */ /* The ltp_mutex lock protects ctx->ltu_key from pool_purgekey() * during this call, since it prevents new pauses. */ ldap_pvt_thread_pool_context_reset(&ctx); ldap_pvt_thread_mutex_lock(&ldap_pvt_thread_pool_mutex); thread_keys[keyslot].ctx = DELETED_THREAD_CTX; ldap_pvt_thread_mutex_unlock(&ldap_pvt_thread_pool_mutex); pool->ltp_open_count--; SET_VARY_OPEN_COUNT(pool); /* let pool_destroy know we're all done */ if (pool->ltp_open_count == 0) ldap_pvt_thread_cond_signal(&pool->ltp_cond); ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex); ldap_pvt_thread_exit(NULL); return(NULL); } /* Arguments > ltp_pause to handle_pause(,PAUSE_ARG()). arg=PAUSE_ARG * ensures (arg-ltp_pause) sets GO_* at need and keeps DO_PAUSE/GO_*. */ #define GO_IDLE 8 #define GO_UNIDLE 16 #define CHECK_PAUSE 32 /* if ltp_pause: GO_IDLE; wait; GO_UNIDLE */ #define DO_PAUSE 64 /* CHECK_PAUSE; pause the pool */ #define PAUSE_ARG(a) \ ((a) | ((a) & (GO_IDLE|GO_UNIDLE) ? GO_IDLE-1 : CHECK_PAUSE)) static int handle_pause( ldap_pvt_thread_pool_t *tpool, int pause_type ) { struct ldap_int_thread_pool_s *pool; int ret = 0, pause, max_ltp_pause; if (tpool == NULL) return(-1); pool = *tpool; if (pool == NULL) return(0); if (pause_type == CHECK_PAUSE && !pool->ltp_pause) return(0); /* Let pool_unidle() ignore requests for new pauses */ max_ltp_pause = pause_type==PAUSE_ARG(GO_UNIDLE) ? WANT_PAUSE : NOT_PAUSED; ldap_pvt_thread_mutex_lock(&pool->ltp_mutex); pause = pool->ltp_pause; /* NOT_PAUSED, WANT_PAUSE or PAUSED */ /* If ltp_pause and not GO_IDLE|GO_UNIDLE: Set GO_IDLE,GO_UNIDLE */ pause_type -= pause; if (pause_type & GO_IDLE) { pool->ltp_pending_count++; pool->ltp_active_count--; if (pause && pool->ltp_active_count < 2) { /* Tell the task waiting to DO_PAUSE it can proceed */ ldap_pvt_thread_cond_signal(&pool->ltp_pcond); } } if (pause_type & GO_UNIDLE) { /* Wait out pause if any, then cancel GO_IDLE */ if (pause > max_ltp_pause) { ret = 1; do { ldap_pvt_thread_cond_wait(&pool->ltp_cond, &pool->ltp_mutex); } while (pool->ltp_pause > max_ltp_pause); } pool->ltp_pending_count--; pool->ltp_active_count++; } if (pause_type & DO_PAUSE) { /* Tell everyone else to pause or finish, then await that */ ret = 0; assert(!pool->ltp_pause); pool->ltp_pause = WANT_PAUSE; /* Let ldap_pvt_thread_pool_submit() through to its ltp_pause test, * and do not finish threads in ldap_pvt_thread_pool_wrapper() */ pool->ltp_open_count = -pool->ltp_open_count; SET_VARY_OPEN_COUNT(pool); /* Hide pending tasks from ldap_pvt_thread_pool_wrapper() */ pool->ltp_work_list = &empty_pending_list; /* Wait for this task to become the sole active task */ while (pool->ltp_active_count > 1) { ldap_pvt_thread_cond_wait(&pool->ltp_pcond, &pool->ltp_mutex); } assert(pool->ltp_pause == WANT_PAUSE); pool->ltp_pause = PAUSED; } ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex); return(ret); } /* Consider this task idle: It will not block pool_pause() in other tasks. */ void ldap_pvt_thread_pool_idle( ldap_pvt_thread_pool_t *tpool ) { handle_pause(tpool, PAUSE_ARG(GO_IDLE)); } /* Cancel pool_idle(). If the pool is paused, wait it out first. */ void ldap_pvt_thread_pool_unidle( ldap_pvt_thread_pool_t *tpool ) { handle_pause(tpool, PAUSE_ARG(GO_UNIDLE)); } /* * If a pause was requested, wait for it. If several threads * are waiting to pause, let through one or more pauses. * The calling task must be active, not idle. * Return 1 if we waited, 0 if not, -1 at parameter error. */ int ldap_pvt_thread_pool_pausecheck( ldap_pvt_thread_pool_t *tpool ) { return handle_pause(tpool, PAUSE_ARG(CHECK_PAUSE)); } /* * Pause the pool. The calling task must be active, not idle. * Return when all other tasks are paused or idle. */ int ldap_pvt_thread_pool_pause( ldap_pvt_thread_pool_t *tpool ) { return handle_pause(tpool, PAUSE_ARG(DO_PAUSE)); } /* End a pause */ int ldap_pvt_thread_pool_resume ( ldap_pvt_thread_pool_t *tpool ) { struct ldap_int_thread_pool_s *pool; if (tpool == NULL) return(-1); pool = *tpool; if (pool == NULL) return(0); ldap_pvt_thread_mutex_lock(&pool->ltp_mutex); assert(pool->ltp_pause == PAUSED); pool->ltp_pause = 0; if (pool->ltp_open_count <= 0) /* true when paused, but be paranoid */ pool->ltp_open_count = -pool->ltp_open_count; SET_VARY_OPEN_COUNT(pool); pool->ltp_work_list = &pool->ltp_pending_list; ldap_pvt_thread_cond_broadcast(&pool->ltp_cond); ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex); return(0); } /* * Get the key's data and optionally free function in the given context. */ int ldap_pvt_thread_pool_getkey( void *xctx, void *key, void **data, ldap_pvt_thread_pool_keyfree_t **kfree ) { ldap_int_thread_userctx_t *ctx = xctx; int i; if ( !ctx || !key || !data ) return EINVAL; for ( i=0; iltu_key[i].ltk_key; i++ ) { if ( ctx->ltu_key[i].ltk_key == key ) { *data = ctx->ltu_key[i].ltk_data; if ( kfree ) *kfree = ctx->ltu_key[i].ltk_free; return 0; } } return ENOENT; } static void clear_key_idx( ldap_int_thread_userctx_t *ctx, int i ) { for ( ; i < MAXKEYS-1 && ctx->ltu_key[i+1].ltk_key; i++ ) ctx->ltu_key[i] = ctx->ltu_key[i+1]; ctx->ltu_key[i].ltk_key = NULL; } /* * Set or remove data for the key in the given context. * key can be any unique pointer. * kfree() is an optional function to free the data (but not the key): * pool_context_reset() and pool_purgekey() call kfree(key, data), * but pool_setkey() does not. For pool_setkey() it is the caller's * responsibility to free any existing data with the same key. * kfree() must not call functions taking a tpool argument. */ int ldap_pvt_thread_pool_setkey( void *xctx, void *key, void *data, ldap_pvt_thread_pool_keyfree_t *kfree, void **olddatap, ldap_pvt_thread_pool_keyfree_t **oldkfreep ) { ldap_int_thread_userctx_t *ctx = xctx; int i, found; if ( !ctx || !key ) return EINVAL; for ( i=found=0; iltu_key[i].ltk_key == key ) { found = 1; break; } else if ( !ctx->ltu_key[i].ltk_key ) { break; } } if ( olddatap ) { if ( found ) { *olddatap = ctx->ltu_key[i].ltk_data; } else { *olddatap = NULL; } } if ( oldkfreep ) { if ( found ) { *oldkfreep = ctx->ltu_key[i].ltk_free; } else { *oldkfreep = 0; } } if ( data || kfree ) { if ( i>=MAXKEYS ) return ENOMEM; ctx->ltu_key[i].ltk_key = key; ctx->ltu_key[i].ltk_data = data; ctx->ltu_key[i].ltk_free = kfree; } else if ( found ) { clear_key_idx( ctx, i ); } return 0; } /* Free all elements with this key, no matter which thread they're in. * May only be called while the pool is paused. */ void ldap_pvt_thread_pool_purgekey( void *key ) { int i, j; ldap_int_thread_userctx_t *ctx; assert ( key != NULL ); for ( i=0; iltu_key[j].ltk_key; j++ ) { if ( ctx->ltu_key[j].ltk_key == key ) { if (ctx->ltu_key[j].ltk_free) ctx->ltu_key[j].ltk_free( ctx->ltu_key[j].ltk_key, ctx->ltu_key[j].ltk_data ); clear_key_idx( ctx, j ); break; } } } } } /* * Find the context of the current thread. * This is necessary if the caller does not have access to the * thread context handle (for example, a slapd plugin calling * slapi_search_internal()). No doubt it is more efficient * for the application to keep track of the thread context * handles itself. */ void *ldap_pvt_thread_pool_context( ) { void *ctx = NULL; ldap_pvt_thread_key_getdata( ldap_tpool_key, &ctx ); return ctx ? ctx : (void *) &ldap_int_main_thrctx; } /* * Free the context's keys. * Must not call functions taking a tpool argument (because this * thread already holds ltp_mutex when called from pool_wrapper()). */ void ldap_pvt_thread_pool_context_reset( void *vctx ) { ldap_int_thread_userctx_t *ctx = vctx; int i; for ( i=MAXKEYS-1; i>=0; i--) { if ( !ctx->ltu_key[i].ltk_key ) continue; if ( ctx->ltu_key[i].ltk_free ) ctx->ltu_key[i].ltk_free( ctx->ltu_key[i].ltk_key, ctx->ltu_key[i].ltk_data ); ctx->ltu_key[i].ltk_key = NULL; } } ldap_pvt_thread_t ldap_pvt_thread_pool_tid( void *vctx ) { ldap_int_thread_userctx_t *ctx = vctx; return ctx->ltu_id; } #endif /* LDAP_THREAD_HAVE_TPOOL */ openldap-2.4.42+dfsg/libraries/libldap/0000755000175000017500000000000012563404150016413 5ustar ryanryanopenldap-2.4.42+dfsg/libraries/libldap/request.c0000644000175000017500000012234712563404150020260 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (c) 1995 Regents of the University of Michigan. * All rights reserved. */ /* This notice applies to changes, created by or for Novell, Inc., * to preexisting works for which notices appear elsewhere in this file. * * Copyright (C) 1999, 2000 Novell, Inc. All Rights Reserved. * * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND TREATIES. * USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO VERSION * 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS AVAILABLE AT * HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE" IN THE * TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION OF THIS * WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP PUBLIC * LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT THE * PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY. *--- * Modification to OpenLDAP source by Novell, Inc. * April 2000 sfs Added code to chase V3 referrals * request.c - sending of ldap requests; handling of referrals *--- * Note: A verbatim copy of version 2.0.1 of the OpenLDAP Public License * can be found in the file "build/LICENSE-2.0.1" in this distribution * of OpenLDAP Software. */ #include "portable.h" #include #include #include #include #include #include #include #include "ldap-int.h" #include "lber.h" /* used by ldap_send_server_request and ldap_new_connection */ #ifdef LDAP_R_COMPILE #define LDAP_CONN_LOCK_IF(nolock) \ { if (nolock) LDAP_MUTEX_LOCK( &ld->ld_conn_mutex ); } #define LDAP_CONN_UNLOCK_IF(nolock) \ { if (nolock) LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); } #define LDAP_REQ_LOCK_IF(nolock) \ { if (nolock) LDAP_MUTEX_LOCK( &ld->ld_req_mutex ); } #define LDAP_REQ_UNLOCK_IF(nolock) \ { if (nolock) LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex ); } #define LDAP_RES_LOCK_IF(nolock) \ { if (nolock) LDAP_MUTEX_LOCK( &ld->ld_res_mutex ); } #define LDAP_RES_UNLOCK_IF(nolock) \ { if (nolock) LDAP_MUTEX_UNLOCK( &ld->ld_res_mutex ); } #else #define LDAP_CONN_LOCK_IF(nolock) #define LDAP_CONN_UNLOCK_IF(nolock) #define LDAP_REQ_LOCK_IF(nolock) #define LDAP_REQ_UNLOCK_IF(nolock) #define LDAP_RES_LOCK_IF(nolock) #define LDAP_RES_UNLOCK_IF(nolock) #endif static LDAPConn *find_connection LDAP_P(( LDAP *ld, LDAPURLDesc *srv, int any )); static void use_connection LDAP_P(( LDAP *ld, LDAPConn *lc )); static void ldap_free_request_int LDAP_P(( LDAP *ld, LDAPRequest *lr )); static BerElement * re_encode_request( LDAP *ld, BerElement *origber, ber_int_t msgid, int sref, LDAPURLDesc *srv, int *type ); BerElement * ldap_alloc_ber_with_options( LDAP *ld ) { BerElement *ber; ber = ber_alloc_t( ld->ld_lberoptions ); if ( ber == NULL ) { ld->ld_errno = LDAP_NO_MEMORY; } return( ber ); } void ldap_set_ber_options( LDAP *ld, BerElement *ber ) { /* ld_lberoptions is constant, hence no lock */ ber->ber_options = ld->ld_lberoptions; } /* sets needed mutexes - no mutexes set to this point */ ber_int_t ldap_send_initial_request( LDAP *ld, ber_tag_t msgtype, const char *dn, BerElement *ber, ber_int_t msgid) { int rc = 1; ber_socket_t sd = AC_SOCKET_INVALID; Debug( LDAP_DEBUG_TRACE, "ldap_send_initial_request\n", 0, 0, 0 ); LDAP_MUTEX_LOCK( &ld->ld_conn_mutex ); if ( ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, &sd ) == -1 ) { /* not connected yet */ rc = ldap_open_defconn( ld ); if ( rc == 0 ) { ber_sockbuf_ctrl( ld->ld_defconn->lconn_sb, LBER_SB_OPT_GET_FD, &sd ); } } if ( ld->ld_defconn && ld->ld_defconn->lconn_status == LDAP_CONNST_CONNECTING ) rc = ldap_int_check_async_open( ld, sd ); if( rc < 0 ) { ber_free( ber, 1 ); LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); return( -1 ); } else if ( rc == 0 ) { Debug( LDAP_DEBUG_TRACE, "ldap_open_defconn: successful\n", 0, 0, 0 ); } #ifdef LDAP_CONNECTIONLESS if (LDAP_IS_UDP(ld)) { if (msgtype == LDAP_REQ_BIND) { LDAP_MUTEX_LOCK( &ld->ld_options.ldo_mutex ); if (ld->ld_options.ldo_cldapdn) ldap_memfree(ld->ld_options.ldo_cldapdn); ld->ld_options.ldo_cldapdn = ldap_strdup(dn); ber_free( ber, 1 ); LDAP_MUTEX_UNLOCK( &ld->ld_options.ldo_mutex ); LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); return 0; } if (msgtype != LDAP_REQ_ABANDON && msgtype != LDAP_REQ_SEARCH) { ber_free( ber, 1 ); LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); return LDAP_PARAM_ERROR; } } #endif LDAP_MUTEX_LOCK( &ld->ld_req_mutex ); rc = ldap_send_server_request( ld, ber, msgid, NULL, NULL, NULL, NULL, 0, 0 ); LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex ); LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); return(rc); } /* protected by conn_mutex */ int ldap_int_flush_request( LDAP *ld, LDAPRequest *lr ) { LDAPConn *lc = lr->lr_conn; LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex ); if ( ber_flush2( lc->lconn_sb, lr->lr_ber, LBER_FLUSH_FREE_NEVER ) != 0 ) { if ( sock_errno() == EAGAIN ) { /* need to continue write later */ lr->lr_status = LDAP_REQST_WRITING; ldap_mark_select_write( ld, lc->lconn_sb ); ld->ld_errno = LDAP_BUSY; return -2; } else { ld->ld_errno = LDAP_SERVER_DOWN; ldap_free_request( ld, lr ); ldap_free_connection( ld, lc, 0, 0 ); return( -1 ); } } else { if ( lr->lr_parent == NULL ) { lr->lr_ber->ber_end = lr->lr_ber->ber_ptr; lr->lr_ber->ber_ptr = lr->lr_ber->ber_buf; } lr->lr_status = LDAP_REQST_INPROGRESS; /* sent -- waiting for a response */ ldap_mark_select_read( ld, lc->lconn_sb ); ldap_clear_select_write( ld, lc->lconn_sb ); } return 0; } /* * protected by req_mutex * if m_noconn then protect using conn_lock * else already protected with conn_lock * if m_res then also protected by res_mutex */ int ldap_send_server_request( LDAP *ld, BerElement *ber, ber_int_t msgid, LDAPRequest *parentreq, LDAPURLDesc **srvlist, LDAPConn *lc, LDAPreqinfo *bind, int m_noconn, int m_res ) { LDAPRequest *lr; int incparent, rc; LDAP_ASSERT_MUTEX_OWNER( &ld->ld_req_mutex ); Debug( LDAP_DEBUG_TRACE, "ldap_send_server_request\n", 0, 0, 0 ); incparent = 0; ld->ld_errno = LDAP_SUCCESS; /* optimistic */ LDAP_CONN_LOCK_IF(m_noconn); if ( lc == NULL ) { if ( srvlist == NULL ) { lc = ld->ld_defconn; } else { lc = find_connection( ld, *srvlist, 1 ); if ( lc == NULL ) { if ( (bind != NULL) && (parentreq != NULL) ) { /* Remember the bind in the parent */ incparent = 1; ++parentreq->lr_outrefcnt; } lc = ldap_new_connection( ld, srvlist, 0, 1, bind, 1, m_res ); } } } /* async connect... */ if ( lc != NULL && lc->lconn_status == LDAP_CONNST_CONNECTING ) { ber_socket_t sd = AC_SOCKET_ERROR; struct timeval tv = { 0 }; ber_sockbuf_ctrl( lc->lconn_sb, LBER_SB_OPT_GET_FD, &sd ); /* poll ... */ switch ( ldap_int_poll( ld, sd, &tv, 1 ) ) { case 0: /* go on! */ lc->lconn_status = LDAP_CONNST_CONNECTED; break; case -2: /* async only occurs if a network timeout is set */ /* honor network timeout */ LDAP_MUTEX_LOCK( &ld->ld_options.ldo_mutex ); if ( time( NULL ) - lc->lconn_created <= ld->ld_options.ldo_tm_net.tv_sec ) { /* caller will have to call again */ ld->ld_errno = LDAP_X_CONNECTING; } LDAP_MUTEX_UNLOCK( &ld->ld_options.ldo_mutex ); /* fallthru */ default: /* error */ break; } } if ( lc == NULL || lc->lconn_status != LDAP_CONNST_CONNECTED ) { if ( ld->ld_errno == LDAP_SUCCESS ) { ld->ld_errno = LDAP_SERVER_DOWN; } ber_free( ber, 1 ); if ( incparent ) { /* Forget about the bind */ --parentreq->lr_outrefcnt; } LDAP_CONN_UNLOCK_IF(m_noconn); return( -1 ); } use_connection( ld, lc ); #ifdef LDAP_CONNECTIONLESS if ( LDAP_IS_UDP( ld )) { BerElement tmpber = *ber; ber_rewind( &tmpber ); LDAP_MUTEX_LOCK( &ld->ld_options.ldo_mutex ); rc = ber_write( &tmpber, ld->ld_options.ldo_peer, sizeof( struct sockaddr_storage ), 0 ); LDAP_MUTEX_UNLOCK( &ld->ld_options.ldo_mutex ); if ( rc == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; LDAP_CONN_UNLOCK_IF(m_noconn); return rc; } } #endif /* If we still have an incomplete write, try to finish it before * dealing with the new request. If we don't finish here, return * LDAP_BUSY and let the caller retry later. We only allow a single * request to be in WRITING state. */ rc = 0; if ( ld->ld_requests && ld->ld_requests->lr_status == LDAP_REQST_WRITING && ldap_int_flush_request( ld, ld->ld_requests ) < 0 ) { rc = -1; } if ( rc ) { LDAP_CONN_UNLOCK_IF(m_noconn); return rc; } lr = (LDAPRequest *)LDAP_CALLOC( 1, sizeof( LDAPRequest ) ); if ( lr == NULL ) { ld->ld_errno = LDAP_NO_MEMORY; ldap_free_connection( ld, lc, 0, 0 ); ber_free( ber, 1 ); if ( incparent ) { /* Forget about the bind */ --parentreq->lr_outrefcnt; } LDAP_CONN_UNLOCK_IF(m_noconn); return( -1 ); } lr->lr_msgid = msgid; lr->lr_status = LDAP_REQST_INPROGRESS; lr->lr_res_errno = LDAP_SUCCESS; /* optimistic */ lr->lr_ber = ber; lr->lr_conn = lc; if ( parentreq != NULL ) { /* sub-request */ if ( !incparent ) { /* Increment if we didn't do it before the bind */ ++parentreq->lr_outrefcnt; } lr->lr_origid = parentreq->lr_origid; lr->lr_parentcnt = ++parentreq->lr_parentcnt; lr->lr_parent = parentreq; lr->lr_refnext = parentreq->lr_child; parentreq->lr_child = lr; } else { /* original request */ lr->lr_origid = lr->lr_msgid; } /* Extract requestDN for future reference */ #ifdef LDAP_CONNECTIONLESS if ( !LDAP_IS_UDP(ld) ) #endif { BerElement tmpber = *ber; ber_int_t bint; ber_tag_t tag, rtag; ber_reset( &tmpber, 1 ); rtag = ber_scanf( &tmpber, "{it", /*}*/ &bint, &tag ); switch ( tag ) { case LDAP_REQ_BIND: rtag = ber_scanf( &tmpber, "{i" /*}*/, &bint ); break; case LDAP_REQ_DELETE: break; default: rtag = ber_scanf( &tmpber, "{" /*}*/ ); case LDAP_REQ_ABANDON: break; } if ( tag != LDAP_REQ_ABANDON ) { ber_skip_tag( &tmpber, &lr->lr_dn.bv_len ); lr->lr_dn.bv_val = tmpber.ber_ptr; } } lr->lr_prev = NULL; lr->lr_next = ld->ld_requests; if ( lr->lr_next != NULL ) { lr->lr_next->lr_prev = lr; } ld->ld_requests = lr; ld->ld_errno = LDAP_SUCCESS; if ( ldap_int_flush_request( ld, lr ) == -1 ) { msgid = -1; } LDAP_CONN_UNLOCK_IF(m_noconn); return( msgid ); } /* return 0 if no StartTLS ext, 1 if present, 2 if critical */ static int find_tls_ext( LDAPURLDesc *srv ) { int i, crit; char *ext; if ( !srv->lud_exts ) return 0; for (i=0; srv->lud_exts[i]; i++) { crit = 0; ext = srv->lud_exts[i]; if ( ext[0] == '!') { ext++; crit = 1; } if ( !strcasecmp( ext, "StartTLS" ) || !strcasecmp( ext, "X-StartTLS" ) || !strcmp( ext, LDAP_EXOP_START_TLS )) { return crit + 1; } } return 0; } /* * always protected by conn_mutex * optionally protected by req_mutex and res_mutex */ LDAPConn * ldap_new_connection( LDAP *ld, LDAPURLDesc **srvlist, int use_ldsb, int connect, LDAPreqinfo *bind, int m_req, int m_res ) { LDAPConn *lc; int async = 0; LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex ); Debug( LDAP_DEBUG_TRACE, "ldap_new_connection %d %d %d\n", use_ldsb, connect, (bind != NULL) ); /* * make a new LDAP server connection * XXX open connection synchronously for now */ lc = (LDAPConn *)LDAP_CALLOC( 1, sizeof( LDAPConn ) ); if ( lc == NULL ) { ld->ld_errno = LDAP_NO_MEMORY; return( NULL ); } if ( use_ldsb ) { assert( ld->ld_sb != NULL ); lc->lconn_sb = ld->ld_sb; } else { lc->lconn_sb = ber_sockbuf_alloc(); if ( lc->lconn_sb == NULL ) { LDAP_FREE( (char *)lc ); ld->ld_errno = LDAP_NO_MEMORY; return( NULL ); } } if ( connect ) { LDAPURLDesc **srvp, *srv = NULL; async = LDAP_BOOL_GET( &ld->ld_options, LDAP_BOOL_CONNECT_ASYNC ); for ( srvp = srvlist; *srvp != NULL; srvp = &(*srvp)->lud_next ) { int rc; rc = ldap_int_open_connection( ld, lc, *srvp, async ); if ( rc != -1 ) { srv = *srvp; /* If we fully connected, async is moot */ if ( rc == 0 ) async = 0; if ( ld->ld_urllist_proc && ( !async || rc != -2 ) ) { ld->ld_urllist_proc( ld, srvlist, srvp, ld->ld_urllist_params ); } break; } } if ( srv == NULL ) { if ( !use_ldsb ) { ber_sockbuf_free( lc->lconn_sb ); } LDAP_FREE( (char *)lc ); ld->ld_errno = LDAP_SERVER_DOWN; return( NULL ); } lc->lconn_server = ldap_url_dup( srv ); if ( !lc->lconn_server ) { if ( !use_ldsb ) ber_sockbuf_free( lc->lconn_sb ); LDAP_FREE( (char *)lc ); ld->ld_errno = LDAP_NO_MEMORY; return( NULL ); } } lc->lconn_status = async ? LDAP_CONNST_CONNECTING : LDAP_CONNST_CONNECTED; lc->lconn_next = ld->ld_conns; ld->ld_conns = lc; if ( connect ) { #ifdef HAVE_TLS if ( lc->lconn_server->lud_exts ) { int rc, ext = find_tls_ext( lc->lconn_server ); if ( ext ) { LDAPConn *savedefconn; savedefconn = ld->ld_defconn; ++lc->lconn_refcnt; /* avoid premature free */ ld->ld_defconn = lc; LDAP_REQ_UNLOCK_IF(m_req); LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); LDAP_RES_UNLOCK_IF(m_res); rc = ldap_start_tls_s( ld, NULL, NULL ); LDAP_RES_LOCK_IF(m_res); LDAP_MUTEX_LOCK( &ld->ld_conn_mutex ); LDAP_REQ_LOCK_IF(m_req); ld->ld_defconn = savedefconn; --lc->lconn_refcnt; if ( rc != LDAP_SUCCESS && ext == 2 ) { ldap_free_connection( ld, lc, 1, 0 ); return NULL; } } } #endif } if ( bind != NULL ) { int err = 0; LDAPConn *savedefconn; /* Set flag to prevent additional referrals * from being processed on this * connection until the bind has completed */ lc->lconn_rebind_inprogress = 1; /* V3 rebind function */ if ( ld->ld_rebind_proc != NULL) { LDAPURLDesc *srvfunc; srvfunc = ldap_url_dup( *srvlist ); if ( srvfunc == NULL ) { ld->ld_errno = LDAP_NO_MEMORY; err = -1; } else { savedefconn = ld->ld_defconn; ++lc->lconn_refcnt; /* avoid premature free */ ld->ld_defconn = lc; Debug( LDAP_DEBUG_TRACE, "Call application rebind_proc\n", 0, 0, 0); LDAP_REQ_UNLOCK_IF(m_req); LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); LDAP_RES_UNLOCK_IF(m_res); err = (*ld->ld_rebind_proc)( ld, bind->ri_url, bind->ri_request, bind->ri_msgid, ld->ld_rebind_params ); LDAP_RES_LOCK_IF(m_res); LDAP_MUTEX_LOCK( &ld->ld_conn_mutex ); LDAP_REQ_LOCK_IF(m_req); ld->ld_defconn = savedefconn; --lc->lconn_refcnt; if ( err != 0 ) { err = -1; ldap_free_connection( ld, lc, 1, 0 ); lc = NULL; } ldap_free_urldesc( srvfunc ); } } else { int msgid, rc; struct berval passwd = BER_BVNULL; savedefconn = ld->ld_defconn; ++lc->lconn_refcnt; /* avoid premature free */ ld->ld_defconn = lc; Debug( LDAP_DEBUG_TRACE, "anonymous rebind via ldap_sasl_bind(\"\")\n", 0, 0, 0); LDAP_REQ_UNLOCK_IF(m_req); LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); LDAP_RES_UNLOCK_IF(m_res); rc = ldap_sasl_bind( ld, "", LDAP_SASL_SIMPLE, &passwd, NULL, NULL, &msgid ); if ( rc != LDAP_SUCCESS ) { err = -1; } else { for ( err = 1; err > 0; ) { struct timeval tv = { 0, 100000 }; LDAPMessage *res = NULL; switch ( ldap_result( ld, msgid, LDAP_MSG_ALL, &tv, &res ) ) { case -1: err = -1; break; case 0: #ifdef LDAP_R_COMPILE ldap_pvt_thread_yield(); #endif break; case LDAP_RES_BIND: rc = ldap_parse_result( ld, res, &err, NULL, NULL, NULL, NULL, 1 ); if ( rc != LDAP_SUCCESS ) { err = -1; } else if ( err != LDAP_SUCCESS ) { err = -1; } /* else err == LDAP_SUCCESS == 0 */ break; default: Debug( LDAP_DEBUG_TRACE, "ldap_new_connection %p: " "unexpected response %d " "from BIND request id=%d\n", (void *) ld, ldap_msgtype( res ), msgid ); err = -1; break; } } } LDAP_RES_LOCK_IF(m_res); LDAP_MUTEX_LOCK( &ld->ld_conn_mutex ); LDAP_REQ_LOCK_IF(m_req); ld->ld_defconn = savedefconn; --lc->lconn_refcnt; if ( err != 0 ) { ldap_free_connection( ld, lc, 1, 0 ); lc = NULL; } } if ( lc != NULL ) lc->lconn_rebind_inprogress = 0; } return( lc ); } /* protected by ld_conn_mutex */ static LDAPConn * find_connection( LDAP *ld, LDAPURLDesc *srv, int any ) /* * return an existing connection (if any) to the server srv * if "any" is non-zero, check for any server in the "srv" chain */ { LDAPConn *lc; LDAPURLDesc *lcu, *lsu; int lcu_port, lsu_port; int found = 0; LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex ); for ( lc = ld->ld_conns; lc != NULL; lc = lc->lconn_next ) { lcu = lc->lconn_server; lcu_port = ldap_pvt_url_scheme_port( lcu->lud_scheme, lcu->lud_port ); for ( lsu = srv; lsu != NULL; lsu = lsu->lud_next ) { lsu_port = ldap_pvt_url_scheme_port( lsu->lud_scheme, lsu->lud_port ); if ( lsu_port == lcu_port && strcmp( lcu->lud_scheme, lsu->lud_scheme ) == 0 && lcu->lud_host != NULL && lsu->lud_host != NULL && strcasecmp( lsu->lud_host, lcu->lud_host ) == 0 ) { found = 1; break; } if ( !any ) break; } if ( found ) break; } return lc; } /* protected by ld_conn_mutex */ static void use_connection( LDAP *ld, LDAPConn *lc ) { LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex ); ++lc->lconn_refcnt; lc->lconn_lastused = time( NULL ); } /* protected by ld_conn_mutex */ void ldap_free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind ) { LDAPConn *tmplc, *prevlc; LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex ); Debug( LDAP_DEBUG_TRACE, "ldap_free_connection %d %d\n", force, unbind, 0 ); if ( force || --lc->lconn_refcnt <= 0 ) { /* remove from connections list first */ for ( prevlc = NULL, tmplc = ld->ld_conns; tmplc != NULL; tmplc = tmplc->lconn_next ) { if ( tmplc == lc ) { if ( prevlc == NULL ) { ld->ld_conns = tmplc->lconn_next; } else { prevlc->lconn_next = tmplc->lconn_next; } if ( ld->ld_defconn == lc ) { ld->ld_defconn = NULL; } break; } prevlc = tmplc; } /* process connection callbacks */ { struct ldapoptions *lo; ldaplist *ll; ldap_conncb *cb; lo = &ld->ld_options; LDAP_MUTEX_LOCK( &lo->ldo_mutex ); if ( lo->ldo_conn_cbs ) { for ( ll=lo->ldo_conn_cbs; ll; ll=ll->ll_next ) { cb = ll->ll_data; cb->lc_del( ld, lc->lconn_sb, cb ); } } LDAP_MUTEX_UNLOCK( &lo->ldo_mutex ); lo = LDAP_INT_GLOBAL_OPT(); LDAP_MUTEX_LOCK( &lo->ldo_mutex ); if ( lo->ldo_conn_cbs ) { for ( ll=lo->ldo_conn_cbs; ll; ll=ll->ll_next ) { cb = ll->ll_data; cb->lc_del( ld, lc->lconn_sb, cb ); } } LDAP_MUTEX_UNLOCK( &lo->ldo_mutex ); } if ( lc->lconn_status == LDAP_CONNST_CONNECTED ) { ldap_mark_select_clear( ld, lc->lconn_sb ); if ( unbind ) { ldap_send_unbind( ld, lc->lconn_sb, NULL, NULL ); } } if ( lc->lconn_ber != NULL ) { ber_free( lc->lconn_ber, 1 ); } ldap_int_sasl_close( ld, lc ); #ifdef HAVE_GSSAPI ldap_int_gssapi_close( ld, lc ); #endif ldap_free_urllist( lc->lconn_server ); /* FIXME: is this at all possible? * ldap_ld_free() in unbind.c calls ldap_free_connection() * with force == 1 __after__ explicitly calling * ldap_free_request() on all requests */ if ( force ) { LDAPRequest *lr; for ( lr = ld->ld_requests; lr; ) { LDAPRequest *lr_next = lr->lr_next; if ( lr->lr_conn == lc ) { ldap_free_request_int( ld, lr ); } lr = lr_next; } } if ( lc->lconn_sb != ld->ld_sb ) { ber_sockbuf_free( lc->lconn_sb ); } else { ber_int_sb_close( lc->lconn_sb ); } if ( lc->lconn_rebind_queue != NULL) { int i; for( i = 0; lc->lconn_rebind_queue[i] != NULL; i++ ) { LDAP_VFREE( lc->lconn_rebind_queue[i] ); } LDAP_FREE( lc->lconn_rebind_queue ); } LDAP_FREE( lc ); Debug( LDAP_DEBUG_TRACE, "ldap_free_connection: actually freed\n", 0, 0, 0 ); } else { lc->lconn_lastused = time( NULL ); Debug( LDAP_DEBUG_TRACE, "ldap_free_connection: refcnt %d\n", lc->lconn_refcnt, 0, 0 ); } } /* Protects self with ld_conn_mutex */ #ifdef LDAP_DEBUG void ldap_dump_connection( LDAP *ld, LDAPConn *lconns, int all ) { LDAPConn *lc; char timebuf[32]; Debug( LDAP_DEBUG_TRACE, "** ld %p Connection%s:\n", (void *)ld, all ? "s" : "", 0 ); LDAP_MUTEX_LOCK( &ld->ld_conn_mutex ); for ( lc = lconns; lc != NULL; lc = lc->lconn_next ) { if ( lc->lconn_server != NULL ) { Debug( LDAP_DEBUG_TRACE, "* host: %s port: %d%s\n", ( lc->lconn_server->lud_host == NULL ) ? "(null)" : lc->lconn_server->lud_host, lc->lconn_server->lud_port, ( lc->lconn_sb == ld->ld_sb ) ? " (default)" : "" ); } Debug( LDAP_DEBUG_TRACE, " refcnt: %d status: %s\n", lc->lconn_refcnt, ( lc->lconn_status == LDAP_CONNST_NEEDSOCKET ) ? "NeedSocket" : ( lc->lconn_status == LDAP_CONNST_CONNECTING ) ? "Connecting" : "Connected", 0 ); Debug( LDAP_DEBUG_TRACE, " last used: %s%s\n", ldap_pvt_ctime( &lc->lconn_lastused, timebuf ), lc->lconn_rebind_inprogress ? " rebind in progress" : "", 0 ); if ( lc->lconn_rebind_inprogress ) { if ( lc->lconn_rebind_queue != NULL) { int i; for ( i = 0; lc->lconn_rebind_queue[i] != NULL; i++ ) { int j; for( j = 0; lc->lconn_rebind_queue[i][j] != 0; j++ ) { Debug( LDAP_DEBUG_TRACE, " queue %d entry %d - %s\n", i, j, lc->lconn_rebind_queue[i][j] ); } } } else { Debug( LDAP_DEBUG_TRACE, " queue is empty\n", 0, 0, 0 ); } } Debug( LDAP_DEBUG_TRACE, "\n", 0, 0, 0 ); if ( !all ) { break; } } LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); } /* protected by req_mutex and res_mutex */ void ldap_dump_requests_and_responses( LDAP *ld ) { LDAPRequest *lr; LDAPMessage *lm, *l; int i; Debug( LDAP_DEBUG_TRACE, "** ld %p Outstanding Requests:\n", (void *)ld, 0, 0 ); lr = ld->ld_requests; if ( lr == NULL ) { Debug( LDAP_DEBUG_TRACE, " Empty\n", 0, 0, 0 ); } for ( i = 0; lr != NULL; lr = lr->lr_next, i++ ) { Debug( LDAP_DEBUG_TRACE, " * msgid %d, origid %d, status %s\n", lr->lr_msgid, lr->lr_origid, ( lr->lr_status == LDAP_REQST_INPROGRESS ) ? "InProgress" : ( lr->lr_status == LDAP_REQST_CHASINGREFS ) ? "ChasingRefs" : ( lr->lr_status == LDAP_REQST_NOTCONNECTED ) ? "NotConnected" : ( lr->lr_status == LDAP_REQST_WRITING ) ? "Writing" : ( lr->lr_status == LDAP_REQST_COMPLETED ) ? "RequestCompleted" : "InvalidStatus" ); Debug( LDAP_DEBUG_TRACE, " outstanding referrals %d, parent count %d\n", lr->lr_outrefcnt, lr->lr_parentcnt, 0 ); } Debug( LDAP_DEBUG_TRACE, " ld %p request count %d (abandoned %lu)\n", (void *)ld, i, ld->ld_nabandoned ); Debug( LDAP_DEBUG_TRACE, "** ld %p Response Queue:\n", (void *)ld, 0, 0 ); if ( ( lm = ld->ld_responses ) == NULL ) { Debug( LDAP_DEBUG_TRACE, " Empty\n", 0, 0, 0 ); } for ( i = 0; lm != NULL; lm = lm->lm_next, i++ ) { Debug( LDAP_DEBUG_TRACE, " * msgid %d, type %lu\n", lm->lm_msgid, (unsigned long)lm->lm_msgtype, 0 ); if ( lm->lm_chain != NULL ) { Debug( LDAP_DEBUG_TRACE, " chained responses:\n", 0, 0, 0 ); for ( l = lm->lm_chain; l != NULL; l = l->lm_chain ) { Debug( LDAP_DEBUG_TRACE, " * msgid %d, type %lu\n", l->lm_msgid, (unsigned long)l->lm_msgtype, 0 ); } } } Debug( LDAP_DEBUG_TRACE, " ld %p response count %d\n", (void *)ld, i, 0 ); } #endif /* LDAP_DEBUG */ /* protected by req_mutex */ static void ldap_free_request_int( LDAP *ld, LDAPRequest *lr ) { LDAP_ASSERT_MUTEX_OWNER( &ld->ld_req_mutex ); /* if lr_refcnt > 0, the request has been looked up * by ldap_find_request_by_msgid(); if in the meanwhile * the request is free()'d by someone else, just decrease * the reference count and extract it from the request * list; later on, it will be freed. */ if ( lr->lr_prev == NULL ) { if ( lr->lr_refcnt == 0 ) { /* free'ing the first request? */ assert( ld->ld_requests == lr ); } if ( ld->ld_requests == lr ) { ld->ld_requests = lr->lr_next; } } else { lr->lr_prev->lr_next = lr->lr_next; } if ( lr->lr_next != NULL ) { lr->lr_next->lr_prev = lr->lr_prev; } if ( lr->lr_refcnt > 0 ) { lr->lr_refcnt = -lr->lr_refcnt; lr->lr_prev = NULL; lr->lr_next = NULL; return; } if ( lr->lr_ber != NULL ) { ber_free( lr->lr_ber, 1 ); lr->lr_ber = NULL; } if ( lr->lr_res_error != NULL ) { LDAP_FREE( lr->lr_res_error ); lr->lr_res_error = NULL; } if ( lr->lr_res_matched != NULL ) { LDAP_FREE( lr->lr_res_matched ); lr->lr_res_matched = NULL; } LDAP_FREE( lr ); } /* protected by req_mutex */ void ldap_free_request( LDAP *ld, LDAPRequest *lr ) { LDAP_ASSERT_MUTEX_OWNER( &ld->ld_req_mutex ); Debug( LDAP_DEBUG_TRACE, "ldap_free_request (origid %d, msgid %d)\n", lr->lr_origid, lr->lr_msgid, 0 ); /* free all referrals (child requests) */ while ( lr->lr_child ) { ldap_free_request( ld, lr->lr_child ); } if ( lr->lr_parent != NULL ) { LDAPRequest **lrp; --lr->lr_parent->lr_outrefcnt; for ( lrp = &lr->lr_parent->lr_child; *lrp && *lrp != lr; lrp = &(*lrp)->lr_refnext ); if ( *lrp == lr ) { *lrp = lr->lr_refnext; } } ldap_free_request_int( ld, lr ); } /* * call first time with *cntp = -1 * when returns *cntp == -1, no referrals are left * * NOTE: may replace *refsp, or shuffle the contents * of the original array. */ static int ldap_int_nextref( LDAP *ld, char ***refsp, int *cntp, void *params ) { assert( refsp != NULL ); assert( *refsp != NULL ); assert( cntp != NULL ); if ( *cntp < -1 ) { *cntp = -1; return -1; } (*cntp)++; if ( (*refsp)[ *cntp ] == NULL ) { *cntp = -1; } return 0; } /* * Chase v3 referrals * * Parameters: * (IN) ld = LDAP connection handle * (IN) lr = LDAP Request structure * (IN) refs = array of pointers to referral strings that we will chase * The array will be free'd by this function when no longer needed * (IN) sref != 0 if following search reference * (OUT) errstrp = Place to return a string of referrals which could not be followed * (OUT) hadrefp = 1 if sucessfully followed referral * * Return value - number of referrals followed * * Protected by res_mutex, conn_mutex and req_mutex (try_read1msg) */ int ldap_chase_v3referrals( LDAP *ld, LDAPRequest *lr, char **refs, int sref, char **errstrp, int *hadrefp ) { char *unfollowed; int unfollowedcnt = 0; LDAPRequest *origreq; LDAPURLDesc *srv = NULL; BerElement *ber; char **refarray = NULL; LDAPConn *lc; int rc, count, i, j, id; LDAPreqinfo rinfo; LDAP_NEXTREF_PROC *nextref_proc = ld->ld_nextref_proc ? ld->ld_nextref_proc : ldap_int_nextref; LDAP_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex ); LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex ); LDAP_ASSERT_MUTEX_OWNER( &ld->ld_req_mutex ); Debug( LDAP_DEBUG_TRACE, "ldap_chase_v3referrals\n", 0, 0, 0 ); ld->ld_errno = LDAP_SUCCESS; /* optimistic */ *hadrefp = 0; unfollowed = NULL; rc = count = 0; /* If no referrals in array, return */ if ( (refs == NULL) || ( (refs)[0] == NULL) ) { rc = 0; goto done; } /* Check for hop limit exceeded */ if ( lr->lr_parentcnt >= ld->ld_refhoplimit ) { Debug( LDAP_DEBUG_ANY, "more than %d referral hops (dropping)\n", ld->ld_refhoplimit, 0, 0 ); ld->ld_errno = LDAP_REFERRAL_LIMIT_EXCEEDED; rc = -1; goto done; } /* find original request */ for ( origreq = lr; origreq->lr_parent != NULL; origreq = origreq->lr_parent ) { /* empty */ ; } refarray = refs; refs = NULL; /* parse out & follow referrals */ /* NOTE: if nextref_proc == ldap_int_nextref, params is ignored */ i = -1; for ( nextref_proc( ld, &refarray, &i, ld->ld_nextref_params ); i != -1; nextref_proc( ld, &refarray, &i, ld->ld_nextref_params ) ) { /* Parse the referral URL */ rc = ldap_url_parse_ext( refarray[i], &srv, LDAP_PVT_URL_PARSE_NOEMPTY_DN ); if ( rc != LDAP_URL_SUCCESS ) { /* ldap_url_parse_ext() returns LDAP_URL_* errors * which do not map on API errors */ ld->ld_errno = LDAP_PARAM_ERROR; rc = -1; goto done; } if( srv->lud_crit_exts ) { int ok = 0; #ifdef HAVE_TLS /* If StartTLS is the only critical ext, OK. */ if ( find_tls_ext( srv ) == 2 && srv->lud_crit_exts == 1 ) ok = 1; #endif if ( !ok ) { /* we do not support any other extensions */ ld->ld_errno = LDAP_NOT_SUPPORTED; rc = -1; goto done; } } /* check connection for re-bind in progress */ if (( lc = find_connection( ld, srv, 1 )) != NULL ) { /* See if we've already requested this DN with this conn */ LDAPRequest *lp; int looped = 0; ber_len_t len = srv->lud_dn ? strlen( srv->lud_dn ) : 0; for ( lp = origreq; lp; ) { if ( lp->lr_conn == lc && len == lp->lr_dn.bv_len && len && strncmp( srv->lud_dn, lp->lr_dn.bv_val, len ) == 0 ) { looped = 1; break; } if ( lp == origreq ) { lp = lp->lr_child; } else { lp = lp->lr_refnext; } } if ( looped ) { ldap_free_urllist( srv ); srv = NULL; ld->ld_errno = LDAP_CLIENT_LOOP; rc = -1; continue; } if ( lc->lconn_rebind_inprogress ) { /* We are already chasing a referral or search reference and a * bind on that connection is in progress. We must queue * referrals on that connection, so we don't get a request * going out before the bind operation completes. This happens * if two search references come in one behind the other * for the same server with different contexts. */ Debug( LDAP_DEBUG_TRACE, "ldap_chase_v3referrals: queue referral \"%s\"\n", refarray[i], 0, 0); if( lc->lconn_rebind_queue == NULL ) { /* Create a referral list */ lc->lconn_rebind_queue = (char ***) LDAP_MALLOC( sizeof(void *) * 2); if( lc->lconn_rebind_queue == NULL) { ld->ld_errno = LDAP_NO_MEMORY; rc = -1; goto done; } lc->lconn_rebind_queue[0] = refarray; lc->lconn_rebind_queue[1] = NULL; refarray = NULL; } else { /* Count how many referral arrays we already have */ for( j = 0; lc->lconn_rebind_queue[j] != NULL; j++) { /* empty */; } /* Add the new referral to the list */ lc->lconn_rebind_queue = (char ***) LDAP_REALLOC( lc->lconn_rebind_queue, sizeof(void *) * (j + 2)); if( lc->lconn_rebind_queue == NULL ) { ld->ld_errno = LDAP_NO_MEMORY; rc = -1; goto done; } lc->lconn_rebind_queue[j] = refarray; lc->lconn_rebind_queue[j+1] = NULL; refarray = NULL; } /* We have queued the referral/reference, now just return */ rc = 0; *hadrefp = 1; count = 1; /* Pretend we already followed referral */ goto done; } } /* Re-encode the request with the new starting point of the search. * Note: In the future we also need to replace the filter if one * was provided with the search reference */ /* For references we don't want old dn if new dn empty */ if ( sref && srv->lud_dn == NULL ) { srv->lud_dn = LDAP_STRDUP( "" ); } LDAP_NEXT_MSGID( ld, id ); ber = re_encode_request( ld, origreq->lr_ber, id, sref, srv, &rinfo.ri_request ); if( ber == NULL ) { ld->ld_errno = LDAP_ENCODING_ERROR; rc = -1; goto done; } Debug( LDAP_DEBUG_TRACE, "ldap_chase_v3referral: msgid %d, url \"%s\"\n", lr->lr_msgid, refarray[i], 0); /* Send the new request to the server - may require a bind */ rinfo.ri_msgid = origreq->lr_origid; rinfo.ri_url = refarray[i]; rc = ldap_send_server_request( ld, ber, id, origreq, &srv, NULL, &rinfo, 0, 1 ); if ( rc < 0 ) { /* Failure, try next referral in the list */ Debug( LDAP_DEBUG_ANY, "Unable to chase referral \"%s\" (%d: %s)\n", refarray[i], ld->ld_errno, ldap_err2string( ld->ld_errno ) ); unfollowedcnt += ldap_append_referral( ld, &unfollowed, refarray[i] ); ldap_free_urllist( srv ); srv = NULL; ld->ld_errno = LDAP_REFERRAL; } else { /* Success, no need to try this referral list further */ rc = 0; ++count; *hadrefp = 1; /* check if there is a queue of referrals that came in during bind */ if ( lc == NULL) { lc = find_connection( ld, srv, 1 ); if ( lc == NULL ) { ld->ld_errno = LDAP_OPERATIONS_ERROR; rc = -1; LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); goto done; } } if ( lc->lconn_rebind_queue != NULL ) { /* Release resources of previous list */ LDAP_VFREE( refarray ); refarray = NULL; ldap_free_urllist( srv ); srv = NULL; /* Pull entries off end of queue so list always null terminated */ for( j = 0; lc->lconn_rebind_queue[j] != NULL; j++ ) ; refarray = lc->lconn_rebind_queue[j - 1]; lc->lconn_rebind_queue[j-1] = NULL; /* we pulled off last entry from queue, free queue */ if ( j == 1 ) { LDAP_FREE( lc->lconn_rebind_queue ); lc->lconn_rebind_queue = NULL; } /* restart the loop the with new referral list */ i = -1; continue; } break; /* referral followed, break out of for loop */ } } /* end for loop */ done: LDAP_VFREE( refarray ); ldap_free_urllist( srv ); LDAP_FREE( *errstrp ); if( rc == 0 ) { *errstrp = NULL; LDAP_FREE( unfollowed ); return count; } else { *errstrp = unfollowed; return rc; } } /* * XXX merging of errors in this routine needs to be improved * Protected by res_mutex, conn_mutex and req_mutex (try_read1msg) */ int ldap_chase_referrals( LDAP *ld, LDAPRequest *lr, char **errstrp, int sref, int *hadrefp ) { int rc, count, id; unsigned len; char *p, *ref, *unfollowed; LDAPRequest *origreq; LDAPURLDesc *srv; BerElement *ber; LDAPreqinfo rinfo; LDAPConn *lc; LDAP_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex ); LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex ); LDAP_ASSERT_MUTEX_OWNER( &ld->ld_req_mutex ); Debug( LDAP_DEBUG_TRACE, "ldap_chase_referrals\n", 0, 0, 0 ); ld->ld_errno = LDAP_SUCCESS; /* optimistic */ *hadrefp = 0; if ( *errstrp == NULL ) { return( 0 ); } len = strlen( *errstrp ); for ( p = *errstrp; len >= LDAP_REF_STR_LEN; ++p, --len ) { if ( strncasecmp( p, LDAP_REF_STR, LDAP_REF_STR_LEN ) == 0 ) { *p = '\0'; p += LDAP_REF_STR_LEN; break; } } if ( len < LDAP_REF_STR_LEN ) { return( 0 ); } if ( lr->lr_parentcnt >= ld->ld_refhoplimit ) { Debug( LDAP_DEBUG_ANY, "more than %d referral hops (dropping)\n", ld->ld_refhoplimit, 0, 0 ); /* XXX report as error in ld->ld_errno? */ return( 0 ); } /* find original request */ for ( origreq = lr; origreq->lr_parent != NULL; origreq = origreq->lr_parent ) { /* empty */; } unfollowed = NULL; rc = count = 0; /* parse out & follow referrals */ for ( ref = p; rc == 0 && ref != NULL; ref = p ) { p = strchr( ref, '\n' ); if ( p != NULL ) { *p++ = '\0'; } rc = ldap_url_parse_ext( ref, &srv, LDAP_PVT_URL_PARSE_NOEMPTY_DN ); if ( rc != LDAP_URL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "ignoring %s referral <%s>\n", ref, rc == LDAP_URL_ERR_BADSCHEME ? "unknown" : "incorrect", 0 ); rc = ldap_append_referral( ld, &unfollowed, ref ); *hadrefp = 1; continue; } Debug( LDAP_DEBUG_TRACE, "chasing LDAP referral: <%s>\n", ref, 0, 0 ); *hadrefp = 1; /* See if we've already been here */ if (( lc = find_connection( ld, srv, 1 )) != NULL ) { LDAPRequest *lp; int looped = 0; ber_len_t len = srv->lud_dn ? strlen( srv->lud_dn ) : 0; for ( lp = lr; lp; lp = lp->lr_parent ) { if ( lp->lr_conn == lc && len == lp->lr_dn.bv_len ) { if ( len && strncmp( srv->lud_dn, lp->lr_dn.bv_val, len ) ) continue; looped = 1; break; } } if ( looped ) { ldap_free_urllist( srv ); ld->ld_errno = LDAP_CLIENT_LOOP; rc = -1; continue; } } LDAP_NEXT_MSGID( ld, id ); ber = re_encode_request( ld, origreq->lr_ber, id, sref, srv, &rinfo.ri_request ); if ( ber == NULL ) { ldap_free_urllist( srv ); return -1 ; } /* copy the complete referral for rebind process */ rinfo.ri_url = LDAP_STRDUP( ref ); rinfo.ri_msgid = origreq->lr_origid; rc = ldap_send_server_request( ld, ber, id, lr, &srv, NULL, &rinfo, 0, 1 ); LDAP_FREE( rinfo.ri_url ); if( rc >= 0 ) { ++count; } else { Debug( LDAP_DEBUG_ANY, "Unable to chase referral \"%s\" (%d: %s)\n", ref, ld->ld_errno, ldap_err2string( ld->ld_errno ) ); rc = ldap_append_referral( ld, &unfollowed, ref ); } ldap_free_urllist(srv); } LDAP_FREE( *errstrp ); *errstrp = unfollowed; return(( rc == 0 ) ? count : rc ); } int ldap_append_referral( LDAP *ld, char **referralsp, char *s ) { int first; if ( *referralsp == NULL ) { first = 1; *referralsp = (char *)LDAP_MALLOC( strlen( s ) + LDAP_REF_STR_LEN + 1 ); } else { first = 0; *referralsp = (char *)LDAP_REALLOC( *referralsp, strlen( *referralsp ) + strlen( s ) + 2 ); } if ( *referralsp == NULL ) { ld->ld_errno = LDAP_NO_MEMORY; return( -1 ); } if ( first ) { strcpy( *referralsp, LDAP_REF_STR ); } else { strcat( *referralsp, "\n" ); } strcat( *referralsp, s ); return( 0 ); } static BerElement * re_encode_request( LDAP *ld, BerElement *origber, ber_int_t msgid, int sref, LDAPURLDesc *srv, int *type ) { /* * XXX this routine knows way too much about how the lber library works! */ ber_int_t along; ber_tag_t tag; ber_tag_t rtag; ber_int_t ver; ber_int_t scope; int rc; BerElement tmpber, *ber; struct berval dn; Debug( LDAP_DEBUG_TRACE, "re_encode_request: new msgid %ld, new dn <%s>\n", (long) msgid, ( srv == NULL || srv->lud_dn == NULL) ? "NONE" : srv->lud_dn, 0 ); tmpber = *origber; /* * all LDAP requests are sequences that start with a message id. * For all except delete, this is followed by a sequence that is * tagged with the operation code. For delete, the provided DN * is not wrapped by a sequence. */ rtag = ber_scanf( &tmpber, "{it", /*}*/ &along, &tag ); if ( rtag == LBER_ERROR ) { ld->ld_errno = LDAP_DECODING_ERROR; return( NULL ); } assert( tag != 0); if ( tag == LDAP_REQ_BIND ) { /* bind requests have a version number before the DN & other stuff */ rtag = ber_scanf( &tmpber, "{im" /*}*/, &ver, &dn ); } else if ( tag == LDAP_REQ_DELETE ) { /* delete requests don't have a DN wrapping sequence */ rtag = ber_scanf( &tmpber, "m", &dn ); } else if ( tag == LDAP_REQ_SEARCH ) { /* search requests need to be re-scope-ed */ rtag = ber_scanf( &tmpber, "{me" /*"}"*/, &dn, &scope ); if( srv->lud_scope != LDAP_SCOPE_DEFAULT ) { /* use the scope provided in reference */ scope = srv->lud_scope; } else if ( sref ) { /* use scope implied by previous operation * base -> base * one -> base * subtree -> subtree * subordinate -> subtree */ switch( scope ) { default: case LDAP_SCOPE_BASE: case LDAP_SCOPE_ONELEVEL: scope = LDAP_SCOPE_BASE; break; case LDAP_SCOPE_SUBTREE: case LDAP_SCOPE_SUBORDINATE: scope = LDAP_SCOPE_SUBTREE; break; } } } else { rtag = ber_scanf( &tmpber, "{m" /*}*/, &dn ); } if( rtag == LBER_ERROR ) { ld->ld_errno = LDAP_DECODING_ERROR; return NULL; } /* restore character zero'd out by ber_scanf*/ dn.bv_val[dn.bv_len] = tmpber.ber_tag; if (( ber = ldap_alloc_ber_with_options( ld )) == NULL ) { return NULL; } if ( srv->lud_dn ) { ber_str2bv( srv->lud_dn, 0, 0, &dn ); } if ( tag == LDAP_REQ_BIND ) { rc = ber_printf( ber, "{it{iO" /*}}*/, msgid, tag, ver, &dn ); } else if ( tag == LDAP_REQ_DELETE ) { rc = ber_printf( ber, "{itON}", msgid, tag, &dn ); } else if ( tag == LDAP_REQ_SEARCH ) { rc = ber_printf( ber, "{it{Oe" /*}}*/, msgid, tag, &dn, scope ); } else { rc = ber_printf( ber, "{it{O" /*}}*/, msgid, tag, &dn ); } if ( rc == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return NULL; } if ( tag != LDAP_REQ_DELETE && ( ber_write(ber, tmpber.ber_ptr, ( tmpber.ber_end - tmpber.ber_ptr ), 0) != ( tmpber.ber_end - tmpber.ber_ptr ) || ber_printf( ber, /*{{*/ "N}N}" ) == -1 ) ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return NULL; } #ifdef LDAP_DEBUG if ( ldap_debug & LDAP_DEBUG_PACKETS ) { Debug( LDAP_DEBUG_ANY, "re_encode_request new request is:\n", 0, 0, 0 ); ber_log_dump( LDAP_DEBUG_BER, ldap_debug, ber, 0 ); } #endif /* LDAP_DEBUG */ *type = tag; /* return request type */ return ber; } /* protected by req_mutex */ LDAPRequest * ldap_find_request_by_msgid( LDAP *ld, ber_int_t msgid ) { LDAPRequest *lr; for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) { if ( lr->lr_status == LDAP_REQST_COMPLETED ) { continue; /* Skip completed requests */ } if ( msgid == lr->lr_msgid ) { lr->lr_refcnt++; break; } } return( lr ); } /* protected by req_mutex */ void ldap_return_request( LDAP *ld, LDAPRequest *lrx, int freeit ) { LDAPRequest *lr; for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) { if ( lr == lrx ) { if ( lr->lr_refcnt > 0 ) { lr->lr_refcnt--; } else if ( lr->lr_refcnt < 0 ) { lr->lr_refcnt++; if ( lr->lr_refcnt == 0 ) { lr = NULL; } } break; } } if ( lr == NULL ) { ldap_free_request_int( ld, lrx ); } else if ( freeit ) { ldap_free_request( ld, lrx ); } } openldap-2.4.42+dfsg/libraries/libldap/stctrl.c0000644000175000017500000001366212563404150020102 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * Portions Copyright 2007 Pierangelo Masarati. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* ACKNOWLEDGEMENTS: * This work was developed by Pierangelo Masarati for inclusion in * OpenLDAP Software. */ #include "portable.h" #include #include #include #include #include "ldap-int.h" #ifdef LDAP_CONTROL_X_SESSION_TRACKING /* * Client-side of */ int ldap_create_session_tracking_value( LDAP *ld, char *sessionSourceIp, char *sessionSourceName, char *formatOID, struct berval *sessionTrackingIdentifier, struct berval *value ) { BerElement *ber = NULL; ber_tag_t tag; struct berval ip, name, oid, id; if ( ld == NULL || formatOID == NULL || value == NULL ) { param_error:; if ( ld ) { ld->ld_errno = LDAP_PARAM_ERROR; } return LDAP_PARAM_ERROR; } assert( LDAP_VALID( ld ) ); ld->ld_errno = LDAP_SUCCESS; /* check sizes according to I.D. */ if ( sessionSourceIp == NULL ) { BER_BVSTR( &ip, "" ); } else { ber_str2bv( sessionSourceIp, 0, 0, &ip ); /* NOTE: we're strict because we don't want * to send out bad data */ if ( ip.bv_len > 128 ) goto param_error; } if ( sessionSourceName == NULL ) { BER_BVSTR( &name, "" ); } else { ber_str2bv( sessionSourceName, 0, 0, &name ); /* NOTE: we're strict because we don't want * to send out bad data */ if ( name.bv_len > 65536 ) goto param_error; } ber_str2bv( formatOID, 0, 0, &oid ); /* NOTE: we're strict because we don't want * to send out bad data */ if ( oid.bv_len > 1024 ) goto param_error; if ( sessionTrackingIdentifier == NULL || sessionTrackingIdentifier->bv_val == NULL ) { BER_BVSTR( &id, "" ); } else { id = *sessionTrackingIdentifier; } /* prepare value */ value->bv_val = NULL; value->bv_len = 0; ber = ldap_alloc_ber_with_options( ld ); if ( ber == NULL ) { ld->ld_errno = LDAP_NO_MEMORY; return ld->ld_errno; } tag = ber_printf( ber, "{OOOO}", &ip, &name, &oid, &id ); if ( tag == LBER_ERROR ) { ld->ld_errno = LDAP_ENCODING_ERROR; goto done; } if ( ber_flatten2( ber, value, 1 ) == -1 ) { ld->ld_errno = LDAP_NO_MEMORY; } done:; if ( ber != NULL ) { ber_free( ber, 1 ); } return ld->ld_errno; } /* * NOTE: this API is bad; it could be much more efficient... */ int ldap_create_session_tracking_control( LDAP *ld, char *sessionSourceIp, char *sessionSourceName, char *formatOID, struct berval *sessionTrackingIdentifier, LDAPControl **ctrlp ) { struct berval value; if ( ctrlp == NULL ) { ld->ld_errno = LDAP_PARAM_ERROR; return ld->ld_errno; } ld->ld_errno = ldap_create_session_tracking_value( ld, sessionSourceIp, sessionSourceName, formatOID, sessionTrackingIdentifier, &value ); if ( ld->ld_errno == LDAP_SUCCESS ) { ld->ld_errno = ldap_control_create( LDAP_CONTROL_X_SESSION_TRACKING, 0, &value, 0, ctrlp ); if ( ld->ld_errno != LDAP_SUCCESS ) { LDAP_FREE( value.bv_val ); } } return ld->ld_errno; } int ldap_parse_session_tracking_control( LDAP *ld, LDAPControl *ctrl, struct berval *ip, struct berval *name, struct berval *oid, struct berval *id ) { BerElement *ber; ber_tag_t tag; ber_len_t len; if ( ld == NULL || ctrl == NULL || ip == NULL || name == NULL || oid == NULL || id == NULL ) { if ( ld ) { ld->ld_errno = LDAP_PARAM_ERROR; } /* NOTE: we want the caller to get all or nothing; * we could allow some of the pointers to be NULL, * if one does not want part of the data */ return LDAP_PARAM_ERROR; } BER_BVZERO( ip ); BER_BVZERO( name ); BER_BVZERO( oid ); BER_BVZERO( id ); ber = ber_init( &ctrl->ldctl_value ); if ( ber == NULL ) { ld->ld_errno = LDAP_NO_MEMORY; return ld->ld_errno; } tag = ber_skip_tag( ber, &len ); if ( tag != LBER_SEQUENCE ) { tag = LBER_ERROR; goto error; } /* sessionSourceIp */ tag = ber_peek_tag( ber, &len ); if ( tag == LBER_DEFAULT ) { tag = LBER_ERROR; goto error; } if ( len == 0 ) { tag = ber_skip_tag( ber, &len ); } else { if ( len > 128 ) { /* should be LDAP_DECODING_ERROR, * but we're liberal in what we accept */ } tag = ber_scanf( ber, "o", ip ); } /* sessionSourceName */ tag = ber_peek_tag( ber, &len ); if ( tag == LBER_DEFAULT ) { tag = LBER_ERROR; goto error; } if ( len == 0 ) { tag = ber_skip_tag( ber, &len ); } else { if ( len > 65536 ) { /* should be LDAP_DECODING_ERROR, * but we're liberal in what we accept */ } tag = ber_scanf( ber, "o", name ); } /* formatOID */ tag = ber_peek_tag( ber, &len ); if ( tag == LBER_DEFAULT ) { tag = LBER_ERROR; goto error; } if ( len == 0 ) { ld->ld_errno = LDAP_DECODING_ERROR; goto error; } else { if ( len > 1024 ) { /* should be LDAP_DECODING_ERROR, * but we're liberal in what we accept */ } tag = ber_scanf( ber, "o", oid ); } /* FIXME: should check if it is an OID... leave it to the caller */ /* sessionTrackingIdentifier */ tag = ber_peek_tag( ber, &len ); if ( tag == LBER_DEFAULT ) { tag = LBER_ERROR; goto error; } if ( len == 0 ) { tag = ber_skip_tag( ber, &len ); } else { #if 0 if ( len > 65536 ) { /* should be LDAP_DECODING_ERROR, * but we're liberal in what we accept */ } #endif tag = ber_scanf( ber, "o", id ); } /* closure */ tag = ber_skip_tag( ber, &len ); if ( tag == LBER_DEFAULT && len == 0 ) { tag = 0; } error:; (void)ber_free( ber, 1 ); if ( tag == LBER_ERROR ) { return LDAP_DECODING_ERROR; } return ld->ld_errno; } #endif /* LDAP_CONTROL_X_SESSION_TRACKING */ openldap-2.4.42+dfsg/libraries/libldap/abandon.c0000644000175000017500000002176312563404150020172 0ustar ryanryan/* abandon.c */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (c) 1990 Regents of the University of Michigan. * All rights reserved. */ #include "portable.h" #include #include #include #include #include #include "ldap-int.h" /* * An abandon request looks like this: * AbandonRequest ::= [APPLICATION 16] MessageID * and has no response. (Source: RFC 4511) */ #include "lutil.h" static int do_abandon( LDAP *ld, ber_int_t origid, ber_int_t msgid, LDAPControl **sctrls, int sendabandon ); /* * ldap_abandon_ext - perform an ldap extended abandon operation. * * Parameters: * ld LDAP descriptor * msgid The message id of the operation to abandon * scntrls Server Controls * ccntrls Client Controls * * ldap_abandon_ext returns a LDAP error code. * (LDAP_SUCCESS if everything went ok) * * Example: * ldap_abandon_ext( ld, msgid, scntrls, ccntrls ); */ int ldap_abandon_ext( LDAP *ld, int msgid, LDAPControl **sctrls, LDAPControl **cctrls ) { int rc; Debug( LDAP_DEBUG_TRACE, "ldap_abandon_ext %d\n", msgid, 0, 0 ); /* check client controls */ LDAP_MUTEX_LOCK( &ld->ld_req_mutex ); rc = ldap_int_client_controls( ld, cctrls ); if ( rc == LDAP_SUCCESS ) { rc = do_abandon( ld, msgid, msgid, sctrls, 1 ); } LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex ); return rc; } /* * ldap_abandon - perform an ldap abandon operation. Parameters: * * ld LDAP descriptor * msgid The message id of the operation to abandon * * ldap_abandon returns 0 if everything went ok, -1 otherwise. * * Example: * ldap_abandon( ld, msgid ); */ int ldap_abandon( LDAP *ld, int msgid ) { Debug( LDAP_DEBUG_TRACE, "ldap_abandon %d\n", msgid, 0, 0 ); return ldap_abandon_ext( ld, msgid, NULL, NULL ) == LDAP_SUCCESS ? 0 : -1; } int ldap_pvt_discard( LDAP *ld, ber_int_t msgid ) { int rc; LDAP_MUTEX_LOCK( &ld->ld_req_mutex ); rc = do_abandon( ld, msgid, msgid, NULL, 0 ); LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex ); return rc; } static int do_abandon( LDAP *ld, ber_int_t origid, ber_int_t msgid, LDAPControl **sctrls, int sendabandon ) { BerElement *ber; int i, err; Sockbuf *sb; LDAPRequest *lr; Debug( LDAP_DEBUG_TRACE, "do_abandon origid %d, msgid %d\n", origid, msgid, 0 ); /* find the request that we are abandoning */ start_again:; lr = ld->ld_requests; while ( lr != NULL ) { /* this message */ if ( lr->lr_msgid == msgid ) { break; } /* child: abandon it */ if ( lr->lr_origid == msgid && !lr->lr_abandoned ) { (void)do_abandon( ld, lr->lr_origid, lr->lr_msgid, sctrls, sendabandon ); /* restart, as lr may now be dangling... */ goto start_again; } lr = lr->lr_next; } if ( lr != NULL ) { if ( origid == msgid && lr->lr_parent != NULL ) { /* don't let caller abandon child requests! */ ld->ld_errno = LDAP_PARAM_ERROR; return( LDAP_PARAM_ERROR ); } if ( lr->lr_status != LDAP_REQST_INPROGRESS ) { /* no need to send abandon message */ sendabandon = 0; } } /* ldap_msgdelete locks the res_mutex. Give up the req_mutex * while we're in there. */ LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex ); err = ldap_msgdelete( ld, msgid ); LDAP_MUTEX_LOCK( &ld->ld_req_mutex ); if ( err == 0 ) { ld->ld_errno = LDAP_SUCCESS; return LDAP_SUCCESS; } /* fetch again the request that we are abandoning */ if ( lr != NULL ) { for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) { /* this message */ if ( lr->lr_msgid == msgid ) { break; } } } err = 0; if ( sendabandon ) { if ( ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, NULL ) == -1 ) { /* not connected */ err = -1; ld->ld_errno = LDAP_SERVER_DOWN; } else if ( ( ber = ldap_alloc_ber_with_options( ld ) ) == NULL ) { /* BER element allocation failed */ err = -1; ld->ld_errno = LDAP_NO_MEMORY; } else { /* * We already have the mutex in LDAP_R_COMPILE, so * don't try to get it again. * LDAP_NEXT_MSGID(ld, i); */ LDAP_NEXT_MSGID(ld, i); #ifdef LDAP_CONNECTIONLESS if ( LDAP_IS_UDP(ld) ) { struct sockaddr_storage sa = {0}; /* dummy, filled with ldo_peer in request.c */ err = ber_write( ber, (char *) &sa, sizeof(sa), 0 ); } if ( LDAP_IS_UDP(ld) && ld->ld_options.ldo_version == LDAP_VERSION2 ) { char *dn; LDAP_MUTEX_LOCK( &ld->ld_options.ldo_mutex ); dn = ld->ld_options.ldo_cldapdn; if (!dn) dn = ""; err = ber_printf( ber, "{isti", /* '}' */ i, dn, LDAP_REQ_ABANDON, msgid ); LDAP_MUTEX_UNLOCK( &ld->ld_options.ldo_mutex ); } else #endif { /* create a message to send */ err = ber_printf( ber, "{iti", /* '}' */ i, LDAP_REQ_ABANDON, msgid ); } if ( err == -1 ) { /* encoding error */ ld->ld_errno = LDAP_ENCODING_ERROR; } else { /* Put Server Controls */ if ( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) { err = -1; } else { /* close '{' */ err = ber_printf( ber, /*{*/ "N}" ); if ( err == -1 ) { /* encoding error */ ld->ld_errno = LDAP_ENCODING_ERROR; } } } if ( err == -1 ) { ber_free( ber, 1 ); } else { /* send the message */ if ( lr != NULL ) { assert( lr->lr_conn != NULL ); sb = lr->lr_conn->lconn_sb; } else { sb = ld->ld_sb; } if ( ber_flush2( sb, ber, LBER_FLUSH_FREE_ALWAYS ) != 0 ) { ld->ld_errno = LDAP_SERVER_DOWN; err = -1; } else { err = 0; } } } } if ( lr != NULL ) { LDAPConn *lc; int freeconn = 0; if ( sendabandon || lr->lr_status == LDAP_REQST_WRITING ) { freeconn = 1; lc = lr->lr_conn; } if ( origid == msgid ) { ldap_free_request( ld, lr ); } else { lr->lr_abandoned = 1; } if ( freeconn ) { /* release ld_req_mutex while grabbing ld_conn_mutex to * prevent deadlock. */ LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex ); LDAP_MUTEX_LOCK( &ld->ld_conn_mutex ); ldap_free_connection( ld, lc, 0, 1 ); LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); LDAP_MUTEX_LOCK( &ld->ld_req_mutex ); } } LDAP_MUTEX_LOCK( &ld->ld_abandon_mutex ); /* use bisection */ i = 0; if ( ld->ld_nabandoned == 0 || ldap_int_bisect_find( ld->ld_abandoned, ld->ld_nabandoned, msgid, &i ) == 0 ) { ldap_int_bisect_insert( &ld->ld_abandoned, &ld->ld_nabandoned, msgid, i ); } if ( err != -1 ) { ld->ld_errno = LDAP_SUCCESS; } LDAP_MUTEX_UNLOCK( &ld->ld_abandon_mutex ); return( ld->ld_errno ); } /* * ldap_int_bisect_find * * args: * v: array of length n (in) * n: length of array v (in) * id: value to look for (in) * idxp: pointer to location of value/insert point * * return: * 0: not found * 1: found * -1: error */ int ldap_int_bisect_find( ber_int_t *v, ber_len_t n, ber_int_t id, int *idxp ) { int begin, end, rc = 0; assert( id >= 0 ); begin = 0; end = n - 1; if ( n <= 0 || id < v[ begin ] ) { *idxp = 0; } else if ( id > v[ end ] ) { *idxp = n; } else { int pos; ber_int_t curid; do { pos = (begin + end)/2; curid = v[ pos ]; if ( id < curid ) { end = pos - 1; } else if ( id > curid ) { begin = ++pos; } else { /* already abandoned? */ rc = 1; break; } } while ( end >= begin ); *idxp = pos; } return rc; } /* * ldap_int_bisect_insert * * args: * vp: pointer to array of length *np (in/out) * np: pointer to length of array *vp (in/out) * id: value to insert (in) * idx: location of insert point (as computed by ldap_int_bisect_find()) * * return: * 0: inserted * -1: error */ int ldap_int_bisect_insert( ber_int_t **vp, ber_len_t *np, int id, int idx ) { ber_int_t *v; ber_len_t n; int i; assert( vp != NULL ); assert( np != NULL ); assert( idx >= 0 ); assert( (unsigned) idx <= *np ); n = *np; v = ber_memrealloc( *vp, sizeof( ber_int_t ) * ( n + 1 ) ); if ( v == NULL ) { return -1; } *vp = v; for ( i = n; i > idx; i-- ) { v[ i ] = v[ i - 1 ]; } v[ idx ] = id; ++(*np); return 0; } /* * ldap_int_bisect_delete * * args: * vp: pointer to array of length *np (in/out) * np: pointer to length of array *vp (in/out) * id: value to delete (in) * idx: location of value to delete (as computed by ldap_int_bisect_find()) * * return: * 0: deleted */ int ldap_int_bisect_delete( ber_int_t **vp, ber_len_t *np, int id, int idx ) { ber_int_t *v; ber_len_t i, n; assert( vp != NULL ); assert( np != NULL ); assert( idx >= 0 ); assert( (unsigned) idx < *np ); v = *vp; assert( v[ idx ] == id ); --(*np); n = *np; for ( i = idx; i < n; i++ ) { v[ i ] = v[ i + 1 ]; } return 0; } openldap-2.4.42+dfsg/libraries/libldap/Makefile.in0000644000175000017500000000614012563404150020461 0ustar ryanryan# Makefile.in for LDAP -lldap # $OpenLDAP$ ## This work is part of OpenLDAP Software . ## ## Copyright 1998-2015 The OpenLDAP Foundation. ## All rights reserved. ## ## Redistribution and use in source and binary forms, with or without ## modification, are permitted only as authorized by the OpenLDAP ## Public License. ## ## A copy of this license is available in the file LICENSE in the ## top-level directory of the distribution or, alternatively, at ## . LIBRARY = libldap.la PROGRAMS = apitest dntest ftest ltest urltest SRCS = bind.c open.c result.c error.c compare.c search.c \ controls.c messages.c references.c extended.c cyrus.c \ modify.c add.c modrdn.c delete.c abandon.c \ sasl.c gssapi.c sbind.c unbind.c cancel.c \ filter.c free.c sort.c passwd.c whoami.c \ getdn.c getentry.c getattr.c getvalues.c addentry.c \ request.c os-ip.c url.c pagectrl.c sortctrl.c vlvctrl.c \ init.c options.c print.c string.c util-int.c schema.c \ charray.c os-local.c dnssrv.c utf-8.c utf-8-conv.c \ tls2.c tls_o.c tls_g.c tls_m.c \ turn.c ppolicy.c dds.c txn.c ldap_sync.c stctrl.c \ assertion.c deref.c ldif.c fetch.c OBJS = bind.lo open.lo result.lo error.lo compare.lo search.lo \ controls.lo messages.lo references.lo extended.lo cyrus.lo \ modify.lo add.lo modrdn.lo delete.lo abandon.lo \ sasl.lo gssapi.lo sbind.lo unbind.lo cancel.lo \ filter.lo free.lo sort.lo passwd.lo whoami.lo \ getdn.lo getentry.lo getattr.lo getvalues.lo addentry.lo \ request.lo os-ip.lo url.lo pagectrl.lo sortctrl.lo vlvctrl.lo \ init.lo options.lo print.lo string.lo util-int.lo schema.lo \ charray.lo os-local.lo dnssrv.lo utf-8.lo utf-8-conv.lo \ tls2.lo tls_o.lo tls_g.lo tls_m.lo \ turn.lo ppolicy.lo dds.lo txn.lo ldap_sync.lo stctrl.lo \ assertion.lo deref.lo ldif.lo fetch.lo LDAP_INCDIR= ../../include LDAP_LIBDIR= ../../libraries LIB_DEFS = -DLDAP_LIBRARY XLIBS = $(LIBRARY) $(LDAP_LIBLBER_LA) $(LDAP_LIBLUTIL_A) XXLIBS = $(SECURITY_LIBS) $(LUTIL_LIBS) NT_LINK_LIBS = $(LDAP_LIBLBER_LA) $(AC_LIBS) $(SECURITY_LIBS) UNIX_LINK_LIBS = $(LDAP_LIBLBER_LA) $(AC_LIBS) $(SECURITY_LIBS) apitest: $(XLIBS) apitest.o $(LTLINK) -o $@ apitest.o $(LIBS) dntest: $(XLIBS) dntest.o $(LTLINK) -o $@ dntest.o $(LIBS) ftest: $(XLIBS) ftest.o $(LTLINK) -o $@ ftest.o $(LIBS) ltest: $(XLIBS) test.o $(LTLINK) -o $@ test.o $(LIBS) urltest: $(XLIBS) urltest.o $(LTLINK) -o $@ urltest.o $(LIBS) CFFILES=ldap.conf install-local: $(CFFILES) FORCE -$(MKDIR) $(DESTDIR)$(libdir) $(LTINSTALL) $(INSTALLFLAGS) -m 644 $(LIBRARY) $(DESTDIR)$(libdir) $(LTFINISH) $(DESTDIR)$(libdir) -$(MKDIR) $(DESTDIR)$(sysconfdir) @for i in $(CFFILES); do \ if test ! -f $(DESTDIR)$(sysconfdir)/$$i; then \ echo "installing $$i in $(sysconfdir)"; \ echo "$(INSTALL) $(INSTALLFLAGS) -m 644 $(srcdir)/$$i $(DESTDIR)$(sysconfdir)/$$i"; \ $(INSTALL) $(INSTALLFLAGS) -m 644 $(srcdir)/$$i $(DESTDIR)$(sysconfdir)/$$i; \ else \ echo "PRESERVING EXISTING CONFIGURATION FILE $(sysconfdir)/$$i" ; \ fi; \ $(INSTALL) $(INSTALLFLAGS) -m 644 $(srcdir)/$$i $(DESTDIR)$(sysconfdir)/$$i.default; \ done openldap-2.4.42+dfsg/libraries/libldap/urltest.c0000644000175000017500000000530612563404150020265 0ustar ryanryan/* urltest.c -- OpenLDAP URL API Test Program */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* ACKNOWLEDGEMENT: * This program was initially developed by Pierangelo Masarati * for inclusion in OpenLDAP Software. */ /* * This program is designed to test the ldap_url_* functions */ #include "portable.h" #include #include #include #include #include #include "ldap-int.h" #include "ldap_defaults.h" int main(int argc, char *argv[]) { const char *url, *scope = NULL; LDAPURLDesc *lud; enum { IS_LDAP = 0, IS_LDAPS, IS_LDAPI } type = IS_LDAP; int rc; if ( argc != 2 ) { fprintf( stderr, "usage: urltest \n" ); exit( EXIT_FAILURE ); } url = argv[ 1 ]; if ( ldap_is_ldaps_url( url ) ) { fprintf( stdout, "LDAPS url\n" ); type = IS_LDAPS; } else if ( ldap_is_ldapi_url( url ) ) { fprintf( stdout, "LDAPI url\n" ); type = IS_LDAPI; } else if ( ldap_is_ldap_url( url ) ) { fprintf( stdout, "generic LDAP url\n" ); } else { fprintf( stderr, "Need a valid LDAP url\n" ); exit( EXIT_FAILURE ); } rc = ldap_url_parse( url, &lud ); if ( rc != LDAP_URL_SUCCESS ) { fprintf( stderr, "ldap_url_parse(%s) failed (%d)\n", url, rc ); exit( EXIT_FAILURE ); } fprintf( stdout, "PROTO: %s\n", lud->lud_scheme ); switch ( type ) { case IS_LDAPI: fprintf( stdout, "PATH: %s\n", lud->lud_host ); break; default: fprintf( stdout, "HOST: %s\n", lud->lud_host ); if ( lud->lud_port != 0 ) { fprintf( stdout, "PORT: %d\n", lud->lud_port ); } } if ( lud->lud_dn && lud->lud_dn[ 0 ] ) { fprintf( stdout, "DN: %s\n", lud->lud_dn ); } if ( lud->lud_attrs ) { int i; fprintf( stdout, "ATTRS:\n" ); for ( i = 0; lud->lud_attrs[ i ]; i++ ) { fprintf( stdout, "\t%s\n", lud->lud_attrs[ i ] ); } } scope = ldap_pvt_scope2str( lud->lud_scope ); if ( scope ) { fprintf( stdout, "SCOPE: %s\n", scope ); } if ( lud->lud_filter ) { fprintf( stdout, "FILTER: %s\n", lud->lud_filter ); } if ( lud->lud_exts ) { int i; fprintf( stdout, "EXTS:\n" ); for ( i = 0; lud->lud_exts[ i ]; i++ ) { fprintf( stdout, "\t%s\n", lud->lud_exts[ i ] ); } } fprintf( stdout, "URL: %s\n", ldap_url_desc2str( lud )); return EXIT_SUCCESS; } openldap-2.4.42+dfsg/libraries/libldap/getdn.c0000644000175000017500000021252212563404150017664 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (c) 1994 Regents of the University of Michigan. * All rights reserved. */ #include "portable.h" #include #include #include #include #include #include "ldap-int.h" #include "ldap_schema.h" /* extension to UFN that turns trailing "dc=value" rdns in DNS style, * e.g. "ou=People,dc=openldap,dc=org" => "People, openldap.org" */ #define DC_IN_UFN /* parsing/printing routines */ static int str2strval( const char *str, ber_len_t stoplen, struct berval *val, const char **next, unsigned flags, int *retFlags, void *ctx ); static int DCE2strval( const char *str, struct berval *val, const char **next, unsigned flags, void *ctx ); static int IA52strval( const char *str, struct berval *val, const char **next, unsigned flags, void *ctx ); static int quotedIA52strval( const char *str, struct berval *val, const char **next, unsigned flags, void *ctx ); static int hexstr2binval( const char *str, struct berval *val, const char **next, unsigned flags, void *ctx ); static int hexstr2bin( const char *str, char *c ); static int byte2hexpair( const char *val, char *pair ); static int binval2hexstr( struct berval *val, char *str ); static int strval2strlen( struct berval *val, unsigned flags, ber_len_t *len ); static int strval2str( struct berval *val, char *str, unsigned flags, ber_len_t *len ); static int strval2IA5strlen( struct berval *val, unsigned flags, ber_len_t *len ); static int strval2IA5str( struct berval *val, char *str, unsigned flags, ber_len_t *len ); static int strval2DCEstrlen( struct berval *val, unsigned flags, ber_len_t *len ); static int strval2DCEstr( struct berval *val, char *str, unsigned flags, ber_len_t *len ); static int strval2ADstrlen( struct berval *val, unsigned flags, ber_len_t *len ); static int strval2ADstr( struct berval *val, char *str, unsigned flags, ber_len_t *len ); static int dn2domain( LDAPDN dn, struct berval *bv, int pos, int *iRDN ); /* AVA helpers */ static LDAPAVA * ldapava_new( const struct berval *attr, const struct berval *val, unsigned flags, void *ctx ); /* Higher level helpers */ static int rdn2strlen( LDAPRDN rdn, unsigned flags, ber_len_t *len, int ( *s2l )( struct berval *, unsigned, ber_len_t * ) ); static int rdn2str( LDAPRDN rdn, char *str, unsigned flags, ber_len_t *len, int ( *s2s )( struct berval *, char *, unsigned, ber_len_t * )); static int rdn2UFNstrlen( LDAPRDN rdn, unsigned flags, ber_len_t *len ); static int rdn2UFNstr( LDAPRDN rdn, char *str, unsigned flags, ber_len_t *len ); static int rdn2DCEstrlen( LDAPRDN rdn, unsigned flags, ber_len_t *len ); static int rdn2DCEstr( LDAPRDN rdn, char *str, unsigned flag, ber_len_t *len, int first ); static int rdn2ADstrlen( LDAPRDN rdn, unsigned flags, ber_len_t *len ); static int rdn2ADstr( LDAPRDN rdn, char *str, unsigned flags, ber_len_t *len, int first ); /* * RFC 1823 ldap_get_dn */ char * ldap_get_dn( LDAP *ld, LDAPMessage *entry ) { char *dn; BerElement tmp; Debug( LDAP_DEBUG_TRACE, "ldap_get_dn\n", 0, 0, 0 ); assert( ld != NULL ); assert( LDAP_VALID(ld) ); assert( entry != NULL ); tmp = *entry->lm_ber; /* struct copy */ if ( ber_scanf( &tmp, "{a" /*}*/, &dn ) == LBER_ERROR ) { ld->ld_errno = LDAP_DECODING_ERROR; return( NULL ); } return( dn ); } int ldap_get_dn_ber( LDAP *ld, LDAPMessage *entry, BerElement **berout, BerValue *dn ) { BerElement tmp, *ber; ber_len_t len = 0; int rc = LDAP_SUCCESS; Debug( LDAP_DEBUG_TRACE, "ldap_get_dn_ber\n", 0, 0, 0 ); assert( ld != NULL ); assert( LDAP_VALID(ld) ); assert( entry != NULL ); assert( dn != NULL ); dn->bv_val = NULL; dn->bv_len = 0; if ( berout ) { *berout = NULL; ber = ldap_alloc_ber_with_options( ld ); if( ber == NULL ) { return LDAP_NO_MEMORY; } *berout = ber; } else { ber = &tmp; } *ber = *entry->lm_ber; /* struct copy */ if ( ber_scanf( ber, "{ml{" /*}*/, dn, &len ) == LBER_ERROR ) { rc = ld->ld_errno = LDAP_DECODING_ERROR; } if ( rc == LDAP_SUCCESS ) { /* set the length to avoid overrun */ rc = ber_set_option( ber, LBER_OPT_REMAINING_BYTES, &len ); if( rc != LBER_OPT_SUCCESS ) { rc = ld->ld_errno = LDAP_LOCAL_ERROR; } } if ( rc != LDAP_SUCCESS && berout ) { ber_free( ber, 0 ); *berout = NULL; } return rc; } /* * RFC 1823 ldap_dn2ufn */ char * ldap_dn2ufn( LDAP_CONST char *dn ) { char *out = NULL; Debug( LDAP_DEBUG_TRACE, "ldap_dn2ufn\n", 0, 0, 0 ); ( void )ldap_dn_normalize( dn, LDAP_DN_FORMAT_LDAP, &out, LDAP_DN_FORMAT_UFN ); return( out ); } /* * RFC 1823 ldap_explode_dn */ char ** ldap_explode_dn( LDAP_CONST char *dn, int notypes ) { LDAPDN tmpDN; char **values = NULL; int iRDN; unsigned flag = notypes ? LDAP_DN_FORMAT_UFN : LDAP_DN_FORMAT_LDAPV3; Debug( LDAP_DEBUG_TRACE, "ldap_explode_dn\n", 0, 0, 0 ); if ( ldap_str2dn( dn, &tmpDN, LDAP_DN_FORMAT_LDAP ) != LDAP_SUCCESS ) { return NULL; } if( tmpDN == NULL ) { values = LDAP_MALLOC( sizeof( char * ) ); if( values == NULL ) return NULL; values[0] = NULL; return values; } for ( iRDN = 0; tmpDN[ iRDN ]; iRDN++ ); values = LDAP_MALLOC( sizeof( char * ) * ( 1 + iRDN ) ); if ( values == NULL ) { ldap_dnfree( tmpDN ); return NULL; } for ( iRDN = 0; tmpDN[ iRDN ]; iRDN++ ) { ldap_rdn2str( tmpDN[ iRDN ], &values[ iRDN ], flag ); } ldap_dnfree( tmpDN ); values[ iRDN ] = NULL; return values; } char ** ldap_explode_rdn( LDAP_CONST char *rdn, int notypes ) { LDAPRDN tmpRDN; char **values = NULL; const char *p; int iAVA; Debug( LDAP_DEBUG_TRACE, "ldap_explode_rdn\n", 0, 0, 0 ); /* * we only parse the first rdn * FIXME: we prefer efficiency over checking if the _ENTIRE_ * dn can be parsed */ if ( ldap_str2rdn( rdn, &tmpRDN, (char **) &p, LDAP_DN_FORMAT_LDAP ) != LDAP_SUCCESS ) { return( NULL ); } for ( iAVA = 0; tmpRDN[ iAVA ]; iAVA++ ) ; values = LDAP_MALLOC( sizeof( char * ) * ( 1 + iAVA ) ); if ( values == NULL ) { ldap_rdnfree( tmpRDN ); return( NULL ); } for ( iAVA = 0; tmpRDN[ iAVA ]; iAVA++ ) { ber_len_t l = 0, vl, al = 0; char *str; LDAPAVA *ava = tmpRDN[ iAVA ]; if ( ava->la_flags & LDAP_AVA_BINARY ) { vl = 1 + 2 * ava->la_value.bv_len; } else { if ( strval2strlen( &ava->la_value, ava->la_flags, &vl ) ) { goto error_return; } } if ( !notypes ) { al = ava->la_attr.bv_len; l = vl + ava->la_attr.bv_len + 1; str = LDAP_MALLOC( l + 1 ); AC_MEMCPY( str, ava->la_attr.bv_val, ava->la_attr.bv_len ); str[ al++ ] = '='; } else { l = vl; str = LDAP_MALLOC( l + 1 ); } if ( ava->la_flags & LDAP_AVA_BINARY ) { str[ al++ ] = '#'; if ( binval2hexstr( &ava->la_value, &str[ al ] ) ) { goto error_return; } } else { if ( strval2str( &ava->la_value, &str[ al ], ava->la_flags, &vl ) ) { goto error_return; } } str[ l ] = '\0'; values[ iAVA ] = str; } values[ iAVA ] = NULL; ldap_rdnfree( tmpRDN ); return( values ); error_return:; LBER_VFREE( values ); ldap_rdnfree( tmpRDN ); return( NULL ); } char * ldap_dn2dcedn( LDAP_CONST char *dn ) { char *out = NULL; Debug( LDAP_DEBUG_TRACE, "ldap_dn2dcedn\n", 0, 0, 0 ); ( void )ldap_dn_normalize( dn, LDAP_DN_FORMAT_LDAP, &out, LDAP_DN_FORMAT_DCE ); return( out ); } char * ldap_dcedn2dn( LDAP_CONST char *dce ) { char *out = NULL; Debug( LDAP_DEBUG_TRACE, "ldap_dcedn2dn\n", 0, 0, 0 ); ( void )ldap_dn_normalize( dce, LDAP_DN_FORMAT_DCE, &out, LDAP_DN_FORMAT_LDAPV3 ); return( out ); } char * ldap_dn2ad_canonical( LDAP_CONST char *dn ) { char *out = NULL; Debug( LDAP_DEBUG_TRACE, "ldap_dn2ad_canonical\n", 0, 0, 0 ); ( void )ldap_dn_normalize( dn, LDAP_DN_FORMAT_LDAP, &out, LDAP_DN_FORMAT_AD_CANONICAL ); return( out ); } /* * function that changes the string representation of dnin * from ( fin & LDAP_DN_FORMAT_MASK ) to ( fout & LDAP_DN_FORMAT_MASK ) * * fin can be one of: * LDAP_DN_FORMAT_LDAP (RFC 4514 liberal, plus some RFC 1779) * LDAP_DN_FORMAT_LDAPV3 (RFC 4514) * LDAP_DN_FORMAT_LDAPV2 (RFC 1779) * LDAP_DN_FORMAT_DCE (?) * * fout can be any of the above except * LDAP_DN_FORMAT_LDAP * plus: * LDAP_DN_FORMAT_UFN (RFC 1781, partial and with extensions) * LDAP_DN_FORMAT_AD_CANONICAL (?) */ int ldap_dn_normalize( LDAP_CONST char *dnin, unsigned fin, char **dnout, unsigned fout ) { int rc; LDAPDN tmpDN = NULL; Debug( LDAP_DEBUG_TRACE, "ldap_dn_normalize\n", 0, 0, 0 ); assert( dnout != NULL ); *dnout = NULL; if ( dnin == NULL ) { return( LDAP_SUCCESS ); } rc = ldap_str2dn( dnin , &tmpDN, fin ); if ( rc != LDAP_SUCCESS ) { return( rc ); } rc = ldap_dn2str( tmpDN, dnout, fout ); ldap_dnfree( tmpDN ); return( rc ); } /* States */ #define B4AVA 0x0000 /* #define B4ATTRTYPE 0x0001 */ #define B4OIDATTRTYPE 0x0002 #define B4STRINGATTRTYPE 0x0003 #define B4AVAEQUALS 0x0100 #define B4AVASEP 0x0200 #define B4RDNSEP 0x0300 #define GOTAVA 0x0400 #define B4ATTRVALUE 0x0010 #define B4STRINGVALUE 0x0020 #define B4IA5VALUEQUOTED 0x0030 #define B4IA5VALUE 0x0040 #define B4BINARYVALUE 0x0050 /* * Helpers (mostly from slap.h) * c is assumed to Unicode in an ASCII compatible format (UTF-8) * Macros assume "C" Locale (ASCII) */ #define LDAP_DN_ASCII_SPACE(c) \ ( (c) == ' ' || (c) == '\t' || (c) == '\n' || (c) == '\r' ) #define LDAP_DN_ASCII_LOWER(c) LDAP_LOWER(c) #define LDAP_DN_ASCII_UPPER(c) LDAP_UPPER(c) #define LDAP_DN_ASCII_ALPHA(c) LDAP_ALPHA(c) #define LDAP_DN_ASCII_DIGIT(c) LDAP_DIGIT(c) #define LDAP_DN_ASCII_LCASE_HEXALPHA(c) LDAP_HEXLOWER(c) #define LDAP_DN_ASCII_UCASE_HEXALPHA(c) LDAP_HEXUPPER(c) #define LDAP_DN_ASCII_HEXDIGIT(c) LDAP_HEX(c) #define LDAP_DN_ASCII_ALNUM(c) LDAP_ALNUM(c) #define LDAP_DN_ASCII_PRINTABLE(c) ( (c) >= ' ' && (c) <= '~' ) /* attribute type */ #define LDAP_DN_OID_LEADCHAR(c) LDAP_DIGIT(c) #define LDAP_DN_DESC_LEADCHAR(c) LDAP_ALPHA(c) #define LDAP_DN_DESC_CHAR(c) LDAP_LDH(c) #define LDAP_DN_LANG_SEP(c) ( (c) == ';' ) #define LDAP_DN_ATTRDESC_CHAR(c) \ ( LDAP_DN_DESC_CHAR(c) || LDAP_DN_LANG_SEP(c) ) /* special symbols */ #define LDAP_DN_AVA_EQUALS(c) ( (c) == '=' ) #define LDAP_DN_AVA_SEP(c) ( (c) == '+' ) #define LDAP_DN_RDN_SEP(c) ( (c) == ',' ) #define LDAP_DN_RDN_SEP_V2(c) ( LDAP_DN_RDN_SEP(c) || (c) == ';' ) #define LDAP_DN_OCTOTHORPE(c) ( (c) == '#' ) #define LDAP_DN_QUOTES(c) ( (c) == '\"' ) #define LDAP_DN_ESCAPE(c) ( (c) == '\\' ) #define LDAP_DN_VALUE_END(c) \ ( LDAP_DN_RDN_SEP(c) || LDAP_DN_AVA_SEP(c) ) /* NOTE: according to RFC 4514, '=' can be escaped and treated as special, * i.e. escaped both as "\" and * as "\=", but it is treated as * a regular char, i.e. it can also appear as '='. * * As such, in 2.2 we used to allow reading unescaped '=', but we always * produced escaped '\3D'; this changes since 2.3, if compatibility issues * do not arise */ #define LDAP_DN_NE(c) \ ( LDAP_DN_RDN_SEP_V2(c) || LDAP_DN_AVA_SEP(c) \ || LDAP_DN_QUOTES(c) \ || (c) == '<' || (c) == '>' ) #define LDAP_DN_MAYESCAPE(c) \ ( LDAP_DN_ESCAPE(c) || LDAP_DN_NE(c) \ || LDAP_DN_AVA_EQUALS(c) \ || LDAP_DN_ASCII_SPACE(c) || LDAP_DN_OCTOTHORPE(c) ) #define LDAP_DN_SHOULDESCAPE(c) ( LDAP_DN_AVA_EQUALS(c) ) #define LDAP_DN_NEEDESCAPE(c) \ ( LDAP_DN_ESCAPE(c) || LDAP_DN_NE(c) ) #define LDAP_DN_NEEDESCAPE_LEAD(c) LDAP_DN_MAYESCAPE(c) #define LDAP_DN_NEEDESCAPE_TRAIL(c) \ ( LDAP_DN_ASCII_SPACE(c) || LDAP_DN_NEEDESCAPE(c) ) #define LDAP_DN_WILLESCAPE_CHAR(c) \ ( LDAP_DN_RDN_SEP(c) || LDAP_DN_AVA_SEP(c) || LDAP_DN_ESCAPE(c) ) #define LDAP_DN_IS_PRETTY(f) ( (f) & LDAP_DN_PRETTY ) #define LDAP_DN_WILLESCAPE_HEX(f, c) \ ( ( !LDAP_DN_IS_PRETTY( f ) ) && LDAP_DN_WILLESCAPE_CHAR(c) ) /* LDAPv2 */ #define LDAP_DN_VALUE_END_V2(c) \ ( LDAP_DN_RDN_SEP_V2(c) || LDAP_DN_AVA_SEP(c) ) /* RFC 1779 */ #define LDAP_DN_V2_SPECIAL(c) \ ( LDAP_DN_RDN_SEP_V2(c) || LDAP_DN_AVA_EQUALS(c) \ || LDAP_DN_AVA_SEP(c) || (c) == '<' || (c) == '>' \ || LDAP_DN_OCTOTHORPE(c) ) #define LDAP_DN_V2_PAIR(c) \ ( LDAP_DN_V2_SPECIAL(c) || LDAP_DN_ESCAPE(c) || LDAP_DN_QUOTES(c) ) /* * DCE (mostly from Luke Howard and IBM implementation for AIX) * * From: "Application Development Guide - Directory Services" (FIXME: add link?) * Here escapes and valid chars for GDS are considered; as soon as more * specific info is found, the macros will be updated. * * Chars: 'a'-'z', 'A'-'Z', '0'-'9', * '.', ':', ',', ''', '+', '-', '=', '(', ')', '?', '/', ' '. * * Metachars: '/', ',', '=', '\'. * * the '\' is used to escape other metachars. * * Assertion: '=' * RDN separator: '/' * AVA separator: ',' * * Attribute types must start with alphabetic chars and can contain * alphabetic chars and digits (FIXME: no '-'?). OIDs are allowed. */ #define LDAP_DN_RDN_SEP_DCE(c) ( (c) == '/' ) #define LDAP_DN_AVA_SEP_DCE(c) ( (c) == ',' ) #define LDAP_DN_ESCAPE_DCE(c) ( LDAP_DN_ESCAPE(c) ) #define LDAP_DN_VALUE_END_DCE(c) \ ( LDAP_DN_RDN_SEP_DCE(c) || LDAP_DN_AVA_SEP_DCE(c) ) #define LDAP_DN_NEEDESCAPE_DCE(c) \ ( LDAP_DN_VALUE_END_DCE(c) || LDAP_DN_AVA_EQUALS(c) ) /* AD Canonical */ #define LDAP_DN_RDN_SEP_AD(c) ( (c) == '/' ) #define LDAP_DN_ESCAPE_AD(c) ( LDAP_DN_ESCAPE(c) ) #define LDAP_DN_AVA_SEP_AD(c) ( (c) == ',' ) /* assume same as DCE */ #define LDAP_DN_VALUE_END_AD(c) \ ( LDAP_DN_RDN_SEP_AD(c) || LDAP_DN_AVA_SEP_AD(c) ) #define LDAP_DN_NEEDESCAPE_AD(c) \ ( LDAP_DN_VALUE_END_AD(c) || LDAP_DN_AVA_EQUALS(c) ) /* generics */ #define LDAP_DN_HEXPAIR(s) \ ( LDAP_DN_ASCII_HEXDIGIT((s)[0]) && LDAP_DN_ASCII_HEXDIGIT((s)[1]) ) /* better look at the AttributeDescription? */ /* FIXME: no composite rdn or non-"dc" types, right? * (what about "dc" in OID form?) */ /* FIXME: we do not allow binary values in domain, right? */ /* NOTE: use this macro only when ABSOLUTELY SURE rdn IS VALID! */ /* NOTE: don't use strcasecmp() as it is locale specific! */ #define LDAP_DC_ATTR "dc" #define LDAP_DC_ATTRU "DC" #define LDAP_DN_IS_RDN_DC( r ) \ ( (r) && (r)[0] && !(r)[1] \ && ((r)[0]->la_flags & LDAP_AVA_STRING) \ && ((r)[0]->la_attr.bv_len == 2) \ && (((r)[0]->la_attr.bv_val[0] == LDAP_DC_ATTR[0]) \ || ((r)[0]->la_attr.bv_val[0] == LDAP_DC_ATTRU[0])) \ && (((r)[0]->la_attr.bv_val[1] == LDAP_DC_ATTR[1]) \ || ((r)[0]->la_attr.bv_val[1] == LDAP_DC_ATTRU[1]))) /* Composite rules */ #define LDAP_DN_ALLOW_ONE_SPACE(f) \ ( LDAP_DN_LDAPV2(f) \ || !( (f) & LDAP_DN_P_NOSPACEAFTERRDN ) ) #define LDAP_DN_ALLOW_SPACES(f) \ ( LDAP_DN_LDAPV2(f) \ || !( (f) & ( LDAP_DN_P_NOLEADTRAILSPACES | LDAP_DN_P_NOSPACEAFTERRDN ) ) ) #define LDAP_DN_LDAP(f) \ ( ( (f) & LDAP_DN_FORMAT_MASK ) == LDAP_DN_FORMAT_LDAP ) #define LDAP_DN_LDAPV3(f) \ ( ( (f) & LDAP_DN_FORMAT_MASK ) == LDAP_DN_FORMAT_LDAPV3 ) #define LDAP_DN_LDAPV2(f) \ ( ( (f) & LDAP_DN_FORMAT_MASK ) == LDAP_DN_FORMAT_LDAPV2 ) #define LDAP_DN_DCE(f) \ ( ( (f) & LDAP_DN_FORMAT_MASK ) == LDAP_DN_FORMAT_DCE ) #define LDAP_DN_UFN(f) \ ( ( (f) & LDAP_DN_FORMAT_MASK ) == LDAP_DN_FORMAT_UFN ) #define LDAP_DN_ADC(f) \ ( ( (f) & LDAP_DN_FORMAT_MASK ) == LDAP_DN_FORMAT_AD_CANONICAL ) #define LDAP_DN_FORMAT(f) ( (f) & LDAP_DN_FORMAT_MASK ) /* * LDAPAVA helpers (will become part of the API for operations * on structural representations of DNs). */ static LDAPAVA * ldapava_new( const struct berval *attr, const struct berval *val, unsigned flags, void *ctx ) { LDAPAVA *ava; assert( attr != NULL ); assert( val != NULL ); ava = LDAP_MALLOCX( sizeof( LDAPAVA ) + attr->bv_len + 1, ctx ); if ( ava ) { ava->la_attr.bv_len = attr->bv_len; ava->la_attr.bv_val = (char *)(ava+1); AC_MEMCPY( ava->la_attr.bv_val, attr->bv_val, attr->bv_len ); ava->la_attr.bv_val[attr->bv_len] = '\0'; ava->la_value = *val; ava->la_flags = flags | LDAP_AVA_FREE_VALUE; ava->la_private = NULL; } return( ava ); } static void ldapava_free( LDAPAVA *ava, void *ctx ) { assert( ava != NULL ); #if 0 /* ava's private must be freed by caller * (at present let's skip this check because la_private * basically holds static data) */ assert( ava->la_private == NULL ); #endif if (ava->la_flags & LDAP_AVA_FREE_VALUE) LDAP_FREEX( ava->la_value.bv_val, ctx ); LDAP_FREEX( ava, ctx ); } void ldap_rdnfree( LDAPRDN rdn ) { ldap_rdnfree_x( rdn, NULL ); } void ldap_rdnfree_x( LDAPRDN rdn, void *ctx ) { int iAVA; if ( rdn == NULL ) { return; } for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) { ldapava_free( rdn[ iAVA ], ctx ); } LDAP_FREEX( rdn, ctx ); } void ldap_dnfree( LDAPDN dn ) { ldap_dnfree_x( dn, NULL ); } void ldap_dnfree_x( LDAPDN dn, void *ctx ) { int iRDN; if ( dn == NULL ) { return; } for ( iRDN = 0; dn[ iRDN ]; iRDN++ ) { ldap_rdnfree_x( dn[ iRDN ], ctx ); } LDAP_FREEX( dn, ctx ); } /* * Converts a string representation of a DN (in LDAPv3, LDAPv2 or DCE) * into a structural representation of the DN, by separating attribute * types and values encoded in the more appropriate form, which is * string or OID for attribute types and binary form of the BER encoded * value or Unicode string. Formats different from LDAPv3 are parsed * according to their own rules and turned into the more appropriate * form according to LDAPv3. * * NOTE: I realize the code is getting spaghettish; it is rather * experimental and will hopefully turn into something more simple * and readable as soon as it works as expected. */ /* * Default sizes of AVA and RDN static working arrays; if required * the are dynamically resized. The values can be tuned in case * of special requirements (e.g. very deep DN trees or high number * of AVAs per RDN). */ #define TMP_AVA_SLOTS 8 #define TMP_RDN_SLOTS 32 int ldap_str2dn( LDAP_CONST char *str, LDAPDN *dn, unsigned flags ) { struct berval bv; assert( str != NULL ); bv.bv_len = strlen( str ); bv.bv_val = (char *) str; return ldap_bv2dn_x( &bv, dn, flags, NULL ); } int ldap_bv2dn( struct berval *bv, LDAPDN *dn, unsigned flags ) { return ldap_bv2dn_x( bv, dn, flags, NULL ); } int ldap_bv2dn_x( struct berval *bvin, LDAPDN *dn, unsigned flags, void *ctx ) { const char *p; int rc = LDAP_DECODING_ERROR; int nrdns = 0; LDAPDN newDN = NULL; LDAPRDN newRDN = NULL, tmpDN_[TMP_RDN_SLOTS], *tmpDN = tmpDN_; int num_slots = TMP_RDN_SLOTS; char *str, *end; struct berval bvtmp, *bv = &bvtmp; assert( bvin != NULL ); assert( bvin->bv_val != NULL ); assert( dn != NULL ); *bv = *bvin; str = bv->bv_val; end = str + bv->bv_len; Debug( LDAP_DEBUG_ARGS, "=> ldap_bv2dn(%s,%u)\n", str, flags, 0 ); *dn = NULL; switch ( LDAP_DN_FORMAT( flags ) ) { case LDAP_DN_FORMAT_LDAP: case LDAP_DN_FORMAT_LDAPV3: case LDAP_DN_FORMAT_DCE: break; /* allow DN enclosed in brackets */ case LDAP_DN_FORMAT_LDAPV2: if ( str[0] == '<' ) { if ( bv->bv_len < 2 || end[ -1 ] != '>' ) { rc = LDAP_DECODING_ERROR; goto parsing_error; } bv->bv_val++; bv->bv_len -= 2; str++; end--; } break; /* unsupported in str2dn */ case LDAP_DN_FORMAT_UFN: case LDAP_DN_FORMAT_AD_CANONICAL: return LDAP_PARAM_ERROR; case LDAP_DN_FORMAT_LBER: default: return LDAP_PARAM_ERROR; } if ( bv->bv_len == 0 ) { return LDAP_SUCCESS; } if( memchr( bv->bv_val, '\0', bv->bv_len ) != NULL ) { /* value must have embedded NULs */ return LDAP_DECODING_ERROR; } p = str; if ( LDAP_DN_DCE( flags ) ) { /* * (from Luke Howard: thnx) A RDN separator is required * at the beginning of an (absolute) DN. */ if ( !LDAP_DN_RDN_SEP_DCE( p[ 0 ] ) ) { goto parsing_error; } p++; /* * actually we do not want to accept by default the DCE form, * we do not want to auto-detect it */ #if 0 } else if ( LDAP_DN_LDAP( flags ) ) { /* * if dn starts with '/' let's make it a DCE dn */ if ( LDAP_DN_RDN_SEP_DCE( p[ 0 ] ) ) { flags |= LDAP_DN_FORMAT_DCE; p++; } #endif } for ( ; p < end; p++ ) { int err; struct berval tmpbv; tmpbv.bv_len = bv->bv_len - ( p - str ); tmpbv.bv_val = (char *)p; err = ldap_bv2rdn_x( &tmpbv, &newRDN, (char **) &p, flags,ctx); if ( err != LDAP_SUCCESS ) { goto parsing_error; } /* * We expect a rdn separator */ if ( p < end && p[ 0 ] ) { switch ( LDAP_DN_FORMAT( flags ) ) { case LDAP_DN_FORMAT_LDAPV3: if ( !LDAP_DN_RDN_SEP( p[ 0 ] ) ) { rc = LDAP_DECODING_ERROR; goto parsing_error; } break; case LDAP_DN_FORMAT_LDAP: case LDAP_DN_FORMAT_LDAPV2: if ( !LDAP_DN_RDN_SEP_V2( p[ 0 ] ) ) { rc = LDAP_DECODING_ERROR; goto parsing_error; } break; case LDAP_DN_FORMAT_DCE: if ( !LDAP_DN_RDN_SEP_DCE( p[ 0 ] ) ) { rc = LDAP_DECODING_ERROR; goto parsing_error; } break; } } tmpDN[nrdns++] = newRDN; newRDN = NULL; /* * make the static RDN array dynamically rescalable */ if ( nrdns == num_slots ) { LDAPRDN *tmp; if ( tmpDN == tmpDN_ ) { tmp = LDAP_MALLOCX( num_slots * 2 * sizeof( LDAPRDN * ), ctx ); if ( tmp == NULL ) { rc = LDAP_NO_MEMORY; goto parsing_error; } AC_MEMCPY( tmp, tmpDN, num_slots * sizeof( LDAPRDN * ) ); } else { tmp = LDAP_REALLOCX( tmpDN, num_slots * 2 * sizeof( LDAPRDN * ), ctx ); if ( tmp == NULL ) { rc = LDAP_NO_MEMORY; goto parsing_error; } } tmpDN = tmp; num_slots *= 2; } if ( p >= end || p[ 0 ] == '\0' ) { /* * the DN is over, phew */ newDN = (LDAPDN)LDAP_MALLOCX( sizeof(LDAPRDN *) * (nrdns+1), ctx ); if ( newDN == NULL ) { rc = LDAP_NO_MEMORY; goto parsing_error; } else { int i; if ( LDAP_DN_DCE( flags ) ) { /* add in reversed order */ for ( i=0; i= 0; nrdns-- ) { ldap_rdnfree_x( tmpDN[nrdns], ctx ); } return_result:; if ( tmpDN != tmpDN_ ) { LDAP_FREEX( tmpDN, ctx ); } Debug( LDAP_DEBUG_ARGS, "<= ldap_bv2dn(%s)=%d %s\n", str, rc, rc ? ldap_err2string( rc ) : "" ); *dn = newDN; return( rc ); } /* * ldap_str2rdn * * Parses a relative DN according to flags up to a rdn separator * or to the end of str. * Returns the rdn and a pointer to the string continuation, which * corresponds to the rdn separator or to '\0' in case the string is over. */ int ldap_str2rdn( LDAP_CONST char *str, LDAPRDN *rdn, char **n_in, unsigned flags ) { struct berval bv; assert( str != NULL ); assert( str[ 0 ] != '\0' ); /* FIXME: is this required? */ bv.bv_len = strlen( str ); bv.bv_val = (char *) str; return ldap_bv2rdn_x( &bv, rdn, n_in, flags, NULL ); } int ldap_bv2rdn( struct berval *bv, LDAPRDN *rdn, char **n_in, unsigned flags ) { return ldap_bv2rdn_x( bv, rdn, n_in, flags, NULL ); } int ldap_bv2rdn_x( struct berval *bv, LDAPRDN *rdn, char **n_in, unsigned flags, void *ctx ) { const char **n = (const char **) n_in; const char *p; int navas = 0; int state = B4AVA; int rc = LDAP_DECODING_ERROR; int attrTypeEncoding = LDAP_AVA_STRING, attrValueEncoding = LDAP_AVA_STRING; struct berval attrType = BER_BVNULL; struct berval attrValue = BER_BVNULL; LDAPRDN newRDN = NULL; LDAPAVA *tmpRDN_[TMP_AVA_SLOTS], **tmpRDN = tmpRDN_; int num_slots = TMP_AVA_SLOTS; char *str; ber_len_t stoplen; assert( bv != NULL ); assert( bv->bv_len != 0 ); assert( bv->bv_val != NULL ); assert( rdn || flags & LDAP_DN_SKIP ); assert( n != NULL ); str = bv->bv_val; stoplen = bv->bv_len; if ( rdn ) { *rdn = NULL; } *n = NULL; switch ( LDAP_DN_FORMAT( flags ) ) { case LDAP_DN_FORMAT_LDAP: case LDAP_DN_FORMAT_LDAPV3: case LDAP_DN_FORMAT_LDAPV2: case LDAP_DN_FORMAT_DCE: break; /* unsupported in str2dn */ case LDAP_DN_FORMAT_UFN: case LDAP_DN_FORMAT_AD_CANONICAL: return LDAP_PARAM_ERROR; case LDAP_DN_FORMAT_LBER: default: return LDAP_PARAM_ERROR; } if ( bv->bv_len == 0 ) { return LDAP_SUCCESS; } if( memchr( bv->bv_val, '\0', bv->bv_len ) != NULL ) { /* value must have embedded NULs */ return LDAP_DECODING_ERROR; } p = str; for ( ; p[ 0 ] || state == GOTAVA; ) { /* * The parser in principle advances one token a time, * or toggles state if preferable. */ switch (state) { /* * an AttributeType can be encoded as: * - its string representation; in detail, implementations * MUST recognize AttributeType string type names listed * in Section 3 of RFC 4514, and MAY recognize other names. * - its numeric OID (a dotted decimal string) */ case B4AVA: if ( LDAP_DN_ASCII_SPACE( p[ 0 ] ) ) { if ( !LDAP_DN_ALLOW_ONE_SPACE( flags ) ) { /* error */ goto parsing_error; } p++; } if ( LDAP_DN_ASCII_SPACE( p[ 0 ] ) ) { if ( !LDAP_DN_ALLOW_SPACES( flags ) ) { /* error */ goto parsing_error; } /* whitespace is allowed (and trimmed) */ p++; while ( p[ 0 ] && LDAP_DN_ASCII_SPACE( p[ 0 ] ) ) { p++; } if ( !p[ 0 ] ) { /* error: we expected an AVA */ goto parsing_error; } } /* oid */ if ( LDAP_DN_OID_LEADCHAR( p[ 0 ] ) ) { state = B4OIDATTRTYPE; break; } /* else must be alpha */ if ( !LDAP_DN_DESC_LEADCHAR( p[ 0 ] ) ) { goto parsing_error; } /* LDAPv2 "oid." prefix */ if ( LDAP_DN_LDAPV2( flags ) ) { /* * to be overly pedantic, we only accept * "OID." or "oid." */ if ( flags & LDAP_DN_PEDANTIC ) { if ( !strncmp( p, "OID.", 4 ) || !strncmp( p, "oid.", 4 ) ) { p += 4; state = B4OIDATTRTYPE; break; } } else { if ( !strncasecmp( p, "oid.", 4 ) ) { p += 4; state = B4OIDATTRTYPE; break; } } } state = B4STRINGATTRTYPE; break; case B4OIDATTRTYPE: { int err = LDAP_SUCCESS; attrType.bv_val = ldap_int_parse_numericoid( &p, &err, LDAP_SCHEMA_SKIP); if ( err != LDAP_SUCCESS ) { goto parsing_error; } attrType.bv_len = p - attrType.bv_val; attrTypeEncoding = LDAP_AVA_BINARY; state = B4AVAEQUALS; break; } case B4STRINGATTRTYPE: { const char *startPos, *endPos = NULL; ber_len_t len; /* * the starting char has been found to be * a LDAP_DN_DESC_LEADCHAR so we don't re-check it * FIXME: DCE attr types seem to have a more * restrictive syntax (no '-' ...) */ for ( startPos = p++; p[ 0 ]; p++ ) { if ( LDAP_DN_DESC_CHAR( p[ 0 ] ) ) { continue; } if ( LDAP_DN_LANG_SEP( p[ 0 ] ) ) { /* * RFC 4514 explicitly does not allow attribute * description options, such as language tags. */ if ( flags & LDAP_DN_PEDANTIC ) { goto parsing_error; } /* * we trim ';' and following lang * and so from attribute types */ endPos = p; for ( ; LDAP_DN_ATTRDESC_CHAR( p[ 0 ] ) || LDAP_DN_LANG_SEP( p[ 0 ] ); p++ ) { /* no op */ ; } break; } break; } len = ( endPos ? endPos : p ) - startPos; if ( len == 0 ) { goto parsing_error; } attrTypeEncoding = LDAP_AVA_STRING; /* * here we need to decide whether to use it as is * or turn it in OID form; as a consequence, we * need to decide whether to binary encode the value */ state = B4AVAEQUALS; if ( flags & LDAP_DN_SKIP ) { break; } attrType.bv_val = (char *)startPos; attrType.bv_len = len; break; } case B4AVAEQUALS: /* spaces may not be allowed */ if ( LDAP_DN_ASCII_SPACE( p[ 0 ] ) ) { if ( !LDAP_DN_ALLOW_SPACES( flags ) ) { goto parsing_error; } /* trim spaces */ for ( p++; LDAP_DN_ASCII_SPACE( p[ 0 ] ); p++ ) { /* no op */ } } /* need equal sign */ if ( !LDAP_DN_AVA_EQUALS( p[ 0 ] ) ) { goto parsing_error; } p++; /* spaces may not be allowed */ if ( LDAP_DN_ASCII_SPACE( p[ 0 ] ) ) { if ( !LDAP_DN_ALLOW_SPACES( flags ) ) { goto parsing_error; } /* trim spaces */ for ( p++; LDAP_DN_ASCII_SPACE( p[ 0 ] ); p++ ) { /* no op */ } } /* * octothorpe means a BER encoded value will follow * FIXME: I don't think DCE will allow it */ if ( LDAP_DN_OCTOTHORPE( p[ 0 ] ) ) { p++; attrValueEncoding = LDAP_AVA_BINARY; state = B4BINARYVALUE; break; } /* STRING value expected */ /* * if we're pedantic, an attribute type in OID form * SHOULD imply a BER encoded attribute value; we * should at least issue a warning */ if ( ( flags & LDAP_DN_PEDANTIC ) && ( attrTypeEncoding == LDAP_AVA_BINARY ) ) { /* OID attrType SHOULD use binary encoding */ goto parsing_error; } attrValueEncoding = LDAP_AVA_STRING; /* * LDAPv2 allows the attribute value to be quoted; * also, IA5 values are expected, in principle */ if ( LDAP_DN_LDAPV2( flags ) || LDAP_DN_LDAP( flags ) ) { if ( LDAP_DN_QUOTES( p[ 0 ] ) ) { p++; state = B4IA5VALUEQUOTED; break; } if ( LDAP_DN_LDAPV2( flags ) ) { state = B4IA5VALUE; break; } } /* * here STRING means RFC 4514 string * FIXME: what about DCE strings? */ if ( !p[ 0 ] ) { /* empty value */ state = GOTAVA; } else { state = B4STRINGVALUE; } break; case B4BINARYVALUE: if ( hexstr2binval( p, &attrValue, &p, flags, ctx ) ) { goto parsing_error; } state = GOTAVA; break; case B4STRINGVALUE: switch ( LDAP_DN_FORMAT( flags ) ) { case LDAP_DN_FORMAT_LDAP: case LDAP_DN_FORMAT_LDAPV3: if ( str2strval( p, stoplen - ( p - str ), &attrValue, &p, flags, &attrValueEncoding, ctx ) ) { goto parsing_error; } break; case LDAP_DN_FORMAT_DCE: if ( DCE2strval( p, &attrValue, &p, flags, ctx ) ) { goto parsing_error; } break; default: assert( 0 ); } state = GOTAVA; break; case B4IA5VALUE: if ( IA52strval( p, &attrValue, &p, flags, ctx ) ) { goto parsing_error; } state = GOTAVA; break; case B4IA5VALUEQUOTED: /* lead quote already stripped */ if ( quotedIA52strval( p, &attrValue, &p, flags, ctx ) ) { goto parsing_error; } state = GOTAVA; break; case GOTAVA: { int rdnsep = 0; if ( !( flags & LDAP_DN_SKIP ) ) { LDAPAVA *ava; /* * we accept empty values */ ava = ldapava_new( &attrType, &attrValue, attrValueEncoding, ctx ); if ( ava == NULL ) { rc = LDAP_NO_MEMORY; goto parsing_error; } tmpRDN[navas++] = ava; attrValue.bv_val = NULL; attrValue.bv_len = 0; /* * prepare room for new AVAs if needed */ if (navas == num_slots) { LDAPAVA **tmp; if ( tmpRDN == tmpRDN_ ) { tmp = LDAP_MALLOCX( num_slots * 2 * sizeof( LDAPAVA * ), ctx ); if ( tmp == NULL ) { rc = LDAP_NO_MEMORY; goto parsing_error; } AC_MEMCPY( tmp, tmpRDN, num_slots * sizeof( LDAPAVA * ) ); } else { tmp = LDAP_REALLOCX( tmpRDN, num_slots * 2 * sizeof( LDAPAVA * ), ctx ); if ( tmp == NULL ) { rc = LDAP_NO_MEMORY; goto parsing_error; } } tmpRDN = tmp; num_slots *= 2; } } /* * if we got an AVA separator ('+', or ',' for DCE ) * we expect a new AVA for this RDN; otherwise * we add the RDN to the DN */ switch ( LDAP_DN_FORMAT( flags ) ) { case LDAP_DN_FORMAT_LDAP: case LDAP_DN_FORMAT_LDAPV3: case LDAP_DN_FORMAT_LDAPV2: if ( !LDAP_DN_AVA_SEP( p[ 0 ] ) ) { rdnsep = 1; } break; case LDAP_DN_FORMAT_DCE: if ( !LDAP_DN_AVA_SEP_DCE( p[ 0 ] ) ) { rdnsep = 1; } break; } if ( rdnsep ) { /* * the RDN is over, phew */ *n = p; if ( !( flags & LDAP_DN_SKIP ) ) { newRDN = (LDAPRDN)LDAP_MALLOCX( sizeof(LDAPAVA) * (navas+1), ctx ); if ( newRDN == NULL ) { rc = LDAP_NO_MEMORY; goto parsing_error; } else { AC_MEMCPY( newRDN, tmpRDN, sizeof(LDAPAVA *) * navas); newRDN[navas] = NULL; } } rc = LDAP_SUCCESS; goto return_result; } /* they should have been used in an AVA */ attrType.bv_val = NULL; attrValue.bv_val = NULL; p++; state = B4AVA; break; } default: assert( 0 ); goto parsing_error; } } *n = p; parsing_error:; /* They are set to NULL after they're used in an AVA */ if ( attrValue.bv_val ) { LDAP_FREEX( attrValue.bv_val, ctx ); } for ( navas-- ; navas >= 0; navas-- ) { ldapava_free( tmpRDN[navas], ctx ); } return_result:; if ( tmpRDN != tmpRDN_ ) { LDAP_FREEX( tmpRDN, ctx ); } if ( rdn ) { *rdn = newRDN; } return( rc ); } /* * reads in a UTF-8 string value, unescaping stuff: * '\' + LDAP_DN_NEEDESCAPE(c) -> 'c' * '\' + HEXPAIR(p) -> unhex(p) */ static int str2strval( const char *str, ber_len_t stoplen, struct berval *val, const char **next, unsigned flags, int *retFlags, void *ctx ) { const char *p, *end, *startPos, *endPos = NULL; ber_len_t len, escapes; assert( str != NULL ); assert( val != NULL ); assert( next != NULL ); *next = NULL; end = str + stoplen; for ( startPos = p = str, escapes = 0; p < end; p++ ) { if ( LDAP_DN_ESCAPE( p[ 0 ] ) ) { p++; if ( p[ 0 ] == '\0' ) { return( 1 ); } if ( LDAP_DN_MAYESCAPE( p[ 0 ] ) ) { escapes++; continue; } if ( LDAP_DN_HEXPAIR( p ) ) { char c; hexstr2bin( p, &c ); escapes += 2; if ( !LDAP_DN_ASCII_PRINTABLE( c ) ) { /* * we assume the string is UTF-8 */ *retFlags = LDAP_AVA_NONPRINTABLE; } p++; continue; } if ( LDAP_DN_PEDANTIC & flags ) { return( 1 ); } /* * we do not allow escaping * of chars that don't need * to and do not belong to * HEXDIGITS */ return( 1 ); } else if ( !LDAP_DN_ASCII_PRINTABLE( p[ 0 ] ) ) { if ( p[ 0 ] == '\0' ) { return( 1 ); } *retFlags = LDAP_AVA_NONPRINTABLE; } else if ( ( LDAP_DN_LDAP( flags ) && LDAP_DN_VALUE_END_V2( p[ 0 ] ) ) || ( LDAP_DN_LDAPV3( flags ) && LDAP_DN_VALUE_END( p[ 0 ] ) ) ) { break; } else if ( LDAP_DN_NEEDESCAPE( p[ 0 ] ) ) { /* * FIXME: maybe we can add * escapes if not pedantic? */ return( 1 ); } } /* * we do allow unescaped spaces at the end * of the value only in non-pedantic mode */ if ( p > startPos + 1 && LDAP_DN_ASCII_SPACE( p[ -1 ] ) && !LDAP_DN_ESCAPE( p[ -2 ] ) ) { if ( flags & LDAP_DN_PEDANTIC ) { return( 1 ); } /* strip trailing (unescaped) spaces */ for ( endPos = p - 1; endPos > startPos + 1 && LDAP_DN_ASCII_SPACE( endPos[ -1 ] ) && !LDAP_DN_ESCAPE( endPos[ -2 ] ); endPos-- ) { /* no op */ } } *next = p; if ( flags & LDAP_DN_SKIP ) { return( 0 ); } /* * FIXME: test memory? */ len = ( endPos ? endPos : p ) - startPos - escapes; val->bv_len = len; if ( escapes == 0 ) { if ( *retFlags & LDAP_AVA_NONPRINTABLE ) { val->bv_val = LDAP_MALLOCX( len + 1, ctx ); AC_MEMCPY( val->bv_val, startPos, len ); val->bv_val[ len ] = '\0'; } else { val->bv_val = LDAP_STRNDUPX( startPos, len, ctx ); } } else { ber_len_t s, d; val->bv_val = LDAP_MALLOCX( len + 1, ctx ); for ( s = 0, d = 0; d < len; ) { if ( LDAP_DN_ESCAPE( startPos[ s ] ) ) { s++; if ( LDAP_DN_MAYESCAPE( startPos[ s ] ) ) { val->bv_val[ d++ ] = startPos[ s++ ]; } else if ( LDAP_DN_HEXPAIR( &startPos[ s ] ) ) { char c; hexstr2bin( &startPos[ s ], &c ); val->bv_val[ d++ ] = c; s += 2; } else { /* we should never get here */ assert( 0 ); } } else { val->bv_val[ d++ ] = startPos[ s++ ]; } } val->bv_val[ d ] = '\0'; assert( d == len ); } return( 0 ); } static int DCE2strval( const char *str, struct berval *val, const char **next, unsigned flags, void *ctx ) { const char *p, *startPos, *endPos = NULL; ber_len_t len, escapes; assert( str != NULL ); assert( val != NULL ); assert( next != NULL ); *next = NULL; for ( startPos = p = str, escapes = 0; p[ 0 ]; p++ ) { if ( LDAP_DN_ESCAPE_DCE( p[ 0 ] ) ) { p++; if ( LDAP_DN_NEEDESCAPE_DCE( p[ 0 ] ) ) { escapes++; } else { return( 1 ); } } else if ( LDAP_DN_VALUE_END_DCE( p[ 0 ] ) ) { break; } /* * FIXME: can we accept anything else? I guess we need * to stop if a value is not legal */ } /* * (unescaped) trailing spaces are trimmed must be silently ignored; * so we eat them */ if ( p > startPos + 1 && LDAP_DN_ASCII_SPACE( p[ -1 ] ) && !LDAP_DN_ESCAPE( p[ -2 ] ) ) { if ( flags & LDAP_DN_PEDANTIC ) { return( 1 ); } /* strip trailing (unescaped) spaces */ for ( endPos = p - 1; endPos > startPos + 1 && LDAP_DN_ASCII_SPACE( endPos[ -1 ] ) && !LDAP_DN_ESCAPE( endPos[ -2 ] ); endPos-- ) { /* no op */ } } *next = p; if ( flags & LDAP_DN_SKIP ) { return( 0 ); } len = ( endPos ? endPos : p ) - startPos - escapes; val->bv_len = len; if ( escapes == 0 ){ val->bv_val = LDAP_STRNDUPX( startPos, len, ctx ); } else { ber_len_t s, d; val->bv_val = LDAP_MALLOCX( len + 1, ctx ); for ( s = 0, d = 0; d < len; ) { /* * This point is reached only if escapes * are properly used, so all we need to * do is eat them */ if ( LDAP_DN_ESCAPE_DCE( startPos[ s ] ) ) { s++; } val->bv_val[ d++ ] = startPos[ s++ ]; } val->bv_val[ d ] = '\0'; assert( strlen( val->bv_val ) == len ); } return( 0 ); } static int IA52strval( const char *str, struct berval *val, const char **next, unsigned flags, void *ctx ) { const char *p, *startPos, *endPos = NULL; ber_len_t len, escapes; assert( str != NULL ); assert( val != NULL ); assert( next != NULL ); *next = NULL; /* * LDAPv2 (RFC 1779) */ for ( startPos = p = str, escapes = 0; p[ 0 ]; p++ ) { if ( LDAP_DN_ESCAPE( p[ 0 ] ) ) { p++; if ( p[ 0 ] == '\0' ) { return( 1 ); } if ( !LDAP_DN_NEEDESCAPE( p[ 0 ] ) && ( LDAP_DN_PEDANTIC & flags ) ) { return( 1 ); } escapes++; } else if ( LDAP_DN_VALUE_END_V2( p[ 0 ] ) ) { break; } /* * FIXME: can we accept anything else? I guess we need * to stop if a value is not legal */ } /* strip trailing (unescaped) spaces */ for ( endPos = p; endPos > startPos + 1 && LDAP_DN_ASCII_SPACE( endPos[ -1 ] ) && !LDAP_DN_ESCAPE( endPos[ -2 ] ); endPos-- ) { /* no op */ } *next = p; if ( flags & LDAP_DN_SKIP ) { return( 0 ); } len = ( endPos ? endPos : p ) - startPos - escapes; val->bv_len = len; if ( escapes == 0 ) { val->bv_val = LDAP_STRNDUPX( startPos, len, ctx ); } else { ber_len_t s, d; val->bv_val = LDAP_MALLOCX( len + 1, ctx ); for ( s = 0, d = 0; d < len; ) { if ( LDAP_DN_ESCAPE( startPos[ s ] ) ) { s++; } val->bv_val[ d++ ] = startPos[ s++ ]; } val->bv_val[ d ] = '\0'; assert( strlen( val->bv_val ) == len ); } return( 0 ); } static int quotedIA52strval( const char *str, struct berval *val, const char **next, unsigned flags, void *ctx ) { const char *p, *startPos, *endPos = NULL; ber_len_t len; unsigned escapes = 0; assert( str != NULL ); assert( val != NULL ); assert( next != NULL ); *next = NULL; /* initial quote already eaten */ for ( startPos = p = str; p[ 0 ]; p++ ) { /* * According to RFC 1779, the quoted value can * contain escaped as well as unescaped special values; * as a consequence we tolerate escaped values * (e.g. '"\,"' -> '\,') and escape unescaped specials * (e.g. '","' -> '\,'). */ if ( LDAP_DN_ESCAPE( p[ 0 ] ) ) { if ( p[ 1 ] == '\0' ) { return( 1 ); } p++; if ( !LDAP_DN_V2_PAIR( p[ 0 ] ) && ( LDAP_DN_PEDANTIC & flags ) ) { /* * do we allow to escape normal chars? * LDAPv2 does not allow any mechanism * for escaping chars with '\' and hex * pair */ return( 1 ); } escapes++; } else if ( LDAP_DN_QUOTES( p[ 0 ] ) ) { endPos = p; /* eat closing quotes */ p++; break; } /* * FIXME: can we accept anything else? I guess we need * to stop if a value is not legal */ } if ( endPos == NULL ) { return( 1 ); } /* Strip trailing (unescaped) spaces */ for ( ; p[ 0 ] && LDAP_DN_ASCII_SPACE( p[ 0 ] ); p++ ) { /* no op */ } *next = p; if ( flags & LDAP_DN_SKIP ) { return( 0 ); } len = endPos - startPos - escapes; assert( endPos >= startPos + escapes ); val->bv_len = len; if ( escapes == 0 ) { val->bv_val = LDAP_STRNDUPX( startPos, len, ctx ); } else { ber_len_t s, d; val->bv_val = LDAP_MALLOCX( len + 1, ctx ); val->bv_len = len; for ( s = d = 0; d < len; ) { if ( LDAP_DN_ESCAPE( str[ s ] ) ) { s++; } val->bv_val[ d++ ] = str[ s++ ]; } val->bv_val[ d ] = '\0'; assert( strlen( val->bv_val ) == len ); } return( 0 ); } static int hexstr2bin( const char *str, char *c ) { char c1, c2; assert( str != NULL ); assert( c != NULL ); c1 = str[ 0 ]; c2 = str[ 1 ]; if ( LDAP_DN_ASCII_DIGIT( c1 ) ) { *c = c1 - '0'; } else { if ( LDAP_DN_ASCII_UCASE_HEXALPHA( c1 ) ) { *c = c1 - 'A' + 10; } else { assert( LDAP_DN_ASCII_LCASE_HEXALPHA( c1 ) ); *c = c1 - 'a' + 10; } } *c <<= 4; if ( LDAP_DN_ASCII_DIGIT( c2 ) ) { *c += c2 - '0'; } else { if ( LDAP_DN_ASCII_UCASE_HEXALPHA( c2 ) ) { *c += c2 - 'A' + 10; } else { assert( LDAP_DN_ASCII_LCASE_HEXALPHA( c2 ) ); *c += c2 - 'a' + 10; } } return( 0 ); } static int hexstr2binval( const char *str, struct berval *val, const char **next, unsigned flags, void *ctx ) { const char *p, *startPos, *endPos = NULL; ber_len_t len; ber_len_t s, d; assert( str != NULL ); assert( val != NULL ); assert( next != NULL ); *next = NULL; for ( startPos = p = str; p[ 0 ]; p += 2 ) { switch ( LDAP_DN_FORMAT( flags ) ) { case LDAP_DN_FORMAT_LDAPV3: if ( LDAP_DN_VALUE_END( p[ 0 ] ) ) { goto end_of_value; } break; case LDAP_DN_FORMAT_LDAP: case LDAP_DN_FORMAT_LDAPV2: if ( LDAP_DN_VALUE_END_V2( p[ 0 ] ) ) { goto end_of_value; } break; case LDAP_DN_FORMAT_DCE: if ( LDAP_DN_VALUE_END_DCE( p[ 0 ] ) ) { goto end_of_value; } break; } if ( LDAP_DN_ASCII_SPACE( p[ 0 ] ) ) { if ( flags & LDAP_DN_PEDANTIC ) { return( 1 ); } endPos = p; for ( ; p[ 0 ]; p++ ) { switch ( LDAP_DN_FORMAT( flags ) ) { case LDAP_DN_FORMAT_LDAPV3: if ( LDAP_DN_VALUE_END( p[ 0 ] ) ) { goto end_of_value; } break; case LDAP_DN_FORMAT_LDAP: case LDAP_DN_FORMAT_LDAPV2: if ( LDAP_DN_VALUE_END_V2( p[ 0 ] ) ) { goto end_of_value; } break; case LDAP_DN_FORMAT_DCE: if ( LDAP_DN_VALUE_END_DCE( p[ 0 ] ) ) { goto end_of_value; } break; } } break; } if ( !LDAP_DN_HEXPAIR( p ) ) { return( 1 ); } } end_of_value:; *next = p; if ( flags & LDAP_DN_SKIP ) { return( 0 ); } len = ( ( endPos ? endPos : p ) - startPos ) / 2; /* must be even! */ assert( 2 * len == (ber_len_t) (( endPos ? endPos : p ) - startPos )); val->bv_len = len; val->bv_val = LDAP_MALLOCX( len + 1, ctx ); if ( val->bv_val == NULL ) { return( LDAP_NO_MEMORY ); } for ( s = 0, d = 0; d < len; s += 2, d++ ) { char c; hexstr2bin( &startPos[ s ], &c ); val->bv_val[ d ] = c; } val->bv_val[ d ] = '\0'; return( 0 ); } /* * convert a byte in a hexadecimal pair */ static int byte2hexpair( const char *val, char *pair ) { static const char hexdig[] = "0123456789ABCDEF"; assert( val != NULL ); assert( pair != NULL ); /* * we assume the string has enough room for the hex encoding * of the value */ pair[ 0 ] = hexdig[ 0x0f & ( val[ 0 ] >> 4 ) ]; pair[ 1 ] = hexdig[ 0x0f & val[ 0 ] ]; return( 0 ); } /* * convert a binary value in hexadecimal pairs */ static int binval2hexstr( struct berval *val, char *str ) { ber_len_t s, d; assert( val != NULL ); assert( str != NULL ); if ( val->bv_len == 0 ) { return( 0 ); } /* * we assume the string has enough room for the hex encoding * of the value */ for ( s = 0, d = 0; s < val->bv_len; s++, d += 2 ) { byte2hexpair( &val->bv_val[ s ], &str[ d ] ); } return( 0 ); } /* * Length of the string representation, accounting for escaped hex * of UTF-8 chars */ static int strval2strlen( struct berval *val, unsigned flags, ber_len_t *len ) { ber_len_t l, cl = 1; char *p, *end; int escaped_byte_len = LDAP_DN_IS_PRETTY( flags ) ? 1 : 3; #ifdef PRETTY_ESCAPE int escaped_ascii_len = LDAP_DN_IS_PRETTY( flags ) ? 2 : 3; #endif /* PRETTY_ESCAPE */ assert( val != NULL ); assert( len != NULL ); *len = 0; if ( val->bv_len == 0 ) { return( 0 ); } end = val->bv_val + val->bv_len - 1; for ( l = 0, p = val->bv_val; p <= end; p += cl ) { /* * escape '%x00' */ if ( p[ 0 ] == '\0' ) { cl = 1; l += 3; continue; } cl = LDAP_UTF8_CHARLEN2( p, cl ); if ( cl == 0 ) { /* illegal utf-8 char! */ return( -1 ); } else if ( cl > 1 ) { ber_len_t cnt; for ( cnt = 1; cnt < cl; cnt++ ) { if ( ( p[ cnt ] & 0xc0 ) != 0x80 ) { return( -1 ); } } l += escaped_byte_len * cl; } else if ( LDAP_DN_NEEDESCAPE( p[ 0 ] ) || LDAP_DN_SHOULDESCAPE( p[ 0 ] ) || ( p == val->bv_val && LDAP_DN_NEEDESCAPE_LEAD( p[ 0 ] ) ) || ( p == end && LDAP_DN_NEEDESCAPE_TRAIL( p[ 0 ] ) ) ) { #ifdef PRETTY_ESCAPE #if 0 if ( LDAP_DN_WILLESCAPE_HEX( flags, p[ 0 ] ) ) { #else if ( LDAP_DN_WILLESCAPE_CHAR( p[ 0 ] ) ) { #endif /* * there might be some chars we want * to escape in form of a couple * of hexdigits for optimization purposes */ l += 3; } else { l += escaped_ascii_len; } #else /* ! PRETTY_ESCAPE */ l += 3; #endif /* ! PRETTY_ESCAPE */ } else { l++; } } *len = l; return( 0 ); } /* * convert to string representation, escaping with hex the UTF-8 stuff; * assume the destination has enough room for escaping */ static int strval2str( struct berval *val, char *str, unsigned flags, ber_len_t *len ) { ber_len_t s, d, end; assert( val != NULL ); assert( str != NULL ); assert( len != NULL ); if ( val->bv_len == 0 ) { *len = 0; return( 0 ); } /* * we assume the string has enough room for the hex encoding * of the value */ for ( s = 0, d = 0, end = val->bv_len - 1; s < val->bv_len; ) { ber_len_t cl; /* * escape '%x00' */ if ( val->bv_val[ s ] == '\0' ) { cl = 1; str[ d++ ] = '\\'; str[ d++ ] = '0'; str[ d++ ] = '0'; s++; continue; } /* * The length was checked in strval2strlen(); */ cl = LDAP_UTF8_CHARLEN( &val->bv_val[ s ] ); /* * there might be some chars we want to escape in form * of a couple of hexdigits for optimization purposes */ if ( ( cl > 1 && !LDAP_DN_IS_PRETTY( flags ) ) #ifdef PRETTY_ESCAPE #if 0 || LDAP_DN_WILLESCAPE_HEX( flags, val->bv_val[ s ] ) #else || LDAP_DN_WILLESCAPE_CHAR( val->bv_val[ s ] ) #endif #else /* ! PRETTY_ESCAPE */ || LDAP_DN_NEEDESCAPE( val->bv_val[ s ] ) || LDAP_DN_SHOULDESCAPE( val->bv_val[ s ] ) || ( d == 0 && LDAP_DN_NEEDESCAPE_LEAD( val->bv_val[ s ] ) ) || ( s == end && LDAP_DN_NEEDESCAPE_TRAIL( val->bv_val[ s ] ) ) #endif /* ! PRETTY_ESCAPE */ ) { for ( ; cl--; ) { str[ d++ ] = '\\'; byte2hexpair( &val->bv_val[ s ], &str[ d ] ); s++; d += 2; } } else if ( cl > 1 ) { for ( ; cl--; ) { str[ d++ ] = val->bv_val[ s++ ]; } } else { #ifdef PRETTY_ESCAPE if ( LDAP_DN_NEEDESCAPE( val->bv_val[ s ] ) || LDAP_DN_SHOULDESCAPE( val->bv_val[ s ] ) || ( d == 0 && LDAP_DN_NEEDESCAPE_LEAD( val->bv_val[ s ] ) ) || ( s == end && LDAP_DN_NEEDESCAPE_TRAIL( val->bv_val[ s ] ) ) ) { str[ d++ ] = '\\'; if ( !LDAP_DN_IS_PRETTY( flags ) ) { byte2hexpair( &val->bv_val[ s ], &str[ d ] ); s++; d += 2; continue; } } #endif /* PRETTY_ESCAPE */ str[ d++ ] = val->bv_val[ s++ ]; } } *len = d; return( 0 ); } /* * Length of the IA5 string representation (no UTF-8 allowed) */ static int strval2IA5strlen( struct berval *val, unsigned flags, ber_len_t *len ) { ber_len_t l; char *p; assert( val != NULL ); assert( len != NULL ); *len = 0; if ( val->bv_len == 0 ) { return( 0 ); } if ( flags & LDAP_AVA_NONPRINTABLE ) { /* * Turn value into a binary encoded BER */ return( -1 ); } else { for ( l = 0, p = val->bv_val; p[ 0 ]; p++ ) { if ( LDAP_DN_NEEDESCAPE( p[ 0 ] ) || LDAP_DN_SHOULDESCAPE( p[ 0 ] ) || ( p == val->bv_val && LDAP_DN_NEEDESCAPE_LEAD( p[ 0 ] ) ) || ( !p[ 1 ] && LDAP_DN_NEEDESCAPE_TRAIL( p[ 0 ] ) ) ) { l += 2; } else { l++; } } } *len = l; return( 0 ); } /* * convert to string representation (np UTF-8) * assume the destination has enough room for escaping */ static int strval2IA5str( struct berval *val, char *str, unsigned flags, ber_len_t *len ) { ber_len_t s, d, end; assert( val != NULL ); assert( str != NULL ); assert( len != NULL ); if ( val->bv_len == 0 ) { *len = 0; return( 0 ); } if ( flags & LDAP_AVA_NONPRINTABLE ) { /* * Turn value into a binary encoded BER */ *len = 0; return( -1 ); } else { /* * we assume the string has enough room for the hex encoding * of the value */ for ( s = 0, d = 0, end = val->bv_len - 1; s < val->bv_len; ) { if ( LDAP_DN_NEEDESCAPE( val->bv_val[ s ] ) || LDAP_DN_SHOULDESCAPE( val->bv_val[ s ] ) || ( s == 0 && LDAP_DN_NEEDESCAPE_LEAD( val->bv_val[ s ] ) ) || ( s == end && LDAP_DN_NEEDESCAPE_TRAIL( val->bv_val[ s ] ) ) ) { str[ d++ ] = '\\'; } str[ d++ ] = val->bv_val[ s++ ]; } } *len = d; return( 0 ); } /* * Length of the (supposedly) DCE string representation, * accounting for escaped hex of UTF-8 chars */ static int strval2DCEstrlen( struct berval *val, unsigned flags, ber_len_t *len ) { ber_len_t l; char *p; assert( val != NULL ); assert( len != NULL ); *len = 0; if ( val->bv_len == 0 ) { return( 0 ); } if ( flags & LDAP_AVA_NONPRINTABLE ) { /* * FIXME: Turn the value into a binary encoded BER? */ return( -1 ); } else { for ( l = 0, p = val->bv_val; p[ 0 ]; p++ ) { if ( LDAP_DN_NEEDESCAPE_DCE( p[ 0 ] ) ) { l += 2; } else { l++; } } } *len = l; return( 0 ); } /* * convert to (supposedly) DCE string representation, * escaping with hex the UTF-8 stuff; * assume the destination has enough room for escaping */ static int strval2DCEstr( struct berval *val, char *str, unsigned flags, ber_len_t *len ) { ber_len_t s, d; assert( val != NULL ); assert( str != NULL ); assert( len != NULL ); if ( val->bv_len == 0 ) { *len = 0; return( 0 ); } if ( flags & LDAP_AVA_NONPRINTABLE ) { /* * FIXME: Turn the value into a binary encoded BER? */ *len = 0; return( -1 ); } else { /* * we assume the string has enough room for the hex encoding * of the value */ for ( s = 0, d = 0; s < val->bv_len; ) { if ( LDAP_DN_NEEDESCAPE_DCE( val->bv_val[ s ] ) ) { str[ d++ ] = '\\'; } str[ d++ ] = val->bv_val[ s++ ]; } } *len = d; return( 0 ); } /* * Length of the (supposedly) AD canonical string representation, * accounting for chars that need to be escaped */ static int strval2ADstrlen( struct berval *val, unsigned flags, ber_len_t *len ) { ber_len_t l, cl; char *p; assert( val != NULL ); assert( len != NULL ); *len = 0; if ( val->bv_len == 0 ) { return( 0 ); } for ( l = 0, p = val->bv_val; p[ 0 ]; p += cl ) { cl = LDAP_UTF8_CHARLEN2( p, cl ); if ( cl == 0 ) { /* illegal utf-8 char */ return -1; } else if ( (cl == 1) && LDAP_DN_NEEDESCAPE_AD( p[ 0 ] ) ) { l += 2; } else { l += cl; } } *len = l; return( 0 ); } /* * convert to (supposedly) AD string representation, * assume the destination has enough room for escaping */ static int strval2ADstr( struct berval *val, char *str, unsigned flags, ber_len_t *len ) { ber_len_t s, d, cl; assert( val != NULL ); assert( str != NULL ); assert( len != NULL ); if ( val->bv_len == 0 ) { *len = 0; return( 0 ); } /* * we assume the string has enough room for the escaping * of the value */ for ( s = 0, d = 0; s < val->bv_len; ) { cl = LDAP_UTF8_CHARLEN2( val->bv_val+s, cl ); if ( cl == 0 ) { /* illegal utf-8 char */ return -1; } else if ( (cl == 1) && LDAP_DN_NEEDESCAPE_AD(val->bv_val[ s ]) ) { str[ d++ ] = '\\'; } for (; cl--;) { str[ d++ ] = val->bv_val[ s++ ]; } } *len = d; return( 0 ); } /* * If the DN is terminated by single-AVA RDNs with attribute type of "dc", * the first part of the AD representation of the DN is written in DNS * form, i.e. dot separated domain name components (as suggested * by Luke Howard, http://www.padl.com/~lukeh) */ static int dn2domain( LDAPDN dn, struct berval *bv, int pos, int *iRDN ) { int i; int domain = 0, first = 1; ber_len_t l = 1; /* we move the null also */ char *str; /* we are guaranteed there's enough memory in str */ /* sanity */ assert( dn != NULL ); assert( bv != NULL ); assert( iRDN != NULL ); assert( *iRDN >= 0 ); str = bv->bv_val + pos; for ( i = *iRDN; i >= 0; i-- ) { LDAPRDN rdn; LDAPAVA *ava; assert( dn[ i ] != NULL ); rdn = dn[ i ]; assert( rdn[ 0 ] != NULL ); ava = rdn[ 0 ]; if ( !LDAP_DN_IS_RDN_DC( rdn ) ) { break; } domain = 1; if ( first ) { first = 0; AC_MEMCPY( str, ava->la_value.bv_val, ava->la_value.bv_len + 1); l += ava->la_value.bv_len; } else { AC_MEMCPY( str + ava->la_value.bv_len + 1, bv->bv_val + pos, l); AC_MEMCPY( str, ava->la_value.bv_val, ava->la_value.bv_len ); str[ ava->la_value.bv_len ] = '.'; l += ava->la_value.bv_len + 1; } } *iRDN = i; bv->bv_len = pos + l - 1; return( domain ); } static int rdn2strlen( LDAPRDN rdn, unsigned flags, ber_len_t *len, int ( *s2l )( struct berval *v, unsigned f, ber_len_t *l ) ) { int iAVA; ber_len_t l = 0; *len = 0; for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) { LDAPAVA *ava = rdn[ iAVA ]; /* len(type) + '=' + '+' | ',' */ l += ava->la_attr.bv_len + 2; if ( ava->la_flags & LDAP_AVA_BINARY ) { /* octothorpe + twice the length */ l += 1 + 2 * ava->la_value.bv_len; } else { ber_len_t vl; unsigned f = flags | ava->la_flags; if ( ( *s2l )( &ava->la_value, f, &vl ) ) { return( -1 ); } l += vl; } } *len = l; return( 0 ); } static int rdn2str( LDAPRDN rdn, char *str, unsigned flags, ber_len_t *len, int ( *s2s ) ( struct berval *v, char * s, unsigned f, ber_len_t *l ) ) { int iAVA; ber_len_t l = 0; for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) { LDAPAVA *ava = rdn[ iAVA ]; AC_MEMCPY( &str[ l ], ava->la_attr.bv_val, ava->la_attr.bv_len ); l += ava->la_attr.bv_len; str[ l++ ] = '='; if ( ava->la_flags & LDAP_AVA_BINARY ) { str[ l++ ] = '#'; if ( binval2hexstr( &ava->la_value, &str[ l ] ) ) { return( -1 ); } l += 2 * ava->la_value.bv_len; } else { ber_len_t vl; unsigned f = flags | ava->la_flags; if ( ( *s2s )( &ava->la_value, &str[ l ], f, &vl ) ) { return( -1 ); } l += vl; } str[ l++ ] = ( rdn[ iAVA + 1] ? '+' : ',' ); } *len = l; return( 0 ); } static int rdn2DCEstrlen( LDAPRDN rdn, unsigned flags, ber_len_t *len ) { int iAVA; ber_len_t l = 0; *len = 0; for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) { LDAPAVA *ava = rdn[ iAVA ]; /* len(type) + '=' + ',' | '/' */ l += ava->la_attr.bv_len + 2; if ( ava->la_flags & LDAP_AVA_BINARY ) { /* octothorpe + twice the length */ l += 1 + 2 * ava->la_value.bv_len; } else { ber_len_t vl; unsigned f = flags | ava->la_flags; if ( strval2DCEstrlen( &ava->la_value, f, &vl ) ) { return( -1 ); } l += vl; } } *len = l; return( 0 ); } static int rdn2DCEstr( LDAPRDN rdn, char *str, unsigned flags, ber_len_t *len, int first ) { int iAVA; ber_len_t l = 0; for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) { LDAPAVA *ava = rdn[ iAVA ]; if ( first ) { first = 0; } else { str[ l++ ] = ( iAVA ? ',' : '/' ); } AC_MEMCPY( &str[ l ], ava->la_attr.bv_val, ava->la_attr.bv_len ); l += ava->la_attr.bv_len; str[ l++ ] = '='; if ( ava->la_flags & LDAP_AVA_BINARY ) { str[ l++ ] = '#'; if ( binval2hexstr( &ava->la_value, &str[ l ] ) ) { return( -1 ); } l += 2 * ava->la_value.bv_len; } else { ber_len_t vl; unsigned f = flags | ava->la_flags; if ( strval2DCEstr( &ava->la_value, &str[ l ], f, &vl ) ) { return( -1 ); } l += vl; } } *len = l; return( 0 ); } static int rdn2UFNstrlen( LDAPRDN rdn, unsigned flags, ber_len_t *len ) { int iAVA; ber_len_t l = 0; assert( rdn != NULL ); assert( len != NULL ); *len = 0; for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) { LDAPAVA *ava = rdn[ iAVA ]; /* ' + ' | ', ' */ l += ( rdn[ iAVA + 1 ] ? 3 : 2 ); /* FIXME: are binary values allowed in UFN? */ if ( ava->la_flags & LDAP_AVA_BINARY ) { /* octothorpe + twice the value */ l += 1 + 2 * ava->la_value.bv_len; } else { ber_len_t vl; unsigned f = flags | ava->la_flags; if ( strval2strlen( &ava->la_value, f, &vl ) ) { return( -1 ); } l += vl; } } *len = l; return( 0 ); } static int rdn2UFNstr( LDAPRDN rdn, char *str, unsigned flags, ber_len_t *len ) { int iAVA; ber_len_t l = 0; for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) { LDAPAVA *ava = rdn[ iAVA ]; if ( ava->la_flags & LDAP_AVA_BINARY ) { str[ l++ ] = '#'; if ( binval2hexstr( &ava->la_value, &str[ l ] ) ) { return( -1 ); } l += 2 * ava->la_value.bv_len; } else { ber_len_t vl; unsigned f = flags | ava->la_flags; if ( strval2str( &ava->la_value, &str[ l ], f, &vl ) ) { return( -1 ); } l += vl; } if ( rdn[ iAVA + 1 ] ) { AC_MEMCPY( &str[ l ], " + ", 3 ); l += 3; } else { AC_MEMCPY( &str[ l ], ", ", 2 ); l += 2; } } *len = l; return( 0 ); } static int rdn2ADstrlen( LDAPRDN rdn, unsigned flags, ber_len_t *len ) { int iAVA; ber_len_t l = 0; assert( rdn != NULL ); assert( len != NULL ); *len = 0; for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) { LDAPAVA *ava = rdn[ iAVA ]; /* ',' | '/' */ l++; /* FIXME: are binary values allowed in UFN? */ if ( ava->la_flags & LDAP_AVA_BINARY ) { /* octothorpe + twice the value */ l += 1 + 2 * ava->la_value.bv_len; } else { ber_len_t vl; unsigned f = flags | ava->la_flags; if ( strval2ADstrlen( &ava->la_value, f, &vl ) ) { return( -1 ); } l += vl; } } *len = l; return( 0 ); } static int rdn2ADstr( LDAPRDN rdn, char *str, unsigned flags, ber_len_t *len, int first ) { int iAVA; ber_len_t l = 0; for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) { LDAPAVA *ava = rdn[ iAVA ]; if ( first ) { first = 0; } else { str[ l++ ] = ( iAVA ? ',' : '/' ); } if ( ava->la_flags & LDAP_AVA_BINARY ) { str[ l++ ] = '#'; if ( binval2hexstr( &ava->la_value, &str[ l ] ) ) { return( -1 ); } l += 2 * ava->la_value.bv_len; } else { ber_len_t vl; unsigned f = flags | ava->la_flags; if ( strval2ADstr( &ava->la_value, &str[ l ], f, &vl ) ) { return( -1 ); } l += vl; } } *len = l; return( 0 ); } /* * ldap_rdn2str * * Returns in str a string representation of rdn based on flags. * There is some duplication of code between this and ldap_dn2str; * this is wanted to reduce the allocation of temporary buffers. */ int ldap_rdn2str( LDAPRDN rdn, char **str, unsigned flags ) { struct berval bv; int rc; assert( str != NULL ); if((flags & LDAP_DN_FORMAT_MASK) == LDAP_DN_FORMAT_LBER) { return LDAP_PARAM_ERROR; } rc = ldap_rdn2bv_x( rdn, &bv, flags, NULL ); *str = bv.bv_val; return rc; } int ldap_rdn2bv( LDAPRDN rdn, struct berval *bv, unsigned flags ) { return ldap_rdn2bv_x( rdn, bv, flags, NULL ); } int ldap_rdn2bv_x( LDAPRDN rdn, struct berval *bv, unsigned flags, void *ctx ) { int rc, back; ber_len_t l; assert( bv != NULL ); bv->bv_len = 0; bv->bv_val = NULL; if ( rdn == NULL ) { bv->bv_val = LDAP_STRDUPX( "", ctx ); return( LDAP_SUCCESS ); } /* * This routine wastes "back" bytes at the end of the string */ switch ( LDAP_DN_FORMAT( flags ) ) { case LDAP_DN_FORMAT_LDAPV3: if ( rdn2strlen( rdn, flags, &l, strval2strlen ) ) { return LDAP_DECODING_ERROR; } break; case LDAP_DN_FORMAT_LDAPV2: if ( rdn2strlen( rdn, flags, &l, strval2IA5strlen ) ) { return LDAP_DECODING_ERROR; } break; case LDAP_DN_FORMAT_UFN: if ( rdn2UFNstrlen( rdn, flags, &l ) ) { return LDAP_DECODING_ERROR; } break; case LDAP_DN_FORMAT_DCE: if ( rdn2DCEstrlen( rdn, flags, &l ) ) { return LDAP_DECODING_ERROR; } break; case LDAP_DN_FORMAT_AD_CANONICAL: if ( rdn2ADstrlen( rdn, flags, &l ) ) { return LDAP_DECODING_ERROR; } break; default: return LDAP_PARAM_ERROR; } bv->bv_val = LDAP_MALLOCX( l + 1, ctx ); switch ( LDAP_DN_FORMAT( flags ) ) { case LDAP_DN_FORMAT_LDAPV3: rc = rdn2str( rdn, bv->bv_val, flags, &l, strval2str ); back = 1; break; case LDAP_DN_FORMAT_LDAPV2: rc = rdn2str( rdn, bv->bv_val, flags, &l, strval2IA5str ); back = 1; break; case LDAP_DN_FORMAT_UFN: rc = rdn2UFNstr( rdn, bv->bv_val, flags, &l ); back = 2; break; case LDAP_DN_FORMAT_DCE: rc = rdn2DCEstr( rdn, bv->bv_val, flags, &l, 1 ); back = 0; break; case LDAP_DN_FORMAT_AD_CANONICAL: rc = rdn2ADstr( rdn, bv->bv_val, flags, &l, 1 ); back = 0; break; default: /* need at least one of the previous */ return LDAP_PARAM_ERROR; } if ( rc ) { LDAP_FREEX( bv->bv_val, ctx ); return rc; } bv->bv_len = l - back; bv->bv_val[ bv->bv_len ] = '\0'; return LDAP_SUCCESS; } /* * Very bulk implementation; many optimizations can be performed * - a NULL dn results in an empty string "" * * FIXME: doubts * a) what do we do if a UTF-8 string must be converted in LDAPv2? * we must encode it in binary form ('#' + HEXPAIRs) * b) does DCE/AD support UTF-8? * no clue; don't think so. * c) what do we do when binary values must be converted in UTF/DCE/AD? * use binary encoded BER */ int ldap_dn2str( LDAPDN dn, char **str, unsigned flags ) { struct berval bv; int rc; assert( str != NULL ); if((flags & LDAP_DN_FORMAT_MASK) == LDAP_DN_FORMAT_LBER) { return LDAP_PARAM_ERROR; } rc = ldap_dn2bv_x( dn, &bv, flags, NULL ); *str = bv.bv_val; return rc; } int ldap_dn2bv( LDAPDN dn, struct berval *bv, unsigned flags ) { return ldap_dn2bv_x( dn, bv, flags, NULL ); } int ldap_dn2bv_x( LDAPDN dn, struct berval *bv, unsigned flags, void *ctx ) { int iRDN; int rc = LDAP_ENCODING_ERROR; ber_len_t len, l; /* stringifying helpers for LDAPv3/LDAPv2 */ int ( *sv2l ) ( struct berval *v, unsigned f, ber_len_t *l ); int ( *sv2s ) ( struct berval *v, char *s, unsigned f, ber_len_t *l ); assert( bv != NULL ); bv->bv_len = 0; bv->bv_val = NULL; Debug( LDAP_DEBUG_ARGS, "=> ldap_dn2bv(%u)\n", flags, 0, 0 ); /* * a null dn means an empty dn string * FIXME: better raise an error? */ if ( dn == NULL || dn[0] == NULL ) { bv->bv_val = LDAP_STRDUPX( "", ctx ); return( LDAP_SUCCESS ); } switch ( LDAP_DN_FORMAT( flags ) ) { case LDAP_DN_FORMAT_LDAPV3: sv2l = strval2strlen; sv2s = strval2str; if( 0 ) { case LDAP_DN_FORMAT_LDAPV2: sv2l = strval2IA5strlen; sv2s = strval2IA5str; } for ( iRDN = 0, len = 0; dn[ iRDN ]; iRDN++ ) { ber_len_t rdnl; if ( rdn2strlen( dn[ iRDN ], flags, &rdnl, sv2l ) ) { goto return_results; } len += rdnl; } if ( ( bv->bv_val = LDAP_MALLOCX( len + 1, ctx ) ) == NULL ) { rc = LDAP_NO_MEMORY; break; } for ( l = 0, iRDN = 0; dn[ iRDN ]; iRDN++ ) { ber_len_t rdnl; if ( rdn2str( dn[ iRDN ], &bv->bv_val[ l ], flags, &rdnl, sv2s ) ) { LDAP_FREEX( bv->bv_val, ctx ); bv->bv_val = NULL; goto return_results; } l += rdnl; } assert( l == len ); /* * trim the last ',' (the allocated memory * is one byte longer than required) */ bv->bv_len = len - 1; bv->bv_val[ bv->bv_len ] = '\0'; rc = LDAP_SUCCESS; break; case LDAP_DN_FORMAT_UFN: { /* * FIXME: quoting from RFC 1781: * To take a distinguished name, and generate a name of this format with attribute types omitted, the following steps are followed. 1. If the first attribute is of type CommonName, the type may be omitted. 2. If the last attribute is of type Country, the type may be omitted. 3. If the last attribute is of type Country, the last Organisation attribute may have the type omitted. 4. All attributes of type OrganisationalUnit may have the type omitted, unless they are after an Organisation attribute or the first attribute is of type OrganisationalUnit. * this should be the pedantic implementation. * * Here the standard implementation reflects * the one historically provided by OpenLDAP * (and UMIch, I presume), with the variant * of spaces and plusses (' + ') separating * rdn components. * * A non-standard but nice implementation could * be to turn the final "dc" attributes into a * dot-separated domain. * * Other improvements could involve the use of * friendly country names and so. */ #ifdef DC_IN_UFN int leftmost_dc = -1; int last_iRDN = -1; #endif /* DC_IN_UFN */ for ( iRDN = 0, len = 0; dn[ iRDN ]; iRDN++ ) { ber_len_t rdnl; if ( rdn2UFNstrlen( dn[ iRDN ], flags, &rdnl ) ) { goto return_results; } len += rdnl; #ifdef DC_IN_UFN if ( LDAP_DN_IS_RDN_DC( dn[ iRDN ] ) ) { if ( leftmost_dc == -1 ) { leftmost_dc = iRDN; } } else { leftmost_dc = -1; } #endif /* DC_IN_UFN */ } if ( ( bv->bv_val = LDAP_MALLOCX( len + 1, ctx ) ) == NULL ) { rc = LDAP_NO_MEMORY; break; } #ifdef DC_IN_UFN if ( leftmost_dc == -1 ) { #endif /* DC_IN_UFN */ for ( l = 0, iRDN = 0; dn[ iRDN ]; iRDN++ ) { ber_len_t vl; if ( rdn2UFNstr( dn[ iRDN ], &bv->bv_val[ l ], flags, &vl ) ) { LDAP_FREEX( bv->bv_val, ctx ); bv->bv_val = NULL; goto return_results; } l += vl; } /* * trim the last ', ' (the allocated memory * is two bytes longer than required) */ bv->bv_len = len - 2; bv->bv_val[ bv->bv_len ] = '\0'; #ifdef DC_IN_UFN } else { last_iRDN = iRDN - 1; for ( l = 0, iRDN = 0; iRDN < leftmost_dc; iRDN++ ) { ber_len_t vl; if ( rdn2UFNstr( dn[ iRDN ], &bv->bv_val[ l ], flags, &vl ) ) { LDAP_FREEX( bv->bv_val, ctx ); bv->bv_val = NULL; goto return_results; } l += vl; } if ( !dn2domain( dn, bv, l, &last_iRDN ) ) { LDAP_FREEX( bv->bv_val, ctx ); bv->bv_val = NULL; goto return_results; } /* the string is correctly terminated by dn2domain */ } #endif /* DC_IN_UFN */ rc = LDAP_SUCCESS; } break; case LDAP_DN_FORMAT_DCE: for ( iRDN = 0, len = 0; dn[ iRDN ]; iRDN++ ) { ber_len_t rdnl; if ( rdn2DCEstrlen( dn[ iRDN ], flags, &rdnl ) ) { goto return_results; } len += rdnl; } if ( ( bv->bv_val = LDAP_MALLOCX( len + 1, ctx ) ) == NULL ) { rc = LDAP_NO_MEMORY; break; } for ( l = 0; iRDN--; ) { ber_len_t rdnl; if ( rdn2DCEstr( dn[ iRDN ], &bv->bv_val[ l ], flags, &rdnl, 0 ) ) { LDAP_FREEX( bv->bv_val, ctx ); bv->bv_val = NULL; goto return_results; } l += rdnl; } assert( l == len ); bv->bv_len = len; bv->bv_val[ bv->bv_len ] = '\0'; rc = LDAP_SUCCESS; break; case LDAP_DN_FORMAT_AD_CANONICAL: { int trailing_slash = 1; /* * Sort of UFN for DCE DNs: a slash ('/') separated * global->local DN with no types; strictly speaking, * the naming context should be a domain, which is * written in DNS-style, e.g. dot-deparated. * * Example: * * "givenName=Bill+sn=Gates,ou=People,dc=microsoft,dc=com" * * will read * * "microsoft.com/People/Bill,Gates" */ for ( iRDN = 0, len = -1; dn[ iRDN ]; iRDN++ ) { ber_len_t rdnl; if ( rdn2ADstrlen( dn[ iRDN ], flags, &rdnl ) ) { goto return_results; } len += rdnl; } /* reserve room for trailing '/' in case the DN * is exactly a domain */ if ( ( bv->bv_val = LDAP_MALLOCX( len + 1 + 1, ctx ) ) == NULL ) { rc = LDAP_NO_MEMORY; break; } iRDN--; if ( iRDN && dn2domain( dn, bv, 0, &iRDN ) != 0 ) { for ( l = bv->bv_len; iRDN >= 0 ; iRDN-- ) { ber_len_t rdnl; trailing_slash = 0; if ( rdn2ADstr( dn[ iRDN ], &bv->bv_val[ l ], flags, &rdnl, 0 ) ) { LDAP_FREEX( bv->bv_val, ctx ); bv->bv_val = NULL; goto return_results; } l += rdnl; } } else { int first = 1; /* * Strictly speaking, AD canonical requires * a DN to be in the form "..., dc=smtg", * i.e. terminated by a domain component */ if ( flags & LDAP_DN_PEDANTIC ) { LDAP_FREEX( bv->bv_val, ctx ); bv->bv_val = NULL; rc = LDAP_ENCODING_ERROR; break; } for ( l = 0; iRDN >= 0 ; iRDN-- ) { ber_len_t rdnl; if ( rdn2ADstr( dn[ iRDN ], &bv->bv_val[ l ], flags, &rdnl, first ) ) { LDAP_FREEX( bv->bv_val, ctx ); bv->bv_val = NULL; goto return_results; } if ( first ) { first = 0; } l += rdnl; } } if ( trailing_slash ) { /* the DN is exactly a domain -- need a trailing * slash; room was reserved in advance */ bv->bv_val[ len ] = '/'; len++; } bv->bv_len = len; bv->bv_val[ bv->bv_len ] = '\0'; rc = LDAP_SUCCESS; } break; default: return LDAP_PARAM_ERROR; } Debug( LDAP_DEBUG_ARGS, "<= ldap_dn2bv(%s)=%d %s\n", bv->bv_val, rc, rc ? ldap_err2string( rc ) : "" ); return_results:; return( rc ); } openldap-2.4.42+dfsg/libraries/libldap/addentry.c0000644000175000017500000000305612563404150020375 0ustar ryanryan/* addentry.c */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (c) 1990 Regents of the University of Michigan. * All rights reserved. */ #include "portable.h" #include #include #include #include #include #include "ldap-int.h" LDAPMessage * ldap_delete_result_entry( LDAPMessage **list, LDAPMessage *e ) { LDAPMessage *tmp, *prev = NULL; assert( list != NULL ); assert( e != NULL ); for ( tmp = *list; tmp != NULL && tmp != e; tmp = tmp->lm_chain ) prev = tmp; if ( tmp == NULL ) return( NULL ); if ( prev == NULL ) { if ( tmp->lm_chain ) tmp->lm_chain->lm_chain_tail = (*list)->lm_chain_tail; *list = tmp->lm_chain; } else { prev->lm_chain = tmp->lm_chain; if ( prev->lm_chain == NULL ) (*list)->lm_chain_tail = prev; } tmp->lm_chain = NULL; return( tmp ); } void ldap_add_result_entry( LDAPMessage **list, LDAPMessage *e ) { assert( list != NULL ); assert( e != NULL ); e->lm_chain = *list; if ( *list ) e->lm_chain_tail = (*list)->lm_chain_tail; else e->lm_chain_tail = e; *list = e; } openldap-2.4.42+dfsg/libraries/libldap/sort.c0000644000175000017500000000770612563404150017560 0ustar ryanryan/* sort.c -- LDAP library entry and value sort routines */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (c) 1994 Regents of the University of Michigan. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of Michigan at Ann Arbor. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. */ #include "portable.h" #include #include #include #include #include #include "ldap-int.h" struct entrything { char **et_vals; LDAPMessage *et_msg; int (*et_cmp_fn) LDAP_P((const char *a, const char *b)); }; static int et_cmp LDAP_P(( const void *aa, const void *bb)); int ldap_sort_strcasecmp( LDAP_CONST void *a, LDAP_CONST void *b ) { return( strcasecmp( *(char *const *)a, *(char *const *)b ) ); } static int et_cmp( const void *aa, const void *bb ) { int i, rc; const struct entrything *a = (const struct entrything *)aa; const struct entrything *b = (const struct entrything *)bb; if ( a->et_vals == NULL && b->et_vals == NULL ) return( 0 ); if ( a->et_vals == NULL ) return( -1 ); if ( b->et_vals == NULL ) return( 1 ); for ( i = 0; a->et_vals[i] && b->et_vals[i]; i++ ) { if ( (rc = a->et_cmp_fn( a->et_vals[i], b->et_vals[i] )) != 0 ) { return( rc ); } } if ( a->et_vals[i] == NULL && b->et_vals[i] == NULL ) return( 0 ); if ( a->et_vals[i] == NULL ) return( -1 ); return( 1 ); } int ldap_sort_entries( LDAP *ld, LDAPMessage **chain, LDAP_CONST char *attr, /* NULL => sort by DN */ int (*cmp) (LDAP_CONST char *, LDAP_CONST char *) ) { int i, count = 0; struct entrything *et; LDAPMessage *e, *ehead = NULL, *etail = NULL; LDAPMessage *ohead = NULL, *otail = NULL; LDAPMessage **ep; assert( ld != NULL ); /* Separate entries from non-entries */ for ( e = *chain; e; e=e->lm_chain ) { if ( e->lm_msgtype == LDAP_RES_SEARCH_ENTRY ) { count++; if ( !ehead ) ehead = e; if ( etail ) etail->lm_chain = e; etail = e; } else { if ( !ohead ) ohead = e; if ( otail ) otail->lm_chain = e; otail = e; } } if ( count < 2 ) { /* zero or one entries -- already sorted! */ if ( ehead ) { etail->lm_chain = ohead; *chain = ehead; } else { *chain = ohead; } return 0; } if ( (et = (struct entrything *) LDAP_MALLOC( count * sizeof(struct entrything) )) == NULL ) { ld->ld_errno = LDAP_NO_MEMORY; return( -1 ); } e = ehead; for ( i = 0; i < count; i++ ) { et[i].et_cmp_fn = cmp; et[i].et_msg = e; if ( attr == NULL ) { char *dn; dn = ldap_get_dn( ld, e ); et[i].et_vals = ldap_explode_dn( dn, 1 ); LDAP_FREE( dn ); } else { et[i].et_vals = ldap_get_values( ld, e, attr ); } e = e->lm_chain; } qsort( et, count, sizeof(struct entrything), et_cmp ); ep = chain; for ( i = 0; i < count; i++ ) { *ep = et[i].et_msg; ep = &(*ep)->lm_chain; LDAP_VFREE( et[i].et_vals ); } *ep = ohead; (*chain)->lm_chain_tail = otail ? otail : etail; LDAP_FREE( (char *) et ); return( 0 ); } int ldap_sort_values( LDAP *ld, char **vals, int (*cmp) (LDAP_CONST void *, LDAP_CONST void *) ) { int nel; for ( nel = 0; vals[nel] != NULL; nel++ ) ; /* NULL */ qsort( vals, nel, sizeof(char *), cmp ); return( 0 ); } openldap-2.4.42+dfsg/libraries/libldap/sasl.c0000644000175000017500000004504112563404150017525 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* * BindRequest ::= SEQUENCE { * version INTEGER, * name DistinguishedName, -- who * authentication CHOICE { * simple [0] OCTET STRING -- passwd * krbv42ldap [1] OCTET STRING -- OBSOLETE * krbv42dsa [2] OCTET STRING -- OBSOLETE * sasl [3] SaslCredentials -- LDAPv3 * } * } * * BindResponse ::= SEQUENCE { * COMPONENTS OF LDAPResult, * serverSaslCreds OCTET STRING OPTIONAL -- LDAPv3 * } * */ #include "portable.h" #include #include #include #include #include #include #include "ldap-int.h" /* * ldap_sasl_bind - bind to the ldap server (and X.500). * The dn (usually NULL), mechanism, and credentials are provided. * The message id of the request initiated is provided upon successful * (LDAP_SUCCESS) return. * * Example: * ldap_sasl_bind( ld, NULL, "mechanism", * cred, NULL, NULL, &msgid ) */ int ldap_sasl_bind( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *mechanism, struct berval *cred, LDAPControl **sctrls, LDAPControl **cctrls, int *msgidp ) { BerElement *ber; int rc; ber_int_t id; Debug( LDAP_DEBUG_TRACE, "ldap_sasl_bind\n", 0, 0, 0 ); assert( ld != NULL ); assert( LDAP_VALID( ld ) ); assert( msgidp != NULL ); /* check client controls */ rc = ldap_int_client_controls( ld, cctrls ); if( rc != LDAP_SUCCESS ) return rc; if( mechanism == LDAP_SASL_SIMPLE ) { if( dn == NULL && cred != NULL && cred->bv_len ) { /* use default binddn */ dn = ld->ld_defbinddn; } } else if( ld->ld_version < LDAP_VERSION3 ) { ld->ld_errno = LDAP_NOT_SUPPORTED; return ld->ld_errno; } if ( dn == NULL ) { dn = ""; } /* create a message to send */ if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) { ld->ld_errno = LDAP_NO_MEMORY; return ld->ld_errno; } assert( LBER_VALID( ber ) ); LDAP_NEXT_MSGID( ld, id ); if( mechanism == LDAP_SASL_SIMPLE ) { /* simple bind */ rc = ber_printf( ber, "{it{istON}" /*}*/, id, LDAP_REQ_BIND, ld->ld_version, dn, LDAP_AUTH_SIMPLE, cred ); } else if ( cred == NULL || cred->bv_val == NULL ) { /* SASL bind w/o credentials */ rc = ber_printf( ber, "{it{ist{sN}N}" /*}*/, id, LDAP_REQ_BIND, ld->ld_version, dn, LDAP_AUTH_SASL, mechanism ); } else { /* SASL bind w/ credentials */ rc = ber_printf( ber, "{it{ist{sON}N}" /*}*/, id, LDAP_REQ_BIND, ld->ld_version, dn, LDAP_AUTH_SASL, mechanism, cred ); } if( rc == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( -1 ); } /* Put Server Controls */ if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) { ber_free( ber, 1 ); return ld->ld_errno; } if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return ld->ld_errno; } /* send the message */ *msgidp = ldap_send_initial_request( ld, LDAP_REQ_BIND, dn, ber, id ); if(*msgidp < 0) return ld->ld_errno; return LDAP_SUCCESS; } int ldap_sasl_bind_s( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *mechanism, struct berval *cred, LDAPControl **sctrls, LDAPControl **cctrls, struct berval **servercredp ) { int rc, msgid; LDAPMessage *result; struct berval *scredp = NULL; Debug( LDAP_DEBUG_TRACE, "ldap_sasl_bind_s\n", 0, 0, 0 ); /* do a quick !LDAPv3 check... ldap_sasl_bind will do the rest. */ if( servercredp != NULL ) { if (ld->ld_version < LDAP_VERSION3) { ld->ld_errno = LDAP_NOT_SUPPORTED; return ld->ld_errno; } *servercredp = NULL; } rc = ldap_sasl_bind( ld, dn, mechanism, cred, sctrls, cctrls, &msgid ); if ( rc != LDAP_SUCCESS ) { return( rc ); } #ifdef LDAP_CONNECTIONLESS if (LDAP_IS_UDP(ld)) { return( rc ); } #endif if ( ldap_result( ld, msgid, LDAP_MSG_ALL, NULL, &result ) == -1 || !result ) { return( ld->ld_errno ); /* ldap_result sets ld_errno */ } /* parse the results */ scredp = NULL; if( servercredp != NULL ) { rc = ldap_parse_sasl_bind_result( ld, result, &scredp, 0 ); } if ( rc != LDAP_SUCCESS ) { ldap_msgfree( result ); return( rc ); } rc = ldap_result2error( ld, result, 1 ); if ( rc == LDAP_SUCCESS || rc == LDAP_SASL_BIND_IN_PROGRESS ) { if( servercredp != NULL ) { *servercredp = scredp; scredp = NULL; } } if ( scredp != NULL ) { ber_bvfree(scredp); } return rc; } /* * Parse BindResponse: * * BindResponse ::= [APPLICATION 1] SEQUENCE { * COMPONENTS OF LDAPResult, * serverSaslCreds [7] OCTET STRING OPTIONAL } * * LDAPResult ::= SEQUENCE { * resultCode ENUMERATED, * matchedDN LDAPDN, * errorMessage LDAPString, * referral [3] Referral OPTIONAL } */ int ldap_parse_sasl_bind_result( LDAP *ld, LDAPMessage *res, struct berval **servercredp, int freeit ) { ber_int_t errcode; struct berval* scred; ber_tag_t tag; BerElement *ber; Debug( LDAP_DEBUG_TRACE, "ldap_parse_sasl_bind_result\n", 0, 0, 0 ); assert( ld != NULL ); assert( LDAP_VALID( ld ) ); assert( res != NULL ); if( servercredp != NULL ) { if( ld->ld_version < LDAP_VERSION2 ) { return LDAP_NOT_SUPPORTED; } *servercredp = NULL; } if( res->lm_msgtype != LDAP_RES_BIND ) { ld->ld_errno = LDAP_PARAM_ERROR; return ld->ld_errno; } scred = NULL; if ( ld->ld_error ) { LDAP_FREE( ld->ld_error ); ld->ld_error = NULL; } if ( ld->ld_matched ) { LDAP_FREE( ld->ld_matched ); ld->ld_matched = NULL; } /* parse results */ ber = ber_dup( res->lm_ber ); if( ber == NULL ) { ld->ld_errno = LDAP_NO_MEMORY; return ld->ld_errno; } if ( ld->ld_version < LDAP_VERSION2 ) { tag = ber_scanf( ber, "{iA}", &errcode, &ld->ld_error ); if( tag == LBER_ERROR ) { ber_free( ber, 0 ); ld->ld_errno = LDAP_DECODING_ERROR; return ld->ld_errno; } } else { ber_len_t len; tag = ber_scanf( ber, "{eAA" /*}*/, &errcode, &ld->ld_matched, &ld->ld_error ); if( tag == LBER_ERROR ) { ber_free( ber, 0 ); ld->ld_errno = LDAP_DECODING_ERROR; return ld->ld_errno; } tag = ber_peek_tag(ber, &len); if( tag == LDAP_TAG_REFERRAL ) { /* skip 'em */ if( ber_scanf( ber, "x" ) == LBER_ERROR ) { ber_free( ber, 0 ); ld->ld_errno = LDAP_DECODING_ERROR; return ld->ld_errno; } tag = ber_peek_tag(ber, &len); } if( tag == LDAP_TAG_SASL_RES_CREDS ) { if( ber_scanf( ber, "O", &scred ) == LBER_ERROR ) { ber_free( ber, 0 ); ld->ld_errno = LDAP_DECODING_ERROR; return ld->ld_errno; } } } ber_free( ber, 0 ); if ( servercredp != NULL ) { *servercredp = scred; } else if ( scred != NULL ) { ber_bvfree( scred ); } ld->ld_errno = errcode; if ( freeit ) { ldap_msgfree( res ); } return( LDAP_SUCCESS ); } int ldap_pvt_sasl_getmechs ( LDAP *ld, char **pmechlist ) { /* we need to query the server for supported mechs anyway */ LDAPMessage *res, *e; char *attrs[] = { "supportedSASLMechanisms", NULL }; char **values, *mechlist; int rc; Debug( LDAP_DEBUG_TRACE, "ldap_pvt_sasl_getmech\n", 0, 0, 0 ); rc = ldap_search_s( ld, "", LDAP_SCOPE_BASE, NULL, attrs, 0, &res ); if ( rc != LDAP_SUCCESS ) { return ld->ld_errno; } e = ldap_first_entry( ld, res ); if ( e == NULL ) { ldap_msgfree( res ); if ( ld->ld_errno == LDAP_SUCCESS ) { ld->ld_errno = LDAP_NO_SUCH_OBJECT; } return ld->ld_errno; } values = ldap_get_values( ld, e, "supportedSASLMechanisms" ); if ( values == NULL ) { ldap_msgfree( res ); ld->ld_errno = LDAP_NO_SUCH_ATTRIBUTE; return ld->ld_errno; } mechlist = ldap_charray2str( values, " " ); if ( mechlist == NULL ) { LDAP_VFREE( values ); ldap_msgfree( res ); ld->ld_errno = LDAP_NO_MEMORY; return ld->ld_errno; } LDAP_VFREE( values ); ldap_msgfree( res ); *pmechlist = mechlist; return LDAP_SUCCESS; } /* * ldap_sasl_interactive_bind - interactive SASL authentication * * This routine uses interactive callbacks. * * LDAP_SUCCESS is returned upon success, the ldap error code * otherwise. LDAP_SASL_BIND_IN_PROGRESS is returned if further * calls are needed. */ int ldap_sasl_interactive_bind( LDAP *ld, LDAP_CONST char *dn, /* usually NULL */ LDAP_CONST char *mechs, LDAPControl **serverControls, LDAPControl **clientControls, unsigned flags, LDAP_SASL_INTERACT_PROC *interact, void *defaults, LDAPMessage *result, const char **rmech, int *msgid ) { char *smechs = NULL; int rc; #ifdef LDAP_CONNECTIONLESS if( LDAP_IS_UDP(ld) ) { /* Just force it to simple bind, silly to make the user * ask all the time. No, we don't ever actually bind, but I'll * let the final bind handler take care of saving the cdn. */ rc = ldap_simple_bind( ld, dn, NULL ); rc = rc < 0 ? rc : 0; goto done; } else #endif /* First time */ if ( !result ) { #ifdef HAVE_CYRUS_SASL if( mechs == NULL || *mechs == '\0' ) { mechs = ld->ld_options.ldo_def_sasl_mech; } #endif if( mechs == NULL || *mechs == '\0' ) { /* FIXME: this needs to be asynchronous too; * perhaps NULL should be disallowed for async usage? */ rc = ldap_pvt_sasl_getmechs( ld, &smechs ); if( rc != LDAP_SUCCESS ) { goto done; } Debug( LDAP_DEBUG_TRACE, "ldap_sasl_interactive_bind: server supports: %s\n", smechs, 0, 0 ); mechs = smechs; } else { Debug( LDAP_DEBUG_TRACE, "ldap_sasl_interactive_bind: user selected: %s\n", mechs, 0, 0 ); } } rc = ldap_int_sasl_bind( ld, dn, mechs, serverControls, clientControls, flags, interact, defaults, result, rmech, msgid ); done: if ( smechs ) LDAP_FREE( smechs ); return rc; } /* * ldap_sasl_interactive_bind_s - interactive SASL authentication * * This routine uses interactive callbacks. * * LDAP_SUCCESS is returned upon success, the ldap error code * otherwise. */ int ldap_sasl_interactive_bind_s( LDAP *ld, LDAP_CONST char *dn, /* usually NULL */ LDAP_CONST char *mechs, LDAPControl **serverControls, LDAPControl **clientControls, unsigned flags, LDAP_SASL_INTERACT_PROC *interact, void *defaults ) { const char *rmech = NULL; LDAPMessage *result = NULL; int rc, msgid; do { rc = ldap_sasl_interactive_bind( ld, dn, mechs, serverControls, clientControls, flags, interact, defaults, result, &rmech, &msgid ); ldap_msgfree( result ); if ( rc != LDAP_SASL_BIND_IN_PROGRESS ) break; #ifdef LDAP_CONNECTIONLESS if (LDAP_IS_UDP(ld)) { break; } #endif if ( ldap_result( ld, msgid, LDAP_MSG_ALL, NULL, &result ) == -1 || !result ) { return( ld->ld_errno ); /* ldap_result sets ld_errno */ } } while ( rc == LDAP_SASL_BIND_IN_PROGRESS ); return rc; } #ifdef HAVE_CYRUS_SASL #ifdef HAVE_SASL_SASL_H #include #else #include #endif #endif /* HAVE_CYRUS_SASL */ static int sb_sasl_generic_remove( Sockbuf_IO_Desc *sbiod ); static int sb_sasl_generic_setup( Sockbuf_IO_Desc *sbiod, void *arg ) { struct sb_sasl_generic_data *p; struct sb_sasl_generic_install *i; assert( sbiod != NULL ); i = (struct sb_sasl_generic_install *)arg; p = LBER_MALLOC( sizeof( *p ) ); if ( p == NULL ) return -1; p->ops = i->ops; p->ops_private = i->ops_private; p->sbiod = sbiod; p->flags = 0; ber_pvt_sb_buf_init( &p->sec_buf_in ); ber_pvt_sb_buf_init( &p->buf_in ); ber_pvt_sb_buf_init( &p->buf_out ); sbiod->sbiod_pvt = p; p->ops->init( p, &p->min_send, &p->max_send, &p->max_recv ); if ( ber_pvt_sb_grow_buffer( &p->sec_buf_in, p->min_send ) < 0 ) { sb_sasl_generic_remove( sbiod ); sock_errset(ENOMEM); return -1; } return 0; } static int sb_sasl_generic_remove( Sockbuf_IO_Desc *sbiod ) { struct sb_sasl_generic_data *p; assert( sbiod != NULL ); p = (struct sb_sasl_generic_data *)sbiod->sbiod_pvt; p->ops->fini(p); ber_pvt_sb_buf_destroy( &p->sec_buf_in ); ber_pvt_sb_buf_destroy( &p->buf_in ); ber_pvt_sb_buf_destroy( &p->buf_out ); LBER_FREE( p ); sbiod->sbiod_pvt = NULL; return 0; } static ber_len_t sb_sasl_generic_pkt_length( struct sb_sasl_generic_data *p, const unsigned char *buf, int debuglevel ) { ber_len_t size; assert( buf != NULL ); size = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3]; if ( size > p->max_recv ) { /* somebody is trying to mess me up. */ ber_log_printf( LDAP_DEBUG_ANY, debuglevel, "sb_sasl_generic_pkt_length: " "received illegal packet length of %lu bytes\n", (unsigned long)size ); size = 16; /* this should lead to an error. */ } return size + 4; /* include the size !!! */ } /* Drop a processed packet from the input buffer */ static void sb_sasl_generic_drop_packet ( struct sb_sasl_generic_data *p, int debuglevel ) { ber_slen_t len; len = p->sec_buf_in.buf_ptr - p->sec_buf_in.buf_end; if ( len > 0 ) AC_MEMCPY( p->sec_buf_in.buf_base, p->sec_buf_in.buf_base + p->sec_buf_in.buf_end, len ); if ( len >= 4 ) { p->sec_buf_in.buf_end = sb_sasl_generic_pkt_length(p, (unsigned char *) p->sec_buf_in.buf_base, debuglevel); } else { p->sec_buf_in.buf_end = 0; } p->sec_buf_in.buf_ptr = len; } static ber_slen_t sb_sasl_generic_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) { struct sb_sasl_generic_data *p; ber_slen_t ret, bufptr; assert( sbiod != NULL ); assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); p = (struct sb_sasl_generic_data *)sbiod->sbiod_pvt; /* Are there anything left in the buffer? */ ret = ber_pvt_sb_copy_out( &p->buf_in, buf, len ); bufptr = ret; len -= ret; if ( len == 0 ) return bufptr; p->ops->reset_buf( p, &p->buf_in ); /* Read the length of the packet */ while ( p->sec_buf_in.buf_ptr < 4 ) { ret = LBER_SBIOD_READ_NEXT( sbiod, p->sec_buf_in.buf_base + p->sec_buf_in.buf_ptr, 4 - p->sec_buf_in.buf_ptr ); #ifdef EINTR if ( ( ret < 0 ) && ( errno == EINTR ) ) continue; #endif if ( ret <= 0 ) return bufptr ? bufptr : ret; p->sec_buf_in.buf_ptr += ret; } /* The new packet always starts at p->sec_buf_in.buf_base */ ret = sb_sasl_generic_pkt_length(p, (unsigned char *) p->sec_buf_in.buf_base, sbiod->sbiod_sb->sb_debug ); /* Grow the packet buffer if neccessary */ if ( ( p->sec_buf_in.buf_size < (ber_len_t) ret ) && ber_pvt_sb_grow_buffer( &p->sec_buf_in, ret ) < 0 ) { sock_errset(ENOMEM); return -1; } p->sec_buf_in.buf_end = ret; /* Did we read the whole encrypted packet? */ while ( p->sec_buf_in.buf_ptr < p->sec_buf_in.buf_end ) { /* No, we have got only a part of it */ ret = p->sec_buf_in.buf_end - p->sec_buf_in.buf_ptr; ret = LBER_SBIOD_READ_NEXT( sbiod, p->sec_buf_in.buf_base + p->sec_buf_in.buf_ptr, ret ); #ifdef EINTR if ( ( ret < 0 ) && ( errno == EINTR ) ) continue; #endif if ( ret <= 0 ) return bufptr ? bufptr : ret; p->sec_buf_in.buf_ptr += ret; } /* Decode the packet */ ret = p->ops->decode( p, &p->sec_buf_in, &p->buf_in ); /* Drop the packet from the input buffer */ sb_sasl_generic_drop_packet( p, sbiod->sbiod_sb->sb_debug ); if ( ret != 0 ) { ber_log_printf( LDAP_DEBUG_ANY, sbiod->sbiod_sb->sb_debug, "sb_sasl_generic_read: failed to decode packet\n" ); sock_errset(EIO); return -1; } bufptr += ber_pvt_sb_copy_out( &p->buf_in, (char*) buf + bufptr, len ); return bufptr; } static ber_slen_t sb_sasl_generic_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) { struct sb_sasl_generic_data *p; int ret; ber_len_t len2; assert( sbiod != NULL ); assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); p = (struct sb_sasl_generic_data *)sbiod->sbiod_pvt; /* Is there anything left in the buffer? */ if ( p->buf_out.buf_ptr != p->buf_out.buf_end ) { ret = ber_pvt_sb_do_write( sbiod, &p->buf_out ); if ( ret < 0 ) return ret; /* Still have something left?? */ if ( p->buf_out.buf_ptr != p->buf_out.buf_end ) { sock_errset(EAGAIN); return -1; } } len2 = p->max_send - 100; /* For safety margin */ len2 = len > len2 ? len2 : len; /* If we're just retrying a partial write, tell the * caller it's done. Let them call again if there's * still more left to write. */ if ( p->flags & LDAP_PVT_SASL_PARTIAL_WRITE ) { p->flags ^= LDAP_PVT_SASL_PARTIAL_WRITE; return len2; } /* now encode the next packet. */ p->ops->reset_buf( p, &p->buf_out ); ret = p->ops->encode( p, buf, len2, &p->buf_out ); if ( ret != 0 ) { ber_log_printf( LDAP_DEBUG_ANY, sbiod->sbiod_sb->sb_debug, "sb_sasl_generic_write: failed to encode packet\n" ); sock_errset(EIO); return -1; } ret = ber_pvt_sb_do_write( sbiod, &p->buf_out ); if ( ret < 0 ) { /* error? */ int err = sock_errno(); /* caller can retry this */ if ( err == EAGAIN || err == EWOULDBLOCK || err == EINTR ) p->flags |= LDAP_PVT_SASL_PARTIAL_WRITE; return ret; } else if ( p->buf_out.buf_ptr != p->buf_out.buf_end ) { /* partial write? pretend nothing got written */ p->flags |= LDAP_PVT_SASL_PARTIAL_WRITE; sock_errset(EAGAIN); len2 = -1; } /* return number of bytes encoded, not written, to ensure * no byte is encoded twice (even if only sent once). */ return len2; } static int sb_sasl_generic_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) { struct sb_sasl_generic_data *p; p = (struct sb_sasl_generic_data *)sbiod->sbiod_pvt; if ( opt == LBER_SB_OPT_DATA_READY ) { if ( p->buf_in.buf_ptr != p->buf_in.buf_end ) return 1; } return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg ); } Sockbuf_IO ldap_pvt_sockbuf_io_sasl_generic = { sb_sasl_generic_setup, /* sbi_setup */ sb_sasl_generic_remove, /* sbi_remove */ sb_sasl_generic_ctrl, /* sbi_ctrl */ sb_sasl_generic_read, /* sbi_read */ sb_sasl_generic_write, /* sbi_write */ NULL /* sbi_close */ }; int ldap_pvt_sasl_generic_install( Sockbuf *sb, struct sb_sasl_generic_install *install_arg ) { Debug( LDAP_DEBUG_TRACE, "ldap_pvt_sasl_generic_install\n", 0, 0, 0 ); /* don't install the stuff unless security has been negotiated */ if ( !ber_sockbuf_ctrl( sb, LBER_SB_OPT_HAS_IO, &ldap_pvt_sockbuf_io_sasl_generic ) ) { #ifdef LDAP_DEBUG ber_sockbuf_add_io( sb, &ber_sockbuf_io_debug, LBER_SBIOD_LEVEL_APPLICATION, (void *)"sasl_generic_" ); #endif ber_sockbuf_add_io( sb, &ldap_pvt_sockbuf_io_sasl_generic, LBER_SBIOD_LEVEL_APPLICATION, install_arg ); } return LDAP_SUCCESS; } void ldap_pvt_sasl_generic_remove( Sockbuf *sb ) { ber_sockbuf_remove_io( sb, &ldap_pvt_sockbuf_io_sasl_generic, LBER_SBIOD_LEVEL_APPLICATION ); #ifdef LDAP_DEBUG ber_sockbuf_remove_io( sb, &ber_sockbuf_io_debug, LBER_SBIOD_LEVEL_APPLICATION ); #endif } openldap-2.4.42+dfsg/libraries/libldap/search.c0000644000175000017500000002750112563404150020031 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (c) 1990 Regents of the University of Michigan. * All rights reserved. */ #include "portable.h" #include #include #include #include #include #include "ldap-int.h" #include "ldap_log.h" /* * ldap_search_ext - initiate an ldap search operation. * * Parameters: * * ld LDAP descriptor * base DN of the base object * scope the search scope - one of * LDAP_SCOPE_BASE (baseObject), * LDAP_SCOPE_ONELEVEL (oneLevel), * LDAP_SCOPE_SUBTREE (subtree), or * LDAP_SCOPE_SUBORDINATE (children) -- OpenLDAP extension * filter a string containing the search filter * (e.g., "(|(cn=bob)(sn=bob))") * attrs list of attribute types to return for matches * attrsonly 1 => attributes only 0 => attributes and values * * Example: * char *attrs[] = { "mail", "title", 0 }; * ldap_search_ext( ld, "dc=example,dc=com", LDAP_SCOPE_SUBTREE, "cn~=bob", * attrs, attrsonly, sctrls, ctrls, timeout, sizelimit, * &msgid ); */ int ldap_search_ext( LDAP *ld, LDAP_CONST char *base, int scope, LDAP_CONST char *filter, char **attrs, int attrsonly, LDAPControl **sctrls, LDAPControl **cctrls, struct timeval *timeout, int sizelimit, int *msgidp ) { return ldap_pvt_search( ld, base, scope, filter, attrs, attrsonly, sctrls, cctrls, timeout, sizelimit, -1, msgidp ); } int ldap_pvt_search( LDAP *ld, LDAP_CONST char *base, int scope, LDAP_CONST char *filter, char **attrs, int attrsonly, LDAPControl **sctrls, LDAPControl **cctrls, struct timeval *timeout, int sizelimit, int deref, int *msgidp ) { int rc; BerElement *ber; int timelimit; ber_int_t id; Debug( LDAP_DEBUG_TRACE, "ldap_search_ext\n", 0, 0, 0 ); assert( ld != NULL ); assert( LDAP_VALID( ld ) ); /* check client controls */ rc = ldap_int_client_controls( ld, cctrls ); if( rc != LDAP_SUCCESS ) return rc; /* * if timeout is provided, both tv_sec and tv_usec must * not be zero */ if( timeout != NULL ) { if( timeout->tv_sec == 0 && timeout->tv_usec == 0 ) { return LDAP_PARAM_ERROR; } /* timelimit must be non-zero if timeout is provided */ timelimit = timeout->tv_sec != 0 ? timeout->tv_sec : 1; } else { /* no timeout, no timelimit */ timelimit = -1; } ber = ldap_build_search_req( ld, base, scope, filter, attrs, attrsonly, sctrls, cctrls, timelimit, sizelimit, deref, &id ); if ( ber == NULL ) { return ld->ld_errno; } /* send the message */ *msgidp = ldap_send_initial_request( ld, LDAP_REQ_SEARCH, base, ber, id ); if( *msgidp < 0 ) return ld->ld_errno; return LDAP_SUCCESS; } int ldap_search_ext_s( LDAP *ld, LDAP_CONST char *base, int scope, LDAP_CONST char *filter, char **attrs, int attrsonly, LDAPControl **sctrls, LDAPControl **cctrls, struct timeval *timeout, int sizelimit, LDAPMessage **res ) { return ldap_pvt_search_s( ld, base, scope, filter, attrs, attrsonly, sctrls, cctrls, timeout, sizelimit, -1, res ); } int ldap_pvt_search_s( LDAP *ld, LDAP_CONST char *base, int scope, LDAP_CONST char *filter, char **attrs, int attrsonly, LDAPControl **sctrls, LDAPControl **cctrls, struct timeval *timeout, int sizelimit, int deref, LDAPMessage **res ) { int rc; int msgid; *res = NULL; rc = ldap_pvt_search( ld, base, scope, filter, attrs, attrsonly, sctrls, cctrls, timeout, sizelimit, deref, &msgid ); if ( rc != LDAP_SUCCESS ) { return( rc ); } rc = ldap_result( ld, msgid, LDAP_MSG_ALL, timeout, res ); if( rc <= 0 ) { /* error(-1) or timeout(0) */ if ( ld->ld_errno == LDAP_TIMEOUT ) { /* cleanup request */ (void) ldap_abandon( ld, msgid ); ld->ld_errno = LDAP_TIMEOUT; } return( ld->ld_errno ); } if( rc == LDAP_RES_SEARCH_REFERENCE || rc == LDAP_RES_INTERMEDIATE ) { return( ld->ld_errno ); } return( ldap_result2error( ld, *res, 0 ) ); } /* * ldap_search - initiate an ldap search operation. * * Parameters: * * ld LDAP descriptor * base DN of the base object * scope the search scope - one of * LDAP_SCOPE_BASE (baseObject), * LDAP_SCOPE_ONELEVEL (oneLevel), * LDAP_SCOPE_SUBTREE (subtree), or * LDAP_SCOPE_SUBORDINATE (children) -- OpenLDAP extension * filter a string containing the search filter * (e.g., "(|(cn=bob)(sn=bob))") * attrs list of attribute types to return for matches * attrsonly 1 => attributes only 0 => attributes and values * * Example: * char *attrs[] = { "mail", "title", 0 }; * msgid = ldap_search( ld, "dc=example,dc=com", LDAP_SCOPE_SUBTREE, "cn~=bob", * attrs, attrsonly ); */ int ldap_search( LDAP *ld, LDAP_CONST char *base, int scope, LDAP_CONST char *filter, char **attrs, int attrsonly ) { BerElement *ber; ber_int_t id; Debug( LDAP_DEBUG_TRACE, "ldap_search\n", 0, 0, 0 ); assert( ld != NULL ); assert( LDAP_VALID( ld ) ); ber = ldap_build_search_req( ld, base, scope, filter, attrs, attrsonly, NULL, NULL, -1, -1, -1, &id ); if ( ber == NULL ) { return( -1 ); } /* send the message */ return ( ldap_send_initial_request( ld, LDAP_REQ_SEARCH, base, ber, id )); } BerElement * ldap_build_search_req( LDAP *ld, LDAP_CONST char *base, ber_int_t scope, LDAP_CONST char *filter, char **attrs, ber_int_t attrsonly, LDAPControl **sctrls, LDAPControl **cctrls, ber_int_t timelimit, ber_int_t sizelimit, ber_int_t deref, ber_int_t *idp) { BerElement *ber; int err; /* * Create the search request. It looks like this: * SearchRequest := [APPLICATION 3] SEQUENCE { * baseObject DistinguishedName, * scope ENUMERATED { * baseObject (0), * singleLevel (1), * wholeSubtree (2) * }, * derefAliases ENUMERATED { * neverDerefaliases (0), * derefInSearching (1), * derefFindingBaseObj (2), * alwaysDerefAliases (3) * }, * sizelimit INTEGER (0 .. 65535), * timelimit INTEGER (0 .. 65535), * attrsOnly BOOLEAN, * filter Filter, * attributes SEQUENCE OF AttributeType * } * wrapped in an ldap message. */ /* create a message to send */ if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) { return( NULL ); } if ( base == NULL ) { /* no base provided, use session default base */ base = ld->ld_options.ldo_defbase; if ( base == NULL ) { /* no session default base, use top */ base = ""; } } LDAP_NEXT_MSGID( ld, *idp ); #ifdef LDAP_CONNECTIONLESS if ( LDAP_IS_UDP(ld) ) { struct sockaddr_storage sa = {0}; /* dummy, filled with ldo_peer in request.c */ err = ber_write( ber, (char *) &sa, sizeof( sa ), 0 ); } if ( LDAP_IS_UDP(ld) && ld->ld_options.ldo_version == LDAP_VERSION2) { char *dn = ld->ld_options.ldo_cldapdn; if (!dn) dn = ""; err = ber_printf( ber, "{ist{seeiib", *idp, dn, LDAP_REQ_SEARCH, base, (ber_int_t) scope, (deref < 0) ? ld->ld_deref : deref, (sizelimit < 0) ? ld->ld_sizelimit : sizelimit, (timelimit < 0) ? ld->ld_timelimit : timelimit, attrsonly ); } else #endif { err = ber_printf( ber, "{it{seeiib", *idp, LDAP_REQ_SEARCH, base, (ber_int_t) scope, (deref < 0) ? ld->ld_deref : deref, (sizelimit < 0) ? ld->ld_sizelimit : sizelimit, (timelimit < 0) ? ld->ld_timelimit : timelimit, attrsonly ); } if ( err == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( NULL ); } if( filter == NULL ) { filter = "(objectclass=*)"; } err = ldap_pvt_put_filter( ber, filter ); if ( err == -1 ) { ld->ld_errno = LDAP_FILTER_ERROR; ber_free( ber, 1 ); return( NULL ); } #ifdef LDAP_DEBUG if ( ldap_debug & LDAP_DEBUG_ARGS ) { char buf[ BUFSIZ ], *ptr = " *"; if ( attrs != NULL ) { int i, len, rest = sizeof( buf ); for ( i = 0; attrs[ i ] != NULL && rest > 0; i++ ) { ptr = &buf[ sizeof( buf ) - rest ]; len = snprintf( ptr, rest, " %s", attrs[ i ] ); rest -= (len >= 0 ? len : (int) sizeof( buf )); } if ( rest <= 0 ) { AC_MEMCPY( &buf[ sizeof( buf ) - STRLENOF( "...(truncated)" ) - 1 ], "...(truncated)", STRLENOF( "...(truncated)" ) + 1 ); } ptr = buf; } Debug( LDAP_DEBUG_ARGS, "ldap_build_search_req ATTRS:%s\n", ptr, 0,0 ); } #endif /* LDAP_DEBUG */ if ( ber_printf( ber, /*{*/ "{v}N}", attrs ) == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( NULL ); } /* Put Server Controls */ if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) { ber_free( ber, 1 ); return( NULL ); } if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( NULL ); } return( ber ); } int ldap_search_st( LDAP *ld, LDAP_CONST char *base, int scope, LDAP_CONST char *filter, char **attrs, int attrsonly, struct timeval *timeout, LDAPMessage **res ) { int msgid; *res = NULL; if ( (msgid = ldap_search( ld, base, scope, filter, attrs, attrsonly )) == -1 ) return( ld->ld_errno ); if ( ldap_result( ld, msgid, LDAP_MSG_ALL, timeout, res ) == -1 || !*res ) return( ld->ld_errno ); if ( ld->ld_errno == LDAP_TIMEOUT ) { (void) ldap_abandon( ld, msgid ); ld->ld_errno = LDAP_TIMEOUT; return( ld->ld_errno ); } return( ldap_result2error( ld, *res, 0 ) ); } int ldap_search_s( LDAP *ld, LDAP_CONST char *base, int scope, LDAP_CONST char *filter, char **attrs, int attrsonly, LDAPMessage **res ) { int msgid; *res = NULL; if ( (msgid = ldap_search( ld, base, scope, filter, attrs, attrsonly )) == -1 ) return( ld->ld_errno ); if ( ldap_result( ld, msgid, LDAP_MSG_ALL, (struct timeval *) NULL, res ) == -1 || !*res ) return( ld->ld_errno ); return( ldap_result2error( ld, *res, 0 ) ); } static char escape[128] = { 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, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 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, 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, 1 }; #define NEEDFLTESCAPE(c) ((c) & 0x80 || escape[ (unsigned)(c) ]) /* * compute the length of the escaped value */ ber_len_t ldap_bv2escaped_filter_value_len( struct berval *in ) { ber_len_t i, l; assert( in != NULL ); if ( in->bv_len == 0 ) { return 0; } for( l = 0, i = 0; i < in->bv_len; l++, i++ ) { char c = in->bv_val[ i ]; if ( NEEDFLTESCAPE( c ) ) { l += 2; } } return l; } int ldap_bv2escaped_filter_value( struct berval *in, struct berval *out ) { return ldap_bv2escaped_filter_value_x( in, out, 0, NULL ); } int ldap_bv2escaped_filter_value_x( struct berval *in, struct berval *out, int inplace, void *ctx ) { ber_len_t i, l; assert( in != NULL ); assert( out != NULL ); BER_BVZERO( out ); if ( in->bv_len == 0 ) { return 0; } /* assume we'll escape everything */ l = ldap_bv2escaped_filter_value_len( in ); if ( l == in->bv_len ) { if ( inplace ) { *out = *in; } else { ber_dupbv( out, in ); } return 0; } out->bv_val = LDAP_MALLOCX( l + 1, ctx ); if ( out->bv_val == NULL ) { return -1; } for ( i = 0; i < in->bv_len; i++ ) { char c = in->bv_val[ i ]; if ( NEEDFLTESCAPE( c ) ) { assert( out->bv_len < l - 2 ); out->bv_val[out->bv_len++] = '\\'; out->bv_val[out->bv_len++] = "0123456789ABCDEF"[0x0f & (c>>4)]; out->bv_val[out->bv_len++] = "0123456789ABCDEF"[0x0f & c]; } else { assert( out->bv_len < l ); out->bv_val[out->bv_len++] = c; } } out->bv_val[out->bv_len] = '\0'; return 0; } openldap-2.4.42+dfsg/libraries/libldap/references.c0000644000175000017500000000534412563404150020706 0ustar ryanryan/* references.c */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #include "portable.h" #include #include #include #include #include #include "ldap-int.h" LDAPMessage * ldap_first_reference( LDAP *ld, LDAPMessage *chain ) { assert( ld != NULL ); assert( LDAP_VALID( ld ) ); assert( chain != NULL ); return chain->lm_msgtype == LDAP_RES_SEARCH_REFERENCE ? chain : ldap_next_reference( ld, chain ); } LDAPMessage * ldap_next_reference( LDAP *ld, LDAPMessage *ref ) { assert( ld != NULL ); assert( LDAP_VALID( ld ) ); assert( ref != NULL ); for ( ref = ref->lm_chain; ref != NULL; ref = ref->lm_chain ) { if( ref->lm_msgtype == LDAP_RES_SEARCH_REFERENCE ) { return( ref ); } } return( NULL ); } int ldap_count_references( LDAP *ld, LDAPMessage *chain ) { int i; assert( ld != NULL ); assert( LDAP_VALID( ld ) ); for ( i = 0; chain != NULL; chain = chain->lm_chain ) { if( chain->lm_msgtype == LDAP_RES_SEARCH_REFERENCE ) { i++; } } return( i ); } int ldap_parse_reference( LDAP *ld, LDAPMessage *ref, char ***referralsp, LDAPControl ***serverctrls, int freeit) { BerElement be; char **refs = NULL; int rc; assert( ld != NULL ); assert( LDAP_VALID( ld ) ); assert( ref != NULL ); if( ref->lm_msgtype != LDAP_RES_SEARCH_REFERENCE ) { return LDAP_PARAM_ERROR; } /* make a private copy of BerElement */ AC_MEMCPY(&be, ref->lm_ber, sizeof(be)); if ( ber_scanf( &be, "{v" /*}*/, &refs ) == LBER_ERROR ) { rc = LDAP_DECODING_ERROR; goto free_and_return; } if ( serverctrls == NULL ) { rc = LDAP_SUCCESS; goto free_and_return; } if ( ber_scanf( &be, /*{*/ "}" ) == LBER_ERROR ) { rc = LDAP_DECODING_ERROR; goto free_and_return; } rc = ldap_pvt_get_controls( &be, serverctrls ); free_and_return: if( referralsp != NULL ) { /* provide references regradless of return code */ *referralsp = refs; } else { LDAP_VFREE( refs ); } if( freeit ) { ldap_msgfree( ref ); } if( rc != LDAP_SUCCESS ) { ld->ld_errno = rc; if( ld->ld_matched != NULL ) { LDAP_FREE( ld->ld_matched ); ld->ld_matched = NULL; } if( ld->ld_error != NULL ) { LDAP_FREE( ld->ld_error ); ld->ld_error = NULL; } } return rc; } openldap-2.4.42+dfsg/libraries/libldap/assertion.c0000644000175000017500000000365012563404150020572 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #include "portable.h" #include #include #include #include #include "ldap-int.h" int ldap_create_assertion_control_value( LDAP *ld, char *assertion, struct berval *value ) { BerElement *ber = NULL; int err; if ( assertion == NULL || assertion[ 0 ] == '\0' ) { ld->ld_errno = LDAP_PARAM_ERROR; return ld->ld_errno; } if ( value == NULL ) { ld->ld_errno = LDAP_PARAM_ERROR; return ld->ld_errno; } BER_BVZERO( value ); ber = ldap_alloc_ber_with_options( ld ); if ( ber == NULL ) { ld->ld_errno = LDAP_NO_MEMORY; return ld->ld_errno; } err = ldap_pvt_put_filter( ber, assertion ); if ( err < 0 ) { ld->ld_errno = LDAP_ENCODING_ERROR; goto done; } err = ber_flatten2( ber, value, 1 ); if ( err < 0 ) { ld->ld_errno = LDAP_NO_MEMORY; goto done; } done:; if ( ber != NULL ) { ber_free( ber, 1 ); } return ld->ld_errno; } int ldap_create_assertion_control( LDAP *ld, char *assertion, int iscritical, LDAPControl **ctrlp ) { struct berval value; if ( ctrlp == NULL ) { ld->ld_errno = LDAP_PARAM_ERROR; return ld->ld_errno; } ld->ld_errno = ldap_create_assertion_control_value( ld, assertion, &value ); if ( ld->ld_errno == LDAP_SUCCESS ) { ld->ld_errno = ldap_control_create( LDAP_CONTROL_ASSERT, iscritical, &value, 0, ctrlp ); if ( ld->ld_errno != LDAP_SUCCESS ) { LDAP_FREE( value.bv_val ); } } return ld->ld_errno; } openldap-2.4.42+dfsg/libraries/libldap/tls2.c0000644000175000017500000010014012563404150017437 0ustar ryanryan/* tls.c - Handle tls/ssl. */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* ACKNOWLEDGEMENTS: restructured by Howard Chu. */ #include "portable.h" #include "ldap_config.h" #include #include #include #include #include #include #include #include #include #include #include "ldap-int.h" #ifdef HAVE_TLS #include "ldap-tls.h" static tls_impl *tls_imp = &ldap_int_tls_impl; #define HAS_TLS( sb ) ber_sockbuf_ctrl( sb, LBER_SB_OPT_HAS_IO, \ (void *)tls_imp->ti_sbio ) #endif /* HAVE_TLS */ #ifdef LDAP_DEVEL #define LDAP_USE_NON_BLOCKING_TLS #endif /* LDAP_DEVEL */ /* RFC2459 minimum required set of supported attribute types * in a certificate DN */ typedef struct oid_name { struct berval oid; struct berval name; } oid_name; static oid_name oids[] = { { BER_BVC("2.5.4.3"), BER_BVC("cn") }, { BER_BVC("2.5.4.4"), BER_BVC("sn") }, { BER_BVC("2.5.4.6"), BER_BVC("c") }, { BER_BVC("2.5.4.7"), BER_BVC("l") }, { BER_BVC("2.5.4.8"), BER_BVC("st") }, { BER_BVC("2.5.4.10"), BER_BVC("o") }, { BER_BVC("2.5.4.11"), BER_BVC("ou") }, { BER_BVC("2.5.4.12"), BER_BVC("title") }, { BER_BVC("2.5.4.41"), BER_BVC("name") }, { BER_BVC("2.5.4.42"), BER_BVC("givenName") }, { BER_BVC("2.5.4.43"), BER_BVC("initials") }, { BER_BVC("2.5.4.44"), BER_BVC("generationQualifier") }, { BER_BVC("2.5.4.46"), BER_BVC("dnQualifier") }, { BER_BVC("1.2.840.113549.1.9.1"), BER_BVC("email") }, { BER_BVC("0.9.2342.19200300.100.1.25"), BER_BVC("dc") }, { BER_BVNULL, BER_BVNULL } }; #ifdef HAVE_TLS void ldap_pvt_tls_ctx_free ( void *c ) { if ( !c ) return; tls_imp->ti_ctx_free( c ); } static void tls_ctx_ref( tls_ctx *ctx ) { if ( !ctx ) return; tls_imp->ti_ctx_ref( ctx ); } #ifdef LDAP_R_COMPILE /* * an extra mutex for the default ctx. */ static ldap_pvt_thread_mutex_t tls_def_ctx_mutex; #endif void ldap_int_tls_destroy( struct ldapoptions *lo ) { if ( lo->ldo_tls_ctx ) { ldap_pvt_tls_ctx_free( lo->ldo_tls_ctx ); lo->ldo_tls_ctx = NULL; } if ( lo->ldo_tls_certfile ) { LDAP_FREE( lo->ldo_tls_certfile ); lo->ldo_tls_certfile = NULL; } if ( lo->ldo_tls_keyfile ) { LDAP_FREE( lo->ldo_tls_keyfile ); lo->ldo_tls_keyfile = NULL; } if ( lo->ldo_tls_dhfile ) { LDAP_FREE( lo->ldo_tls_dhfile ); lo->ldo_tls_dhfile = NULL; } if ( lo->ldo_tls_cacertfile ) { LDAP_FREE( lo->ldo_tls_cacertfile ); lo->ldo_tls_cacertfile = NULL; } if ( lo->ldo_tls_cacertdir ) { LDAP_FREE( lo->ldo_tls_cacertdir ); lo->ldo_tls_cacertdir = NULL; } if ( lo->ldo_tls_ciphersuite ) { LDAP_FREE( lo->ldo_tls_ciphersuite ); lo->ldo_tls_ciphersuite = NULL; } if ( lo->ldo_tls_crlfile ) { LDAP_FREE( lo->ldo_tls_crlfile ); lo->ldo_tls_crlfile = NULL; } } /* * Tear down the TLS subsystem. Should only be called once. */ void ldap_pvt_tls_destroy( void ) { struct ldapoptions *lo = LDAP_INT_GLOBAL_OPT(); ldap_int_tls_destroy( lo ); tls_imp->ti_tls_destroy(); } /* * Initialize a particular TLS implementation. * Called once per implementation. */ static int tls_init(tls_impl *impl ) { static int tls_initialized = 0; if ( !tls_initialized++ ) { #ifdef LDAP_R_COMPILE ldap_pvt_thread_mutex_init( &tls_def_ctx_mutex ); #endif } if ( impl->ti_inited++ ) return 0; #ifdef LDAP_R_COMPILE impl->ti_thr_init(); #endif return impl->ti_tls_init(); } /* * Initialize TLS subsystem. Called once per implementation. */ int ldap_pvt_tls_init( void ) { return tls_init( tls_imp ); } /* * initialize a new TLS context */ static int ldap_int_tls_init_ctx( struct ldapoptions *lo, int is_server ) { int rc = 0; tls_impl *ti = tls_imp; struct ldaptls lts = lo->ldo_tls_info; if ( lo->ldo_tls_ctx ) return 0; tls_init( ti ); if ( is_server && !lts.lt_certfile && !lts.lt_keyfile && !lts.lt_cacertfile && !lts.lt_cacertdir ) { /* minimum configuration not provided */ return LDAP_NOT_SUPPORTED; } #ifdef HAVE_EBCDIC /* This ASCII/EBCDIC handling is a real pain! */ if ( lts.lt_ciphersuite ) { lts.lt_ciphersuite = LDAP_STRDUP( lts.lt_ciphersuite ); __atoe( lts.lt_ciphersuite ); } if ( lts.lt_cacertfile ) { lts.lt_cacertfile = LDAP_STRDUP( lts.lt_cacertfile ); __atoe( lts.lt_cacertfile ); } if ( lts.lt_certfile ) { lts.lt_certfile = LDAP_STRDUP( lts.lt_certfile ); __atoe( lts.lt_certfile ); } if ( lts.lt_keyfile ) { lts.lt_keyfile = LDAP_STRDUP( lts.lt_keyfile ); __atoe( lts.lt_keyfile ); } if ( lts.lt_crlfile ) { lts.lt_crlfile = LDAP_STRDUP( lts.lt_crlfile ); __atoe( lts.lt_crlfile ); } if ( lts.lt_cacertdir ) { lts.lt_cacertdir = LDAP_STRDUP( lts.lt_cacertdir ); __atoe( lts.lt_cacertdir ); } if ( lts.lt_dhfile ) { lts.lt_dhfile = LDAP_STRDUP( lts.lt_dhfile ); __atoe( lts.lt_dhfile ); } #endif lo->ldo_tls_ctx = ti->ti_ctx_new( lo ); if ( lo->ldo_tls_ctx == NULL ) { Debug( LDAP_DEBUG_ANY, "TLS: could not allocate default ctx.\n", 0,0,0); rc = -1; goto error_exit; } rc = ti->ti_ctx_init( lo, <s, is_server ); error_exit: if ( rc < 0 && lo->ldo_tls_ctx != NULL ) { ldap_pvt_tls_ctx_free( lo->ldo_tls_ctx ); lo->ldo_tls_ctx = NULL; } #ifdef HAVE_EBCDIC LDAP_FREE( lts.lt_ciphersuite ); LDAP_FREE( lts.lt_cacertfile ); LDAP_FREE( lts.lt_certfile ); LDAP_FREE( lts.lt_keyfile ); LDAP_FREE( lts.lt_crlfile ); LDAP_FREE( lts.lt_cacertdir ); LDAP_FREE( lts.lt_dhfile ); #endif return rc; } /* * initialize the default context */ int ldap_pvt_tls_init_def_ctx( int is_server ) { struct ldapoptions *lo = LDAP_INT_GLOBAL_OPT(); int rc; LDAP_MUTEX_LOCK( &tls_def_ctx_mutex ); rc = ldap_int_tls_init_ctx( lo, is_server ); LDAP_MUTEX_UNLOCK( &tls_def_ctx_mutex ); return rc; } static tls_session * alloc_handle( void *ctx_arg, int is_server ) { tls_ctx *ctx; tls_session *ssl; if ( ctx_arg ) { ctx = ctx_arg; } else { struct ldapoptions *lo = LDAP_INT_GLOBAL_OPT(); if ( ldap_pvt_tls_init_def_ctx( is_server ) < 0 ) return NULL; ctx = lo->ldo_tls_ctx; } ssl = tls_imp->ti_session_new( ctx, is_server ); if ( ssl == NULL ) { Debug( LDAP_DEBUG_ANY,"TLS: can't create ssl handle.\n",0,0,0); return NULL; } return ssl; } static int update_flags( Sockbuf *sb, tls_session * ssl, int rc ) { sb->sb_trans_needs_read = 0; sb->sb_trans_needs_write = 0; return tls_imp->ti_session_upflags( sb, ssl, rc ); } /* * Call this to do a TLS connect on a sockbuf. ctx_arg can be * a SSL_CTX * or NULL, in which case the default ctx is used. * * Return value: * * 0 - Success. Connection is ready for communication. * <0 - Error. Can't create a TLS stream. * >0 - Partial success. * Do a select (using information from lber_pvt_sb_needs_{read,write} * and call again. */ static int ldap_int_tls_connect( LDAP *ld, LDAPConn *conn ) { Sockbuf *sb = conn->lconn_sb; int err; tls_session *ssl = NULL; if ( HAS_TLS( sb )) { ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_SSL, (void *)&ssl ); } else { struct ldapoptions *lo; tls_ctx *ctx; ctx = ld->ld_options.ldo_tls_ctx; ssl = alloc_handle( ctx, 0 ); if ( ssl == NULL ) return -1; #ifdef LDAP_DEBUG ber_sockbuf_add_io( sb, &ber_sockbuf_io_debug, LBER_SBIOD_LEVEL_TRANSPORT, (void *)"tls_" ); #endif ber_sockbuf_add_io( sb, tls_imp->ti_sbio, LBER_SBIOD_LEVEL_TRANSPORT, (void *)ssl ); lo = LDAP_INT_GLOBAL_OPT(); if( ctx == NULL ) { ctx = lo->ldo_tls_ctx; ld->ld_options.ldo_tls_ctx = ctx; tls_ctx_ref( ctx ); } if ( ld->ld_options.ldo_tls_connect_cb ) ld->ld_options.ldo_tls_connect_cb( ld, ssl, ctx, ld->ld_options.ldo_tls_connect_arg ); if ( lo && lo->ldo_tls_connect_cb && lo->ldo_tls_connect_cb != ld->ld_options.ldo_tls_connect_cb ) lo->ldo_tls_connect_cb( ld, ssl, ctx, lo->ldo_tls_connect_arg ); } err = tls_imp->ti_session_connect( ld, ssl ); #ifdef HAVE_WINSOCK errno = WSAGetLastError(); #endif if ( err < 0 ) { char buf[256], *msg; if ( update_flags( sb, ssl, err )) { return 1; } msg = tls_imp->ti_session_errmsg( ssl, err, buf, sizeof(buf) ); if ( msg ) { if ( ld->ld_error ) { LDAP_FREE( ld->ld_error ); } ld->ld_error = LDAP_STRDUP( msg ); #ifdef HAVE_EBCDIC if ( ld->ld_error ) __etoa(ld->ld_error); #endif } Debug( LDAP_DEBUG_ANY,"TLS: can't connect: %s.\n", ld->ld_error ? ld->ld_error : "" ,0,0); ber_sockbuf_remove_io( sb, tls_imp->ti_sbio, LBER_SBIOD_LEVEL_TRANSPORT ); #ifdef LDAP_DEBUG ber_sockbuf_remove_io( sb, &ber_sockbuf_io_debug, LBER_SBIOD_LEVEL_TRANSPORT ); #endif return -1; } return 0; } /* * Call this to do a TLS accept on a sockbuf. * Everything else is the same as with tls_connect. */ int ldap_pvt_tls_accept( Sockbuf *sb, void *ctx_arg ) { int err; tls_session *ssl = NULL; if ( HAS_TLS( sb )) { ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_SSL, (void *)&ssl ); } else { ssl = alloc_handle( ctx_arg, 1 ); if ( ssl == NULL ) return -1; #ifdef LDAP_DEBUG ber_sockbuf_add_io( sb, &ber_sockbuf_io_debug, LBER_SBIOD_LEVEL_TRANSPORT, (void *)"tls_" ); #endif ber_sockbuf_add_io( sb, tls_imp->ti_sbio, LBER_SBIOD_LEVEL_TRANSPORT, (void *)ssl ); } err = tls_imp->ti_session_accept( ssl ); #ifdef HAVE_WINSOCK errno = WSAGetLastError(); #endif if ( err < 0 ) { if ( update_flags( sb, ssl, err )) return 1; if ( DebugTest( LDAP_DEBUG_ANY ) ) { char buf[256], *msg; msg = tls_imp->ti_session_errmsg( ssl, err, buf, sizeof(buf) ); Debug( LDAP_DEBUG_ANY,"TLS: can't accept: %s.\n", msg ? msg : "(unknown)", 0, 0 ); } ber_sockbuf_remove_io( sb, tls_imp->ti_sbio, LBER_SBIOD_LEVEL_TRANSPORT ); #ifdef LDAP_DEBUG ber_sockbuf_remove_io( sb, &ber_sockbuf_io_debug, LBER_SBIOD_LEVEL_TRANSPORT ); #endif return -1; } return 0; } int ldap_pvt_tls_inplace ( Sockbuf *sb ) { return HAS_TLS( sb ) ? 1 : 0; } int ldap_tls_inplace( LDAP *ld ) { Sockbuf *sb = NULL; if ( ld->ld_defconn && ld->ld_defconn->lconn_sb ) { sb = ld->ld_defconn->lconn_sb; } else if ( ld->ld_sb ) { sb = ld->ld_sb; } else { return 0; } return ldap_pvt_tls_inplace( sb ); } int ldap_pvt_tls_get_peer_dn( void *s, struct berval *dn, LDAPDN_rewrite_dummy *func, unsigned flags ) { tls_session *session = s; struct berval bvdn; int rc; rc = tls_imp->ti_session_peer_dn( session, &bvdn ); if ( rc ) return rc; rc = ldap_X509dn2bv( &bvdn, dn, (LDAPDN_rewrite_func *)func, flags); return rc; } int ldap_pvt_tls_check_hostname( LDAP *ld, void *s, const char *name_in ) { tls_session *session = s; return tls_imp->ti_session_chkhost( ld, session, name_in ); } int ldap_int_tls_config( LDAP *ld, int option, const char *arg ) { int i; switch( option ) { case LDAP_OPT_X_TLS_CACERTFILE: case LDAP_OPT_X_TLS_CACERTDIR: case LDAP_OPT_X_TLS_CERTFILE: case LDAP_OPT_X_TLS_KEYFILE: case LDAP_OPT_X_TLS_RANDOM_FILE: case LDAP_OPT_X_TLS_CIPHER_SUITE: case LDAP_OPT_X_TLS_DHFILE: case LDAP_OPT_X_TLS_CRLFILE: /* GnuTLS only */ return ldap_pvt_tls_set_option( ld, option, (void *) arg ); case LDAP_OPT_X_TLS_REQUIRE_CERT: case LDAP_OPT_X_TLS: i = -1; if ( strcasecmp( arg, "never" ) == 0 ) { i = LDAP_OPT_X_TLS_NEVER ; } else if ( strcasecmp( arg, "demand" ) == 0 ) { i = LDAP_OPT_X_TLS_DEMAND ; } else if ( strcasecmp( arg, "allow" ) == 0 ) { i = LDAP_OPT_X_TLS_ALLOW ; } else if ( strcasecmp( arg, "try" ) == 0 ) { i = LDAP_OPT_X_TLS_TRY ; } else if ( ( strcasecmp( arg, "hard" ) == 0 ) || ( strcasecmp( arg, "on" ) == 0 ) || ( strcasecmp( arg, "yes" ) == 0) || ( strcasecmp( arg, "true" ) == 0 ) ) { i = LDAP_OPT_X_TLS_HARD ; } if (i >= 0) { return ldap_pvt_tls_set_option( ld, option, &i ); } return -1; case LDAP_OPT_X_TLS_PROTOCOL_MIN: { char *next; long l; l = strtol( arg, &next, 10 ); if ( l < 0 || l > 0xff || next == arg || ( *next != '\0' && *next != '.' ) ) return -1; i = l << 8; if (*next == '.') { arg = next + 1; l = strtol( arg, &next, 10 ); if ( l < 0 || l > 0xff || next == arg || *next != '\0' ) return -1; i += l; } return ldap_pvt_tls_set_option( ld, option, &i ); } #ifdef HAVE_OPENSSL_CRL case LDAP_OPT_X_TLS_CRLCHECK: /* OpenSSL only */ i = -1; if ( strcasecmp( arg, "none" ) == 0 ) { i = LDAP_OPT_X_TLS_CRL_NONE ; } else if ( strcasecmp( arg, "peer" ) == 0 ) { i = LDAP_OPT_X_TLS_CRL_PEER ; } else if ( strcasecmp( arg, "all" ) == 0 ) { i = LDAP_OPT_X_TLS_CRL_ALL ; } if (i >= 0) { return ldap_pvt_tls_set_option( ld, option, &i ); } return -1; #endif } return -1; } int ldap_pvt_tls_get_option( LDAP *ld, int option, void *arg ) { struct ldapoptions *lo; if( option == LDAP_OPT_X_TLS_PACKAGE ) { *(char **)arg = LDAP_STRDUP( tls_imp->ti_name ); return 0; } if( ld != NULL ) { assert( LDAP_VALID( ld ) ); if( !LDAP_VALID( ld ) ) { return LDAP_OPT_ERROR; } lo = &ld->ld_options; } else { /* Get pointer to global option structure */ lo = LDAP_INT_GLOBAL_OPT(); if ( lo == NULL ) { return LDAP_NO_MEMORY; } } switch( option ) { case LDAP_OPT_X_TLS: *(int *)arg = lo->ldo_tls_mode; break; case LDAP_OPT_X_TLS_CTX: *(void **)arg = lo->ldo_tls_ctx; if ( lo->ldo_tls_ctx ) { tls_ctx_ref( lo->ldo_tls_ctx ); } break; case LDAP_OPT_X_TLS_CACERTFILE: *(char **)arg = lo->ldo_tls_cacertfile ? LDAP_STRDUP( lo->ldo_tls_cacertfile ) : NULL; break; case LDAP_OPT_X_TLS_CACERTDIR: *(char **)arg = lo->ldo_tls_cacertdir ? LDAP_STRDUP( lo->ldo_tls_cacertdir ) : NULL; break; case LDAP_OPT_X_TLS_CERTFILE: *(char **)arg = lo->ldo_tls_certfile ? LDAP_STRDUP( lo->ldo_tls_certfile ) : NULL; break; case LDAP_OPT_X_TLS_KEYFILE: *(char **)arg = lo->ldo_tls_keyfile ? LDAP_STRDUP( lo->ldo_tls_keyfile ) : NULL; break; case LDAP_OPT_X_TLS_DHFILE: *(char **)arg = lo->ldo_tls_dhfile ? LDAP_STRDUP( lo->ldo_tls_dhfile ) : NULL; break; case LDAP_OPT_X_TLS_CRLFILE: /* GnuTLS only */ *(char **)arg = lo->ldo_tls_crlfile ? LDAP_STRDUP( lo->ldo_tls_crlfile ) : NULL; break; case LDAP_OPT_X_TLS_REQUIRE_CERT: *(int *)arg = lo->ldo_tls_require_cert; break; #ifdef HAVE_OPENSSL_CRL case LDAP_OPT_X_TLS_CRLCHECK: /* OpenSSL only */ *(int *)arg = lo->ldo_tls_crlcheck; break; #endif case LDAP_OPT_X_TLS_CIPHER_SUITE: *(char **)arg = lo->ldo_tls_ciphersuite ? LDAP_STRDUP( lo->ldo_tls_ciphersuite ) : NULL; break; case LDAP_OPT_X_TLS_PROTOCOL_MIN: *(int *)arg = lo->ldo_tls_protocol_min; break; case LDAP_OPT_X_TLS_RANDOM_FILE: *(char **)arg = lo->ldo_tls_randfile ? LDAP_STRDUP( lo->ldo_tls_randfile ) : NULL; break; case LDAP_OPT_X_TLS_SSL_CTX: { void *retval = 0; if ( ld != NULL ) { LDAPConn *conn = ld->ld_defconn; if ( conn != NULL ) { Sockbuf *sb = conn->lconn_sb; retval = ldap_pvt_tls_sb_ctx( sb ); } } *(void **)arg = retval; break; } case LDAP_OPT_X_TLS_CONNECT_CB: *(LDAP_TLS_CONNECT_CB **)arg = lo->ldo_tls_connect_cb; break; case LDAP_OPT_X_TLS_CONNECT_ARG: *(void **)arg = lo->ldo_tls_connect_arg; break; default: return -1; } return 0; } int ldap_pvt_tls_set_option( LDAP *ld, int option, void *arg ) { struct ldapoptions *lo; if( ld != NULL ) { assert( LDAP_VALID( ld ) ); if( !LDAP_VALID( ld ) ) { return LDAP_OPT_ERROR; } lo = &ld->ld_options; } else { /* Get pointer to global option structure */ lo = LDAP_INT_GLOBAL_OPT(); if ( lo == NULL ) { return LDAP_NO_MEMORY; } } switch( option ) { case LDAP_OPT_X_TLS: if ( !arg ) return -1; switch( *(int *) arg ) { case LDAP_OPT_X_TLS_NEVER: case LDAP_OPT_X_TLS_DEMAND: case LDAP_OPT_X_TLS_ALLOW: case LDAP_OPT_X_TLS_TRY: case LDAP_OPT_X_TLS_HARD: if (lo != NULL) { lo->ldo_tls_mode = *(int *)arg; } return 0; } return -1; case LDAP_OPT_X_TLS_CTX: if ( lo->ldo_tls_ctx ) ldap_pvt_tls_ctx_free( lo->ldo_tls_ctx ); lo->ldo_tls_ctx = arg; tls_ctx_ref( lo->ldo_tls_ctx ); return 0; case LDAP_OPT_X_TLS_CONNECT_CB: lo->ldo_tls_connect_cb = (LDAP_TLS_CONNECT_CB *)arg; return 0; case LDAP_OPT_X_TLS_CONNECT_ARG: lo->ldo_tls_connect_arg = arg; return 0; case LDAP_OPT_X_TLS_CACERTFILE: if ( lo->ldo_tls_cacertfile ) LDAP_FREE( lo->ldo_tls_cacertfile ); lo->ldo_tls_cacertfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL; return 0; case LDAP_OPT_X_TLS_CACERTDIR: if ( lo->ldo_tls_cacertdir ) LDAP_FREE( lo->ldo_tls_cacertdir ); lo->ldo_tls_cacertdir = arg ? LDAP_STRDUP( (char *) arg ) : NULL; return 0; case LDAP_OPT_X_TLS_CERTFILE: if ( lo->ldo_tls_certfile ) LDAP_FREE( lo->ldo_tls_certfile ); lo->ldo_tls_certfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL; return 0; case LDAP_OPT_X_TLS_KEYFILE: if ( lo->ldo_tls_keyfile ) LDAP_FREE( lo->ldo_tls_keyfile ); lo->ldo_tls_keyfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL; return 0; case LDAP_OPT_X_TLS_DHFILE: if ( lo->ldo_tls_dhfile ) LDAP_FREE( lo->ldo_tls_dhfile ); lo->ldo_tls_dhfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL; return 0; case LDAP_OPT_X_TLS_CRLFILE: /* GnuTLS only */ if ( lo->ldo_tls_crlfile ) LDAP_FREE( lo->ldo_tls_crlfile ); lo->ldo_tls_crlfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL; return 0; case LDAP_OPT_X_TLS_REQUIRE_CERT: if ( !arg ) return -1; switch( *(int *) arg ) { case LDAP_OPT_X_TLS_NEVER: case LDAP_OPT_X_TLS_DEMAND: case LDAP_OPT_X_TLS_ALLOW: case LDAP_OPT_X_TLS_TRY: case LDAP_OPT_X_TLS_HARD: lo->ldo_tls_require_cert = * (int *) arg; return 0; } return -1; #ifdef HAVE_OPENSSL_CRL case LDAP_OPT_X_TLS_CRLCHECK: /* OpenSSL only */ if ( !arg ) return -1; switch( *(int *) arg ) { case LDAP_OPT_X_TLS_CRL_NONE: case LDAP_OPT_X_TLS_CRL_PEER: case LDAP_OPT_X_TLS_CRL_ALL: lo->ldo_tls_crlcheck = * (int *) arg; return 0; } return -1; #endif case LDAP_OPT_X_TLS_CIPHER_SUITE: if ( lo->ldo_tls_ciphersuite ) LDAP_FREE( lo->ldo_tls_ciphersuite ); lo->ldo_tls_ciphersuite = arg ? LDAP_STRDUP( (char *) arg ) : NULL; return 0; case LDAP_OPT_X_TLS_PROTOCOL_MIN: if ( !arg ) return -1; lo->ldo_tls_protocol_min = *(int *)arg; return 0; case LDAP_OPT_X_TLS_RANDOM_FILE: if ( ld != NULL ) return -1; if ( lo->ldo_tls_randfile ) LDAP_FREE (lo->ldo_tls_randfile ); lo->ldo_tls_randfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL; break; case LDAP_OPT_X_TLS_NEWCTX: if ( !arg ) return -1; if ( lo->ldo_tls_ctx ) ldap_pvt_tls_ctx_free( lo->ldo_tls_ctx ); lo->ldo_tls_ctx = NULL; return ldap_int_tls_init_ctx( lo, *(int *)arg ); default: return -1; } return 0; } int ldap_int_tls_start ( LDAP *ld, LDAPConn *conn, LDAPURLDesc *srv ) { Sockbuf *sb; char *host; void *ssl; int ret; #ifdef LDAP_USE_NON_BLOCKING_TLS struct timeval start_time_tv, tv, tv0; ber_socket_t sd = AC_SOCKET_ERROR; #endif /* LDAP_USE_NON_BLOCKING_TLS */ if ( !conn ) return LDAP_PARAM_ERROR; sb = conn->lconn_sb; if( srv ) { host = srv->lud_host; } else { host = conn->lconn_server->lud_host; } /* avoid NULL host */ if( host == NULL ) { host = "localhost"; } (void) tls_init( tls_imp ); #ifdef LDAP_USE_NON_BLOCKING_TLS /* * Use non-blocking io during SSL Handshake when a timeout is configured */ if ( ld->ld_options.ldo_tm_net.tv_sec >= 0 ) { ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_SET_NONBLOCK, sb ); ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); tv = ld->ld_options.ldo_tm_net; tv0 = tv; #ifdef HAVE_GETTIMEOFDAY gettimeofday( &start_time_tv, NULL ); #else /* ! HAVE_GETTIMEOFDAY */ time( &start_time_tv.tv_sec ); start_time_tv.tv_usec = 0; #endif /* ! HAVE_GETTIMEOFDAY */ } #endif /* LDAP_USE_NON_BLOCKING_TLS */ ld->ld_errno = LDAP_SUCCESS; ret = ldap_int_tls_connect( ld, conn ); #ifdef LDAP_USE_NON_BLOCKING_TLS while ( ret > 0 ) { /* this should only happen for non-blocking io */ int wr=0; if ( sb->sb_trans_needs_read ) { wr=0; } else if ( sb->sb_trans_needs_write ) { wr=1; } Debug( LDAP_DEBUG_TRACE, "ldap_int_tls_start: ldap_int_tls_connect needs %s\n", wr ? "write": "read", 0, 0); ret = ldap_int_poll( ld, sd, &tv, wr); if ( ret < 0 ) { ld->ld_errno = LDAP_TIMEOUT; break; } else { /* ldap_int_poll called ldap_pvt_ndelay_off */ ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_SET_NONBLOCK, sb ); ret = ldap_int_tls_connect( ld, conn ); if ( ret > 0 ) { /* need to call tls_connect once more */ struct timeval curr_time_tv, delta_tv; /* This is mostly copied from result.c:wait4msg(), should * probably be moved into a separate function */ #ifdef HAVE_GETTIMEOFDAY gettimeofday( &curr_time_tv, NULL ); #else /* ! HAVE_GETTIMEOFDAY */ time( &curr_time_tv.tv_sec ); curr_time_tv.tv_usec = 0; #endif /* ! HAVE_GETTIMEOFDAY */ /* delta = curr - start */ delta_tv.tv_sec = curr_time_tv.tv_sec - start_time_tv.tv_sec; delta_tv.tv_usec = curr_time_tv.tv_usec - start_time_tv.tv_usec; if ( delta_tv.tv_usec < 0 ) { delta_tv.tv_sec--; delta_tv.tv_usec += 1000000; } /* tv0 < delta ? */ if ( ( tv0.tv_sec < delta_tv.tv_sec ) || ( ( tv0.tv_sec == delta_tv.tv_sec ) && ( tv0.tv_usec < delta_tv.tv_usec ) ) ) { ret = -1; ld->ld_errno = LDAP_TIMEOUT; break; } else { /* timeout -= delta_time */ tv0.tv_sec -= delta_tv.tv_sec; tv0.tv_usec -= delta_tv.tv_usec; if ( tv0.tv_usec < 0 ) { tv0.tv_sec--; tv0.tv_usec += 1000000; } start_time_tv.tv_sec = curr_time_tv.tv_sec; start_time_tv.tv_usec = curr_time_tv.tv_usec; } tv = tv0; Debug( LDAP_DEBUG_TRACE, "ldap_int_tls_start: ld %p %ld s %ld us to go\n", (void *)ld, (long) tv.tv_sec, (long) tv.tv_usec ); } } } if ( ld->ld_options.ldo_tm_net.tv_sec >= 0 ) { ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_SET_NONBLOCK, NULL ); } #endif /* LDAP_USE_NON_BLOCKING_TLS */ if ( ret < 0 ) { if ( ld->ld_errno == LDAP_SUCCESS ) ld->ld_errno = LDAP_CONNECT_ERROR; return (ld->ld_errno); } ssl = ldap_pvt_tls_sb_ctx( sb ); assert( ssl != NULL ); /* * compare host with name(s) in certificate */ if (ld->ld_options.ldo_tls_require_cert != LDAP_OPT_X_TLS_NEVER && ld->ld_options.ldo_tls_require_cert != LDAP_OPT_X_TLS_ALLOW) { ld->ld_errno = ldap_pvt_tls_check_hostname( ld, ssl, host ); if (ld->ld_errno != LDAP_SUCCESS) { return ld->ld_errno; } } return LDAP_SUCCESS; } void * ldap_pvt_tls_sb_ctx( Sockbuf *sb ) { void *p = NULL; ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_SSL, (void *)&p ); return p; } int ldap_pvt_tls_get_strength( void *s ) { tls_session *session = s; return tls_imp->ti_session_strength( session ); } int ldap_pvt_tls_get_my_dn( void *s, struct berval *dn, LDAPDN_rewrite_dummy *func, unsigned flags ) { tls_session *session = s; struct berval der_dn; int rc; rc = tls_imp->ti_session_my_dn( session, &der_dn ); if ( rc == LDAP_SUCCESS ) rc = ldap_X509dn2bv(&der_dn, dn, (LDAPDN_rewrite_func *)func, flags ); return rc; } #endif /* HAVE_TLS */ int ldap_start_tls( LDAP *ld, LDAPControl **serverctrls, LDAPControl **clientctrls, int *msgidp ) { return ldap_extended_operation( ld, LDAP_EXOP_START_TLS, NULL, serverctrls, clientctrls, msgidp ); } int ldap_install_tls( LDAP *ld ) { #ifndef HAVE_TLS return LDAP_NOT_SUPPORTED; #else if ( ldap_tls_inplace( ld ) ) { return LDAP_LOCAL_ERROR; } return ldap_int_tls_start( ld, ld->ld_defconn, NULL ); #endif } int ldap_start_tls_s ( LDAP *ld, LDAPControl **serverctrls, LDAPControl **clientctrls ) { #ifndef HAVE_TLS return LDAP_NOT_SUPPORTED; #else int rc; char *rspoid = NULL; struct berval *rspdata = NULL; /* XXYYZ: this initiates operation only on default connection! */ if ( ldap_tls_inplace( ld ) ) { return LDAP_LOCAL_ERROR; } rc = ldap_extended_operation_s( ld, LDAP_EXOP_START_TLS, NULL, serverctrls, clientctrls, &rspoid, &rspdata ); if ( rspoid != NULL ) { LDAP_FREE(rspoid); } if ( rspdata != NULL ) { ber_bvfree( rspdata ); } if ( rc == LDAP_SUCCESS ) { rc = ldap_int_tls_start( ld, ld->ld_defconn, NULL ); } return rc; #endif } /* These tags probably all belong in lber.h, but they're * not normally encountered when processing LDAP, so maybe * they belong somewhere else instead. */ #define LBER_TAG_OID ((ber_tag_t) 0x06UL) /* Tags for string types used in a DirectoryString. * * Note that IA5string is not one of the defined choices for * DirectoryString in X.520, but it gets used for email AVAs. */ #define LBER_TAG_UTF8 ((ber_tag_t) 0x0cUL) #define LBER_TAG_PRINTABLE ((ber_tag_t) 0x13UL) #define LBER_TAG_TELETEX ((ber_tag_t) 0x14UL) #define LBER_TAG_IA5 ((ber_tag_t) 0x16UL) #define LBER_TAG_UNIVERSAL ((ber_tag_t) 0x1cUL) #define LBER_TAG_BMP ((ber_tag_t) 0x1eUL) static oid_name * find_oid( struct berval *oid ) { int i; for ( i=0; !BER_BVISNULL( &oids[i].oid ); i++ ) { if ( oids[i].oid.bv_len != oid->bv_len ) continue; if ( !strcmp( oids[i].oid.bv_val, oid->bv_val )) return &oids[i]; } return NULL; } /* Converts BER Bitstring value to LDAP BitString value (RFC4517) * * berValue : IN * rfc4517Value: OUT * * berValue and ldapValue should not be NULL */ #define BITS_PER_BYTE 8 #define SQUOTE_LENGTH 1 #define B_CHAR_LENGTH 1 #define STR_OVERHEAD (2*SQUOTE_LENGTH + B_CHAR_LENGTH) static int der_to_ldap_BitString (struct berval *berValue, struct berval *ldapValue) { ber_len_t bitPadding=0; ber_len_t bits, maxBits; char *tmpStr; unsigned char byte; ber_len_t bitLength; ber_len_t valLen; unsigned char* valPtr; ldapValue->bv_len=0; ldapValue->bv_val=NULL; /* Gets padding and points to binary data */ valLen=berValue->bv_len; valPtr=(unsigned char*)berValue->bv_val; if (valLen) { bitPadding=(ber_len_t)(valPtr[0]); valLen--; valPtr++; } /* If Block is non DER encoding fixes to DER encoding */ if (bitPadding >= BITS_PER_BYTE) { if (valLen*BITS_PER_BYTE > bitPadding ) { valLen-=(bitPadding/BITS_PER_BYTE); bitPadding%=BITS_PER_BYTE; } else { valLen=0; bitPadding=0; } } /* Just in case bad encoding */ if (valLen*BITS_PER_BYTE < bitPadding ) { bitPadding=0; valLen=0; } /* Gets buffer to hold RFC4517 Bit String format */ bitLength=valLen*BITS_PER_BYTE-bitPadding; tmpStr=LDAP_MALLOC(bitLength + STR_OVERHEAD + 1); if (!tmpStr) return LDAP_NO_MEMORY; ldapValue->bv_val=tmpStr; ldapValue->bv_len=bitLength + STR_OVERHEAD; /* Formatting in '*binary-digit'B format */ maxBits=BITS_PER_BYTE; *tmpStr++ ='\''; while(valLen) { byte=*valPtr; if (valLen==1) maxBits-=bitPadding; for (bits=0; bitsbv_len = 0; bv->bv_val = NULL; navas = 0; nrdns = 0; /* A DN is a SEQUENCE of RDNs. An RDN is a SET of AVAs. * An AVA is a SEQUENCE of attr and value. * Count the number of AVAs and RDNs */ ber_init2( ber, in, LBER_USE_DER ); tag = ber_peek_tag( ber, &len ); if ( tag != LBER_SEQUENCE ) return LDAP_DECODING_ERROR; for ( tag = ber_first_element( ber, &len, &dn_end ); tag == LBER_SET; tag = ber_next_element( ber, &len, dn_end )) { nrdns++; for ( tag = ber_first_element( ber, &len, &rdn_end ); tag == LBER_SEQUENCE; tag = ber_next_element( ber, &len, rdn_end )) { tag = ber_skip_tag( ber, &len ); ber_skip_data( ber, len ); navas++; } } /* Allocate the DN/RDN/AVA stuff as a single block */ dnsize = sizeof(LDAPRDN) * (nrdns+1); dnsize += sizeof(LDAPAVA *) * (navas+nrdns); dnsize += sizeof(LDAPAVA) * navas; if (dnsize > sizeof(ptrs)) { newDN = (LDAPDN)LDAP_MALLOC( dnsize ); if ( newDN == NULL ) return LDAP_NO_MEMORY; } else { newDN = (LDAPDN)(char *)ptrs; } newDN[nrdns] = NULL; newRDN = (LDAPRDN)(newDN + nrdns+1); newAVA = (LDAPAVA *)(newRDN + navas + nrdns); baseAVA = newAVA; /* Rewind and start extracting */ ber_rewind( ber ); tag = ber_first_element( ber, &len, &dn_end ); for ( i = nrdns - 1; i >= 0; i-- ) { newDN[i] = newRDN; for ( tag = ber_first_element( ber, &len, &rdn_end ); tag == LBER_SEQUENCE; tag = ber_next_element( ber, &len, rdn_end )) { *newRDN++ = newAVA; tag = ber_skip_tag( ber, &len ); tag = ber_get_stringbv( ber, &Oid, LBER_BV_NOTERM ); if ( tag != LBER_TAG_OID ) { rc = LDAP_DECODING_ERROR; goto nomem; } oid2.bv_val = oidptr; oid2.bv_len = oidrem; if ( ber_decode_oid( &Oid, &oid2 ) < 0 ) { rc = LDAP_DECODING_ERROR; goto nomem; } oidname = find_oid( &oid2 ); if ( !oidname ) { newAVA->la_attr = oid2; oidptr += oid2.bv_len + 1; oidrem -= oid2.bv_len + 1; /* Running out of OID buffer space? */ if (oidrem < 128) { if ( oidsize == 0 ) { oidsize = sizeof(oids) * 2; oidrem = oidsize; oidbuf = LDAP_MALLOC( oidsize ); if ( oidbuf == NULL ) goto nomem; oidptr = oidbuf; } else { char *old = oidbuf; oidbuf = LDAP_REALLOC( oidbuf, oidsize*2 ); if ( oidbuf == NULL ) goto nomem; /* Buffer moved! Fix AVA pointers */ if ( old != oidbuf ) { LDAPAVA *a; long dif = oidbuf - old; for (a=baseAVA; a<=newAVA; a++){ if (a->la_attr.bv_val >= old && a->la_attr.bv_val <= (old + oidsize)) a->la_attr.bv_val += dif; } } oidptr = oidbuf + oidsize - oidrem; oidrem += oidsize; oidsize *= 2; } } } else { if ( func ) { newAVA->la_attr = oidname->oid; } else { newAVA->la_attr = oidname->name; } } newAVA->la_private = NULL; newAVA->la_flags = LDAP_AVA_STRING; tag = ber_get_stringbv( ber, &Val, LBER_BV_NOTERM ); switch(tag) { case LBER_TAG_UNIVERSAL: /* This uses 32-bit ISO 10646-1 */ csize = 4; goto to_utf8; case LBER_TAG_BMP: /* This uses 16-bit ISO 10646-1 */ csize = 2; goto to_utf8; case LBER_TAG_TELETEX: /* This uses 8-bit, assume ISO 8859-1 */ csize = 1; to_utf8: rc = ldap_ucs_to_utf8s( &Val, csize, &newAVA->la_value ); newAVA->la_flags |= LDAP_AVA_NONPRINTABLE; allocd: newAVA->la_flags |= LDAP_AVA_FREE_VALUE; if (rc != LDAP_SUCCESS) goto nomem; break; case LBER_TAG_UTF8: newAVA->la_flags |= LDAP_AVA_NONPRINTABLE; /* This is already in UTF-8 encoding */ case LBER_TAG_IA5: case LBER_TAG_PRINTABLE: /* These are always 7-bit strings */ newAVA->la_value = Val; break; case LBER_BITSTRING: /* X.690 bitString value converted to RFC4517 Bit String */ rc = der_to_ldap_BitString( &Val, &newAVA->la_value ); goto allocd; default: /* Not a string type at all */ newAVA->la_flags = 0; newAVA->la_value = Val; break; } newAVA++; } *newRDN++ = NULL; tag = ber_next_element( ber, &len, dn_end ); } if ( func ) { rc = func( newDN, flags, NULL ); if ( rc != LDAP_SUCCESS ) goto nomem; } rc = ldap_dn2bv_x( newDN, bv, LDAP_DN_FORMAT_LDAPV3, NULL ); nomem: for (;baseAVA < newAVA; baseAVA++) { if (baseAVA->la_flags & LDAP_AVA_FREE_ATTR) LDAP_FREE( baseAVA->la_attr.bv_val ); if (baseAVA->la_flags & LDAP_AVA_FREE_VALUE) LDAP_FREE( baseAVA->la_value.bv_val ); } if ( oidsize != 0 ) LDAP_FREE( oidbuf ); if ( newDN != (LDAPDN)(char *) ptrs ) LDAP_FREE( newDN ); return rc; } openldap-2.4.42+dfsg/libraries/libldap/util-int.c0000644000175000017500000004260012563404150020326 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * Portions Copyright 1998 A. Hartgers. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* ACKNOWLEDGEMENTS: * This work was initially developed by Bart Hartgers for inclusion in * OpenLDAP Software. */ /* * util-int.c Various functions to replace missing threadsafe ones. * Without the real *_r funcs, things will * work, but might not be threadsafe. */ #include "portable.h" #include #include #include #include #include #include #include "ldap-int.h" #ifndef h_errno /* newer systems declare this in for you, older ones don't. * harmless to declare it again (unless defined by a macro). */ extern int h_errno; #endif #ifdef HAVE_HSTRERROR # define HSTRERROR(e) hstrerror(e) #else # define HSTRERROR(e) hp_strerror(e) #endif #ifndef LDAP_R_COMPILE # undef HAVE_REENTRANT_FUNCTIONS # undef HAVE_CTIME_R # undef HAVE_GETHOSTBYNAME_R # undef HAVE_GETHOSTBYADDR_R #else # include ldap_pvt_thread_mutex_t ldap_int_resolv_mutex; ldap_pvt_thread_mutex_t ldap_int_hostname_mutex; static ldap_pvt_thread_mutex_t ldap_int_gettime_mutex; # if (defined( HAVE_CTIME_R ) || defined( HAVE_REENTRANT_FUNCTIONS)) \ && defined( CTIME_R_NARGS ) # define USE_CTIME_R # else static ldap_pvt_thread_mutex_t ldap_int_ctime_mutex; # endif /* USE_GMTIME_R and USE_LOCALTIME_R defined in ldap_pvt.h */ #ifdef LDAP_DEVEL /* to be released with 2.5 */ #if !defined( USE_GMTIME_R ) || !defined( USE_LOCALTIME_R ) /* we use the same mutex for gmtime(3) and localtime(3) * because implementations may use the same buffer * for both functions */ static ldap_pvt_thread_mutex_t ldap_int_gmtime_mutex; #endif #else /* ! LDAP_DEVEL */ ldap_pvt_thread_mutex_t ldap_int_gmtime_mutex; #endif /* ! LDAP_DEVEL */ # if defined(HAVE_GETHOSTBYNAME_R) && \ (GETHOSTBYNAME_R_NARGS < 5) || (6 < GETHOSTBYNAME_R_NARGS) /* Don't know how to handle this version, pretend it's not there */ # undef HAVE_GETHOSTBYNAME_R # endif # if defined(HAVE_GETHOSTBYADDR_R) && \ (GETHOSTBYADDR_R_NARGS < 7) || (8 < GETHOSTBYADDR_R_NARGS) /* Don't know how to handle this version, pretend it's not there */ # undef HAVE_GETHOSTBYADDR_R # endif #endif /* LDAP_R_COMPILE */ char *ldap_pvt_ctime( const time_t *tp, char *buf ) { #ifdef USE_CTIME_R # if (CTIME_R_NARGS > 3) || (CTIME_R_NARGS < 2) # error "CTIME_R_NARGS should be 2 or 3" # elif CTIME_R_NARGS > 2 && defined(CTIME_R_RETURNS_INT) return( ctime_r(tp,buf,26) < 0 ? 0 : buf ); # elif CTIME_R_NARGS > 2 return ctime_r(tp,buf,26); # else return ctime_r(tp,buf); # endif #else LDAP_MUTEX_LOCK( &ldap_int_ctime_mutex ); AC_MEMCPY( buf, ctime(tp), 26 ); LDAP_MUTEX_UNLOCK( &ldap_int_ctime_mutex ); return buf; #endif } #if !defined( USE_GMTIME_R ) || !defined( USE_LOCALTIME_R ) int ldap_pvt_gmtime_lock( void ) { # ifndef LDAP_R_COMPILE return 0; # else /* LDAP_R_COMPILE */ return ldap_pvt_thread_mutex_lock( &ldap_int_gmtime_mutex ); # endif /* LDAP_R_COMPILE */ } int ldap_pvt_gmtime_unlock( void ) { # ifndef LDAP_R_COMPILE return 0; # else /* LDAP_R_COMPILE */ return ldap_pvt_thread_mutex_unlock( &ldap_int_gmtime_mutex ); # endif /* LDAP_R_COMPILE */ } #endif /* !USE_GMTIME_R || !USE_LOCALTIME_R */ #ifndef USE_GMTIME_R struct tm * ldap_pvt_gmtime( const time_t *timep, struct tm *result ) { struct tm *tm_ptr; LDAP_MUTEX_LOCK( &ldap_int_gmtime_mutex ); tm_ptr = gmtime( timep ); if ( tm_ptr == NULL ) { result = NULL; } else { *result = *tm_ptr; } LDAP_MUTEX_UNLOCK( &ldap_int_gmtime_mutex ); return result; } #endif /* !USE_GMTIME_R */ #ifndef USE_LOCALTIME_R struct tm * ldap_pvt_localtime( const time_t *timep, struct tm *result ) { struct tm *tm_ptr; LDAP_MUTEX_LOCK( &ldap_int_gmtime_mutex ); tm_ptr = localtime( timep ); if ( tm_ptr == NULL ) { result = NULL; } else { *result = *tm_ptr; } LDAP_MUTEX_UNLOCK( &ldap_int_gmtime_mutex ); return result; } #endif /* !USE_LOCALTIME_R */ /* return a broken out time, with microseconds */ #ifdef _WIN32 /* Windows SYSTEMTIME only has 10 millisecond resolution, so we * also need to use a high resolution timer to get microseconds. * This is pretty clunky. */ void ldap_pvt_gettime( struct lutil_tm *tm ) { static LARGE_INTEGER cFreq; static LARGE_INTEGER prevCount; static int subs; static int offset; LARGE_INTEGER count; SYSTEMTIME st; GetSystemTime( &st ); QueryPerformanceCounter( &count ); /* It shouldn't ever go backwards, but multiple CPUs might * be able to hit in the same tick. */ LDAP_MUTEX_LOCK( &ldap_int_gettime_mutex ); if ( count.QuadPart <= prevCount.QuadPart ) { subs++; } else { subs = 0; prevCount = count; } LDAP_MUTEX_UNLOCK( &ldap_int_gettime_mutex ); /* We assume Windows has at least a vague idea of * when a second begins. So we align our microsecond count * with the Windows millisecond count using this offset. * We retain the submillisecond portion of our own count. * * Note - this also assumes that the relationship between * the PerformanceCouunter and SystemTime stays constant; * that assumption breaks if the SystemTime is adjusted by * an external action. */ if ( !cFreq.QuadPart ) { long long t; int usec; QueryPerformanceFrequency( &cFreq ); /* just get sub-second portion of counter */ t = count.QuadPart % cFreq.QuadPart; /* convert to microseconds */ t *= 1000000; usec = t / cFreq.QuadPart; offset = usec - st.wMilliseconds * 1000; } tm->tm_usub = subs; /* convert to microseconds */ count.QuadPart %= cFreq.QuadPart; count.QuadPart *= 1000000; count.QuadPart /= cFreq.QuadPart; count.QuadPart -= offset; tm->tm_usec = count.QuadPart % 1000000; if ( tm->tm_usec < 0 ) tm->tm_usec += 1000000; /* any difference larger than microseconds is * already reflected in st */ tm->tm_sec = st.wSecond; tm->tm_min = st.wMinute; tm->tm_hour = st.wHour; tm->tm_mday = st.wDay; tm->tm_mon = st.wMonth - 1; tm->tm_year = st.wYear - 1900; } #else void ldap_pvt_gettime( struct lutil_tm *ltm ) { struct timeval tv; static struct timeval prevTv; static int subs; struct tm tm; time_t t; gettimeofday( &tv, NULL ); t = tv.tv_sec; LDAP_MUTEX_LOCK( &ldap_int_gettime_mutex ); if ( tv.tv_sec < prevTv.tv_sec || ( tv.tv_sec == prevTv.tv_sec && tv.tv_usec <= prevTv.tv_usec )) { subs++; } else { subs = 0; prevTv = tv; } LDAP_MUTEX_UNLOCK( &ldap_int_gettime_mutex ); ltm->tm_usub = subs; ldap_pvt_gmtime( &t, &tm ); ltm->tm_sec = tm.tm_sec; ltm->tm_min = tm.tm_min; ltm->tm_hour = tm.tm_hour; ltm->tm_mday = tm.tm_mday; ltm->tm_mon = tm.tm_mon; ltm->tm_year = tm.tm_year; ltm->tm_usec = tv.tv_usec; } #endif size_t ldap_pvt_csnstr(char *buf, size_t len, unsigned int replica, unsigned int mod) { struct lutil_tm tm; int n; ldap_pvt_gettime( &tm ); n = snprintf( buf, len, "%4d%02d%02d%02d%02d%02d.%06dZ#%06x#%03x#%06x", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_usec, tm.tm_usub, replica, mod ); if( n < 0 ) return 0; return ( (size_t) n < len ) ? n : 0; } #define BUFSTART (1024-32) #define BUFMAX (32*1024-32) #if defined(LDAP_R_COMPILE) static char *safe_realloc( char **buf, int len ); #if !(defined(HAVE_GETHOSTBYNAME_R) && defined(HAVE_GETHOSTBYADDR_R)) static int copy_hostent( struct hostent *res, char **buf, struct hostent * src ); #endif #endif int ldap_pvt_gethostbyname_a( const char *name, struct hostent *resbuf, char **buf, struct hostent **result, int *herrno_ptr ) { #if defined( HAVE_GETHOSTBYNAME_R ) # define NEED_SAFE_REALLOC 1 int r=-1; int buflen=BUFSTART; *buf = NULL; for(;buflensa_family == AF_INET6) { struct sockaddr_in6 *sin = (struct sockaddr_in6 *)sa; addr = (char *)&sin->sin6_addr; alen = sizeof(sin->sin6_addr); } else #endif if (sa->sa_family == AF_INET) { struct sockaddr_in *sin = (struct sockaddr_in *)sa; addr = (char *)&sin->sin_addr; alen = sizeof(sin->sin_addr); } else { rc = NO_RECOVERY; *err = (char *)HSTRERROR( rc ); return rc; } #if defined( HAVE_GETHOSTBYADDR_R ) for(;buflensa_family, &hb, buf, buflen, &h_errno ); rc = (hp == NULL) ? -1 : 0; #else rc = gethostbyaddr_r( addr, alen, sa->sa_family, &hb, buf, buflen, &hp, &h_errno ); #endif #ifdef NETDB_INTERNAL if ((rc<0) && (h_errno==NETDB_INTERNAL) && (errno==ERANGE)) { buflen*=2; continue; } #endif break; } if (hp) { strncpy( name, hp->h_name, namelen ); } else { *err = (char *)HSTRERROR( h_errno ); } LDAP_FREE(buf); #else /* HAVE_GETHOSTBYADDR_R */ LDAP_MUTEX_LOCK( &ldap_int_resolv_mutex ); hp = gethostbyaddr( addr, alen, sa->sa_family ); if (hp) { strncpy( name, hp->h_name, namelen ); rc = 0; } else { rc = h_errno; *err = (char *)HSTRERROR( h_errno ); } LDAP_MUTEX_UNLOCK( &ldap_int_resolv_mutex ); #endif /* !HAVE_GETHOSTBYADDR_R */ return rc; #endif /* !HAVE_GETNAMEINFO */ } int ldap_pvt_gethostbyaddr_a( const char *addr, int len, int type, struct hostent *resbuf, char **buf, struct hostent **result, int *herrno_ptr ) { #if defined( HAVE_GETHOSTBYADDR_R ) # undef NEED_SAFE_REALLOC # define NEED_SAFE_REALLOC int r=-1; int buflen=BUFSTART; *buf = NULL; for(;buflenh_name ) + 1; if( src->h_aliases != NULL ) { for( p = src->h_aliases; (*p) != NULL; p++ ) { total_alias_len += strlen( *p ) + 1; n_alias++; } } if( src->h_addr_list != NULL ) { for( p = src->h_addr_list; (*p) != NULL; p++ ) { n_addr++; } total_addr_len = n_addr * src->h_length; } total_len = (n_alias + n_addr + 2) * sizeof( char * ) + total_addr_len + total_alias_len + name_len; if (safe_realloc( buf, total_len )) { tp = (char **) *buf; tbuf = *buf + (n_alias + n_addr + 2) * sizeof( char * ); AC_MEMCPY( res, src, sizeof( struct hostent ) ); /* first the name... */ AC_MEMCPY( tbuf, src->h_name, name_len ); res->h_name = tbuf; tbuf+=name_len; /* now the aliases */ res->h_aliases = tp; if ( src->h_aliases != NULL ) { tbuf = cpy_aliases( &tp, tbuf, src->h_aliases ); } *tp++=NULL; /* finally the addresses */ res->h_addr_list = tp; if ( src->h_addr_list != NULL ) { tbuf = cpy_addresses( &tp, tbuf, src->h_addr_list, src->h_length ); } *tp++=NULL; return 0; } return -1; } #endif #if defined( NEED_SAFE_REALLOC ) static char *safe_realloc( char **buf, int len ) { char *tmpbuf; tmpbuf = LDAP_REALLOC( *buf, len ); if (tmpbuf) { *buf=tmpbuf; } return tmpbuf; } #endif char * ldap_pvt_get_fqdn( char *name ) { char *fqdn, *ha_buf; char hostbuf[MAXHOSTNAMELEN+1]; struct hostent *hp, he_buf; int rc, local_h_errno; if( name == NULL ) { if( gethostname( hostbuf, MAXHOSTNAMELEN ) == 0 ) { hostbuf[MAXHOSTNAMELEN] = '\0'; name = hostbuf; } else { name = "localhost"; } } rc = ldap_pvt_gethostbyname_a( name, &he_buf, &ha_buf, &hp, &local_h_errno ); if( rc < 0 || hp == NULL || hp->h_name == NULL ) { fqdn = LDAP_STRDUP( name ); } else { fqdn = LDAP_STRDUP( hp->h_name ); } LDAP_FREE( ha_buf ); return fqdn; } #if ( defined( HAVE_GETADDRINFO ) || defined( HAVE_GETNAMEINFO ) ) \ && !defined( HAVE_GAI_STRERROR ) char *ldap_pvt_gai_strerror (int code) { static struct { int code; const char *msg; } values[] = { #ifdef EAI_ADDRFAMILY { EAI_ADDRFAMILY, N_("Address family for hostname not supported") }, #endif { EAI_AGAIN, N_("Temporary failure in name resolution") }, { EAI_BADFLAGS, N_("Bad value for ai_flags") }, { EAI_FAIL, N_("Non-recoverable failure in name resolution") }, { EAI_FAMILY, N_("ai_family not supported") }, { EAI_MEMORY, N_("Memory allocation failure") }, #ifdef EAI_NODATA { EAI_NODATA, N_("No address associated with hostname") }, #endif { EAI_NONAME, N_("Name or service not known") }, { EAI_SERVICE, N_("Servname not supported for ai_socktype") }, { EAI_SOCKTYPE, N_("ai_socktype not supported") }, #ifdef EAI_SYSTEM { EAI_SYSTEM, N_("System error") }, #endif { 0, NULL } }; int i; for ( i = 0; values[i].msg != NULL; i++ ) { if ( values[i].code == code ) { return (char *) _(values[i].msg); } } return _("Unknown error"); } #endif openldap-2.4.42+dfsg/libraries/libldap/whoami.c0000644000175000017500000000404012563404150020041 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* ACKNOWLEDGEMENTS: * This program was orignally developed by Kurt D. Zeilenga for inclusion in * OpenLDAP Software. */ #include "portable.h" #include #include #include #include #include "ldap-int.h" /* * LDAP Who Am I? (Extended) Operation */ int ldap_parse_whoami( LDAP *ld, LDAPMessage *res, struct berval **authzid ) { int rc; char *retoid = NULL; assert( ld != NULL ); assert( LDAP_VALID( ld ) ); assert( res != NULL ); assert( authzid != NULL ); *authzid = NULL; rc = ldap_parse_extended_result( ld, res, &retoid, authzid, 0 ); if( rc != LDAP_SUCCESS ) { ldap_perror( ld, "ldap_parse_whoami" ); return rc; } ber_memfree( retoid ); return rc; } int ldap_whoami( LDAP *ld, LDAPControl **sctrls, LDAPControl **cctrls, int *msgidp ) { int rc; assert( ld != NULL ); assert( LDAP_VALID( ld ) ); assert( msgidp != NULL ); rc = ldap_extended_operation( ld, LDAP_EXOP_WHO_AM_I, NULL, sctrls, cctrls, msgidp ); return rc; } int ldap_whoami_s( LDAP *ld, struct berval **authzid, LDAPControl **sctrls, LDAPControl **cctrls ) { int rc; int msgid; LDAPMessage *res; rc = ldap_whoami( ld, sctrls, cctrls, &msgid ); if ( rc != LDAP_SUCCESS ) return rc; if ( ldap_result( ld, msgid, LDAP_MSG_ALL, (struct timeval *) NULL, &res ) == -1 || !res ) { return ld->ld_errno; } rc = ldap_parse_whoami( ld, res, authzid ); if( rc != LDAP_SUCCESS ) { ldap_msgfree( res ); return rc; } return( ldap_result2error( ld, res, 1 ) ); } openldap-2.4.42+dfsg/libraries/libldap/cancel.c0000644000175000017500000000334412563404150020010 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* ACKNOWLEDGEMENTS: * This program was originally developed by Kurt D. Zeilenga for inclusion * in OpenLDAP Software. */ /* * LDAPv3 Cancel Operation Request */ #include "portable.h" #include #include #include #include #include #include "ldap-int.h" #include "ldap_log.h" int ldap_cancel( LDAP *ld, int cancelid, LDAPControl **sctrls, LDAPControl **cctrls, int *msgidp ) { BerElement *cancelidber = NULL; struct berval *cancelidvalp = NULL; int rc; cancelidber = ber_alloc_t( LBER_USE_DER ); ber_printf( cancelidber, "{i}", cancelid ); ber_flatten( cancelidber, &cancelidvalp ); rc = ldap_extended_operation( ld, LDAP_EXOP_CANCEL, cancelidvalp, sctrls, cctrls, msgidp ); ber_free( cancelidber, 1 ); return rc; } int ldap_cancel_s( LDAP *ld, int cancelid, LDAPControl **sctrls, LDAPControl **cctrls ) { BerElement *cancelidber = NULL; struct berval *cancelidvalp = NULL; int rc; cancelidber = ber_alloc_t( LBER_USE_DER ); ber_printf( cancelidber, "{i}", cancelid ); ber_flatten( cancelidber, &cancelidvalp ); rc = ldap_extended_operation_s( ld, LDAP_EXOP_CANCEL, cancelidvalp, sctrls, cctrls, NULL, NULL ); ber_free( cancelidber, 1 ); return rc; } openldap-2.4.42+dfsg/libraries/libldap/cyrus.c0000644000175000017500000006507412563404150017740 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #include "portable.h" #include #include #include #include #include #include #include #include #ifdef HAVE_LIMITS_H #include #endif #include "ldap-int.h" #ifdef HAVE_CYRUS_SASL #ifdef HAVE_LIMITS_H #include #endif #ifndef INT_MAX #define INT_MAX 2147483647 /* 32 bit signed max */ #endif #ifdef HAVE_SASL_SASL_H #include #else #include #endif #if SASL_VERSION_MAJOR >= 2 #define SASL_CONST const #else #define SASL_CONST #endif /* * Various Cyrus SASL related stuff. */ static const sasl_callback_t client_callbacks[] = { #ifdef SASL_CB_GETREALM { SASL_CB_GETREALM, NULL, NULL }, #endif { SASL_CB_USER, NULL, NULL }, { SASL_CB_AUTHNAME, NULL, NULL }, { SASL_CB_PASS, NULL, NULL }, { SASL_CB_ECHOPROMPT, NULL, NULL }, { SASL_CB_NOECHOPROMPT, NULL, NULL }, { SASL_CB_LIST_END, NULL, NULL } }; int ldap_int_sasl_init( void ) { /* XXX not threadsafe */ static int sasl_initialized = 0; #ifdef HAVE_SASL_VERSION /* stringify the version number, sasl.h doesn't do it for us */ #define VSTR0(maj, min, pat) #maj "." #min "." #pat #define VSTR(maj, min, pat) VSTR0(maj, min, pat) #define SASL_VERSION_STRING VSTR(SASL_VERSION_MAJOR, SASL_VERSION_MINOR, \ SASL_VERSION_STEP) { int rc; sasl_version( NULL, &rc ); if ( ((rc >> 16) != ((SASL_VERSION_MAJOR << 8)|SASL_VERSION_MINOR)) || (rc & 0xffff) < SASL_VERSION_STEP) { char version[sizeof("xxx.xxx.xxxxx")]; sprintf( version, "%u.%d.%d", (unsigned)rc >> 24, (rc >> 16) & 0xff, rc & 0xffff ); Debug( LDAP_DEBUG_ANY, "ldap_int_sasl_init: SASL library version mismatch:" " expected " SASL_VERSION_STRING "," " got %s\n", version, 0, 0 ); return -1; } } #endif if ( sasl_initialized ) { return 0; } /* SASL 2 takes care of its own memory completely internally */ #if SASL_VERSION_MAJOR < 2 && !defined(CSRIMALLOC) sasl_set_alloc( ber_memalloc, ber_memcalloc, ber_memrealloc, ber_memfree ); #endif /* CSRIMALLOC */ #ifdef LDAP_R_COMPILE sasl_set_mutex( ldap_pvt_sasl_mutex_new, ldap_pvt_sasl_mutex_lock, ldap_pvt_sasl_mutex_unlock, ldap_pvt_sasl_mutex_dispose ); #endif if ( sasl_client_init( NULL ) == SASL_OK ) { sasl_initialized = 1; return 0; } #if SASL_VERSION_MAJOR < 2 /* A no-op to make sure we link with Cyrus 1.5 */ sasl_client_auth( NULL, NULL, NULL, 0, NULL, NULL ); #endif return -1; } static void sb_sasl_cyrus_init( struct sb_sasl_generic_data *p, ber_len_t *min_send, ber_len_t *max_send, ber_len_t *max_recv) { sasl_conn_t *sasl_context = (sasl_conn_t *)p->ops_private; ber_len_t maxbuf; sasl_getprop( sasl_context, SASL_MAXOUTBUF, (SASL_CONST void **)(char *) &maxbuf ); *min_send = SASL_MIN_BUFF_SIZE; *max_send = maxbuf; *max_recv = SASL_MAX_BUFF_SIZE; } static ber_int_t sb_sasl_cyrus_encode( struct sb_sasl_generic_data *p, unsigned char *buf, ber_len_t len, Sockbuf_Buf *dst) { sasl_conn_t *sasl_context = (sasl_conn_t *)p->ops_private; ber_int_t ret; unsigned tmpsize = dst->buf_size; ret = sasl_encode( sasl_context, (char *)buf, len, (SASL_CONST char **)&dst->buf_base, &tmpsize ); dst->buf_size = tmpsize; dst->buf_end = dst->buf_size; if ( ret != SASL_OK ) { ber_log_printf( LDAP_DEBUG_ANY, p->sbiod->sbiod_sb->sb_debug, "sb_sasl_cyrus_encode: failed to encode packet: %s\n", sasl_errstring( ret, NULL, NULL ) ); return -1; } return 0; } static ber_int_t sb_sasl_cyrus_decode( struct sb_sasl_generic_data *p, const Sockbuf_Buf *src, Sockbuf_Buf *dst) { sasl_conn_t *sasl_context = (sasl_conn_t *)p->ops_private; ber_int_t ret; unsigned tmpsize = dst->buf_size; ret = sasl_decode( sasl_context, src->buf_base, src->buf_end, (SASL_CONST char **)&dst->buf_base, (unsigned *)&tmpsize ); dst->buf_size = tmpsize; dst->buf_end = dst->buf_size; if ( ret != SASL_OK ) { ber_log_printf( LDAP_DEBUG_ANY, p->sbiod->sbiod_sb->sb_debug, "sb_sasl_cyrus_decode: failed to decode packet: %s\n", sasl_errstring( ret, NULL, NULL ) ); return -1; } return 0; } static void sb_sasl_cyrus_reset_buf( struct sb_sasl_generic_data *p, Sockbuf_Buf *buf) { #if SASL_VERSION_MAJOR >= 2 ber_pvt_sb_buf_init( buf ); #else ber_pvt_sb_buf_destroy( buf ); #endif } static void sb_sasl_cyrus_fini( struct sb_sasl_generic_data *p) { #if SASL_VERSION_MAJOR >= 2 /* * SASLv2 encode/decode buffers are managed by * libsasl2. Ensure they are not freed by liblber. */ p->buf_in.buf_base = NULL; p->buf_out.buf_base = NULL; #endif } static const struct sb_sasl_generic_ops sb_sasl_cyrus_ops = { sb_sasl_cyrus_init, sb_sasl_cyrus_encode, sb_sasl_cyrus_decode, sb_sasl_cyrus_reset_buf, sb_sasl_cyrus_fini }; int ldap_pvt_sasl_install( Sockbuf *sb, void *ctx_arg ) { struct sb_sasl_generic_install install_arg; install_arg.ops = &sb_sasl_cyrus_ops; install_arg.ops_private = ctx_arg; return ldap_pvt_sasl_generic_install( sb, &install_arg ); } void ldap_pvt_sasl_remove( Sockbuf *sb ) { ldap_pvt_sasl_generic_remove( sb ); } static int sasl_err2ldap( int saslerr ) { int rc; /* map SASL errors to LDAP API errors returned by: * sasl_client_new() * SASL_OK, SASL_NOMECH, SASL_NOMEM * sasl_client_start() * SASL_OK, SASL_NOMECH, SASL_NOMEM, SASL_INTERACT * sasl_client_step() * SASL_OK, SASL_INTERACT, SASL_BADPROT, SASL_BADSERV */ switch (saslerr) { case SASL_CONTINUE: rc = LDAP_MORE_RESULTS_TO_RETURN; break; case SASL_INTERACT: rc = LDAP_LOCAL_ERROR; break; case SASL_OK: rc = LDAP_SUCCESS; break; case SASL_NOMEM: rc = LDAP_NO_MEMORY; break; case SASL_NOMECH: rc = LDAP_AUTH_UNKNOWN; break; case SASL_BADPROT: rc = LDAP_DECODING_ERROR; break; case SASL_BADSERV: rc = LDAP_AUTH_UNKNOWN; break; /* other codes */ case SASL_BADAUTH: rc = LDAP_AUTH_UNKNOWN; break; case SASL_NOAUTHZ: rc = LDAP_PARAM_ERROR; break; case SASL_FAIL: rc = LDAP_LOCAL_ERROR; break; case SASL_TOOWEAK: case SASL_ENCRYPT: rc = LDAP_AUTH_UNKNOWN; break; default: rc = LDAP_LOCAL_ERROR; break; } assert( rc == LDAP_SUCCESS || LDAP_API_ERROR( rc ) ); return rc; } int ldap_int_sasl_open( LDAP *ld, LDAPConn *lc, const char * host ) { int rc; sasl_conn_t *ctx; assert( lc->lconn_sasl_authctx == NULL ); if ( host == NULL ) { ld->ld_errno = LDAP_LOCAL_ERROR; return ld->ld_errno; } if ( ldap_int_sasl_init() ) { ld->ld_errno = LDAP_LOCAL_ERROR; return ld->ld_errno; } #if SASL_VERSION_MAJOR >= 2 rc = sasl_client_new( "ldap", host, NULL, NULL, client_callbacks, 0, &ctx ); #else rc = sasl_client_new( "ldap", host, client_callbacks, SASL_SECURITY_LAYER, &ctx ); #endif if ( rc != SASL_OK ) { ld->ld_errno = sasl_err2ldap( rc ); return ld->ld_errno; } Debug( LDAP_DEBUG_TRACE, "ldap_int_sasl_open: host=%s\n", host, 0, 0 ); lc->lconn_sasl_authctx = ctx; return LDAP_SUCCESS; } int ldap_int_sasl_close( LDAP *ld, LDAPConn *lc ) { sasl_conn_t *ctx = lc->lconn_sasl_authctx; if( ctx != NULL ) { sasl_dispose( &ctx ); if ( lc->lconn_sasl_sockctx && lc->lconn_sasl_authctx != lc->lconn_sasl_sockctx ) { ctx = lc->lconn_sasl_sockctx; sasl_dispose( &ctx ); } lc->lconn_sasl_sockctx = NULL; lc->lconn_sasl_authctx = NULL; } return LDAP_SUCCESS; } int ldap_int_sasl_bind( LDAP *ld, const char *dn, const char *mechs, LDAPControl **sctrls, LDAPControl **cctrls, unsigned flags, LDAP_SASL_INTERACT_PROC *interact, void *defaults, LDAPMessage *result, const char **rmech, int *msgid ) { const char *mech; sasl_ssf_t *ssf; sasl_conn_t *ctx; sasl_interact_t *prompts = NULL; struct berval ccred = BER_BVNULL; int saslrc, rc; unsigned credlen; Debug( LDAP_DEBUG_TRACE, "ldap_int_sasl_bind: %s\n", mechs ? mechs : "", 0, 0 ); /* do a quick !LDAPv3 check... ldap_sasl_bind will do the rest. */ if (ld->ld_version < LDAP_VERSION3) { ld->ld_errno = LDAP_NOT_SUPPORTED; return ld->ld_errno; } /* Starting a Bind */ if ( !result ) { const char *pmech = NULL; sasl_conn_t *oldctx; ber_socket_t sd; void *ssl; rc = 0; LDAP_MUTEX_LOCK( &ld->ld_conn_mutex ); ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, &sd ); if ( sd == AC_SOCKET_INVALID || !ld->ld_defconn ) { /* not connected yet */ rc = ldap_open_defconn( ld ); if ( rc == 0 ) { ber_sockbuf_ctrl( ld->ld_defconn->lconn_sb, LBER_SB_OPT_GET_FD, &sd ); if( sd == AC_SOCKET_INVALID ) { ld->ld_errno = LDAP_LOCAL_ERROR; rc = ld->ld_errno; } } } if ( rc == 0 && ld->ld_defconn && ld->ld_defconn->lconn_status == LDAP_CONNST_CONNECTING ) { rc = ldap_int_check_async_open( ld, sd ); } LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); if( rc != 0 ) return ld->ld_errno; oldctx = ld->ld_defconn->lconn_sasl_authctx; /* If we already have an authentication context, clear it out */ if( oldctx ) { if ( oldctx != ld->ld_defconn->lconn_sasl_sockctx ) { sasl_dispose( &oldctx ); } ld->ld_defconn->lconn_sasl_authctx = NULL; } { char *saslhost; int nocanon = (int)LDAP_BOOL_GET( &ld->ld_options, LDAP_BOOL_SASL_NOCANON ); /* If we don't need to canonicalize just use the host * from the LDAP URI. */ if ( nocanon ) saslhost = ld->ld_defconn->lconn_server->lud_host; else saslhost = ldap_host_connected_to( ld->ld_defconn->lconn_sb, "localhost" ); rc = ldap_int_sasl_open( ld, ld->ld_defconn, saslhost ); if ( !nocanon ) LDAP_FREE( saslhost ); } if ( rc != LDAP_SUCCESS ) return rc; ctx = ld->ld_defconn->lconn_sasl_authctx; #ifdef HAVE_TLS /* Check for TLS */ ssl = ldap_pvt_tls_sb_ctx( ld->ld_defconn->lconn_sb ); if ( ssl ) { struct berval authid = BER_BVNULL; ber_len_t fac; fac = ldap_pvt_tls_get_strength( ssl ); /* failure is OK, we just can't use SASL EXTERNAL */ (void) ldap_pvt_tls_get_my_dn( ssl, &authid, NULL, 0 ); (void) ldap_int_sasl_external( ld, ld->ld_defconn, authid.bv_val, fac ); LDAP_FREE( authid.bv_val ); } #endif #if !defined(_WIN32) /* Check for local */ if ( ldap_pvt_url_scheme2proto( ld->ld_defconn->lconn_server->lud_scheme ) == LDAP_PROTO_IPC ) { char authid[sizeof("gidNumber=4294967295+uidNumber=4294967295," "cn=peercred,cn=external,cn=auth")]; sprintf( authid, "gidNumber=%u+uidNumber=%u," "cn=peercred,cn=external,cn=auth", getegid(), geteuid() ); (void) ldap_int_sasl_external( ld, ld->ld_defconn, authid, LDAP_PVT_SASL_LOCAL_SSF ); } #endif /* (re)set security properties */ sasl_setprop( ctx, SASL_SEC_PROPS, &ld->ld_options.ldo_sasl_secprops ); mech = NULL; do { saslrc = sasl_client_start( ctx, mechs, #if SASL_VERSION_MAJOR < 2 NULL, #endif &prompts, (SASL_CONST char **)&ccred.bv_val, &credlen, &mech ); if( pmech == NULL && mech != NULL ) { pmech = mech; *rmech = mech; if( flags != LDAP_SASL_QUIET ) { fprintf(stderr, "SASL/%s authentication started\n", pmech ); } } if( saslrc == SASL_INTERACT ) { int res; if( !interact ) break; res = (interact)( ld, flags, defaults, prompts ); if( res != LDAP_SUCCESS ) break; } } while ( saslrc == SASL_INTERACT ); rc = LDAP_SASL_BIND_IN_PROGRESS; } else { /* continuing an in-progress Bind */ struct berval *scred = NULL; ctx = ld->ld_defconn->lconn_sasl_authctx; rc = ldap_parse_sasl_bind_result( ld, result, &scred, 0 ); if ( rc != LDAP_SUCCESS ) { if ( scred ) ber_bvfree( scred ); goto done; } rc = ldap_result2error( ld, result, 0 ); if ( rc != LDAP_SUCCESS && rc != LDAP_SASL_BIND_IN_PROGRESS ) { if( scred ) { /* and server provided us with data? */ Debug( LDAP_DEBUG_TRACE, "ldap_int_sasl_bind: rc=%d len=%ld\n", rc, scred ? (long) scred->bv_len : -1L, 0 ); ber_bvfree( scred ); scred = NULL; } goto done; } mech = *rmech; if ( rc == LDAP_SUCCESS && mech == NULL ) { if ( scred ) ber_bvfree( scred ); goto success; } do { if( ! scred ) { /* no data! */ Debug( LDAP_DEBUG_TRACE, "ldap_int_sasl_bind: no data in step!\n", 0, 0, 0 ); } saslrc = sasl_client_step( ctx, (scred == NULL) ? NULL : scred->bv_val, (scred == NULL) ? 0 : scred->bv_len, &prompts, (SASL_CONST char **)&ccred.bv_val, &credlen ); Debug( LDAP_DEBUG_TRACE, "sasl_client_step: %d\n", saslrc, 0, 0 ); if( saslrc == SASL_INTERACT ) { int res; if( !interact ) break; res = (interact)( ld, flags, defaults, prompts ); if( res != LDAP_SUCCESS ) break; } } while ( saslrc == SASL_INTERACT ); ber_bvfree( scred ); } if ( (saslrc != SASL_OK) && (saslrc != SASL_CONTINUE) ) { rc = ld->ld_errno = sasl_err2ldap( saslrc ); #if SASL_VERSION_MAJOR >= 2 if ( ld->ld_error ) { LDAP_FREE( ld->ld_error ); } ld->ld_error = LDAP_STRDUP( sasl_errdetail( ctx ) ); #endif goto done; } if ( saslrc == SASL_OK ) *rmech = NULL; ccred.bv_len = credlen; if ( rc == LDAP_SASL_BIND_IN_PROGRESS ) { rc = ldap_sasl_bind( ld, dn, mech, &ccred, sctrls, cctrls, msgid ); if ( ccred.bv_val != NULL ) { #if SASL_VERSION_MAJOR < 2 LDAP_FREE( ccred.bv_val ); #endif ccred.bv_val = NULL; } if ( rc == LDAP_SUCCESS ) rc = LDAP_SASL_BIND_IN_PROGRESS; goto done; } success: /* Conversation was completed successfully by now */ if( flags != LDAP_SASL_QUIET ) { char *data; saslrc = sasl_getprop( ctx, SASL_USERNAME, (SASL_CONST void **)(char *) &data ); if( saslrc == SASL_OK && data && *data ) { fprintf( stderr, "SASL username: %s\n", data ); } #if SASL_VERSION_MAJOR < 2 saslrc = sasl_getprop( ctx, SASL_REALM, (SASL_CONST void **) &data ); if( saslrc == SASL_OK && data && *data ) { fprintf( stderr, "SASL realm: %s\n", data ); } #endif } ssf = NULL; saslrc = sasl_getprop( ctx, SASL_SSF, (SASL_CONST void **)(char *) &ssf ); if( saslrc == SASL_OK ) { if( flags != LDAP_SASL_QUIET ) { fprintf( stderr, "SASL SSF: %lu\n", (unsigned long) *ssf ); } if( ssf && *ssf ) { if ( ld->ld_defconn->lconn_sasl_sockctx ) { sasl_conn_t *oldctx = ld->ld_defconn->lconn_sasl_sockctx; sasl_dispose( &oldctx ); ldap_pvt_sasl_remove( ld->ld_defconn->lconn_sb ); } ldap_pvt_sasl_install( ld->ld_defconn->lconn_sb, ctx ); ld->ld_defconn->lconn_sasl_sockctx = ctx; if( flags != LDAP_SASL_QUIET ) { fprintf( stderr, "SASL data security layer installed.\n" ); } } } ld->ld_defconn->lconn_sasl_authctx = ctx; done: return rc; } int ldap_int_sasl_external( LDAP *ld, LDAPConn *conn, const char * authid, ber_len_t ssf ) { int sc; sasl_conn_t *ctx; #if SASL_VERSION_MAJOR < 2 sasl_external_properties_t extprops; #else sasl_ssf_t sasl_ssf = ssf; #endif ctx = conn->lconn_sasl_authctx; if ( ctx == NULL ) { return LDAP_LOCAL_ERROR; } #if SASL_VERSION_MAJOR >= 2 sc = sasl_setprop( ctx, SASL_SSF_EXTERNAL, &sasl_ssf ); if ( sc == SASL_OK ) sc = sasl_setprop( ctx, SASL_AUTH_EXTERNAL, authid ); #else memset( &extprops, '\0', sizeof(extprops) ); extprops.ssf = ssf; extprops.auth_id = (char *) authid; sc = sasl_setprop( ctx, SASL_SSF_EXTERNAL, (void *) &extprops ); #endif if ( sc != SASL_OK ) { return LDAP_LOCAL_ERROR; } return LDAP_SUCCESS; } #define GOT_MINSSF 1 #define GOT_MAXSSF 2 #define GOT_MAXBUF 4 static struct { struct berval key; int sflag; int ival; int idef; } sprops[] = { { BER_BVC("none"), 0, 0, 0 }, { BER_BVC("nodict"), SASL_SEC_NODICTIONARY, 0, 0 }, { BER_BVC("noplain"), SASL_SEC_NOPLAINTEXT, 0, 0 }, { BER_BVC("noactive"), SASL_SEC_NOACTIVE, 0, 0 }, { BER_BVC("passcred"), SASL_SEC_PASS_CREDENTIALS, 0, 0 }, { BER_BVC("forwardsec"), SASL_SEC_FORWARD_SECRECY, 0, 0 }, { BER_BVC("noanonymous"), SASL_SEC_NOANONYMOUS, 0, 0 }, { BER_BVC("minssf="), 0, GOT_MINSSF, 0 }, { BER_BVC("maxssf="), 0, GOT_MAXSSF, INT_MAX }, { BER_BVC("maxbufsize="), 0, GOT_MAXBUF, 65536 }, { BER_BVNULL, 0, 0, 0 } }; void ldap_pvt_sasl_secprops_unparse( sasl_security_properties_t *secprops, struct berval *out ) { int i, l = 0; int comma; char *ptr; if ( secprops == NULL || out == NULL ) { return; } comma = 0; for ( i=0; !BER_BVISNULL( &sprops[i].key ); i++ ) { if ( sprops[i].ival ) { int v = 0; switch( sprops[i].ival ) { case GOT_MINSSF: v = secprops->min_ssf; break; case GOT_MAXSSF: v = secprops->max_ssf; break; case GOT_MAXBUF: v = secprops->maxbufsize; break; } /* It is the default, ignore it */ if ( v == sprops[i].idef ) continue; l += sprops[i].key.bv_len + 24; } else if ( sprops[i].sflag ) { if ( sprops[i].sflag & secprops->security_flags ) { l += sprops[i].key.bv_len; } } else if ( secprops->security_flags == 0 ) { l += sprops[i].key.bv_len; } if ( comma ) l++; comma = 1; } l++; out->bv_val = LDAP_MALLOC( l ); if ( out->bv_val == NULL ) { out->bv_len = 0; return; } ptr = out->bv_val; comma = 0; for ( i=0; !BER_BVISNULL( &sprops[i].key ); i++ ) { if ( sprops[i].ival ) { int v = 0; switch( sprops[i].ival ) { case GOT_MINSSF: v = secprops->min_ssf; break; case GOT_MAXSSF: v = secprops->max_ssf; break; case GOT_MAXBUF: v = secprops->maxbufsize; break; } /* It is the default, ignore it */ if ( v == sprops[i].idef ) continue; if ( comma ) *ptr++ = ','; ptr += sprintf(ptr, "%s%d", sprops[i].key.bv_val, v ); comma = 1; } else if ( sprops[i].sflag ) { if ( sprops[i].sflag & secprops->security_flags ) { if ( comma ) *ptr++ = ','; ptr += sprintf(ptr, "%s", sprops[i].key.bv_val ); comma = 1; } } else if ( secprops->security_flags == 0 ) { if ( comma ) *ptr++ = ','; ptr += sprintf(ptr, "%s", sprops[i].key.bv_val ); comma = 1; } } out->bv_len = ptr - out->bv_val; } int ldap_pvt_sasl_secprops( const char *in, sasl_security_properties_t *secprops ) { unsigned i, j, l; char **props; unsigned sflags = 0; int got_sflags = 0; sasl_ssf_t max_ssf = 0; int got_max_ssf = 0; sasl_ssf_t min_ssf = 0; int got_min_ssf = 0; unsigned maxbufsize = 0; int got_maxbufsize = 0; if( secprops == NULL ) { return LDAP_PARAM_ERROR; } props = ldap_str2charray( in, "," ); if( props == NULL ) { return LDAP_PARAM_ERROR; } for( i=0; props[i]; i++ ) { l = strlen( props[i] ); for ( j=0; !BER_BVISNULL( &sprops[j].key ); j++ ) { if ( l < sprops[j].key.bv_len ) continue; if ( strncasecmp( props[i], sprops[j].key.bv_val, sprops[j].key.bv_len )) continue; if ( sprops[j].ival ) { unsigned v; char *next = NULL; if ( !isdigit( (unsigned char)props[i][sprops[j].key.bv_len] )) continue; v = strtoul( &props[i][sprops[j].key.bv_len], &next, 10 ); if ( next == &props[i][sprops[j].key.bv_len] || next[0] != '\0' ) continue; switch( sprops[j].ival ) { case GOT_MINSSF: min_ssf = v; got_min_ssf++; break; case GOT_MAXSSF: max_ssf = v; got_max_ssf++; break; case GOT_MAXBUF: maxbufsize = v; got_maxbufsize++; break; } } else { if ( props[i][sprops[j].key.bv_len] ) continue; if ( sprops[j].sflag ) sflags |= sprops[j].sflag; else sflags = 0; got_sflags++; } break; } if ( BER_BVISNULL( &sprops[j].key )) { ldap_charray_free( props ); return LDAP_NOT_SUPPORTED; } } if(got_sflags) { secprops->security_flags = sflags; } if(got_min_ssf) { secprops->min_ssf = min_ssf; } if(got_max_ssf) { secprops->max_ssf = max_ssf; } if(got_maxbufsize) { secprops->maxbufsize = maxbufsize; } ldap_charray_free( props ); return LDAP_SUCCESS; } int ldap_int_sasl_config( struct ldapoptions *lo, int option, const char *arg ) { int rc; switch( option ) { case LDAP_OPT_X_SASL_SECPROPS: rc = ldap_pvt_sasl_secprops( arg, &lo->ldo_sasl_secprops ); if( rc == LDAP_SUCCESS ) return 0; } return -1; } int ldap_int_sasl_get_option( LDAP *ld, int option, void *arg ) { if ( option == LDAP_OPT_X_SASL_MECHLIST ) { if ( ldap_int_sasl_init() ) return -1; *(char ***)arg = (char **)sasl_global_listmech(); return 0; } if ( ld == NULL ) return -1; switch ( option ) { case LDAP_OPT_X_SASL_MECH: { *(char **)arg = ld->ld_options.ldo_def_sasl_mech ? LDAP_STRDUP( ld->ld_options.ldo_def_sasl_mech ) : NULL; } break; case LDAP_OPT_X_SASL_REALM: { *(char **)arg = ld->ld_options.ldo_def_sasl_realm ? LDAP_STRDUP( ld->ld_options.ldo_def_sasl_realm ) : NULL; } break; case LDAP_OPT_X_SASL_AUTHCID: { *(char **)arg = ld->ld_options.ldo_def_sasl_authcid ? LDAP_STRDUP( ld->ld_options.ldo_def_sasl_authcid ) : NULL; } break; case LDAP_OPT_X_SASL_AUTHZID: { *(char **)arg = ld->ld_options.ldo_def_sasl_authzid ? LDAP_STRDUP( ld->ld_options.ldo_def_sasl_authzid ) : NULL; } break; case LDAP_OPT_X_SASL_SSF: { int sc; sasl_ssf_t *ssf; sasl_conn_t *ctx; if( ld->ld_defconn == NULL ) { return -1; } ctx = ld->ld_defconn->lconn_sasl_sockctx; if ( ctx == NULL ) { return -1; } sc = sasl_getprop( ctx, SASL_SSF, (SASL_CONST void **)(char *) &ssf ); if ( sc != SASL_OK ) { return -1; } *(ber_len_t *)arg = *ssf; } break; case LDAP_OPT_X_SASL_SSF_EXTERNAL: /* this option is write only */ return -1; case LDAP_OPT_X_SASL_SSF_MIN: *(ber_len_t *)arg = ld->ld_options.ldo_sasl_secprops.min_ssf; break; case LDAP_OPT_X_SASL_SSF_MAX: *(ber_len_t *)arg = ld->ld_options.ldo_sasl_secprops.max_ssf; break; case LDAP_OPT_X_SASL_MAXBUFSIZE: *(ber_len_t *)arg = ld->ld_options.ldo_sasl_secprops.maxbufsize; break; case LDAP_OPT_X_SASL_NOCANON: *(int *)arg = (int) LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_SASL_NOCANON ); break; case LDAP_OPT_X_SASL_USERNAME: { int sc; char *username; sasl_conn_t *ctx; if( ld->ld_defconn == NULL ) { return -1; } ctx = ld->ld_defconn->lconn_sasl_authctx; if ( ctx == NULL ) { return -1; } sc = sasl_getprop( ctx, SASL_USERNAME, (SASL_CONST void **)(char **) &username ); if ( sc != SASL_OK ) { return -1; } *(char **)arg = username ? LDAP_STRDUP( username ) : NULL; } break; case LDAP_OPT_X_SASL_SECPROPS: /* this option is write only */ return -1; #ifdef SASL_GSS_CREDS case LDAP_OPT_X_SASL_GSS_CREDS: { sasl_conn_t *ctx; int sc; if ( ld->ld_defconn == NULL ) return -1; ctx = ld->ld_defconn->lconn_sasl_authctx; if ( ctx == NULL ) return -1; sc = sasl_getprop( ctx, SASL_GSS_CREDS, arg ); if ( sc != SASL_OK ) return -1; } break; #endif default: return -1; } return 0; } int ldap_int_sasl_set_option( LDAP *ld, int option, void *arg ) { if ( ld == NULL ) return -1; if ( arg == NULL && option != LDAP_OPT_X_SASL_NOCANON ) return -1; switch ( option ) { case LDAP_OPT_X_SASL_SSF: case LDAP_OPT_X_SASL_USERNAME: /* This option is read-only */ return -1; case LDAP_OPT_X_SASL_SSF_EXTERNAL: { int sc; #if SASL_VERSION_MAJOR < 2 sasl_external_properties_t extprops; #else sasl_ssf_t sasl_ssf; #endif sasl_conn_t *ctx; if( ld->ld_defconn == NULL ) { return -1; } ctx = ld->ld_defconn->lconn_sasl_authctx; if ( ctx == NULL ) { return -1; } #if SASL_VERSION_MAJOR >= 2 sasl_ssf = * (ber_len_t *)arg; sc = sasl_setprop( ctx, SASL_SSF_EXTERNAL, &sasl_ssf); #else memset(&extprops, 0L, sizeof(extprops)); extprops.ssf = * (ber_len_t *) arg; sc = sasl_setprop( ctx, SASL_SSF_EXTERNAL, (void *) &extprops ); #endif if ( sc != SASL_OK ) { return -1; } } break; case LDAP_OPT_X_SASL_SSF_MIN: ld->ld_options.ldo_sasl_secprops.min_ssf = *(ber_len_t *)arg; break; case LDAP_OPT_X_SASL_SSF_MAX: ld->ld_options.ldo_sasl_secprops.max_ssf = *(ber_len_t *)arg; break; case LDAP_OPT_X_SASL_MAXBUFSIZE: ld->ld_options.ldo_sasl_secprops.maxbufsize = *(ber_len_t *)arg; break; case LDAP_OPT_X_SASL_NOCANON: if ( arg == LDAP_OPT_OFF ) { LDAP_BOOL_CLR(&ld->ld_options, LDAP_BOOL_SASL_NOCANON ); } else { LDAP_BOOL_SET(&ld->ld_options, LDAP_BOOL_SASL_NOCANON ); } break; case LDAP_OPT_X_SASL_SECPROPS: { int sc; sc = ldap_pvt_sasl_secprops( (char *) arg, &ld->ld_options.ldo_sasl_secprops ); return sc == LDAP_SUCCESS ? 0 : -1; } #ifdef SASL_GSS_CREDS case LDAP_OPT_X_SASL_GSS_CREDS: { sasl_conn_t *ctx; int sc; if ( ld->ld_defconn == NULL ) return -1; ctx = ld->ld_defconn->lconn_sasl_authctx; if ( ctx == NULL ) return -1; sc = sasl_setprop( ctx, SASL_GSS_CREDS, arg ); if ( sc != SASL_OK ) return -1; } break; #endif default: return -1; } return 0; } #ifdef LDAP_R_COMPILE #define LDAP_DEBUG_R_SASL void *ldap_pvt_sasl_mutex_new(void) { ldap_pvt_thread_mutex_t *mutex; mutex = (ldap_pvt_thread_mutex_t *) LDAP_CALLOC( 1, sizeof(ldap_pvt_thread_mutex_t) ); if ( ldap_pvt_thread_mutex_init( mutex ) == 0 ) { return mutex; } LDAP_FREE( mutex ); #ifndef LDAP_DEBUG_R_SASL assert( 0 ); #endif /* !LDAP_DEBUG_R_SASL */ return NULL; } int ldap_pvt_sasl_mutex_lock(void *mutex) { #ifdef LDAP_DEBUG_R_SASL if ( mutex == NULL ) { return SASL_OK; } #else /* !LDAP_DEBUG_R_SASL */ assert( mutex != NULL ); #endif /* !LDAP_DEBUG_R_SASL */ return ldap_pvt_thread_mutex_lock( (ldap_pvt_thread_mutex_t *)mutex ) ? SASL_FAIL : SASL_OK; } int ldap_pvt_sasl_mutex_unlock(void *mutex) { #ifdef LDAP_DEBUG_R_SASL if ( mutex == NULL ) { return SASL_OK; } #else /* !LDAP_DEBUG_R_SASL */ assert( mutex != NULL ); #endif /* !LDAP_DEBUG_R_SASL */ return ldap_pvt_thread_mutex_unlock( (ldap_pvt_thread_mutex_t *)mutex ) ? SASL_FAIL : SASL_OK; } void ldap_pvt_sasl_mutex_dispose(void *mutex) { #ifdef LDAP_DEBUG_R_SASL if ( mutex == NULL ) { return; } #else /* !LDAP_DEBUG_R_SASL */ assert( mutex != NULL ); #endif /* !LDAP_DEBUG_R_SASL */ (void) ldap_pvt_thread_mutex_destroy( (ldap_pvt_thread_mutex_t *)mutex ); LDAP_FREE( mutex ); } #endif #else int ldap_int_sasl_init( void ) { return LDAP_SUCCESS; } int ldap_int_sasl_close( LDAP *ld, LDAPConn *lc ) { return LDAP_SUCCESS; } int ldap_int_sasl_bind( LDAP *ld, const char *dn, const char *mechs, LDAPControl **sctrls, LDAPControl **cctrls, unsigned flags, LDAP_SASL_INTERACT_PROC *interact, void *defaults, LDAPMessage *result, const char **rmech, int *msgid ) { return LDAP_NOT_SUPPORTED; } int ldap_int_sasl_external( LDAP *ld, LDAPConn *conn, const char * authid, ber_len_t ssf ) { return LDAP_SUCCESS; } #endif /* HAVE_CYRUS_SASL */ openldap-2.4.42+dfsg/libraries/libldap/ppolicy.c0000644000175000017500000001461512563404150020245 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 2004-2015 The OpenLDAP Foundation. * Portions Copyright 2004 Hewlett-Packard Company. * Portions Copyright 2004 Howard Chu, Symas Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* ACKNOWLEDGEMENTS: * This work was developed by Howard Chu for inclusion in * OpenLDAP Software, based on prior work by Neil Dunbar (HP). * This work was sponsored by the Hewlett-Packard Company. */ #include "portable.h" #include #include #include #include #include "ldap-int.h" #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST /* IMPLICIT TAGS, all context-specific */ #define PPOLICY_WARNING 0xa0L /* constructed + 0 */ #define PPOLICY_ERROR 0x81L /* primitive + 1 */ #define PPOLICY_EXPIRE 0x80L /* primitive + 0 */ #define PPOLICY_GRACE 0x81L /* primitive + 1 */ /*--- ldap_create_passwordpolicy_control Create and encode the Password Policy Request ld (IN) An LDAP session handle, as obtained from a call to ldap_init(). ctrlp (OUT) A result parameter that will be assigned the address of an LDAPControl structure that contains the passwordPolicyRequest control created by this function. The memory occupied by the LDAPControl structure SHOULD be freed when it is no longer in use by calling ldap_control_free(). There is no control value for a password policy request ---*/ int ldap_create_passwordpolicy_control( LDAP *ld, LDAPControl **ctrlp ) { assert( ld != NULL ); assert( LDAP_VALID( ld ) ); assert( ctrlp != NULL ); ld->ld_errno = ldap_control_create( LDAP_CONTROL_PASSWORDPOLICYREQUEST, 0, NULL, 0, ctrlp ); return ld->ld_errno; } /*--- ldap_parse_passwordpolicy_control Decode the passwordPolicyResponse control and return information. ld (IN) An LDAP session handle. ctrl (IN) The address of an LDAPControl structure, either obtained by running thorugh the list of response controls or by a call to ldap_control_find(). exptimep (OUT) This result parameter is filled in with the number of seconds before the password will expire, if expiration is imminent (imminency defined by the password policy). If expiration is not imminent, the value is set to -1. gracep (OUT) This result parameter is filled in with the number of grace logins after the password has expired, before no further login attempts will be allowed. errorcodep (OUT) This result parameter is filled in with the error code of the password operation If no error was detected, this error is set to PP_noError. Ber encoding PasswordPolicyResponseValue ::= SEQUENCE { warning [0] CHOICE { timeBeforeExpiration [0] INTEGER (0 .. maxInt), graceLoginsRemaining [1] INTEGER (0 .. maxInt) } OPTIONAL error [1] ENUMERATED { passwordExpired (0), accountLocked (1), changeAfterReset (2), passwordModNotAllowed (3), mustSupplyOldPassword (4), invalidPasswordSyntax (5), passwordTooShort (6), passwordTooYoung (7), passwordInHistory (8) } OPTIONAL } ---*/ int ldap_parse_passwordpolicy_control( LDAP *ld, LDAPControl *ctrl, ber_int_t *expirep, ber_int_t *gracep, LDAPPasswordPolicyError *errorp ) { BerElement *ber; int exp = -1, grace = -1; ber_tag_t tag; ber_len_t berLen; char *last; int err = PP_noError; assert( ld != NULL ); assert( LDAP_VALID( ld ) ); assert( ctrl != NULL ); if ( !ctrl->ldctl_value.bv_val ) { ld->ld_errno = LDAP_DECODING_ERROR; return(ld->ld_errno); } /* Create a BerElement from the berval returned in the control. */ ber = ber_init(&ctrl->ldctl_value); if (ber == NULL) { ld->ld_errno = LDAP_NO_MEMORY; return(ld->ld_errno); } tag = ber_peek_tag( ber, &berLen ); if (tag != LBER_SEQUENCE) goto exit; for( tag = ber_first_element( ber, &berLen, &last ); tag != LBER_DEFAULT; tag = ber_next_element( ber, &berLen, last ) ) { switch (tag) { case PPOLICY_WARNING: ber_skip_tag(ber, &berLen ); tag = ber_peek_tag( ber, &berLen ); switch( tag ) { case PPOLICY_EXPIRE: if (ber_get_int( ber, &exp ) == LBER_DEFAULT) goto exit; break; case PPOLICY_GRACE: if (ber_get_int( ber, &grace ) == LBER_DEFAULT) goto exit; break; default: goto exit; } break; case PPOLICY_ERROR: if (ber_get_enum( ber, &err ) == LBER_DEFAULT) goto exit; break; default: goto exit; } } ber_free(ber, 1); /* Return data to the caller for items that were requested. */ if (expirep) *expirep = exp; if (gracep) *gracep = grace; if (errorp) *errorp = err; ld->ld_errno = LDAP_SUCCESS; return(ld->ld_errno); exit: ber_free(ber, 1); ld->ld_errno = LDAP_DECODING_ERROR; return(ld->ld_errno); } const char * ldap_passwordpolicy_err2txt( LDAPPasswordPolicyError err ) { switch(err) { case PP_passwordExpired: return "Password expired"; case PP_accountLocked: return "Account locked"; case PP_changeAfterReset: return "Password must be changed"; case PP_passwordModNotAllowed: return "Policy prevents password modification"; case PP_mustSupplyOldPassword: return "Policy requires old password in order to change password"; case PP_insufficientPasswordQuality: return "Password fails quality checks"; case PP_passwordTooShort: return "Password is too short for policy"; case PP_passwordTooYoung: return "Password has been changed too recently"; case PP_passwordInHistory: return "New password is in list of old passwords"; case PP_noError: return "No error"; default: return "Unknown error code"; } } #endif /* LDAP_CONTROL_PASSWORDPOLICYREQUEST */ openldap-2.4.42+dfsg/libraries/libldap/passwd.c0000644000175000017500000000650312563404150020064 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* ACKNOWLEDGEMENTS: * This program was orignally developed by Kurt D. Zeilenga for inclusion in * OpenLDAP Software. */ #include "portable.h" #include #include #include #include #include "ldap-int.h" /* * LDAP Password Modify (Extended) Operation (RFC 3062) */ int ldap_parse_passwd( LDAP *ld, LDAPMessage *res, struct berval *newpasswd ) { int rc; struct berval *retdata = NULL; assert( ld != NULL ); assert( LDAP_VALID( ld ) ); assert( res != NULL ); assert( newpasswd != NULL ); newpasswd->bv_val = NULL; newpasswd->bv_len = 0; rc = ldap_parse_extended_result( ld, res, NULL, &retdata, 0 ); if ( rc != LDAP_SUCCESS ) { return rc; } if ( retdata != NULL ) { ber_tag_t tag; BerElement *ber = ber_init( retdata ); if ( ber == NULL ) { rc = ld->ld_errno = LDAP_NO_MEMORY; goto done; } /* we should check the tag */ tag = ber_scanf( ber, "{o}", newpasswd ); ber_free( ber, 1 ); if ( tag == LBER_ERROR ) { rc = ld->ld_errno = LDAP_DECODING_ERROR; } } done:; ber_bvfree( retdata ); return rc; } int ldap_passwd( LDAP *ld, struct berval *user, struct berval *oldpw, struct berval *newpw, LDAPControl **sctrls, LDAPControl **cctrls, int *msgidp ) { int rc; struct berval bv = BER_BVNULL; BerElement *ber = NULL; assert( ld != NULL ); assert( LDAP_VALID( ld ) ); assert( msgidp != NULL ); if( user != NULL || oldpw != NULL || newpw != NULL ) { /* build change password control */ ber = ber_alloc_t( LBER_USE_DER ); if( ber == NULL ) { ld->ld_errno = LDAP_NO_MEMORY; return ld->ld_errno; } ber_printf( ber, "{" /*}*/ ); if( user != NULL ) { ber_printf( ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_ID, user ); } if( oldpw != NULL ) { ber_printf( ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_OLD, oldpw ); } if( newpw != NULL ) { ber_printf( ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_NEW, newpw ); } ber_printf( ber, /*{*/ "N}" ); rc = ber_flatten2( ber, &bv, 0 ); if( rc < 0 ) { ld->ld_errno = LDAP_ENCODING_ERROR; return ld->ld_errno; } } rc = ldap_extended_operation( ld, LDAP_EXOP_MODIFY_PASSWD, bv.bv_val ? &bv : NULL, sctrls, cctrls, msgidp ); ber_free( ber, 1 ); return rc; } int ldap_passwd_s( LDAP *ld, struct berval *user, struct berval *oldpw, struct berval *newpw, struct berval *newpasswd, LDAPControl **sctrls, LDAPControl **cctrls ) { int rc; int msgid; LDAPMessage *res; rc = ldap_passwd( ld, user, oldpw, newpw, sctrls, cctrls, &msgid ); if ( rc != LDAP_SUCCESS ) { return rc; } if ( ldap_result( ld, msgid, LDAP_MSG_ALL, (struct timeval *) NULL, &res ) == -1 || !res ) { return ld->ld_errno; } rc = ldap_parse_passwd( ld, res, newpasswd ); if( rc != LDAP_SUCCESS ) { ldap_msgfree( res ); return rc; } return( ldap_result2error( ld, res, 1 ) ); } openldap-2.4.42+dfsg/libraries/libldap/string.c0000644000175000017500000000525412563404150020073 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* * Locale-specific 1-byte character versions * See utf-8.c for UTF-8 versions */ #include "portable.h" #include #include #include #include #include "ldap-int.h" #if defined ( HAVE_STRSPN ) #define int_strspn strspn #else static int int_strspn( const char *str, const char *delim ) { int pos; const char *p=delim; for( pos=0; (*str) ; pos++,str++) { if (*str!=*p) { for( p=delim; (*p) ; p++ ) { if (*str==*p) { break; } } } if (*p=='\0') { return pos; } } return pos; } #endif #if defined( HAVE_STRPBRK ) #define int_strpbrk strpbrk #else static char *(int_strpbrk)( const char *str, const char *accept ) { const char *p; for( ; (*str) ; str++ ) { for( p=accept; (*p) ; p++) { if (*str==*p) { return str; } } } return NULL; } #endif char *(ldap_pvt_strtok)( char *str, const char *delim, char **pos ) { char *p; if (pos==NULL) { return NULL; } if (str==NULL) { if (*pos==NULL) { return NULL; } str=*pos; } /* skip any initial delimiters */ str += int_strspn( str, delim ); if (*str == '\0') { return NULL; } p = int_strpbrk( str, delim ); if (p==NULL) { *pos = NULL; } else { *p ='\0'; *pos = p+1; } return str; } char * ldap_pvt_str2upper( char *str ) { char *s; /* to upper */ if ( str ) { for ( s = str; *s; s++ ) { *s = TOUPPER( (unsigned char) *s ); } } return( str ); } struct berval * ldap_pvt_str2upperbv( char *str, struct berval *bv ) { char *s = NULL; assert( bv != NULL ); /* to upper */ if ( str ) { for ( s = str; *s; s++ ) { *s = TOUPPER( (unsigned char) *s ); } } bv->bv_val = str; bv->bv_len = (ber_len_t)(s - str); return( bv ); } char * ldap_pvt_str2lower( char *str ) { char *s; /* to lower */ if ( str ) { for ( s = str; *s; s++ ) { *s = TOLOWER( (unsigned char) *s ); } } return( str ); } struct berval * ldap_pvt_str2lowerbv( char *str, struct berval *bv ) { char *s = NULL; assert( bv != NULL ); /* to lower */ if ( str ) { for ( s = str; *s; s++ ) { *s = TOLOWER( (unsigned char) *s ); } } bv->bv_val = str; bv->bv_len = (ber_len_t)(s - str); return( bv ); } openldap-2.4.42+dfsg/libraries/libldap/os-local.c0000644000175000017500000002020112563404150020263 0ustar ryanryan/* os-local.c -- platform-specific domain socket code */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (c) 1995 Regents of the University of Michigan. * All rights reserved. */ /* Portions (C) Copyright PADL Software Pty Ltd. 1999 * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that this notice is preserved * and that due credit is given to PADL Software Pty Ltd. This software * is provided ``as is'' without express or implied warranty. */ #include "portable.h" #ifdef LDAP_PF_LOCAL #include #include #include #include #include #include #include #ifdef HAVE_SYS_STAT_H #include #endif #ifdef HAVE_SYS_UIO_H #include #endif #ifdef HAVE_IO_H #include #endif /* HAVE_IO_H */ #ifdef HAVE_FCNTL_H #include #endif #include "ldap-int.h" #include "ldap_defaults.h" #ifdef LDAP_DEBUG #define oslocal_debug(ld,fmt,arg1,arg2,arg3) \ do { \ ldap_log_printf(ld, LDAP_DEBUG_TRACE, fmt, arg1, arg2, arg3); \ } while(0) #else #define oslocal_debug(ld,fmt,arg1,arg2,arg3) ((void)0) #endif /* LDAP_DEBUG */ static void ldap_pvt_set_errno(int err) { errno = err; } static int ldap_pvt_ndelay_on(LDAP *ld, int fd) { oslocal_debug(ld, "ldap_ndelay_on: %d\n",fd,0,0); return ber_pvt_socket_set_nonblock( fd, 1 ); } static int ldap_pvt_ndelay_off(LDAP *ld, int fd) { oslocal_debug(ld, "ldap_ndelay_off: %d\n",fd,0,0); return ber_pvt_socket_set_nonblock( fd, 0 ); } static ber_socket_t ldap_pvt_socket(LDAP *ld) { ber_socket_t s = socket(PF_LOCAL, SOCK_STREAM, 0); oslocal_debug(ld, "ldap_new_socket: %d\n",s,0,0); #ifdef FD_CLOEXEC fcntl(s, F_SETFD, FD_CLOEXEC); #endif return ( s ); } static int ldap_pvt_close_socket(LDAP *ld, int s) { oslocal_debug(ld, "ldap_close_socket: %d\n",s,0,0); return tcp_close(s); } #undef TRACE #define TRACE do { \ char ebuf[128]; \ oslocal_debug(ld, \ "ldap_is_socket_ready: errror on socket %d: errno: %d (%s)\n", \ s, \ errno, \ AC_STRERROR_R(errno, ebuf, sizeof ebuf)); \ } while( 0 ) /* * check the socket for errors after select returned. */ static int ldap_pvt_is_socket_ready(LDAP *ld, int s) { oslocal_debug(ld, "ldap_is_sock_ready: %d\n",s,0,0); #if defined( notyet ) /* && defined( SO_ERROR ) */ { int so_errno; ber_socklen_t dummy = sizeof(so_errno); if ( getsockopt( s, SOL_SOCKET, SO_ERROR, &so_errno, &dummy ) == AC_SOCKET_ERROR ) { return -1; } if ( so_errno ) { ldap_pvt_set_errno(so_errno); TRACE; return -1; } return 0; } #else { /* error slippery */ struct sockaddr_un sa; char ch; ber_socklen_t dummy = sizeof(sa); if ( getpeername( s, (struct sockaddr *) &sa, &dummy ) == AC_SOCKET_ERROR ) { /* XXX: needs to be replace with ber_stream_read() */ (void)read(s, &ch, 1); TRACE; return -1; } return 0; } #endif return -1; } #undef TRACE #ifdef LDAP_PF_LOCAL_SENDMSG static const char abandonPDU[] = {LDAP_TAG_MESSAGE, 6, LDAP_TAG_MSGID, 1, 0, LDAP_REQ_ABANDON, 1, 0}; #endif static int ldap_pvt_connect(LDAP *ld, ber_socket_t s, struct sockaddr_un *sa, int async) { int rc; struct timeval tv, *opt_tv = NULL; if ( ld->ld_options.ldo_tm_net.tv_sec >= 0 ) { tv = ld->ld_options.ldo_tm_net; opt_tv = &tv; } oslocal_debug(ld, "ldap_connect_timeout: fd: %d tm: %ld async: %d\n", s, opt_tv ? tv.tv_sec : -1L, async); if ( ldap_pvt_ndelay_on(ld, s) == -1 ) return -1; if ( connect(s, (struct sockaddr *) sa, sizeof(struct sockaddr_un)) != AC_SOCKET_ERROR ) { if ( ldap_pvt_ndelay_off(ld, s) == -1 ) return -1; #ifdef LDAP_PF_LOCAL_SENDMSG /* Send a dummy message with access rights. Remote side will * obtain our uid/gid by fstat'ing this descriptor. The * descriptor permissions must match exactly, and we also * send the socket name, which must also match. */ sendcred: { int fds[2]; ber_socklen_t salen = sizeof(*sa); if (pipe(fds) == 0) { /* Abandon, noop, has no reply */ struct iovec iov; struct msghdr msg = {0}; # ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL # ifndef CMSG_SPACE # define CMSG_SPACE(len) (_CMSG_ALIGN( sizeof(struct cmsghdr)) + _CMSG_ALIGN(len) ) # endif # ifndef CMSG_LEN # define CMSG_LEN(len) (_CMSG_ALIGN( sizeof(struct cmsghdr)) + (len) ) # endif union { struct cmsghdr cm; unsigned char control[CMSG_SPACE(sizeof(int))]; } control_un; struct cmsghdr *cmsg; # endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */ msg.msg_name = NULL; msg.msg_namelen = 0; iov.iov_base = (char *) abandonPDU; iov.iov_len = sizeof abandonPDU; msg.msg_iov = &iov; msg.msg_iovlen = 1; # ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL msg.msg_control = control_un.control; msg.msg_controllen = sizeof( control_un.control ); msg.msg_flags = 0; cmsg = CMSG_FIRSTHDR( &msg ); cmsg->cmsg_len = CMSG_LEN( sizeof(int) ); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; *((int *)CMSG_DATA(cmsg)) = fds[0]; # else msg.msg_accrights = (char *)fds; msg.msg_accrightslen = sizeof(int); # endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */ getpeername( s, (struct sockaddr *) sa, &salen ); fchmod( fds[0], S_ISUID|S_IRWXU ); write( fds[1], sa, salen ); sendmsg( s, &msg, 0 ); close(fds[0]); close(fds[1]); } } #endif return 0; } if ( errno != EINPROGRESS && errno != EWOULDBLOCK ) return -1; #ifdef notyet if ( async ) return -2; #endif #ifdef HAVE_POLL { struct pollfd fd; int timeout = INFTIM; if( opt_tv != NULL ) timeout = TV2MILLISEC( &tv ); fd.fd = s; fd.events = POLL_WRITE; do { fd.revents = 0; rc = poll( &fd, 1, timeout ); } while( rc == AC_SOCKET_ERROR && errno == EINTR && LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_RESTART )); if( rc == AC_SOCKET_ERROR ) return rc; if( fd.revents & POLL_WRITE ) { if ( ldap_pvt_is_socket_ready(ld, s) == -1 ) return -1; if ( ldap_pvt_ndelay_off(ld, s) == -1 ) return -1; #ifdef LDAP_PF_LOCAL_SENDMSG goto sendcred; #else return ( 0 ); #endif } } #else { fd_set wfds, *z=NULL; #ifdef FD_SETSIZE if ( s >= FD_SETSIZE ) { rc = AC_SOCKET_ERROR; tcp_close( s ); ldap_pvt_set_errno( EMFILE ); return rc; } #endif do { FD_ZERO(&wfds); FD_SET(s, &wfds ); rc = select( ldap_int_tblsize, z, &wfds, z, opt_tv ? &tv : NULL ); } while( rc == AC_SOCKET_ERROR && errno == EINTR && LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_RESTART )); if( rc == AC_SOCKET_ERROR ) return rc; if ( FD_ISSET(s, &wfds) ) { if ( ldap_pvt_is_socket_ready(ld, s) == -1 ) return -1; if ( ldap_pvt_ndelay_off(ld, s) == -1 ) return -1; #ifdef LDAP_PF_LOCAL_SENDMSG goto sendcred; #else return ( 0 ); #endif } } #endif oslocal_debug(ld, "ldap_connect_timeout: timed out\n",0,0,0); ldap_pvt_set_errno( ETIMEDOUT ); return ( -1 ); } int ldap_connect_to_path(LDAP *ld, Sockbuf *sb, LDAPURLDesc *srv, int async) { struct sockaddr_un server; ber_socket_t s; int rc; const char *path = srv->lud_host; oslocal_debug(ld, "ldap_connect_to_path\n",0,0,0); if ( path == NULL || path[0] == '\0' ) { path = LDAPI_SOCK; } else { if ( strlen(path) > (sizeof( server.sun_path ) - 1) ) { ldap_pvt_set_errno( ENAMETOOLONG ); return -1; } } s = ldap_pvt_socket( ld ); if ( s == AC_SOCKET_INVALID ) { return -1; } oslocal_debug(ld, "ldap_connect_to_path: Trying %s\n", path, 0, 0); memset( &server, '\0', sizeof(server) ); server.sun_family = AF_LOCAL; strcpy( server.sun_path, path ); rc = ldap_pvt_connect(ld, s, &server, async); if (rc == 0) { rc = ldap_int_connect_cbs( ld, sb, &s, srv, (struct sockaddr *)&server ); } if ( rc ) { ldap_pvt_close_socket(ld, s); } return rc; } #else static int dummy; #endif /* LDAP_PF_LOCAL */ openldap-2.4.42+dfsg/libraries/libldap/ldap-int.h0000644000175000017500000005542512563404150020307 0ustar ryanryan/* ldap-int.h - defines & prototypes internal to the LDAP library */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (c) 1995 Regents of the University of Michigan. * All rights reserved. */ #ifndef _LDAP_INT_H #define _LDAP_INT_H 1 #ifdef LDAP_R_COMPILE #define LDAP_THREAD_SAFE 1 #endif #include "../liblber/lber-int.h" #include "lutil.h" #ifdef LDAP_R_COMPILE #include #endif #ifdef HAVE_CYRUS_SASL /* the need for this should be removed */ #ifdef HAVE_SASL_SASL_H #include #else #include #endif #define SASL_MAX_BUFF_SIZE (0xffffff) #define SASL_MIN_BUFF_SIZE 4096 #endif /* for struct timeval */ #include #ifdef _WIN32 #include #endif #undef TV2MILLISEC #define TV2MILLISEC(tv) (((tv)->tv_sec * 1000) + ((tv)->tv_usec/1000)) /* * Support needed if the library is running in the kernel */ #if LDAP_INT_IN_KERNEL /* * Platform specific function to return a pointer to the * process-specific global options. * * This function should perform the following functions: * Allocate and initialize a global options struct on a per process basis * Use callers process identifier to return its global options struct * Note: Deallocate structure when the process exits */ # define LDAP_INT_GLOBAL_OPT() ldap_int_global_opt() struct ldapoptions *ldap_int_global_opt(void); #else # define LDAP_INT_GLOBAL_OPT() (&ldap_int_global_options) #endif #define ldap_debug ((LDAP_INT_GLOBAL_OPT())->ldo_debug) #include "ldap_log.h" #undef Debug #ifdef LDAP_DEBUG #define DebugTest( level ) \ ( ldap_debug & level ) #define Debug( level, fmt, arg1, arg2, arg3 ) \ do { if ( ldap_debug & level ) \ ldap_log_printf( NULL, (level), (fmt), (arg1), (arg2), (arg3) ); \ } while ( 0 ) #define LDAP_Debug( subsystem, level, fmt, arg1, arg2, arg3 )\ ldap_log_printf( NULL, (level), (fmt), (arg1), (arg2), (arg3) ) #else #define DebugTest( level ) (0 == 1) #define Debug( level, fmt, arg1, arg2, arg3 ) ((void)0) #define LDAP_Debug( subsystem, level, fmt, arg1, arg2, arg3 ) ((void)0) #endif /* LDAP_DEBUG */ #define LDAP_DEPRECATED 1 #include "ldap.h" #include "ldap_pvt.h" LDAP_BEGIN_DECL #define LDAP_URL_PREFIX "ldap://" #define LDAP_URL_PREFIX_LEN STRLENOF(LDAP_URL_PREFIX) #define LDAPS_URL_PREFIX "ldaps://" #define LDAPS_URL_PREFIX_LEN STRLENOF(LDAPS_URL_PREFIX) #define LDAPI_URL_PREFIX "ldapi://" #define LDAPI_URL_PREFIX_LEN STRLENOF(LDAPI_URL_PREFIX) #ifdef LDAP_CONNECTIONLESS #define LDAPC_URL_PREFIX "cldap://" #define LDAPC_URL_PREFIX_LEN STRLENOF(LDAPC_URL_PREFIX) #endif #define LDAP_URL_URLCOLON "URL:" #define LDAP_URL_URLCOLON_LEN STRLENOF(LDAP_URL_URLCOLON) #define LDAP_REF_STR "Referral:\n" #define LDAP_REF_STR_LEN STRLENOF(LDAP_REF_STR) #define LDAP_LDAP_REF_STR LDAP_URL_PREFIX #define LDAP_LDAP_REF_STR_LEN LDAP_URL_PREFIX_LEN #define LDAP_DEFAULT_REFHOPLIMIT 5 #define LDAP_BOOL_REFERRALS 0 #define LDAP_BOOL_RESTART 1 #define LDAP_BOOL_TLS 3 #define LDAP_BOOL_CONNECT_ASYNC 4 #define LDAP_BOOL_SASL_NOCANON 5 #define LDAP_BOOLEANS unsigned long #define LDAP_BOOL(n) ((LDAP_BOOLEANS)1 << (n)) #define LDAP_BOOL_GET(lo, bool) \ ((lo)->ldo_booleans & LDAP_BOOL(bool) ? -1 : 0) #define LDAP_BOOL_SET(lo, bool) ((lo)->ldo_booleans |= LDAP_BOOL(bool)) #define LDAP_BOOL_CLR(lo, bool) ((lo)->ldo_booleans &= ~LDAP_BOOL(bool)) #define LDAP_BOOL_ZERO(lo) ((lo)->ldo_booleans = 0) /* * This structure represents both ldap messages and ldap responses. * These are really the same, except in the case of search responses, * where a response has multiple messages. */ struct ldapmsg { ber_int_t lm_msgid; /* the message id */ ber_tag_t lm_msgtype; /* the message type */ BerElement *lm_ber; /* the ber encoded message contents */ struct ldapmsg *lm_chain; /* for search - next msg in the resp */ struct ldapmsg *lm_chain_tail; struct ldapmsg *lm_next; /* next response */ time_t lm_time; /* used to maintain cache */ }; #ifdef HAVE_TLS struct ldaptls { char *lt_certfile; char *lt_keyfile; char *lt_dhfile; char *lt_cacertfile; char *lt_cacertdir; char *lt_ciphersuite; char *lt_crlfile; char *lt_randfile; /* OpenSSL only */ int lt_protocol_min; }; #endif typedef struct ldaplist { struct ldaplist *ll_next; void *ll_data; } ldaplist; /* * structure representing get/set'able options * which have global defaults. * Protect access to this struct with ldo_mutex * ldap_log.h:ldapoptions_prefix must match the head of this struct. */ struct ldapoptions { short ldo_valid; #define LDAP_UNINITIALIZED 0x0 #define LDAP_INITIALIZED 0x1 #define LDAP_VALID_SESSION 0x2 #define LDAP_TRASHED_SESSION 0xFF int ldo_debug; ber_int_t ldo_version; ber_int_t ldo_deref; ber_int_t ldo_timelimit; ber_int_t ldo_sizelimit; /* per API call timeout */ struct timeval ldo_tm_api; struct timeval ldo_tm_net; LDAPURLDesc *ldo_defludp; int ldo_defport; char* ldo_defbase; char* ldo_defbinddn; /* bind dn */ /* * Per connection tcp-keepalive settings (Linux only, * ignored where unsupported) */ ber_int_t ldo_keepalive_idle; ber_int_t ldo_keepalive_probes; ber_int_t ldo_keepalive_interval; int ldo_refhoplimit; /* limit on referral nesting */ /* LDAPv3 server and client controls */ LDAPControl **ldo_sctrls; LDAPControl **ldo_cctrls; /* LDAP rebind callback function */ LDAP_REBIND_PROC *ldo_rebind_proc; void *ldo_rebind_params; LDAP_NEXTREF_PROC *ldo_nextref_proc; void *ldo_nextref_params; LDAP_URLLIST_PROC *ldo_urllist_proc; void *ldo_urllist_params; /* LDAP connection callback stack */ ldaplist *ldo_conn_cbs; LDAP_BOOLEANS ldo_booleans; /* boolean options */ #define LDAP_LDO_NULLARG ,0,0,0,0 ,{0},{0} ,0,0,0,0, 0,0,0,0, 0,0, 0,0,0,0,0,0, 0, 0 #ifdef LDAP_CONNECTIONLESS #define LDAP_IS_UDP(ld) ((ld)->ld_options.ldo_is_udp) void* ldo_peer; /* struct sockaddr* */ char* ldo_cldapdn; int ldo_is_udp; #define LDAP_LDO_CONNECTIONLESS_NULLARG ,0,0,0 #else #define LDAP_LDO_CONNECTIONLESS_NULLARG #endif #ifdef HAVE_TLS /* tls context */ void *ldo_tls_ctx; LDAP_TLS_CONNECT_CB *ldo_tls_connect_cb; void* ldo_tls_connect_arg; struct ldaptls ldo_tls_info; #define ldo_tls_certfile ldo_tls_info.lt_certfile #define ldo_tls_keyfile ldo_tls_info.lt_keyfile #define ldo_tls_dhfile ldo_tls_info.lt_dhfile #define ldo_tls_cacertfile ldo_tls_info.lt_cacertfile #define ldo_tls_cacertdir ldo_tls_info.lt_cacertdir #define ldo_tls_ciphersuite ldo_tls_info.lt_ciphersuite #define ldo_tls_protocol_min ldo_tls_info.lt_protocol_min #define ldo_tls_crlfile ldo_tls_info.lt_crlfile #define ldo_tls_randfile ldo_tls_info.lt_randfile int ldo_tls_mode; int ldo_tls_require_cert; int ldo_tls_impl; int ldo_tls_crlcheck; #define LDAP_LDO_TLS_NULLARG ,0,0,0,{0,0,0,0,0,0,0,0,0},0,0,0,0 #else #define LDAP_LDO_TLS_NULLARG #endif #ifdef HAVE_CYRUS_SASL char* ldo_def_sasl_mech; /* SASL Mechanism(s) */ char* ldo_def_sasl_realm; /* SASL realm */ char* ldo_def_sasl_authcid; /* SASL authentication identity */ char* ldo_def_sasl_authzid; /* SASL authorization identity */ /* SASL Security Properties */ struct sasl_security_properties ldo_sasl_secprops; #define LDAP_LDO_SASL_NULLARG ,0,0,0,0,{0} #else #define LDAP_LDO_SASL_NULLARG #endif #ifdef HAVE_GSSAPI unsigned ldo_gssapi_flags; #define LDAP_GSSAPI_OPT_DO_NOT_FREE_GSS_CONTEXT 0x0001 #define LDAP_GSSAPI_OPT_ALLOW_REMOTE_PRINCIPAL 0x0002 unsigned ldo_gssapi_options; #define LDAP_LDO_GSSAPI_NULLARG ,0,0 #else #define LDAP_LDO_GSSAPI_NULLARG #endif #ifdef LDAP_R_COMPILE ldap_pvt_thread_mutex_t ldo_mutex; #define LDAP_LDO_MUTEX_NULLARG , LDAP_PVT_MUTEX_NULL #else #define LDAP_LDO_MUTEX_NULLARG #endif }; /* * structure for representing an LDAP server connection */ typedef struct ldap_conn { Sockbuf *lconn_sb; #ifdef HAVE_CYRUS_SASL void *lconn_sasl_authctx; /* context for bind */ void *lconn_sasl_sockctx; /* for security layer */ #endif #ifdef HAVE_GSSAPI void *lconn_gss_ctx; /* gss_ctx_id_t */ #endif int lconn_refcnt; time_t lconn_created; /* time */ time_t lconn_lastused; /* time */ int lconn_rebind_inprogress; /* set if rebind in progress */ char ***lconn_rebind_queue; /* used if rebind in progress */ int lconn_status; #define LDAP_CONNST_NEEDSOCKET 1 #define LDAP_CONNST_CONNECTING 2 #define LDAP_CONNST_CONNECTED 3 LDAPURLDesc *lconn_server; BerElement *lconn_ber; /* ber receiving on this conn. */ struct ldap_conn *lconn_next; } LDAPConn; /* * structure used to track outstanding requests */ typedef struct ldapreq { ber_int_t lr_msgid; /* the message id */ int lr_status; /* status of request */ #define LDAP_REQST_COMPLETED 0 #define LDAP_REQST_INPROGRESS 1 #define LDAP_REQST_CHASINGREFS 2 #define LDAP_REQST_NOTCONNECTED 3 #define LDAP_REQST_WRITING 4 int lr_refcnt; /* count of references */ int lr_outrefcnt; /* count of outstanding referrals */ int lr_abandoned; /* the request has been abandoned */ ber_int_t lr_origid; /* original request's message id */ int lr_parentcnt; /* count of parent requests */ ber_tag_t lr_res_msgtype; /* result message type */ ber_int_t lr_res_errno; /* result LDAP errno */ char *lr_res_error; /* result error string */ char *lr_res_matched;/* result matched DN string */ BerElement *lr_ber; /* ber encoded request contents */ LDAPConn *lr_conn; /* connection used to send request */ struct berval lr_dn; /* DN of request, in lr_ber */ struct ldapreq *lr_parent; /* request that spawned this referral */ struct ldapreq *lr_child; /* first child request */ struct ldapreq *lr_refnext; /* next referral spawned */ struct ldapreq *lr_prev; /* previous request */ struct ldapreq *lr_next; /* next request */ } LDAPRequest; /* * structure for client cache */ #define LDAP_CACHE_BUCKETS 31 /* cache hash table size */ typedef struct ldapcache { LDAPMessage *lc_buckets[LDAP_CACHE_BUCKETS];/* hash table */ LDAPMessage *lc_requests; /* unfulfilled reqs */ long lc_timeout; /* request timeout */ ber_len_t lc_maxmem; /* memory to use */ ber_len_t lc_memused; /* memory in use */ int lc_enabled; /* enabled? */ unsigned long lc_options; /* options */ #define LDAP_CACHE_OPT_CACHENOERRS 0x00000001 #define LDAP_CACHE_OPT_CACHEALLERRS 0x00000002 } LDAPCache; /* * structure containing referral request info for rebind procedure */ typedef struct ldapreqinfo { ber_len_t ri_msgid; int ri_request; char *ri_url; } LDAPreqinfo; /* * structure representing an ldap connection */ struct ldap_common { Sockbuf *ldc_sb; /* socket descriptor & buffer */ #define ld_sb ldc->ldc_sb unsigned short ldc_lberoptions; #define ld_lberoptions ldc->ldc_lberoptions /* protected by msgid_mutex */ ber_len_t ldc_msgid; #define ld_msgid ldc->ldc_msgid /* do not mess with these */ /* protected by req_mutex */ LDAPRequest *ldc_requests; /* list of outstanding requests */ /* protected by res_mutex */ LDAPMessage *ldc_responses; /* list of outstanding responses */ #define ld_requests ldc->ldc_requests #define ld_responses ldc->ldc_responses /* protected by abandon_mutex */ ber_len_t ldc_nabandoned; ber_int_t *ldc_abandoned; /* array of abandoned requests */ #define ld_nabandoned ldc->ldc_nabandoned #define ld_abandoned ldc->ldc_abandoned /* unused by libldap */ LDAPCache *ldc_cache; /* non-null if cache is initialized */ #define ld_cache ldc->ldc_cache /* do not mess with the rest though */ /* protected by conn_mutex */ LDAPConn *ldc_defconn; /* default connection */ #define ld_defconn ldc->ldc_defconn LDAPConn *ldc_conns; /* list of server connections */ #define ld_conns ldc->ldc_conns void *ldc_selectinfo;/* platform specifics for select */ #define ld_selectinfo ldc->ldc_selectinfo /* ldap_common refcnt - free only if 0 */ /* protected by ldc_mutex */ unsigned int ldc_refcnt; #define ld_ldcrefcnt ldc->ldc_refcnt /* protected by ldo_mutex */ struct ldapoptions ldc_options; #define ld_options ldc->ldc_options #define ld_valid ld_options.ldo_valid #define ld_debug ld_options.ldo_debug #define ld_deref ld_options.ldo_deref #define ld_timelimit ld_options.ldo_timelimit #define ld_sizelimit ld_options.ldo_sizelimit #define ld_defbinddn ld_options.ldo_defbinddn #define ld_defbase ld_options.ldo_defbase #define ld_defhost ld_options.ldo_defhost #define ld_defport ld_options.ldo_defport #define ld_refhoplimit ld_options.ldo_refhoplimit #define ld_sctrls ld_options.ldo_sctrls #define ld_cctrls ld_options.ldo_cctrls #define ld_rebind_proc ld_options.ldo_rebind_proc #define ld_rebind_params ld_options.ldo_rebind_params #define ld_nextref_proc ld_options.ldo_nextref_proc #define ld_nextref_params ld_options.ldo_nextref_params #define ld_urllist_proc ld_options.ldo_urllist_proc #define ld_urllist_params ld_options.ldo_urllist_params #define ld_version ld_options.ldo_version #ifdef LDAP_R_COMPILE ldap_pvt_thread_mutex_t ldc_mutex; ldap_pvt_thread_mutex_t ldc_msgid_mutex; ldap_pvt_thread_mutex_t ldc_conn_mutex; ldap_pvt_thread_mutex_t ldc_req_mutex; ldap_pvt_thread_mutex_t ldc_res_mutex; ldap_pvt_thread_mutex_t ldc_abandon_mutex; #define ld_ldopts_mutex ld_options.ldo_mutex #define ld_ldcmutex ldc->ldc_mutex #define ld_msgid_mutex ldc->ldc_msgid_mutex #define ld_conn_mutex ldc->ldc_conn_mutex #define ld_req_mutex ldc->ldc_req_mutex #define ld_res_mutex ldc->ldc_res_mutex #define ld_abandon_mutex ldc->ldc_abandon_mutex #endif }; struct ldap { /* thread shared */ struct ldap_common *ldc; /* thread specific */ ber_int_t ld_errno; char *ld_error; char *ld_matched; char **ld_referrals; }; #define LDAP_VALID(ld) ( (ld)->ld_valid == LDAP_VALID_SESSION ) #define LDAP_TRASHED(ld) ( (ld)->ld_valid == LDAP_TRASHED_SESSION ) #define LDAP_TRASH(ld) ( (ld)->ld_valid = LDAP_TRASHED_SESSION ) #ifdef LDAP_R_COMPILE LDAP_V ( ldap_pvt_thread_mutex_t ) ldap_int_resolv_mutex; LDAP_V ( ldap_pvt_thread_mutex_t ) ldap_int_hostname_mutex; #ifdef HAVE_GSSAPI LDAP_V( ldap_pvt_thread_mutex_t ) ldap_int_gssapi_mutex; #endif #endif #ifdef LDAP_R_COMPILE #define LDAP_MUTEX_LOCK(mutex) ldap_pvt_thread_mutex_lock( mutex ) #define LDAP_MUTEX_UNLOCK(mutex) ldap_pvt_thread_mutex_unlock( mutex ) #define LDAP_ASSERT_MUTEX_OWNER(mutex) \ LDAP_PVT_THREAD_ASSERT_MUTEX_OWNER(mutex) #else #define LDAP_MUTEX_LOCK(mutex) ((void) 0) #define LDAP_MUTEX_UNLOCK(mutex) ((void) 0) #define LDAP_ASSERT_MUTEX_OWNER(mutex) ((void) 0) #endif #define LDAP_NEXT_MSGID(ld, id) do { \ LDAP_MUTEX_LOCK( &(ld)->ld_msgid_mutex ); \ (id) = ++(ld)->ld_msgid; \ LDAP_MUTEX_UNLOCK( &(ld)->ld_msgid_mutex ); \ } while (0) /* * in abandon.c */ LDAP_F (int) ldap_int_bisect_find( ber_int_t *v, ber_len_t n, ber_int_t id, int *idxp ); LDAP_F (int) ldap_int_bisect_insert( ber_int_t **vp, ber_len_t *np, int id, int idx ); LDAP_F (int) ldap_int_bisect_delete( ber_int_t **vp, ber_len_t *np, int id, int idx ); /* * in init.c */ LDAP_V ( struct ldapoptions ) ldap_int_global_options; LDAP_F ( void ) ldap_int_initialize LDAP_P((struct ldapoptions *, int *)); LDAP_F ( void ) ldap_int_initialize_global_options LDAP_P(( struct ldapoptions *, int *)); /* memory.c */ /* simple macros to realloc for now */ #define LDAP_MALLOC(s) (ber_memalloc_x((s),NULL)) #define LDAP_CALLOC(n,s) (ber_memcalloc_x((n),(s),NULL)) #define LDAP_REALLOC(p,s) (ber_memrealloc_x((p),(s),NULL)) #define LDAP_FREE(p) (ber_memfree_x((p),NULL)) #define LDAP_VFREE(v) (ber_memvfree_x((void **)(v),NULL)) #define LDAP_STRDUP(s) (ber_strdup_x((s),NULL)) #define LDAP_STRNDUP(s,l) (ber_strndup_x((s),(l),NULL)) #define LDAP_MALLOCX(s,x) (ber_memalloc_x((s),(x))) #define LDAP_CALLOCX(n,s,x) (ber_memcalloc_x((n),(s),(x))) #define LDAP_REALLOCX(p,s,x) (ber_memrealloc_x((p),(s),(x))) #define LDAP_FREEX(p,x) (ber_memfree_x((p),(x))) #define LDAP_VFREEX(v,x) (ber_memvfree_x((void **)(v),(x))) #define LDAP_STRDUPX(s,x) (ber_strdup_x((s),(x))) #define LDAP_STRNDUPX(s,l,x) (ber_strndup_x((s),(l),(x))) /* * in error.c */ LDAP_F (void) ldap_int_error_init( void ); /* * in unit-int.c */ LDAP_F (void) ldap_int_utils_init LDAP_P(( void )); /* * in print.c */ LDAP_F (int) ldap_log_printf LDAP_P((LDAP *ld, int level, const char *fmt, ...)) LDAP_GCCATTR((format(printf, 3, 4))); /* * in cache.c */ LDAP_F (void) ldap_add_request_to_cache LDAP_P(( LDAP *ld, ber_tag_t msgtype, BerElement *request )); LDAP_F (void) ldap_add_result_to_cache LDAP_P(( LDAP *ld, LDAPMessage *result )); LDAP_F (int) ldap_check_cache LDAP_P(( LDAP *ld, ber_tag_t msgtype, BerElement *request )); /* * in controls.c */ LDAP_F (int) ldap_int_put_controls LDAP_P(( LDAP *ld, LDAPControl *const *ctrls, BerElement *ber )); LDAP_F (int) ldap_int_client_controls LDAP_P(( LDAP *ld, LDAPControl **ctrlp )); /* * in dsparse.c */ LDAP_F (int) ldap_int_next_line_tokens LDAP_P(( char **bufp, ber_len_t *blenp, char ***toksp )); /* * in open.c */ LDAP_F (int) ldap_open_defconn( LDAP *ld ); LDAP_F (int) ldap_int_open_connection( LDAP *ld, LDAPConn *conn, LDAPURLDesc *srvlist, int async ); LDAP_F (int) ldap_int_check_async_open( LDAP *ld, ber_socket_t sd ); /* * in os-ip.c */ #ifndef HAVE_POLL LDAP_V (int) ldap_int_tblsize; LDAP_F (void) ldap_int_ip_init( void ); #endif LDAP_F (int) ldap_int_timeval_dup( struct timeval **dest, const struct timeval *tm ); LDAP_F (int) ldap_connect_to_host( LDAP *ld, Sockbuf *sb, int proto, LDAPURLDesc *srv, int async ); LDAP_F (int) ldap_int_poll( LDAP *ld, ber_socket_t s, struct timeval *tvp, int wr ); #if defined(HAVE_TLS) || defined(HAVE_CYRUS_SASL) LDAP_V (char *) ldap_int_hostname; LDAP_F (char *) ldap_host_connected_to( Sockbuf *sb, const char *host ); #endif LDAP_F (int) ldap_int_select( LDAP *ld, struct timeval *timeout ); LDAP_F (void *) ldap_new_select_info( void ); LDAP_F (void) ldap_free_select_info( void *sip ); LDAP_F (void) ldap_mark_select_write( LDAP *ld, Sockbuf *sb ); LDAP_F (void) ldap_mark_select_read( LDAP *ld, Sockbuf *sb ); LDAP_F (void) ldap_mark_select_clear( LDAP *ld, Sockbuf *sb ); LDAP_F (void) ldap_clear_select_write( LDAP *ld, Sockbuf *sb ); LDAP_F (int) ldap_is_read_ready( LDAP *ld, Sockbuf *sb ); LDAP_F (int) ldap_is_write_ready( LDAP *ld, Sockbuf *sb ); LDAP_F (int) ldap_int_connect_cbs( LDAP *ld, Sockbuf *sb, ber_socket_t *s, LDAPURLDesc *srv, struct sockaddr *addr ); /* * in os-local.c */ #ifdef LDAP_PF_LOCAL LDAP_F (int) ldap_connect_to_path( LDAP *ld, Sockbuf *sb, LDAPURLDesc *srv, int async ); #endif /* LDAP_PF_LOCAL */ /* * in request.c */ LDAP_F (ber_int_t) ldap_send_initial_request( LDAP *ld, ber_tag_t msgtype, const char *dn, BerElement *ber, ber_int_t msgid ); LDAP_F (BerElement *) ldap_alloc_ber_with_options( LDAP *ld ); LDAP_F (void) ldap_set_ber_options( LDAP *ld, BerElement *ber ); LDAP_F (int) ldap_send_server_request( LDAP *ld, BerElement *ber, ber_int_t msgid, LDAPRequest *parentreq, LDAPURLDesc **srvlist, LDAPConn *lc, LDAPreqinfo *bind, int noconn, int m_res ); LDAP_F (LDAPConn *) ldap_new_connection( LDAP *ld, LDAPURLDesc **srvlist, int use_ldsb, int connect, LDAPreqinfo *bind, int m_req, int m_res ); LDAP_F (LDAPRequest *) ldap_find_request_by_msgid( LDAP *ld, ber_int_t msgid ); LDAP_F (void) ldap_return_request( LDAP *ld, LDAPRequest *lr, int freeit ); LDAP_F (void) ldap_free_request( LDAP *ld, LDAPRequest *lr ); LDAP_F (void) ldap_free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind ); LDAP_F (void) ldap_dump_connection( LDAP *ld, LDAPConn *lconns, int all ); LDAP_F (void) ldap_dump_requests_and_responses( LDAP *ld ); LDAP_F (int) ldap_chase_referrals( LDAP *ld, LDAPRequest *lr, char **errstrp, int sref, int *hadrefp ); LDAP_F (int) ldap_chase_v3referrals( LDAP *ld, LDAPRequest *lr, char **refs, int sref, char **referralsp, int *hadrefp ); LDAP_F (int) ldap_append_referral( LDAP *ld, char **referralsp, char *s ); LDAP_F (int) ldap_int_flush_request( LDAP *ld, LDAPRequest *lr ); /* * in result.c: */ LDAP_F (const char *) ldap_int_msgtype2str( ber_tag_t tag ); /* * in search.c */ LDAP_F (BerElement *) ldap_build_search_req LDAP_P(( LDAP *ld, const char *base, ber_int_t scope, const char *filter, char **attrs, ber_int_t attrsonly, LDAPControl **sctrls, LDAPControl **cctrls, ber_int_t timelimit, ber_int_t sizelimit, ber_int_t deref, ber_int_t *msgidp)); /* * in unbind.c */ LDAP_F (int) ldap_ld_free LDAP_P(( LDAP *ld, int close, LDAPControl **sctrls, LDAPControl **cctrls )); LDAP_F (int) ldap_send_unbind LDAP_P(( LDAP *ld, Sockbuf *sb, LDAPControl **sctrls, LDAPControl **cctrls )); /* * in url.c */ LDAP_F (LDAPURLDesc *) ldap_url_dup LDAP_P(( LDAPURLDesc *ludp )); LDAP_F (LDAPURLDesc *) ldap_url_duplist LDAP_P(( LDAPURLDesc *ludlist )); LDAP_F (int) ldap_url_parsehosts LDAP_P(( LDAPURLDesc **ludlist, const char *hosts, int port )); LDAP_F (char *) ldap_url_list2hosts LDAP_P(( LDAPURLDesc *ludlist )); /* * in cyrus.c */ LDAP_F (int) ldap_int_sasl_init LDAP_P(( void )); LDAP_F (int) ldap_int_sasl_open LDAP_P(( LDAP *ld, LDAPConn *conn, const char* host )); LDAP_F (int) ldap_int_sasl_close LDAP_P(( LDAP *ld, LDAPConn *conn )); LDAP_F (int) ldap_int_sasl_external LDAP_P(( LDAP *ld, LDAPConn *conn, const char* authid, ber_len_t ssf )); LDAP_F (int) ldap_int_sasl_get_option LDAP_P(( LDAP *ld, int option, void *arg )); LDAP_F (int) ldap_int_sasl_set_option LDAP_P(( LDAP *ld, int option, void *arg )); LDAP_F (int) ldap_int_sasl_config LDAP_P(( struct ldapoptions *lo, int option, const char *arg )); LDAP_F (int) ldap_int_sasl_bind LDAP_P(( LDAP *ld, const char *, const char *, LDAPControl **, LDAPControl **, /* should be passed in client controls */ unsigned flags, LDAP_SASL_INTERACT_PROC *interact, void *defaults, LDAPMessage *result, const char **rmech, int *msgid )); /* in schema.c */ LDAP_F (char *) ldap_int_parse_numericoid LDAP_P(( const char **sp, int *code, const int flags )); /* * in tls.c */ LDAP_F (int) ldap_int_tls_config LDAP_P(( LDAP *ld, int option, const char *arg )); LDAP_F (int) ldap_int_tls_start LDAP_P(( LDAP *ld, LDAPConn *conn, LDAPURLDesc *srv )); LDAP_F (void) ldap_int_tls_destroy LDAP_P(( struct ldapoptions *lo )); /* * in getvalues.c */ LDAP_F (char **) ldap_value_dup LDAP_P(( char *const *vals )); /* * in gssapi.c */ #ifdef HAVE_GSSAPI LDAP_F(int) ldap_int_gssapi_get_option LDAP_P(( LDAP *ld, int option, void *arg )); LDAP_F(int) ldap_int_gssapi_set_option LDAP_P(( LDAP *ld, int option, void *arg )); LDAP_F(int) ldap_int_gssapi_config LDAP_P(( struct ldapoptions *lo, int option, const char *arg )); LDAP_F(void) ldap_int_gssapi_close LDAP_P(( LDAP *ld, LDAPConn *lc )); #endif LDAP_END_DECL #endif /* _LDAP_INT_H */ openldap-2.4.42+dfsg/libraries/libldap/dds.c0000644000175000017500000000575712563404150017347 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 2005-2015 The OpenLDAP Foundation. * Portions Copyright 2005-2006 SysNet s.n.c. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* ACKNOWLEDGEMENTS: * This work was developed by Pierangelo Masarati for inclusion * in OpenLDAP Software */ #include "portable.h" #include #include #include #include #include "ldap-int.h" int ldap_parse_refresh( LDAP *ld, LDAPMessage *res, ber_int_t *newttl ) { int rc; struct berval *retdata = NULL; ber_tag_t tag; BerElement *ber; assert( ld != NULL ); assert( LDAP_VALID( ld ) ); assert( res != NULL ); assert( newttl != NULL ); *newttl = 0; rc = ldap_parse_extended_result( ld, res, NULL, &retdata, 0 ); if ( rc != LDAP_SUCCESS ) { return rc; } if ( ld->ld_errno != LDAP_SUCCESS ) { return ld->ld_errno; } if ( retdata == NULL ) { rc = ld->ld_errno = LDAP_DECODING_ERROR; return rc; } ber = ber_init( retdata ); if ( ber == NULL ) { rc = ld->ld_errno = LDAP_NO_MEMORY; goto done; } /* check the tag */ tag = ber_scanf( ber, "{i}", newttl ); ber_free( ber, 1 ); if ( tag != LDAP_TAG_EXOP_REFRESH_RES_TTL ) { *newttl = 0; rc = ld->ld_errno = LDAP_DECODING_ERROR; } done:; if ( retdata ) { ber_bvfree( retdata ); } return rc; } int ldap_refresh( LDAP *ld, struct berval *dn, ber_int_t ttl, LDAPControl **sctrls, LDAPControl **cctrls, int *msgidp ) { struct berval bv = { 0, NULL }; BerElement *ber = NULL; int rc; assert( ld != NULL ); assert( LDAP_VALID( ld ) ); assert( dn != NULL ); assert( msgidp != NULL ); *msgidp = -1; ber = ber_alloc_t( LBER_USE_DER ); if ( ber == NULL ) { ld->ld_errno = LDAP_NO_MEMORY; return ld->ld_errno; } ber_printf( ber, "{tOtiN}", LDAP_TAG_EXOP_REFRESH_REQ_DN, dn, LDAP_TAG_EXOP_REFRESH_REQ_TTL, ttl ); rc = ber_flatten2( ber, &bv, 0 ); if ( rc < 0 ) { rc = ld->ld_errno = LDAP_ENCODING_ERROR; goto done; } rc = ldap_extended_operation( ld, LDAP_EXOP_REFRESH, &bv, sctrls, cctrls, msgidp ); done:; ber_free( ber, 1 ); return rc; } int ldap_refresh_s( LDAP *ld, struct berval *dn, ber_int_t ttl, ber_int_t *newttl, LDAPControl **sctrls, LDAPControl **cctrls ) { int rc; int msgid; LDAPMessage *res; rc = ldap_refresh( ld, dn, ttl, sctrls, cctrls, &msgid ); if ( rc != LDAP_SUCCESS ) return rc; rc = ldap_result( ld, msgid, LDAP_MSG_ALL, (struct timeval *)NULL, &res ); if( rc == -1 || !res ) return ld->ld_errno; rc = ldap_parse_refresh( ld, res, newttl ); if( rc != LDAP_SUCCESS ) { ldap_msgfree( res ); return rc; } return ldap_result2error( ld, res, 1 ); } openldap-2.4.42+dfsg/libraries/libldap/utf-8-conv.c0000644000175000017500000003220612563404150020470 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (C) 1999, 2000 Novell, Inc. All Rights Reserved. * * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND * TREATIES. USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT * TO VERSION 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS * AVAILABLE AT HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE" * IN THE TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION * OF THIS WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP * PUBLIC LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT * THE PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY. *--- * Note: A verbatim copy of version 2.0.1 of the OpenLDAP Public License * can be found in the file "build/LICENSE-2.0.1" in this distribution * of OpenLDAP Software. */ /* * UTF-8 Conversion Routines * * These routines convert between Wide Character and UTF-8, * or between MultiByte and UTF-8 encodings. * * Both single character and string versions of the functions are provided. * All functions return -1 if the character or string cannot be converted. */ #include "portable.h" #if SIZEOF_WCHAR_T >= 4 /* These routines assume ( sizeof(wchar_t) >= 4 ) */ #include #include /* For wctomb, wcstombs, mbtowc, mbstowcs */ #include #include /* for time_t */ #include "ldap-int.h" #include static unsigned char mask[] = { 0, 0x7f, 0x1f, 0x0f, 0x07, 0x03, 0x01 }; /*----------------------------------------------------------------------------- UTF-8 Format Summary ASCII chars 7 bits 0xxxxxxx 2-character UTF-8 sequence: 11 bits 110xxxxx 10xxxxxx 3-character UTF-8 16 bits 1110xxxx 10xxxxxx 10xxxxxx 4-char UTF-8 21 bits 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 5-char UTF-8 26 bits 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 6-char UTF-8 31 bits 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx Unicode address space (0 - 0x10FFFF) 21 bits ISO-10646 address space (0 - 0x7FFFFFFF) 31 bits Note: This code does not prevent UTF-8 sequences which are longer than necessary from being decoded. */ /*----------------------------------------------------------------------------- Convert a UTF-8 character to a wide char. Return the length of the UTF-8 input character in bytes. */ int ldap_x_utf8_to_wc ( wchar_t *wchar, const char *utf8char ) { int utflen, i; wchar_t ch; if (utf8char == NULL) return -1; /* Get UTF-8 sequence length from 1st byte */ utflen = LDAP_UTF8_CHARLEN2(utf8char, utflen); if( utflen==0 || utflen > (int)LDAP_MAX_UTF8_LEN ) return -1; /* First byte minus length tag */ ch = (wchar_t)(utf8char[0] & mask[utflen]); for(i=1; i < utflen; i++) { /* Subsequent bytes must start with 10 */ if ((utf8char[i] & 0xc0) != 0x80) return -1; ch <<= 6; /* 6 bits of data in each subsequent byte */ ch |= (wchar_t)(utf8char[i] & 0x3f); } if (wchar) *wchar = ch; return utflen; } /*----------------------------------------------------------------------------- Convert a UTF-8 string to a wide char string. No more than 'count' wide chars will be written to the output buffer. Return the size of the converted string in wide chars, excl null terminator. */ int ldap_x_utf8s_to_wcs ( wchar_t *wcstr, const char *utf8str, size_t count ) { size_t wclen = 0; int utflen, i; wchar_t ch; /* If input ptr is NULL or empty... */ if (utf8str == NULL || !*utf8str) { if ( wcstr ) *wcstr = 0; return 0; } /* Examine next UTF-8 character. If output buffer is NULL, ignore count */ while ( *utf8str && (wcstr==NULL || wclen (int)LDAP_MAX_UTF8_LEN ) return -1; /* First byte minus length tag */ ch = (wchar_t)(utf8str[0] & mask[utflen]); for(i=1; i < utflen; i++) { /* Subsequent bytes must start with 10 */ if ((utf8str[i] & 0xc0) != 0x80) return -1; ch <<= 6; /* 6 bits of data in each subsequent byte */ ch |= (wchar_t)(utf8str[i] & 0x3f); } if (wcstr) wcstr[wclen] = ch; utf8str += utflen; /* Move to next UTF-8 character */ wclen++; /* Count number of wide chars stored/required */ } /* Add null terminator if there's room in the buffer. */ if (wcstr && wclen < count) wcstr[wclen] = 0; return wclen; } /*----------------------------------------------------------------------------- Convert one wide char to a UTF-8 character. Return the length of the converted UTF-8 character in bytes. No more than 'count' bytes will be written to the output buffer. */ int ldap_x_wc_to_utf8 ( char *utf8char, wchar_t wchar, size_t count ) { int len=0; if (utf8char == NULL) /* Just determine the required UTF-8 char length. */ { /* Ignore count */ if( wchar < 0 ) return -1; if( wchar < 0x80 ) return 1; if( wchar < 0x800 ) return 2; if( wchar < 0x10000 ) return 3; if( wchar < 0x200000 ) return 4; if( wchar < 0x4000000 ) return 5; #if SIZEOF_WCHAR_T > 4 /* UL is not strictly needed by ANSI C */ if( wchar < (wchar_t)0x80000000UL ) #endif /* SIZEOF_WCHAR_T > 4 */ return 6; return -1; } if ( wchar < 0 ) { /* Invalid wide character */ len = -1; } else if( wchar < 0x80 ) { if (count >= 1) { utf8char[len++] = (char)wchar; } } else if( wchar < 0x800 ) { if (count >=2) { utf8char[len++] = 0xc0 | ( wchar >> 6 ); utf8char[len++] = 0x80 | ( wchar & 0x3f ); } } else if( wchar < 0x10000 ) { if (count >= 3) { utf8char[len++] = 0xe0 | ( wchar >> 12 ); utf8char[len++] = 0x80 | ( (wchar >> 6) & 0x3f ); utf8char[len++] = 0x80 | ( wchar & 0x3f ); } } else if( wchar < 0x200000 ) { if (count >= 4) { utf8char[len++] = 0xf0 | ( wchar >> 18 ); utf8char[len++] = 0x80 | ( (wchar >> 12) & 0x3f ); utf8char[len++] = 0x80 | ( (wchar >> 6) & 0x3f ); utf8char[len++] = 0x80 | ( wchar & 0x3f ); } } else if( wchar < 0x4000000 ) { if (count >= 5) { utf8char[len++] = 0xf8 | ( wchar >> 24 ); utf8char[len++] = 0x80 | ( (wchar >> 18) & 0x3f ); utf8char[len++] = 0x80 | ( (wchar >> 12) & 0x3f ); utf8char[len++] = 0x80 | ( (wchar >> 6) & 0x3f ); utf8char[len++] = 0x80 | ( wchar & 0x3f ); } } else #if SIZEOF_WCHAR_T > 4 /* UL is not strictly needed by ANSI C */ if( wchar < (wchar_t)0x80000000UL ) #endif /* SIZEOF_WCHAR_T > 4 */ { if (count >= 6) { utf8char[len++] = 0xfc | ( wchar >> 30 ); utf8char[len++] = 0x80 | ( (wchar >> 24) & 0x3f ); utf8char[len++] = 0x80 | ( (wchar >> 18) & 0x3f ); utf8char[len++] = 0x80 | ( (wchar >> 12) & 0x3f ); utf8char[len++] = 0x80 | ( (wchar >> 6) & 0x3f ); utf8char[len++] = 0x80 | ( wchar & 0x3f ); } #if SIZEOF_WCHAR_T > 4 } else { len = -1; #endif /* SIZEOF_WCHAR_T > 4 */ } return len; } /*----------------------------------------------------------------------------- Convert a wide char string to a UTF-8 string. No more than 'count' bytes will be written to the output buffer. Return the # of bytes written to the output buffer, excl null terminator. */ int ldap_x_wcs_to_utf8s ( char *utf8str, const wchar_t *wcstr, size_t count ) { int len = 0; int n; char *p = utf8str; wchar_t empty = 0; /* To avoid use of L"" construct */ if (wcstr == NULL) /* Treat input ptr NULL as an empty string */ wcstr = ∅ if (utf8str == NULL) /* Just compute size of output, excl null */ { while (*wcstr) { /* Get UTF-8 size of next wide char */ n = ldap_x_wc_to_utf8( NULL, *wcstr++, LDAP_MAX_UTF8_LEN); if (n == -1) return -1; len += n; } return len; } /* Do the actual conversion. */ n = 1; /* In case of empty wcstr */ while (*wcstr) { n = ldap_x_wc_to_utf8( p, *wcstr++, count); if (n <= 0) /* If encoding error (-1) or won't fit (0), quit */ break; p += n; count -= n; /* Space left in output buffer */ } /* If not enough room for last character, pad remainder with null so that return value = original count, indicating buffer full. */ if (n == 0) { while (count--) *p++ = 0; } /* Add a null terminator if there's room. */ else if (count) *p = 0; if (n == -1) /* Conversion encountered invalid wide char. */ return -1; /* Return the number of bytes written to output buffer, excl null. */ return (p - utf8str); } #ifdef ANDROID int wctomb(char *s, wchar_t wc) { return wcrtomb(s,wc,NULL); } int mbtowc(wchar_t *pwc, const char *s, size_t n) { return mbrtowc(pwc, s, n, NULL); } #endif /*----------------------------------------------------------------------------- Convert a UTF-8 character to a MultiByte character. Return the size of the converted character in bytes. */ int ldap_x_utf8_to_mb ( char *mbchar, const char *utf8char, int (*f_wctomb)(char *mbchar, wchar_t wchar) ) { wchar_t wchar; int n; char tmp[6]; /* Large enough for biggest multibyte char */ if (f_wctomb == NULL) /* If no conversion function was given... */ f_wctomb = wctomb; /* use the local ANSI C function */ /* First convert UTF-8 char to a wide char */ n = ldap_x_utf8_to_wc( &wchar, utf8char); if (n == -1) return -1; /* Invalid UTF-8 character */ if (mbchar == NULL) n = f_wctomb( tmp, wchar ); else n = f_wctomb( mbchar, wchar); return n; } /*----------------------------------------------------------------------------- Convert a UTF-8 string to a MultiByte string. No more than 'count' bytes will be written to the output buffer. Return the size of the converted string in bytes, excl null terminator. */ int ldap_x_utf8s_to_mbs ( char *mbstr, const char *utf8str, size_t count, size_t (*f_wcstombs)(char *mbstr, const wchar_t *wcstr, size_t count) ) { wchar_t *wcs; size_t wcsize; int n; if (f_wcstombs == NULL) /* If no conversion function was given... */ f_wcstombs = wcstombs; /* use the local ANSI C function */ if (utf8str == NULL || *utf8str == 0) /* NULL or empty input string */ { if (mbstr) *mbstr = 0; return 0; } /* Allocate memory for the maximum size wchar string that we could get. */ wcsize = strlen(utf8str) + 1; wcs = (wchar_t *)LDAP_MALLOC(wcsize * sizeof(wchar_t)); if (wcs == NULL) return -1; /* Memory allocation failure. */ /* First convert the UTF-8 string to a wide char string */ n = ldap_x_utf8s_to_wcs( wcs, utf8str, wcsize); /* Then convert wide char string to multi-byte string */ if (n != -1) { n = f_wcstombs(mbstr, wcs, count); } LDAP_FREE(wcs); return n; } /*----------------------------------------------------------------------------- Convert a MultiByte character to a UTF-8 character. 'mbsize' indicates the number of bytes of 'mbchar' to check. Returns the number of bytes written to the output character. */ int ldap_x_mb_to_utf8 ( char *utf8char, const char *mbchar, size_t mbsize, int (*f_mbtowc)(wchar_t *wchar, const char *mbchar, size_t count) ) { wchar_t wchar; int n; if (f_mbtowc == NULL) /* If no conversion function was given... */ f_mbtowc = mbtowc; /* use the local ANSI C function */ if (mbsize == 0) /* 0 is not valid. */ return -1; if (mbchar == NULL || *mbchar == 0) { if (utf8char) *utf8char = 0; return 1; } /* First convert the MB char to a Wide Char */ n = f_mbtowc( &wchar, mbchar, mbsize); if (n == -1) return -1; /* Convert the Wide Char to a UTF-8 character. */ n = ldap_x_wc_to_utf8( utf8char, wchar, LDAP_MAX_UTF8_LEN); return n; } /*----------------------------------------------------------------------------- Convert a MultiByte string to a UTF-8 string. No more than 'count' bytes will be written to the output buffer. Return the size of the converted string in bytes, excl null terminator. */ int ldap_x_mbs_to_utf8s ( char *utf8str, const char *mbstr, size_t count, size_t (*f_mbstowcs)(wchar_t *wcstr, const char *mbstr, size_t count) ) { wchar_t *wcs; int n; size_t wcsize; if (mbstr == NULL) /* Treat NULL input string as an empty string */ mbstr = ""; if (f_mbstowcs == NULL) /* If no conversion function was given... */ f_mbstowcs = mbstowcs; /* use the local ANSI C function */ /* Allocate memory for the maximum size wchar string that we could get. */ wcsize = strlen(mbstr) + 1; wcs = (wchar_t *)LDAP_MALLOC( wcsize * sizeof(wchar_t) ); if (wcs == NULL) return -1; /* First convert multi-byte string to a wide char string */ n = f_mbstowcs(wcs, mbstr, wcsize); /* Convert wide char string to UTF-8 string */ if (n != -1) { n = ldap_x_wcs_to_utf8s( utf8str, wcs, count); } LDAP_FREE(wcs); return n; } #endif /* SIZEOF_WCHAR_T >= 4 */ openldap-2.4.42+dfsg/libraries/libldap/sortctrl.c0000644000175000017500000003535512563404150020446 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (C) 1999, 2000 Novell, Inc. All Rights Reserved. * * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND * TREATIES. USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT * TO VERSION 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS * AVAILABLE AT HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE" * IN THE TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION * OF THIS WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP * PUBLIC LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT * THE PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY. */ /* Note: A verbatim copy of version 2.0.1 of the OpenLDAP Public License * can be found in the file "build/LICENSE-2.0.1" in this distribution * of OpenLDAP Software. */ #include "portable.h" #include #include #include #include #include "ldap-int.h" #define LDAP_MATCHRULE_IDENTIFIER 0x80L #define LDAP_REVERSEORDER_IDENTIFIER 0x81L #define LDAP_ATTRTYPES_IDENTIFIER 0x80L /* --------------------------------------------------------------------------- countKeys Internal function to determine the number of keys in the string. keyString (IN) String of items separated by whitespace. ---------------------------------------------------------------------------*/ static int countKeys(char *keyString) { char *p = keyString; int count = 0; for (;;) { while (LDAP_SPACE(*p)) /* Skip leading whitespace */ p++; if (*p == '\0') /* End of string? */ return count; count++; /* Found start of a key */ while (!LDAP_SPACE(*p)) /* Skip till next space or end of string. */ if (*p++ == '\0') return count; } } /* --------------------------------------------------------------------------- readNextKey Internal function to parse the next sort key in the string. Allocate an LDAPSortKey structure and initialize it with attribute name, reverse flag, and matching rule OID. Each sort key in the string has the format: [whitespace][-]attribute[:[OID]] pNextKey (IN/OUT) Points to the next key in the sortkey string to parse. The pointer is updated to point to the next character after the sortkey being parsed. key (OUT) Points to the address of an LDAPSortKey stucture which has been allocated by this routine and initialized with information from the next sortkey. ---------------------------------------------------------------------------*/ static int readNextKey( char **pNextKey, LDAPSortKey **key) { char *p = *pNextKey; int rev = 0; char *attrStart; int attrLen; char *oidStart = NULL; int oidLen = 0; /* Skip leading white space. */ while (LDAP_SPACE(*p)) p++; if (*p == '-') /* Check if the reverse flag is present. */ { rev=1; p++; } /* We're now positioned at the start of the attribute. */ attrStart = p; /* Get the length of the attribute until the next whitespace or ":". */ attrLen = strcspn(p, " \t:"); p += attrLen; if (attrLen == 0) /* If no attribute name was present, quit. */ return LDAP_PARAM_ERROR; if (*p == ':') { oidStart = ++p; /* Start of the OID, after the colon */ oidLen = strcspn(p, " \t"); /* Get length of OID till next whitespace */ p += oidLen; } *pNextKey = p; /* Update argument to point to next key */ /* Allocate an LDAPSortKey structure */ *key = LDAP_MALLOC(sizeof(LDAPSortKey)); if (*key == NULL) return LDAP_NO_MEMORY; /* Allocate memory for the attribute and copy to it. */ (*key)->attributeType = LDAP_MALLOC(attrLen+1); if ((*key)->attributeType == NULL) { LDAP_FREE(*key); return LDAP_NO_MEMORY; } strncpy((*key)->attributeType, attrStart, attrLen); (*key)->attributeType[attrLen] = 0; /* If present, allocate memory for the OID and copy to it. */ if (oidLen) { (*key)->orderingRule = LDAP_MALLOC(oidLen+1); if ((*key)->orderingRule == NULL) { LDAP_FREE((*key)->attributeType); LDAP_FREE(*key); return LDAP_NO_MEMORY; } strncpy((*key)->orderingRule, oidStart, oidLen); (*key)->orderingRule[oidLen] = 0; } else { (*key)->orderingRule = NULL; } (*key)->reverseOrder = rev; return LDAP_SUCCESS; } /* --------------------------------------------------------------------------- ldap_create_sort_keylist Create an array of pointers to LDAPSortKey structures, containing the information specified by the string representation of one or more sort keys. sortKeyList (OUT) Points to a null-terminated array of pointers to LDAPSortKey structures allocated by this routine. This memory SHOULD be freed by the calling program using ldap_free_sort_keylist(). keyString (IN) Points to a string of one or more sort keys. ---------------------------------------------------------------------------*/ int ldap_create_sort_keylist ( LDAPSortKey ***sortKeyList, char *keyString ) { int numKeys, rc, i; char *nextKey; LDAPSortKey **keyList = NULL; assert( sortKeyList != NULL ); assert( keyString != NULL ); *sortKeyList = NULL; /* Determine the number of sort keys so we can allocate memory. */ if (( numKeys = countKeys(keyString)) == 0) { return LDAP_PARAM_ERROR; } /* Allocate the array of pointers. Initialize to NULL. */ keyList=(LDAPSortKey**)LBER_CALLOC(numKeys+1, sizeof(LDAPSortKey*)); if ( keyList == NULL) return LDAP_NO_MEMORY; /* For each sort key in the string, create an LDAPSortKey structure and add it to the list. */ nextKey = keyString; /* Points to the next key in the string */ for (i=0; i < numKeys; i++) { rc = readNextKey(&nextKey, &keyList[i]); if (rc != LDAP_SUCCESS) { ldap_free_sort_keylist(keyList); return rc; } } *sortKeyList = keyList; return LDAP_SUCCESS; } /* --------------------------------------------------------------------------- ldap_free_sort_keylist Frees the sort key structures created by ldap_create_sort_keylist(). Frees the memory referenced by the LDAPSortKey structures, the LDAPSortKey structures themselves, and the array of pointers to the structures. keyList (IN) Points to an array of pointers to LDAPSortKey structures. ---------------------------------------------------------------------------*/ void ldap_free_sort_keylist ( LDAPSortKey **keyList ) { int i; LDAPSortKey *nextKeyp; if (keyList == NULL) return; i=0; while ( 0 != (nextKeyp = keyList[i++]) ) { if (nextKeyp->attributeType) { LBER_FREE(nextKeyp->attributeType); } if (nextKeyp->orderingRule != NULL) { LBER_FREE(nextKeyp->orderingRule); } LBER_FREE(nextKeyp); } LBER_FREE(keyList); } /* --------------------------------------------------------------------------- ldap_create_sort_control_value Create and encode the value of the server-side sort control. ld (IN) An LDAP session handle, as obtained from a call to ldap_init(). keyList (IN) Points to a null-terminated array of pointers to LDAPSortKey structures, containing a description of each of the sort keys to be used. The description consists of an attribute name, ascending/descending flag, and an optional matching rule (OID) to use. value (OUT) Contains the control value; the bv_val member of the berval structure SHOULD be freed by calling ldap_memfree() when done. Ber encoding SortKeyList ::= SEQUENCE OF SEQUENCE { attributeType AttributeDescription, orderingRule [0] MatchingRuleId OPTIONAL, reverseOrder [1] BOOLEAN DEFAULT FALSE } ---------------------------------------------------------------------------*/ int ldap_create_sort_control_value( LDAP *ld, LDAPSortKey **keyList, struct berval *value ) { int i; BerElement *ber = NULL; ber_tag_t tag; assert( ld != NULL ); assert( LDAP_VALID( ld ) ); if ( ld == NULL ) return LDAP_PARAM_ERROR; if ( keyList == NULL || value == NULL ) { ld->ld_errno = LDAP_PARAM_ERROR; return LDAP_PARAM_ERROR; } value->bv_val = NULL; value->bv_len = 0; ld->ld_errno = LDAP_SUCCESS; ber = ldap_alloc_ber_with_options( ld ); if ( ber == NULL) { ld->ld_errno = LDAP_NO_MEMORY; return ld->ld_errno; } tag = ber_printf( ber, "{" /*}*/ ); if ( tag == LBER_ERROR ) { goto error_return; } for ( i = 0; keyList[i] != NULL; i++ ) { tag = ber_printf( ber, "{s" /*}*/, keyList[i]->attributeType ); if ( tag == LBER_ERROR ) { goto error_return; } if ( keyList[i]->orderingRule != NULL ) { tag = ber_printf( ber, "ts", LDAP_MATCHRULE_IDENTIFIER, keyList[i]->orderingRule ); if ( tag == LBER_ERROR ) { goto error_return; } } if ( keyList[i]->reverseOrder ) { tag = ber_printf( ber, "tb", LDAP_REVERSEORDER_IDENTIFIER, keyList[i]->reverseOrder ); if ( tag == LBER_ERROR ) { goto error_return; } } tag = ber_printf( ber, /*{*/ "N}" ); if ( tag == LBER_ERROR ) { goto error_return; } } tag = ber_printf( ber, /*{*/ "N}" ); if ( tag == LBER_ERROR ) { goto error_return; } if ( ber_flatten2( ber, value, 1 ) == -1 ) { ld->ld_errno = LDAP_NO_MEMORY; } if ( 0 ) { error_return:; ld->ld_errno = LDAP_ENCODING_ERROR; } if ( ber != NULL ) { ber_free( ber, 1 ); } return ld->ld_errno; } /* --------------------------------------------------------------------------- ldap_create_sort_control Create and encode the server-side sort control. ld (IN) An LDAP session handle, as obtained from a call to ldap_init(). keyList (IN) Points to a null-terminated array of pointers to LDAPSortKey structures, containing a description of each of the sort keys to be used. The description consists of an attribute name, ascending/descending flag, and an optional matching rule (OID) to use. isCritical (IN) 0 - Indicates the control is not critical to the operation. non-zero - The control is critical to the operation. ctrlp (OUT) Returns a pointer to the LDAPControl created. This control SHOULD be freed by calling ldap_control_free() when done. Ber encoding SortKeyList ::= SEQUENCE OF SEQUENCE { attributeType AttributeDescription, orderingRule [0] MatchingRuleId OPTIONAL, reverseOrder [1] BOOLEAN DEFAULT FALSE } ---------------------------------------------------------------------------*/ int ldap_create_sort_control( LDAP *ld, LDAPSortKey **keyList, int isCritical, LDAPControl **ctrlp ) { struct berval value; assert( ld != NULL ); assert( LDAP_VALID( ld ) ); if ( ld == NULL ) { return LDAP_PARAM_ERROR; } if ( ctrlp == NULL ) { ld->ld_errno = LDAP_PARAM_ERROR; return ld->ld_errno; } ld->ld_errno = ldap_create_sort_control_value( ld, keyList, &value ); if ( ld->ld_errno == LDAP_SUCCESS ) { ld->ld_errno = ldap_control_create( LDAP_CONTROL_SORTREQUEST, isCritical, &value, 0, ctrlp ); if ( ld->ld_errno != LDAP_SUCCESS ) { LDAP_FREE( value.bv_val ); } } return ld->ld_errno; } /* --------------------------------------------------------------------------- ldap_parse_sortedresult_control Decode the server-side sort control return information. ld (IN) An LDAP session handle, as obtained from a call to ldap_init(). ctrl (IN) The address of the LDAP Control Structure. returnCode (OUT) This result parameter is filled in with the sort control result code. This parameter MUST not be NULL. attribute (OUT) If an error occured the server may return a string indicating the first attribute in the sortkey list that was in error. If a string is returned, the memory should be freed with ldap_memfree. If this parameter is NULL, no string is returned. Ber encoding for sort control SortResult ::= SEQUENCE { sortResult ENUMERATED { success (0), -- results are sorted operationsError (1), -- server internal failure timeLimitExceeded (3), -- timelimit reached before -- sorting was completed strongAuthRequired (8), -- refused to return sorted -- results via insecure -- protocol adminLimitExceeded (11), -- too many matching entries -- for the server to sort noSuchAttribute (16), -- unrecognized attribute -- type in sort key inappropriateMatching (18), -- unrecognized or inappro- -- priate matching rule in -- sort key insufficientAccessRights (50), -- refused to return sorted -- results to this client busy (51), -- too busy to process unwillingToPerform (53), -- unable to sort other (80) }, attributeType [0] AttributeDescription OPTIONAL } ---------------------------------------------------------------------------*/ int ldap_parse_sortresponse_control( LDAP *ld, LDAPControl *ctrl, ber_int_t *returnCode, char **attribute ) { BerElement *ber; ber_tag_t tag, berTag; ber_len_t berLen; assert( ld != NULL ); assert( LDAP_VALID( ld ) ); if (ld == NULL) { return LDAP_PARAM_ERROR; } if (ctrl == NULL) { ld->ld_errno = LDAP_PARAM_ERROR; return(ld->ld_errno); } if (attribute) { *attribute = NULL; } if ( strcmp(LDAP_CONTROL_SORTRESPONSE, ctrl->ldctl_oid) != 0 ) { /* Not sort result control */ ld->ld_errno = LDAP_CONTROL_NOT_FOUND; return(ld->ld_errno); } /* Create a BerElement from the berval returned in the control. */ ber = ber_init(&ctrl->ldctl_value); if (ber == NULL) { ld->ld_errno = LDAP_NO_MEMORY; return(ld->ld_errno); } /* Extract the result code from the control. */ tag = ber_scanf(ber, "{e" /*}*/, returnCode); if( tag == LBER_ERROR ) { ber_free(ber, 1); ld->ld_errno = LDAP_DECODING_ERROR; return(ld->ld_errno); } /* If caller wants the attribute name, and if it's present in the control, extract the attribute name which caused the error. */ if (attribute && (LDAP_ATTRTYPES_IDENTIFIER == ber_peek_tag(ber, &berLen))) { tag = ber_scanf(ber, "ta", &berTag, attribute); if (tag == LBER_ERROR ) { ber_free(ber, 1); ld->ld_errno = LDAP_DECODING_ERROR; return(ld->ld_errno); } } ber_free(ber,1); ld->ld_errno = LDAP_SUCCESS; return(ld->ld_errno); } openldap-2.4.42+dfsg/libraries/libldap/options.c0000644000175000017500000005140412563404150020256 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #include "portable.h" #include #include #include #include #include #include "ldap-int.h" #define LDAP_OPT_REBIND_PROC 0x4e814d #define LDAP_OPT_REBIND_PARAMS 0x4e814e #define LDAP_OPT_NEXTREF_PROC 0x4e815d #define LDAP_OPT_NEXTREF_PARAMS 0x4e815e #define LDAP_OPT_URLLIST_PROC 0x4e816d #define LDAP_OPT_URLLIST_PARAMS 0x4e816e static const LDAPAPIFeatureInfo features[] = { #ifdef LDAP_API_FEATURE_X_OPENLDAP { /* OpenLDAP Extensions API Feature */ LDAP_FEATURE_INFO_VERSION, "X_OPENLDAP", LDAP_API_FEATURE_X_OPENLDAP }, #endif #ifdef LDAP_API_FEATURE_THREAD_SAFE { /* Basic Thread Safe */ LDAP_FEATURE_INFO_VERSION, "THREAD_SAFE", LDAP_API_FEATURE_THREAD_SAFE }, #endif #ifdef LDAP_API_FEATURE_SESSION_THREAD_SAFE { /* Session Thread Safe */ LDAP_FEATURE_INFO_VERSION, "SESSION_THREAD_SAFE", LDAP_API_FEATURE_SESSION_THREAD_SAFE }, #endif #ifdef LDAP_API_FEATURE_OPERATION_THREAD_SAFE { /* Operation Thread Safe */ LDAP_FEATURE_INFO_VERSION, "OPERATION_THREAD_SAFE", LDAP_API_FEATURE_OPERATION_THREAD_SAFE }, #endif #ifdef LDAP_API_FEATURE_X_OPENLDAP_REENTRANT { /* OpenLDAP Reentrant */ LDAP_FEATURE_INFO_VERSION, "X_OPENLDAP_REENTRANT", LDAP_API_FEATURE_X_OPENLDAP_REENTRANT }, #endif #if defined( LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE ) && \ defined( LDAP_THREAD_SAFE ) { /* OpenLDAP Thread Safe */ LDAP_FEATURE_INFO_VERSION, "X_OPENLDAP_THREAD_SAFE", LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE }, #endif #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS { /* V2 Referrals */ LDAP_FEATURE_INFO_VERSION, "X_OPENLDAP_V2_REFERRALS", LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS }, #endif {0, NULL, 0} }; int ldap_get_option( LDAP *ld, int option, void *outvalue) { struct ldapoptions *lo; int rc = LDAP_OPT_ERROR; /* Get pointer to global option structure */ lo = LDAP_INT_GLOBAL_OPT(); if (NULL == lo) { return LDAP_NO_MEMORY; } if( lo->ldo_valid != LDAP_INITIALIZED ) { ldap_int_initialize(lo, NULL); } if(ld != NULL) { assert( LDAP_VALID( ld ) ); if( !LDAP_VALID( ld ) ) { return LDAP_OPT_ERROR; } lo = &ld->ld_options; } if(outvalue == NULL) { /* no place to get to */ return LDAP_OPT_ERROR; } LDAP_MUTEX_LOCK( &lo->ldo_mutex ); switch(option) { case LDAP_OPT_API_INFO: { struct ldapapiinfo *info = (struct ldapapiinfo *) outvalue; if(info == NULL) { /* outvalue must point to an apiinfo structure */ break; /* LDAP_OPT_ERROR */ } if(info->ldapai_info_version != LDAP_API_INFO_VERSION) { /* api info version mismatch */ info->ldapai_info_version = LDAP_API_INFO_VERSION; break; /* LDAP_OPT_ERROR */ } info->ldapai_api_version = LDAP_API_VERSION; info->ldapai_protocol_version = LDAP_VERSION_MAX; if(features[0].ldapaif_name == NULL) { info->ldapai_extensions = NULL; } else { int i; info->ldapai_extensions = LDAP_MALLOC(sizeof(char *) * sizeof(features)/sizeof(LDAPAPIFeatureInfo)); for(i=0; features[i].ldapaif_name != NULL; i++) { info->ldapai_extensions[i] = LDAP_STRDUP(features[i].ldapaif_name); } info->ldapai_extensions[i] = NULL; } info->ldapai_vendor_name = LDAP_STRDUP(LDAP_VENDOR_NAME); info->ldapai_vendor_version = LDAP_VENDOR_VERSION; rc = LDAP_OPT_SUCCESS; break; } break; case LDAP_OPT_DESC: if( ld == NULL || ld->ld_sb == NULL ) { /* bad param */ break; } ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, outvalue ); rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_SOCKBUF: if( ld == NULL ) break; *(Sockbuf **)outvalue = ld->ld_sb; rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_TIMEOUT: /* the caller has to free outvalue ! */ if ( lo->ldo_tm_api.tv_sec < 0 ) { *(void **)outvalue = NULL; } else if ( ldap_int_timeval_dup( outvalue, &lo->ldo_tm_api ) != 0 ) { break; /* LDAP_OPT_ERROR */ } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_NETWORK_TIMEOUT: /* the caller has to free outvalue ! */ if ( lo->ldo_tm_net.tv_sec < 0 ) { *(void **)outvalue = NULL; } else if ( ldap_int_timeval_dup( outvalue, &lo->ldo_tm_net ) != 0 ) { break; /* LDAP_OPT_ERROR */ } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_DEREF: * (int *) outvalue = lo->ldo_deref; rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_SIZELIMIT: * (int *) outvalue = lo->ldo_sizelimit; rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_TIMELIMIT: * (int *) outvalue = lo->ldo_timelimit; rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_REFERRALS: * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_REFERRALS); rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_RESTART: * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_RESTART); rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_PROTOCOL_VERSION: * (int *) outvalue = lo->ldo_version; rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_SERVER_CONTROLS: * (LDAPControl ***) outvalue = ldap_controls_dup( lo->ldo_sctrls ); rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_CLIENT_CONTROLS: * (LDAPControl ***) outvalue = ldap_controls_dup( lo->ldo_cctrls ); rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_HOST_NAME: * (char **) outvalue = ldap_url_list2hosts(lo->ldo_defludp); rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_URI: * (char **) outvalue = ldap_url_list2urls(lo->ldo_defludp); rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_DEFBASE: if( lo->ldo_defbase == NULL ) { * (char **) outvalue = NULL; } else { * (char **) outvalue = LDAP_STRDUP(lo->ldo_defbase); } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_CONNECT_ASYNC: * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_CONNECT_ASYNC); rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_CONNECT_CB: { /* Getting deletes the specified callback */ ldaplist **ll = &lo->ldo_conn_cbs; for (;*ll;ll = &(*ll)->ll_next) { if ((*ll)->ll_data == outvalue) { ldaplist *lc = *ll; *ll = lc->ll_next; LDAP_FREE(lc); break; } } } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_RESULT_CODE: if(ld == NULL) { /* bad param */ break; } * (int *) outvalue = ld->ld_errno; rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_DIAGNOSTIC_MESSAGE: if(ld == NULL) { /* bad param */ break; } if( ld->ld_error == NULL ) { * (char **) outvalue = NULL; } else { * (char **) outvalue = LDAP_STRDUP(ld->ld_error); } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_MATCHED_DN: if(ld == NULL) { /* bad param */ break; } if( ld->ld_matched == NULL ) { * (char **) outvalue = NULL; } else { * (char **) outvalue = LDAP_STRDUP( ld->ld_matched ); } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_REFERRAL_URLS: if(ld == NULL) { /* bad param */ break; } if( ld->ld_referrals == NULL ) { * (char ***) outvalue = NULL; } else { * (char ***) outvalue = ldap_value_dup(ld->ld_referrals); } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_API_FEATURE_INFO: { LDAPAPIFeatureInfo *info = (LDAPAPIFeatureInfo *) outvalue; int i; if(info == NULL) break; /* LDAP_OPT_ERROR */ if(info->ldapaif_info_version != LDAP_FEATURE_INFO_VERSION) { /* api info version mismatch */ info->ldapaif_info_version = LDAP_FEATURE_INFO_VERSION; break; /* LDAP_OPT_ERROR */ } if(info->ldapaif_name == NULL) break; /* LDAP_OPT_ERROR */ for(i=0; features[i].ldapaif_name != NULL; i++) { if(!strcmp(info->ldapaif_name, features[i].ldapaif_name)) { info->ldapaif_version = features[i].ldapaif_version; rc = LDAP_OPT_SUCCESS; break; } } } break; case LDAP_OPT_DEBUG_LEVEL: * (int *) outvalue = lo->ldo_debug; rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_SESSION_REFCNT: if(ld == NULL) { /* bad param */ break; } LDAP_MUTEX_LOCK( &ld->ld_ldcmutex ); * (int *) outvalue = ld->ld_ldcrefcnt; LDAP_MUTEX_UNLOCK( &ld->ld_ldcmutex ); rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_X_KEEPALIVE_IDLE: * (int *) outvalue = lo->ldo_keepalive_idle; rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_X_KEEPALIVE_PROBES: * (int *) outvalue = lo->ldo_keepalive_probes; rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_X_KEEPALIVE_INTERVAL: * (int *) outvalue = lo->ldo_keepalive_interval; rc = LDAP_OPT_SUCCESS; break; default: #ifdef HAVE_TLS if ( ldap_pvt_tls_get_option( ld, option, outvalue ) == 0 ) { rc = LDAP_OPT_SUCCESS; break; } #endif #ifdef HAVE_CYRUS_SASL if ( ldap_int_sasl_get_option( ld, option, outvalue ) == 0 ) { rc = LDAP_OPT_SUCCESS; break; } #endif #ifdef HAVE_GSSAPI if ( ldap_int_gssapi_get_option( ld, option, outvalue ) == 0 ) { rc = LDAP_OPT_SUCCESS; break; } #endif /* bad param */ break; } LDAP_MUTEX_UNLOCK( &lo->ldo_mutex ); return ( rc ); } int ldap_set_option( LDAP *ld, int option, LDAP_CONST void *invalue) { struct ldapoptions *lo; int *dbglvl = NULL; int rc = LDAP_OPT_ERROR; /* Get pointer to global option structure */ lo = LDAP_INT_GLOBAL_OPT(); if (lo == NULL) { return LDAP_NO_MEMORY; } /* * The architecture to turn on debugging has a chicken and egg * problem. Thus, we introduce a fix here. */ if (option == LDAP_OPT_DEBUG_LEVEL) { dbglvl = (int *) invalue; } if( lo->ldo_valid != LDAP_INITIALIZED ) { ldap_int_initialize(lo, dbglvl); } if(ld != NULL) { assert( LDAP_VALID( ld ) ); if( !LDAP_VALID( ld ) ) { return LDAP_OPT_ERROR; } lo = &ld->ld_options; } LDAP_MUTEX_LOCK( &lo->ldo_mutex ); switch ( option ) { /* options with boolean values */ case LDAP_OPT_REFERRALS: if(invalue == LDAP_OPT_OFF) { LDAP_BOOL_CLR(lo, LDAP_BOOL_REFERRALS); } else { LDAP_BOOL_SET(lo, LDAP_BOOL_REFERRALS); } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_RESTART: if(invalue == LDAP_OPT_OFF) { LDAP_BOOL_CLR(lo, LDAP_BOOL_RESTART); } else { LDAP_BOOL_SET(lo, LDAP_BOOL_RESTART); } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_CONNECT_ASYNC: if(invalue == LDAP_OPT_OFF) { LDAP_BOOL_CLR(lo, LDAP_BOOL_CONNECT_ASYNC); } else { LDAP_BOOL_SET(lo, LDAP_BOOL_CONNECT_ASYNC); } rc = LDAP_OPT_SUCCESS; break; /* options which can withstand invalue == NULL */ case LDAP_OPT_SERVER_CONTROLS: { LDAPControl *const *controls = (LDAPControl *const *) invalue; if( lo->ldo_sctrls ) ldap_controls_free( lo->ldo_sctrls ); if( controls == NULL || *controls == NULL ) { lo->ldo_sctrls = NULL; rc = LDAP_OPT_SUCCESS; break; } lo->ldo_sctrls = ldap_controls_dup( controls ); if(lo->ldo_sctrls == NULL) { /* memory allocation error ? */ break; /* LDAP_OPT_ERROR */ } } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_CLIENT_CONTROLS: { LDAPControl *const *controls = (LDAPControl *const *) invalue; if( lo->ldo_cctrls ) ldap_controls_free( lo->ldo_cctrls ); if( controls == NULL || *controls == NULL ) { lo->ldo_cctrls = NULL; rc = LDAP_OPT_SUCCESS; break; } lo->ldo_cctrls = ldap_controls_dup( controls ); if(lo->ldo_cctrls == NULL) { /* memory allocation error ? */ break; /* LDAP_OPT_ERROR */ } } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_HOST_NAME: { const char *host = (const char *) invalue; LDAPURLDesc *ludlist = NULL; rc = LDAP_OPT_SUCCESS; if(host != NULL) { rc = ldap_url_parsehosts( &ludlist, host, lo->ldo_defport ? lo->ldo_defport : LDAP_PORT ); } else if(ld == NULL) { /* * must want global default returned * to initial condition. */ rc = ldap_url_parselist_ext(&ludlist, "ldap://localhost/", NULL, LDAP_PVT_URL_PARSE_NOEMPTY_HOST | LDAP_PVT_URL_PARSE_DEF_PORT ); } else { /* * must want the session default * updated to the current global default */ ludlist = ldap_url_duplist( ldap_int_global_options.ldo_defludp); if (ludlist == NULL) rc = LDAP_NO_MEMORY; } if (rc == LDAP_OPT_SUCCESS) { if (lo->ldo_defludp != NULL) ldap_free_urllist(lo->ldo_defludp); lo->ldo_defludp = ludlist; } break; } case LDAP_OPT_URI: { const char *urls = (const char *) invalue; LDAPURLDesc *ludlist = NULL; rc = LDAP_OPT_SUCCESS; if(urls != NULL) { rc = ldap_url_parselist_ext(&ludlist, urls, NULL, LDAP_PVT_URL_PARSE_NOEMPTY_HOST | LDAP_PVT_URL_PARSE_DEF_PORT ); } else if(ld == NULL) { /* * must want global default returned * to initial condition. */ rc = ldap_url_parselist_ext(&ludlist, "ldap://localhost/", NULL, LDAP_PVT_URL_PARSE_NOEMPTY_HOST | LDAP_PVT_URL_PARSE_DEF_PORT ); } else { /* * must want the session default * updated to the current global default */ ludlist = ldap_url_duplist( ldap_int_global_options.ldo_defludp); if (ludlist == NULL) rc = LDAP_URL_ERR_MEM; } switch (rc) { case LDAP_URL_SUCCESS: /* Success */ rc = LDAP_SUCCESS; break; case LDAP_URL_ERR_MEM: /* can't allocate memory space */ rc = LDAP_NO_MEMORY; break; case LDAP_URL_ERR_PARAM: /* parameter is bad */ case LDAP_URL_ERR_BADSCHEME: /* URL doesn't begin with "ldap[si]://" */ case LDAP_URL_ERR_BADENCLOSURE: /* URL is missing trailing ">" */ case LDAP_URL_ERR_BADURL: /* URL is bad */ case LDAP_URL_ERR_BADHOST: /* host port is bad */ case LDAP_URL_ERR_BADATTRS: /* bad (or missing) attributes */ case LDAP_URL_ERR_BADSCOPE: /* scope string is invalid (or missing) */ case LDAP_URL_ERR_BADFILTER: /* bad or missing filter */ case LDAP_URL_ERR_BADEXTS: /* bad or missing extensions */ rc = LDAP_PARAM_ERROR; break; } if (rc == LDAP_SUCCESS) { if (lo->ldo_defludp != NULL) ldap_free_urllist(lo->ldo_defludp); lo->ldo_defludp = ludlist; } break; } case LDAP_OPT_DEFBASE: { const char *newbase = (const char *) invalue; char *defbase = NULL; if ( newbase != NULL ) { defbase = LDAP_STRDUP( newbase ); if ( defbase == NULL ) { rc = LDAP_NO_MEMORY; break; } } else if ( ld != NULL ) { defbase = LDAP_STRDUP( ldap_int_global_options.ldo_defbase ); if ( defbase == NULL ) { rc = LDAP_NO_MEMORY; break; } } if ( lo->ldo_defbase != NULL ) LDAP_FREE( lo->ldo_defbase ); lo->ldo_defbase = defbase; } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_DIAGNOSTIC_MESSAGE: { const char *err = (const char *) invalue; if(ld == NULL) { /* need a struct ldap */ break; /* LDAP_OPT_ERROR */ } if( ld->ld_error ) { LDAP_FREE(ld->ld_error); ld->ld_error = NULL; } if ( err ) { ld->ld_error = LDAP_STRDUP(err); } } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_MATCHED_DN: { const char *matched = (const char *) invalue; if (ld == NULL) { /* need a struct ldap */ break; /* LDAP_OPT_ERROR */ } if( ld->ld_matched ) { LDAP_FREE(ld->ld_matched); ld->ld_matched = NULL; } if ( matched ) { ld->ld_matched = LDAP_STRDUP( matched ); } } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_REFERRAL_URLS: { char *const *referrals = (char *const *) invalue; if(ld == NULL) { /* need a struct ldap */ break; /* LDAP_OPT_ERROR */ } if( ld->ld_referrals ) { LDAP_VFREE(ld->ld_referrals); } if ( referrals ) { ld->ld_referrals = ldap_value_dup(referrals); } } rc = LDAP_OPT_SUCCESS; break; /* Only accessed from inside this function by ldap_set_rebind_proc() */ case LDAP_OPT_REBIND_PROC: { lo->ldo_rebind_proc = (LDAP_REBIND_PROC *)invalue; } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_REBIND_PARAMS: { lo->ldo_rebind_params = (void *)invalue; } rc = LDAP_OPT_SUCCESS; break; /* Only accessed from inside this function by ldap_set_nextref_proc() */ case LDAP_OPT_NEXTREF_PROC: { lo->ldo_nextref_proc = (LDAP_NEXTREF_PROC *)invalue; } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_NEXTREF_PARAMS: { lo->ldo_nextref_params = (void *)invalue; } rc = LDAP_OPT_SUCCESS; break; /* Only accessed from inside this function by ldap_set_urllist_proc() */ case LDAP_OPT_URLLIST_PROC: { lo->ldo_urllist_proc = (LDAP_URLLIST_PROC *)invalue; } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_URLLIST_PARAMS: { lo->ldo_urllist_params = (void *)invalue; } rc = LDAP_OPT_SUCCESS; break; /* read-only options */ case LDAP_OPT_API_INFO: case LDAP_OPT_DESC: case LDAP_OPT_SOCKBUF: case LDAP_OPT_API_FEATURE_INFO: break; /* LDAP_OPT_ERROR */ /* options which cannot withstand invalue == NULL */ case LDAP_OPT_DEREF: case LDAP_OPT_SIZELIMIT: case LDAP_OPT_TIMELIMIT: case LDAP_OPT_PROTOCOL_VERSION: case LDAP_OPT_RESULT_CODE: case LDAP_OPT_DEBUG_LEVEL: case LDAP_OPT_TIMEOUT: case LDAP_OPT_NETWORK_TIMEOUT: case LDAP_OPT_CONNECT_CB: case LDAP_OPT_X_KEEPALIVE_IDLE: case LDAP_OPT_X_KEEPALIVE_PROBES : case LDAP_OPT_X_KEEPALIVE_INTERVAL : if(invalue == NULL) { /* no place to set from */ LDAP_MUTEX_UNLOCK( &lo->ldo_mutex ); return ( LDAP_OPT_ERROR ); } break; default: #ifdef HAVE_TLS if ( ldap_pvt_tls_set_option( ld, option, (void *)invalue ) == 0 ) { LDAP_MUTEX_UNLOCK( &lo->ldo_mutex ); return ( LDAP_OPT_SUCCESS ); } #endif #ifdef HAVE_CYRUS_SASL if ( ldap_int_sasl_set_option( ld, option, (void *)invalue ) == 0 ) { LDAP_MUTEX_UNLOCK( &lo->ldo_mutex ); return ( LDAP_OPT_SUCCESS ); } #endif #ifdef HAVE_GSSAPI if ( ldap_int_gssapi_set_option( ld, option, (void *)invalue ) == 0 ) { LDAP_MUTEX_UNLOCK( &lo->ldo_mutex ); return ( LDAP_OPT_SUCCESS ); } #endif /* bad param */ break; /* LDAP_OPT_ERROR */ } /* options which cannot withstand invalue == NULL */ switch(option) { case LDAP_OPT_DEREF: /* FIXME: check value for protocol compliance? */ lo->ldo_deref = * (const int *) invalue; rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_SIZELIMIT: /* FIXME: check value for protocol compliance? */ lo->ldo_sizelimit = * (const int *) invalue; rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_TIMELIMIT: /* FIXME: check value for protocol compliance? */ lo->ldo_timelimit = * (const int *) invalue; rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_TIMEOUT: { const struct timeval *tv = (const struct timeval *) invalue; lo->ldo_tm_api = *tv; } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_NETWORK_TIMEOUT: { const struct timeval *tv = (const struct timeval *) invalue; lo->ldo_tm_net = *tv; } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_PROTOCOL_VERSION: { int vers = * (const int *) invalue; if (vers < LDAP_VERSION_MIN || vers > LDAP_VERSION_MAX) { /* not supported */ break; } lo->ldo_version = vers; } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_RESULT_CODE: { int err = * (const int *) invalue; if(ld == NULL) { /* need a struct ldap */ break; } ld->ld_errno = err; } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_DEBUG_LEVEL: lo->ldo_debug = * (const int *) invalue; rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_CONNECT_CB: { /* setting pushes the callback */ ldaplist *ll; ll = LDAP_MALLOC( sizeof( *ll )); ll->ll_data = (void *)invalue; ll->ll_next = lo->ldo_conn_cbs; lo->ldo_conn_cbs = ll; } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_X_KEEPALIVE_IDLE: lo->ldo_keepalive_idle = * (const int *) invalue; rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_X_KEEPALIVE_PROBES : lo->ldo_keepalive_probes = * (const int *) invalue; rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_X_KEEPALIVE_INTERVAL : lo->ldo_keepalive_interval = * (const int *) invalue; rc = LDAP_OPT_SUCCESS; break; } LDAP_MUTEX_UNLOCK( &lo->ldo_mutex ); return ( rc ); } int ldap_set_rebind_proc( LDAP *ld, LDAP_REBIND_PROC *proc, void *params ) { int rc; rc = ldap_set_option( ld, LDAP_OPT_REBIND_PROC, (void *)proc ); if( rc != LDAP_OPT_SUCCESS ) return rc; rc = ldap_set_option( ld, LDAP_OPT_REBIND_PARAMS, (void *)params ); return rc; } int ldap_set_nextref_proc( LDAP *ld, LDAP_NEXTREF_PROC *proc, void *params ) { int rc; rc = ldap_set_option( ld, LDAP_OPT_NEXTREF_PROC, (void *)proc ); if( rc != LDAP_OPT_SUCCESS ) return rc; rc = ldap_set_option( ld, LDAP_OPT_NEXTREF_PARAMS, (void *)params ); return rc; } int ldap_set_urllist_proc( LDAP *ld, LDAP_URLLIST_PROC *proc, void *params ) { int rc; rc = ldap_set_option( ld, LDAP_OPT_URLLIST_PROC, (void *)proc ); if( rc != LDAP_OPT_SUCCESS ) return rc; rc = ldap_set_option( ld, LDAP_OPT_URLLIST_PARAMS, (void *)params ); return rc; } openldap-2.4.42+dfsg/libraries/libldap/ldap.conf0000644000175000017500000000036512563404150020206 0ustar ryanryan# # LDAP Defaults # # See ldap.conf(5) for details # This file should be world readable but not world writable. #BASE dc=example,dc=com #URI ldap://ldap.example.com ldap://ldap-master.example.com:666 #SIZELIMIT 12 #TIMELIMIT 15 #DEREF never openldap-2.4.42+dfsg/libraries/libldap/ldap-tls.h0000644000175000017500000000445112563404150020310 0ustar ryanryan/* ldap-tls.h - TLS defines & prototypes internal to the LDAP library */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 2008-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #ifndef _LDAP_TLS_H #define _LDAP_TLS_H 1 struct tls_impl; struct tls_ctx; struct tls_session; typedef struct tls_ctx tls_ctx; typedef struct tls_session tls_session; typedef int (TI_tls_init)(void); typedef void (TI_tls_destroy)(void); typedef tls_ctx *(TI_ctx_new)(struct ldapoptions *lo); typedef void (TI_ctx_ref)(tls_ctx *ctx); typedef void (TI_ctx_free)(tls_ctx *ctx); typedef int (TI_ctx_init)(struct ldapoptions *lo, struct ldaptls *lt, int is_server); typedef tls_session *(TI_session_new)(tls_ctx *ctx, int is_server); typedef int (TI_session_connect)(LDAP *ld, tls_session *s); typedef int (TI_session_accept)(tls_session *s); typedef int (TI_session_upflags)(Sockbuf *sb, tls_session *s, int rc); typedef char *(TI_session_errmsg)(tls_session *s, int rc, char *buf, size_t len ); typedef int (TI_session_dn)(tls_session *sess, struct berval *dn); typedef int (TI_session_chkhost)(LDAP *ld, tls_session *s, const char *name_in); typedef int (TI_session_strength)(tls_session *sess); typedef void (TI_thr_init)(void); typedef struct tls_impl { const char *ti_name; TI_tls_init *ti_tls_init; /* library initialization */ TI_tls_destroy *ti_tls_destroy; TI_ctx_new *ti_ctx_new; TI_ctx_ref *ti_ctx_ref; TI_ctx_free *ti_ctx_free; TI_ctx_init *ti_ctx_init; TI_session_new *ti_session_new; TI_session_connect *ti_session_connect; TI_session_accept *ti_session_accept; TI_session_upflags *ti_session_upflags; TI_session_errmsg *ti_session_errmsg; TI_session_dn *ti_session_my_dn; TI_session_dn *ti_session_peer_dn; TI_session_chkhost *ti_session_chkhost; TI_session_strength *ti_session_strength; Sockbuf_IO *ti_sbio; TI_thr_init *ti_thr_init; int ti_inited; } tls_impl; extern tls_impl ldap_int_tls_impl; #endif /* _LDAP_TLS_H */ openldap-2.4.42+dfsg/libraries/libldap/url.c0000644000175000017500000007136412563404150017374 0ustar ryanryan/* LIBLDAP url.c -- LDAP URL (RFC 4516) related routines */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (c) 1996 Regents of the University of Michigan. * All rights reserved. */ /* * LDAP URLs look like this: * ldap[is]://host[:port][/[dn[?[attributes][?[scope][?[filter][?exts]]]]]] * * where: * attributes is a comma separated list * scope is one of these three strings: base one sub (default=base) * filter is an string-represented filter as in RFC 4515 * * e.g., ldap://host:port/dc=com?o,cn?base?(o=openldap)?extension * * We also tolerate URLs that look like: and */ #include "portable.h" #include #include #include #include #include #include #include "ldap-int.h" /* local functions */ static const char* skip_url_prefix LDAP_P(( const char *url, int *enclosedp, const char **scheme )); int ldap_pvt_url_scheme2proto( const char *scheme ) { assert( scheme != NULL ); if( scheme == NULL ) { return -1; } if( strcmp("ldap", scheme) == 0 ) { return LDAP_PROTO_TCP; } if( strcmp("ldapi", scheme) == 0 ) { return LDAP_PROTO_IPC; } if( strcmp("ldaps", scheme) == 0 ) { return LDAP_PROTO_TCP; } #ifdef LDAP_CONNECTIONLESS if( strcmp("cldap", scheme) == 0 ) { return LDAP_PROTO_UDP; } #endif return -1; } int ldap_pvt_url_scheme_port( const char *scheme, int port ) { assert( scheme != NULL ); if( port ) return port; if( scheme == NULL ) return port; if( strcmp("ldap", scheme) == 0 ) { return LDAP_PORT; } if( strcmp("ldapi", scheme) == 0 ) { return -1; } if( strcmp("ldaps", scheme) == 0 ) { return LDAPS_PORT; } #ifdef LDAP_CONNECTIONLESS if( strcmp("cldap", scheme) == 0 ) { return LDAP_PORT; } #endif return -1; } int ldap_pvt_url_scheme2tls( const char *scheme ) { assert( scheme != NULL ); if( scheme == NULL ) { return -1; } return strcmp("ldaps", scheme) == 0; } int ldap_is_ldap_url( LDAP_CONST char *url ) { int enclosed; const char * scheme; if( url == NULL ) { return 0; } if( skip_url_prefix( url, &enclosed, &scheme ) == NULL ) { return 0; } return 1; } int ldap_is_ldaps_url( LDAP_CONST char *url ) { int enclosed; const char * scheme; if( url == NULL ) { return 0; } if( skip_url_prefix( url, &enclosed, &scheme ) == NULL ) { return 0; } return strcmp(scheme, "ldaps") == 0; } int ldap_is_ldapi_url( LDAP_CONST char *url ) { int enclosed; const char * scheme; if( url == NULL ) { return 0; } if( skip_url_prefix( url, &enclosed, &scheme ) == NULL ) { return 0; } return strcmp(scheme, "ldapi") == 0; } #ifdef LDAP_CONNECTIONLESS int ldap_is_ldapc_url( LDAP_CONST char *url ) { int enclosed; const char * scheme; if( url == NULL ) { return 0; } if( skip_url_prefix( url, &enclosed, &scheme ) == NULL ) { return 0; } return strcmp(scheme, "cldap") == 0; } #endif static const char* skip_url_prefix( const char *url, int *enclosedp, const char **scheme ) { /* * return non-zero if this looks like a LDAP URL; zero if not * if non-zero returned, *urlp will be moved past "ldap://" part of URL */ const char *p; if ( url == NULL ) { return( NULL ); } p = url; /* skip leading '<' (if any) */ if ( *p == '<' ) { *enclosedp = 1; ++p; } else { *enclosedp = 0; } /* skip leading "URL:" (if any) */ if ( strncasecmp( p, LDAP_URL_URLCOLON, LDAP_URL_URLCOLON_LEN ) == 0 ) { p += LDAP_URL_URLCOLON_LEN; } /* check for "ldap://" prefix */ if ( strncasecmp( p, LDAP_URL_PREFIX, LDAP_URL_PREFIX_LEN ) == 0 ) { /* skip over "ldap://" prefix and return success */ p += LDAP_URL_PREFIX_LEN; *scheme = "ldap"; return( p ); } /* check for "ldaps://" prefix */ if ( strncasecmp( p, LDAPS_URL_PREFIX, LDAPS_URL_PREFIX_LEN ) == 0 ) { /* skip over "ldaps://" prefix and return success */ p += LDAPS_URL_PREFIX_LEN; *scheme = "ldaps"; return( p ); } /* check for "ldapi://" prefix */ if ( strncasecmp( p, LDAPI_URL_PREFIX, LDAPI_URL_PREFIX_LEN ) == 0 ) { /* skip over "ldapi://" prefix and return success */ p += LDAPI_URL_PREFIX_LEN; *scheme = "ldapi"; return( p ); } #ifdef LDAP_CONNECTIONLESS /* check for "cldap://" prefix */ if ( strncasecmp( p, LDAPC_URL_PREFIX, LDAPC_URL_PREFIX_LEN ) == 0 ) { /* skip over "cldap://" prefix and return success */ p += LDAPC_URL_PREFIX_LEN; *scheme = "cldap"; return( p ); } #endif return( NULL ); } int ldap_pvt_scope2bv( int scope, struct berval *bv ) { switch ( scope ) { case LDAP_SCOPE_BASE: BER_BVSTR( bv, "base" ); break; case LDAP_SCOPE_ONELEVEL: BER_BVSTR( bv, "one" ); break; case LDAP_SCOPE_SUBTREE: BER_BVSTR( bv, "sub" ); break; case LDAP_SCOPE_SUBORDINATE: BER_BVSTR( bv, "subordinate" ); break; default: return LDAP_OTHER; } return LDAP_SUCCESS; } const char * ldap_pvt_scope2str( int scope ) { struct berval bv; if ( ldap_pvt_scope2bv( scope, &bv ) == LDAP_SUCCESS ) { return bv.bv_val; } return NULL; } int ldap_pvt_bv2scope( struct berval *bv ) { static struct { struct berval bv; int scope; } v[] = { { BER_BVC( "one" ), LDAP_SCOPE_ONELEVEL }, { BER_BVC( "onelevel" ), LDAP_SCOPE_ONELEVEL }, { BER_BVC( "base" ), LDAP_SCOPE_BASE }, { BER_BVC( "sub" ), LDAP_SCOPE_SUBTREE }, { BER_BVC( "subtree" ), LDAP_SCOPE_SUBTREE }, { BER_BVC( "subord" ), LDAP_SCOPE_SUBORDINATE }, { BER_BVC( "subordinate" ), LDAP_SCOPE_SUBORDINATE }, { BER_BVC( "children" ), LDAP_SCOPE_SUBORDINATE }, { BER_BVNULL, -1 } }; int i; for ( i = 0; v[ i ].scope != -1; i++ ) { if ( ber_bvstrcasecmp( bv, &v[ i ].bv ) == 0 ) { return v[ i ].scope; } } return( -1 ); } int ldap_pvt_str2scope( const char *p ) { struct berval bv; ber_str2bv( p, 0, 0, &bv ); return ldap_pvt_bv2scope( &bv ); } static const char hex[] = "0123456789ABCDEF"; #define URLESC_NONE 0x0000U #define URLESC_COMMA 0x0001U #define URLESC_SLASH 0x0002U static int hex_escape_len( const char *s, unsigned list ) { int len; if ( s == NULL ) { return 0; } for ( len = 0; s[0]; s++ ) { switch ( s[0] ) { /* RFC 2396: reserved */ case '?': len += 3; break; case ',': if ( list & URLESC_COMMA ) { len += 3; } else { len++; } break; case '/': if ( list & URLESC_SLASH ) { len += 3; } else { len++; } break; case ';': case ':': case '@': case '&': case '=': case '+': case '$': /* RFC 2396: unreserved mark */ case '-': case '_': case '.': case '!': case '~': case '*': case '\'': case '(': case ')': len++; break; /* RFC 2396: unreserved alphanum */ default: if ( !isalnum( (unsigned char) s[0] ) ) { len += 3; } else { len++; } break; } } return len; } static int hex_escape( char *buf, int len, const char *s, unsigned list ) { int i; int pos; if ( s == NULL ) { return 0; } for ( pos = 0, i = 0; s[i] && pos < len; i++ ) { int escape = 0; switch ( s[i] ) { /* RFC 2396: reserved */ case '?': escape = 1; break; case ',': if ( list & URLESC_COMMA ) { escape = 1; } break; case '/': if ( list & URLESC_SLASH ) { escape = 1; } break; case ';': case ':': case '@': case '&': case '=': case '+': case '$': /* RFC 2396: unreserved mark */ case '-': case '_': case '.': case '!': case '~': case '*': case '\'': case '(': case ')': break; /* RFC 2396: unreserved alphanum */ default: if ( !isalnum( (unsigned char) s[i] ) ) { escape = 1; } break; } if ( escape ) { buf[pos++] = '%'; buf[pos++] = hex[ (s[i] >> 4) & 0x0f ]; buf[pos++] = hex[ s[i] & 0x0f ]; } else { buf[pos++] = s[i]; } } buf[pos] = '\0'; return pos; } static int hex_escape_len_list( char **s, unsigned flags ) { int len; int i; if ( s == NULL ) { return 0; } len = 0; for ( i = 0; s[i] != NULL; i++ ) { if ( len ) { len++; } len += hex_escape_len( s[i], flags ); } return len; } static int hex_escape_list( char *buf, int len, char **s, unsigned flags ) { int pos; int i; if ( s == NULL ) { return 0; } pos = 0; for ( i = 0; s[i] != NULL; i++ ) { int curlen; if ( pos ) { buf[pos++] = ','; len--; } curlen = hex_escape( &buf[pos], len, s[i], flags ); len -= curlen; pos += curlen; } return pos; } static int desc2str_len( LDAPURLDesc *u ) { int sep = 0; int len = 0; int is_ipc = 0; struct berval scope; if ( u == NULL || u->lud_scheme == NULL ) { return -1; } if ( !strcmp( "ldapi", u->lud_scheme )) { is_ipc = 1; } if ( u->lud_exts ) { len += hex_escape_len_list( u->lud_exts, URLESC_COMMA ); if ( !sep ) { sep = 5; } } if ( u->lud_filter ) { len += hex_escape_len( u->lud_filter, URLESC_NONE ); if ( !sep ) { sep = 4; } } if ( ldap_pvt_scope2bv( u->lud_scope, &scope ) == LDAP_SUCCESS ) { len += scope.bv_len; if ( !sep ) { sep = 3; } } if ( u->lud_attrs ) { len += hex_escape_len_list( u->lud_attrs, URLESC_NONE ); if ( !sep ) { sep = 2; } } if ( u->lud_dn && u->lud_dn[0] ) { len += hex_escape_len( u->lud_dn, URLESC_NONE ); if ( !sep ) { sep = 1; } }; len += sep; if ( u->lud_port ) { unsigned p = u->lud_port; if ( p > 65535 ) return -1; len += (p > 999 ? 5 + (p > 9999) : p > 99 ? 4 : 2 + (p > 9)); } if ( u->lud_host && u->lud_host[0] ) { char *ptr; len += hex_escape_len( u->lud_host, URLESC_SLASH ); if ( !is_ipc && ( ptr = strchr( u->lud_host, ':' ))) { if ( strchr( ptr+1, ':' )) len += 2; /* IPv6, [] */ } } len += strlen( u->lud_scheme ) + STRLENOF( "://" ); return len; } static int desc2str( LDAPURLDesc *u, char *s, int len ) { int i; int sep = 0; int sofar = 0; int is_v6 = 0; int is_ipc = 0; struct berval scope = BER_BVNULL; char *ptr; if ( u == NULL ) { return -1; } if ( s == NULL ) { return -1; } if ( u->lud_scheme && !strcmp( "ldapi", u->lud_scheme )) { is_ipc = 1; } ldap_pvt_scope2bv( u->lud_scope, &scope ); if ( u->lud_exts ) { sep = 5; } else if ( u->lud_filter ) { sep = 4; } else if ( !BER_BVISEMPTY( &scope ) ) { sep = 3; } else if ( u->lud_attrs ) { sep = 2; } else if ( u->lud_dn && u->lud_dn[0] ) { sep = 1; } if ( !is_ipc && u->lud_host && ( ptr = strchr( u->lud_host, ':' ))) { if ( strchr( ptr+1, ':' )) is_v6 = 1; } if ( u->lud_port ) { sofar = sprintf( s, "%s://%s%s%s:%d", u->lud_scheme, is_v6 ? "[" : "", u->lud_host ? u->lud_host : "", is_v6 ? "]" : "", u->lud_port ); len -= sofar; } else { sofar = sprintf( s, "%s://", u->lud_scheme ); len -= sofar; if ( u->lud_host && u->lud_host[0] ) { if ( is_v6 ) { s[sofar++] = '['; len--; } i = hex_escape( &s[sofar], len, u->lud_host, URLESC_SLASH ); sofar += i; len -= i; if ( is_v6 ) { s[sofar++] = ']'; len--; } } } assert( len >= 0 ); if ( sep < 1 ) { goto done; } s[sofar++] = '/'; len--; assert( len >= 0 ); if ( u->lud_dn && u->lud_dn[0] ) { i = hex_escape( &s[sofar], len, u->lud_dn, URLESC_NONE ); sofar += i; len -= i; assert( len >= 0 ); } if ( sep < 2 ) { goto done; } s[sofar++] = '?'; len--; assert( len >= 0 ); i = hex_escape_list( &s[sofar], len, u->lud_attrs, URLESC_NONE ); sofar += i; len -= i; assert( len >= 0 ); if ( sep < 3 ) { goto done; } s[sofar++] = '?'; len--; assert( len >= 0 ); if ( !BER_BVISNULL( &scope ) ) { strcpy( &s[sofar], scope.bv_val ); sofar += scope.bv_len; len -= scope.bv_len; } assert( len >= 0 ); if ( sep < 4 ) { goto done; } s[sofar++] = '?'; len--; assert( len >= 0 ); i = hex_escape( &s[sofar], len, u->lud_filter, URLESC_NONE ); sofar += i; len -= i; assert( len >= 0 ); if ( sep < 5 ) { goto done; } s[sofar++] = '?'; len--; assert( len >= 0 ); i = hex_escape_list( &s[sofar], len, u->lud_exts, URLESC_COMMA ); sofar += i; len -= i; assert( len >= 0 ); done: if ( len < 0 ) { return -1; } return sofar; } char * ldap_url_desc2str( LDAPURLDesc *u ) { int len; char *s; if ( u == NULL ) { return NULL; } len = desc2str_len( u ); if ( len < 0 ) { return NULL; } /* allocate enough to hex escape everything -- overkill */ s = LDAP_MALLOC( len + 1 ); if ( s == NULL ) { return NULL; } if ( desc2str( u, s, len ) != len ) { LDAP_FREE( s ); return NULL; } s[len] = '\0'; return s; } int ldap_url_parse_ext( LDAP_CONST char *url_in, LDAPURLDesc **ludpp, unsigned flags ) { /* * Pick apart the pieces of an LDAP URL. */ LDAPURLDesc *ludp; char *p, *q, *r; int i, enclosed, proto, is_v6 = 0; const char *scheme = NULL; const char *url_tmp; char *url; int check_dn = 1; if( url_in == NULL || ludpp == NULL ) { return LDAP_URL_ERR_PARAM; } #ifndef LDAP_INT_IN_KERNEL /* Global options may not be created yet * We can't test if the global options are initialized * because a call to LDAP_INT_GLOBAL_OPT() will try to allocate * the options and cause infinite recursion */ Debug( LDAP_DEBUG_TRACE, "ldap_url_parse_ext(%s)\n", url_in, 0, 0 ); #endif *ludpp = NULL; /* pessimistic */ url_tmp = skip_url_prefix( url_in, &enclosed, &scheme ); if ( url_tmp == NULL ) { return LDAP_URL_ERR_BADSCHEME; } assert( scheme != NULL ); proto = ldap_pvt_url_scheme2proto( scheme ); if ( proto == -1 ) { return LDAP_URL_ERR_BADSCHEME; } /* make working copy of the remainder of the URL */ url = LDAP_STRDUP( url_tmp ); if ( url == NULL ) { return LDAP_URL_ERR_MEM; } if ( enclosed ) { p = &url[strlen(url)-1]; if( *p != '>' ) { LDAP_FREE( url ); return LDAP_URL_ERR_BADENCLOSURE; } *p = '\0'; } /* allocate return struct */ ludp = (LDAPURLDesc *)LDAP_CALLOC( 1, sizeof( LDAPURLDesc )); if ( ludp == NULL ) { LDAP_FREE( url ); return LDAP_URL_ERR_MEM; } ludp->lud_next = NULL; ludp->lud_host = NULL; ludp->lud_port = 0; ludp->lud_dn = NULL; ludp->lud_attrs = NULL; ludp->lud_scope = ( flags & LDAP_PVT_URL_PARSE_NODEF_SCOPE ) ? LDAP_SCOPE_BASE : LDAP_SCOPE_DEFAULT; ludp->lud_filter = NULL; ludp->lud_exts = NULL; ludp->lud_scheme = LDAP_STRDUP( scheme ); if ( ludp->lud_scheme == NULL ) { LDAP_FREE( url ); ldap_free_urldesc( ludp ); return LDAP_URL_ERR_MEM; } /* scan forward for '/' that marks end of hostport and begin. of dn */ p = strchr( url, '/' ); q = NULL; if( p != NULL ) { /* terminate hostport; point to start of dn */ *p++ = '\0'; } else { /* check for Novell kludge, see below */ p = strchr( url, '?' ); if ( p ) { *p++ = '\0'; q = p; p = NULL; } } if ( proto != LDAP_PROTO_IPC ) { /* IPv6 syntax with [ip address]:port */ if ( *url == '[' ) { r = strchr( url, ']' ); if ( r == NULL ) { LDAP_FREE( url ); ldap_free_urldesc( ludp ); return LDAP_URL_ERR_BADURL; } *r++ = '\0'; q = strchr( r, ':' ); if ( q && q != r ) { LDAP_FREE( url ); ldap_free_urldesc( ludp ); return LDAP_URL_ERR_BADURL; } is_v6 = 1; } else { q = strchr( url, ':' ); } if ( q != NULL ) { char *next; *q++ = '\0'; ldap_pvt_hex_unescape( q ); if( *q == '\0' ) { LDAP_FREE( url ); ldap_free_urldesc( ludp ); return LDAP_URL_ERR_BADURL; } ludp->lud_port = strtol( q, &next, 10 ); if ( next == q || next[0] != '\0' ) { LDAP_FREE( url ); ldap_free_urldesc( ludp ); return LDAP_URL_ERR_BADURL; } /* check for Novell kludge */ if ( !p ) { if ( *next != '\0' ) { q = &next[1]; } else { q = NULL; } } } if ( ( flags & LDAP_PVT_URL_PARSE_DEF_PORT ) && ludp->lud_port == 0 ) { if ( strcmp( ludp->lud_scheme, "ldaps" ) == 0 ) { ludp->lud_port = LDAPS_PORT; } else { ludp->lud_port = LDAP_PORT; } } } ldap_pvt_hex_unescape( url ); /* If [ip address]:port syntax, url is [ip and we skip the [ */ ludp->lud_host = LDAP_STRDUP( url + is_v6 ); if( ludp->lud_host == NULL ) { LDAP_FREE( url ); ldap_free_urldesc( ludp ); return LDAP_URL_ERR_MEM; } if ( ( flags & LDAP_PVT_URL_PARSE_NOEMPTY_HOST ) && ludp->lud_host != NULL && *ludp->lud_host == '\0' ) { LDAP_FREE( ludp->lud_host ); ludp->lud_host = NULL; } /* * Kludge. ldap://111.222.333.444:389??cn=abc,o=company * * On early Novell releases, search references/referrals were returned * in this format, i.e., the dn was kind of in the scope position, * but the required slash is missing. The whole thing is illegal syntax, * but we need to account for it. Fortunately it can't be confused with * anything real. */ if( (p == NULL) && (q != NULL) && (*q == '?') ) { /* ? immediately followed by question */ q++; if( *q != '\0' ) { /* parse dn part */ ldap_pvt_hex_unescape( q ); ludp->lud_dn = LDAP_STRDUP( q ); } else if ( !( flags & LDAP_PVT_URL_PARSE_NOEMPTY_DN ) ) { ludp->lud_dn = LDAP_STRDUP( "" ); } else { check_dn = 0; } if ( check_dn && ludp->lud_dn == NULL ) { LDAP_FREE( url ); ldap_free_urldesc( ludp ); return LDAP_URL_ERR_MEM; } } if( p == NULL ) { LDAP_FREE( url ); *ludpp = ludp; return LDAP_URL_SUCCESS; } /* scan forward for '?' that may marks end of dn */ q = strchr( p, '?' ); if( q != NULL ) { /* terminate dn part */ *q++ = '\0'; } if( *p != '\0' ) { /* parse dn part */ ldap_pvt_hex_unescape( p ); ludp->lud_dn = LDAP_STRDUP( p ); } else if ( !( flags & LDAP_PVT_URL_PARSE_NOEMPTY_DN ) ) { ludp->lud_dn = LDAP_STRDUP( "" ); } else { check_dn = 0; } if( check_dn && ludp->lud_dn == NULL ) { LDAP_FREE( url ); ldap_free_urldesc( ludp ); return LDAP_URL_ERR_MEM; } if( q == NULL ) { /* no more */ LDAP_FREE( url ); *ludpp = ludp; return LDAP_URL_SUCCESS; } /* scan forward for '?' that may marks end of attributes */ p = q; q = strchr( p, '?' ); if( q != NULL ) { /* terminate attributes part */ *q++ = '\0'; } if( *p != '\0' ) { /* parse attributes */ ldap_pvt_hex_unescape( p ); ludp->lud_attrs = ldap_str2charray( p, "," ); if( ludp->lud_attrs == NULL ) { LDAP_FREE( url ); ldap_free_urldesc( ludp ); return LDAP_URL_ERR_BADATTRS; } } if ( q == NULL ) { /* no more */ LDAP_FREE( url ); *ludpp = ludp; return LDAP_URL_SUCCESS; } /* scan forward for '?' that may marks end of scope */ p = q; q = strchr( p, '?' ); if( q != NULL ) { /* terminate the scope part */ *q++ = '\0'; } if( *p != '\0' ) { /* parse the scope */ ldap_pvt_hex_unescape( p ); ludp->lud_scope = ldap_pvt_str2scope( p ); if( ludp->lud_scope == -1 ) { LDAP_FREE( url ); ldap_free_urldesc( ludp ); return LDAP_URL_ERR_BADSCOPE; } } if ( q == NULL ) { /* no more */ LDAP_FREE( url ); *ludpp = ludp; return LDAP_URL_SUCCESS; } /* scan forward for '?' that may marks end of filter */ p = q; q = strchr( p, '?' ); if( q != NULL ) { /* terminate the filter part */ *q++ = '\0'; } if( *p != '\0' ) { /* parse the filter */ ldap_pvt_hex_unescape( p ); if( ! *p ) { /* missing filter */ LDAP_FREE( url ); ldap_free_urldesc( ludp ); return LDAP_URL_ERR_BADFILTER; } ludp->lud_filter = LDAP_STRDUP( p ); if( ludp->lud_filter == NULL ) { LDAP_FREE( url ); ldap_free_urldesc( ludp ); return LDAP_URL_ERR_MEM; } } if ( q == NULL ) { /* no more */ LDAP_FREE( url ); *ludpp = ludp; return LDAP_URL_SUCCESS; } /* scan forward for '?' that may marks end of extensions */ p = q; q = strchr( p, '?' ); if( q != NULL ) { /* extra '?' */ LDAP_FREE( url ); ldap_free_urldesc( ludp ); return LDAP_URL_ERR_BADURL; } /* parse the extensions */ ludp->lud_exts = ldap_str2charray( p, "," ); if( ludp->lud_exts == NULL ) { LDAP_FREE( url ); ldap_free_urldesc( ludp ); return LDAP_URL_ERR_BADEXTS; } for( i=0; ludp->lud_exts[i] != NULL; i++ ) { ldap_pvt_hex_unescape( ludp->lud_exts[i] ); if( *ludp->lud_exts[i] == '!' ) { /* count the number of critical extensions */ ludp->lud_crit_exts++; } } if( i == 0 ) { /* must have 1 or more */ LDAP_FREE( url ); ldap_free_urldesc( ludp ); return LDAP_URL_ERR_BADEXTS; } /* no more */ *ludpp = ludp; LDAP_FREE( url ); return LDAP_URL_SUCCESS; } int ldap_url_parse( LDAP_CONST char *url_in, LDAPURLDesc **ludpp ) { return ldap_url_parse_ext( url_in, ludpp, LDAP_PVT_URL_PARSE_HISTORIC ); } LDAPURLDesc * ldap_url_dup ( LDAPURLDesc *ludp ) { LDAPURLDesc *dest; if ( ludp == NULL ) { return NULL; } dest = LDAP_MALLOC( sizeof(LDAPURLDesc) ); if (dest == NULL) return NULL; *dest = *ludp; dest->lud_scheme = NULL; dest->lud_host = NULL; dest->lud_dn = NULL; dest->lud_filter = NULL; dest->lud_attrs = NULL; dest->lud_exts = NULL; dest->lud_next = NULL; if ( ludp->lud_scheme != NULL ) { dest->lud_scheme = LDAP_STRDUP( ludp->lud_scheme ); if (dest->lud_scheme == NULL) { ldap_free_urldesc(dest); return NULL; } } if ( ludp->lud_host != NULL ) { dest->lud_host = LDAP_STRDUP( ludp->lud_host ); if (dest->lud_host == NULL) { ldap_free_urldesc(dest); return NULL; } } if ( ludp->lud_dn != NULL ) { dest->lud_dn = LDAP_STRDUP( ludp->lud_dn ); if (dest->lud_dn == NULL) { ldap_free_urldesc(dest); return NULL; } } if ( ludp->lud_filter != NULL ) { dest->lud_filter = LDAP_STRDUP( ludp->lud_filter ); if (dest->lud_filter == NULL) { ldap_free_urldesc(dest); return NULL; } } if ( ludp->lud_attrs != NULL ) { dest->lud_attrs = ldap_charray_dup( ludp->lud_attrs ); if (dest->lud_attrs == NULL) { ldap_free_urldesc(dest); return NULL; } } if ( ludp->lud_exts != NULL ) { dest->lud_exts = ldap_charray_dup( ludp->lud_exts ); if (dest->lud_exts == NULL) { ldap_free_urldesc(dest); return NULL; } } return dest; } LDAPURLDesc * ldap_url_duplist (LDAPURLDesc *ludlist) { LDAPURLDesc *dest, *tail, *ludp, *newludp; dest = NULL; tail = NULL; for (ludp = ludlist; ludp != NULL; ludp = ludp->lud_next) { newludp = ldap_url_dup(ludp); if (newludp == NULL) { ldap_free_urllist(dest); return NULL; } if (tail == NULL) dest = newludp; else tail->lud_next = newludp; tail = newludp; } return dest; } static int ldap_url_parselist_int (LDAPURLDesc **ludlist, const char *url, const char *sep, unsigned flags ) { int i, rc; LDAPURLDesc *ludp; char **urls; assert( ludlist != NULL ); assert( url != NULL ); *ludlist = NULL; if ( sep == NULL ) { sep = ", "; } urls = ldap_str2charray( url, sep ); if (urls == NULL) return LDAP_URL_ERR_MEM; /* count the URLs... */ for (i = 0; urls[i] != NULL; i++) ; /* ...and put them in the "stack" backward */ while (--i >= 0) { rc = ldap_url_parse_ext( urls[i], &ludp, flags ); if ( rc != 0 ) { ldap_charray_free( urls ); ldap_free_urllist( *ludlist ); *ludlist = NULL; return rc; } ludp->lud_next = *ludlist; *ludlist = ludp; } ldap_charray_free( urls ); return LDAP_URL_SUCCESS; } int ldap_url_parselist (LDAPURLDesc **ludlist, const char *url ) { return ldap_url_parselist_int( ludlist, url, ", ", LDAP_PVT_URL_PARSE_HISTORIC ); } int ldap_url_parselist_ext (LDAPURLDesc **ludlist, const char *url, const char *sep, unsigned flags ) { return ldap_url_parselist_int( ludlist, url, sep, flags ); } int ldap_url_parsehosts( LDAPURLDesc **ludlist, const char *hosts, int port ) { int i; LDAPURLDesc *ludp; char **specs, *p; assert( ludlist != NULL ); assert( hosts != NULL ); *ludlist = NULL; specs = ldap_str2charray(hosts, ", "); if (specs == NULL) return LDAP_NO_MEMORY; /* count the URLs... */ for (i = 0; specs[i] != NULL; i++) /* EMPTY */; /* ...and put them in the "stack" backward */ while (--i >= 0) { ludp = LDAP_CALLOC( 1, sizeof(LDAPURLDesc) ); if (ludp == NULL) { ldap_charray_free(specs); ldap_free_urllist(*ludlist); *ludlist = NULL; return LDAP_NO_MEMORY; } ludp->lud_port = port; ludp->lud_host = specs[i]; specs[i] = NULL; p = strchr(ludp->lud_host, ':'); if (p != NULL) { /* more than one :, IPv6 address */ if ( strchr(p+1, ':') != NULL ) { /* allow [address] and [address]:port */ if ( *ludp->lud_host == '[' ) { p = LDAP_STRDUP(ludp->lud_host+1); /* copied, make sure we free source later */ specs[i] = ludp->lud_host; ludp->lud_host = p; p = strchr( ludp->lud_host, ']' ); if ( p == NULL ) { LDAP_FREE(ludp); ldap_charray_free(specs); return LDAP_PARAM_ERROR; } *p++ = '\0'; if ( *p != ':' ) { if ( *p != '\0' ) { LDAP_FREE(ludp); ldap_charray_free(specs); return LDAP_PARAM_ERROR; } p = NULL; } } else { p = NULL; } } if (p != NULL) { char *next; *p++ = 0; ldap_pvt_hex_unescape(p); ludp->lud_port = strtol( p, &next, 10 ); if ( next == p || next[0] != '\0' ) { LDAP_FREE(ludp); ldap_charray_free(specs); return LDAP_PARAM_ERROR; } } } ldap_pvt_hex_unescape(ludp->lud_host); ludp->lud_scheme = LDAP_STRDUP("ldap"); ludp->lud_next = *ludlist; *ludlist = ludp; } /* this should be an array of NULLs now */ /* except entries starting with [ */ ldap_charray_free(specs); return LDAP_SUCCESS; } char * ldap_url_list2hosts (LDAPURLDesc *ludlist) { LDAPURLDesc *ludp; int size; char *s, *p, buf[32]; /* big enough to hold a long decimal # (overkill) */ if (ludlist == NULL) return NULL; /* figure out how big the string is */ size = 1; /* nul-term */ for (ludp = ludlist; ludp != NULL; ludp = ludp->lud_next) { if ( ludp->lud_host == NULL ) continue; size += strlen(ludp->lud_host) + 1; /* host and space */ if (strchr(ludp->lud_host, ':')) /* will add [ ] below */ size += 2; if (ludp->lud_port != 0) size += sprintf(buf, ":%d", ludp->lud_port); } s = LDAP_MALLOC(size); if (s == NULL) return NULL; p = s; for (ludp = ludlist; ludp != NULL; ludp = ludp->lud_next) { if ( ludp->lud_host == NULL ) continue; if (strchr(ludp->lud_host, ':')) { p += sprintf(p, "[%s]", ludp->lud_host); } else { strcpy(p, ludp->lud_host); p += strlen(ludp->lud_host); } if (ludp->lud_port != 0) p += sprintf(p, ":%d", ludp->lud_port); *p++ = ' '; } if (p != s) p--; /* nuke that extra space */ *p = '\0'; return s; } char * ldap_url_list2urls( LDAPURLDesc *ludlist ) { LDAPURLDesc *ludp; int size, sofar; char *s; if ( ludlist == NULL ) { return NULL; } /* figure out how big the string is */ for ( size = 0, ludp = ludlist; ludp != NULL; ludp = ludp->lud_next ) { int len = desc2str_len( ludp ); if ( len < 0 ) { return NULL; } size += len + 1; } s = LDAP_MALLOC( size ); if ( s == NULL ) { return NULL; } for ( sofar = 0, ludp = ludlist; ludp != NULL; ludp = ludp->lud_next ) { int len; len = desc2str( ludp, &s[sofar], size ); if ( len < 0 ) { LDAP_FREE( s ); return NULL; } sofar += len; size -= len; s[sofar++] = ' '; size--; assert( size >= 0 ); } s[sofar - 1] = '\0'; return s; } void ldap_free_urllist( LDAPURLDesc *ludlist ) { LDAPURLDesc *ludp, *next; for (ludp = ludlist; ludp != NULL; ludp = next) { next = ludp->lud_next; ldap_free_urldesc(ludp); } } void ldap_free_urldesc( LDAPURLDesc *ludp ) { if ( ludp == NULL ) { return; } if ( ludp->lud_scheme != NULL ) { LDAP_FREE( ludp->lud_scheme ); } if ( ludp->lud_host != NULL ) { LDAP_FREE( ludp->lud_host ); } if ( ludp->lud_dn != NULL ) { LDAP_FREE( ludp->lud_dn ); } if ( ludp->lud_filter != NULL ) { LDAP_FREE( ludp->lud_filter); } if ( ludp->lud_attrs != NULL ) { LDAP_VFREE( ludp->lud_attrs ); } if ( ludp->lud_exts != NULL ) { LDAP_VFREE( ludp->lud_exts ); } LDAP_FREE( ludp ); } static int ldap_int_is_hexpair( char *s ) { int i; for ( i = 0; i < 2; i++ ) { if ( s[i] >= '0' && s[i] <= '9' ) { continue; } if ( s[i] >= 'A' && s[i] <= 'F' ) { continue; } if ( s[i] >= 'a' && s[i] <= 'f' ) { continue; } return 0; } return 1; } static int ldap_int_unhex( int c ) { return( c >= '0' && c <= '9' ? c - '0' : c >= 'A' && c <= 'F' ? c - 'A' + 10 : c - 'a' + 10 ); } void ldap_pvt_hex_unescape( char *s ) { /* * Remove URL hex escapes from s... done in place. The basic concept for * this routine is borrowed from the WWW library HTUnEscape() routine. */ char *p, *save_s = s; for ( p = s; *s != '\0'; ++s ) { if ( *s == '%' ) { /* * FIXME: what if '%' is followed * by non-hexpair chars? */ if ( !ldap_int_is_hexpair( s + 1 ) ) { p = save_s; break; } if ( *++s == '\0' ) { break; } *p = ldap_int_unhex( *s ) << 4; if ( *++s == '\0' ) { break; } *p++ += ldap_int_unhex( *s ); } else { *p++ = *s; } } *p = '\0'; } openldap-2.4.42+dfsg/libraries/libldap/delete.c0000644000175000017500000000644612563404150020033 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (c) 1990 Regents of the University of Michigan. * All rights reserved. */ #include "portable.h" #include #include #include #include #include "ldap-int.h" /* * A delete request looks like this: * DelRequet ::= DistinguishedName, */ /* * ldap_delete_ext - initiate an ldap extended delete operation. Parameters: * * ld LDAP descriptor * dn DN of the object to delete * sctrls Server Controls * cctrls Client Controls * msgidp Message Id Pointer * * Example: * rc = ldap_delete( ld, dn, sctrls, cctrls, msgidp ); */ int ldap_delete_ext( LDAP *ld, LDAP_CONST char* dn, LDAPControl **sctrls, LDAPControl **cctrls, int *msgidp ) { int rc; BerElement *ber; ber_int_t id; Debug( LDAP_DEBUG_TRACE, "ldap_delete_ext\n", 0, 0, 0 ); assert( ld != NULL ); assert( LDAP_VALID( ld ) ); assert( dn != NULL ); assert( msgidp != NULL ); /* check client controls */ rc = ldap_int_client_controls( ld, cctrls ); if( rc != LDAP_SUCCESS ) return rc; /* create a message to send */ if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) { ld->ld_errno = LDAP_NO_MEMORY; return( ld->ld_errno ); } LDAP_NEXT_MSGID( ld, id ); rc = ber_printf( ber, "{its", /* '}' */ id, LDAP_REQ_DELETE, dn ); if ( rc == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( ld->ld_errno ); } /* Put Server Controls */ if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) { ber_free( ber, 1 ); return ld->ld_errno; } if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( ld->ld_errno ); } /* send the message */ *msgidp = ldap_send_initial_request( ld, LDAP_REQ_DELETE, dn, ber, id ); if(*msgidp < 0) return ld->ld_errno; return LDAP_SUCCESS; } int ldap_delete_ext_s( LDAP *ld, LDAP_CONST char *dn, LDAPControl **sctrls, LDAPControl **cctrls ) { int msgid; int rc; LDAPMessage *res; rc = ldap_delete_ext( ld, dn, sctrls, cctrls, &msgid ); if( rc != LDAP_SUCCESS ) return( ld->ld_errno ); if ( ldap_result( ld, msgid, LDAP_MSG_ALL, (struct timeval *) NULL, &res ) == -1 || !res ) return( ld->ld_errno ); return( ldap_result2error( ld, res, 1 ) ); } /* * ldap_delete - initiate an ldap (and X.500) delete operation. Parameters: * * ld LDAP descriptor * dn DN of the object to delete * * Example: * msgid = ldap_delete( ld, dn ); */ int ldap_delete( LDAP *ld, LDAP_CONST char *dn ) { int msgid; /* * A delete request looks like this: * DelRequet ::= DistinguishedName, */ Debug( LDAP_DEBUG_TRACE, "ldap_delete\n", 0, 0, 0 ); return ldap_delete_ext( ld, dn, NULL, NULL, &msgid ) == LDAP_SUCCESS ? msgid : -1 ; } int ldap_delete_s( LDAP *ld, LDAP_CONST char *dn ) { return ldap_delete_ext_s( ld, dn, NULL, NULL ); } openldap-2.4.42+dfsg/libraries/libldap/modify.c0000644000175000017500000001305712563404150020054 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (c) 1990 Regents of the University of Michigan. * All rights reserved. */ #include "portable.h" #include #include #include #include #include "ldap-int.h" /* A modify request/response looks like this: * ModifyRequest ::= [APPLICATION 6] SEQUENCE { * object LDAPDN, * changes SEQUENCE OF change SEQUENCE { * operation ENUMERATED { * add (0), * delete (1), * replace (2), * ... }, * modification PartialAttribute } } * * PartialAttribute ::= SEQUENCE { * type AttributeDescription, * vals SET OF value AttributeValue } * * AttributeDescription ::= LDAPString * -- Constrained to [RFC4512] * * AttributeValue ::= OCTET STRING * * ModifyResponse ::= [APPLICATION 7] LDAPResult * * (Source: RFC 4511) */ /* * ldap_modify_ext - initiate an ldap extended modify operation. * * Parameters: * * ld LDAP descriptor * dn DN of the object to modify * mods List of modifications to make. This is null-terminated * array of struct ldapmod's, specifying the modifications * to perform. * sctrls Server Controls * cctrls Client Controls * msgidp Message ID pointer * * Example: * LDAPMod *mods[] = { * { LDAP_MOD_ADD, "cn", { "babs jensen", "babs", 0 } }, * { LDAP_MOD_REPLACE, "sn", { "babs jensen", "babs", 0 } }, * { LDAP_MOD_DELETE, "ou", 0 }, * { LDAP_MOD_INCREMENT, "uidNumber, { "1", 0 } } * 0 * } * rc= ldap_modify_ext( ld, dn, mods, sctrls, cctrls, &msgid ); */ int ldap_modify_ext( LDAP *ld, LDAP_CONST char *dn, LDAPMod **mods, LDAPControl **sctrls, LDAPControl **cctrls, int *msgidp ) { BerElement *ber; int i, rc; ber_int_t id; Debug( LDAP_DEBUG_TRACE, "ldap_modify_ext\n", 0, 0, 0 ); /* check client controls */ rc = ldap_int_client_controls( ld, cctrls ); if( rc != LDAP_SUCCESS ) return rc; /* create a message to send */ if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) { return( LDAP_NO_MEMORY ); } LDAP_NEXT_MSGID( ld, id ); rc = ber_printf( ber, "{it{s{" /*}}}*/, id, LDAP_REQ_MODIFY, dn ); if ( rc == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( ld->ld_errno ); } /* allow mods to be NULL ("touch") */ if ( mods ) { /* for each modification to be performed... */ for ( i = 0; mods[i] != NULL; i++ ) { if (( mods[i]->mod_op & LDAP_MOD_BVALUES) != 0 ) { rc = ber_printf( ber, "{e{s[V]N}N}", (ber_int_t) ( mods[i]->mod_op & ~LDAP_MOD_BVALUES ), mods[i]->mod_type, mods[i]->mod_bvalues ); } else { rc = ber_printf( ber, "{e{s[v]N}N}", (ber_int_t) mods[i]->mod_op, mods[i]->mod_type, mods[i]->mod_values ); } if ( rc == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( ld->ld_errno ); } } } if ( ber_printf( ber, /*{{*/ "N}N}" ) == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( ld->ld_errno ); } /* Put Server Controls */ if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) { ber_free( ber, 1 ); return ld->ld_errno; } if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( ld->ld_errno ); } /* send the message */ *msgidp = ldap_send_initial_request( ld, LDAP_REQ_MODIFY, dn, ber, id ); return( *msgidp < 0 ? ld->ld_errno : LDAP_SUCCESS ); } /* * ldap_modify - initiate an ldap modify operation. * * Parameters: * * ld LDAP descriptor * dn DN of the object to modify * mods List of modifications to make. This is null-terminated * array of struct ldapmod's, specifying the modifications * to perform. * * Example: * LDAPMod *mods[] = { * { LDAP_MOD_ADD, "cn", { "babs jensen", "babs", 0 } }, * { LDAP_MOD_REPLACE, "sn", { "babs jensen", "babs", 0 } }, * { LDAP_MOD_DELETE, "ou", 0 }, * { LDAP_MOD_INCREMENT, "uidNumber, { "1", 0 } } * 0 * } * msgid = ldap_modify( ld, dn, mods ); */ int ldap_modify( LDAP *ld, LDAP_CONST char *dn, LDAPMod **mods ) { int rc, msgid; Debug( LDAP_DEBUG_TRACE, "ldap_modify\n", 0, 0, 0 ); rc = ldap_modify_ext( ld, dn, mods, NULL, NULL, &msgid ); if ( rc != LDAP_SUCCESS ) return -1; return msgid; } int ldap_modify_ext_s( LDAP *ld, LDAP_CONST char *dn, LDAPMod **mods, LDAPControl **sctrl, LDAPControl **cctrl ) { int rc; int msgid; LDAPMessage *res; rc = ldap_modify_ext( ld, dn, mods, sctrl, cctrl, &msgid ); if ( rc != LDAP_SUCCESS ) return( rc ); if ( ldap_result( ld, msgid, LDAP_MSG_ALL, (struct timeval *) NULL, &res ) == -1 || !res ) return( ld->ld_errno ); return( ldap_result2error( ld, res, 1 ) ); } int ldap_modify_s( LDAP *ld, LDAP_CONST char *dn, LDAPMod **mods ) { return ldap_modify_ext_s( ld, dn, mods, NULL, NULL ); } openldap-2.4.42+dfsg/libraries/libldap/ftest.c0000644000175000017500000000453612563404150017714 0ustar ryanryan/* ftest.c -- OpenLDAP Filter API Test */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #include "portable.h" #include #include #include #include #include #include "ldap_pvt.h" #include "lber_pvt.h" #include "ldif.h" #include "lutil.h" #include "lutil_ldap.h" #include "ldap_defaults.h" static int filter2ber( char *filter ); int usage() { fprintf( stderr, "usage:\n" " ftest [-d n] filter\n" " filter - RFC 4515 string representation of an " "LDAP search filter\n" ); return EXIT_FAILURE; } int main( int argc, char *argv[] ) { int c; int debug=0; while( (c = getopt( argc, argv, "d:" )) != EOF ) { switch ( c ) { case 'd': debug = atoi( optarg ); break; default: fprintf( stderr, "ftest: unrecognized option -%c\n", optopt ); return usage(); } } if ( debug ) { if ( ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &debug ) != LBER_OPT_SUCCESS ) { fprintf( stderr, "Could not set LBER_OPT_DEBUG_LEVEL %d\n", debug ); } if ( ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, &debug ) != LDAP_OPT_SUCCESS ) { fprintf( stderr, "Could not set LDAP_OPT_DEBUG_LEVEL %d\n", debug ); } } if ( argc - optind != 1 ) { return usage(); } return filter2ber( strdup( argv[optind] ) ); } static int filter2ber( char *filter ) { int rc; struct berval bv = BER_BVNULL; BerElement *ber; printf( "Filter: %s\n", filter ); ber = ber_alloc_t( LBER_USE_DER ); if( ber == NULL ) { perror( "ber_alloc_t" ); return EXIT_FAILURE; } rc = ldap_pvt_put_filter( ber, filter ); if( rc < 0 ) { fprintf( stderr, "Filter error!\n"); return EXIT_FAILURE; } rc = ber_flatten2( ber, &bv, 0 ); if( rc < 0 ) { perror( "ber_flatten2" ); return EXIT_FAILURE; } printf( "BER encoding (len=%ld):\n", (long) bv.bv_len ); ber_bprint( bv.bv_val, bv.bv_len ); ber_free( ber, 1 ); return EXIT_SUCCESS; } openldap-2.4.42+dfsg/libraries/libldap/fetch.c0000644000175000017500000000477512563404150017665 0ustar ryanryan/* fetch.c - routines for fetching data at URLs */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1999-2015 The OpenLDAP Foundation. * Portions Copyright 1999-2003 Kurt D. Zeilenga. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* This work was initially developed by Kurt D. Zeilenga for * inclusion in OpenLDAP Software. */ #include "portable.h" #include #include #include #include #include #ifdef HAVE_FETCH #include #endif #include "lber_pvt.h" #include "ldap_pvt.h" #include "ldap_config.h" #include "ldif.h" FILE * ldif_open_url( LDAP_CONST char *urlstr ) { FILE *url; if( strncasecmp( "file:", urlstr, sizeof("file:")-1 ) == 0 ) { char *p; urlstr += sizeof("file:")-1; /* we don't check for LDAP_DIRSEP since URLs should contain '/' */ if ( urlstr[0] == '/' && urlstr[1] == '/' ) { urlstr += 2; /* path must be absolute if authority is present */ if ( urlstr[0] != '/' ) return NULL; } p = ber_strdup( urlstr ); /* But we should convert to LDAP_DIRSEP before use */ if ( LDAP_DIRSEP[0] != '/' ) { char *s = p; while (( s = strchr( s, '/' ))) *s++ = LDAP_DIRSEP[0]; } ldap_pvt_hex_unescape( p ); url = fopen( p, "rb" ); ber_memfree( p ); } else { #ifdef HAVE_FETCH url = fetchGetURL( (char*) urlstr, "" ); #else url = NULL; #endif } return url; } int ldif_fetch_url( LDAP_CONST char *urlstr, char **valuep, ber_len_t *vlenp ) { FILE *url; char buffer[1024]; char *p = NULL; size_t total; size_t bytes; *valuep = NULL; *vlenp = 0; url = ldif_open_url( urlstr ); if( url == NULL ) { return -1; } total = 0; while( (bytes = fread( buffer, 1, sizeof(buffer), url )) != 0 ) { char *newp = ber_memrealloc( p, total + bytes + 1 ); if( newp == NULL ) { ber_memfree( p ); fclose( url ); return -1; } p = newp; AC_MEMCPY( &p[total], buffer, bytes ); total += bytes; } fclose( url ); if( total == 0 ) { char *newp = ber_memrealloc( p, 1 ); if( newp == NULL ) { ber_memfree( p ); return -1; } p = newp; } p[total] = '\0'; *valuep = p; *vlenp = total; return 0; } openldap-2.4.42+dfsg/libraries/libldap/deref.c0000644000175000017500000001267112563404150017653 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * Portions Copyright 2008 Pierangelo Masarati. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* ACKNOWLEDGEMENTS: * This work was initially developed by Pierangelo Masarati * for inclusion in OpenLDAP Software. */ #include "portable.h" #include #include #include #include #include "ldap-int.h" int ldap_create_deref_control_value( LDAP *ld, LDAPDerefSpec *ds, struct berval *value ) { BerElement *ber = NULL; ber_tag_t tag; int i; if ( ld == NULL || value == NULL || ds == NULL ) { if ( ld ) ld->ld_errno = LDAP_PARAM_ERROR; return LDAP_PARAM_ERROR; } assert( LDAP_VALID( ld ) ); value->bv_val = NULL; value->bv_len = 0; ld->ld_errno = LDAP_SUCCESS; ber = ldap_alloc_ber_with_options( ld ); if ( ber == NULL ) { ld->ld_errno = LDAP_NO_MEMORY; return ld->ld_errno; } tag = ber_printf( ber, "{" /*}*/ ); if ( tag == LBER_ERROR ) { ld->ld_errno = LDAP_ENCODING_ERROR; goto done; } for ( i = 0; ds[i].derefAttr != NULL; i++ ) { int j; tag = ber_printf( ber, "{s{" /*}}*/ , ds[i].derefAttr ); if ( tag == LBER_ERROR ) { ld->ld_errno = LDAP_ENCODING_ERROR; goto done; } for ( j = 0; ds[i].attributes[j] != NULL; j++ ) { tag = ber_printf( ber, "s", ds[i].attributes[ j ] ); if ( tag == LBER_ERROR ) { ld->ld_errno = LDAP_ENCODING_ERROR; goto done; } } tag = ber_printf( ber, /*{{*/ "}N}" ); if ( tag == LBER_ERROR ) { ld->ld_errno = LDAP_ENCODING_ERROR; goto done; } } tag = ber_printf( ber, /*{*/ "}" ); if ( tag == LBER_ERROR ) { ld->ld_errno = LDAP_ENCODING_ERROR; goto done; } if ( ber_flatten2( ber, value, 1 ) == -1 ) { ld->ld_errno = LDAP_NO_MEMORY; } done:; if ( ber != NULL ) { ber_free( ber, 1 ); } return ld->ld_errno; } int ldap_create_deref_control( LDAP *ld, LDAPDerefSpec *ds, int iscritical, LDAPControl **ctrlp ) { struct berval value; if ( ctrlp == NULL ) { ld->ld_errno = LDAP_PARAM_ERROR; return ld->ld_errno; } ld->ld_errno = ldap_create_deref_control_value( ld, ds, &value ); if ( ld->ld_errno == LDAP_SUCCESS ) { ld->ld_errno = ldap_control_create( LDAP_CONTROL_X_DEREF, iscritical, &value, 0, ctrlp ); if ( ld->ld_errno != LDAP_SUCCESS ) { LDAP_FREE( value.bv_val ); } } return ld->ld_errno; } void ldap_derefresponse_free( LDAPDerefRes *dr ) { for ( ; dr; ) { LDAPDerefRes *drnext = dr->next; LDAPDerefVal *dv; LDAP_FREE( dr->derefAttr ); LDAP_FREE( dr->derefVal.bv_val ); for ( dv = dr->attrVals; dv; ) { LDAPDerefVal *dvnext = dv->next; LDAP_FREE( dv->type ); ber_bvarray_free( dv->vals ); LDAP_FREE( dv ); dv = dvnext; } LDAP_FREE( dr ); dr = drnext; } } int ldap_parse_derefresponse_control( LDAP *ld, LDAPControl *ctrl, LDAPDerefRes **drp2 ) { BerElement *ber; ber_tag_t tag; ber_len_t len; char *last; LDAPDerefRes *drhead = NULL, **drp; if ( ld == NULL || ctrl == NULL || drp2 == NULL ) { if ( ld ) ld->ld_errno = LDAP_PARAM_ERROR; return LDAP_PARAM_ERROR; } /* Create a BerElement from the berval returned in the control. */ ber = ber_init( &ctrl->ldctl_value ); if ( ber == NULL ) { ld->ld_errno = LDAP_NO_MEMORY; return ld->ld_errno; } /* Extract the count and cookie from the control. */ drp = &drhead; for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_DEFAULT; tag = ber_next_element( ber, &len, last ) ) { LDAPDerefRes *dr; LDAPDerefVal **dvp; char *last2; dr = LDAP_CALLOC( 1, sizeof(LDAPDerefRes) ); dvp = &dr->attrVals; tag = ber_scanf( ber, "{ao", &dr->derefAttr, &dr->derefVal ); if ( tag == LBER_ERROR ) { goto done; } tag = ber_peek_tag( ber, &len ); if ( tag == (LBER_CONSTRUCTED|LBER_CLASS_CONTEXT) ) { for ( tag = ber_first_element( ber, &len, &last2 ); tag != LBER_DEFAULT; tag = ber_next_element( ber, &len, last2 ) ) { LDAPDerefVal *dv; dv = LDAP_CALLOC( 1, sizeof(LDAPDerefVal) ); tag = ber_scanf( ber, "{a[W]}", &dv->type, &dv->vals ); if ( tag == LBER_ERROR ) { goto done; } *dvp = dv; dvp = &dv->next; } } tag = ber_scanf( ber, "}" ); if ( tag == LBER_ERROR ) { goto done; } *drp = dr; drp = &dr->next; } tag = 0; done:; ber_free( ber, 1 ); if ( tag == LBER_ERROR ) { if ( drhead != NULL ) { ldap_derefresponse_free( drhead ); } *drp2 = NULL; ld->ld_errno = LDAP_DECODING_ERROR; } else { *drp2 = drhead; ld->ld_errno = LDAP_SUCCESS; } return ld->ld_errno; } int ldap_parse_deref_control( LDAP *ld, LDAPControl **ctrls, LDAPDerefRes **drp ) { LDAPControl *c; if ( drp == NULL ) { ld->ld_errno = LDAP_PARAM_ERROR; return ld->ld_errno; } *drp = NULL; if ( ctrls == NULL ) { ld->ld_errno = LDAP_CONTROL_NOT_FOUND; return ld->ld_errno; } c = ldap_control_find( LDAP_CONTROL_X_DEREF, ctrls, NULL ); if ( c == NULL ) { /* No deref control was found. */ ld->ld_errno = LDAP_CONTROL_NOT_FOUND; return ld->ld_errno; } ld->ld_errno = ldap_parse_derefresponse_control( ld, c, drp ); return ld->ld_errno; } openldap-2.4.42+dfsg/libraries/libldap/vlvctrl.c0000644000175000017500000002301012563404150020247 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (C) 1999, 2000 Novell, Inc. All Rights Reserved. * * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND * TREATIES. USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT * TO VERSION 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS * AVAILABLE AT HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE" * IN THE TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION * OF THIS WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP * PUBLIC LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT * THE PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY. *--- * Note: A verbatim copy of version 2.0.1 of the OpenLDAP Public License * can be found in the file "build/LICENSE-2.0.1" in this distribution * of OpenLDAP Software. */ #include "portable.h" #include #include #include #include #include "ldap-int.h" #define LDAP_VLVBYINDEX_IDENTIFIER 0xa0L #define LDAP_VLVBYVALUE_IDENTIFIER 0x81L #define LDAP_VLVCONTEXT_IDENTIFIER 0x04L /*--- ldap_create_vlv_control Create and encode the Virtual List View control. ld (IN) An LDAP session handle. vlvinfop (IN) The address of an LDAPVLVInfo structure whose contents are used to construct the value of the control that is created. value (OUT) A struct berval that contains the value to be assigned to the ldctl_value member of an LDAPControl structure that contains the VirtualListViewRequest control. The bv_val member of the berval structure SHOULD be freed when it is no longer in use by calling ldap_memfree(). Ber encoding VirtualListViewRequest ::= SEQUENCE { beforeCount INTEGER (0 .. maxInt), afterCount INTEGER (0 .. maxInt), CHOICE { byoffset [0] SEQUENCE, { offset INTEGER (0 .. maxInt), contentCount INTEGER (0 .. maxInt) } [1] greaterThanOrEqual assertionValue } contextID OCTET STRING OPTIONAL } Note: The first time the VLV control is created, the ldvlv_context field of the LDAPVLVInfo structure should be set to NULL. The context obtained from calling ldap_parse_vlv_control() should be used as the context in the next ldap_create_vlv_control call. ---*/ int ldap_create_vlv_control_value( LDAP *ld, LDAPVLVInfo *vlvinfop, struct berval *value ) { ber_tag_t tag; BerElement *ber; if ( ld == NULL || vlvinfop == NULL || value == NULL ) { if ( ld ) ld->ld_errno = LDAP_PARAM_ERROR; return LDAP_PARAM_ERROR; } assert( LDAP_VALID( ld ) ); value->bv_val = NULL; value->bv_len = 0; ld->ld_errno = LDAP_SUCCESS; ber = ldap_alloc_ber_with_options( ld ); if ( ber == NULL ) { ld->ld_errno = LDAP_NO_MEMORY; return ld->ld_errno; } tag = ber_printf( ber, "{ii" /*}*/, vlvinfop->ldvlv_before_count, vlvinfop->ldvlv_after_count ); if ( tag == LBER_ERROR ) { goto error_return; } if ( vlvinfop->ldvlv_attrvalue == NULL ) { tag = ber_printf( ber, "t{iiN}", LDAP_VLVBYINDEX_IDENTIFIER, vlvinfop->ldvlv_offset, vlvinfop->ldvlv_count ); if ( tag == LBER_ERROR ) { goto error_return; } } else { tag = ber_printf( ber, "tO", LDAP_VLVBYVALUE_IDENTIFIER, vlvinfop->ldvlv_attrvalue ); if ( tag == LBER_ERROR ) { goto error_return; } } if ( vlvinfop->ldvlv_context ) { tag = ber_printf( ber, "tO", LDAP_VLVCONTEXT_IDENTIFIER, vlvinfop->ldvlv_context ); if ( tag == LBER_ERROR ) { goto error_return; } } tag = ber_printf( ber, /*{*/ "N}" ); if ( tag == LBER_ERROR ) { goto error_return; } if ( ber_flatten2( ber, value, 1 ) == -1 ) { ld->ld_errno = LDAP_NO_MEMORY; } if ( 0 ) { error_return:; ld->ld_errno = LDAP_ENCODING_ERROR; } if ( ber != NULL ) { ber_free( ber, 1 ); } return ld->ld_errno; } /*--- ldap_create_vlv_control Create and encode the Virtual List View control. ld (IN) An LDAP session handle. vlvinfop (IN) The address of an LDAPVLVInfo structure whose contents are used to construct the value of the control that is created. ctrlp (OUT) A result parameter that will be assigned the address of an LDAPControl structure that contains the VirtualListViewRequest control created by this function. The memory occupied by the LDAPControl structure SHOULD be freed when it is no longer in use by calling ldap_control_free(). Ber encoding VirtualListViewRequest ::= SEQUENCE { beforeCount INTEGER (0 .. maxInt), afterCount INTEGER (0 .. maxInt), CHOICE { byoffset [0] SEQUENCE, { offset INTEGER (0 .. maxInt), contentCount INTEGER (0 .. maxInt) } [1] greaterThanOrEqual assertionValue } contextID OCTET STRING OPTIONAL } Note: The first time the VLV control is created, the ldvlv_context field of the LDAPVLVInfo structure should be set to NULL. The context obtained from calling ldap_parse_vlv_control() should be used as the context in the next ldap_create_vlv_control call. ---*/ int ldap_create_vlv_control( LDAP *ld, LDAPVLVInfo *vlvinfop, LDAPControl **ctrlp ) { struct berval value; if ( ctrlp == NULL ) { ld->ld_errno = LDAP_PARAM_ERROR; return ld->ld_errno; } ld->ld_errno = ldap_create_vlv_control_value( ld, vlvinfop, &value ); if ( ld->ld_errno == LDAP_SUCCESS ) { ld->ld_errno = ldap_control_create( LDAP_CONTROL_VLVREQUEST, 1, &value, 0, ctrlp ); if ( ld->ld_errno != LDAP_SUCCESS ) { LDAP_FREE( value.bv_val ); } } return ld->ld_errno; } /*--- ldap_parse_vlvresponse_control Decode the Virtual List View control return information. ld (IN) An LDAP session handle. ctrl (IN) The address of the LDAPControl structure. target_posp (OUT) This result parameter is filled in with the list index of the target entry. If this parameter is NULL, the target position is not returned. list_countp (OUT) This result parameter is filled in with the server's estimate of the size of the list. If this parameter is NULL, the size is not returned. contextp (OUT) This result parameter is filled in with the address of a struct berval that contains the server- generated context identifier if one was returned by the server. If the server did not return a context identifier, this parameter will be set to NULL, even if an error occured. The returned context SHOULD be used in the next call to create a VLV sort control. The struct berval returned SHOULD be disposed of by calling ber_bvfree() when it is no longer needed. If NULL is passed for contextp, the context identifier is not returned. errcodep (OUT) This result parameter is filled in with the VLV result code. If this parameter is NULL, the result code is not returned. Ber encoding VirtualListViewResponse ::= SEQUENCE { targetPosition INTEGER (0 .. maxInt), contentCount INTEGER (0 .. maxInt), virtualListViewResult ENUMERATED { success (0), operatonsError (1), unwillingToPerform (53), insufficientAccessRights (50), busy (51), timeLimitExceeded (3), adminLimitExceeded (11), sortControlMissing (60), offsetRangeError (61), other (80) }, contextID OCTET STRING OPTIONAL } ---*/ int ldap_parse_vlvresponse_control( LDAP *ld, LDAPControl *ctrl, ber_int_t *target_posp, ber_int_t *list_countp, struct berval **contextp, ber_int_t *errcodep ) { BerElement *ber; ber_int_t pos, count, err; ber_tag_t tag, berTag; ber_len_t berLen; assert( ld != NULL ); assert( LDAP_VALID( ld ) ); if (contextp) { *contextp = NULL; /* Make sure we return a NULL if error occurs. */ } if (ctrl == NULL) { ld->ld_errno = LDAP_PARAM_ERROR; return(ld->ld_errno); } if (strcmp(LDAP_CONTROL_VLVRESPONSE, ctrl->ldctl_oid) != 0) { /* Not VLV Response control */ ld->ld_errno = LDAP_CONTROL_NOT_FOUND; return(ld->ld_errno); } /* Create a BerElement from the berval returned in the control. */ ber = ber_init(&ctrl->ldctl_value); if (ber == NULL) { ld->ld_errno = LDAP_NO_MEMORY; return(ld->ld_errno); } /* Extract the data returned in the control. */ tag = ber_scanf(ber, "{iie" /*}*/, &pos, &count, &err); if( tag == LBER_ERROR) { ber_free(ber, 1); ld->ld_errno = LDAP_DECODING_ERROR; return(ld->ld_errno); } /* Since the context is the last item encoded, if caller doesn't want it returned, don't decode it. */ if (contextp) { if (LDAP_VLVCONTEXT_IDENTIFIER == ber_peek_tag(ber, &berLen)) { tag = ber_scanf(ber, "tO", &berTag, contextp); if( tag == LBER_ERROR) { ber_free(ber, 1); ld->ld_errno = LDAP_DECODING_ERROR; return(ld->ld_errno); } } } ber_free(ber, 1); /* Return data to the caller for items that were requested. */ if (target_posp) *target_posp = pos; if (list_countp) *list_countp = count; if (errcodep) *errcodep = err; ld->ld_errno = LDAP_SUCCESS; return(ld->ld_errno); } openldap-2.4.42+dfsg/libraries/libldap/t61.c0000644000175000017500000006103012563404150017171 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 2002-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* ACKNOWLEDGEMENTS: * This work was initially developed by Howard Chu for inclusion in * OpenLDAP Software. */ /* * Basic T.61 <-> UTF-8 conversion * * These routines will perform a lossless translation from T.61 to UTF-8 * and a lossy translation from UTF-8 to T.61. */ #include "portable.h" #include #include #include #include #include #include "ldap-int.h" #include "ldap_utf8.h" #include "ldap_defaults.h" /* * T.61 is somewhat braindead; even in the 7-bit space it is not * completely equivalent to 7-bit US-ASCII. Our definition of the * character set comes from RFC 1345 with a slightly more readable * rendition at http://std.dkuug.dk/i18n/charmaps/T.61-8BIT. * * Even though '#' and '$' are present in the 7-bit US-ASCII space, * (x23 and x24, resp.) in T.61 they are mapped to 8-bit characters * xA6 and xA4. * * Also T.61 lacks * backslash \ (x5C) * caret ^ (x5E) * backquote ` (x60) * left brace { (x7B) * right brace } (x7D) * tilde ~ (x7E) * * In T.61, the codes xC1 to xCF (excluding xC9, unused) are non-spacing * accents of some form or another. There are predefined combinations * for certain characters, but they can also be used arbitrarily. The * table at dkuug.dk maps these accents to the E000 "private use" range * of the Unicode space, but I believe they more properly belong in the * 0300 range (non-spacing accents). The transformation is complicated * slightly because Unicode wants the non-spacing character to follow * the base character, while T.61 has the non-spacing character leading. * Also, T.61 specifically recognizes certain combined pairs as "characters" * but doesn't specify how to treat unrecognized pairs. This code will * always attempt to combine pairs when a known Unicode composite exists. */ static const wchar_t t61_tab[] = { 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007, 0x008, 0x009, 0x00a, 0x00b, 0x00c, 0x00d, 0x00e, 0x00f, 0x010, 0x011, 0x012, 0x013, 0x014, 0x015, 0x016, 0x017, 0x018, 0x019, 0x01a, 0x01b, 0x01c, 0x01d, 0x01e, 0x01f, 0x020, 0x021, 0x022, 0x000, 0x000, 0x025, 0x026, 0x027, 0x028, 0x029, 0x02a, 0x02b, 0x02c, 0x02d, 0x02e, 0x02f, 0x030, 0x031, 0x032, 0x033, 0x034, 0x035, 0x036, 0x037, 0x038, 0x039, 0x03a, 0x03b, 0x03c, 0x03d, 0x03e, 0x03f, 0x040, 0x041, 0x042, 0x043, 0x044, 0x045, 0x046, 0x047, 0x048, 0x049, 0x04a, 0x04b, 0x04c, 0x04d, 0x04e, 0x04f, 0x050, 0x051, 0x052, 0x053, 0x054, 0x055, 0x056, 0x057, 0x058, 0x059, 0x05a, 0x05b, 0x000, 0x05d, 0x000, 0x05f, 0x000, 0x061, 0x062, 0x063, 0x064, 0x065, 0x066, 0x067, 0x068, 0x069, 0x06a, 0x06b, 0x06c, 0x06d, 0x06e, 0x06f, 0x070, 0x071, 0x072, 0x073, 0x074, 0x075, 0x076, 0x077, 0x078, 0x079, 0x07a, 0x000, 0x07c, 0x000, 0x000, 0x07f, 0x080, 0x081, 0x082, 0x083, 0x084, 0x085, 0x086, 0x087, 0x088, 0x089, 0x08a, 0x08b, 0x08c, 0x08d, 0x08e, 0x08f, 0x090, 0x091, 0x092, 0x093, 0x094, 0x095, 0x096, 0x097, 0x098, 0x099, 0x09a, 0x09b, 0x09c, 0x09d, 0x09e, 0x09f, 0x0a0, 0x0a1, 0x0a2, 0x0a3, 0x024, 0x0a5, 0x023, 0x0a7, 0x0a4, 0x000, 0x000, 0x0ab, 0x000, 0x000, 0x000, 0x000, 0x0b0, 0x0b1, 0x0b2, 0x0b3, 0x0d7, 0x0b5, 0x0b6, 0x0b7, 0x0f7, 0x000, 0x000, 0x0bb, 0x0bc, 0x0bd, 0x0be, 0x0bf, 0x000, 0x300, 0x301, 0x302, 0x303, 0x304, 0x306, 0x307, 0x308, 0x000, 0x30a, 0x327, 0x332, 0x30b, 0x328, 0x30c, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x2126, 0xc6, 0x0d0, 0x0aa, 0x126, 0x000, 0x132, 0x13f, 0x141, 0x0d8, 0x152, 0x0ba, 0x0de, 0x166, 0x14a, 0x149, 0x138, 0x0e6, 0x111, 0x0f0, 0x127, 0x131, 0x133, 0x140, 0x142, 0x0f8, 0x153, 0x0df, 0x0fe, 0x167, 0x14b, 0x000 }; typedef wchar_t wvec16[16]; typedef wchar_t wvec32[32]; typedef wchar_t wvec64[64]; /* Substitutions when 0xc1-0xcf appears by itself or with space 0x20 */ static const wvec16 accents = { 0x000, 0x060, 0x0b4, 0x05e, 0x07e, 0x0af, 0x2d8, 0x2d9, 0x0a8, 0x000, 0x2da, 0x0b8, 0x000, 0x2dd, 0x2db, 0x2c7}; /* In the following tables, base characters commented in (parentheses) * are not defined by T.61 but are mapped anyway since their Unicode * composite exists. */ /* Grave accented chars AEIOU (NWY) */ static const wvec32 c1_vec1 = { /* Upper case */ 0, 0xc0, 0, 0, 0, 0xc8, 0, 0, 0, 0xcc, 0, 0, 0, 0, 0x1f8, 0xd2, 0, 0, 0, 0, 0, 0xd9, 0, 0x1e80, 0, 0x1ef2, 0, 0, 0, 0, 0, 0}; static const wvec32 c1_vec2 = { /* Lower case */ 0, 0xe0, 0, 0, 0, 0xe8, 0, 0, 0, 0xec, 0, 0, 0, 0, 0x1f9, 0xf2, 0, 0, 0, 0, 0, 0xf9, 0, 0x1e81, 0, 0x1ef3, 0, 0, 0, 0, 0, 0}; static const wvec32 *c1_grave[] = { NULL, NULL, &c1_vec1, &c1_vec2, NULL, NULL, NULL, NULL }; /* Acute accented chars AEIOUYCLNRSZ (GKMPW) */ static const wvec32 c2_vec1 = { /* Upper case */ 0, 0xc1, 0, 0x106, 0, 0xc9, 0, 0x1f4, 0, 0xcd, 0, 0x1e30, 0x139, 0x1e3e, 0x143, 0xd3, 0x1e54, 0, 0x154, 0x15a, 0, 0xda, 0, 0x1e82, 0, 0xdd, 0x179, 0, 0, 0, 0, 0}; static const wvec32 c2_vec2 = { /* Lower case */ 0, 0xe1, 0, 0x107, 0, 0xe9, 0, 0x1f5, 0, 0xed, 0, 0x1e31, 0x13a, 0x1e3f, 0x144, 0xf3, 0x1e55, 0, 0x155, 0x15b, 0, 0xfa, 0, 0x1e83, 0, 0xfd, 0x17a, 0, 0, 0, 0, 0}; static const wvec32 c2_vec3 = { /* (AE and ae) */ 0, 0x1fc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1fd, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; static const wvec32 *c2_acute[] = { NULL, NULL, &c2_vec1, &c2_vec2, NULL, NULL, NULL, &c2_vec3 }; /* Circumflex AEIOUYCGHJSW (Z) */ static const wvec32 c3_vec1 = { /* Upper case */ 0, 0xc2, 0, 0x108, 0, 0xca, 0, 0x11c, 0x124, 0xce, 0x134, 0, 0, 0, 0, 0xd4, 0, 0, 0, 0x15c, 0, 0xdb, 0, 0x174, 0, 0x176, 0x1e90, 0, 0, 0, 0, 0}; static const wvec32 c3_vec2 = { /* Lower case */ 0, 0xe2, 0, 0x109, 0, 0xea, 0, 0x11d, 0x125, 0xee, 0x135, 0, 0, 0, 0, 0xf4, 0, 0, 0, 0x15d, 0, 0xfb, 0, 0x175, 0, 0x177, 0x1e91, 0, 0, 0, 0, 0}; static const wvec32 *c3_circumflex[] = { NULL, NULL, &c3_vec1, &c3_vec2, NULL, NULL, NULL, NULL }; /* Tilde AIOUN (EVY) */ static const wvec32 c4_vec1 = { /* Upper case */ 0, 0xc3, 0, 0, 0, 0x1ebc, 0, 0, 0, 0x128, 0, 0, 0, 0, 0xd1, 0xd5, 0, 0, 0, 0, 0, 0x168, 0x1e7c, 0, 0, 0x1ef8, 0, 0, 0, 0, 0, 0}; static const wvec32 c4_vec2 = { /* Lower case */ 0, 0xe3, 0, 0, 0, 0x1ebd, 0, 0, 0, 0x129, 0, 0, 0, 0, 0xf1, 0xf5, 0, 0, 0, 0, 0, 0x169, 0x1e7d, 0, 0, 0x1ef9, 0, 0, 0, 0, 0, 0}; static const wvec32 *c4_tilde[] = { NULL, NULL, &c4_vec1, &c4_vec2, NULL, NULL, NULL, NULL }; /* Macron AEIOU (YG) */ static const wvec32 c5_vec1 = { /* Upper case */ 0, 0x100, 0, 0, 0, 0x112, 0, 0x1e20, 0, 0x12a, 0, 0, 0, 0, 0, 0x14c, 0, 0, 0, 0, 0, 0x16a, 0, 0, 0, 0x232, 0, 0, 0, 0, 0, 0}; static const wvec32 c5_vec2 = { /* Lower case */ 0, 0x101, 0, 0, 0, 0x113, 0, 0x1e21, 0, 0x12b, 0, 0, 0, 0, 0, 0x14d, 0, 0, 0, 0, 0, 0x16b, 0, 0, 0, 0x233, 0, 0, 0, 0, 0, 0}; static const wvec32 c5_vec3 = { /* (AE and ae) */ 0, 0x1e2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1e3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; static const wvec32 *c5_macron[] = { NULL, NULL, &c5_vec1, &c5_vec2, NULL, NULL, NULL, &c5_vec3 }; /* Breve AUG (EIO) */ static const wvec32 c6_vec1 = { /* Upper case */ 0, 0x102, 0, 0, 0, 0x114, 0, 0x11e, 0, 0x12c, 0, 0, 0, 0, 0, 0x14e, 0, 0, 0, 0, 0, 0x16c, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; static const wvec32 c6_vec2 = { /* Lower case */ 0, 0x103, 0, 0, 0, 0x115, 0, 0x11f, 0, 0x12d, 0, 0, 0, 0, 0, 0x14f, 0, 0, 0, 0, 0, 0x16d, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; static const wvec32 *c6_breve[] = { NULL, NULL, &c6_vec1, &c6_vec2, NULL, NULL, NULL, NULL }; /* Dot Above CEGIZ (AOBDFHMNPRSTWXY) */ static const wvec32 c7_vec1 = { /* Upper case */ 0, 0x226, 0x1e02, 0x10a, 0x1e0a, 0x116, 0x1e1e, 0x120, 0x1e22, 0x130, 0, 0, 0, 0x1e40, 0x1e44, 0x22e, 0x1e56, 0, 0x1e58, 0x1e60, 0x1e6a, 0, 0, 0x1e86, 0x1e8a, 0x1e8e, 0x17b, 0, 0, 0, 0, 0}; static const wvec32 c7_vec2 = { /* Lower case */ 0, 0x227, 0x1e03, 0x10b, 0x1e0b, 0x117, 0x1e1f, 0x121, 0x1e23, 0, 0, 0, 0, 0x1e41, 0x1e45, 0x22f, 0x1e57, 0, 0x1e59, 0x1e61, 0x1e6b, 0, 0, 0x1e87, 0x1e8b, 0x1e8f, 0x17c, 0, 0, 0, 0, 0}; static const wvec32 *c7_dotabove[] = { NULL, NULL, &c7_vec1, &c7_vec2, NULL, NULL, NULL, NULL }; /* Diaeresis AEIOUY (HWXt) */ static const wvec32 c8_vec1 = { /* Upper case */ 0, 0xc4, 0, 0, 0, 0xcb, 0, 0, 0x1e26, 0xcf, 0, 0, 0, 0, 0, 0xd6, 0, 0, 0, 0, 0, 0xdc, 0, 0x1e84, 0x1e8c, 0x178, 0, 0, 0, 0, 0, 0}; static const wvec32 c8_vec2 = { /* Lower case */ 0, 0xe4, 0, 0, 0, 0xeb, 0, 0, 0x1e27, 0xef, 0, 0, 0, 0, 0, 0xf6, 0, 0, 0, 0, 0x1e97, 0xfc, 0, 0x1e85, 0x1e8d, 0xff, 0, 0, 0, 0, 0, 0}; static const wvec32 *c8_diaeresis[] = { NULL, NULL, &c8_vec1, &c8_vec2, NULL, NULL, NULL, NULL }; /* Ring Above AU (wy) */ static const wvec32 ca_vec1 = { /* Upper case */ 0, 0xc5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x16e, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; static const wvec32 ca_vec2 = { /* Lower case */ 0, 0xe5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x16f, 0, 0x1e98, 0, 0x1e99, 0, 0, 0, 0, 0, 0}; static const wvec32 *ca_ringabove[] = { NULL, NULL, &ca_vec1, &ca_vec2, NULL, NULL, NULL, NULL }; /* Cedilla CGKLNRST (EDH) */ static const wvec32 cb_vec1 = { /* Upper case */ 0, 0, 0, 0xc7, 0x1e10, 0x228, 0, 0x122, 0x1e28, 0, 0, 0x136, 0x13b, 0, 0x145, 0, 0, 0, 0x156, 0x15e, 0x162, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; static const wvec32 cb_vec2 = { /* Lower case */ 0, 0, 0, 0xe7, 0x1e11, 0x229, 0, 0x123, 0x1e29, 0, 0, 0x137, 0x13c, 0, 0x146, 0, 0, 0, 0x157, 0x15f, 0x163, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; static const wvec32 *cb_cedilla[] = { NULL, NULL, &cb_vec1, &cb_vec2, NULL, NULL, NULL, NULL }; /* Double Acute Accent OU */ static const wvec32 cd_vec1 = { /* Upper case */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x150, 0, 0, 0, 0, 0, 0x170, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; static const wvec32 cd_vec2 = { /* Lower case */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x151, 0, 0, 0, 0, 0, 0x171, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; static const wvec32 *cd_doubleacute[] = { NULL, NULL, &cd_vec1, &cd_vec2, NULL, NULL, NULL, NULL }; /* Ogonek AEIU (O) */ static const wvec32 ce_vec1 = { /* Upper case */ 0, 0x104, 0, 0, 0, 0x118, 0, 0, 0, 0x12e, 0, 0, 0, 0, 0, 0x1ea, 0, 0, 0, 0, 0, 0x172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; static const wvec32 ce_vec2 = { /* Lower case */ 0, 0x105, 0, 0, 0, 0x119, 0, 0, 0, 0x12f, 0, 0, 0, 0, 0, 0x1eb, 0, 0, 0, 0, 0, 0x173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; static const wvec32 *ce_ogonek[] = { NULL, NULL, &ce_vec1, &ce_vec2, NULL, NULL, NULL, NULL }; /* Caron CDELNRSTZ (AIOUGKjH) */ static const wvec32 cf_vec1 = { /* Upper case */ 0, 0x1cd, 0, 0x10c, 0x10e, 0x11a, 0, 0x1e6, 0x21e, 0x1cf, 0, 0x1e8, 0x13d, 0, 0x147, 0x1d1, 0, 0, 0x158, 0x160, 0x164, 0x1d3, 0, 0, 0, 0, 0x17d, 0, 0, 0, 0, 0}; static const wvec32 cf_vec2 = { /* Lower case */ 0, 0x1ce, 0, 0x10d, 0x10f, 0x11b, 0, 0x1e7, 0x21f, 0x1d0, 0x1f0, 0x1e9, 0x13e, 0, 0x148, 0x1d2, 0, 0, 0x159, 0x161, 0x165, 0x1d4, 0, 0, 0, 0, 0x17e, 0, 0, 0, 0, 0}; static const wvec32 *cf_caron[] = { NULL, NULL, &cf_vec1, &cf_vec2, NULL, NULL, NULL, NULL }; static const wvec32 **cx_tab[] = { NULL, c1_grave, c2_acute, c3_circumflex, c4_tilde, c5_macron, c6_breve, c7_dotabove, c8_diaeresis, NULL, ca_ringabove, cb_cedilla, NULL, cd_doubleacute, ce_ogonek, cf_caron }; int ldap_t61s_valid( struct berval *str ) { unsigned char *c = (unsigned char *)str->bv_val; int i; for (i=0; i < str->bv_len; c++,i++) if (!t61_tab[*c]) return 0; return 1; } /* Transform a T.61 string to UTF-8. */ int ldap_t61s_to_utf8s( struct berval *src, struct berval *dst ) { unsigned char *c; char *d; int i, wlen = 0; /* Just count the length of the UTF-8 result first */ for (i=0,c=(unsigned char *)src->bv_val; i < src->bv_len; c++,i++) { /* Invalid T.61 characters? */ if (!t61_tab[*c]) return LDAP_INVALID_SYNTAX; if ((*c & 0xf0) == 0xc0) { int j = *c & 0x0f; /* If this is the end of the string, or if the base * character is just a space, treat this as a regular * spacing character. */ if ((!c[1] || c[1] == 0x20) && accents[j]) { wlen += ldap_x_wc_to_utf8(NULL, accents[j], 0); } else if (cx_tab[j] && cx_tab[j][c[1]>>5] && /* We have a composite mapping for this pair */ (*cx_tab[j][c[1]>>5])[c[1]&0x1f]) { wlen += ldap_x_wc_to_utf8( NULL, (*cx_tab[j][c[1]>>5])[c[1]&0x1f], 0); } else { /* No mapping, just swap it around so the base * character comes first. */ wlen += ldap_x_wc_to_utf8(NULL, c[1], 0); wlen += ldap_x_wc_to_utf8(NULL, t61_tab[*c], 0); } c++; i++; continue; } else { wlen += ldap_x_wc_to_utf8(NULL, t61_tab[*c], 0); } } /* Now transform the string */ dst->bv_len = wlen; dst->bv_val = LDAP_MALLOC( wlen+1 ); d = dst->bv_val; if (!d) return LDAP_NO_MEMORY; for (i=0,c=(unsigned char *)src->bv_val; i < src->bv_len; c++,i++) { if ((*c & 0xf0) == 0xc0) { int j = *c & 0x0f; /* If this is the end of the string, or if the base * character is just a space, treat this as a regular * spacing character. */ if ((!c[1] || c[1] == 0x20) && accents[j]) { d += ldap_x_wc_to_utf8(d, accents[j], 6); } else if (cx_tab[j] && cx_tab[j][c[1]>>5] && /* We have a composite mapping for this pair */ (*cx_tab[j][c[1]>>5])[c[1]&0x1f]) { d += ldap_x_wc_to_utf8(d, (*cx_tab[j][c[1]>>5])[c[1]&0x1f], 6); } else { /* No mapping, just swap it around so the base * character comes first. */ d += ldap_x_wc_to_utf8(d, c[1], 6); d += ldap_x_wc_to_utf8(d, t61_tab[*c], 6); } c++; i++; continue; } else { d += ldap_x_wc_to_utf8(d, t61_tab[*c], 6); } } *d = '\0'; return LDAP_SUCCESS; } /* For the reverse mapping, we just pay attention to the Latin-oriented * code blocks. These are * 0000 - 007f Basic Latin * 0080 - 00ff Latin-1 Supplement * 0100 - 017f Latin Extended-A * 0180 - 024f Latin Extended-B * 1e00 - 1eff Latin Extended Additional * * We have a special case to map Ohm U2126 back to T.61 0xe0. All other * unrecognized characters are replaced with '?' 0x3f. */ static const wvec64 u000 = { 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, 0x0020, 0x0021, 0x0022, 0x00a6, 0x00a4, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f}; /* In this range, we've mapped caret to xc3/x20, backquote to xc1/x20, * and tilde to xc4/x20. T.61 (stupidly!) doesn't define these characters * on their own, even though it provides them as combiners for other * letters. T.61 doesn't define these pairings either, so this may just * have to be replaced with '?' 0x3f if other software can't cope with it. */ static const wvec64 u001 = { 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x003f, 0x005d, 0xc320, 0x005f, 0xc120, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x003f, 0x007c, 0x003f, 0xc420, 0x007f}; static const wvec64 u002 = { 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f, 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a8, 0x00a5, 0x003f, 0x00a7, 0xc820, 0x003f, 0x00e3, 0x00ab, 0x003f, 0x003f, 0x003f, 0xc520, 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0xc220, 0x00b5, 0x00b6, 0x00b7, 0xcb20, 0x003f, 0x00eb, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf}; static const wvec64 u003 = { 0xc141, 0xc241, 0xc341, 0xc441, 0xc841, 0xca41, 0x00e1, 0xcb43, 0xc145, 0xc245, 0xc345, 0xc845, 0xc149, 0xc249, 0xc349, 0xc849, 0x00e2, 0xc44e, 0xc14f, 0xc24f, 0xc34f, 0xc44f, 0xc84f, 0x00b4, 0x00e9, 0xc155, 0xc255, 0xc355, 0xc855, 0xc259, 0x00ec, 0x00fb, 0xc161, 0xc261, 0xc361, 0xc461, 0xc861, 0xca61, 0x00f1, 0xcb63, 0xc165, 0xc265, 0xc365, 0xc865, 0xc169, 0xc269, 0xc369, 0xc869, 0x00f3, 0xc46e, 0xc16f, 0xc26f, 0xc36f, 0xc46f, 0xc86f, 0x00b8, 0x00f9, 0xc175, 0xc275, 0xc375, 0xc875, 0xc279, 0x00fc, 0xc879}; /* These codes are used here but not defined by T.61: * x114 = xc6/x45, x115 = xc6/x65, x12c = xc6/x49, x12d = xc6/x69 */ static const wvec64 u010 = { 0xc541, 0xc561, 0xc641, 0xc661, 0xce41, 0xce61, 0xc243, 0xc263, 0xc343, 0xc363, 0xc743, 0xc763, 0xcf43, 0xcf63, 0xcf44, 0xcf64, 0x003f, 0x00f2, 0xc545, 0xc565, 0xc645, 0xc665, 0xc745, 0xc765, 0xce45, 0xce65, 0xcf45, 0xcf65, 0xc347, 0xc367, 0xc647, 0xc667, 0xc747, 0xc767, 0xcb47, 0xcb67, 0xc348, 0xc368, 0x00e4, 0x00f4, 0xc449, 0xc469, 0xc549, 0xc569, 0xc649, 0xc669, 0xce49, 0xce69, 0xc749, 0x00f5, 0x00e6, 0x00f6, 0xc34a, 0xc36a, 0xcb4b, 0xcb6b, 0x00f0, 0xc24c, 0xc26c, 0xcb4c, 0xcb6c, 0xcf4c, 0xcf6c, 0x00e7}; /* These codes are used here but not defined by T.61: * x14e = xc6/x4f, x14f = xc6/x6f */ static const wvec64 u011 = { 0x00f7, 0x00e8, 0x00f8, 0xc24e, 0xc26e, 0xcb4e, 0xcb6e, 0xcf4e, 0xcf6e, 0x00ef, 0x00ee, 0x00fe, 0xc54f, 0xc56f, 0xc64f, 0xc66f, 0xcd4f, 0xcd6f, 0x00ea, 0x00fa, 0xc252, 0xc272, 0xcb52, 0xcb72, 0xcf52, 0xcf72, 0xc253, 0xc273, 0xc353, 0xc373, 0xcb53, 0xcb73, 0xcf53, 0xcf73, 0xcb54, 0xcb74, 0xcf54, 0xcf74, 0x00ed, 0x00fd, 0xc455, 0xc475, 0xc555, 0xc575, 0xc655, 0xc675, 0xca55, 0xca75, 0xcd55, 0xcd75, 0xce55, 0xce75, 0xc357, 0xc377, 0xc359, 0xc379, 0xc859, 0xc25a, 0xc27a, 0xc75a, 0xc77a, 0xcf5a, 0xcf7a, 0x003f}; /* All of the codes in this block are undefined in T.61. */ static const wvec64 u013 = { 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0xcf41, 0xcf61, 0xcf49, 0xcf69, 0xcf4f, 0xcf6f, 0xcf55, 0xcf75, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0xc5e1, 0xc5f1, 0x003f, 0x003f, 0xcf47, 0xcf67, 0xcf4b, 0xcf6b, 0xce4f, 0xce6f, 0x003f, 0x003f, 0x003f, 0x003f, 0xcf6a, 0x003f, 0x003f, 0x003f, 0xc247, 0xc267, 0x003f, 0x003f, 0xc14e, 0xc16e, 0x003f, 0x003f, 0xc2e1, 0xc2f1, 0x003f, 0x003f}; /* All of the codes in this block are undefined in T.61. */ static const wvec64 u020 = { 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0xcf48, 0xcf68, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0xc741, 0xc761, 0xcb45, 0xcb65, 0x003f, 0x003f, 0x003f, 0x003f, 0xc74f, 0xc76f, 0x003f, 0x003f, 0xc559, 0xc579, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f}; static const wvec64 u023 = { 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0xcf20, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0xc620, 0xc720, 0xca20, 0xce20, 0x003f, 0xcd20, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f}; /* These are the non-spacing characters by themselves. They should * never appear by themselves in actual text. */ static const wvec64 u030 = { 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x003f, 0x00c6, 0x00c7, 0x00c8, 0x003f, 0x00ca, 0x00cd, 0x00cf, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x00cb, 0x00ce, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x00cc, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f}; /* None of the following blocks are defined in T.61. */ static const wvec64 u1e0 = { 0x003f, 0x003f, 0xc742, 0xc762, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0xc744, 0xc764, 0x003f, 0x003f, 0x003f, 0x003f, 0xcb44, 0xcb64, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0xc746, 0xc766, 0xc547, 0xc567, 0xc748, 0xc768, 0x003f, 0x003f, 0xc848, 0xc868, 0xcb48, 0xcb68, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0xc24b, 0xc26b, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0xc24d, 0xc26d, }; static const wvec64 u1e1 = { 0xc74d, 0xc76d, 0x003f, 0x003f, 0xc74e, 0xc76e, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0xc250, 0xc270, 0xc750, 0xc770, 0xc752, 0xc772, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0xc753, 0xc773, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0xc754, 0xc774, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0xc456, 0xc476, 0x003f, 0x003f, }; static const wvec64 u1e2 = { 0xc157, 0xc177, 0xc257, 0xc277, 0xc857, 0xc877, 0xc757, 0xc777, 0x003f, 0x003f, 0xc758, 0xc778, 0xc858, 0xc878, 0xc759, 0xc779, 0xc35a, 0xc37a, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0xc874, 0xca77, 0xca79, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0xc445, 0xc465, 0x003f, 0x003f, }; static const wvec64 u1e3 = { 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0xc159, 0xc179, 0x003f, 0x003f, 0x003f, 0x003f, 0xc459, 0xc479, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, }; static const wvec64 *wc00[] = { &u000, &u001, &u002, &u003, &u010, &u011, NULL, &u013, &u020, NULL, NULL, &u023, &u030, NULL, NULL, NULL}; static const wvec64 *wc1e[] = { &u1e0, &u1e1, &u1e2, &u1e3}; int ldap_utf8s_to_t61s( struct berval *src, struct berval *dst ) { char *c, *d; wchar_t tmp; int i, j, tlen = 0; /* Just count the length of the T.61 result first */ for (i=0,c=src->bv_val; i < src->bv_len;) { j = ldap_x_utf8_to_wc( &tmp, c ); if (j == -1) return LDAP_INVALID_SYNTAX; switch (tmp >> 8) { case 0x00: case 0x01: case 0x02: case 0x03: if (wc00[tmp >> 6] && ((*wc00[tmp >> 6])[tmp & 0x3f] & 0xff00)) { tlen++; } tlen++; break; case 0x1e: if ((*wc1e[(tmp >> 6) & 3])[tmp & 0x3f] & 0xff00) { tlen++; } case 0x21: default: tlen ++; break; } i += j; c += j; } dst->bv_len = tlen; dst->bv_val = LDAP_MALLOC( tlen+1 ); if (!dst->bv_val) return LDAP_NO_MEMORY; d = dst->bv_val; for (i=0,c=src->bv_val; i < src->bv_len;) { j = ldap_x_utf8_to_wc( &tmp, c ); switch (tmp >> 8) { case 0x00: case 0x01: case 0x02: if (wc00[tmp >> 6]) { tmp = (*wc00[tmp >> 6])[tmp & 0x3f]; if (tmp & 0xff00) *d++ = (tmp >> 8); *d++ = tmp & 0xff; } else { *d++ = 0x3f; } break; case 0x03: /* swap order of non-spacing characters */ if (wc00[tmp >> 6]) { wchar_t t2 = (*wc00[tmp >> 6])[tmp & 0x3f]; if (t2 != 0x3f) { d[0] = d[-1]; d[-1] = t2; d++; } else { *d++ = 0x3f; } } else { *d++ = 0x3f; } break; case 0x1e: tmp = (*wc1e[(tmp >> 6) & 3])[tmp & 0x3f]; if (tmp & 0xff00) *d++ = (tmp >> 8); *d++ = tmp & 0xff; break; case 0x21: if (tmp == 0x2126) { *d++ = 0xe0; break; } /* FALLTHRU */ default: *d++ = 0x3f; break; } i += j; c += j; } *d = '\0'; return LDAP_SUCCESS; } openldap-2.4.42+dfsg/libraries/libldap/gssapi.c0000644000175000017500000005503212563404150020052 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Author: Stefan Metzmacher * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #include "portable.h" #include #include #include #include #include #include #include #include #ifdef HAVE_LIMITS_H #include #endif #include "ldap-int.h" #ifdef HAVE_GSSAPI #ifdef HAVE_GSSAPI_GSSAPI_H #include #else #include #endif static char * gsserrstr( char *buf, ber_len_t buf_len, gss_OID mech, int gss_rc, OM_uint32 minor_status ) { OM_uint32 min2; gss_buffer_desc mech_msg = GSS_C_EMPTY_BUFFER; gss_buffer_desc gss_msg = GSS_C_EMPTY_BUFFER; gss_buffer_desc minor_msg = GSS_C_EMPTY_BUFFER; OM_uint32 msg_ctx = 0; if (buf == NULL) { return NULL; } if (buf_len == 0) { return NULL; } #ifdef HAVE_GSS_OID_TO_STR gss_oid_to_str(&min2, mech, &mech_msg); #endif gss_display_status(&min2, gss_rc, GSS_C_GSS_CODE, mech, &msg_ctx, &gss_msg); gss_display_status(&min2, minor_status, GSS_C_MECH_CODE, mech, &msg_ctx, &minor_msg); snprintf(buf, buf_len, "gss_rc[%d:%*s] mech[%*s] minor[%u:%*s]", gss_rc, (int)gss_msg.length, (const char *)(gss_msg.value?gss_msg.value:""), (int)mech_msg.length, (const char *)(mech_msg.value?mech_msg.value:""), minor_status, (int)minor_msg.length, (const char *)(minor_msg.value?minor_msg.value:"")); gss_release_buffer(&min2, &mech_msg); gss_release_buffer(&min2, &gss_msg); gss_release_buffer(&min2, &minor_msg); buf[buf_len-1] = '\0'; return buf; } static void sb_sasl_gssapi_init( struct sb_sasl_generic_data *p, ber_len_t *min_send, ber_len_t *max_send, ber_len_t *max_recv ) { gss_ctx_id_t gss_ctx = (gss_ctx_id_t)p->ops_private; int gss_rc; OM_uint32 minor_status; gss_OID ctx_mech = GSS_C_NO_OID; OM_uint32 ctx_flags = 0; int conf_req_flag = 0; OM_uint32 max_input_size; gss_inquire_context(&minor_status, gss_ctx, NULL, NULL, NULL, &ctx_mech, &ctx_flags, NULL, NULL); if (ctx_flags & (GSS_C_CONF_FLAG)) { conf_req_flag = 1; } #if defined(HAVE_CYRUS_SASL) #define SEND_PREALLOC_SIZE SASL_MIN_BUFF_SIZE #else #define SEND_PREALLOC_SIZE 4096 #endif #define SEND_MAX_WIRE_SIZE 0x00A00000 #define RECV_MAX_WIRE_SIZE 0x0FFFFFFF #define FALLBACK_SEND_MAX_SIZE 0x009FFFB8 /* from MIT 1.5.x */ gss_rc = gss_wrap_size_limit(&minor_status, gss_ctx, conf_req_flag, GSS_C_QOP_DEFAULT, SEND_MAX_WIRE_SIZE, &max_input_size); if ( gss_rc != GSS_S_COMPLETE ) { char msg[256]; ber_log_printf( LDAP_DEBUG_ANY, p->sbiod->sbiod_sb->sb_debug, "sb_sasl_gssapi_init: failed to wrap size limit: %s\n", gsserrstr( msg, sizeof(msg), ctx_mech, gss_rc, minor_status ) ); ber_log_printf( LDAP_DEBUG_ANY, p->sbiod->sbiod_sb->sb_debug, "sb_sasl_gssapi_init: fallback to default wrap size limit\n"); /* * some libgssglue/libgssapi versions * have a broken gss_wrap_size_limit() * implementation */ max_input_size = FALLBACK_SEND_MAX_SIZE; } *min_send = SEND_PREALLOC_SIZE; *max_send = max_input_size; *max_recv = RECV_MAX_WIRE_SIZE; } static ber_int_t sb_sasl_gssapi_encode( struct sb_sasl_generic_data *p, unsigned char *buf, ber_len_t len, Sockbuf_Buf *dst ) { gss_ctx_id_t gss_ctx = (gss_ctx_id_t)p->ops_private; int gss_rc; OM_uint32 minor_status; gss_buffer_desc unwrapped, wrapped; gss_OID ctx_mech = GSS_C_NO_OID; OM_uint32 ctx_flags = 0; int conf_req_flag = 0; int conf_state; unsigned char *b; ber_len_t pkt_len; unwrapped.value = buf; unwrapped.length = len; gss_inquire_context(&minor_status, gss_ctx, NULL, NULL, NULL, &ctx_mech, &ctx_flags, NULL, NULL); if (ctx_flags & (GSS_C_CONF_FLAG)) { conf_req_flag = 1; } gss_rc = gss_wrap(&minor_status, gss_ctx, conf_req_flag, GSS_C_QOP_DEFAULT, &unwrapped, &conf_state, &wrapped); if ( gss_rc != GSS_S_COMPLETE ) { char msg[256]; ber_log_printf( LDAP_DEBUG_ANY, p->sbiod->sbiod_sb->sb_debug, "sb_sasl_gssapi_encode: failed to encode packet: %s\n", gsserrstr( msg, sizeof(msg), ctx_mech, gss_rc, minor_status ) ); return -1; } if ( conf_req_flag && conf_state == 0 ) { ber_log_printf( LDAP_DEBUG_ANY, p->sbiod->sbiod_sb->sb_debug, "sb_sasl_gssapi_encode: GSS_C_CONF_FLAG was ignored by our gss_wrap()\n" ); return -1; } pkt_len = 4 + wrapped.length; /* Grow the packet buffer if neccessary */ if ( dst->buf_size < pkt_len && ber_pvt_sb_grow_buffer( dst, pkt_len ) < 0 ) { ber_log_printf( LDAP_DEBUG_ANY, p->sbiod->sbiod_sb->sb_debug, "sb_sasl_gssapi_encode: failed to grow the buffer to %lu bytes\n", pkt_len ); return -1; } dst->buf_end = pkt_len; b = (unsigned char *)dst->buf_base; b[0] = (unsigned char)(wrapped.length >> 24); b[1] = (unsigned char)(wrapped.length >> 16); b[2] = (unsigned char)(wrapped.length >> 8); b[3] = (unsigned char)(wrapped.length >> 0); /* copy the wrapped blob to the right location */ memcpy(b + 4, wrapped.value, wrapped.length); gss_release_buffer(&minor_status, &wrapped); return 0; } static ber_int_t sb_sasl_gssapi_decode( struct sb_sasl_generic_data *p, const Sockbuf_Buf *src, Sockbuf_Buf *dst ) { gss_ctx_id_t gss_ctx = (gss_ctx_id_t)p->ops_private; int gss_rc; OM_uint32 minor_status; gss_buffer_desc unwrapped, wrapped; gss_OID ctx_mech = GSS_C_NO_OID; OM_uint32 ctx_flags = 0; int conf_req_flag = 0; int conf_state; unsigned char *b; wrapped.value = src->buf_base + 4; wrapped.length = src->buf_end - 4; gss_inquire_context(&minor_status, gss_ctx, NULL, NULL, NULL, &ctx_mech, &ctx_flags, NULL, NULL); if (ctx_flags & (GSS_C_CONF_FLAG)) { conf_req_flag = 1; } gss_rc = gss_unwrap(&minor_status, gss_ctx, &wrapped, &unwrapped, &conf_state, GSS_C_QOP_DEFAULT); if ( gss_rc != GSS_S_COMPLETE ) { char msg[256]; ber_log_printf( LDAP_DEBUG_ANY, p->sbiod->sbiod_sb->sb_debug, "sb_sasl_gssapi_decode: failed to decode packet: %s\n", gsserrstr( msg, sizeof(msg), ctx_mech, gss_rc, minor_status ) ); return -1; } if ( conf_req_flag && conf_state == 0 ) { ber_log_printf( LDAP_DEBUG_ANY, p->sbiod->sbiod_sb->sb_debug, "sb_sasl_gssapi_encode: GSS_C_CONF_FLAG was ignored by our peer\n" ); return -1; } /* Grow the packet buffer if neccessary */ if ( dst->buf_size < unwrapped.length && ber_pvt_sb_grow_buffer( dst, unwrapped.length ) < 0 ) { ber_log_printf( LDAP_DEBUG_ANY, p->sbiod->sbiod_sb->sb_debug, "sb_sasl_gssapi_decode: failed to grow the buffer to %lu bytes\n", unwrapped.length ); return -1; } dst->buf_end = unwrapped.length; b = (unsigned char *)dst->buf_base; /* copy the wrapped blob to the right location */ memcpy(b, unwrapped.value, unwrapped.length); gss_release_buffer(&minor_status, &unwrapped); return 0; } static void sb_sasl_gssapi_reset_buf( struct sb_sasl_generic_data *p, Sockbuf_Buf *buf ) { ber_pvt_sb_buf_destroy( buf ); } static void sb_sasl_gssapi_fini( struct sb_sasl_generic_data *p ) { } static const struct sb_sasl_generic_ops sb_sasl_gssapi_ops = { sb_sasl_gssapi_init, sb_sasl_gssapi_encode, sb_sasl_gssapi_decode, sb_sasl_gssapi_reset_buf, sb_sasl_gssapi_fini }; static int sb_sasl_gssapi_install( Sockbuf *sb, gss_ctx_id_t gss_ctx ) { struct sb_sasl_generic_install install_arg; install_arg.ops = &sb_sasl_gssapi_ops; install_arg.ops_private = gss_ctx; return ldap_pvt_sasl_generic_install( sb, &install_arg ); } static void sb_sasl_gssapi_remove( Sockbuf *sb ) { ldap_pvt_sasl_generic_remove( sb ); } static int map_gsserr2ldap( LDAP *ld, gss_OID mech, int gss_rc, OM_uint32 minor_status ) { char msg[256]; Debug( LDAP_DEBUG_ANY, "%s\n", gsserrstr( msg, sizeof(msg), mech, gss_rc, minor_status ), NULL, NULL ); if (gss_rc == GSS_S_COMPLETE) { ld->ld_errno = LDAP_SUCCESS; } else if (GSS_CALLING_ERROR(gss_rc)) { ld->ld_errno = LDAP_LOCAL_ERROR; } else if (GSS_ROUTINE_ERROR(gss_rc)) { ld->ld_errno = LDAP_INAPPROPRIATE_AUTH; } else if (gss_rc == GSS_S_CONTINUE_NEEDED) { ld->ld_errno = LDAP_SASL_BIND_IN_PROGRESS; } else if (GSS_SUPPLEMENTARY_INFO(gss_rc)) { ld->ld_errno = LDAP_AUTH_UNKNOWN; } else if (GSS_ERROR(gss_rc)) { ld->ld_errno = LDAP_AUTH_UNKNOWN; } else { ld->ld_errno = LDAP_OTHER; } return ld->ld_errno; } static int ldap_gssapi_get_rootdse_infos ( LDAP *ld, char **pmechlist, char **pldapServiceName, char **pdnsHostName ) { /* we need to query the server for supported mechs anyway */ LDAPMessage *res, *e; char *attrs[] = { "supportedSASLMechanisms", "ldapServiceName", "dnsHostName", NULL }; char **values, *mechlist; char *ldapServiceName = NULL; char *dnsHostName = NULL; int rc; Debug( LDAP_DEBUG_TRACE, "ldap_gssapi_get_rootdse_infos\n", 0, 0, 0 ); rc = ldap_search_s( ld, "", LDAP_SCOPE_BASE, NULL, attrs, 0, &res ); if ( rc != LDAP_SUCCESS ) { return ld->ld_errno; } e = ldap_first_entry( ld, res ); if ( e == NULL ) { ldap_msgfree( res ); if ( ld->ld_errno == LDAP_SUCCESS ) { ld->ld_errno = LDAP_NO_SUCH_OBJECT; } return ld->ld_errno; } values = ldap_get_values( ld, e, "supportedSASLMechanisms" ); if ( values == NULL ) { ldap_msgfree( res ); ld->ld_errno = LDAP_NO_SUCH_ATTRIBUTE; return ld->ld_errno; } mechlist = ldap_charray2str( values, " " ); if ( mechlist == NULL ) { LDAP_VFREE( values ); ldap_msgfree( res ); ld->ld_errno = LDAP_NO_MEMORY; return ld->ld_errno; } LDAP_VFREE( values ); values = ldap_get_values( ld, e, "ldapServiceName" ); if ( values == NULL ) { goto get_dns_host_name; } ldapServiceName = ldap_charray2str( values, " " ); if ( ldapServiceName == NULL ) { LDAP_FREE( mechlist ); LDAP_VFREE( values ); ldap_msgfree( res ); ld->ld_errno = LDAP_NO_MEMORY; return ld->ld_errno; } LDAP_VFREE( values ); get_dns_host_name: values = ldap_get_values( ld, e, "dnsHostName" ); if ( values == NULL ) { goto done; } dnsHostName = ldap_charray2str( values, " " ); if ( dnsHostName == NULL ) { LDAP_FREE( mechlist ); LDAP_FREE( ldapServiceName ); LDAP_VFREE( values ); ldap_msgfree( res ); ld->ld_errno = LDAP_NO_MEMORY; return ld->ld_errno; } LDAP_VFREE( values ); done: ldap_msgfree( res ); *pmechlist = mechlist; *pldapServiceName = ldapServiceName; *pdnsHostName = dnsHostName; return LDAP_SUCCESS; } static int check_for_gss_spnego_support( LDAP *ld, const char *mechs_str ) { int rc; char **mechs_list = NULL; mechs_list = ldap_str2charray( mechs_str, " " ); if ( mechs_list == NULL ) { ld->ld_errno = LDAP_NO_MEMORY; return ld->ld_errno; } rc = ldap_charray_inlist( mechs_list, "GSS-SPNEGO" ); ldap_charray_free( mechs_list ); if ( rc != 1) { ld->ld_errno = LDAP_STRONG_AUTH_NOT_SUPPORTED; return ld->ld_errno; } return LDAP_SUCCESS; } static int guess_service_principal( LDAP *ld, const char *ldapServiceName, const char *dnsHostName, gss_name_t *principal ) { gss_buffer_desc input_name; /* GSS_KRB5_NT_PRINCIPAL_NAME */ gss_OID_desc nt_principal = {10, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x01"}; const char *host = ld->ld_defconn->lconn_server->lud_host; OM_uint32 minor_status; int gss_rc; int ret; size_t svc_principal_size; char *svc_principal = NULL; const char *principal_fmt = NULL; const char *str = NULL; const char *givenstr = NULL; const char *ignore = "not_defined_in_RFC4178@please_ignore"; int allow_remote = 0; if (ldapServiceName) { givenstr = strchr(ldapServiceName, ':'); if (givenstr && givenstr[1]) { givenstr++; if (strcmp(givenstr, ignore) == 0) { givenstr = NULL; } } else { givenstr = NULL; } } if ( ld->ld_options.ldo_gssapi_options & LDAP_GSSAPI_OPT_ALLOW_REMOTE_PRINCIPAL ) { allow_remote = 1; } if (allow_remote && givenstr) { principal_fmt = "%s"; svc_principal_size = strlen(givenstr) + 1; str = givenstr; } else if (allow_remote && dnsHostName) { principal_fmt = "ldap/%s"; svc_principal_size = STRLENOF("ldap/") + strlen(dnsHostName) + 1; str = dnsHostName; } else { principal_fmt = "ldap/%s"; svc_principal_size = STRLENOF("ldap/") + strlen(host) + 1; str = host; } svc_principal = (char*) ldap_memalloc(svc_principal_size * sizeof(char)); if ( svc_principal == NULL ) { ld->ld_errno = LDAP_NO_MEMORY; return ld->ld_errno; } ret = snprintf( svc_principal, svc_principal_size, principal_fmt, str ); if (ret < 0 || (size_t)ret >= svc_principal_size) { ld->ld_errno = LDAP_LOCAL_ERROR; return ld->ld_errno; } Debug( LDAP_DEBUG_TRACE, "principal for host[%s]: '%s'\n", host, svc_principal, 0 ); input_name.value = svc_principal; input_name.length = (size_t)ret; gss_rc = gss_import_name( &minor_status, &input_name, &nt_principal, principal ); ldap_memfree( svc_principal ); if ( gss_rc != GSS_S_COMPLETE ) { return map_gsserr2ldap( ld, GSS_C_NO_OID, gss_rc, minor_status ); } return LDAP_SUCCESS; } void ldap_int_gssapi_close( LDAP *ld, LDAPConn *lc ) { if ( lc && lc->lconn_gss_ctx ) { OM_uint32 minor_status; OM_uint32 ctx_flags = 0; gss_ctx_id_t old_gss_ctx = GSS_C_NO_CONTEXT; old_gss_ctx = (gss_ctx_id_t)lc->lconn_gss_ctx; gss_inquire_context(&minor_status, old_gss_ctx, NULL, NULL, NULL, NULL, &ctx_flags, NULL, NULL); if (!( ld->ld_options.ldo_gssapi_options & LDAP_GSSAPI_OPT_DO_NOT_FREE_GSS_CONTEXT )) { gss_delete_sec_context( &minor_status, &old_gss_ctx, GSS_C_NO_BUFFER ); } lc->lconn_gss_ctx = GSS_C_NO_CONTEXT; if (ctx_flags & (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG)) { /* remove wrapping layer */ sb_sasl_gssapi_remove( lc->lconn_sb ); } } } static void ldap_int_gssapi_setup( LDAP *ld, LDAPConn *lc, gss_ctx_id_t gss_ctx) { OM_uint32 minor_status; OM_uint32 ctx_flags = 0; ldap_int_gssapi_close( ld, lc ); gss_inquire_context(&minor_status, gss_ctx, NULL, NULL, NULL, NULL, &ctx_flags, NULL, NULL); lc->lconn_gss_ctx = gss_ctx; if (ctx_flags & (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG)) { /* setup wrapping layer */ sb_sasl_gssapi_install( lc->lconn_sb, gss_ctx ); } } #ifdef LDAP_R_COMPILE ldap_pvt_thread_mutex_t ldap_int_gssapi_mutex; #endif static int ldap_int_gss_spnego_bind_s( LDAP *ld ) { int rc; int gss_rc; OM_uint32 minor_status; char *mechlist = NULL; char *ldapServiceName = NULL; char *dnsHostName = NULL; gss_OID_set supported_mechs = GSS_C_NO_OID_SET; int spnego_support = 0; #define __SPNEGO_OID_LENGTH 6 #define __SPNEGO_OID "\053\006\001\005\005\002" gss_OID_desc spnego_oid = {__SPNEGO_OID_LENGTH, __SPNEGO_OID}; gss_OID req_mech = GSS_C_NO_OID; gss_OID ret_mech = GSS_C_NO_OID; gss_ctx_id_t gss_ctx = GSS_C_NO_CONTEXT; gss_name_t principal = GSS_C_NO_NAME; OM_uint32 req_flags; OM_uint32 ret_flags; gss_buffer_desc input_token, output_token = GSS_C_EMPTY_BUFFER; struct berval cred, *scred = NULL; LDAP_MUTEX_LOCK( &ldap_int_gssapi_mutex ); /* get information from RootDSE entry */ rc = ldap_gssapi_get_rootdse_infos ( ld, &mechlist, &ldapServiceName, &dnsHostName); if ( rc != LDAP_SUCCESS ) { return rc; } /* check that the server supports GSS-SPNEGO */ rc = check_for_gss_spnego_support( ld, mechlist ); if ( rc != LDAP_SUCCESS ) { goto rc_error; } /* prepare new gss_ctx_id_t */ rc = guess_service_principal( ld, ldapServiceName, dnsHostName, &principal ); if ( rc != LDAP_SUCCESS ) { goto rc_error; } /* see if our gssapi library supports spnego */ gss_rc = gss_indicate_mechs( &minor_status, &supported_mechs ); if ( gss_rc != GSS_S_COMPLETE ) { goto gss_error; } gss_rc = gss_test_oid_set_member( &minor_status, &spnego_oid, supported_mechs, &spnego_support); gss_release_oid_set( &minor_status, &supported_mechs); if ( gss_rc != GSS_S_COMPLETE ) { goto gss_error; } if ( spnego_support != 0 ) { req_mech = &spnego_oid; } req_flags = ld->ld_options.ldo_gssapi_flags; req_flags |= GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG; /* * loop around gss_init_sec_context() and ldap_sasl_bind_s() */ input_token.value = NULL; input_token.length = 0; gss_rc = gss_init_sec_context(&minor_status, GSS_C_NO_CREDENTIAL, &gss_ctx, principal, req_mech, req_flags, 0, NULL, &input_token, &ret_mech, &output_token, &ret_flags, NULL); if ( gss_rc == GSS_S_COMPLETE ) { rc = LDAP_INAPPROPRIATE_AUTH; goto rc_error; } if ( gss_rc != GSS_S_CONTINUE_NEEDED ) { goto gss_error; } while (1) { cred.bv_val = (char *)output_token.value; cred.bv_len = output_token.length; rc = ldap_sasl_bind_s( ld, NULL, "GSS-SPNEGO", &cred, NULL, NULL, &scred ); gss_release_buffer( &minor_status, &output_token ); if ( rc != LDAP_SUCCESS && rc != LDAP_SASL_BIND_IN_PROGRESS ) { goto rc_error; } if ( scred ) { input_token.value = scred->bv_val; input_token.length = scred->bv_len; } else { input_token.value = NULL; input_token.length = 0; } gss_rc = gss_init_sec_context(&minor_status, GSS_C_NO_CREDENTIAL, &gss_ctx, principal, req_mech, req_flags, 0, NULL, &input_token, &ret_mech, &output_token, &ret_flags, NULL); if ( scred ) { ber_bvfree( scred ); } if ( gss_rc == GSS_S_COMPLETE ) { gss_release_buffer( &minor_status, &output_token ); break; } if ( gss_rc != GSS_S_CONTINUE_NEEDED ) { goto gss_error; } } ldap_int_gssapi_setup( ld, ld->ld_defconn, gss_ctx); gss_ctx = GSS_C_NO_CONTEXT; rc = LDAP_SUCCESS; goto rc_error; gss_error: rc = map_gsserr2ldap( ld, (ret_mech != GSS_C_NO_OID ? ret_mech : req_mech ), gss_rc, minor_status ); rc_error: LDAP_MUTEX_UNLOCK( &ldap_int_gssapi_mutex ); LDAP_FREE( mechlist ); LDAP_FREE( ldapServiceName ); LDAP_FREE( dnsHostName ); gss_release_buffer( &minor_status, &output_token ); if ( gss_ctx != GSS_C_NO_CONTEXT ) { gss_delete_sec_context( &minor_status, &gss_ctx, GSS_C_NO_BUFFER ); } if ( principal != GSS_C_NO_NAME ) { gss_release_name( &minor_status, &principal ); } return rc; } int ldap_int_gssapi_config( struct ldapoptions *lo, int option, const char *arg ) { int ok = 0; switch( option ) { case LDAP_OPT_SIGN: if (!arg) { } else if (strcasecmp(arg, "on") == 0) { ok = 1; } else if (strcasecmp(arg, "yes") == 0) { ok = 1; } else if (strcasecmp(arg, "true") == 0) { ok = 1; } if (ok) { lo->ldo_gssapi_flags |= GSS_C_INTEG_FLAG; } return 0; case LDAP_OPT_ENCRYPT: if (!arg) { } else if (strcasecmp(arg, "on") == 0) { ok = 1; } else if (strcasecmp(arg, "yes") == 0) { ok = 1; } else if (strcasecmp(arg, "true") == 0) { ok = 1; } if (ok) { lo->ldo_gssapi_flags |= GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG; } return 0; case LDAP_OPT_X_GSSAPI_ALLOW_REMOTE_PRINCIPAL: if (!arg) { } else if (strcasecmp(arg, "on") == 0) { ok = 1; } else if (strcasecmp(arg, "yes") == 0) { ok = 1; } else if (strcasecmp(arg, "true") == 0) { ok = 1; } if (ok) { lo->ldo_gssapi_options |= LDAP_GSSAPI_OPT_ALLOW_REMOTE_PRINCIPAL; } return 0; } return -1; } int ldap_int_gssapi_get_option( LDAP *ld, int option, void *arg ) { if ( ld == NULL ) return -1; switch ( option ) { case LDAP_OPT_SSPI_FLAGS: * (unsigned *) arg = (unsigned) ld->ld_options.ldo_gssapi_flags; break; case LDAP_OPT_SIGN: if ( ld->ld_options.ldo_gssapi_flags & GSS_C_INTEG_FLAG ) { * (int *) arg = (int)-1; } else { * (int *) arg = (int)0; } break; case LDAP_OPT_ENCRYPT: if ( ld->ld_options.ldo_gssapi_flags & GSS_C_CONF_FLAG ) { * (int *) arg = (int)-1; } else { * (int *) arg = (int)0; } break; case LDAP_OPT_SASL_METHOD: * (char **) arg = LDAP_STRDUP("GSS-SPNEGO"); break; case LDAP_OPT_SECURITY_CONTEXT: if ( ld->ld_defconn && ld->ld_defconn->lconn_gss_ctx ) { * (gss_ctx_id_t *) arg = (gss_ctx_id_t)ld->ld_defconn->lconn_gss_ctx; } else { * (gss_ctx_id_t *) arg = GSS_C_NO_CONTEXT; } break; case LDAP_OPT_X_GSSAPI_DO_NOT_FREE_CONTEXT: if ( ld->ld_options.ldo_gssapi_options & LDAP_GSSAPI_OPT_DO_NOT_FREE_GSS_CONTEXT ) { * (int *) arg = (int)-1; } else { * (int *) arg = (int)0; } break; case LDAP_OPT_X_GSSAPI_ALLOW_REMOTE_PRINCIPAL: if ( ld->ld_options.ldo_gssapi_options & LDAP_GSSAPI_OPT_ALLOW_REMOTE_PRINCIPAL ) { * (int *) arg = (int)-1; } else { * (int *) arg = (int)0; } break; default: return -1; } return 0; } int ldap_int_gssapi_set_option( LDAP *ld, int option, void *arg ) { if ( ld == NULL ) return -1; switch ( option ) { case LDAP_OPT_SSPI_FLAGS: if ( arg != LDAP_OPT_OFF ) { ld->ld_options.ldo_gssapi_flags = * (unsigned *)arg; } break; case LDAP_OPT_SIGN: if ( arg != LDAP_OPT_OFF ) { ld->ld_options.ldo_gssapi_flags |= GSS_C_INTEG_FLAG; } break; case LDAP_OPT_ENCRYPT: if ( arg != LDAP_OPT_OFF ) { ld->ld_options.ldo_gssapi_flags |= GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG; } break; case LDAP_OPT_SASL_METHOD: if ( arg != LDAP_OPT_OFF ) { const char *m = (const char *)arg; if ( strcmp( "GSS-SPNEGO", m ) != 0 ) { /* we currently only support GSS-SPNEGO */ return -1; } } break; case LDAP_OPT_SECURITY_CONTEXT: if ( arg != LDAP_OPT_OFF && ld->ld_defconn) { ldap_int_gssapi_setup( ld, ld->ld_defconn, (gss_ctx_id_t) arg); } break; case LDAP_OPT_X_GSSAPI_DO_NOT_FREE_CONTEXT: if ( arg != LDAP_OPT_OFF ) { ld->ld_options.ldo_gssapi_options |= LDAP_GSSAPI_OPT_DO_NOT_FREE_GSS_CONTEXT; } break; case LDAP_OPT_X_GSSAPI_ALLOW_REMOTE_PRINCIPAL: if ( arg != LDAP_OPT_OFF ) { ld->ld_options.ldo_gssapi_options |= LDAP_GSSAPI_OPT_ALLOW_REMOTE_PRINCIPAL; } break; default: return -1; } return 0; } #else /* HAVE_GSSAPI */ #define ldap_int_gss_spnego_bind_s(ld) LDAP_NOT_SUPPORTED #endif /* HAVE_GSSAPI */ int ldap_gssapi_bind( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *creds ) { return LDAP_NOT_SUPPORTED; } int ldap_gssapi_bind_s( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *creds ) { if ( dn != NULL ) { return LDAP_NOT_SUPPORTED; } if ( creds != NULL ) { return LDAP_NOT_SUPPORTED; } return ldap_int_gss_spnego_bind_s(ld); } openldap-2.4.42+dfsg/libraries/libldap/getentry.c0000644000175000017500000000457112563404150020427 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (c) 1990 Regents of the University of Michigan. * All rights reserved. */ #include "portable.h" #include #include #include #include #include #include "ldap-int.h" /* ARGSUSED */ LDAPMessage * ldap_first_entry( LDAP *ld, LDAPMessage *chain ) { assert( ld != NULL ); assert( LDAP_VALID( ld ) ); assert( chain != NULL ); return chain->lm_msgtype == LDAP_RES_SEARCH_ENTRY ? chain : ldap_next_entry( ld, chain ); } LDAPMessage * ldap_next_entry( LDAP *ld, LDAPMessage *entry ) { assert( ld != NULL ); assert( LDAP_VALID( ld ) ); assert( entry != NULL ); for( entry = entry->lm_chain; entry != NULL; entry = entry->lm_chain ) { if( entry->lm_msgtype == LDAP_RES_SEARCH_ENTRY ) { return( entry ); } } return( NULL ); } int ldap_count_entries( LDAP *ld, LDAPMessage *chain ) { int i; assert( ld != NULL ); assert( LDAP_VALID( ld ) ); for ( i = 0; chain != NULL; chain = chain->lm_chain ) { if( chain->lm_msgtype == LDAP_RES_SEARCH_ENTRY ) { i++; } } return( i ); } int ldap_get_entry_controls( LDAP *ld, LDAPMessage *entry, LDAPControl ***sctrls ) { int rc; BerElement be; assert( ld != NULL ); assert( LDAP_VALID( ld ) ); assert( entry != NULL ); assert( sctrls != NULL ); if ( entry->lm_msgtype != LDAP_RES_SEARCH_ENTRY ) { return LDAP_PARAM_ERROR; } /* make a local copy of the BerElement */ AC_MEMCPY(&be, entry->lm_ber, sizeof(be)); if ( ber_scanf( &be, "{xx" /*}*/ ) == LBER_ERROR ) { rc = LDAP_DECODING_ERROR; goto cleanup_and_return; } rc = ldap_pvt_get_controls( &be, sctrls ); cleanup_and_return: if( rc != LDAP_SUCCESS ) { ld->ld_errno = rc; if( ld->ld_matched != NULL ) { LDAP_FREE( ld->ld_matched ); ld->ld_matched = NULL; } if( ld->ld_error != NULL ) { LDAP_FREE( ld->ld_error ); ld->ld_error = NULL; } } return rc; } openldap-2.4.42+dfsg/libraries/libldap/bind.c0000644000175000017500000000623512563404150017501 0ustar ryanryan/* bind.c */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (c) 1990 Regents of the University of Michigan. * All rights reserved. */ #include "portable.h" #include #include #include #include #include #include "ldap-int.h" #include "ldap_log.h" /* * BindRequest ::= SEQUENCE { * version INTEGER, * name DistinguishedName, -- who * authentication CHOICE { * simple [0] OCTET STRING -- passwd * krbv42ldap [1] OCTET STRING -- OBSOLETE * krbv42dsa [2] OCTET STRING -- OBSOLETE * sasl [3] SaslCredentials -- LDAPv3 * } * } * * BindResponse ::= SEQUENCE { * COMPONENTS OF LDAPResult, * serverSaslCreds OCTET STRING OPTIONAL -- LDAPv3 * } * * (Source: RFC 2251) */ /* * ldap_bind - bind to the ldap server (and X.500). The dn and password * of the entry to which to bind are supplied, along with the authentication * method to use. The msgid of the bind request is returned on success, * -1 if there's trouble. ldap_result() should be called to find out the * outcome of the bind request. * * Example: * ldap_bind( ld, "cn=manager, o=university of michigan, c=us", "secret", * LDAP_AUTH_SIMPLE ) */ int ldap_bind( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *passwd, int authmethod ) { Debug( LDAP_DEBUG_TRACE, "ldap_bind\n", 0, 0, 0 ); switch ( authmethod ) { case LDAP_AUTH_SIMPLE: return( ldap_simple_bind( ld, dn, passwd ) ); #ifdef HAVE_GSSAPI case LDAP_AUTH_NEGOTIATE: return( ldap_gssapi_bind_s( ld, dn, passwd) ); #endif case LDAP_AUTH_SASL: /* user must use ldap_sasl_bind */ /* FALL-THRU */ default: ld->ld_errno = LDAP_AUTH_UNKNOWN; return( -1 ); } } /* * ldap_bind_s - bind to the ldap server (and X.500). The dn and password * of the entry to which to bind are supplied, along with the authentication * method to use. This routine just calls whichever bind routine is * appropriate and returns the result of the bind (e.g. LDAP_SUCCESS or * some other error indication). * * Examples: * ldap_bind_s( ld, "cn=manager, o=university of michigan, c=us", * "secret", LDAP_AUTH_SIMPLE ) * ldap_bind_s( ld, "cn=manager, o=university of michigan, c=us", * NULL, LDAP_AUTH_KRBV4 ) */ int ldap_bind_s( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *passwd, int authmethod ) { Debug( LDAP_DEBUG_TRACE, "ldap_bind_s\n", 0, 0, 0 ); switch ( authmethod ) { case LDAP_AUTH_SIMPLE: return( ldap_simple_bind_s( ld, dn, passwd ) ); #ifdef HAVE_GSSAPI case LDAP_AUTH_NEGOTIATE: return( ldap_gssapi_bind_s( ld, dn, passwd) ); #endif case LDAP_AUTH_SASL: /* user must use ldap_sasl_bind */ /* FALL-THRU */ default: return( ld->ld_errno = LDAP_AUTH_UNKNOWN ); } } openldap-2.4.42+dfsg/libraries/libldap/utf-8.c0000644000175000017500000003032312563404150017523 0ustar ryanryan/* utf-8.c -- Basic UTF-8 routines */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Basic UTF-8 routines * * These routines are "dumb". Though they understand UTF-8, * they don't grok Unicode. That is, they can push bits, * but don't have a clue what the bits represent. That's * good enough for use with the LDAP Client SDK. * * These routines are not optimized. */ #include "portable.h" #include #include #include #include #include #include "ldap_utf8.h" #include "ldap-int.h" #include "ldap_defaults.h" /* * return the number of bytes required to hold the * NULL-terminated UTF-8 string NOT INCLUDING the * termination. */ ber_len_t ldap_utf8_bytes( const char * p ) { ber_len_t bytes; for( bytes=0; p[bytes]; bytes++ ) { /* EMPTY */ ; } return bytes; } ber_len_t ldap_utf8_chars( const char * p ) { /* could be optimized and could check for invalid sequences */ ber_len_t chars=0; for( ; *p ; LDAP_UTF8_INCR(p) ) { chars++; } return chars; } /* return offset to next character */ int ldap_utf8_offset( const char * p ) { return LDAP_UTF8_NEXT(p) - p; } /* * Returns length indicated by first byte. */ const char ldap_utf8_lentab[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0 }; int ldap_utf8_charlen( const char * p ) { if (!(*p & 0x80)) return 1; return ldap_utf8_lentab[*(const unsigned char *)p ^ 0x80]; } /* * Make sure the UTF-8 char used the shortest possible encoding * returns charlen if valid, 0 if not. * * Here are the valid UTF-8 encodings, taken from RFC 2279 page 4. * The table is slightly modified from that of the RFC. * * UCS-4 range (hex) UTF-8 sequence (binary) * 0000 0000-0000 007F 0....... * 0000 0080-0000 07FF 110++++. 10...... * 0000 0800-0000 FFFF 1110++++ 10+..... 10...... * 0001 0000-001F FFFF 11110+++ 10++.... 10...... 10...... * 0020 0000-03FF FFFF 111110++ 10+++... 10...... 10...... 10...... * 0400 0000-7FFF FFFF 1111110+ 10++++.. 10...... 10...... 10...... 10...... * * The '.' bits are "don't cares". When validating a UTF-8 sequence, * at least one of the '+' bits must be set, otherwise the character * should have been encoded in fewer octets. Note that in the two-octet * case, only the first octet needs to be validated, and this is done * in the ldap_utf8_lentab[] above. */ /* mask of required bits in second octet */ #undef c #define c const char c ldap_utf8_mintab[] = { (c)0x20, (c)0x80, (c)0x80, (c)0x80, (c)0x80, (c)0x80, (c)0x80, (c)0x80, (c)0x80, (c)0x80, (c)0x80, (c)0x80, (c)0x80, (c)0x80, (c)0x80, (c)0x80, (c)0x30, (c)0x80, (c)0x80, (c)0x80, (c)0x80, (c)0x80, (c)0x80, (c)0x80, (c)0x38, (c)0x80, (c)0x80, (c)0x80, (c)0x3c, (c)0x80, (c)0x00, (c)0x00 }; #undef c int ldap_utf8_charlen2( const char * p ) { int i = LDAP_UTF8_CHARLEN( p ); if ( i > 2 ) { if ( !( ldap_utf8_mintab[*p & 0x1f] & p[1] ) ) i = 0; } return i; } /* conv UTF-8 to UCS-4, useful for comparisons */ ldap_ucs4_t ldap_x_utf8_to_ucs4( const char * p ) { const unsigned char *c = (const unsigned char *) p; ldap_ucs4_t ch; int len, i; static unsigned char mask[] = { 0, 0x7f, 0x1f, 0x0f, 0x07, 0x03, 0x01 }; len = LDAP_UTF8_CHARLEN2(p, len); if( len == 0 ) return LDAP_UCS4_INVALID; ch = c[0] & mask[len]; for(i=1; i < len; i++) { if ((c[i] & 0xc0) != 0x80) { return LDAP_UCS4_INVALID; } ch <<= 6; ch |= c[i] & 0x3f; } return ch; } /* conv UCS-4 to UTF-8, not used */ int ldap_x_ucs4_to_utf8( ldap_ucs4_t c, char *buf ) { int len=0; unsigned char* p = (unsigned char *) buf; /* not a valid Unicode character */ if ( c < 0 ) return 0; /* Just return length, don't convert */ if(buf == NULL) { if( c < 0x80 ) return 1; else if( c < 0x800 ) return 2; else if( c < 0x10000 ) return 3; else if( c < 0x200000 ) return 4; else if( c < 0x4000000 ) return 5; else return 6; } if( c < 0x80 ) { p[len++] = c; } else if( c < 0x800 ) { p[len++] = 0xc0 | ( c >> 6 ); p[len++] = 0x80 | ( c & 0x3f ); } else if( c < 0x10000 ) { p[len++] = 0xe0 | ( c >> 12 ); p[len++] = 0x80 | ( (c >> 6) & 0x3f ); p[len++] = 0x80 | ( c & 0x3f ); } else if( c < 0x200000 ) { p[len++] = 0xf0 | ( c >> 18 ); p[len++] = 0x80 | ( (c >> 12) & 0x3f ); p[len++] = 0x80 | ( (c >> 6) & 0x3f ); p[len++] = 0x80 | ( c & 0x3f ); } else if( c < 0x4000000 ) { p[len++] = 0xf8 | ( c >> 24 ); p[len++] = 0x80 | ( (c >> 18) & 0x3f ); p[len++] = 0x80 | ( (c >> 12) & 0x3f ); p[len++] = 0x80 | ( (c >> 6) & 0x3f ); p[len++] = 0x80 | ( c & 0x3f ); } else /* if( c < 0x80000000 ) */ { p[len++] = 0xfc | ( c >> 30 ); p[len++] = 0x80 | ( (c >> 24) & 0x3f ); p[len++] = 0x80 | ( (c >> 18) & 0x3f ); p[len++] = 0x80 | ( (c >> 12) & 0x3f ); p[len++] = 0x80 | ( (c >> 6) & 0x3f ); p[len++] = 0x80 | ( c & 0x3f ); } return len; } #define LDAP_UCS_UTF8LEN(c) \ c < 0 ? 0 : (c < 0x80 ? 1 : (c < 0x800 ? 2 : (c < 0x10000 ? 3 : \ (c < 0x200000 ? 4 : (c < 0x4000000 ? 5 : 6))))) /* Convert a string to UTF-8 format. The input string is expected to * have characters of 1, 2, or 4 octets (in network byte order) * corresponding to the ASN.1 T61STRING, BMPSTRING, and UNIVERSALSTRING * types respectively. (Here T61STRING just means that there is one * octet per character and characters may use the high bit of the octet. * The characters are assumed to use ISO mappings, no provision is made * for converting from T.61 coding rules to Unicode.) */ int ldap_ucs_to_utf8s( struct berval *ucs, int csize, struct berval *utf8s ) { unsigned char *in, *end; char *ptr; ldap_ucs4_t u; int i, l = 0; utf8s->bv_val = NULL; utf8s->bv_len = 0; in = (unsigned char *)ucs->bv_val; /* Make sure we stop at an even multiple of csize */ end = in + ( ucs->bv_len & ~(csize-1) ); for (; in < end; ) { u = *in++; if (csize > 1) { u <<= 8; u |= *in++; } if (csize > 2) { u <<= 8; u |= *in++; u <<= 8; u |= *in++; } i = LDAP_UCS_UTF8LEN(u); if (i == 0) return LDAP_INVALID_SYNTAX; l += i; } utf8s->bv_val = LDAP_MALLOC( l+1 ); if (utf8s->bv_val == NULL) return LDAP_NO_MEMORY; utf8s->bv_len = l; ptr = utf8s->bv_val; for (in = (unsigned char *)ucs->bv_val; in < end; ) { u = *in++; if (csize > 1) { u <<= 8; u |= *in++; } if (csize > 2) { u <<= 8; u |= *in++; u <<= 8; u |= *in++; } ptr += ldap_x_ucs4_to_utf8(u, ptr); } *ptr = '\0'; return LDAP_SUCCESS; } /* * Advance to the next UTF-8 character * * Ignores length of multibyte character, instead rely on * continuation markers to find start of next character. * This allows for "resyncing" of when invalid characters * are provided provided the start of the next character * is appears within the 6 bytes examined. */ char* ldap_utf8_next( const char * p ) { int i; const unsigned char *u = (const unsigned char *) p; if( LDAP_UTF8_ISASCII(u) ) { return (char *) &p[1]; } for( i=1; i<6; i++ ) { if ( ( u[i] & 0xc0 ) != 0x80 ) { return (char *) &p[i]; } } return (char *) &p[i]; } /* * Advance to the previous UTF-8 character * * Ignores length of multibyte character, instead rely on * continuation markers to find start of next character. * This allows for "resyncing" of when invalid characters * are provided provided the start of the next character * is appears within the 6 bytes examined. */ char* ldap_utf8_prev( const char * p ) { int i; const unsigned char *u = (const unsigned char *) p; for( i=-1; i>-6 ; i-- ) { if ( ( u[i] & 0xc0 ) != 0x80 ) { return (char *) &p[i]; } } return (char *) &p[i]; } /* * Copy one UTF-8 character from src to dst returning * number of bytes copied. * * Ignores length of multibyte character, instead rely on * continuation markers to find start of next character. * This allows for "resyncing" of when invalid characters * are provided provided the start of the next character * is appears within the 6 bytes examined. */ int ldap_utf8_copy( char* dst, const char *src ) { int i; const unsigned char *u = (const unsigned char *) src; dst[0] = src[0]; if( LDAP_UTF8_ISASCII(u) ) { return 1; } for( i=1; i<6; i++ ) { if ( ( u[i] & 0xc0 ) != 0x80 ) { return i; } dst[i] = src[i]; } return i; } #ifndef UTF8_ALPHA_CTYPE /* * UTF-8 ctype routines * Only deals with characters < 0x80 (ie: US-ASCII) */ int ldap_utf8_isascii( const char * p ) { unsigned c = * (const unsigned char *) p; return LDAP_ASCII(c); } int ldap_utf8_isdigit( const char * p ) { unsigned c = * (const unsigned char *) p; if(!LDAP_ASCII(c)) return 0; return LDAP_DIGIT( c ); } int ldap_utf8_isxdigit( const char * p ) { unsigned c = * (const unsigned char *) p; if(!LDAP_ASCII(c)) return 0; return LDAP_HEX(c); } int ldap_utf8_isspace( const char * p ) { unsigned c = * (const unsigned char *) p; if(!LDAP_ASCII(c)) return 0; switch(c) { case ' ': case '\t': case '\n': case '\r': case '\v': case '\f': return 1; } return 0; } /* * These are not needed by the C SDK and are * not "good enough" for general use. */ int ldap_utf8_isalpha( const char * p ) { unsigned c = * (const unsigned char *) p; if(!LDAP_ASCII(c)) return 0; return LDAP_ALPHA(c); } int ldap_utf8_isalnum( const char * p ) { unsigned c = * (const unsigned char *) p; if(!LDAP_ASCII(c)) return 0; return LDAP_ALNUM(c); } int ldap_utf8_islower( const char * p ) { unsigned c = * (const unsigned char *) p; if(!LDAP_ASCII(c)) return 0; return LDAP_LOWER(c); } int ldap_utf8_isupper( const char * p ) { unsigned c = * (const unsigned char *) p; if(!LDAP_ASCII(c)) return 0; return LDAP_UPPER(c); } #endif /* * UTF-8 string routines */ /* like strchr() */ char * (ldap_utf8_strchr)( const char *str, const char *chr ) { for( ; *str != '\0'; LDAP_UTF8_INCR(str) ) { if( ldap_x_utf8_to_ucs4( str ) == ldap_x_utf8_to_ucs4( chr ) ) { return (char *) str; } } return NULL; } /* like strcspn() but returns number of bytes, not characters */ ber_len_t (ldap_utf8_strcspn)( const char *str, const char *set ) { const char *cstr; const char *cset; for( cstr = str; *cstr != '\0'; LDAP_UTF8_INCR(cstr) ) { for( cset = set; *cset != '\0'; LDAP_UTF8_INCR(cset) ) { if( ldap_x_utf8_to_ucs4( cstr ) == ldap_x_utf8_to_ucs4( cset ) ) { return cstr - str; } } } return cstr - str; } /* like strspn() but returns number of bytes, not characters */ ber_len_t (ldap_utf8_strspn)( const char *str, const char *set ) { const char *cstr; const char *cset; for( cstr = str; *cstr != '\0'; LDAP_UTF8_INCR(cstr) ) { for( cset = set; ; LDAP_UTF8_INCR(cset) ) { if( *cset == '\0' ) { return cstr - str; } if( ldap_x_utf8_to_ucs4( cstr ) == ldap_x_utf8_to_ucs4( cset ) ) { break; } } } return cstr - str; } /* like strpbrk(), replaces strchr() as well */ char *(ldap_utf8_strpbrk)( const char *str, const char *set ) { for( ; *str != '\0'; LDAP_UTF8_INCR(str) ) { const char *cset; for( cset = set; *cset != '\0'; LDAP_UTF8_INCR(cset) ) { if( ldap_x_utf8_to_ucs4( str ) == ldap_x_utf8_to_ucs4( cset ) ) { return (char *) str; } } } return NULL; } /* like strtok_r(), not strtok() */ char *(ldap_utf8_strtok)(char *str, const char *sep, char **last) { char *begin; char *end; if( last == NULL ) return NULL; begin = str ? str : *last; begin += ldap_utf8_strspn( begin, sep ); if( *begin == '\0' ) { *last = NULL; return NULL; } end = &begin[ ldap_utf8_strcspn( begin, sep ) ]; if( *end != '\0' ) { char *next = LDAP_UTF8_NEXT( end ); *end = '\0'; end = next; } *last = end; return begin; } openldap-2.4.42+dfsg/libraries/libldap/txn.c0000644000175000017500000000556012563404150017376 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 2006-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* ACKNOWLEDGEMENTS: * This program was orignally developed by Kurt D. Zeilenga for inclusion * in OpenLDAP Software. */ /* * LDAPv3 Transactions (draft-zeilenga-ldap-txn) */ #include "portable.h" #include #include #include #include #include #include "ldap-int.h" #include "ldap_log.h" #ifdef LDAP_X_TXN int ldap_txn_start( LDAP *ld, LDAPControl **sctrls, LDAPControl **cctrls, int *msgidp ) { return ldap_extended_operation( ld, LDAP_EXOP_X_TXN_START, NULL, sctrls, cctrls, msgidp ); } int ldap_txn_start_s( LDAP *ld, LDAPControl **sctrls, LDAPControl **cctrls, struct berval **txnid ) { assert( txnid != NULL ); return ldap_extended_operation_s( ld, LDAP_EXOP_X_TXN_START, NULL, sctrls, cctrls, NULL, txnid ); } int ldap_txn_end( LDAP *ld, int commit, struct berval *txnid, LDAPControl **sctrls, LDAPControl **cctrls, int *msgidp ) { int rc; BerElement *txnber = NULL; struct berval *txnval = NULL; assert( txnid != NULL ); txnber = ber_alloc_t( LBER_USE_DER ); if( commit ) { ber_printf( txnber, "{ON}", txnid ); } else { ber_printf( txnber, "{bON}", commit, txnid ); } ber_flatten( txnber, &txnval ); rc = ldap_extended_operation( ld, LDAP_EXOP_X_TXN_END, txnval, sctrls, cctrls, msgidp ); ber_free( txnber, 1 ); return rc; } int ldap_txn_end_s( LDAP *ld, int commit, struct berval *txnid, LDAPControl **sctrls, LDAPControl **cctrls, int *retidp ) { int rc; BerElement *txnber = NULL; struct berval *txnval = NULL; struct berval *retdata = NULL; if ( retidp != NULL ) *retidp = -1; txnber = ber_alloc_t( LBER_USE_DER ); if( commit ) { ber_printf( txnber, "{ON}", txnid ); } else { ber_printf( txnber, "{bON}", commit, txnid ); } ber_flatten( txnber, &txnval ); rc = ldap_extended_operation_s( ld, LDAP_EXOP_X_TXN_END, txnval, sctrls, cctrls, NULL, &retdata ); ber_free( txnber, 1 ); /* parse retdata */ if( retdata != NULL ) { BerElement *ber; ber_tag_t tag; ber_int_t retid; if( retidp == NULL ) goto done; ber = ber_init( retdata ); if( ber == NULL ) { rc = ld->ld_errno = LDAP_NO_MEMORY; goto done; } tag = ber_scanf( ber, "i", &retid ); ber_free( ber, 1 ); if ( tag != LBER_INTEGER ) { rc = ld->ld_errno = LDAP_DECODING_ERROR; goto done; } *retidp = (int) retid; done: ber_bvfree( retdata ); } return rc; } #endif openldap-2.4.42+dfsg/libraries/libldap/controls.c0000644000175000017500000002524512563404150020432 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* This notice applies to changes, created by or for Novell, Inc., * to preexisting works for which notices appear elsewhere in this file. * * Copyright (C) 1999, 2000 Novell, Inc. All Rights Reserved. * * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND TREATIES. * USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO VERSION * 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS AVAILABLE AT * HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE" IN THE * TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION OF THIS * WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP PUBLIC * LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT THE * PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY. *--- * Note: A verbatim copy of version 2.0.1 of the OpenLDAP Public License * can be found in the file "build/LICENSE-2.0.1" in this distribution * of OpenLDAP Software. */ #include "portable.h" #include #include #include #include "ldap-int.h" /* LDAPv3 Controls (RFC 4511) * * Controls ::= SEQUENCE OF control Control * * Control ::= SEQUENCE { * controlType LDAPOID, * criticality BOOLEAN DEFAULT FALSE, * controlValue OCTET STRING OPTIONAL * } */ int ldap_pvt_put_control( const LDAPControl *c, BerElement *ber ) { if ( ber_printf( ber, "{s" /*}*/, c->ldctl_oid ) == -1 ) { return LDAP_ENCODING_ERROR; } if ( c->ldctl_iscritical /* only if true */ && ( ber_printf( ber, "b", (ber_int_t) c->ldctl_iscritical ) == -1 ) ) { return LDAP_ENCODING_ERROR; } if ( !BER_BVISNULL( &c->ldctl_value ) /* only if we have a value */ && ( ber_printf( ber, "O", &c->ldctl_value ) == -1 ) ) { return LDAP_ENCODING_ERROR; } if ( ber_printf( ber, /*{*/"N}" ) == -1 ) { return LDAP_ENCODING_ERROR; } return LDAP_SUCCESS; } /* * ldap_int_put_controls */ int ldap_int_put_controls( LDAP *ld, LDAPControl *const *ctrls, BerElement *ber ) { LDAPControl *const *c; assert( ld != NULL ); assert( LDAP_VALID( ld ) ); assert( ber != NULL ); if( ctrls == NULL ) { /* use default server controls */ ctrls = ld->ld_sctrls; } if( ctrls == NULL || *ctrls == NULL ) { return LDAP_SUCCESS; } if ( ld->ld_version < LDAP_VERSION3 ) { /* LDAPv2 doesn't support controls, * error if any control is critical */ for( c = ctrls ; *c != NULL; c++ ) { if( (*c)->ldctl_iscritical ) { ld->ld_errno = LDAP_NOT_SUPPORTED; return ld->ld_errno; } } return LDAP_SUCCESS; } /* Controls are encoded as a sequence of sequences */ if( ber_printf( ber, "t{"/*}*/, LDAP_TAG_CONTROLS ) == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; return ld->ld_errno; } for( c = ctrls ; *c != NULL; c++ ) { ld->ld_errno = ldap_pvt_put_control( *c, ber ); if ( ld->ld_errno != LDAP_SUCCESS ) { return ld->ld_errno; } } if( ber_printf( ber, /*{*/ "}" ) == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; return ld->ld_errno; } return LDAP_SUCCESS; } int ldap_pvt_get_controls( BerElement *ber, LDAPControl ***ctrls ) { int nctrls; ber_tag_t tag; ber_len_t len; char *opaque; assert( ber != NULL ); if( ctrls == NULL ) { return LDAP_SUCCESS; } *ctrls = NULL; len = ber_pvt_ber_remaining( ber ); if( len == 0) { /* no controls */ return LDAP_SUCCESS; } if(( tag = ber_peek_tag( ber, &len )) != LDAP_TAG_CONTROLS ) { if( tag == LBER_ERROR ) { /* decoding error */ return LDAP_DECODING_ERROR; } /* ignore unexpected input */ return LDAP_SUCCESS; } /* set through each element */ nctrls = 0; *ctrls = LDAP_MALLOC( 1 * sizeof(LDAPControl *) ); if( *ctrls == NULL ) { return LDAP_NO_MEMORY; } *ctrls[nctrls] = NULL; for( tag = ber_first_element( ber, &len, &opaque ); tag != LBER_ERROR; tag = ber_next_element( ber, &len, opaque ) ) { LDAPControl *tctrl; LDAPControl **tctrls; tctrl = LDAP_CALLOC( 1, sizeof(LDAPControl) ); /* allocate pointer space for current controls (nctrls) * + this control + extra NULL */ tctrls = (tctrl == NULL) ? NULL : LDAP_REALLOC(*ctrls, (nctrls+2) * sizeof(LDAPControl *)); if( tctrls == NULL ) { /* one of the above allocation failed */ if( tctrl != NULL ) { LDAP_FREE( tctrl ); } ldap_controls_free(*ctrls); *ctrls = NULL; return LDAP_NO_MEMORY; } tctrls[nctrls++] = tctrl; tctrls[nctrls] = NULL; tag = ber_scanf( ber, "{a" /*}*/, &tctrl->ldctl_oid ); if( tag == LBER_ERROR ) { *ctrls = NULL; ldap_controls_free( tctrls ); return LDAP_DECODING_ERROR; } tag = ber_peek_tag( ber, &len ); if( tag == LBER_BOOLEAN ) { ber_int_t crit; tag = ber_scanf( ber, "b", &crit ); tctrl->ldctl_iscritical = crit ? (char) 0 : (char) ~0; tag = ber_peek_tag( ber, &len ); } if( tag == LBER_OCTETSTRING ) { tag = ber_scanf( ber, "o", &tctrl->ldctl_value ); } else { BER_BVZERO( &tctrl->ldctl_value ); } *ctrls = tctrls; } return LDAP_SUCCESS; } /* * Free a LDAPControl */ void ldap_control_free( LDAPControl *c ) { LDAP_MEMORY_DEBUG_ASSERT( c != NULL ); if ( c != NULL ) { if( c->ldctl_oid != NULL) { LDAP_FREE( c->ldctl_oid ); } if( c->ldctl_value.bv_val != NULL ) { LDAP_FREE( c->ldctl_value.bv_val ); } LDAP_FREE( c ); } } /* * Free an array of LDAPControl's */ void ldap_controls_free( LDAPControl **controls ) { LDAP_MEMORY_DEBUG_ASSERT( controls != NULL ); if ( controls != NULL ) { int i; for( i=0; controls[i] != NULL; i++) { ldap_control_free( controls[i] ); } LDAP_FREE( controls ); } } /* * Duplicate an array of LDAPControl */ LDAPControl ** ldap_controls_dup( LDAPControl *const *controls ) { LDAPControl **new; int i; if ( controls == NULL ) { return NULL; } /* count the controls */ for(i=0; controls[i] != NULL; i++) /* empty */ ; if( i < 1 ) { /* no controls to duplicate */ return NULL; } new = (LDAPControl **) LDAP_MALLOC( (i+1) * sizeof(LDAPControl *) ); if( new == NULL ) { /* memory allocation failure */ return NULL; } /* duplicate the controls */ for(i=0; controls[i] != NULL; i++) { new[i] = ldap_control_dup( controls[i] ); if( new[i] == NULL ) { ldap_controls_free( new ); return NULL; } } new[i] = NULL; return new; } /* * Duplicate a LDAPControl */ LDAPControl * ldap_control_dup( const LDAPControl *c ) { LDAPControl *new; if ( c == NULL || c->ldctl_oid == NULL ) { return NULL; } new = (LDAPControl *) LDAP_MALLOC( sizeof(LDAPControl) ); if( new == NULL ) { return NULL; } new->ldctl_oid = LDAP_STRDUP( c->ldctl_oid ); if(new->ldctl_oid == NULL) { LDAP_FREE( new ); return NULL; } if( c->ldctl_value.bv_val != NULL ) { new->ldctl_value.bv_val = (char *) LDAP_MALLOC( c->ldctl_value.bv_len + 1 ); if(new->ldctl_value.bv_val == NULL) { if(new->ldctl_oid != NULL) { LDAP_FREE( new->ldctl_oid ); } LDAP_FREE( new ); return NULL; } new->ldctl_value.bv_len = c->ldctl_value.bv_len; AC_MEMCPY( new->ldctl_value.bv_val, c->ldctl_value.bv_val, c->ldctl_value.bv_len ); new->ldctl_value.bv_val[new->ldctl_value.bv_len] = '\0'; } else { new->ldctl_value.bv_len = 0; new->ldctl_value.bv_val = NULL; } new->ldctl_iscritical = c->ldctl_iscritical; return new; } /* * Find a LDAPControl - deprecated */ LDAPControl * ldap_find_control( LDAP_CONST char *oid, LDAPControl **ctrls ) { if( ctrls == NULL || *ctrls == NULL ) { return NULL; } for( ; *ctrls != NULL; ctrls++ ) { if( strcmp( (*ctrls)->ldctl_oid, oid ) == 0 ) { return *ctrls; } } return NULL; } /* * Find a LDAPControl */ LDAPControl * ldap_control_find( LDAP_CONST char *oid, LDAPControl **ctrls, LDAPControl ***nextctrlp ) { if ( oid == NULL || ctrls == NULL || *ctrls == NULL ) { return NULL; } for( ; *ctrls != NULL; ctrls++ ) { if( strcmp( (*ctrls)->ldctl_oid, oid ) == 0 ) { if ( nextctrlp != NULL ) { *nextctrlp = ctrls + 1; } return *ctrls; } } if ( nextctrlp != NULL ) { *nextctrlp = NULL; } return NULL; } /* * Create a LDAPControl, optionally from ber - deprecated */ int ldap_create_control( LDAP_CONST char *requestOID, BerElement *ber, int iscritical, LDAPControl **ctrlp ) { LDAPControl *ctrl; assert( requestOID != NULL ); assert( ctrlp != NULL ); ctrl = (LDAPControl *) LDAP_MALLOC( sizeof(LDAPControl) ); if ( ctrl == NULL ) { return LDAP_NO_MEMORY; } BER_BVZERO(&ctrl->ldctl_value); if ( ber && ( ber_flatten2( ber, &ctrl->ldctl_value, 1 ) == -1 )) { LDAP_FREE( ctrl ); return LDAP_NO_MEMORY; } ctrl->ldctl_oid = LDAP_STRDUP( requestOID ); ctrl->ldctl_iscritical = iscritical; if ( requestOID != NULL && ctrl->ldctl_oid == NULL ) { ldap_control_free( ctrl ); return LDAP_NO_MEMORY; } *ctrlp = ctrl; return LDAP_SUCCESS; } /* * Create a LDAPControl, optionally from value */ int ldap_control_create( LDAP_CONST char *requestOID, int iscritical, struct berval *value, int dupval, LDAPControl **ctrlp ) { LDAPControl *ctrl; assert( requestOID != NULL ); assert( ctrlp != NULL ); ctrl = (LDAPControl *) LDAP_CALLOC( sizeof(LDAPControl), 1 ); if ( ctrl == NULL ) { return LDAP_NO_MEMORY; } ctrl->ldctl_iscritical = iscritical; if ( requestOID != NULL ) { ctrl->ldctl_oid = LDAP_STRDUP( requestOID ); if ( ctrl->ldctl_oid == NULL ) { ldap_control_free( ctrl ); return LDAP_NO_MEMORY; } } if ( value && !BER_BVISNULL( value ) ) { if ( dupval ) { ber_dupbv( &ctrl->ldctl_value, value ); if ( BER_BVISNULL( &ctrl->ldctl_value ) ) { ldap_control_free( ctrl ); return LDAP_NO_MEMORY; } } else { ctrl->ldctl_value = *value; } } *ctrlp = ctrl; return LDAP_SUCCESS; } /* * check for critical client controls and bitch if present * if we ever support critical controls, we'll have to * find a means for maintaining per API call control * information. */ int ldap_int_client_controls( LDAP *ld, LDAPControl **ctrls ) { LDAPControl *const *c; assert( ld != NULL ); assert( LDAP_VALID( ld ) ); if( ctrls == NULL ) { /* use default client controls */ ctrls = ld->ld_cctrls; } if( ctrls == NULL || *ctrls == NULL ) { return LDAP_SUCCESS; } for( c = ctrls ; *c != NULL; c++ ) { if( (*c)->ldctl_iscritical ) { ld->ld_errno = LDAP_NOT_SUPPORTED; return ld->ld_errno; } } return LDAP_SUCCESS; } openldap-2.4.42+dfsg/libraries/libldap/print.c0000644000175000017500000000222312563404150017712 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #include "portable.h" #include #include #include #include #include #include "ldap-int.h" /* * ldap log */ static int ldap_log_check( LDAP *ld, int loglvl ) { int errlvl; if(ld == NULL) { errlvl = ldap_debug; } else { errlvl = ld->ld_debug; } return errlvl & loglvl ? 1 : 0; } int ldap_log_printf( LDAP *ld, int loglvl, const char *fmt, ... ) { char buf[ 1024 ]; va_list ap; if ( !ldap_log_check( ld, loglvl )) { return 0; } va_start( ap, fmt ); buf[sizeof(buf) - 1] = '\0'; vsnprintf( buf, sizeof(buf)-1, fmt, ap ); va_end(ap); (*ber_pvt_log_print)( buf ); return 1; } openldap-2.4.42+dfsg/libraries/libldap/free.c0000644000175000017500000000373512563404150017510 0ustar ryanryan/* free.c */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (c) 1994 The Regents of the University of Michigan. * All rights reserved. */ /* * free.c - some free routines are included here to avoid having to * link in lots of extra code when not using certain features */ #include "portable.h" #include #include #include #include #include "ldap-int.h" /* * C-API deallocator */ void ldap_memfree( void *p ) { LDAP_FREE( p ); } void ldap_memvfree( void **v ) { LDAP_VFREE( v ); } void * ldap_memalloc( ber_len_t s ) { return LDAP_MALLOC( s ); } void * ldap_memcalloc( ber_len_t n, ber_len_t s ) { return LDAP_CALLOC( n, s ); } void * ldap_memrealloc( void* p, ber_len_t s ) { return LDAP_REALLOC( p, s ); } char * ldap_strdup( LDAP_CONST char *p ) { return LDAP_STRDUP( p ); } /* * free a null-terminated array of pointers to mod structures. the * structures are freed, not the array itself, unless the freemods * flag is set. */ void ldap_mods_free( LDAPMod **mods, int freemods ) { int i; if ( mods == NULL ) return; for ( i = 0; mods[i] != NULL; i++ ) { if ( mods[i]->mod_op & LDAP_MOD_BVALUES ) { if( mods[i]->mod_bvalues != NULL ) ber_bvecfree( mods[i]->mod_bvalues ); } else if( mods[i]->mod_values != NULL ) { LDAP_VFREE( mods[i]->mod_values ); } if ( mods[i]->mod_type != NULL ) { LDAP_FREE( mods[i]->mod_type ); } LDAP_FREE( (char *) mods[i] ); } if ( freemods ) { LDAP_FREE( (char *) mods ); } } openldap-2.4.42+dfsg/libraries/libldap/dntest.c0000644000175000017500000001750712563404150020072 0ustar ryanryan/* dntest.c -- OpenLDAP DN API Test Program */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* ACKNOWLEDGEMENT: * This program was initially developed by Pierangelo Masarati * for inclusion in OpenLDAP Software. */ /* * This program is designed to test the ldap_str2dn/ldap_dn2str * functions */ #include "portable.h" #include #include #include #include #include #include "ldap-int.h" #include "ldif.h" #include "lutil.h" #include "lutil_ldap.h" #include "ldap_defaults.h" int main( int argc, char *argv[] ) { int rc, i, debug = 0, f2 = 0; unsigned flags[ 2 ] = { 0U, 0 }; char *strin, *str = NULL, buf[ 1024 ]; LDAPDN dn, dn2 = NULL; while ( 1 ) { int opt = getopt( argc, argv, "d:" ); if ( opt == EOF ) { break; } switch ( opt ) { case 'd': debug = atoi( optarg ); break; } } optind--; argc -= optind; argv += optind; if ( argc < 2 ) { fprintf( stderr, "usage: dntest [flags-in[,...]] [flags-out[,...]]\n\n" ); fprintf( stderr, "\tflags-in: V3,V2,DCE,\n" ); fprintf( stderr, "\tflags-out: V3,V2,UFN,DCE,AD,\n\n" ); fprintf( stderr, "\t: PRETTY,PEDANTIC,NOSPACES,NOONESPACE\n\n" ); return( 0 ); } if ( ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &debug ) != LBER_OPT_SUCCESS ) { fprintf( stderr, "Could not set LBER_OPT_DEBUG_LEVEL %d\n", debug ); } if ( ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, &debug ) != LDAP_OPT_SUCCESS ) { fprintf( stderr, "Could not set LDAP_OPT_DEBUG_LEVEL %d\n", debug ); } if ( strcmp( argv[ 1 ], "-" ) == 0 ) { size_t len = fgets( buf, sizeof( buf ), stdin ) ? strlen( buf ) : 0; if ( len == 0 || buf[ --len ] == '\n' ) { buf[ len ] = '\0'; } strin = buf; } else { strin = argv[ 1 ]; } if ( argc >= 3 ) { for ( i = 0; i < argc - 2; i++ ) { char *s, *e; for ( s = argv[ 2 + i ]; s; s = e ) { e = strchr( s, ',' ); if ( e != NULL ) { e[ 0 ] = '\0'; e++; } if ( !strcasecmp( s, "V3" ) ) { flags[ i ] |= LDAP_DN_FORMAT_LDAPV3; } else if ( !strcasecmp( s, "V2" ) ) { flags[ i ] |= LDAP_DN_FORMAT_LDAPV2; } else if ( !strcasecmp( s, "DCE" ) ) { flags[ i ] |= LDAP_DN_FORMAT_DCE; } else if ( !strcasecmp( s, "UFN" ) ) { flags[ i ] |= LDAP_DN_FORMAT_UFN; } else if ( !strcasecmp( s, "AD" ) ) { flags[ i ] |= LDAP_DN_FORMAT_AD_CANONICAL; } else if ( !strcasecmp( s, "PRETTY" ) ) { flags[ i ] |= LDAP_DN_PRETTY; } else if ( !strcasecmp( s, "PEDANTIC" ) ) { flags[ i ] |= LDAP_DN_PEDANTIC; } else if ( !strcasecmp( s, "NOSPACES" ) ) { flags[ i ] |= LDAP_DN_P_NOLEADTRAILSPACES; } else if ( !strcasecmp( s, "NOONESPACE" ) ) { flags[ i ] |= LDAP_DN_P_NOSPACEAFTERRDN; } } } } if ( flags[ 1 ] == 0 ) flags[ 1 ] = LDAP_DN_FORMAT_LDAPV3; f2 = 1; rc = ldap_str2dn( strin, &dn, flags[ 0 ] ); if ( rc == LDAP_SUCCESS ) { int i; if ( dn ) { for ( i = 0; dn[ i ]; i++ ) { LDAPRDN rdn = dn[ i ]; char *rstr = NULL; if ( ldap_rdn2str( rdn, &rstr, flags[ f2 ] ) ) { fprintf( stdout, "\tldap_rdn2str() failed\n" ); continue; } fprintf( stdout, "\tldap_rdn2str() = \"%s\"\n", rstr ); ldap_memfree( rstr ); } } else { fprintf( stdout, "\tempty DN\n" ); } } str = NULL; if ( rc == LDAP_SUCCESS && ldap_dn2str( dn, &str, flags[ f2 ] ) == LDAP_SUCCESS ) { char **values, *tmp, *tmp2, *str2 = NULL; int n; fprintf( stdout, "\nldap_dn2str(ldap_str2dn(\"%s\"))\n" "\t= \"%s\"\n", strin, str ); switch ( flags[ f2 ] & LDAP_DN_FORMAT_MASK ) { case LDAP_DN_FORMAT_UFN: case LDAP_DN_FORMAT_AD_CANONICAL: return( 0 ); case LDAP_DN_FORMAT_LDAPV3: case LDAP_DN_FORMAT_LDAPV2: n = ldap_dn2domain( strin, &tmp ); if ( n ) { fprintf( stdout, "\nldap_dn2domain(\"%s\") FAILED\n", strin ); } else { fprintf( stdout, "\nldap_dn2domain(\"%s\")\n" "\t= \"%s\"\n", strin, tmp ? tmp : "" ); } ldap_memfree( tmp ); tmp = ldap_dn2ufn( strin ); fprintf( stdout, "\nldap_dn2ufn(\"%s\")\n" "\t= \"%s\"\n", strin, tmp ? tmp : "" ); ldap_memfree( tmp ); tmp = ldap_dn2dcedn( strin ); fprintf( stdout, "\nldap_dn2dcedn(\"%s\")\n" "\t= \"%s\"\n", strin, tmp ? tmp : "" ); tmp2 = ldap_dcedn2dn( tmp ); fprintf( stdout, "\nldap_dcedn2dn(\"%s\")\n" "\t= \"%s\"\n", tmp ? tmp : "", tmp2 ? tmp2 : "" ); ldap_memfree( tmp ); ldap_memfree( tmp2 ); tmp = ldap_dn2ad_canonical( strin ); fprintf( stdout, "\nldap_dn2ad_canonical(\"%s\")\n" "\t= \"%s\"\n", strin, tmp ? tmp : "" ); ldap_memfree( tmp ); fprintf( stdout, "\nldap_explode_dn(\"%s\"):\n", str ); values = ldap_explode_dn( str, 0 ); for ( n = 0; values && values[ n ]; n++ ) { char **vv; int nn; fprintf( stdout, "\t\"%s\"\n", values[ n ] ); fprintf( stdout, "\tldap_explode_rdn(\"%s\")\n", values[ n ] ); vv = ldap_explode_rdn( values[ n ], 0 ); for ( nn = 0; vv && vv[ nn ]; nn++ ) { fprintf( stdout, "\t\t'%s'\n", vv[ nn ] ); } LDAP_VFREE( vv ); fprintf( stdout, "\tldap_explode_rdn(\"%s\")" " (no types)\n", values[ n ] ); vv = ldap_explode_rdn( values[ n ], 1 ); for ( nn = 0; vv && vv[ nn ]; nn++ ) { fprintf( stdout, "\t\t\t\"%s\"\n", vv[ nn ] ); } LDAP_VFREE( vv ); } LDAP_VFREE( values ); fprintf( stdout, "\nldap_explode_dn(\"%s\")" " (no types):\n", str ); values = ldap_explode_dn( str, 1 ); for ( n = 0; values && values[ n ]; n++ ) { fprintf( stdout, "\t\"%s\"\n", values[ n ] ); } LDAP_VFREE( values ); break; } dn2 = NULL; rc = ldap_str2dn( str, &dn2, flags[ f2 ] ); str2 = NULL; if ( rc == LDAP_SUCCESS && ldap_dn2str( dn2, &str2, flags[ f2 ] ) == LDAP_SUCCESS ) { int iRDN; fprintf( stdout, "\n\"%s\"\n\t == \"%s\" ? %s\n", str, str2, strcmp( str, str2 ) == 0 ? "yes" : "no" ); if( dn != NULL && dn2 == NULL ) { fprintf( stdout, "dn mismatch\n" ); } else if (( dn != NULL ) && (dn2 != NULL)) for ( iRDN = 0; dn[ iRDN ] && dn2[ iRDN ]; iRDN++ ) { LDAPRDN r = dn[ iRDN ]; LDAPRDN r2 = dn2[ iRDN ]; int iAVA; for ( iAVA = 0; r[ iAVA ] && r2[ iAVA ]; iAVA++ ) { LDAPAVA *a = r[ iAVA ]; LDAPAVA *a2 = r2[ iAVA ]; if ( a->la_attr.bv_len != a2->la_attr.bv_len ) { fprintf( stdout, "ava(%d), rdn(%d) attr len mismatch (%ld->%ld)\n", iAVA + 1, iRDN + 1, a->la_attr.bv_len, a2->la_attr.bv_len ); } else if ( memcmp( a->la_attr.bv_val, a2->la_attr.bv_val, a->la_attr.bv_len ) ) { fprintf( stdout, "ava(%d), rdn(%d) attr mismatch\n", iAVA + 1, iRDN + 1 ); } else if ( a->la_flags != a2->la_flags ) { fprintf( stdout, "ava(%d), rdn(%d) flag mismatch (%x->%x)\n", iAVA + 1, iRDN + 1, a->la_flags, a2->la_flags ); } else if ( a->la_value.bv_len != a2->la_value.bv_len ) { fprintf( stdout, "ava(%d), rdn(%d) value len mismatch (%ld->%ld)\n", iAVA + 1, iRDN + 1, a->la_value.bv_len, a2->la_value.bv_len ); } else if ( memcmp( a->la_value.bv_val, a2->la_value.bv_val, a->la_value.bv_len ) ) { fprintf( stdout, "ava(%d), rdn(%d) value mismatch\n", iAVA + 1, iRDN + 1 ); } } } ldap_dnfree( dn2 ); ldap_memfree( str2 ); } ldap_memfree( str ); } ldap_dnfree( dn ); /* note: dn is not freed */ return( 0 ); } openldap-2.4.42+dfsg/libraries/libldap/messages.c0000644000175000017500000000241312563404150020366 0ustar ryanryan/* messages.c */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #include "portable.h" #include #include #include #include #include #include "ldap-int.h" LDAPMessage * ldap_first_message( LDAP *ld, LDAPMessage *chain ) { assert( ld != NULL ); assert( LDAP_VALID( ld ) ); assert( chain != NULL ); return chain; } LDAPMessage * ldap_next_message( LDAP *ld, LDAPMessage *msg ) { assert( ld != NULL ); assert( LDAP_VALID( ld ) ); assert( msg != NULL ); return msg->lm_chain; } int ldap_count_messages( LDAP *ld, LDAPMessage *chain ) { int i; assert( ld != NULL ); assert( LDAP_VALID( ld ) ); for ( i = 0; chain != NULL; chain = chain->lm_chain ) { i++; } return( i ); } BerElement* ldap_get_message_ber( LDAPMessage *ld ) { return ld->lm_ber; } openldap-2.4.42+dfsg/libraries/libldap/apitest.c0000644000175000017500000001466112563404150020240 0ustar ryanryan/* apitest.c -- OpenLDAP API Test Program */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * Portions Copyright 1998-2003 Kurt D. Zeilenga. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* ACKNOWLEDGEMENTS: * This program was orignally developed by Kurt D. Zeilenga for inclusion in * OpenLDAP Software. */ #include "portable.h" #include #include #include int main(int argc, char **argv) { LDAPAPIInfo api; int ival; char *sval; printf("Compile time API Information\n"); #ifdef LDAP_API_INFO_VERSION api.ldapai_info_version = LDAP_API_INFO_VERSION; printf(" API Info version: %d\n", (int) api.ldapai_info_version); #else api.ldapai_info_version = 1; printf(" API Info version: unknown\n"); #endif #ifdef LDAP_FEATURE_INFO_VERSION printf(" Feature Info version: %d\n", (int) LDAP_FEATURE_INFO_VERSION); #else printf(" Feature Info version: unknown\n"); api.ldapai_info_version = 1; #endif #ifdef LDAP_API_VERSION printf(" API version: %d\n", (int) LDAP_API_VERSION); #else printf(" API version: unknown\n"); #endif #ifdef LDAP_VERSION printf(" Protocol Version: %d\n", (int) LDAP_VERSION); #else printf(" Protocol Version: unknown\n"); #endif #ifdef LDAP_VERSION_MIN printf(" Protocol Min: %d\n", (int) LDAP_VERSION_MIN); #else printf(" Protocol Min: unknown\n"); #endif #ifdef LDAP_VERSION_MAX printf(" Protocol Max: %d\n", (int) LDAP_VERSION_MAX); #else printf(" Protocol Max: unknown\n"); #endif #ifdef LDAP_VENDOR_NAME printf(" Vendor Name: %s\n", LDAP_VENDOR_NAME); #else printf(" Vendor Name: unknown\n"); #endif #ifdef LDAP_VENDOR_VERSION printf(" Vendor Version: %d\n", (int) LDAP_VENDOR_VERSION); #else printf(" Vendor Version: unknown\n"); #endif if(ldap_get_option(NULL, LDAP_OPT_API_INFO, &api) != LDAP_SUCCESS) { fprintf(stderr, "%s: ldap_get_option(API_INFO) failed\n", argv[0]); return EXIT_FAILURE; } printf("\nExecution time API Information\n"); printf(" API Info version: %d\n", api.ldapai_info_version); if (api.ldapai_info_version != LDAP_API_INFO_VERSION) { printf(" API INFO version mismatch: got %d, expected %d\n", api.ldapai_info_version, LDAP_API_INFO_VERSION); return EXIT_FAILURE; } printf(" API Version: %d\n", api.ldapai_api_version); printf(" Protocol Max: %d\n", api.ldapai_protocol_version); if(api.ldapai_extensions == NULL) { printf(" Extensions: none\n"); } else { int i; for(i=0; api.ldapai_extensions[i] != NULL; i++) /* empty */; printf(" Extensions: %d\n", i); for(i=0; api.ldapai_extensions[i] != NULL; i++) { #ifdef LDAP_OPT_API_FEATURE_INFO LDAPAPIFeatureInfo fi; fi.ldapaif_info_version = LDAP_FEATURE_INFO_VERSION; fi.ldapaif_name = api.ldapai_extensions[i]; fi.ldapaif_version = 0; if( ldap_get_option(NULL, LDAP_OPT_API_FEATURE_INFO, &fi) == LDAP_SUCCESS ) { if(fi.ldapaif_info_version != LDAP_FEATURE_INFO_VERSION) { printf(" %s feature info mismatch: got %d, expected %d\n", api.ldapai_extensions[i], LDAP_FEATURE_INFO_VERSION, fi.ldapaif_info_version); } else { printf(" %s: version %d\n", fi.ldapaif_name, fi.ldapaif_version); } } else { printf(" %s (NO FEATURE INFO)\n", api.ldapai_extensions[i]); } #else printf(" %s\n", api.ldapai_extensions[i]); #endif ldap_memfree(api.ldapai_extensions[i]); } ldap_memfree(api.ldapai_extensions); } printf(" Vendor Name: %s\n", api.ldapai_vendor_name); ldap_memfree(api.ldapai_vendor_name); printf(" Vendor Version: %d\n", api.ldapai_vendor_version); printf("\nExecution time Default Options\n"); if(ldap_get_option(NULL, LDAP_OPT_DEREF, &ival) != LDAP_SUCCESS) { fprintf(stderr, "%s: ldap_get_option(api) failed\n", argv[0]); return EXIT_FAILURE; } printf(" DEREF: %d\n", ival); if(ldap_get_option(NULL, LDAP_OPT_SIZELIMIT, &ival) != LDAP_SUCCESS) { fprintf(stderr, "%s: ldap_get_option(sizelimit) failed\n", argv[0]); return EXIT_FAILURE; } printf(" SIZELIMIT: %d\n", ival); if(ldap_get_option(NULL, LDAP_OPT_TIMELIMIT, &ival) != LDAP_SUCCESS) { fprintf(stderr, "%s: ldap_get_option(timelimit) failed\n", argv[0]); return EXIT_FAILURE; } printf(" TIMELIMIT: %d\n", ival); if(ldap_get_option(NULL, LDAP_OPT_REFERRALS, &ival) != LDAP_SUCCESS) { fprintf(stderr, "%s: ldap_get_option(referrals) failed\n", argv[0]); return EXIT_FAILURE; } printf(" REFERRALS: %s\n", ival ? "on" : "off"); if(ldap_get_option(NULL, LDAP_OPT_RESTART, &ival) != LDAP_SUCCESS) { fprintf(stderr, "%s: ldap_get_option(restart) failed\n", argv[0]); return EXIT_FAILURE; } printf(" RESTART: %s\n", ival ? "on" : "off"); if(ldap_get_option(NULL, LDAP_OPT_PROTOCOL_VERSION, &ival) != LDAP_SUCCESS) { fprintf(stderr, "%s: ldap_get_option(protocol version) failed\n", argv[0]); return EXIT_FAILURE; } printf(" PROTOCOL VERSION: %d\n", ival); if(ldap_get_option(NULL, LDAP_OPT_HOST_NAME, &sval) != LDAP_SUCCESS) { fprintf(stderr, "%s: ldap_get_option(host name) failed\n", argv[0]); return EXIT_FAILURE; } if( sval != NULL ) { printf(" HOST NAME: %s\n", sval); ldap_memfree(sval); } else { puts(" HOST NAME: "); } #if 0 /* API tests */ { /* bindless unbind */ LDAP *ld; int rc; ld = ldap_init( "localhost", 389 ); if( ld == NULL ) { perror("ldap_init"); return EXIT_FAILURE; } rc = ldap_unbind( ld ); if( rc != LDAP_SUCCESS ) { perror("ldap_unbind"); return EXIT_FAILURE; } } { /* bindless unbind */ LDAP *ld; int rc; ld = ldap_init( "localhost", 389 ); if( ld == NULL ) { perror("ldap_init"); return EXIT_FAILURE; } rc = ldap_abandon_ext( ld, 0, NULL, NULL ); if( rc != LDAP_SERVER_DOWN ) { ldap_perror( ld, "ldap_abandon"); return EXIT_FAILURE; } rc = ldap_unbind( ld ); if( rc != LDAP_SUCCESS ) { perror("ldap_unbind"); return EXIT_FAILURE; } } #endif return EXIT_SUCCESS; } openldap-2.4.42+dfsg/libraries/libldap/tls_m.c0000644000175000017500000025657512563404150017721 0ustar ryanryan/* tls_m.c - Handle tls/ssl using Mozilla NSS. */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 2008-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* ACKNOWLEDGEMENTS: Initial version written by Howard Chu. * Additional support by Rich Megginson. */ #include "portable.h" #ifdef HAVE_MOZNSS #include "ldap_config.h" #include #if defined( HAVE_FCNTL_H ) #include #endif #include #include #include #include #include #include #include #include #include #include "ldap-int.h" #include "ldap-tls.h" #define READ_PASSWORD_FROM_STDIN #define READ_PASSWORD_FROM_FILE #ifdef READ_PASSWORD_FROM_STDIN #include /* for echo on/off */ #endif #include #include #include #include #include #include #include #include #include #include #include #undef NSS_VERSION_INT #define NSS_VERSION_INT ((NSS_VMAJOR << 24) | (NSS_VMINOR << 16) | \ (NSS_VPATCH << 8) | NSS_VBUILD) /* NSS 3.12.5 and later have NSS_InitContext */ #if NSS_VERSION_INT >= 0x030c0500 #define HAVE_NSS_INITCONTEXT 1 #endif /* NSS 3.12.9 and later have SECMOD_RestartModules */ #if NSS_VERSION_INT >= 0x030c0900 #define HAVE_SECMOD_RESTARTMODULES 1 #endif /* InitContext does not currently work in server mode */ /* #define INITCONTEXT_HACK 1 */ typedef struct tlsm_ctx { PRFileDesc *tc_model; int tc_refcnt; int tc_unique; /* unique number associated with this ctx */ PRBool tc_verify_cert; CERTCertDBHandle *tc_certdb; PK11SlotInfo *tc_certdb_slot; CERTCertificate *tc_certificate; SECKEYPrivateKey *tc_private_key; char *tc_pin_file; struct ldaptls *tc_config; int tc_is_server; int tc_require_cert; PRCallOnceType tc_callonce; PRBool tc_using_pem; #ifdef HAVE_NSS_INITCONTEXT NSSInitContext *tc_initctx; /* the NSS context */ #endif PK11GenericObject **tc_pem_objs; /* array of objects to free */ int tc_n_pem_objs; /* number of objects */ PRBool tc_warn_only; /* only warn of errors in validation */ #ifdef LDAP_R_COMPILE ldap_pvt_thread_mutex_t tc_refmutex; #endif } tlsm_ctx; typedef PRFileDesc tlsm_session; static int tlsm_ctx_count; #define TLSM_CERTDB_DESC_FMT "ldap(%d)" static PRDescIdentity tlsm_layer_id; static const PRIOMethods tlsm_PR_methods; #define CERTDB_NONE NULL #define PREFIX_NONE NULL #define PEM_LIBRARY "nsspem" #define PEM_MODULE "PEM" /* hash files for use with cacertdir have this file name suffix */ #define PEM_CA_HASH_FILE_SUFFIX ".0" #define PEM_CA_HASH_FILE_SUFFIX_LEN 2 static SECMODModule *pem_module; #define DEFAULT_TOKEN_NAME "default" #define TLSM_PEM_SLOT_CACERTS "PEM Token #0" #define TLSM_PEM_SLOT_CERTS "PEM Token #1" #define PK11_SETATTRS(x,id,v,l) (x).type = (id); \ (x).pValue=(v); (x).ulValueLen = (l); /* forward declaration */ static int tlsm_init( void ); #ifdef LDAP_R_COMPILE /* it doesn't seem guaranteed that a client will call tlsm_thr_init in a non-threaded context - so we have to wrap the mutex creation in a prcallonce */ static ldap_pvt_thread_mutex_t tlsm_ctx_count_mutex; static ldap_pvt_thread_mutex_t tlsm_init_mutex; static ldap_pvt_thread_mutex_t tlsm_pem_mutex; static PRCallOnceType tlsm_init_mutex_callonce = {0,0}; static PRStatus PR_CALLBACK tlsm_thr_init_callonce( void ) { if ( ldap_pvt_thread_mutex_init( &tlsm_ctx_count_mutex ) ) { Debug( LDAP_DEBUG_ANY, "TLS: could not create mutex for context counter: %d\n", errno, 0, 0 ); return PR_FAILURE; } if ( ldap_pvt_thread_mutex_init( &tlsm_init_mutex ) ) { Debug( LDAP_DEBUG_ANY, "TLS: could not create mutex for moznss initialization: %d\n", errno, 0, 0 ); return PR_FAILURE; } if ( ldap_pvt_thread_mutex_init( &tlsm_pem_mutex ) ) { Debug( LDAP_DEBUG_ANY, "TLS: could not create mutex for PEM module: %d\n", errno, 0, 0 ); return PR_FAILURE; } return PR_SUCCESS; } static void tlsm_thr_init( void ) { ( void )PR_CallOnce( &tlsm_init_mutex_callonce, tlsm_thr_init_callonce ); } #endif /* LDAP_R_COMPILE */ static const char * tlsm_dump_cipher_info(PRFileDesc *fd) { PRUint16 ii; for (ii = 0; ii < SSL_NumImplementedCiphers; ++ii) { PRInt32 cipher = (PRInt32)SSL_ImplementedCiphers[ii]; PRBool enabled = PR_FALSE; PRInt32 policy = 0; SSLCipherSuiteInfo info; if (fd) { SSL_CipherPrefGet(fd, cipher, &enabled); } else { SSL_CipherPrefGetDefault(cipher, &enabled); } SSL_CipherPolicyGet(cipher, &policy); SSL_GetCipherSuiteInfo(cipher, &info, (PRUintn)sizeof(info)); Debug( LDAP_DEBUG_TRACE, "TLS: cipher: %d - %s, enabled: %d, ", info.cipherSuite, info.cipherSuiteName, enabled ); Debug( LDAP_DEBUG_TRACE, "policy: %d\n", policy, 0, 0 ); } return ""; } /* Cipher definitions */ typedef struct { char *ossl_name; /* The OpenSSL cipher name */ int num; /* The cipher id */ int attr; /* cipher attributes: algorithms, etc */ int version; /* protocol version valid for this cipher */ int bits; /* bits of strength */ int alg_bits; /* bits of the algorithm */ int strength; /* LOW, MEDIUM, HIGH */ int enabled; /* Enabled by default? */ } cipher_properties; /* cipher attributes */ #define SSL_kRSA 0x00000001L #define SSL_aRSA 0x00000002L #define SSL_aDSS 0x00000004L #define SSL_DSS SSL_aDSS #define SSL_eNULL 0x00000008L #define SSL_DES 0x00000010L #define SSL_3DES 0x00000020L #define SSL_RC4 0x00000040L #define SSL_RC2 0x00000080L #define SSL_AES 0x00000100L #define SSL_MD5 0x00000200L #define SSL_SHA1 0x00000400L #define SSL_SHA SSL_SHA1 #define SSL_RSA (SSL_kRSA|SSL_aRSA) /* cipher strength */ #define SSL_NULL 0x00000001L #define SSL_EXPORT40 0x00000002L #define SSL_EXPORT56 0x00000004L #define SSL_LOW 0x00000008L #define SSL_MEDIUM 0x00000010L #define SSL_HIGH 0x00000020L #define SSL2 0x00000001L #define SSL3 0x00000002L /* OpenSSL treats SSL3 and TLSv1 the same */ #define TLS1 SSL3 /* Cipher translation */ static cipher_properties ciphers_def[] = { /* SSL 2 ciphers */ {"DES-CBC3-MD5", SSL_EN_DES_192_EDE3_CBC_WITH_MD5, SSL_kRSA|SSL_aRSA|SSL_3DES|SSL_MD5, SSL2, 168, 168, SSL_HIGH, SSL_ALLOWED}, {"RC2-CBC-MD5", SSL_EN_RC2_128_CBC_WITH_MD5, SSL_kRSA|SSL_aRSA|SSL_RC2|SSL_MD5, SSL2, 128, 128, SSL_MEDIUM, SSL_ALLOWED}, {"RC4-MD5", SSL_EN_RC4_128_WITH_MD5, SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_MD5, SSL2, 128, 128, SSL_MEDIUM, SSL_ALLOWED}, {"DES-CBC-MD5", SSL_EN_DES_64_CBC_WITH_MD5, SSL_kRSA|SSL_aRSA|SSL_DES|SSL_MD5, SSL2, 56, 56, SSL_LOW, SSL_ALLOWED}, {"EXP-RC2-CBC-MD5", SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5, SSL_kRSA|SSL_aRSA|SSL_RC2|SSL_MD5, SSL2, 40, 128, SSL_EXPORT40, SSL_ALLOWED}, {"EXP-RC4-MD5", SSL_EN_RC4_128_EXPORT40_WITH_MD5, SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_MD5, SSL2, 40, 128, SSL_EXPORT40, SSL_ALLOWED}, /* SSL3 ciphers */ {"RC4-MD5", SSL_RSA_WITH_RC4_128_MD5, SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_MD5, SSL3, 128, 128, SSL_MEDIUM, SSL_ALLOWED}, {"RC4-SHA", SSL_RSA_WITH_RC4_128_SHA, SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_SHA1, SSL3, 128, 128, SSL_MEDIUM, SSL_ALLOWED}, {"DES-CBC3-SHA", SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_kRSA|SSL_aRSA|SSL_3DES|SSL_SHA1, SSL3, 168, 168, SSL_HIGH, SSL_ALLOWED}, {"DES-CBC-SHA", SSL_RSA_WITH_DES_CBC_SHA, SSL_kRSA|SSL_aRSA|SSL_DES|SSL_SHA1, SSL3, 56, 56, SSL_LOW, SSL_ALLOWED}, {"EXP-RC4-MD5", SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_MD5, SSL3, 40, 128, SSL_EXPORT40, SSL_ALLOWED}, {"EXP-RC2-CBC-MD5", SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5, SSL_kRSA|SSL_aRSA|SSL_RC2|SSL_MD5, SSL3, 0, 0, SSL_EXPORT40, SSL_ALLOWED}, {"NULL-MD5", SSL_RSA_WITH_NULL_MD5, SSL_kRSA|SSL_aRSA|SSL_eNULL|SSL_MD5, SSL3, 0, 0, SSL_NULL, SSL_NOT_ALLOWED}, {"NULL-SHA", SSL_RSA_WITH_NULL_SHA, SSL_kRSA|SSL_aRSA|SSL_eNULL|SSL_SHA1, SSL3, 0, 0, SSL_NULL, SSL_NOT_ALLOWED}, /* TLSv1 ciphers */ {"EXP1024-DES-CBC-SHA", TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA, SSL_kRSA|SSL_aRSA|SSL_DES|SSL_SHA, TLS1, 56, 56, SSL_EXPORT56, SSL_ALLOWED}, {"EXP1024-RC4-SHA", TLS_RSA_EXPORT1024_WITH_RC4_56_SHA, SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_SHA, TLS1, 56, 56, SSL_EXPORT56, SSL_ALLOWED}, {"AES128-SHA", TLS_RSA_WITH_AES_128_CBC_SHA, SSL_kRSA|SSL_aRSA|SSL_AES|SSL_SHA, TLS1, 128, 128, SSL_HIGH, SSL_ALLOWED}, {"AES256-SHA", TLS_RSA_WITH_AES_256_CBC_SHA, SSL_kRSA|SSL_aRSA|SSL_AES|SSL_SHA, TLS1, 256, 256, SSL_HIGH, SSL_ALLOWED}, }; #define ciphernum (sizeof(ciphers_def)/sizeof(cipher_properties)) /* given err which is the current errno, calls PR_SetError with the corresponding NSPR error code */ static void tlsm_map_error(int err) { PRErrorCode prError; switch ( err ) { case EACCES: prError = PR_NO_ACCESS_RIGHTS_ERROR; break; case EADDRINUSE: prError = PR_ADDRESS_IN_USE_ERROR; break; case EADDRNOTAVAIL: prError = PR_ADDRESS_NOT_AVAILABLE_ERROR; break; case EAFNOSUPPORT: prError = PR_ADDRESS_NOT_SUPPORTED_ERROR; break; case EAGAIN: prError = PR_WOULD_BLOCK_ERROR; break; /* * On QNX and Neutrino, EALREADY is defined as EBUSY. */ #if EALREADY != EBUSY case EALREADY: prError = PR_ALREADY_INITIATED_ERROR; break; #endif case EBADF: prError = PR_BAD_DESCRIPTOR_ERROR; break; #ifdef EBADMSG case EBADMSG: prError = PR_IO_ERROR; break; #endif case EBUSY: prError = PR_FILESYSTEM_MOUNTED_ERROR; break; case ECONNABORTED: prError = PR_CONNECT_ABORTED_ERROR; break; case ECONNREFUSED: prError = PR_CONNECT_REFUSED_ERROR; break; case ECONNRESET: prError = PR_CONNECT_RESET_ERROR; break; case EDEADLK: prError = PR_DEADLOCK_ERROR; break; #ifdef EDIRCORRUPTED case EDIRCORRUPTED: prError = PR_DIRECTORY_CORRUPTED_ERROR; break; #endif #ifdef EDQUOT case EDQUOT: prError = PR_NO_DEVICE_SPACE_ERROR; break; #endif case EEXIST: prError = PR_FILE_EXISTS_ERROR; break; case EFAULT: prError = PR_ACCESS_FAULT_ERROR; break; case EFBIG: prError = PR_FILE_TOO_BIG_ERROR; break; case EHOSTUNREACH: prError = PR_HOST_UNREACHABLE_ERROR; break; case EINPROGRESS: prError = PR_IN_PROGRESS_ERROR; break; case EINTR: prError = PR_PENDING_INTERRUPT_ERROR; break; case EINVAL: prError = PR_INVALID_ARGUMENT_ERROR; break; case EIO: prError = PR_IO_ERROR; break; case EISCONN: prError = PR_IS_CONNECTED_ERROR; break; case EISDIR: prError = PR_IS_DIRECTORY_ERROR; break; case ELOOP: prError = PR_LOOP_ERROR; break; case EMFILE: prError = PR_PROC_DESC_TABLE_FULL_ERROR; break; case EMLINK: prError = PR_MAX_DIRECTORY_ENTRIES_ERROR; break; case EMSGSIZE: prError = PR_INVALID_ARGUMENT_ERROR; break; #ifdef EMULTIHOP case EMULTIHOP: prError = PR_REMOTE_FILE_ERROR; break; #endif case ENAMETOOLONG: prError = PR_NAME_TOO_LONG_ERROR; break; case ENETUNREACH: prError = PR_NETWORK_UNREACHABLE_ERROR; break; case ENFILE: prError = PR_SYS_DESC_TABLE_FULL_ERROR; break; /* * On SCO OpenServer 5, ENOBUFS is defined as ENOSR. */ #if defined(ENOBUFS) && (ENOBUFS != ENOSR) case ENOBUFS: prError = PR_INSUFFICIENT_RESOURCES_ERROR; break; #endif case ENODEV: prError = PR_FILE_NOT_FOUND_ERROR; break; case ENOENT: prError = PR_FILE_NOT_FOUND_ERROR; break; case ENOLCK: prError = PR_FILE_IS_LOCKED_ERROR; break; #ifdef ENOLINK case ENOLINK: prError = PR_REMOTE_FILE_ERROR; break; #endif case ENOMEM: prError = PR_OUT_OF_MEMORY_ERROR; break; case ENOPROTOOPT: prError = PR_INVALID_ARGUMENT_ERROR; break; case ENOSPC: prError = PR_NO_DEVICE_SPACE_ERROR; break; #ifdef ENOSR case ENOSR: prError = PR_INSUFFICIENT_RESOURCES_ERROR; break; #endif case ENOTCONN: prError = PR_NOT_CONNECTED_ERROR; break; case ENOTDIR: prError = PR_NOT_DIRECTORY_ERROR; break; case ENOTSOCK: prError = PR_NOT_SOCKET_ERROR; break; case ENXIO: prError = PR_FILE_NOT_FOUND_ERROR; break; case EOPNOTSUPP: prError = PR_NOT_TCP_SOCKET_ERROR; break; #ifdef EOVERFLOW case EOVERFLOW: prError = PR_BUFFER_OVERFLOW_ERROR; break; #endif case EPERM: prError = PR_NO_ACCESS_RIGHTS_ERROR; break; case EPIPE: prError = PR_CONNECT_RESET_ERROR; break; #ifdef EPROTO case EPROTO: prError = PR_IO_ERROR; break; #endif case EPROTONOSUPPORT: prError = PR_PROTOCOL_NOT_SUPPORTED_ERROR; break; case EPROTOTYPE: prError = PR_ADDRESS_NOT_SUPPORTED_ERROR; break; case ERANGE: prError = PR_INVALID_METHOD_ERROR; break; case EROFS: prError = PR_READ_ONLY_FILESYSTEM_ERROR; break; case ESPIPE: prError = PR_INVALID_METHOD_ERROR; break; case ETIMEDOUT: prError = PR_IO_TIMEOUT_ERROR; break; #if EWOULDBLOCK != EAGAIN case EWOULDBLOCK: prError = PR_WOULD_BLOCK_ERROR; break; #endif case EXDEV: prError = PR_NOT_SAME_DEVICE_ERROR; break; default: prError = PR_UNKNOWN_ERROR; break; } PR_SetError( prError, err ); } /* * cipher_list is an integer array with the following values: * -1: never enable this cipher * 0: cipher disabled * 1: cipher enabled */ static int nss_parse_ciphers(const char *cipherstr, int cipher_list[ciphernum]) { int i; char *cipher; char *ciphers; char *ciphertip; int action; int rv; /* All disabled to start */ for (i=0; itc_model, SSL_ImplementedCiphers[i], SSL_NOT_ALLOWED); /* Now enable what was requested */ for (i=0; itc_model, ciphers_def[i].num, enabled); } } } return rv == 1 ? 0 : -1; } static SECStatus tlsm_bad_cert_handler(void *arg, PRFileDesc *ssl) { SECStatus success = SECSuccess; PRErrorCode err; tlsm_ctx *ctx = (tlsm_ctx *)arg; if (!ssl || !ctx) { return SECFailure; } err = PORT_GetError(); switch (err) { case SEC_ERROR_UNTRUSTED_ISSUER: case SEC_ERROR_UNKNOWN_ISSUER: case SEC_ERROR_EXPIRED_CERTIFICATE: case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE: if (ctx->tc_verify_cert) { success = SECFailure; } break; /* we bypass NSS's hostname checks and do our own */ case SSL_ERROR_BAD_CERT_DOMAIN: break; default: success = SECFailure; break; } return success; } static const char * tlsm_dump_security_status(PRFileDesc *fd) { char * cp; /* bulk cipher name */ char * ip; /* cert issuer DN */ char * sp; /* cert subject DN */ int op; /* High, Low, Off */ int kp0; /* total key bits */ int kp1; /* secret key bits */ SSL3Statistics * ssl3stats = SSL_GetStatistics(); SSL_SecurityStatus( fd, &op, &cp, &kp0, &kp1, &ip, &sp ); Debug( LDAP_DEBUG_TRACE, "TLS certificate verification: subject: %s, issuer: %s, cipher: %s, ", sp ? sp : "-unknown-", ip ? ip : "-unknown-", cp ? cp : "-unknown-" ); PR_Free(cp); PR_Free(ip); PR_Free(sp); Debug( LDAP_DEBUG_TRACE, "security level: %s, secret key bits: %d, total key bits: %d, ", ((op == SSL_SECURITY_STATUS_ON_HIGH) ? "high" : ((op == SSL_SECURITY_STATUS_ON_LOW) ? "low" : "off")), kp1, kp0 ); Debug( LDAP_DEBUG_TRACE, "cache hits: %ld, cache misses: %ld, cache not reusable: %ld\n", ssl3stats->hch_sid_cache_hits, ssl3stats->hch_sid_cache_misses, ssl3stats->hch_sid_cache_not_ok ); return ""; } static void tlsm_handshake_complete_cb( PRFileDesc *fd, void *client_data ) { tlsm_dump_security_status( fd ); } #ifdef READ_PASSWORD_FROM_FILE static char * tlsm_get_pin_from_file(const char *token_name, tlsm_ctx *ctx) { char *pwdstr = NULL; char *contents = NULL; char *lasts = NULL; char *line = NULL; char *candidate = NULL; PRFileInfo file_info; PRFileDesc *pwd_fileptr = PR_Open( ctx->tc_pin_file, PR_RDONLY, 00400 ); /* open the password file */ if ( !pwd_fileptr ) { PRErrorCode errcode = PR_GetError(); Debug( LDAP_DEBUG_ANY, "TLS: could not open security pin file %s - error %d:%s.\n", ctx->tc_pin_file, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) ); goto done; } /* get the file size */ if ( PR_SUCCESS != PR_GetFileInfo( ctx->tc_pin_file, &file_info ) ) { PRErrorCode errcode = PR_GetError(); Debug( LDAP_DEBUG_ANY, "TLS: could not get file info from pin file %s - error %d:%s.\n", ctx->tc_pin_file, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) ); goto done; } /* create a buffer to hold the file contents */ if ( !( contents = PR_CALLOC( file_info.size + 1 ) ) ) { PRErrorCode errcode = PR_GetError(); Debug( LDAP_DEBUG_ANY, "TLS: could not alloc a buffer for contents of pin file %s - error %d:%s.\n", ctx->tc_pin_file, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) ); goto done; } /* read file into the buffer */ if( PR_Read( pwd_fileptr, contents, file_info.size ) <= 0 ) { PRErrorCode errcode = PR_GetError(); Debug( LDAP_DEBUG_ANY, "TLS: could not read the file contents from pin file %s - error %d:%s.\n", ctx->tc_pin_file, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) ); goto done; } /* format is [tokenname:]password EOL [tokenname:]password EOL ... */ /* if you want to use a password containing a colon character, use the special tokenname "default" */ for ( line = PL_strtok_r( contents, "\r\n", &lasts ); line; line = PL_strtok_r( NULL, "\r\n", &lasts ) ) { char *colon; if ( !*line ) { continue; /* skip blank lines */ } colon = PL_strchr( line, ':' ); if ( colon ) { if ( *(colon + 1) && token_name && !PL_strncmp( token_name, line, colon-line ) ) { candidate = colon + 1; /* found a definite match */ break; } else if ( !PL_strncmp( DEFAULT_TOKEN_NAME, line, colon-line ) ) { candidate = colon + 1; /* found possible match */ } } else { /* no token name */ candidate = line; } } done: if ( pwd_fileptr ) { PR_Close( pwd_fileptr ); } if ( candidate ) { pwdstr = PL_strdup( candidate ); } PL_strfree( contents ); return pwdstr; } #endif /* READ_PASSWORD_FROM_FILE */ #ifdef READ_PASSWORD_FROM_STDIN /* * Turn the echoing off on a tty. */ static void echoOff(int fd) { if ( isatty( fd ) ) { struct termios tio; tcgetattr( fd, &tio ); tio.c_lflag &= ~ECHO; tcsetattr( fd, TCSAFLUSH, &tio ); } } /* * Turn the echoing on on a tty. */ static void echoOn(int fd) { if ( isatty( fd ) ) { struct termios tio; tcgetattr( fd, &tio ); tio.c_lflag |= ECHO; tcsetattr( fd, TCSAFLUSH, &tio ); tcsetattr( fd, TCSAFLUSH, &tio ); } } #endif /* READ_PASSWORD_FROM_STDIN */ /* * This does the actual work of reading the pin/password/pass phrase */ static char * tlsm_get_pin(PK11SlotInfo *slot, PRBool retry, tlsm_ctx *ctx) { char *token_name = NULL; char *pwdstr = NULL; token_name = PK11_GetTokenName( slot ); #ifdef READ_PASSWORD_FROM_FILE /* Try to get the passwords from the password file if it exists. * THIS IS UNSAFE and is provided for convenience only. Without this * capability the server would have to be started in foreground mode * if using an encrypted key. */ if ( ctx && ctx->tc_pin_file ) { pwdstr = tlsm_get_pin_from_file( token_name, ctx ); if ( retry && pwdstr != NULL ) return NULL; } #endif /* RETRIEVE_PASSWORD_FROM_FILE */ #ifdef READ_PASSWORD_FROM_STDIN if ( !pwdstr ) { int infd = PR_FileDesc2NativeHandle( PR_STDIN ); int isTTY = isatty( infd ); unsigned char phrase[200]; /* Prompt for password */ if ( isTTY ) { fprintf( stdout, "Please enter pin, password, or pass phrase for security token '%s': ", token_name ? token_name : DEFAULT_TOKEN_NAME ); echoOff( infd ); } fgets( (char*)phrase, sizeof(phrase), stdin ); if ( isTTY ) { fprintf( stdout, "\n" ); echoOn( infd ); } /* stomp on newline */ phrase[strlen((char*)phrase)-1] = 0; pwdstr = PL_strdup( (char*)phrase ); } #endif /* READ_PASSWORD_FROM_STDIN */ return pwdstr; } /* * PKCS11 devices (including the internal softokn cert/key database) * may be protected by a pin or password or even pass phrase * MozNSS needs a way for the user to provide that */ static char * tlsm_pin_prompt(PK11SlotInfo *slot, PRBool retry, void *arg) { tlsm_ctx *ctx = (tlsm_ctx *)arg; return tlsm_get_pin( slot, retry, ctx ); } static char * tlsm_ctx_subject_name(tlsm_ctx *ctx) { if ( !ctx || !ctx->tc_certificate ) return "(unknown)"; return ctx->tc_certificate->subjectName; } static SECStatus tlsm_get_basic_constraint_extension( CERTCertificate *cert, CERTBasicConstraints *cbcval ) { SECItem encodedVal = { 0, NULL }; SECStatus rc; rc = CERT_FindCertExtension( cert, SEC_OID_X509_BASIC_CONSTRAINTS, &encodedVal); if ( rc != SECSuccess ) { return rc; } rc = CERT_DecodeBasicConstraintValue( cbcval, &encodedVal ); /* free the raw extension data */ PORT_Free( encodedVal.data ); return rc; } static PRBool tlsm_cert_is_self_issued( CERTCertificate *cert ) { /* A cert is self-issued if its subject and issuer are equal and * both are of non-zero length. */ PRBool is_self_issued = cert && (PRBool)SECITEM_ItemsAreEqual( &cert->derIssuer, &cert->derSubject ) && cert->derSubject.len > 0; return is_self_issued; } /* * The private key for used certificate can be already unlocked by other * thread or library. Find the unlocked key if possible. */ static SECKEYPrivateKey * tlsm_find_unlocked_key( tlsm_ctx *ctx, void *pin_arg ) { SECKEYPrivateKey *result = NULL; PK11SlotList *slots = PK11_GetAllSlotsForCert( ctx->tc_certificate, NULL ); if ( !slots ) { PRErrorCode errcode = PR_GetError(); Debug( LDAP_DEBUG_ANY, "TLS: cannot get all slots for certificate '%s' (error %d: %s)", tlsm_ctx_subject_name( ctx ), errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) ); return result; } PK11SlotListElement *le; for ( le = slots->head; le; le = le->next ) { PK11SlotInfo *slot = le->slot; if ( PK11_IsLoggedIn( slot, NULL ) ) { result = PK11_FindKeyByDERCert( slot, ctx->tc_certificate, pin_arg ); break; } } PK11_FreeSlotList( slots ); return result; } static SECStatus tlsm_verify_cert(CERTCertDBHandle *handle, CERTCertificate *cert, void *pinarg, PRBool checksig, SECCertificateUsage certUsage, PRBool warn_only, PRBool ignore_issuer ) { CERTVerifyLog verifylog; SECStatus ret = SECSuccess; const char *name; int debug_level = LDAP_DEBUG_ANY; if ( warn_only ) { debug_level = LDAP_DEBUG_TRACE; } /* the log captures information about every cert in the chain, so we can tell which cert caused the problem and what the problem was */ memset( &verifylog, 0, sizeof( verifylog ) ); verifylog.arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE ); if ( verifylog.arena == NULL ) { Debug( LDAP_DEBUG_ANY, "TLS certificate verification: Out of memory for certificate verification logger\n", 0, 0, 0 ); return SECFailure; } ret = CERT_VerifyCertificate( handle, cert, checksig, certUsage, PR_Now(), pinarg, &verifylog, NULL ); if ( ( name = cert->subjectName ) == NULL ) { name = cert->nickname; } if ( verifylog.head == NULL ) { /* it is possible for CERT_VerifyCertificate return with an error with no logging */ if ( ret != SECSuccess ) { PRErrorCode errcode = PR_GetError(); Debug( debug_level, "TLS: certificate [%s] is not valid - error %d:%s.\n", name ? name : "(unknown)", errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) ); } } else { const char *name; CERTVerifyLogNode *node; ret = SECSuccess; /* reset */ node = verifylog.head; while ( node ) { if ( ( name = node->cert->subjectName ) == NULL ) { name = node->cert->nickname; } if ( node->error ) { /* NSS does not like CA certs that have the basic constraints extension with the CA flag set to FALSE - openssl doesn't check if the cert is self issued */ if ( ( node->error == SEC_ERROR_CA_CERT_INVALID ) && tlsm_cert_is_self_issued( node->cert ) ) { PRErrorCode orig_error = PR_GetError(); PRInt32 orig_oserror = PR_GetOSError(); CERTBasicConstraints basicConstraint; SECStatus rv = tlsm_get_basic_constraint_extension( node->cert, &basicConstraint ); if ( ( rv == SECSuccess ) && ( basicConstraint.isCA == PR_FALSE ) ) { Debug( LDAP_DEBUG_TRACE, "TLS: certificate [%s] is not correct because it is a CA cert and the " "BasicConstraint CA flag is set to FALSE - allowing for now, but " "please fix your certs if possible\n", name, 0, 0 ); } else { /* does not have basicconstraint, or some other error */ ret = SECFailure; Debug( debug_level, "TLS: certificate [%s] is not valid - CA cert is not valid\n", name, 0, 0 ); } PR_SetError( orig_error, orig_oserror ); } else if ( warn_only || ( ignore_issuer && ( node->error == SEC_ERROR_UNKNOWN_ISSUER || node->error == SEC_ERROR_UNTRUSTED_ISSUER ) ) ) { ret = SECSuccess; Debug( debug_level, "TLS: Warning: ignoring error for certificate [%s] - error %ld:%s.\n", name, node->error, PR_ErrorToString( node->error, PR_LANGUAGE_I_DEFAULT ) ); } else { ret = SECFailure; Debug( debug_level, "TLS: certificate [%s] is not valid - error %ld:%s.\n", name, node->error, PR_ErrorToString( node->error, PR_LANGUAGE_I_DEFAULT ) ); } } CERT_DestroyCertificate( node->cert ); node = node->next; } } PORT_FreeArena( verifylog.arena, PR_FALSE ); if ( ret == SECSuccess ) { Debug( LDAP_DEBUG_TRACE, "TLS: certificate [%s] is valid\n", name, 0, 0 ); } return ret; } static SECStatus tlsm_auth_cert_handler(void *arg, PRFileDesc *fd, PRBool checksig, PRBool isServer) { SECCertificateUsage certUsage = isServer ? certificateUsageSSLClient : certificateUsageSSLServer; SECStatus ret = SECSuccess; CERTCertificate *peercert = SSL_PeerCertificate( fd ); tlsm_ctx *ctx = (tlsm_ctx *)arg; ret = tlsm_verify_cert( ctx->tc_certdb, peercert, SSL_RevealPinArg( fd ), checksig, certUsage, ctx->tc_warn_only, PR_FALSE ); CERT_DestroyCertificate( peercert ); return ret; } static SECStatus tlsm_nss_shutdown_cb( void *appData, void *nssData ) { SECStatus rc = SECSuccess; SSL_ShutdownServerSessionIDCache(); if ( pem_module ) { SECMOD_UnloadUserModule( pem_module ); SECMOD_DestroyModule( pem_module ); pem_module = NULL; } return rc; } static PRCallOnceType tlsm_register_shutdown_callonce = {0,0}; static PRStatus PR_CALLBACK tlsm_register_nss_shutdown_cb( void ) { if ( SECSuccess == NSS_RegisterShutdown( tlsm_nss_shutdown_cb, NULL ) ) { return PR_SUCCESS; } return PR_FAILURE; } static PRStatus tlsm_register_nss_shutdown( void ) { return PR_CallOnce( &tlsm_register_shutdown_callonce, tlsm_register_nss_shutdown_cb ); } static int tlsm_init_pem_module( void ) { int rc = 0; char *fullname = NULL; char *configstring = NULL; if ( pem_module ) { return rc; } /* not loaded - load it */ /* get the system dependent library name */ fullname = PR_GetLibraryName( NULL, PEM_LIBRARY ); /* Load our PKCS#11 module */ configstring = PR_smprintf( "library=%s name=" PEM_MODULE " parameters=\"\"", fullname ); PL_strfree( fullname ); pem_module = SECMOD_LoadUserModule( configstring, NULL, PR_FALSE ); PR_smprintf_free( configstring ); if ( !pem_module || !pem_module->loaded ) { if ( pem_module ) { SECMOD_DestroyModule( pem_module ); pem_module = NULL; } rc = -1; } return rc; } static void tlsm_add_pem_obj( tlsm_ctx *ctx, PK11GenericObject *obj ) { int idx = ctx->tc_n_pem_objs; ctx->tc_n_pem_objs++; ctx->tc_pem_objs = (PK11GenericObject **) PORT_Realloc( ctx->tc_pem_objs, ctx->tc_n_pem_objs * sizeof( PK11GenericObject * ) ); ctx->tc_pem_objs[idx] = obj; } static void tlsm_free_pem_objs( tlsm_ctx *ctx ) { /* free in reverse order of allocation */ while ( ctx->tc_n_pem_objs-- ) { PK11_DestroyGenericObject( ctx->tc_pem_objs[ctx->tc_n_pem_objs] ); ctx->tc_pem_objs[ctx->tc_n_pem_objs] = NULL; } PORT_Free(ctx->tc_pem_objs); ctx->tc_pem_objs = NULL; ctx->tc_n_pem_objs = 0; } static int tlsm_add_cert_from_file( tlsm_ctx *ctx, const char *filename, PRBool isca ) { PK11SlotInfo *slot; PK11GenericObject *cert; CK_ATTRIBUTE attrs[4]; CK_BBOOL cktrue = CK_TRUE; CK_BBOOL ckfalse = CK_FALSE; CK_OBJECT_CLASS objClass = CKO_CERTIFICATE; char *slotname; PRFileInfo fi; PRStatus status; SECItem certDER = { 0, NULL, 0 }; memset( &fi, 0, sizeof(fi) ); status = PR_GetFileInfo( filename, &fi ); if ( PR_SUCCESS != status) { PRErrorCode errcode = PR_GetError(); Debug( LDAP_DEBUG_ANY, "TLS: could not read certificate file %s - error %d:%s.\n", filename, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) ); return -1; } if ( fi.type != PR_FILE_FILE ) { PR_SetError(PR_IS_DIRECTORY_ERROR, 0); Debug( LDAP_DEBUG_ANY, "TLS: error: the certificate file %s is not a file.\n", filename, 0 ,0 ); return -1; } slotname = isca ? TLSM_PEM_SLOT_CACERTS : TLSM_PEM_SLOT_CERTS; slot = PK11_FindSlotByName( slotname ); if ( !slot ) { PRErrorCode errcode = PR_GetError(); Debug( LDAP_DEBUG_ANY, "TLS: could not find the slot for the certificate '%s' - error %d:%s.\n", filename, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) ); return -1; } PK11_SETATTRS( attrs[0], CKA_CLASS, &objClass, sizeof( objClass ) ); PK11_SETATTRS( attrs[1], CKA_TOKEN, &cktrue, sizeof( CK_BBOOL ) ); PK11_SETATTRS( attrs[2], CKA_LABEL, (unsigned char *) filename, strlen( filename ) + 1 ); PK11_SETATTRS( attrs[3], CKA_TRUST, isca ? &cktrue : &ckfalse, sizeof( CK_BBOOL ) ); cert = PK11_CreateGenericObject( slot, attrs, 4, PR_FALSE /* isPerm */ ); if ( !cert ) { PRErrorCode errcode = PR_GetError(); Debug( LDAP_DEBUG_ANY, "TLS: could not add the certificate '%s' - error %d:%s.\n", filename, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) ); PK11_FreeSlot( slot ); return -1; } /* if not CA, we store the certificate in ctx->tc_certificate */ if ( !isca ) { if ( PK11_ReadRawAttribute( PK11_TypeGeneric, cert, CKA_VALUE, &certDER ) != SECSuccess ) { PRErrorCode errcode = PR_GetError(); Debug( LDAP_DEBUG_ANY, "TLS: could not get DER of the '%s' certificate - error %d:%s.\n", filename, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) ); PK11_DestroyGenericObject( cert ); PK11_FreeSlot( slot ); return -1; } ctx->tc_certificate = PK11_FindCertFromDERCertItem( slot, &certDER, NULL ); SECITEM_FreeItem( &certDER, PR_FALSE ); if ( !ctx->tc_certificate ) { PRErrorCode errcode = PR_GetError(); Debug( LDAP_DEBUG_ANY, "TLS: could not get certificate '%s' using DER - error %d:%s.\n", filename, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) ); PK11_DestroyGenericObject( cert ); PK11_FreeSlot( slot ); return -1; } } tlsm_add_pem_obj( ctx, cert ); PK11_FreeSlot( slot ); return 0; } static int tlsm_ctx_load_private_key( tlsm_ctx *ctx ) { if ( !ctx->tc_certificate ) return -1; if ( ctx->tc_private_key ) return 0; void *pin_arg = SSL_RevealPinArg( ctx->tc_model ); SECKEYPrivateKey *unlocked_key = tlsm_find_unlocked_key( ctx, pin_arg ); Debug( LDAP_DEBUG_ANY, "TLS: %s unlocked certificate for certificate '%s'.\n", unlocked_key ? "found" : "no", tlsm_ctx_subject_name( ctx ), 0 ); /* prefer unlocked key, then key from opened certdb, then any other */ if ( unlocked_key ) ctx->tc_private_key = unlocked_key; else if ( ctx->tc_certdb_slot ) ctx->tc_private_key = PK11_FindKeyByDERCert( ctx->tc_certdb_slot, ctx->tc_certificate, pin_arg ); else ctx->tc_private_key = PK11_FindKeyByAnyCert( ctx->tc_certificate, pin_arg ); if ( !ctx->tc_private_key ) { PRErrorCode errcode = PR_GetError(); Debug(LDAP_DEBUG_ANY, "TLS: cannot find private key for certificate '%s' (error %d: %s)", tlsm_ctx_subject_name( ctx ), errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) ); return -1; } return 0; } static int tlsm_add_key_from_file( tlsm_ctx *ctx, const char *filename ) { PK11SlotInfo * slot = NULL; PK11GenericObject *key; CK_ATTRIBUTE attrs[3]; CK_BBOOL cktrue = CK_TRUE; CK_OBJECT_CLASS objClass = CKO_PRIVATE_KEY; int retcode = 0; PRFileInfo fi; PRStatus status; memset( &fi, 0, sizeof(fi) ); status = PR_GetFileInfo( filename, &fi ); if ( PR_SUCCESS != status) { PRErrorCode errcode = PR_GetError(); Debug( LDAP_DEBUG_ANY, "TLS: could not read key file %s - error %d:%s.\n", filename, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) ); return -1; } if ( fi.type != PR_FILE_FILE ) { PR_SetError(PR_IS_DIRECTORY_ERROR, 0); Debug( LDAP_DEBUG_ANY, "TLS: error: the key file %s is not a file.\n", filename, 0 ,0 ); return -1; } slot = PK11_FindSlotByName( TLSM_PEM_SLOT_CERTS ); if ( !slot ) { PRErrorCode errcode = PR_GetError(); Debug( LDAP_DEBUG_ANY, "TLS: could not find the slot for the private key '%s' - error %d:%s.\n", filename, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) ); return -1; } PK11_SETATTRS( attrs[0], CKA_CLASS, &objClass, sizeof( objClass ) ); PK11_SETATTRS( attrs[1], CKA_TOKEN, &cktrue, sizeof( CK_BBOOL ) ); PK11_SETATTRS( attrs[2], CKA_LABEL, (unsigned char *)filename, strlen( filename ) + 1 ); key = PK11_CreateGenericObject( slot, attrs, 3, PR_FALSE /* isPerm */ ); if ( !key ) { PRErrorCode errcode = PR_GetError(); Debug( LDAP_DEBUG_ANY, "TLS: could not add the private key '%s' - error %d:%s.\n", filename, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) ); retcode = -1; } else { tlsm_add_pem_obj( ctx, key ); retcode = 0; /* When adding an encrypted key the PKCS#11 will be set as removed */ /* This will force the token to be seen as re-inserted */ SECMOD_WaitForAnyTokenEvent( pem_module, 0, 0 ); PK11_IsPresent( slot ); } PK11_FreeSlot( slot ); return retcode; } static int tlsm_init_ca_certs( tlsm_ctx *ctx, const char *cacertfile, const char *cacertdir ) { PRBool isca = PR_TRUE; PRStatus status = PR_SUCCESS; PRErrorCode errcode = PR_SUCCESS; if ( !cacertfile && !cacertdir ) { /* no checking - not good, but allowed */ return 0; } if ( cacertfile ) { int rc = tlsm_add_cert_from_file( ctx, cacertfile, isca ); if ( rc ) { errcode = PR_GetError(); Debug( LDAP_DEBUG_ANY, "TLS: %s is not a valid CA certificate file - error %d:%s.\n", cacertfile, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) ); /* failure with cacertfile is a hard failure even if cacertdir is also specified and contains valid CA cert files */ status = PR_FAILURE; } else { Debug( LDAP_DEBUG_TRACE, "TLS: loaded CA certificate file %s.\n", cacertfile, 0, 0 ); } } /* if cacertfile above failed, we will return failure, even if there is a valid CA cert in cacertdir - but we still process cacertdir in case the user has enabled trace level debugging so they can see the processing for cacertdir too */ /* any cacertdir failures are "soft" failures - if the user specifies no cert checking, then we allow the tls/ssl to continue, no matter what was specified for cacertdir, or the contents of the directory - this is different behavior than that of cacertfile */ if ( cacertdir ) { PRFileInfo fi; PRDir *dir; PRDirEntry *entry; PRStatus fistatus = PR_FAILURE; memset( &fi, 0, sizeof(fi) ); fistatus = PR_GetFileInfo( cacertdir, &fi ); if ( PR_SUCCESS != fistatus) { errcode = PR_GetError(); Debug( LDAP_DEBUG_ANY, "TLS: could not get info about the CA certificate directory %s - error %d:%s.\n", cacertdir, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) ); goto done; } if ( fi.type != PR_FILE_DIRECTORY ) { Debug( LDAP_DEBUG_ANY, "TLS: error: the CA certificate directory %s is not a directory.\n", cacertdir, 0 ,0 ); goto done; } dir = PR_OpenDir( cacertdir ); if ( NULL == dir ) { errcode = PR_GetError(); Debug( LDAP_DEBUG_ANY, "TLS: could not open the CA certificate directory %s - error %d:%s.\n", cacertdir, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) ); goto done; } do { entry = PR_ReadDir( dir, PR_SKIP_BOTH | PR_SKIP_HIDDEN ); if ( ( NULL != entry ) && ( NULL != entry->name ) ) { char *fullpath = NULL; char *ptr; ptr = PL_strrstr( entry->name, PEM_CA_HASH_FILE_SUFFIX ); if ( ( ptr == NULL ) || ( *(ptr + PEM_CA_HASH_FILE_SUFFIX_LEN) != '\0' ) ) { Debug( LDAP_DEBUG_TRACE, "TLS: file %s does not end in [%s] - does not appear to be a CA certificate " "directory file with a properly hashed file name - skipping.\n", entry->name, PEM_CA_HASH_FILE_SUFFIX, 0 ); continue; } fullpath = PR_smprintf( "%s/%s", cacertdir, entry->name ); if ( !tlsm_add_cert_from_file( ctx, fullpath, isca ) ) { Debug( LDAP_DEBUG_TRACE, "TLS: loaded CA certificate file %s from CA certificate directory %s.\n", fullpath, cacertdir, 0 ); } else { errcode = PR_GetError(); Debug( LDAP_DEBUG_TRACE, "TLS: %s is not a valid CA certificate file - error %d:%s.\n", fullpath, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) ); } PR_smprintf_free( fullpath ); } } while ( NULL != entry ); PR_CloseDir( dir ); } done: if ( status != PR_SUCCESS ) { return -1; } return 0; } /* * NSS supports having multiple cert/key databases in the same * directory, each one having a unique string prefix e.g. * slapd-01-cert8.db - the prefix here is "slapd-01-" * this function examines the given certdir - if it looks like * /path/to/directory/prefix it will return the * /path/to/directory part in realcertdir, and the prefix in prefix */ static void tlsm_get_certdb_prefix( const char *certdir, char **realcertdir, char **prefix ) { char sep = PR_GetDirectorySeparator(); char *ptr = NULL; struct PRFileInfo prfi; PRStatus prc; *realcertdir = (char *)certdir; /* default is the one passed in */ /* if certdir is not given, just return */ if ( !certdir ) { return; } prc = PR_GetFileInfo( certdir, &prfi ); /* if certdir exists (file or directory) then it cannot specify a prefix */ if ( prc == PR_SUCCESS ) { return; } /* if certdir was given, and there is a '/' in certdir, see if there is anything after the last '/' - if so, assume it is the prefix */ if ( ( ( ptr = strrchr( certdir, sep ) ) ) && *(ptr+1) ) { *realcertdir = PL_strndup( certdir, ptr-certdir ); *prefix = PL_strdup( ptr+1 ); } return; } /* * Currently mutiple MozNSS contexts share one certificate storage. When the * certdb is being opened, only new certificates are added to the storage. * When different databases are used, conflicting nicknames make the * certificate lookup by the nickname impossible. In addition a token * description might be prepended in certain conditions. * * In order to make the certificate lookup by nickname possible, we explicitly * open each database using SECMOD_OpenUserDB and assign it the token * description. The token description is generated using ctx->tc_unique value, * which is unique for each context. */ static PK11SlotInfo * tlsm_init_open_certdb( tlsm_ctx *ctx, const char *dbdir, const char *prefix ) { PK11SlotInfo *slot = NULL; char *token_desc = NULL; char *config = NULL; token_desc = PR_smprintf( TLSM_CERTDB_DESC_FMT, ctx->tc_unique ); config = PR_smprintf( "configDir='%s' tokenDescription='%s' certPrefix='%s' keyPrefix='%s' flags=readOnly", dbdir, token_desc, prefix, prefix ); Debug( LDAP_DEBUG_TRACE, "TLS: certdb config: %s\n", config, 0, 0 ); slot = SECMOD_OpenUserDB( config ); if ( !slot ) { PRErrorCode errcode = PR_GetError(); Debug( LDAP_DEBUG_TRACE, "TLS: cannot open certdb '%s', error %d:%s\n", dbdir, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) ); } if ( token_desc ) PR_smprintf_free( token_desc ); if ( config ) PR_smprintf_free( config ); return slot; } /* * This is the part of the init we defer until we get the * actual security configuration information. This is * only called once, protected by a PRCallOnce * NOTE: This must be done before the first call to SSL_ImportFD, * especially the setting of the policy * NOTE: This must be called after fork() */ static int tlsm_deferred_init( void *arg ) { tlsm_ctx *ctx = (tlsm_ctx *)arg; struct ldaptls *lt = ctx->tc_config; const char *securitydirs[3]; int ii; int nn; PRErrorCode errcode = 1; #ifdef HAVE_NSS_INITCONTEXT NSSInitParameters initParams; NSSInitContext *initctx = NULL; PK11SlotInfo *certdb_slot = NULL; #endif SECStatus rc; int done = 0; #ifdef HAVE_SECMOD_RESTARTMODULES /* NSS enforces the pkcs11 requirement that modules should be unloaded after a fork() - since there is no portable way to determine if NSS has been already initialized in a parent process, we just call SECMOD_RestartModules with force == FALSE - if the module has been unloaded due to a fork, it will be reloaded, otherwise, it is a no-op */ if ( SECFailure == ( rc = SECMOD_RestartModules(PR_FALSE /* do not force */) ) ) { errcode = PORT_GetError(); if ( errcode != SEC_ERROR_NOT_INITIALIZED ) { Debug( LDAP_DEBUG_TRACE, "TLS: could not restart the security modules: %d:%s\n", errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), 0 ); } else { errcode = 1; } } #endif #ifdef HAVE_NSS_INITCONTEXT memset( &initParams, 0, sizeof( initParams ) ); initParams.length = sizeof( initParams ); #endif /* HAVE_NSS_INITCONTEXT */ #ifdef LDAP_R_COMPILE if ( PR_CallOnce( &tlsm_init_mutex_callonce, tlsm_thr_init_callonce ) ) { return -1; } #endif /* LDAP_R_COMPILE */ #ifndef HAVE_NSS_INITCONTEXT if ( !NSS_IsInitialized() ) { #endif /* HAVE_NSS_INITCONTEXT */ /* MOZNSS_DIR will override everything else - you can always set MOZNSS_DIR to force the use of this directory If using MOZNSS, specify the location of the moznss db dir in the cacertdir directive of the OpenLDAP configuration. DEFAULT_MOZNSS_DIR will only be used if the code cannot find a security dir to use based on the current settings */ nn = 0; securitydirs[nn++] = PR_GetEnv( "MOZNSS_DIR" ); securitydirs[nn++] = lt->lt_cacertdir; securitydirs[nn++] = PR_GetEnv( "DEFAULT_MOZNSS_DIR" ); for ( ii = 0; !done && ( ii < nn ); ++ii ) { char *realcertdir = NULL; const char *defprefix = ""; char *prefix = (char *)defprefix; const char *securitydir = securitydirs[ii]; if ( NULL == securitydir ) { continue; } tlsm_get_certdb_prefix( securitydir, &realcertdir, &prefix ); /* initialize only moddb; certdb will be initialized explicitly */ #ifdef HAVE_NSS_INITCONTEXT #ifdef INITCONTEXT_HACK if ( !NSS_IsInitialized() && ctx->tc_is_server ) { rc = NSS_Initialize( realcertdir, prefix, prefix, SECMOD_DB, NSS_INIT_READONLY ); } else { initctx = NSS_InitContext( realcertdir, prefix, prefix, SECMOD_DB, &initParams, NSS_INIT_READONLY|NSS_INIT_NOCERTDB ); } #else initctx = NSS_InitContext( realcertdir, prefix, prefix, SECMOD_DB, &initParams, NSS_INIT_READONLY|NSS_INIT_NOCERTDB ); #endif rc = SECFailure; if ( initctx != NULL ) { certdb_slot = tlsm_init_open_certdb( ctx, realcertdir, prefix ); if ( certdb_slot ) { rc = SECSuccess; ctx->tc_initctx = initctx; ctx->tc_certdb_slot = certdb_slot; } else { NSS_ShutdownContext( initctx ); initctx = NULL; } } #else rc = NSS_Initialize( realcertdir, prefix, prefix, SECMOD_DB, NSS_INIT_READONLY ); #endif if ( rc != SECSuccess ) { errcode = PORT_GetError(); if ( securitydirs[ii] != lt->lt_cacertdir) { Debug( LDAP_DEBUG_TRACE, "TLS: could not initialize moznss using security dir %s prefix %s - error %d.\n", realcertdir, prefix, errcode ); } } else { /* success */ Debug( LDAP_DEBUG_TRACE, "TLS: using moznss security dir %s prefix %s.\n", realcertdir, prefix, 0 ); errcode = 0; done = 1; } if ( realcertdir != securitydir ) { PL_strfree( realcertdir ); } if ( prefix != defprefix ) { PL_strfree( prefix ); } } if ( errcode ) { /* no moznss db found, or not using moznss db */ #ifdef HAVE_NSS_INITCONTEXT int flags = NSS_INIT_READONLY|NSS_INIT_NOCERTDB|NSS_INIT_NOMODDB; #ifdef INITCONTEXT_HACK if ( !NSS_IsInitialized() && ctx->tc_is_server ) { rc = NSS_NoDB_Init( NULL ); } else { initctx = NSS_InitContext( CERTDB_NONE, PREFIX_NONE, PREFIX_NONE, SECMOD_DB, &initParams, flags ); rc = (initctx == NULL) ? SECFailure : SECSuccess; } #else initctx = NSS_InitContext( CERTDB_NONE, PREFIX_NONE, PREFIX_NONE, SECMOD_DB, &initParams, flags ); if ( initctx ) { ctx->tc_initctx = initctx; rc = SECSuccess; } else { rc = SECFailure; } #endif #else rc = NSS_NoDB_Init( NULL ); #endif if ( rc != SECSuccess ) { errcode = PORT_GetError(); Debug( LDAP_DEBUG_ANY, "TLS: could not initialize moznss - error %d:%s.\n", errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), 0 ); return -1; } } if ( errcode || lt->lt_cacertfile ) { /* initialize the PEM module */ if ( tlsm_init_pem_module() ) { int pem_errcode = PORT_GetError(); Debug( LDAP_DEBUG_ANY, "TLS: could not initialize moznss PEM module - error %d:%s.\n", pem_errcode, PR_ErrorToString( pem_errcode, PR_LANGUAGE_I_DEFAULT ), 0 ); if ( errcode ) /* PEM is required */ return -1; } else if ( !errcode ) { tlsm_init_ca_certs( ctx, lt->lt_cacertfile, NULL ); } } if ( errcode ) { if ( tlsm_init_ca_certs( ctx, lt->lt_cacertfile, lt->lt_cacertdir ) ) { /* if we tried to use lt->lt_cacertdir as an NSS key/cert db, errcode will be a value other than 1 - print an error message so that the user will know that failed too */ if ( ( errcode != 1 ) && ( lt->lt_cacertdir ) ) { char *realcertdir = NULL; char *prefix = NULL; tlsm_get_certdb_prefix( lt->lt_cacertdir, &realcertdir, &prefix ); Debug( LDAP_DEBUG_TRACE, "TLS: could not initialize moznss using security dir %s prefix %s - error %d.\n", realcertdir, prefix ? prefix : "", errcode ); if ( realcertdir != lt->lt_cacertdir ) { PL_strfree( realcertdir ); } PL_strfree( prefix ); } return -1; } ctx->tc_using_pem = PR_TRUE; } NSS_SetDomesticPolicy(); PK11_SetPasswordFunc( tlsm_pin_prompt ); /* register cleanup function */ if ( tlsm_register_nss_shutdown() ) { errcode = PORT_GetError(); Debug( LDAP_DEBUG_ANY, "TLS: could not register NSS shutdown function: %d:%s\n", errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), 0 ); return -1; } if ( ctx->tc_is_server ) { /* 0 means use the defaults here */ SSL_ConfigServerSessionIDCache( 0, 0, 0, NULL ); } #ifndef HAVE_NSS_INITCONTEXT } #endif /* HAVE_NSS_INITCONTEXT */ return 0; } /* * Find and verify the certificate. * The key is loaded and stored in ctx->tc_private_key */ static int tlsm_find_and_verify_cert_key( tlsm_ctx *ctx ) { SECCertificateUsage certUsage; PRBool checkSig; SECStatus status; void *pin_arg; if ( tlsm_ctx_load_private_key( ctx ) ) return -1; pin_arg = SSL_RevealPinArg( ctx->tc_model ); certUsage = ctx->tc_is_server ? certificateUsageSSLServer : certificateUsageSSLClient; checkSig = ctx->tc_verify_cert ? PR_TRUE : PR_FALSE; status = tlsm_verify_cert( ctx->tc_certdb, ctx->tc_certificate, pin_arg, checkSig, certUsage, ctx->tc_warn_only, PR_TRUE ); return status == SECSuccess ? 0 : -1; } static int tlsm_get_client_auth_data( void *arg, PRFileDesc *fd, CERTDistNames *caNames, CERTCertificate **pRetCert, SECKEYPrivateKey **pRetKey ) { tlsm_ctx *ctx = (tlsm_ctx *)arg; if ( pRetCert ) *pRetCert = CERT_DupCertificate( ctx->tc_certificate ); if ( pRetKey ) *pRetKey = SECKEY_CopyPrivateKey( ctx->tc_private_key ); return SECSuccess; } /* * ctx must have a tc_model that is valid */ static int tlsm_clientauth_init( tlsm_ctx *ctx ) { SECStatus status = SECFailure; int rc; PRBool saveval; saveval = ctx->tc_warn_only; ctx->tc_warn_only = PR_TRUE; rc = tlsm_find_and_verify_cert_key(ctx); ctx->tc_warn_only = saveval; if ( rc ) { Debug( LDAP_DEBUG_ANY, "TLS: error: unable to set up client certificate authentication for " "certificate named %s\n", tlsm_ctx_subject_name(ctx), 0, 0 ); return -1; } status = SSL_GetClientAuthDataHook( ctx->tc_model, tlsm_get_client_auth_data, (void *)ctx ); return ( status == SECSuccess ? 0 : -1 ); } /* * Tear down the TLS subsystem. Should only be called once. */ static void tlsm_destroy( void ) { #ifdef LDAP_R_COMPILE ldap_pvt_thread_mutex_destroy( &tlsm_ctx_count_mutex ); ldap_pvt_thread_mutex_destroy( &tlsm_init_mutex ); ldap_pvt_thread_mutex_destroy( &tlsm_pem_mutex ); #endif } static struct ldaptls * tlsm_copy_config ( const struct ldaptls *config ) { struct ldaptls *copy; assert( config ); copy = LDAP_MALLOC( sizeof( *copy ) ); if ( !copy ) return NULL; memset( copy, 0, sizeof( *copy ) ); if ( config->lt_certfile ) copy->lt_certfile = LDAP_STRDUP( config->lt_certfile ); if ( config->lt_keyfile ) copy->lt_keyfile = LDAP_STRDUP( config->lt_keyfile ); if ( config->lt_dhfile ) copy->lt_dhfile = LDAP_STRDUP( config->lt_dhfile ); if ( config->lt_cacertfile ) copy->lt_cacertfile = LDAP_STRDUP( config->lt_cacertfile ); if ( config->lt_cacertdir ) copy->lt_cacertdir = LDAP_STRDUP( config->lt_cacertdir ); if ( config->lt_ciphersuite ) copy->lt_ciphersuite = LDAP_STRDUP( config->lt_ciphersuite ); if ( config->lt_crlfile ) copy->lt_crlfile = LDAP_STRDUP( config->lt_crlfile ); if ( config->lt_randfile ) copy->lt_randfile = LDAP_STRDUP( config->lt_randfile ); copy->lt_protocol_min = config->lt_protocol_min; return copy; } static void tlsm_free_config ( struct ldaptls *config ) { assert( config ); if ( config->lt_certfile ) LDAP_FREE( config->lt_certfile ); if ( config->lt_keyfile ) LDAP_FREE( config->lt_keyfile ); if ( config->lt_dhfile ) LDAP_FREE( config->lt_dhfile ); if ( config->lt_cacertfile ) LDAP_FREE( config->lt_cacertfile ); if ( config->lt_cacertdir ) LDAP_FREE( config->lt_cacertdir ); if ( config->lt_ciphersuite ) LDAP_FREE( config->lt_ciphersuite ); if ( config->lt_crlfile ) LDAP_FREE( config->lt_crlfile ); if ( config->lt_randfile ) LDAP_FREE( config->lt_randfile ); LDAP_FREE( config ); } static tls_ctx * tlsm_ctx_new ( struct ldapoptions *lo ) { tlsm_ctx *ctx; ctx = LDAP_MALLOC( sizeof (*ctx) ); if ( ctx ) { ctx->tc_refcnt = 1; #ifdef LDAP_R_COMPILE ldap_pvt_thread_mutex_init( &ctx->tc_refmutex ); #endif LDAP_MUTEX_LOCK( &tlsm_ctx_count_mutex ); ctx->tc_unique = tlsm_ctx_count++; LDAP_MUTEX_UNLOCK( &tlsm_ctx_count_mutex ); ctx->tc_config = NULL; /* populated later by tlsm_ctx_init */ ctx->tc_certdb = NULL; ctx->tc_certdb_slot = NULL; ctx->tc_certificate = NULL; ctx->tc_private_key = NULL; ctx->tc_pin_file = NULL; ctx->tc_model = NULL; memset(&ctx->tc_callonce, 0, sizeof(ctx->tc_callonce)); ctx->tc_require_cert = lo->ldo_tls_require_cert; ctx->tc_verify_cert = PR_FALSE; ctx->tc_using_pem = PR_FALSE; #ifdef HAVE_NSS_INITCONTEXT ctx->tc_initctx = NULL; #endif /* HAVE_NSS_INITCONTEXT */ ctx->tc_pem_objs = NULL; ctx->tc_n_pem_objs = 0; ctx->tc_warn_only = PR_FALSE; } return (tls_ctx *)ctx; } static void tlsm_ctx_ref( tls_ctx *ctx ) { tlsm_ctx *c = (tlsm_ctx *)ctx; LDAP_MUTEX_LOCK( &c->tc_refmutex ); c->tc_refcnt++; LDAP_MUTEX_UNLOCK( &c->tc_refmutex ); } static void tlsm_ctx_free ( tls_ctx *ctx ) { tlsm_ctx *c = (tlsm_ctx *)ctx; int refcount; if ( !c ) return; LDAP_MUTEX_LOCK( &c->tc_refmutex ); refcount = --c->tc_refcnt; LDAP_MUTEX_UNLOCK( &c->tc_refmutex ); if ( refcount ) return; LDAP_MUTEX_LOCK( &tlsm_init_mutex ); if ( c->tc_model ) PR_Close( c->tc_model ); if ( c->tc_certificate ) CERT_DestroyCertificate( c->tc_certificate ); if ( c->tc_private_key ) SECKEY_DestroyPrivateKey( c->tc_private_key ); c->tc_certdb = NULL; /* if not the default, may have to clean up */ if ( c->tc_certdb_slot ) { if ( SECMOD_CloseUserDB( c->tc_certdb_slot ) ) { PRErrorCode errcode = PR_GetError(); Debug( LDAP_DEBUG_ANY, "TLS: could not close certdb slot - error %d:%s.\n", errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), 0 ); } } if ( c->tc_pin_file ) { PL_strfree( c->tc_pin_file ); c->tc_pin_file = NULL; } tlsm_free_pem_objs( c ); #ifdef HAVE_NSS_INITCONTEXT if ( c->tc_initctx ) { if ( NSS_ShutdownContext( c->tc_initctx ) ) { PRErrorCode errcode = PR_GetError(); Debug( LDAP_DEBUG_ANY, "TLS: could not shutdown NSS - error %d:%s.\n", errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), 0 ); } } c->tc_initctx = NULL; #endif /* HAVE_NSS_INITCONTEXT */ LDAP_MUTEX_UNLOCK( &tlsm_init_mutex ); #ifdef LDAP_R_COMPILE ldap_pvt_thread_mutex_destroy( &c->tc_refmutex ); #endif if ( c->tc_config ) tlsm_free_config( c->tc_config ); LDAP_FREE( c ); } /* * initialize a new TLS context */ static int tlsm_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server ) { tlsm_ctx *ctx = (tlsm_ctx *)lo->ldo_tls_ctx; ctx->tc_config = tlsm_copy_config( lt ); ctx->tc_is_server = is_server; return 0; } /* returns true if the given string looks like "tokenname" ":" "certnickname" This is true if there is a ':' colon character in the string and the colon is not the first or the last character in the string */ static int tlsm_is_tokenname_certnick( const char *certfile ) { if ( certfile ) { const char *ptr = PL_strchr( certfile, ':' ); return ptr && (ptr != certfile) && (*(ptr+1)); } return 0; } static int tlsm_deferred_ctx_init( void *arg ) { tlsm_ctx *ctx = (tlsm_ctx *)arg; PRBool sslv2 = PR_FALSE; PRBool sslv3 = PR_TRUE; PRBool tlsv1 = PR_TRUE; PRBool request_cert = PR_FALSE; PRInt32 require_cert = PR_FALSE; PRFileDesc *fd; struct ldaptls *lt; if ( tlsm_deferred_init( ctx ) ) { Debug( LDAP_DEBUG_ANY, "TLS: could not perform TLS system initialization.\n", 0, 0, 0 ); return -1; } ctx->tc_certdb = CERT_GetDefaultCertDB(); /* If there is ever a per-context db, change this */ fd = PR_CreateIOLayerStub( tlsm_layer_id, &tlsm_PR_methods ); if ( fd ) { ctx->tc_model = SSL_ImportFD( NULL, fd ); } if ( !ctx->tc_model ) { PRErrorCode err = PR_GetError(); Debug( LDAP_DEBUG_ANY, "TLS: could perform TLS socket I/O layer initialization - error %d:%s.\n", err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ), NULL ); if ( fd ) { PR_Close( fd ); } return -1; } if ( SSL_SetPKCS11PinArg(ctx->tc_model, ctx) ) { Debug( LDAP_DEBUG_ANY, "TLS: could not set pin prompt argument\n", 0, 0, 0); return -1; } if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_SECURITY, PR_TRUE ) ) { Debug( LDAP_DEBUG_ANY, "TLS: could not set secure mode on.\n", 0, 0, 0 ); return -1; } lt = ctx->tc_config; /* default is sslv3 and tlsv1 */ if ( lt->lt_protocol_min ) { if ( lt->lt_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_SSL3 ) { sslv3 = PR_FALSE; } else if ( lt->lt_protocol_min <= LDAP_OPT_X_TLS_PROTOCOL_SSL2 ) { sslv2 = PR_TRUE; Debug( LDAP_DEBUG_ANY, "TLS: warning: minimum TLS protocol level set to " "include SSLv2 - SSLv2 is insecure - do not use\n", 0, 0, 0 ); } } if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_ENABLE_SSL2, sslv2 ) ) { Debug( LDAP_DEBUG_ANY, "TLS: could not set SSLv2 mode on.\n", 0, 0, 0 ); return -1; } if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_ENABLE_SSL3, sslv3 ) ) { Debug( LDAP_DEBUG_ANY, "TLS: could not set SSLv3 mode on.\n", 0, 0, 0 ); return -1; } if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_ENABLE_TLS, tlsv1 ) ) { Debug( LDAP_DEBUG_ANY, "TLS: could not set TLSv1 mode on.\n", 0, 0, 0 ); return -1; } if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_HANDSHAKE_AS_CLIENT, !ctx->tc_is_server ) ) { Debug( LDAP_DEBUG_ANY, "TLS: could not set handshake as client.\n", 0, 0, 0 ); return -1; } if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_HANDSHAKE_AS_SERVER, ctx->tc_is_server ) ) { Debug( LDAP_DEBUG_ANY, "TLS: could not set handshake as server.\n", 0, 0, 0 ); return -1; } if ( lt->lt_ciphersuite ) { if ( tlsm_parse_ciphers( ctx, lt->lt_ciphersuite ) ) { Debug( LDAP_DEBUG_ANY, "TLS: could not set cipher list %s.\n", lt->lt_ciphersuite, 0, 0 ); return -1; } } else if ( tlsm_parse_ciphers( ctx, "DEFAULT" ) ) { Debug( LDAP_DEBUG_ANY, "TLS: could not set cipher list DEFAULT.\n", 0, 0, 0 ); return -1; } if ( !ctx->tc_require_cert ) { ctx->tc_verify_cert = PR_FALSE; } else if ( !ctx->tc_is_server ) { request_cert = PR_TRUE; require_cert = SSL_REQUIRE_NO_ERROR; if ( ctx->tc_require_cert == LDAP_OPT_X_TLS_DEMAND || ctx->tc_require_cert == LDAP_OPT_X_TLS_HARD ) { require_cert = SSL_REQUIRE_ALWAYS; } if ( ctx->tc_require_cert != LDAP_OPT_X_TLS_ALLOW ) ctx->tc_verify_cert = PR_TRUE; } else { /* server */ /* server does not request certs by default */ /* if allow - client may send cert, server will ignore if errors */ /* if try - client may send cert, server will error if bad cert */ /* if hard or demand - client must send cert, server will error if bad cert */ request_cert = PR_TRUE; require_cert = SSL_REQUIRE_NO_ERROR; if ( ctx->tc_require_cert == LDAP_OPT_X_TLS_DEMAND || ctx->tc_require_cert == LDAP_OPT_X_TLS_HARD ) { require_cert = SSL_REQUIRE_ALWAYS; } if ( ctx->tc_require_cert != LDAP_OPT_X_TLS_ALLOW ) { ctx->tc_verify_cert = PR_TRUE; } else { ctx->tc_warn_only = PR_TRUE; } } if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_REQUEST_CERTIFICATE, request_cert ) ) { Debug( LDAP_DEBUG_ANY, "TLS: could not set request certificate mode.\n", 0, 0, 0 ); return -1; } if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_REQUIRE_CERTIFICATE, require_cert ) ) { Debug( LDAP_DEBUG_ANY, "TLS: could not set require certificate mode.\n", 0, 0, 0 ); return -1; } /* set up our cert and key, if any */ if ( lt->lt_certfile ) { /* if using the PEM module, load the PEM file specified by lt_certfile */ /* otherwise, assume this is the name of a cert already in the db */ if ( ctx->tc_using_pem ) { /* this sets ctx->tc_certificate to the correct value */ int rc = tlsm_add_cert_from_file( ctx, lt->lt_certfile, PR_FALSE ); if ( rc ) { return rc; } } else { char *tmp_certname; if ( tlsm_is_tokenname_certnick( lt->lt_certfile )) { /* assume already in form tokenname:certnickname */ tmp_certname = PL_strdup( lt->lt_certfile ); } else if ( ctx->tc_certdb_slot ) { tmp_certname = PR_smprintf( TLSM_CERTDB_DESC_FMT ":%s", ctx->tc_unique, lt->lt_certfile ); } else { tmp_certname = PR_smprintf( "%s", lt->lt_certfile ); } ctx->tc_certificate = PK11_FindCertFromNickname( tmp_certname, SSL_RevealPinArg( ctx->tc_model ) ); PR_smprintf_free( tmp_certname ); if ( !ctx->tc_certificate ) { PRErrorCode errcode = PR_GetError(); Debug( LDAP_DEBUG_ANY, "TLS: error: the certificate '%s' could not be found in the database - error %d:%s.\n", lt->lt_certfile, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) ); return -1; } } } if ( lt->lt_keyfile ) { /* if using the PEM module, load the PEM file specified by lt_keyfile */ /* otherwise, assume this is the pininfo for the key */ if ( ctx->tc_using_pem ) { int rc = tlsm_add_key_from_file( ctx, lt->lt_keyfile ); if ( rc ) { return rc; } } else { if ( ctx->tc_pin_file ) PL_strfree( ctx->tc_pin_file ); ctx->tc_pin_file = PL_strdup( lt->lt_keyfile ); } } /* Set up callbacks for use by clients */ if ( !ctx->tc_is_server ) { if ( SSL_OptionSet( ctx->tc_model, SSL_NO_CACHE, PR_TRUE ) != SECSuccess ) { PRErrorCode err = PR_GetError(); Debug( LDAP_DEBUG_ANY, "TLS: error: could not set nocache option for moznss - error %d:%s\n", err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ), NULL ); return -1; } if ( SSL_BadCertHook( ctx->tc_model, tlsm_bad_cert_handler, ctx ) != SECSuccess ) { PRErrorCode err = PR_GetError(); Debug( LDAP_DEBUG_ANY, "TLS: error: could not set bad cert handler for moznss - error %d:%s\n", err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ), NULL ); return -1; } /* since a cert has been specified, assume the client wants to do cert auth */ if ( ctx->tc_certificate ) { if ( tlsm_clientauth_init( ctx ) ) { Debug( LDAP_DEBUG_ANY, "TLS: error: unable to set up client certificate authentication using '%s'\n", tlsm_ctx_subject_name(ctx), 0, 0 ); return -1; } } } else { /* set up secure server */ SSLKEAType certKEA; SECStatus status; /* must have a certificate for the server to use */ if ( !ctx->tc_certificate ) { Debug( LDAP_DEBUG_ANY, "TLS: error: no server certificate: must specify a certificate for the server to use\n", 0, 0, 0 ); return -1; } if ( tlsm_find_and_verify_cert_key( ctx ) ) { Debug( LDAP_DEBUG_ANY, "TLS: error: unable to find and verify server's cert and key for certificate %s\n", tlsm_ctx_subject_name(ctx), 0, 0 ); return -1; } /* configure the socket to be a secure server socket */ certKEA = NSS_FindCertKEAType( ctx->tc_certificate ); status = SSL_ConfigSecureServer( ctx->tc_model, ctx->tc_certificate, ctx->tc_private_key, certKEA ); if ( SECSuccess != status ) { PRErrorCode err = PR_GetError(); Debug( LDAP_DEBUG_ANY, "TLS: error: unable to configure secure server using certificate '%s' - error %d:%s\n", tlsm_ctx_subject_name(ctx), err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ) ); return -1; } } /* Callback for authenticating certificate */ if ( SSL_AuthCertificateHook( ctx->tc_model, tlsm_auth_cert_handler, ctx ) != SECSuccess ) { PRErrorCode err = PR_GetError(); Debug( LDAP_DEBUG_ANY, "TLS: error: could not set auth cert handler for moznss - error %d:%s\n", err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ), NULL ); return -1; } if ( SSL_HandshakeCallback( ctx->tc_model, tlsm_handshake_complete_cb, ctx ) ) { PRErrorCode err = PR_GetError(); Debug( LDAP_DEBUG_ANY, "TLS: error: could not set handshake callback for moznss - error %d:%s\n", err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ), NULL ); return -1; } tlsm_free_config( ctx->tc_config ); ctx->tc_config = NULL; return 0; } struct tls_data { tlsm_session *session; Sockbuf_IO_Desc *sbiod; /* there seems to be no portable way to determine if the sockbuf sd has been set to nonblocking mode - the call to ber_pvt_socket_set_nonblock() takes place before the tls socket is set up, so we cannot intercept that call either. On systems where fcntl is available, we can just F_GETFL and test for O_NONBLOCK. On other systems, we will just see if the IO op returns EAGAIN or EWOULDBLOCK, and just set this flag */ PRBool nonblock; /* * NSS tries hard to be backwards compatible with SSLv2 clients, or * clients that send an SSLv2 client hello. This message is not * tagged in any way, so NSS has no way to know if the incoming * message is a valid SSLv2 client hello or just some bogus data * (or cleartext LDAP). We store the first byte read from the * client here. The most common case will be a client sending * LDAP data instead of SSL encrypted LDAP data. This can happen, * for example, if using ldapsearch -Z - if the starttls fails, * the client will fallback to plain cleartext LDAP. So if we * see that the firstbyte is a valid LDAP tag, we can be * pretty sure this is happening. */ ber_tag_t firsttag; /* * NSS doesn't return SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE, etc. * when it is blocked, so we have to set a flag in the wrapped send * and recv calls that tells us what operation NSS was last blocked * on */ #define TLSM_READ 1 #define TLSM_WRITE 2 int io_flag; }; static struct tls_data * tlsm_get_pvt_tls_data( PRFileDesc *fd ) { struct tls_data *p; PRFileDesc *myfd; if ( !fd ) { return NULL; } myfd = PR_GetIdentitiesLayer( fd, tlsm_layer_id ); if ( !myfd ) { return NULL; } p = (struct tls_data *)myfd->secret; return p; } static int tlsm_is_non_ssl_message( PRFileDesc *fd, ber_tag_t *thebyte ) { struct tls_data *p; if ( thebyte ) { *thebyte = LBER_DEFAULT; } p = tlsm_get_pvt_tls_data( fd ); if ( p == NULL || p->sbiod == NULL ) { return 0; } if ( p->firsttag == LBER_SEQUENCE ) { if ( thebyte ) { *thebyte = p->firsttag; } return 1; } return 0; } static tls_session * tlsm_session_new ( tls_ctx * ctx, int is_server ) { tlsm_ctx *c = (tlsm_ctx *)ctx; tlsm_session *session; PRFileDesc *fd; PRStatus status; int rc; c->tc_is_server = is_server; LDAP_MUTEX_LOCK( &tlsm_init_mutex ); status = PR_CallOnceWithArg( &c->tc_callonce, tlsm_deferred_ctx_init, c ); LDAP_MUTEX_UNLOCK( &tlsm_init_mutex ); if ( PR_SUCCESS != status ) { PRErrorCode err = PR_GetError(); Debug( LDAP_DEBUG_ANY, "TLS: error: could not initialize moznss security context - error %d:%s\n", err, PR_ErrorToString(err, PR_LANGUAGE_I_DEFAULT), NULL ); return NULL; } fd = PR_CreateIOLayerStub( tlsm_layer_id, &tlsm_PR_methods ); if ( !fd ) { return NULL; } session = SSL_ImportFD( c->tc_model, fd ); if ( !session ) { PR_DELETE( fd ); return NULL; } rc = SSL_ResetHandshake( session, is_server ); if ( rc ) { PRErrorCode err = PR_GetError(); Debug( LDAP_DEBUG_TRACE, "TLS: error: new session - reset handshake failure %d - error %d:%s\n", rc, err, err ? PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ) : "unknown" ); PR_DELETE( fd ); PR_Close( session ); session = NULL; } return (tls_session *)session; } static int tlsm_session_accept_or_connect( tls_session *session, int is_accept ) { tlsm_session *s = (tlsm_session *)session; int rc; const char *op = is_accept ? "accept" : "connect"; if ( pem_module ) { LDAP_MUTEX_LOCK( &tlsm_pem_mutex ); } rc = SSL_ForceHandshake( s ); if ( pem_module ) { LDAP_MUTEX_UNLOCK( &tlsm_pem_mutex ); } if ( rc ) { PRErrorCode err = PR_GetError(); rc = -1; if ( err == PR_WOULD_BLOCK_ERROR ) { ber_tag_t thetag = LBER_DEFAULT; /* see if we are blocked because of a bogus packet */ if ( tlsm_is_non_ssl_message( s, &thetag ) ) { /* see if we received a non-SSL message */ Debug( LDAP_DEBUG_ANY, "TLS: error: %s - error - received non-SSL message [0x%x]\n", op, (unsigned int)thetag, 0 ); /* reset error to something more descriptive */ PR_SetError( SSL_ERROR_RX_MALFORMED_HELLO_REQUEST, EPROTO ); } } else { Debug( LDAP_DEBUG_ANY, "TLS: error: %s - force handshake failure: errno %d - moznss error %d\n", op, errno, err ); } } return rc; } static int tlsm_session_accept( tls_session *session ) { return tlsm_session_accept_or_connect( session, 1 ); } static int tlsm_session_connect( LDAP *ld, tls_session *session ) { return tlsm_session_accept_or_connect( session, 0 ); } static int tlsm_session_upflags( Sockbuf *sb, tls_session *session, int rc ) { int prerror = PR_GetError(); if ( ( prerror == PR_PENDING_INTERRUPT_ERROR ) || ( prerror == PR_WOULD_BLOCK_ERROR ) ) { tlsm_session *s = (tlsm_session *)session; struct tls_data *p = tlsm_get_pvt_tls_data( s ); if ( p && ( p->io_flag == TLSM_READ ) ) { sb->sb_trans_needs_read = 1; return 1; } else if ( p && ( p->io_flag == TLSM_WRITE ) ) { sb->sb_trans_needs_write = 1; return 1; } } return 0; } static char * tlsm_session_errmsg( tls_session *sess, int rc, char *buf, size_t len ) { int i; int prerror = PR_GetError(); i = PR_GetErrorTextLength(); if ( i > len ) { char *msg = LDAP_MALLOC( i+1 ); PR_GetErrorText( msg ); memcpy( buf, msg, len ); LDAP_FREE( msg ); } else if ( i ) { PR_GetErrorText( buf ); } else if ( prerror ) { i = PR_snprintf( buf, len, "TLS error %d:%s", prerror, PR_ErrorToString( prerror, PR_LANGUAGE_I_DEFAULT ) ); } return ( i > 0 ) ? buf : NULL; } static int tlsm_session_my_dn( tls_session *session, struct berval *der_dn ) { tlsm_session *s = (tlsm_session *)session; CERTCertificate *cert; cert = SSL_LocalCertificate( s ); if (!cert) return LDAP_INVALID_CREDENTIALS; der_dn->bv_val = (char *)cert->derSubject.data; der_dn->bv_len = cert->derSubject.len; CERT_DestroyCertificate( cert ); return 0; } static int tlsm_session_peer_dn( tls_session *session, struct berval *der_dn ) { tlsm_session *s = (tlsm_session *)session; CERTCertificate *cert; cert = SSL_PeerCertificate( s ); if (!cert) return LDAP_INVALID_CREDENTIALS; der_dn->bv_val = (char *)cert->derSubject.data; der_dn->bv_len = cert->derSubject.len; CERT_DestroyCertificate( cert ); return 0; } /* what kind of hostname were we given? */ #define IS_DNS 0 #define IS_IP4 1 #define IS_IP6 2 static int tlsm_session_chkhost( LDAP *ld, tls_session *session, const char *name_in ) { tlsm_session *s = (tlsm_session *)session; CERTCertificate *cert; const char *name, *domain = NULL, *ptr; int ret, ntype = IS_DNS, nlen, dlen; #ifdef LDAP_PF_INET6 struct in6_addr addr; #else struct in_addr addr; #endif SECItem altname; SECStatus rv; if( ldap_int_hostname && ( !name_in || !strcasecmp( name_in, "localhost" ) ) ) { name = ldap_int_hostname; } else { name = name_in; } nlen = strlen( name ); cert = SSL_PeerCertificate( s ); if (!cert) { Debug( LDAP_DEBUG_ANY, "TLS: unable to get peer certificate.\n", 0, 0, 0 ); /* if this was a fatal condition, things would have * aborted long before now. */ return LDAP_SUCCESS; } #ifdef LDAP_PF_INET6 if (inet_pton(AF_INET6, name, &addr)) { ntype = IS_IP6; } else #endif if ((ptr = strrchr(name, '.')) && isdigit((unsigned char)ptr[1])) { if (inet_aton(name, (struct in_addr *)&addr)) ntype = IS_IP4; } if (ntype == IS_DNS ) { domain = strchr( name, '.' ); if ( domain ) dlen = nlen - ( domain - name ); } ret = LDAP_LOCAL_ERROR; rv = CERT_FindCertExtension( cert, SEC_OID_X509_SUBJECT_ALT_NAME, &altname ); if ( rv == SECSuccess && altname.data ) { PRArenaPool *arena; CERTGeneralName *names, *cur; arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if ( !arena ) { ret = LDAP_NO_MEMORY; goto fail; } names = cur = CERT_DecodeAltNameExtension(arena, &altname); if ( !cur ) goto altfail; do { char *host; int hlen; /* ignore empty */ if ( !cur->name.other.len ) continue; host = (char *)cur->name.other.data; hlen = cur->name.other.len; if ( cur->type == certDNSName ) { if ( ntype != IS_DNS ) continue; /* is this an exact match? */ if ( nlen == hlen && !strncasecmp( name, host, nlen )) { ret = LDAP_SUCCESS; break; } /* is this a wildcard match? */ if ( domain && host[0] == '*' && host[1] == '.' && dlen == hlen-1 && !strncasecmp( domain, host+1, dlen )) { ret = LDAP_SUCCESS; break; } } else if ( cur->type == certIPAddress ) { if ( ntype == IS_DNS ) continue; #ifdef LDAP_PF_INET6 if (ntype == IS_IP6 && hlen != sizeof(struct in6_addr)) { continue; } else #endif if (ntype == IS_IP4 && hlen != sizeof(struct in_addr)) { continue; } if (!memcmp(host, &addr, hlen)) { ret = LDAP_SUCCESS; break; } } } while (( cur = CERT_GetNextGeneralName( cur )) != names ); altfail: PORT_FreeArena( arena, PR_FALSE ); SECITEM_FreeItem( &altname, PR_FALSE ); } /* no altnames matched, try the CN */ if ( ret != LDAP_SUCCESS ) { /* find the last CN */ CERTRDN *rdn, **rdns; CERTAVA *lastava = NULL; char buf[2048]; buf[0] = '\0'; rdns = cert->subject.rdns; while ( rdns && ( rdn = *rdns++ )) { CERTAVA *ava, **avas = rdn->avas; while ( avas && ( ava = *avas++ )) { if ( CERT_GetAVATag( ava ) == SEC_OID_AVA_COMMON_NAME ) lastava = ava; } } if ( lastava ) { SECItem *av = CERT_DecodeAVAValue( &lastava->value ); if ( av ) { if ( av->len == nlen && !strncasecmp( name, (char *)av->data, nlen )) { ret = LDAP_SUCCESS; } else if ( av->data[0] == '*' && av->data[1] == '.' && domain && dlen == av->len - 1 && !strncasecmp( domain, (char *)(av->data+1), dlen )) { ret = LDAP_SUCCESS; } else { int len = av->len; if ( len >= sizeof(buf) ) len = sizeof(buf)-1; memcpy( buf, av->data, len ); buf[len] = '\0'; } SECITEM_FreeItem( av, PR_TRUE ); } } if ( ret != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "TLS: hostname (%s) does not match " "common name in certificate (%s).\n", name, buf, 0 ); ret = LDAP_CONNECT_ERROR; if ( ld->ld_error ) { LDAP_FREE( ld->ld_error ); } ld->ld_error = LDAP_STRDUP( _("TLS: hostname does not match CN in peer certificate")); } } fail: CERT_DestroyCertificate( cert ); return ret; } static int tlsm_session_strength( tls_session *session ) { tlsm_session *s = (tlsm_session *)session; int rc, keySize; rc = SSL_SecurityStatus( s, NULL, NULL, NULL, &keySize, NULL, NULL ); return rc ? 0 : keySize; } /* * TLS support for LBER Sockbufs */ static PRStatus PR_CALLBACK tlsm_PR_Close(PRFileDesc *fd) { int rc = PR_SUCCESS; /* we don't need to actually close anything here, just pop our io layer off the stack */ fd->secret = NULL; /* must have been freed before calling PR_Close */ if ( fd->lower ) { fd = PR_PopIOLayer( fd, tlsm_layer_id ); /* if we are not the last layer, pass the close along */ if ( fd ) { if ( fd->dtor ) { fd->dtor( fd ); } rc = fd->methods->close( fd ); } } else { /* we are the last layer - just call our dtor */ fd->dtor(fd); } return rc; } static PRStatus PR_CALLBACK tlsm_PR_Shutdown(PRFileDesc *fd, PRShutdownHow how) { int rc = PR_SUCCESS; if ( fd->lower ) { rc = PR_Shutdown( fd->lower, how ); } return rc; } static int PR_CALLBACK tlsm_PR_Recv(PRFileDesc *fd, void *buf, PRInt32 len, PRIntn flags, PRIntervalTime timeout) { struct tls_data *p; int rc; if ( buf == NULL || len <= 0 ) return 0; p = tlsm_get_pvt_tls_data( fd ); if ( p == NULL || p->sbiod == NULL ) { return 0; } rc = LBER_SBIOD_READ_NEXT( p->sbiod, buf, len ); if (rc <= 0) { tlsm_map_error( errno ); if ( errno == EAGAIN || errno == EWOULDBLOCK ) { p->nonblock = PR_TRUE; /* fd is using non-blocking io */ } else if ( errno ) { /* real error */ Debug( LDAP_DEBUG_TRACE, "TLS: error: tlsm_PR_Recv returned %d - error %d:%s\n", rc, errno, STRERROR(errno) ); } } else if ( ( rc > 0 ) && ( len > 0 ) && ( p->firsttag == LBER_DEFAULT ) ) { p->firsttag = (ber_tag_t)*((char *)buf); } p->io_flag = TLSM_READ; return rc; } static int PR_CALLBACK tlsm_PR_Send(PRFileDesc *fd, const void *buf, PRInt32 len, PRIntn flags, PRIntervalTime timeout) { struct tls_data *p; int rc; if ( buf == NULL || len <= 0 ) return 0; p = tlsm_get_pvt_tls_data( fd ); if ( p == NULL || p->sbiod == NULL ) { return 0; } rc = LBER_SBIOD_WRITE_NEXT( p->sbiod, (char *)buf, len ); if (rc <= 0) { tlsm_map_error( errno ); if ( errno == EAGAIN || errno == EWOULDBLOCK ) { p->nonblock = PR_TRUE; } else if ( errno ) { /* real error */ Debug( LDAP_DEBUG_TRACE, "TLS: error: tlsm_PR_Send returned %d - error %d:%s\n", rc, errno, STRERROR(errno) ); } } p->io_flag = TLSM_WRITE; return rc; } static int PR_CALLBACK tlsm_PR_Read(PRFileDesc *fd, void *buf, PRInt32 len) { return tlsm_PR_Recv( fd, buf, len, 0, PR_INTERVAL_NO_TIMEOUT ); } static int PR_CALLBACK tlsm_PR_Write(PRFileDesc *fd, const void *buf, PRInt32 len) { return tlsm_PR_Send( fd, buf, len, 0, PR_INTERVAL_NO_TIMEOUT ); } static PRStatus PR_CALLBACK tlsm_PR_GetPeerName(PRFileDesc *fd, PRNetAddr *addr) { struct tls_data *p; ber_socklen_t len; p = tlsm_get_pvt_tls_data( fd ); if ( p == NULL || p->sbiod == NULL ) { return PR_FAILURE; } len = sizeof(PRNetAddr); return getpeername( p->sbiod->sbiod_sb->sb_fd, (struct sockaddr *)addr, &len ); } static PRStatus PR_CALLBACK tlsm_PR_GetSocketOption(PRFileDesc *fd, PRSocketOptionData *data) { struct tls_data *p; p = tlsm_get_pvt_tls_data( fd ); if ( p == NULL || data == NULL ) { return PR_FAILURE; } /* only the nonblocking option is supported at this time MozNSS SSL code needs it */ if ( data->option != PR_SockOpt_Nonblocking ) { PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return PR_FAILURE; } #ifdef HAVE_FCNTL int flags = fcntl( p->sbiod->sbiod_sb->sb_fd, F_GETFL ); data->value.non_blocking = (flags & O_NONBLOCK) ? PR_TRUE : PR_FALSE; #else /* punt :P */ data->value.non_blocking = p->nonblock; #endif return PR_SUCCESS; } static PRStatus PR_CALLBACK tlsm_PR_prs_unimp() { PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return PR_FAILURE; } static PRFileDesc * PR_CALLBACK tlsm_PR_pfd_unimp() { PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return NULL; } static PRInt16 PR_CALLBACK tlsm_PR_i16_unimp() { PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return SECFailure; } static PRInt32 PR_CALLBACK tlsm_PR_i32_unimp() { PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return SECFailure; } static PRInt64 PR_CALLBACK tlsm_PR_i64_unimp() { PRInt64 res; PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); LL_I2L(res, -1L); return res; } static const PRIOMethods tlsm_PR_methods = { PR_DESC_LAYERED, tlsm_PR_Close, /* close */ tlsm_PR_Read, /* read */ tlsm_PR_Write, /* write */ tlsm_PR_i32_unimp, /* available */ tlsm_PR_i64_unimp, /* available64 */ tlsm_PR_prs_unimp, /* fsync */ tlsm_PR_i32_unimp, /* seek */ tlsm_PR_i64_unimp, /* seek64 */ tlsm_PR_prs_unimp, /* fileInfo */ tlsm_PR_prs_unimp, /* fileInfo64 */ tlsm_PR_i32_unimp, /* writev */ tlsm_PR_prs_unimp, /* connect */ tlsm_PR_pfd_unimp, /* accept */ tlsm_PR_prs_unimp, /* bind */ tlsm_PR_prs_unimp, /* listen */ (PRShutdownFN)tlsm_PR_Shutdown, /* shutdown */ tlsm_PR_Recv, /* recv */ tlsm_PR_Send, /* send */ tlsm_PR_i32_unimp, /* recvfrom */ tlsm_PR_i32_unimp, /* sendto */ (PRPollFN)tlsm_PR_i16_unimp, /* poll */ tlsm_PR_i32_unimp, /* acceptread */ tlsm_PR_i32_unimp, /* transmitfile */ tlsm_PR_prs_unimp, /* getsockname */ tlsm_PR_GetPeerName, /* getpeername */ tlsm_PR_i32_unimp, /* getsockopt OBSOLETE */ tlsm_PR_i32_unimp, /* setsockopt OBSOLETE */ tlsm_PR_GetSocketOption, /* getsocketoption */ tlsm_PR_i32_unimp, /* setsocketoption */ tlsm_PR_i32_unimp, /* Send a (partial) file with header/trailer*/ (PRConnectcontinueFN)tlsm_PR_prs_unimp, /* connectcontinue */ tlsm_PR_i32_unimp, /* reserved for future use */ tlsm_PR_i32_unimp, /* reserved for future use */ tlsm_PR_i32_unimp, /* reserved for future use */ tlsm_PR_i32_unimp /* reserved for future use */ }; /* * Initialize TLS subsystem. Should be called only once. * See tlsm_deferred_init for the bulk of the init process */ static int tlsm_init( void ) { char *nofork = PR_GetEnv( "NSS_STRICT_NOFORK" ); PR_Init(0, 0, 0); tlsm_layer_id = PR_GetUniqueIdentity( "OpenLDAP" ); /* * There are some applications that acquire a crypto context in the parent process * and expect that crypto context to work after a fork(). This does not work * with NSS using strict PKCS11 compliance mode. We set this environment * variable here to tell the software encryption module/token to allow crypto * contexts to persist across a fork(). However, if you are using some other * module or encryption device that supports and expects full PKCS11 semantics, * the only recourse is to rewrite the application with atfork() handlers to save * the crypto context in the parent and restore (and SECMOD_RestartModules) the * context in the child. */ if ( !nofork ) { /* will leak one time */ char *noforkenvvar = PL_strdup( "NSS_STRICT_NOFORK=DISABLED" ); PR_SetEnv( noforkenvvar ); } return 0; } static int tlsm_sb_setup( Sockbuf_IO_Desc *sbiod, void *arg ) { struct tls_data *p; tlsm_session *session = arg; PRFileDesc *fd; assert( sbiod != NULL ); p = LBER_MALLOC( sizeof( *p ) ); if ( p == NULL ) { return -1; } fd = PR_GetIdentitiesLayer( session, tlsm_layer_id ); if ( !fd ) { LBER_FREE( p ); return -1; } fd->secret = (PRFilePrivate *)p; p->session = session; p->sbiod = sbiod; p->firsttag = LBER_DEFAULT; sbiod->sbiod_pvt = p; return 0; } static int tlsm_sb_remove( Sockbuf_IO_Desc *sbiod ) { struct tls_data *p; assert( sbiod != NULL ); assert( sbiod->sbiod_pvt != NULL ); p = (struct tls_data *)sbiod->sbiod_pvt; PR_Close( p->session ); LBER_FREE( sbiod->sbiod_pvt ); sbiod->sbiod_pvt = NULL; return 0; } static int tlsm_sb_close( Sockbuf_IO_Desc *sbiod ) { struct tls_data *p; assert( sbiod != NULL ); assert( sbiod->sbiod_pvt != NULL ); p = (struct tls_data *)sbiod->sbiod_pvt; PR_Shutdown( p->session, PR_SHUTDOWN_BOTH ); return 0; } static int tlsm_sb_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) { struct tls_data *p; assert( sbiod != NULL ); assert( sbiod->sbiod_pvt != NULL ); p = (struct tls_data *)sbiod->sbiod_pvt; if ( opt == LBER_SB_OPT_GET_SSL ) { *((tlsm_session **)arg) = p->session; return 1; } else if ( opt == LBER_SB_OPT_DATA_READY ) { if ( p && ( SSL_DataPending( p->session ) > 0 ) ) { return 1; } } return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg ); } static ber_slen_t tlsm_sb_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) { struct tls_data *p; ber_slen_t ret; int err; assert( sbiod != NULL ); assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); p = (struct tls_data *)sbiod->sbiod_pvt; ret = PR_Recv( p->session, buf, len, 0, PR_INTERVAL_NO_TIMEOUT ); if ( ret < 0 ) { err = PR_GetError(); if ( err == PR_PENDING_INTERRUPT_ERROR || err == PR_WOULD_BLOCK_ERROR ) { sbiod->sbiod_sb->sb_trans_needs_read = 1; sock_errset(EWOULDBLOCK); } } else { sbiod->sbiod_sb->sb_trans_needs_read = 0; } return ret; } static ber_slen_t tlsm_sb_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) { struct tls_data *p; ber_slen_t ret; int err; assert( sbiod != NULL ); assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); p = (struct tls_data *)sbiod->sbiod_pvt; ret = PR_Send( p->session, (char *)buf, len, 0, PR_INTERVAL_NO_TIMEOUT ); if ( ret < 0 ) { err = PR_GetError(); if ( err == PR_PENDING_INTERRUPT_ERROR || err == PR_WOULD_BLOCK_ERROR ) { sbiod->sbiod_sb->sb_trans_needs_write = 1; sock_errset(EWOULDBLOCK); ret = 0; } } else { sbiod->sbiod_sb->sb_trans_needs_write = 0; } return ret; } static Sockbuf_IO tlsm_sbio = { tlsm_sb_setup, /* sbi_setup */ tlsm_sb_remove, /* sbi_remove */ tlsm_sb_ctrl, /* sbi_ctrl */ tlsm_sb_read, /* sbi_read */ tlsm_sb_write, /* sbi_write */ tlsm_sb_close /* sbi_close */ }; tls_impl ldap_int_tls_impl = { "MozNSS", tlsm_init, tlsm_destroy, tlsm_ctx_new, tlsm_ctx_ref, tlsm_ctx_free, tlsm_ctx_init, tlsm_session_new, tlsm_session_connect, tlsm_session_accept, tlsm_session_upflags, tlsm_session_errmsg, tlsm_session_my_dn, tlsm_session_peer_dn, tlsm_session_chkhost, tlsm_session_strength, &tlsm_sbio, #ifdef LDAP_R_COMPILE tlsm_thr_init, #else NULL, #endif 0 }; #endif /* HAVE_MOZNSS */ /* emacs settings Local Variables: indent-tabs-mode: t tab-width: 4 End: */ openldap-2.4.42+dfsg/libraries/libldap/unbind.c0000644000175000017500000001555112563404150020045 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (c) 1990 Regents of the University of Michigan. * All rights reserved. */ #include "portable.h" #include #include #include #include #include #include "ldap-int.h" /* An Unbind Request looks like this: * * UnbindRequest ::= [APPLICATION 2] NULL * * and has no response. (Source: RFC 4511) */ int ldap_unbind_ext( LDAP *ld, LDAPControl **sctrls, LDAPControl **cctrls ) { int rc; assert( ld != NULL ); assert( LDAP_VALID( ld ) ); /* check client controls */ rc = ldap_int_client_controls( ld, cctrls ); if( rc != LDAP_SUCCESS ) return rc; return ldap_ld_free( ld, 1, sctrls, cctrls ); } int ldap_unbind_ext_s( LDAP *ld, LDAPControl **sctrls, LDAPControl **cctrls ) { return ldap_unbind_ext( ld, sctrls, cctrls ); } int ldap_unbind( LDAP *ld ) { Debug( LDAP_DEBUG_TRACE, "ldap_unbind\n", 0, 0, 0 ); return( ldap_unbind_ext( ld, NULL, NULL ) ); } int ldap_ld_free( LDAP *ld, int close, LDAPControl **sctrls, LDAPControl **cctrls ) { LDAPMessage *lm, *next; int err = LDAP_SUCCESS; LDAP_MUTEX_LOCK( &ld->ld_ldcmutex ); /* Someone else is still using this ld. */ if (ld->ld_ldcrefcnt > 1) { /* but not last thread */ /* clean up self only */ ld->ld_ldcrefcnt--; if ( ld->ld_error != NULL ) { LDAP_FREE( ld->ld_error ); ld->ld_error = NULL; } if ( ld->ld_matched != NULL ) { LDAP_FREE( ld->ld_matched ); ld->ld_matched = NULL; } if ( ld->ld_referrals != NULL) { LDAP_VFREE(ld->ld_referrals); ld->ld_referrals = NULL; } LDAP_MUTEX_UNLOCK( &ld->ld_ldcmutex ); LDAP_FREE( (char *) ld ); return( err ); } /* This ld is the last thread. */ LDAP_MUTEX_UNLOCK( &ld->ld_ldcmutex ); /* free LDAP structure and outstanding requests/responses */ LDAP_MUTEX_LOCK( &ld->ld_req_mutex ); while ( ld->ld_requests != NULL ) { ldap_free_request( ld, ld->ld_requests ); } LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex ); LDAP_MUTEX_LOCK( &ld->ld_conn_mutex ); /* free and unbind from all open connections */ while ( ld->ld_conns != NULL ) { ldap_free_connection( ld, ld->ld_conns, 1, close ); } LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); LDAP_MUTEX_LOCK( &ld->ld_res_mutex ); for ( lm = ld->ld_responses; lm != NULL; lm = next ) { next = lm->lm_next; ldap_msgfree( lm ); } if ( ld->ld_abandoned != NULL ) { LDAP_FREE( ld->ld_abandoned ); ld->ld_abandoned = NULL; } LDAP_MUTEX_UNLOCK( &ld->ld_res_mutex ); ber_sockbuf_free( ld->ld_sb ); LDAP_MUTEX_LOCK( &ld->ld_ldopts_mutex ); /* final close callbacks */ { ldaplist *ll, *next; for ( ll = ld->ld_options.ldo_conn_cbs; ll; ll = next ) { ldap_conncb *cb = ll->ll_data; next = ll->ll_next; cb->lc_del( ld, NULL, cb ); LDAP_FREE( ll ); } } if ( ld->ld_error != NULL ) { LDAP_FREE( ld->ld_error ); ld->ld_error = NULL; } if ( ld->ld_matched != NULL ) { LDAP_FREE( ld->ld_matched ); ld->ld_matched = NULL; } if ( ld->ld_referrals != NULL) { LDAP_VFREE(ld->ld_referrals); ld->ld_referrals = NULL; } if ( ld->ld_selectinfo != NULL ) { ldap_free_select_info( ld->ld_selectinfo ); ld->ld_selectinfo = NULL; } if ( ld->ld_options.ldo_defludp != NULL ) { ldap_free_urllist( ld->ld_options.ldo_defludp ); ld->ld_options.ldo_defludp = NULL; } #ifdef LDAP_CONNECTIONLESS if ( ld->ld_options.ldo_peer != NULL ) { LDAP_FREE( ld->ld_options.ldo_peer ); ld->ld_options.ldo_peer = NULL; } if ( ld->ld_options.ldo_cldapdn != NULL ) { LDAP_FREE( ld->ld_options.ldo_cldapdn ); ld->ld_options.ldo_cldapdn = NULL; } #endif #ifdef HAVE_CYRUS_SASL if ( ld->ld_options.ldo_def_sasl_mech != NULL ) { LDAP_FREE( ld->ld_options.ldo_def_sasl_mech ); ld->ld_options.ldo_def_sasl_mech = NULL; } if ( ld->ld_options.ldo_def_sasl_realm != NULL ) { LDAP_FREE( ld->ld_options.ldo_def_sasl_realm ); ld->ld_options.ldo_def_sasl_realm = NULL; } if ( ld->ld_options.ldo_def_sasl_authcid != NULL ) { LDAP_FREE( ld->ld_options.ldo_def_sasl_authcid ); ld->ld_options.ldo_def_sasl_authcid = NULL; } if ( ld->ld_options.ldo_def_sasl_authzid != NULL ) { LDAP_FREE( ld->ld_options.ldo_def_sasl_authzid ); ld->ld_options.ldo_def_sasl_authzid = NULL; } #endif #ifdef HAVE_TLS ldap_int_tls_destroy( &ld->ld_options ); #endif if ( ld->ld_options.ldo_sctrls != NULL ) { ldap_controls_free( ld->ld_options.ldo_sctrls ); ld->ld_options.ldo_sctrls = NULL; } if ( ld->ld_options.ldo_cctrls != NULL ) { ldap_controls_free( ld->ld_options.ldo_cctrls ); ld->ld_options.ldo_cctrls = NULL; } LDAP_MUTEX_UNLOCK( &ld->ld_ldopts_mutex ); #ifdef LDAP_R_COMPILE ldap_pvt_thread_mutex_destroy( &ld->ld_msgid_mutex ); ldap_pvt_thread_mutex_destroy( &ld->ld_conn_mutex ); ldap_pvt_thread_mutex_destroy( &ld->ld_req_mutex ); ldap_pvt_thread_mutex_destroy( &ld->ld_res_mutex ); ldap_pvt_thread_mutex_destroy( &ld->ld_abandon_mutex ); ldap_pvt_thread_mutex_destroy( &ld->ld_ldopts_mutex ); ldap_pvt_thread_mutex_destroy( &ld->ld_ldcmutex ); #endif #ifndef NDEBUG LDAP_TRASH(ld); #endif LDAP_FREE( (char *) ld->ldc ); LDAP_FREE( (char *) ld ); return( err ); } int ldap_destroy( LDAP *ld ) { return ( ldap_ld_free( ld, 1, NULL, NULL ) ); } int ldap_unbind_s( LDAP *ld ) { return( ldap_unbind_ext( ld, NULL, NULL ) ); } /* FIXME: this function is called only by ldap_free_connection(), * which, most of the times, is called with ld_req_mutex locked */ int ldap_send_unbind( LDAP *ld, Sockbuf *sb, LDAPControl **sctrls, LDAPControl **cctrls ) { BerElement *ber; ber_int_t id; Debug( LDAP_DEBUG_TRACE, "ldap_send_unbind\n", 0, 0, 0 ); #ifdef LDAP_CONNECTIONLESS if (LDAP_IS_UDP(ld)) return LDAP_SUCCESS; #endif /* create a message to send */ if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) { return( ld->ld_errno ); } LDAP_NEXT_MSGID(ld, id); /* fill it in */ if ( ber_printf( ber, "{itn" /*}*/, id, LDAP_REQ_UNBIND ) == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( ld->ld_errno ); } /* Put Server Controls */ if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) { ber_free( ber, 1 ); return ld->ld_errno; } if ( ber_printf( ber, /*{*/ "N}", LDAP_REQ_UNBIND ) == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( ld->ld_errno ); } ld->ld_errno = LDAP_SUCCESS; /* send the message */ if ( ber_flush2( sb, ber, LBER_FLUSH_FREE_ALWAYS ) == -1 ) { ld->ld_errno = LDAP_SERVER_DOWN; } return( ld->ld_errno ); } openldap-2.4.42+dfsg/libraries/libldap/ldap_sync.c0000644000175000017500000004637412563404150020551 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 2006-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* ACKNOWLEDGEMENTS: * This program was originally developed by Pierangelo Masarati * for inclusion in OpenLDAP Software. */ /* * Proof-of-concept API that implement the client-side * of the "LDAP Content Sync Operation" (RFC 4533) */ #include "portable.h" #include #include "ldap-int.h" #ifdef LDAP_SYNC_TRACE static const char * ldap_sync_state2str( int state ) { switch ( state ) { case LDAP_SYNC_PRESENT: return "LDAP_SYNC_PRESENT"; case LDAP_SYNC_ADD: return "LDAP_SYNC_ADD"; case LDAP_SYNC_MODIFY: return "LDAP_SYNC_MODIFY"; case LDAP_SYNC_DELETE: return "LDAP_SYNC_DELETE"; default: return "(unknown)"; } } #endif /* * initialize the persistent search structure */ ldap_sync_t * ldap_sync_initialize( ldap_sync_t *ls_in ) { ldap_sync_t *ls = ls_in; if ( ls == NULL ) { ls = ldap_memalloc( sizeof( ldap_sync_t ) ); if ( ls == NULL ) { return NULL; } } memset( ls, 0, sizeof( ldap_sync_t ) ); ls->ls_scope = LDAP_SCOPE_SUBTREE; ls->ls_timeout = -1; return ls; } /* * destroy the persistent search structure */ void ldap_sync_destroy( ldap_sync_t *ls, int freeit ) { assert( ls != NULL ); if ( ls->ls_base != NULL ) { ldap_memfree( ls->ls_base ); ls->ls_base = NULL; } if ( ls->ls_filter != NULL ) { ldap_memfree( ls->ls_filter ); ls->ls_filter = NULL; } if ( ls->ls_attrs != NULL ) { int i; for ( i = 0; ls->ls_attrs[ i ] != NULL; i++ ) { ldap_memfree( ls->ls_attrs[ i ] ); } ldap_memfree( ls->ls_attrs ); ls->ls_attrs = NULL; } if ( ls->ls_ld != NULL ) { (void)ldap_unbind_ext( ls->ls_ld, NULL, NULL ); #ifdef LDAP_SYNC_TRACE fprintf( stderr, "ldap_unbind_ext()\n" ); #endif /* LDAP_SYNC_TRACE */ ls->ls_ld = NULL; } if ( ls->ls_cookie.bv_val != NULL ) { ldap_memfree( ls->ls_cookie.bv_val ); ls->ls_cookie.bv_val = NULL; } if ( freeit ) { ldap_memfree( ls ); } } /* * handle the LDAP_RES_SEARCH_ENTRY response */ static int ldap_sync_search_entry( ldap_sync_t *ls, LDAPMessage *res ) { LDAPControl **ctrls = NULL; int rc = LDAP_OTHER, i; BerElement *ber = NULL; struct berval entryUUID = { 0 }, cookie = { 0 }; int state = -1; ber_len_t len; ldap_sync_refresh_t phase; #ifdef LDAP_SYNC_TRACE fprintf( stderr, "\tgot LDAP_RES_SEARCH_ENTRY\n" ); #endif /* LDAP_SYNC_TRACE */ assert( ls != NULL ); assert( res != NULL ); phase = ls->ls_refreshPhase; /* OK */ /* extract: * - data * - entryUUID * * check that: * - Sync State Control is "add" */ /* the control MUST be present */ /* extract controls */ ldap_get_entry_controls( ls->ls_ld, res, &ctrls ); if ( ctrls == NULL ) { goto done; } /* lookup the sync state control */ for ( i = 0; ctrls[ i ] != NULL; i++ ) { if ( strcmp( ctrls[ i ]->ldctl_oid, LDAP_CONTROL_SYNC_STATE ) == 0 ) { break; } } /* control must be present; there might be other... */ if ( ctrls[ i ] == NULL ) { goto done; } /* extract data */ ber = ber_init( &ctrls[ i ]->ldctl_value ); if ( ber == NULL ) { goto done; } /* scan entryUUID in-place ("m") */ if ( ber_scanf( ber, "{em" /*"}"*/, &state, &entryUUID ) == LBER_ERROR || entryUUID.bv_len == 0 ) { goto done; } if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SYNC_COOKIE ) { /* scan cookie in-place ("m") */ if ( ber_scanf( ber, /*"{"*/ "m}", &cookie ) == LBER_ERROR ) { goto done; } if ( cookie.bv_val != NULL ) { ber_bvreplace( &ls->ls_cookie, &cookie ); } #ifdef LDAP_SYNC_TRACE fprintf( stderr, "\t\tgot cookie=%s\n", cookie.bv_val ? cookie.bv_val : "(null)" ); #endif /* LDAP_SYNC_TRACE */ } switch ( state ) { case LDAP_SYNC_PRESENT: case LDAP_SYNC_DELETE: case LDAP_SYNC_ADD: case LDAP_SYNC_MODIFY: /* NOTE: ldap_sync_refresh_t is defined * as the corresponding LDAP_SYNC_* * for the 4 above cases */ phase = state; #ifdef LDAP_SYNC_TRACE fprintf( stderr, "\t\tgot syncState=%s\n", ldap_sync_state2str( state ) ); #endif /* LDAP_SYNC_TRACE */ break; default: #ifdef LDAP_SYNC_TRACE fprintf( stderr, "\t\tgot unknown syncState=%d\n", state ); #endif /* LDAP_SYNC_TRACE */ goto done; } rc = ls->ls_search_entry ? ls->ls_search_entry( ls, res, &entryUUID, phase ) : LDAP_SUCCESS; done:; if ( ber != NULL ) { ber_free( ber, 1 ); } if ( ctrls != NULL ) { ldap_controls_free( ctrls ); } return rc; } /* * handle the LDAP_RES_SEARCH_REFERENCE response * (to be implemented yet) */ static int ldap_sync_search_reference( ldap_sync_t *ls, LDAPMessage *res ) { int rc = 0; #ifdef LDAP_SYNC_TRACE fprintf( stderr, "\tgot LDAP_RES_SEARCH_REFERENCE\n" ); #endif /* LDAP_SYNC_TRACE */ assert( ls != NULL ); assert( res != NULL ); if ( ls->ls_search_reference ) { rc = ls->ls_search_reference( ls, res ); } return rc; } /* * handle the LDAP_RES_SEARCH_RESULT response */ static int ldap_sync_search_result( ldap_sync_t *ls, LDAPMessage *res ) { int err; char *matched = NULL, *msg = NULL; LDAPControl **ctrls = NULL; int rc; int refreshDeletes = -1; #ifdef LDAP_SYNC_TRACE fprintf( stderr, "\tgot LDAP_RES_SEARCH_RESULT\n" ); #endif /* LDAP_SYNC_TRACE */ assert( ls != NULL ); assert( res != NULL ); /* should not happen in refreshAndPersist... */ rc = ldap_parse_result( ls->ls_ld, res, &err, &matched, &msg, NULL, &ctrls, 0 ); #ifdef LDAP_SYNC_TRACE fprintf( stderr, "\tldap_parse_result(%d, \"%s\", \"%s\") == %d\n", err, matched ? matched : "", msg ? msg : "", rc ); #endif /* LDAP_SYNC_TRACE */ if ( rc == LDAP_SUCCESS ) { rc = err; } ls->ls_refreshPhase = LDAP_SYNC_CAPI_DONE; switch ( rc ) { case LDAP_SUCCESS: { int i; BerElement *ber = NULL; ber_len_t len; struct berval cookie = { 0 }; rc = LDAP_OTHER; /* deal with control; then fallthru to handler */ if ( ctrls == NULL ) { goto done; } /* lookup the sync state control */ for ( i = 0; ctrls[ i ] != NULL; i++ ) { if ( strcmp( ctrls[ i ]->ldctl_oid, LDAP_CONTROL_SYNC_DONE ) == 0 ) { break; } } /* control must be present; there might be other... */ if ( ctrls[ i ] == NULL ) { goto done; } /* extract data */ ber = ber_init( &ctrls[ i ]->ldctl_value ); if ( ber == NULL ) { goto done; } if ( ber_scanf( ber, "{" /*"}"*/) == LBER_ERROR ) { goto ber_done; } if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SYNC_COOKIE ) { if ( ber_scanf( ber, "m", &cookie ) == LBER_ERROR ) { goto ber_done; } if ( cookie.bv_val != NULL ) { ber_bvreplace( &ls->ls_cookie, &cookie ); } #ifdef LDAP_SYNC_TRACE fprintf( stderr, "\t\tgot cookie=%s\n", cookie.bv_val ? cookie.bv_val : "(null)" ); #endif /* LDAP_SYNC_TRACE */ } refreshDeletes = 0; if ( ber_peek_tag( ber, &len ) == LDAP_TAG_REFRESHDELETES ) { if ( ber_scanf( ber, "b", &refreshDeletes ) == LBER_ERROR ) { goto ber_done; } if ( refreshDeletes ) { refreshDeletes = 1; } } if ( ber_scanf( ber, /*"{"*/ "}" ) != LBER_ERROR ) { rc = LDAP_SUCCESS; } ber_done:; ber_free( ber, 1 ); if ( rc != LDAP_SUCCESS ) { break; } #ifdef LDAP_SYNC_TRACE fprintf( stderr, "\t\tgot refreshDeletes=%s\n", refreshDeletes ? "TRUE" : "FALSE" ); #endif /* LDAP_SYNC_TRACE */ /* FIXME: what should we do with the refreshDelete? */ switch ( refreshDeletes ) { case 0: ls->ls_refreshPhase = LDAP_SYNC_CAPI_PRESENTS; break; default: ls->ls_refreshPhase = LDAP_SYNC_CAPI_DELETES; break; } } /* fallthru */ case LDAP_SYNC_REFRESH_REQUIRED: /* TODO: check for Sync Done Control */ /* FIXME: perhaps the handler should be called * also in case of failure; we'll deal with this * later when implementing refreshOnly */ if ( ls->ls_search_result ) { err = ls->ls_search_result( ls, res, refreshDeletes ); } break; } done:; if ( matched != NULL ) { ldap_memfree( matched ); } if ( msg != NULL ) { ldap_memfree( msg ); } if ( ctrls != NULL ) { ldap_controls_free( ctrls ); } ls->ls_refreshPhase = LDAP_SYNC_CAPI_DONE; return rc; } /* * handle the LDAP_RES_INTERMEDIATE response */ static int ldap_sync_search_intermediate( ldap_sync_t *ls, LDAPMessage *res, int *refreshDone ) { int rc; char *retoid = NULL; struct berval *retdata = NULL; BerElement *ber = NULL; ber_len_t len; ber_tag_t syncinfo_tag; struct berval cookie; int refreshDeletes = 0; BerVarray syncUUIDs = NULL; ldap_sync_refresh_t phase; #ifdef LDAP_SYNC_TRACE fprintf( stderr, "\tgot LDAP_RES_INTERMEDIATE\n" ); #endif /* LDAP_SYNC_TRACE */ assert( ls != NULL ); assert( res != NULL ); assert( refreshDone != NULL ); *refreshDone = 0; rc = ldap_parse_intermediate( ls->ls_ld, res, &retoid, &retdata, NULL, 0 ); #ifdef LDAP_SYNC_TRACE fprintf( stderr, "\t%sldap_parse_intermediate(%s) == %d\n", rc != LDAP_SUCCESS ? "!!! " : "", retoid == NULL ? "\"\"" : retoid, rc ); #endif /* LDAP_SYNC_TRACE */ /* parsing must be successful, and yield the OID * of the sync info intermediate response */ if ( rc != LDAP_SUCCESS ) { goto done; } rc = LDAP_OTHER; if ( retoid == NULL || strcmp( retoid, LDAP_SYNC_INFO ) != 0 ) { goto done; } /* init ber using the value in the response */ ber = ber_init( retdata ); if ( ber == NULL ) { goto done; } syncinfo_tag = ber_peek_tag( ber, &len ); switch ( syncinfo_tag ) { case LDAP_TAG_SYNC_NEW_COOKIE: if ( ber_scanf( ber, "m", &cookie ) == LBER_ERROR ) { goto done; } if ( cookie.bv_val != NULL ) { ber_bvreplace( &ls->ls_cookie, &cookie ); } #ifdef LDAP_SYNC_TRACE fprintf( stderr, "\t\tgot cookie=%s\n", cookie.bv_val ? cookie.bv_val : "(null)" ); #endif /* LDAP_SYNC_TRACE */ break; case LDAP_TAG_SYNC_REFRESH_DELETE: case LDAP_TAG_SYNC_REFRESH_PRESENT: if ( syncinfo_tag == LDAP_TAG_SYNC_REFRESH_DELETE ) { #ifdef LDAP_SYNC_TRACE fprintf( stderr, "\t\tgot refreshDelete\n" ); #endif /* LDAP_SYNC_TRACE */ switch ( ls->ls_refreshPhase ) { case LDAP_SYNC_CAPI_NONE: case LDAP_SYNC_CAPI_PRESENTS: ls->ls_refreshPhase = LDAP_SYNC_CAPI_DELETES; break; default: /* TODO: impossible; handle */ goto done; } } else { #ifdef LDAP_SYNC_TRACE fprintf( stderr, "\t\tgot refreshPresent\n" ); #endif /* LDAP_SYNC_TRACE */ switch ( ls->ls_refreshPhase ) { case LDAP_SYNC_CAPI_NONE: ls->ls_refreshPhase = LDAP_SYNC_CAPI_PRESENTS; break; default: /* TODO: impossible; handle */ goto done; } } if ( ber_scanf( ber, "{" /*"}"*/ ) == LBER_ERROR ) { goto done; } if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SYNC_COOKIE ) { if ( ber_scanf( ber, "m", &cookie ) == LBER_ERROR ) { goto done; } if ( cookie.bv_val != NULL ) { ber_bvreplace( &ls->ls_cookie, &cookie ); } #ifdef LDAP_SYNC_TRACE fprintf( stderr, "\t\tgot cookie=%s\n", cookie.bv_val ? cookie.bv_val : "(null)" ); #endif /* LDAP_SYNC_TRACE */ } *refreshDone = 1; if ( ber_peek_tag( ber, &len ) == LDAP_TAG_REFRESHDONE ) { if ( ber_scanf( ber, "b", refreshDone ) == LBER_ERROR ) { goto done; } } #ifdef LDAP_SYNC_TRACE fprintf( stderr, "\t\tgot refreshDone=%s\n", *refreshDone ? "TRUE" : "FALSE" ); #endif /* LDAP_SYNC_TRACE */ if ( ber_scanf( ber, /*"{"*/ "}" ) == LBER_ERROR ) { goto done; } if ( *refreshDone ) { ls->ls_refreshPhase = LDAP_SYNC_CAPI_DONE; } if ( ls->ls_intermediate ) { ls->ls_intermediate( ls, res, NULL, ls->ls_refreshPhase ); } break; case LDAP_TAG_SYNC_ID_SET: #ifdef LDAP_SYNC_TRACE fprintf( stderr, "\t\tgot syncIdSet\n" ); #endif /* LDAP_SYNC_TRACE */ if ( ber_scanf( ber, "{" /*"}"*/ ) == LBER_ERROR ) { goto done; } if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SYNC_COOKIE ) { if ( ber_scanf( ber, "m", &cookie ) == LBER_ERROR ) { goto done; } if ( cookie.bv_val != NULL ) { ber_bvreplace( &ls->ls_cookie, &cookie ); } #ifdef LDAP_SYNC_TRACE fprintf( stderr, "\t\tgot cookie=%s\n", cookie.bv_val ? cookie.bv_val : "(null)" ); #endif /* LDAP_SYNC_TRACE */ } if ( ber_peek_tag( ber, &len ) == LDAP_TAG_REFRESHDELETES ) { if ( ber_scanf( ber, "b", &refreshDeletes ) == LBER_ERROR ) { goto done; } } if ( ber_scanf( ber, /*"{"*/ "[W]}", &syncUUIDs ) == LBER_ERROR || syncUUIDs == NULL ) { goto done; } #ifdef LDAP_SYNC_TRACE { int i; fprintf( stderr, "\t\tgot refreshDeletes=%s\n", refreshDeletes ? "TRUE" : "FALSE" ); for ( i = 0; syncUUIDs[ i ].bv_val != NULL; i++ ) { char buf[ BUFSIZ ]; fprintf( stderr, "\t\t%s\n", lutil_uuidstr_from_normalized( syncUUIDs[ i ].bv_val, syncUUIDs[ i ].bv_len, buf, sizeof( buf ) ) ); } } #endif /* LDAP_SYNC_TRACE */ if ( refreshDeletes ) { phase = LDAP_SYNC_CAPI_DELETES_IDSET; } else { phase = LDAP_SYNC_CAPI_PRESENTS_IDSET; } /* FIXME: should touch ls->ls_refreshPhase? */ if ( ls->ls_intermediate ) { ls->ls_intermediate( ls, res, syncUUIDs, phase ); } ber_bvarray_free( syncUUIDs ); break; default: #ifdef LDAP_SYNC_TRACE fprintf( stderr, "\t\tunknown tag!\n" ); #endif /* LDAP_SYNC_TRACE */ goto done; } rc = LDAP_SUCCESS; done:; if ( ber != NULL ) { ber_free( ber, 1 ); } if ( retoid != NULL ) { ldap_memfree( retoid ); } if ( retdata != NULL ) { ber_bvfree( retdata ); } return rc; } /* * initialize the sync */ int ldap_sync_init( ldap_sync_t *ls, int mode ) { LDAPControl ctrl = { 0 }, *ctrls[ 2 ]; BerElement *ber = NULL; int rc; struct timeval tv = { 0 }, *tvp = NULL; LDAPMessage *res = NULL; #ifdef LDAP_SYNC_TRACE fprintf( stderr, "ldap_sync_init(%s)...\n", mode == LDAP_SYNC_REFRESH_AND_PERSIST ? "LDAP_SYNC_REFRESH_AND_PERSIST" : ( mode == LDAP_SYNC_REFRESH_ONLY ? "LDAP_SYNC_REFRESH_ONLY" : "unknown" ) ); #endif /* LDAP_SYNC_TRACE */ assert( ls != NULL ); assert( ls->ls_ld != NULL ); /* support both refreshOnly and refreshAndPersist */ switch ( mode ) { case LDAP_SYNC_REFRESH_AND_PERSIST: case LDAP_SYNC_REFRESH_ONLY: break; default: fprintf( stderr, "ldap_sync_init: unknown mode=%d\n", mode ); return LDAP_PARAM_ERROR; } /* check consistency of cookie and reloadHint at initial refresh */ if ( ls->ls_cookie.bv_val == NULL && ls->ls_reloadHint != 0 ) { fprintf( stderr, "ldap_sync_init: inconsistent cookie/rhint\n" ); return LDAP_PARAM_ERROR; } ctrls[ 0 ] = &ctrl; ctrls[ 1 ] = NULL; /* prepare the Sync Request control */ ber = ber_alloc_t( LBER_USE_DER ); #ifdef LDAP_SYNC_TRACE fprintf( stderr, "%sber_alloc_t() %s= NULL\n", ber == NULL ? "!!! " : "", ber == NULL ? "=" : "!" ); #endif /* LDAP_SYNC_TRACE */ if ( ber == NULL ) { rc = LDAP_NO_MEMORY; goto done; } ls->ls_refreshPhase = LDAP_SYNC_CAPI_NONE; if ( ls->ls_cookie.bv_val != NULL ) { ber_printf( ber, "{eOb}", mode, &ls->ls_cookie, ls->ls_reloadHint ); } else { ber_printf( ber, "{eb}", mode, ls->ls_reloadHint ); } rc = ber_flatten2( ber, &ctrl.ldctl_value, 0 ); #ifdef LDAP_SYNC_TRACE fprintf( stderr, "%sber_flatten2() == %d\n", rc ? "!!! " : "", rc ); #endif /* LDAP_SYNC_TRACE */ if ( rc < 0 ) { rc = LDAP_OTHER; goto done; } /* make the control critical, as we cannot proceed without */ ctrl.ldctl_oid = LDAP_CONTROL_SYNC; ctrl.ldctl_iscritical = 1; /* timelimit? */ if ( ls->ls_timelimit ) { tv.tv_sec = ls->ls_timelimit; tvp = &tv; } /* actually run the search */ rc = ldap_search_ext( ls->ls_ld, ls->ls_base, ls->ls_scope, ls->ls_filter, ls->ls_attrs, 0, ctrls, NULL, tvp, ls->ls_sizelimit, &ls->ls_msgid ); #ifdef LDAP_SYNC_TRACE fprintf( stderr, "%sldap_search_ext(\"%s\", %d, \"%s\") == %d\n", rc ? "!!! " : "", ls->ls_base, ls->ls_scope, ls->ls_filter, rc ); #endif /* LDAP_SYNC_TRACE */ if ( rc != LDAP_SUCCESS ) { goto done; } /* initial content/content update phase */ for ( ; ; ) { LDAPMessage *msg = NULL; /* NOTE: this very short timeout is just to let * ldap_result() yield long enough to get something */ tv.tv_sec = 0; tv.tv_usec = 100000; rc = ldap_result( ls->ls_ld, ls->ls_msgid, LDAP_MSG_RECEIVED, &tv, &res ); #ifdef LDAP_SYNC_TRACE fprintf( stderr, "\t%sldap_result(%d) == %d\n", rc == -1 ? "!!! " : "", ls->ls_msgid, rc ); #endif /* LDAP_SYNC_TRACE */ switch ( rc ) { case 0: /* * timeout * * TODO: can do something else in the meanwhile) */ break; case -1: /* smtg bad! */ goto done; default: for ( msg = ldap_first_message( ls->ls_ld, res ); msg != NULL; msg = ldap_next_message( ls->ls_ld, msg ) ) { int refreshDone; switch ( ldap_msgtype( msg ) ) { case LDAP_RES_SEARCH_ENTRY: rc = ldap_sync_search_entry( ls, res ); break; case LDAP_RES_SEARCH_REFERENCE: rc = ldap_sync_search_reference( ls, res ); break; case LDAP_RES_SEARCH_RESULT: rc = ldap_sync_search_result( ls, res ); goto done_search; case LDAP_RES_INTERMEDIATE: rc = ldap_sync_search_intermediate( ls, res, &refreshDone ); if ( rc != LDAP_SUCCESS || refreshDone ) { goto done_search; } break; default: #ifdef LDAP_SYNC_TRACE fprintf( stderr, "\tgot something unexpected...\n" ); #endif /* LDAP_SYNC_TRACE */ ldap_msgfree( res ); rc = LDAP_OTHER; goto done; } } ldap_msgfree( res ); res = NULL; break; } } done_search:; ldap_msgfree( res ); done:; if ( ber != NULL ) { ber_free( ber, 1 ); } return rc; } /* * initialize the refreshOnly sync */ int ldap_sync_init_refresh_only( ldap_sync_t *ls ) { return ldap_sync_init( ls, LDAP_SYNC_REFRESH_ONLY ); } /* * initialize the refreshAndPersist sync */ int ldap_sync_init_refresh_and_persist( ldap_sync_t *ls ) { return ldap_sync_init( ls, LDAP_SYNC_REFRESH_AND_PERSIST ); } /* * poll for new responses */ int ldap_sync_poll( ldap_sync_t *ls ) { struct timeval tv, *tvp = NULL; LDAPMessage *res = NULL, *msg; int rc = 0; #ifdef LDAP_SYNC_TRACE fprintf( stderr, "ldap_sync_poll...\n" ); #endif /* LDAP_SYNC_TRACE */ assert( ls != NULL ); assert( ls->ls_ld != NULL ); if ( ls->ls_timeout != -1 ) { tv.tv_sec = ls->ls_timeout; tv.tv_usec = 0; tvp = &tv; } rc = ldap_result( ls->ls_ld, ls->ls_msgid, LDAP_MSG_RECEIVED, tvp, &res ); if ( rc <= 0 ) { return rc; } for ( msg = ldap_first_message( ls->ls_ld, res ); msg; msg = ldap_next_message( ls->ls_ld, msg ) ) { int refreshDone; switch ( ldap_msgtype( msg ) ) { case LDAP_RES_SEARCH_ENTRY: rc = ldap_sync_search_entry( ls, res ); break; case LDAP_RES_SEARCH_REFERENCE: rc = ldap_sync_search_reference( ls, res ); break; case LDAP_RES_SEARCH_RESULT: rc = ldap_sync_search_result( ls, res ); goto done_search; case LDAP_RES_INTERMEDIATE: rc = ldap_sync_search_intermediate( ls, res, &refreshDone ); if ( rc != LDAP_SUCCESS || refreshDone ) { goto done_search; } break; default: #ifdef LDAP_SYNC_TRACE fprintf( stderr, "\tgot something unexpected...\n" ); #endif /* LDAP_SYNC_TRACE */ ldap_msgfree( res ); rc = LDAP_OTHER; goto done; } } done_search:; ldap_msgfree( res ); done:; return rc; } openldap-2.4.42+dfsg/libraries/libldap/init.c0000644000175000017500000004210412563404150017523 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #include "portable.h" #include #include #ifdef HAVE_GETEUID #include #endif #include #include #include #include #ifdef HAVE_LIMITS_H #include #endif #include "ldap-int.h" #include "ldap_defaults.h" #include "lutil.h" struct ldapoptions ldap_int_global_options = { LDAP_UNINITIALIZED, LDAP_DEBUG_NONE LDAP_LDO_NULLARG LDAP_LDO_CONNECTIONLESS_NULLARG LDAP_LDO_TLS_NULLARG LDAP_LDO_SASL_NULLARG LDAP_LDO_GSSAPI_NULLARG LDAP_LDO_MUTEX_NULLARG }; #define ATTR_NONE 0 #define ATTR_BOOL 1 #define ATTR_INT 2 #define ATTR_KV 3 #define ATTR_STRING 4 #define ATTR_OPTION 5 #define ATTR_SASL 6 #define ATTR_TLS 7 #define ATTR_OPT_TV 8 #define ATTR_OPT_INT 9 #define ATTR_GSSAPI 10 struct ol_keyvalue { const char * key; int value; }; static const struct ol_keyvalue deref_kv[] = { {"never", LDAP_DEREF_NEVER}, {"searching", LDAP_DEREF_SEARCHING}, {"finding", LDAP_DEREF_FINDING}, {"always", LDAP_DEREF_ALWAYS}, {NULL, 0} }; static const struct ol_attribute { int useronly; int type; const char * name; const void * data; size_t offset; } attrs[] = { {0, ATTR_OPT_TV, "TIMEOUT", NULL, LDAP_OPT_TIMEOUT}, {0, ATTR_OPT_TV, "NETWORK_TIMEOUT", NULL, LDAP_OPT_NETWORK_TIMEOUT}, {0, ATTR_OPT_INT, "VERSION", NULL, LDAP_OPT_PROTOCOL_VERSION}, {0, ATTR_KV, "DEREF", deref_kv, /* or &deref_kv[0] */ offsetof(struct ldapoptions, ldo_deref)}, {0, ATTR_INT, "SIZELIMIT", NULL, offsetof(struct ldapoptions, ldo_sizelimit)}, {0, ATTR_INT, "TIMELIMIT", NULL, offsetof(struct ldapoptions, ldo_timelimit)}, {1, ATTR_STRING, "BINDDN", NULL, offsetof(struct ldapoptions, ldo_defbinddn)}, {0, ATTR_STRING, "BASE", NULL, offsetof(struct ldapoptions, ldo_defbase)}, {0, ATTR_INT, "PORT", NULL, /* deprecated */ offsetof(struct ldapoptions, ldo_defport)}, {0, ATTR_OPTION, "HOST", NULL, LDAP_OPT_HOST_NAME}, /* deprecated */ {0, ATTR_OPTION, "URI", NULL, LDAP_OPT_URI}, /* replaces HOST/PORT */ {0, ATTR_BOOL, "REFERRALS", NULL, LDAP_BOOL_REFERRALS}, #if 0 /* This should only be allowed via ldap_set_option(3) */ {0, ATTR_BOOL, "RESTART", NULL, LDAP_BOOL_RESTART}, #endif #ifdef HAVE_CYRUS_SASL {0, ATTR_STRING, "SASL_MECH", NULL, offsetof(struct ldapoptions, ldo_def_sasl_mech)}, {0, ATTR_STRING, "SASL_REALM", NULL, offsetof(struct ldapoptions, ldo_def_sasl_realm)}, {1, ATTR_STRING, "SASL_AUTHCID", NULL, offsetof(struct ldapoptions, ldo_def_sasl_authcid)}, {1, ATTR_STRING, "SASL_AUTHZID", NULL, offsetof(struct ldapoptions, ldo_def_sasl_authzid)}, {0, ATTR_SASL, "SASL_SECPROPS", NULL, LDAP_OPT_X_SASL_SECPROPS}, {0, ATTR_BOOL, "SASL_NOCANON", NULL, LDAP_BOOL_SASL_NOCANON}, #endif #ifdef HAVE_GSSAPI {0, ATTR_GSSAPI,"GSSAPI_SIGN", NULL, LDAP_OPT_SIGN}, {0, ATTR_GSSAPI,"GSSAPI_ENCRYPT", NULL, LDAP_OPT_ENCRYPT}, {0, ATTR_GSSAPI,"GSSAPI_ALLOW_REMOTE_PRINCIPAL",NULL, LDAP_OPT_X_GSSAPI_ALLOW_REMOTE_PRINCIPAL}, #endif #ifdef HAVE_TLS {1, ATTR_TLS, "TLS_CERT", NULL, LDAP_OPT_X_TLS_CERTFILE}, {1, ATTR_TLS, "TLS_KEY", NULL, LDAP_OPT_X_TLS_KEYFILE}, {0, ATTR_TLS, "TLS_CACERT", NULL, LDAP_OPT_X_TLS_CACERTFILE}, {0, ATTR_TLS, "TLS_CACERTDIR", NULL, LDAP_OPT_X_TLS_CACERTDIR}, {0, ATTR_TLS, "TLS_REQCERT", NULL, LDAP_OPT_X_TLS_REQUIRE_CERT}, {0, ATTR_TLS, "TLS_RANDFILE", NULL, LDAP_OPT_X_TLS_RANDOM_FILE}, {0, ATTR_TLS, "TLS_CIPHER_SUITE", NULL, LDAP_OPT_X_TLS_CIPHER_SUITE}, {0, ATTR_TLS, "TLS_PROTOCOL_MIN", NULL, LDAP_OPT_X_TLS_PROTOCOL_MIN}, #ifdef HAVE_OPENSSL_CRL {0, ATTR_TLS, "TLS_CRLCHECK", NULL, LDAP_OPT_X_TLS_CRLCHECK}, #endif #ifdef HAVE_GNUTLS {0, ATTR_TLS, "TLS_CRLFILE", NULL, LDAP_OPT_X_TLS_CRLFILE}, #endif #endif {0, ATTR_NONE, NULL, NULL, 0} }; #define MAX_LDAP_ATTR_LEN sizeof("GSSAPI_ALLOW_REMOTE_PRINCIPAL") #define MAX_LDAP_ENV_PREFIX_LEN 8 static void openldap_ldap_init_w_conf( const char *file, int userconf ) { char linebuf[ AC_LINE_MAX ]; FILE *fp; int i; char *cmd, *opt; char *start, *end; struct ldapoptions *gopts; if ((gopts = LDAP_INT_GLOBAL_OPT()) == NULL) { return; /* Could not allocate mem for global options */ } if (file == NULL) { /* no file name */ return; } Debug(LDAP_DEBUG_TRACE, "ldap_init: trying %s\n", file, 0, 0); fp = fopen(file, "r"); if(fp == NULL) { /* could not open file */ return; } Debug(LDAP_DEBUG_TRACE, "ldap_init: using %s\n", file, 0, 0); while((start = fgets(linebuf, sizeof(linebuf), fp)) != NULL) { /* skip lines starting with '#' */ if(*start == '#') continue; /* trim leading white space */ while((*start != '\0') && isspace((unsigned char) *start)) start++; /* anything left? */ if(*start == '\0') continue; /* trim trailing white space */ end = &start[strlen(start)-1]; while(isspace((unsigned char)*end)) end--; end[1] = '\0'; /* anything left? */ if(*start == '\0') continue; /* parse the command */ cmd=start; while((*start != '\0') && !isspace((unsigned char)*start)) { start++; } if(*start == '\0') { /* command has no argument */ continue; } *start++ = '\0'; /* we must have some whitespace to skip */ while(isspace((unsigned char)*start)) start++; opt = start; for(i=0; attrs[i].type != ATTR_NONE; i++) { void *p; if( !userconf && attrs[i].useronly ) { continue; } if(strcasecmp(cmd, attrs[i].name) != 0) { continue; } switch(attrs[i].type) { case ATTR_BOOL: if((strcasecmp(opt, "on") == 0) || (strcasecmp(opt, "yes") == 0) || (strcasecmp(opt, "true") == 0)) { LDAP_BOOL_SET(gopts, attrs[i].offset); } else { LDAP_BOOL_CLR(gopts, attrs[i].offset); } break; case ATTR_INT: { char *next; long l; p = &((char *) gopts)[attrs[i].offset]; l = strtol( opt, &next, 10 ); if ( next != opt && next[ 0 ] == '\0' ) { * (int*) p = l; } } break; case ATTR_KV: { const struct ol_keyvalue *kv; for(kv = attrs[i].data; kv->key != NULL; kv++) { if(strcasecmp(opt, kv->key) == 0) { p = &((char *) gopts)[attrs[i].offset]; * (int*) p = kv->value; break; } } } break; case ATTR_STRING: p = &((char *) gopts)[attrs[i].offset]; if (* (char**) p != NULL) LDAP_FREE(* (char**) p); * (char**) p = LDAP_STRDUP(opt); break; case ATTR_OPTION: ldap_set_option( NULL, attrs[i].offset, opt ); break; case ATTR_SASL: #ifdef HAVE_CYRUS_SASL ldap_int_sasl_config( gopts, attrs[i].offset, opt ); #endif break; case ATTR_GSSAPI: #ifdef HAVE_GSSAPI ldap_int_gssapi_config( gopts, attrs[i].offset, opt ); #endif break; case ATTR_TLS: #ifdef HAVE_TLS ldap_int_tls_config( NULL, attrs[i].offset, opt ); #endif break; case ATTR_OPT_TV: { struct timeval tv; char *next; tv.tv_usec = 0; tv.tv_sec = strtol( opt, &next, 10 ); if ( next != opt && next[ 0 ] == '\0' && tv.tv_sec > 0 ) { (void)ldap_set_option( NULL, attrs[i].offset, (const void *)&tv ); } } break; case ATTR_OPT_INT: { long l; char *next; l = strtol( opt, &next, 10 ); if ( next != opt && next[ 0 ] == '\0' && l > 0 && (long)((int)l) == l ) { int v = (int)l; (void)ldap_set_option( NULL, attrs[i].offset, (const void *)&v ); } } break; } break; } } fclose(fp); } static void openldap_ldap_init_w_sysconf(const char *file) { openldap_ldap_init_w_conf( file, 0 ); } static void openldap_ldap_init_w_userconf(const char *file) { char *home; char *path = NULL; if (file == NULL) { /* no file name */ return; } home = getenv("HOME"); if (home != NULL) { Debug(LDAP_DEBUG_TRACE, "ldap_init: HOME env is %s\n", home, 0, 0); path = LDAP_MALLOC(strlen(home) + strlen(file) + sizeof( LDAP_DIRSEP ".")); } else { Debug(LDAP_DEBUG_TRACE, "ldap_init: HOME env is NULL\n", 0, 0, 0); } if(home != NULL && path != NULL) { /* we assume UNIX path syntax is used... */ /* try ~/file */ sprintf(path, "%s" LDAP_DIRSEP "%s", home, file); openldap_ldap_init_w_conf(path, 1); /* try ~/.file */ sprintf(path, "%s" LDAP_DIRSEP ".%s", home, file); openldap_ldap_init_w_conf(path, 1); } if(path != NULL) { LDAP_FREE(path); } /* try file */ openldap_ldap_init_w_conf(file, 1); } static void openldap_ldap_init_w_env( struct ldapoptions *gopts, const char *prefix) { char buf[MAX_LDAP_ATTR_LEN+MAX_LDAP_ENV_PREFIX_LEN]; int len; int i; void *p; char *value; if (prefix == NULL) { prefix = LDAP_ENV_PREFIX; } strncpy(buf, prefix, MAX_LDAP_ENV_PREFIX_LEN); buf[MAX_LDAP_ENV_PREFIX_LEN] = '\0'; len = strlen(buf); for(i=0; attrs[i].type != ATTR_NONE; i++) { strcpy(&buf[len], attrs[i].name); value = getenv(buf); if(value == NULL) { continue; } switch(attrs[i].type) { case ATTR_BOOL: if((strcasecmp(value, "on") == 0) || (strcasecmp(value, "yes") == 0) || (strcasecmp(value, "true") == 0)) { LDAP_BOOL_SET(gopts, attrs[i].offset); } else { LDAP_BOOL_CLR(gopts, attrs[i].offset); } break; case ATTR_INT: p = &((char *) gopts)[attrs[i].offset]; * (int*) p = atoi(value); break; case ATTR_KV: { const struct ol_keyvalue *kv; for(kv = attrs[i].data; kv->key != NULL; kv++) { if(strcasecmp(value, kv->key) == 0) { p = &((char *) gopts)[attrs[i].offset]; * (int*) p = kv->value; break; } } } break; case ATTR_STRING: p = &((char *) gopts)[attrs[i].offset]; if (* (char**) p != NULL) LDAP_FREE(* (char**) p); if (*value == '\0') { * (char**) p = NULL; } else { * (char**) p = LDAP_STRDUP(value); } break; case ATTR_OPTION: ldap_set_option( NULL, attrs[i].offset, value ); break; case ATTR_SASL: #ifdef HAVE_CYRUS_SASL ldap_int_sasl_config( gopts, attrs[i].offset, value ); #endif break; case ATTR_GSSAPI: #ifdef HAVE_GSSAPI ldap_int_gssapi_config( gopts, attrs[i].offset, value ); #endif break; case ATTR_TLS: #ifdef HAVE_TLS ldap_int_tls_config( NULL, attrs[i].offset, value ); #endif break; case ATTR_OPT_TV: { struct timeval tv; char *next; tv.tv_usec = 0; tv.tv_sec = strtol( value, &next, 10 ); if ( next != value && next[ 0 ] == '\0' && tv.tv_sec > 0 ) { (void)ldap_set_option( NULL, attrs[i].offset, (const void *)&tv ); } } break; case ATTR_OPT_INT: { long l; char *next; l = strtol( value, &next, 10 ); if ( next != value && next[ 0 ] == '\0' && l > 0 && (long)((int)l) == l ) { int v = (int)l; (void)ldap_set_option( NULL, attrs[i].offset, (const void *)&v ); } } break; } } } #if defined(__GNUC__) /* Declare this function as a destructor so that it will automatically be * invoked either at program exit (if libldap is a static library) or * at unload time (if libldap is a dynamic library). * * Sorry, don't know how to handle this for non-GCC environments. */ static void ldap_int_destroy_global_options(void) __attribute__ ((destructor)); #endif static void ldap_int_destroy_global_options(void) { struct ldapoptions *gopts = LDAP_INT_GLOBAL_OPT(); if ( gopts == NULL ) return; gopts->ldo_valid = LDAP_UNINITIALIZED; if ( gopts->ldo_defludp ) { ldap_free_urllist( gopts->ldo_defludp ); gopts->ldo_defludp = NULL; } #if defined(HAVE_WINSOCK) || defined(HAVE_WINSOCK2) WSACleanup( ); #endif #if defined(HAVE_TLS) || defined(HAVE_CYRUS_SASL) if ( ldap_int_hostname ) { LDAP_FREE( ldap_int_hostname ); ldap_int_hostname = NULL; } #endif #ifdef HAVE_CYRUS_SASL if ( gopts->ldo_def_sasl_authcid ) { LDAP_FREE( gopts->ldo_def_sasl_authcid ); gopts->ldo_def_sasl_authcid = NULL; } #endif #ifdef HAVE_TLS ldap_int_tls_destroy( gopts ); #endif } /* * Initialize the global options structure with default values. */ void ldap_int_initialize_global_options( struct ldapoptions *gopts, int *dbglvl ) { #ifdef LDAP_R_COMPILE LDAP_PVT_MUTEX_FIRSTCREATE(gopts->ldo_mutex); #endif LDAP_MUTEX_LOCK( &gopts->ldo_mutex ); if (gopts->ldo_valid == LDAP_INITIALIZED) { /* someone else got here first */ LDAP_MUTEX_UNLOCK( &gopts->ldo_mutex ); return; } if (dbglvl) gopts->ldo_debug = *dbglvl; else gopts->ldo_debug = 0; gopts->ldo_version = LDAP_VERSION2; gopts->ldo_deref = LDAP_DEREF_NEVER; gopts->ldo_timelimit = LDAP_NO_LIMIT; gopts->ldo_sizelimit = LDAP_NO_LIMIT; gopts->ldo_tm_api.tv_sec = -1; gopts->ldo_tm_net.tv_sec = -1; /* ldo_defludp will be freed by the termination handler */ ldap_url_parselist(&gopts->ldo_defludp, "ldap://localhost/"); gopts->ldo_defport = LDAP_PORT; #if !defined(__GNUC__) && !defined(PIC) /* Do this only for a static library, and only if we can't * arrange for it to be executed as a library destructor */ atexit(ldap_int_destroy_global_options); #endif gopts->ldo_refhoplimit = LDAP_DEFAULT_REFHOPLIMIT; gopts->ldo_rebind_proc = NULL; gopts->ldo_rebind_params = NULL; LDAP_BOOL_ZERO(gopts); LDAP_BOOL_SET(gopts, LDAP_BOOL_REFERRALS); #ifdef LDAP_CONNECTIONLESS gopts->ldo_peer = NULL; gopts->ldo_cldapdn = NULL; gopts->ldo_is_udp = 0; #endif #ifdef HAVE_CYRUS_SASL gopts->ldo_def_sasl_mech = NULL; gopts->ldo_def_sasl_realm = NULL; gopts->ldo_def_sasl_authcid = NULL; gopts->ldo_def_sasl_authzid = NULL; memset( &gopts->ldo_sasl_secprops, '\0', sizeof(gopts->ldo_sasl_secprops) ); gopts->ldo_sasl_secprops.max_ssf = INT_MAX; gopts->ldo_sasl_secprops.maxbufsize = SASL_MAX_BUFF_SIZE; gopts->ldo_sasl_secprops.security_flags = SASL_SEC_NOPLAINTEXT | SASL_SEC_NOANONYMOUS; #endif #ifdef HAVE_TLS gopts->ldo_tls_connect_cb = NULL; gopts->ldo_tls_connect_arg = NULL; gopts->ldo_tls_require_cert = LDAP_OPT_X_TLS_DEMAND; #endif gopts->ldo_keepalive_probes = 0; gopts->ldo_keepalive_interval = 0; gopts->ldo_keepalive_idle = 0; gopts->ldo_valid = LDAP_INITIALIZED; LDAP_MUTEX_UNLOCK( &gopts->ldo_mutex ); return; } #if defined(HAVE_TLS) || defined(HAVE_CYRUS_SASL) char * ldap_int_hostname = NULL; #endif void ldap_int_initialize( struct ldapoptions *gopts, int *dbglvl ) { if ( gopts->ldo_valid == LDAP_INITIALIZED ) { return; } ldap_int_error_init(); ldap_int_utils_init(); #ifdef HAVE_WINSOCK2 { WORD wVersionRequested; WSADATA wsaData; wVersionRequested = MAKEWORD( 2, 0 ); if ( WSAStartup( wVersionRequested, &wsaData ) != 0 ) { /* Tell the user that we couldn't find a usable */ /* WinSock DLL. */ return; } /* Confirm that the WinSock DLL supports 2.0.*/ /* Note that if the DLL supports versions greater */ /* than 2.0 in addition to 2.0, it will still return */ /* 2.0 in wVersion since that is the version we */ /* requested. */ if ( LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 0 ) { /* Tell the user that we couldn't find a usable */ /* WinSock DLL. */ WSACleanup( ); return; } } /* The WinSock DLL is acceptable. Proceed. */ #elif defined(HAVE_WINSOCK) { WSADATA wsaData; if ( WSAStartup( 0x0101, &wsaData ) != 0 ) { return; } } #endif #if defined(HAVE_TLS) || defined(HAVE_CYRUS_SASL) LDAP_MUTEX_LOCK( &ldap_int_hostname_mutex ); { char *name = ldap_int_hostname; ldap_int_hostname = ldap_pvt_get_fqdn( name ); if ( name != NULL && name != ldap_int_hostname ) { LDAP_FREE( name ); } } LDAP_MUTEX_UNLOCK( &ldap_int_hostname_mutex ); #endif #ifndef HAVE_POLL if ( ldap_int_tblsize == 0 ) ldap_int_ip_init(); #endif ldap_int_initialize_global_options(gopts, dbglvl); if( getenv("LDAPNOINIT") != NULL ) { return; } #ifdef HAVE_CYRUS_SASL { /* set authentication identity to current user name */ char *user = getenv("USER"); if( user == NULL ) user = getenv("USERNAME"); if( user == NULL ) user = getenv("LOGNAME"); if( user != NULL ) { gopts->ldo_def_sasl_authcid = LDAP_STRDUP( user ); } } #endif openldap_ldap_init_w_sysconf(LDAP_CONF_FILE); #ifdef HAVE_GETEUID if ( geteuid() != getuid() ) return; #endif openldap_ldap_init_w_userconf(LDAP_USERRC_FILE); { char *altfile = getenv(LDAP_ENV_PREFIX "CONF"); if( altfile != NULL ) { Debug(LDAP_DEBUG_TRACE, "ldap_init: %s env is %s\n", LDAP_ENV_PREFIX "CONF", altfile, 0); openldap_ldap_init_w_sysconf( altfile ); } else Debug(LDAP_DEBUG_TRACE, "ldap_init: %s env is NULL\n", LDAP_ENV_PREFIX "CONF", 0, 0); } { char *altfile = getenv(LDAP_ENV_PREFIX "RC"); if( altfile != NULL ) { Debug(LDAP_DEBUG_TRACE, "ldap_init: %s env is %s\n", LDAP_ENV_PREFIX "RC", altfile, 0); openldap_ldap_init_w_userconf( altfile ); } else Debug(LDAP_DEBUG_TRACE, "ldap_init: %s env is NULL\n", LDAP_ENV_PREFIX "RC", 0, 0); } openldap_ldap_init_w_env(gopts, NULL); } openldap-2.4.42+dfsg/libraries/libldap/modrdn.c0000644000175000017500000001300212563404150020036 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (c) 1990 Regents of the University of Michigan. * All rights reserved. */ /* Copyright 1999, Juan C. Gomez, All rights reserved. * This software is not subject to any license of Silicon Graphics * Inc. or Purdue University. * * Redistribution and use in source and binary forms are permitted * without restriction or fee of any kind as long as this notice * is preserved. */ /* ACKNOWLEDGEMENTS: * Juan C. Gomez */ #include "portable.h" #include #include #include #include #include "ldap-int.h" /* * A modify rdn request looks like this: * ModifyRDNRequest ::= SEQUENCE { * entry DistinguishedName, * newrdn RelativeDistinguishedName, * deleteoldrdn BOOLEAN * newSuperior [0] DistinguishedName [v3 only] * } */ /* * ldap_rename - initiate an ldap extended modifyDN operation. * * Parameters: * ld LDAP descriptor * dn DN of the object to modify * newrdn RDN to give the object * deleteoldrdn nonzero means to delete old rdn values from the entry * newSuperior DN of the new parent if applicable * * Returns the LDAP error code. */ int ldap_rename( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *newrdn, LDAP_CONST char *newSuperior, int deleteoldrdn, LDAPControl **sctrls, LDAPControl **cctrls, int *msgidp ) { BerElement *ber; int rc; ber_int_t id; Debug( LDAP_DEBUG_TRACE, "ldap_rename\n", 0, 0, 0 ); /* check client controls */ rc = ldap_int_client_controls( ld, cctrls ); if( rc != LDAP_SUCCESS ) return rc; /* create a message to send */ if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) { return( LDAP_NO_MEMORY ); } LDAP_NEXT_MSGID( ld, id ); if( newSuperior != NULL ) { /* must be version 3 (or greater) */ if ( ld->ld_version < LDAP_VERSION3 ) { ld->ld_errno = LDAP_NOT_SUPPORTED; ber_free( ber, 1 ); return( ld->ld_errno ); } rc = ber_printf( ber, "{it{ssbtsN}", /* '}' */ id, LDAP_REQ_MODDN, dn, newrdn, (ber_int_t) deleteoldrdn, LDAP_TAG_NEWSUPERIOR, newSuperior ); } else { rc = ber_printf( ber, "{it{ssbN}", /* '}' */ id, LDAP_REQ_MODDN, dn, newrdn, (ber_int_t) deleteoldrdn ); } if ( rc < 0 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( ld->ld_errno ); } /* Put Server Controls */ if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) { ber_free( ber, 1 ); return ld->ld_errno; } rc = ber_printf( ber, /*{*/ "N}" ); if ( rc < 0 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( ld->ld_errno ); } /* send the message */ *msgidp = ldap_send_initial_request( ld, LDAP_REQ_MODRDN, dn, ber, id ); if( *msgidp < 0 ) { return( ld->ld_errno ); } return LDAP_SUCCESS; } /* * ldap_rename2 - initiate an ldap (and X.500) modifyDN operation. Parameters: * (LDAP V3 MODIFYDN REQUEST) * ld LDAP descriptor * dn DN of the object to modify * newrdn RDN to give the object * deleteoldrdn nonzero means to delete old rdn values from the entry * newSuperior DN of the new parent if applicable * * ldap_rename2 uses a U-Mich Style API. It returns the msgid. */ int ldap_rename2( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *newrdn, LDAP_CONST char *newSuperior, int deleteoldrdn ) { int msgid; int rc; Debug( LDAP_DEBUG_TRACE, "ldap_rename2\n", 0, 0, 0 ); rc = ldap_rename( ld, dn, newrdn, newSuperior, deleteoldrdn, NULL, NULL, &msgid ); return rc == LDAP_SUCCESS ? msgid : -1; } /* * ldap_modrdn2 - initiate an ldap modifyRDN operation. Parameters: * * ld LDAP descriptor * dn DN of the object to modify * newrdn RDN to give the object * deleteoldrdn nonzero means to delete old rdn values from the entry * * Example: * msgid = ldap_modrdn( ld, dn, newrdn ); */ int ldap_modrdn2( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *newrdn, int deleteoldrdn ) { return ldap_rename2( ld, dn, newrdn, NULL, deleteoldrdn ); } int ldap_modrdn( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *newrdn ) { return( ldap_rename2( ld, dn, newrdn, NULL, 1 ) ); } int ldap_rename_s( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *newrdn, LDAP_CONST char *newSuperior, int deleteoldrdn, LDAPControl **sctrls, LDAPControl **cctrls ) { int rc; int msgid; LDAPMessage *res; rc = ldap_rename( ld, dn, newrdn, newSuperior, deleteoldrdn, sctrls, cctrls, &msgid ); if( rc != LDAP_SUCCESS ) { return rc; } rc = ldap_result( ld, msgid, LDAP_MSG_ALL, NULL, &res ); if( rc == -1 || !res ) { return ld->ld_errno; } return ldap_result2error( ld, res, 1 ); } int ldap_rename2_s( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *newrdn, LDAP_CONST char *newSuperior, int deleteoldrdn ) { return ldap_rename_s( ld, dn, newrdn, newSuperior, deleteoldrdn, NULL, NULL ); } int ldap_modrdn2_s( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *newrdn, int deleteoldrdn ) { return ldap_rename_s( ld, dn, newrdn, NULL, deleteoldrdn, NULL, NULL ); } int ldap_modrdn_s( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *newrdn ) { return ldap_rename_s( ld, dn, newrdn, NULL, 1, NULL, NULL ); } openldap-2.4.42+dfsg/libraries/libldap/dnssrv.c0000644000175000017500000002217612563404150020106 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* * locate LDAP servers using DNS SRV records. * Location code based on MIT Kerberos KDC location code. */ #include "portable.h" #include #include #include #include #include #include #include "ldap-int.h" #ifdef HAVE_ARPA_NAMESER_H #include #endif #ifdef HAVE_RESOLV_H #include #endif int ldap_dn2domain( LDAP_CONST char *dn_in, char **domainp) { int i, j; char *ndomain; LDAPDN dn = NULL; LDAPRDN rdn = NULL; LDAPAVA *ava = NULL; struct berval domain = BER_BVNULL; static const struct berval DC = BER_BVC("DC"); static const struct berval DCOID = BER_BVC("0.9.2342.19200300.100.1.25"); assert( dn_in != NULL ); assert( domainp != NULL ); *domainp = NULL; if ( ldap_str2dn( dn_in, &dn, LDAP_DN_FORMAT_LDAP ) != LDAP_SUCCESS ) { return -2; } if( dn ) for( i=0; dn[i] != NULL; i++ ) { rdn = dn[i]; for( j=0; rdn[j] != NULL; j++ ) { ava = rdn[j]; if( rdn[j+1] == NULL && (ava->la_flags & LDAP_AVA_STRING) && ava->la_value.bv_len && ( ber_bvstrcasecmp( &ava->la_attr, &DC ) == 0 || ber_bvcmp( &ava->la_attr, &DCOID ) == 0 ) ) { if( domain.bv_len == 0 ) { ndomain = LDAP_REALLOC( domain.bv_val, ava->la_value.bv_len + 1); if( ndomain == NULL ) { goto return_error; } domain.bv_val = ndomain; AC_MEMCPY( domain.bv_val, ava->la_value.bv_val, ava->la_value.bv_len ); domain.bv_len = ava->la_value.bv_len; domain.bv_val[domain.bv_len] = '\0'; } else { ndomain = LDAP_REALLOC( domain.bv_val, ava->la_value.bv_len + sizeof(".") + domain.bv_len ); if( ndomain == NULL ) { goto return_error; } domain.bv_val = ndomain; domain.bv_val[domain.bv_len++] = '.'; AC_MEMCPY( &domain.bv_val[domain.bv_len], ava->la_value.bv_val, ava->la_value.bv_len ); domain.bv_len += ava->la_value.bv_len; domain.bv_val[domain.bv_len] = '\0'; } } else { domain.bv_len = 0; } } } if( domain.bv_len == 0 && domain.bv_val != NULL ) { LDAP_FREE( domain.bv_val ); domain.bv_val = NULL; } ldap_dnfree( dn ); *domainp = domain.bv_val; return 0; return_error: ldap_dnfree( dn ); LDAP_FREE( domain.bv_val ); return -1; } int ldap_domain2dn( LDAP_CONST char *domain_in, char **dnp) { char *domain, *s, *tok_r, *dn, *dntmp; size_t loc; assert( domain_in != NULL ); assert( dnp != NULL ); domain = LDAP_STRDUP(domain_in); if (domain == NULL) { return LDAP_NO_MEMORY; } dn = NULL; loc = 0; for (s = ldap_pvt_strtok(domain, ".", &tok_r); s != NULL; s = ldap_pvt_strtok(NULL, ".", &tok_r)) { size_t len = strlen(s); dntmp = (char *) LDAP_REALLOC(dn, loc + sizeof(",dc=") + len ); if (dntmp == NULL) { if (dn != NULL) LDAP_FREE(dn); LDAP_FREE(domain); return LDAP_NO_MEMORY; } dn = dntmp; if (loc > 0) { /* not first time. */ strcpy(dn + loc, ","); loc++; } strcpy(dn + loc, "dc="); loc += sizeof("dc=")-1; strcpy(dn + loc, s); loc += len; } LDAP_FREE(domain); *dnp = dn; return LDAP_SUCCESS; } #ifdef HAVE_RES_QUERY #define DNSBUFSIZ (64*1024) #define MAXHOST 254 /* RFC 1034, max length is 253 chars */ typedef struct srv_record { u_short priority; u_short weight; u_short port; char hostname[MAXHOST]; } srv_record; /* Linear Congruential Generator - we don't need * high quality randomness, and we don't want to * interfere with anyone else's use of srand(). * * The PRNG here cycles thru 941,955 numbers. */ static float srv_seed; static void srv_srand(int seed) { srv_seed = (float)seed / (float)RAND_MAX; } static float srv_rand() { float val = 9821.0 * srv_seed + .211327; srv_seed = val - (int)val; return srv_seed; } static int srv_cmp(const void *aa, const void *bb){ srv_record *a=(srv_record *)aa; srv_record *b=(srv_record *)bb; int i = a->priority - b->priority; if (i) return i; return b->weight - a->weight; } static void srv_shuffle(srv_record *a, int n) { int i, j, total = 0, r, p; for (i=0; i= 0) { unsigned char *p; char host[DNSBUFSIZ]; int status; u_short port, priority, weight; /* Parse out query */ p = reply; #ifdef NS_HFIXEDSZ /* Bind 8/9 interface */ p += NS_HFIXEDSZ; #elif defined(HFIXEDSZ) /* Bind 4 interface w/ HFIXEDSZ */ p += HFIXEDSZ; #else /* Bind 4 interface w/o HFIXEDSZ */ p += sizeof(HEADER); #endif status = dn_expand(reply, reply + len, p, host, sizeof(host)); if (status < 0) { goto out; } p += status; p += 4; while (p < reply + len) { int type, class, ttl, size; status = dn_expand(reply, reply + len, p, host, sizeof(host)); if (status < 0) { goto out; } p += status; type = (p[0] << 8) | p[1]; p += 2; class = (p[0] << 8) | p[1]; p += 2; ttl = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; p += 4; size = (p[0] << 8) | p[1]; p += 2; if (type == T_SRV) { status = dn_expand(reply, reply + len, p + 6, host, sizeof(host)); if (status < 0) { goto out; } /* Get priority weight and port */ priority = (p[0] << 8) | p[1]; weight = (p[2] << 8) | p[3]; port = (p[4] << 8) | p[5]; if ( port == 0 || host[ 0 ] == '\0' ) { goto add_size; } hostent_head = (srv_record *) LDAP_REALLOC(hostent_head, (hostent_count+1)*(sizeof(srv_record))); if(hostent_head==NULL){ rc=LDAP_NO_MEMORY; goto out; } hostent_head[hostent_count].priority=priority; hostent_head[hostent_count].weight=weight; hostent_head[hostent_count].port=port; strncpy(hostent_head[hostent_count].hostname, host, MAXHOST-1); hostent_head[hostent_count].hostname[MAXHOST-1] = '\0'; hostent_count++; } add_size:; p += size; } if (!hostent_head) goto out; qsort(hostent_head, hostent_count, sizeof(srv_record), srv_cmp); if (!srv_seed) srv_srand(time(0L)); /* shuffle records of same priority */ j = 0; priority = hostent_head[0].priority; for (i=1; i 1) srv_shuffle(hostent_head+j, i-j); j = i; } } if (i-j > 1) srv_shuffle(hostent_head+j, i-j); for(i=0; i0){ hostlist[cur++]=' '; } cur += sprintf(&hostlist[cur], "%s:%hu", hostent_head[i].hostname, hostent_head[i].port); } } if (hostlist == NULL) { /* No LDAP servers found in DNS. */ rc = LDAP_UNAVAILABLE; goto out; } rc = LDAP_SUCCESS; *list = hostlist; out: LDAP_MUTEX_UNLOCK(&ldap_int_resolv_mutex); if (request != NULL) { LDAP_FREE(request); } if (hostent_head != NULL) { LDAP_FREE(hostent_head); } if (rc != LDAP_SUCCESS && hostlist != NULL) { LDAP_FREE(hostlist); } return rc; #else return LDAP_NOT_SUPPORTED; #endif /* HAVE_RES_QUERY */ } openldap-2.4.42+dfsg/libraries/libldap/sbind.c0000644000175000017500000000523112563404150017657 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (c) 1993 Regents of the University of Michigan. * All rights reserved. */ /* * BindRequest ::= SEQUENCE { * version INTEGER, * name DistinguishedName, -- who * authentication CHOICE { * simple [0] OCTET STRING -- passwd * krbv42ldap [1] OCTET STRING -- OBSOLETE * krbv42dsa [2] OCTET STRING -- OBSOLETE * sasl [3] SaslCredentials -- LDAPv3 * } * } * * BindResponse ::= SEQUENCE { * COMPONENTS OF LDAPResult, * serverSaslCreds OCTET STRING OPTIONAL -- LDAPv3 * } * */ #include "portable.h" #include #include #include #include #include "ldap-int.h" /* * ldap_simple_bind - bind to the ldap server (and X.500). The dn and * password of the entry to which to bind are supplied. The message id * of the request initiated is returned. * * Example: * ldap_simple_bind( ld, "cn=manager, o=university of michigan, c=us", * "secret" ) */ int ldap_simple_bind( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *passwd ) { int rc; int msgid; struct berval cred; Debug( LDAP_DEBUG_TRACE, "ldap_simple_bind\n", 0, 0, 0 ); assert( ld != NULL ); assert( LDAP_VALID( ld ) ); if ( passwd != NULL ) { cred.bv_val = (char *) passwd; cred.bv_len = strlen( passwd ); } else { cred.bv_val = ""; cred.bv_len = 0; } rc = ldap_sasl_bind( ld, dn, LDAP_SASL_SIMPLE, &cred, NULL, NULL, &msgid ); return rc == LDAP_SUCCESS ? msgid : -1; } /* * ldap_simple_bind - bind to the ldap server (and X.500) using simple * authentication. The dn and password of the entry to which to bind are * supplied. LDAP_SUCCESS is returned upon success, the ldap error code * otherwise. * * Example: * ldap_simple_bind_s( ld, "cn=manager, o=university of michigan, c=us", * "secret" ) */ int ldap_simple_bind_s( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *passwd ) { struct berval cred; Debug( LDAP_DEBUG_TRACE, "ldap_simple_bind_s\n", 0, 0, 0 ); if ( passwd != NULL ) { cred.bv_val = (char *) passwd; cred.bv_len = strlen( passwd ); } else { cred.bv_val = ""; cred.bv_len = 0; } return ldap_sasl_bind_s( ld, dn, LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL ); } openldap-2.4.42+dfsg/libraries/libldap/schema.c0000644000175000017500000021654112563404150020030 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* * schema.c: parsing routines used by servers and clients to process * schema definitions */ #include "portable.h" #include #include #include #include #include "ldap-int.h" #include static const char EndOfInput[] = "end of input"; static const char * choose_name( char *names[], const char *fallback ) { return (names != NULL && names[0] != NULL) ? names[0] : fallback; } LDAP_CONST char * ldap_syntax2name( LDAPSyntax * syn ) { if (!syn) return NULL; return( syn->syn_oid ); } LDAP_CONST char * ldap_matchingrule2name( LDAPMatchingRule * mr ) { if (!mr) return NULL; return( choose_name( mr->mr_names, mr->mr_oid ) ); } LDAP_CONST char * ldap_matchingruleuse2name( LDAPMatchingRuleUse * mru ) { if (!mru) return NULL; return( choose_name( mru->mru_names, mru->mru_oid ) ); } LDAP_CONST char * ldap_attributetype2name( LDAPAttributeType * at ) { if (!at) return NULL; return( choose_name( at->at_names, at->at_oid ) ); } LDAP_CONST char * ldap_objectclass2name( LDAPObjectClass * oc ) { if (!oc) return NULL; return( choose_name( oc->oc_names, oc->oc_oid ) ); } LDAP_CONST char * ldap_contentrule2name( LDAPContentRule * cr ) { if (!cr) return NULL; return( choose_name( cr->cr_names, cr->cr_oid ) ); } LDAP_CONST char * ldap_nameform2name( LDAPNameForm * nf ) { if (!nf) return NULL; return( choose_name( nf->nf_names, nf->nf_oid ) ); } LDAP_CONST char * ldap_structurerule2name( LDAPStructureRule * sr ) { if (!sr) return NULL; return( choose_name( sr->sr_names, NULL ) ); } /* * When pretty printing the entities we will be appending to a buffer. * Since checking for overflow, realloc'ing and checking if no error * is extremely boring, we will use a protection layer that will let * us blissfully ignore the error until the end. This layer is * implemented with the help of the next type. */ typedef struct safe_string { char * val; ber_len_t size; ber_len_t pos; int at_whsp; } safe_string; static safe_string * new_safe_string(int size) { safe_string * ss; ss = LDAP_MALLOC(sizeof(safe_string)); if ( !ss ) return(NULL); ss->val = LDAP_MALLOC(size); if ( !ss->val ) { LDAP_FREE(ss); return(NULL); } ss->size = size; ss->pos = 0; ss->at_whsp = 0; return ss; } static void safe_string_free(safe_string * ss) { if ( !ss ) return; LDAP_FREE(ss->val); LDAP_FREE(ss); } #if 0 /* unused */ static char * safe_string_val(safe_string * ss) { ss->val[ss->pos] = '\0'; return(ss->val); } #endif static char * safe_strdup(safe_string * ss) { char *ret = LDAP_MALLOC(ss->pos+1); if (!ret) return NULL; AC_MEMCPY(ret, ss->val, ss->pos); ret[ss->pos] = '\0'; return ret; } static int append_to_safe_string(safe_string * ss, char * s) { int l = strlen(s); char * temp; /* * Some runaway process is trying to append to a string that * overflowed and we could not extend. */ if ( !ss->val ) return -1; /* We always make sure there is at least one position available */ if ( ss->pos + l >= ss->size-1 ) { ss->size *= 2; if ( ss->pos + l >= ss->size-1 ) { ss->size = ss->pos + l + 1; } temp = LDAP_REALLOC(ss->val, ss->size); if ( !temp ) { /* Trouble, out of memory */ LDAP_FREE(ss->val); return -1; } ss->val = temp; } strncpy(&ss->val[ss->pos], s, l); ss->pos += l; if ( ss->pos > 0 && LDAP_SPACE(ss->val[ss->pos-1]) ) ss->at_whsp = 1; else ss->at_whsp = 0; return 0; } static int print_literal(safe_string *ss, char *s) { return(append_to_safe_string(ss,s)); } static int print_whsp(safe_string *ss) { if ( ss->at_whsp ) return(append_to_safe_string(ss,"")); else return(append_to_safe_string(ss," ")); } static int print_numericoid(safe_string *ss, char *s) { if ( s ) return(append_to_safe_string(ss,s)); else return(append_to_safe_string(ss,"")); } /* This one is identical to print_qdescr */ static int print_qdstring(safe_string *ss, char *s) { print_whsp(ss); print_literal(ss,"'"); append_to_safe_string(ss,s); print_literal(ss,"'"); return(print_whsp(ss)); } static int print_qdescr(safe_string *ss, char *s) { print_whsp(ss); print_literal(ss,"'"); append_to_safe_string(ss,s); print_literal(ss,"'"); return(print_whsp(ss)); } static int print_qdescrlist(safe_string *ss, char **sa) { char **sp; int ret = 0; for (sp=sa; *sp; sp++) { ret = print_qdescr(ss,*sp); } /* If the list was empty, we return zero that is potentially * incorrect, but since we will be still appending things, the * overflow will be detected later. Maybe FIX. */ return(ret); } static int print_qdescrs(safe_string *ss, char **sa) { /* The only way to represent an empty list is as a qdescrlist * so, if the list is empty we treat it as a long list. * Really, this is what the syntax mandates. We should not * be here if the list was empty, but if it happens, a label * has already been output and we cannot undo it. */ if ( !sa[0] || ( sa[0] && sa[1] ) ) { print_whsp(ss); print_literal(ss,"("/*)*/); print_qdescrlist(ss,sa); print_literal(ss,/*(*/")"); return(print_whsp(ss)); } else { return(print_qdescr(ss,*sa)); } } static int print_woid(safe_string *ss, char *s) { print_whsp(ss); append_to_safe_string(ss,s); return print_whsp(ss); } static int print_oidlist(safe_string *ss, char **sa) { char **sp; for (sp=sa; *(sp+1); sp++) { print_woid(ss,*sp); print_literal(ss,"$"); } return(print_woid(ss,*sp)); } static int print_oids(safe_string *ss, char **sa) { if ( sa[0] && sa[1] ) { print_literal(ss,"("/*)*/); print_oidlist(ss,sa); print_whsp(ss); return(print_literal(ss,/*(*/")")); } else { return(print_woid(ss,*sa)); } } static int print_noidlen(safe_string *ss, char *s, int l) { char buf[64]; int ret; ret = print_numericoid(ss,s); if ( l ) { snprintf(buf, sizeof buf, "{%d}",l); ret = print_literal(ss,buf); } return(ret); } static int print_ruleid(safe_string *ss, int rid) { char buf[64]; snprintf(buf, sizeof buf, "%d", rid); return print_literal(ss,buf); } static int print_ruleids(safe_string *ss, int n, int *rids) { int i; if( n == 1 ) { print_ruleid(ss,rids[0]); return print_whsp(ss); } else { print_literal(ss,"("/*)*/); for( i=0; ilsei_name); print_whsp(ss); /* Should be print_qdstrings */ print_qdescrs(ss, (*ext)->lsei_values); print_whsp(ss); } } return 0; } char * ldap_syntax2str( LDAPSyntax * syn ) { struct berval bv; if (ldap_syntax2bv( syn, &bv )) return(bv.bv_val); else return NULL; } struct berval * ldap_syntax2bv( LDAPSyntax * syn, struct berval *bv ) { safe_string * ss; if ( !syn || !bv ) return NULL; ss = new_safe_string(256); if ( !ss ) return NULL; print_literal(ss,"("/*)*/); print_whsp(ss); print_numericoid(ss, syn->syn_oid); print_whsp(ss); if ( syn->syn_desc ) { print_literal(ss,"DESC"); print_qdstring(ss,syn->syn_desc); } print_whsp(ss); print_extensions(ss, syn->syn_extensions); print_literal(ss,/*(*/ ")"); bv->bv_val = safe_strdup(ss); bv->bv_len = ss->pos; safe_string_free(ss); return(bv); } char * ldap_matchingrule2str( LDAPMatchingRule * mr ) { struct berval bv; if (ldap_matchingrule2bv( mr, &bv )) return(bv.bv_val); else return NULL; } struct berval * ldap_matchingrule2bv( LDAPMatchingRule * mr, struct berval *bv ) { safe_string * ss; if ( !mr || !bv ) return NULL; ss = new_safe_string(256); if ( !ss ) return NULL; print_literal(ss,"(" /*)*/); print_whsp(ss); print_numericoid(ss, mr->mr_oid); print_whsp(ss); if ( mr->mr_names ) { print_literal(ss,"NAME"); print_qdescrs(ss,mr->mr_names); } if ( mr->mr_desc ) { print_literal(ss,"DESC"); print_qdstring(ss,mr->mr_desc); } if ( mr->mr_obsolete ) { print_literal(ss, "OBSOLETE"); print_whsp(ss); } if ( mr->mr_syntax_oid ) { print_literal(ss,"SYNTAX"); print_whsp(ss); print_literal(ss, mr->mr_syntax_oid); print_whsp(ss); } print_whsp(ss); print_extensions(ss, mr->mr_extensions); print_literal(ss,/*(*/")"); bv->bv_val = safe_strdup(ss); bv->bv_len = ss->pos; safe_string_free(ss); return(bv); } char * ldap_matchingruleuse2str( LDAPMatchingRuleUse * mru ) { struct berval bv; if (ldap_matchingruleuse2bv( mru, &bv )) return(bv.bv_val); else return NULL; } struct berval * ldap_matchingruleuse2bv( LDAPMatchingRuleUse * mru, struct berval *bv ) { safe_string * ss; if ( !mru || !bv ) return NULL; ss = new_safe_string(256); if ( !ss ) return NULL; print_literal(ss,"(" /*)*/); print_whsp(ss); print_numericoid(ss, mru->mru_oid); print_whsp(ss); if ( mru->mru_names ) { print_literal(ss,"NAME"); print_qdescrs(ss,mru->mru_names); } if ( mru->mru_desc ) { print_literal(ss,"DESC"); print_qdstring(ss,mru->mru_desc); } if ( mru->mru_obsolete ) { print_literal(ss, "OBSOLETE"); print_whsp(ss); } if ( mru->mru_applies_oids ) { print_literal(ss,"APPLIES"); print_whsp(ss); print_oids(ss, mru->mru_applies_oids); print_whsp(ss); } print_whsp(ss); print_extensions(ss, mru->mru_extensions); print_literal(ss,/*(*/")"); bv->bv_val = safe_strdup(ss); bv->bv_len = ss->pos; safe_string_free(ss); return(bv); } char * ldap_objectclass2str( LDAPObjectClass * oc ) { struct berval bv; if (ldap_objectclass2bv( oc, &bv )) return(bv.bv_val); else return NULL; } struct berval * ldap_objectclass2bv( LDAPObjectClass * oc, struct berval *bv ) { safe_string * ss; if ( !oc || !bv ) return NULL; ss = new_safe_string(256); if ( !ss ) return NULL; print_literal(ss,"("/*)*/); print_whsp(ss); print_numericoid(ss, oc->oc_oid); print_whsp(ss); if ( oc->oc_names ) { print_literal(ss,"NAME"); print_qdescrs(ss,oc->oc_names); } if ( oc->oc_desc ) { print_literal(ss,"DESC"); print_qdstring(ss,oc->oc_desc); } if ( oc->oc_obsolete ) { print_literal(ss, "OBSOLETE"); print_whsp(ss); } if ( oc->oc_sup_oids ) { print_literal(ss,"SUP"); print_whsp(ss); print_oids(ss,oc->oc_sup_oids); print_whsp(ss); } switch (oc->oc_kind) { case LDAP_SCHEMA_ABSTRACT: print_literal(ss,"ABSTRACT"); break; case LDAP_SCHEMA_STRUCTURAL: print_literal(ss,"STRUCTURAL"); break; case LDAP_SCHEMA_AUXILIARY: print_literal(ss,"AUXILIARY"); break; default: print_literal(ss,"KIND-UNKNOWN"); break; } print_whsp(ss); if ( oc->oc_at_oids_must ) { print_literal(ss,"MUST"); print_whsp(ss); print_oids(ss,oc->oc_at_oids_must); print_whsp(ss); } if ( oc->oc_at_oids_may ) { print_literal(ss,"MAY"); print_whsp(ss); print_oids(ss,oc->oc_at_oids_may); print_whsp(ss); } print_whsp(ss); print_extensions(ss, oc->oc_extensions); print_literal(ss, /*(*/")"); bv->bv_val = safe_strdup(ss); bv->bv_len = ss->pos; safe_string_free(ss); return(bv); } char * ldap_contentrule2str( LDAPContentRule * cr ) { struct berval bv; if (ldap_contentrule2bv( cr, &bv )) return(bv.bv_val); else return NULL; } struct berval * ldap_contentrule2bv( LDAPContentRule * cr, struct berval *bv ) { safe_string * ss; if ( !cr || !bv ) return NULL; ss = new_safe_string(256); if ( !ss ) return NULL; print_literal(ss,"("/*)*/); print_whsp(ss); print_numericoid(ss, cr->cr_oid); print_whsp(ss); if ( cr->cr_names ) { print_literal(ss,"NAME"); print_qdescrs(ss,cr->cr_names); } if ( cr->cr_desc ) { print_literal(ss,"DESC"); print_qdstring(ss,cr->cr_desc); } if ( cr->cr_obsolete ) { print_literal(ss, "OBSOLETE"); print_whsp(ss); } if ( cr->cr_oc_oids_aux ) { print_literal(ss,"AUX"); print_whsp(ss); print_oids(ss,cr->cr_oc_oids_aux); print_whsp(ss); } if ( cr->cr_at_oids_must ) { print_literal(ss,"MUST"); print_whsp(ss); print_oids(ss,cr->cr_at_oids_must); print_whsp(ss); } if ( cr->cr_at_oids_may ) { print_literal(ss,"MAY"); print_whsp(ss); print_oids(ss,cr->cr_at_oids_may); print_whsp(ss); } if ( cr->cr_at_oids_not ) { print_literal(ss,"NOT"); print_whsp(ss); print_oids(ss,cr->cr_at_oids_not); print_whsp(ss); } print_whsp(ss); print_extensions(ss, cr->cr_extensions); print_literal(ss, /*(*/")"); bv->bv_val = safe_strdup(ss); bv->bv_len = ss->pos; safe_string_free(ss); return(bv); } char * ldap_structurerule2str( LDAPStructureRule * sr ) { struct berval bv; if (ldap_structurerule2bv( sr, &bv )) return(bv.bv_val); else return NULL; } struct berval * ldap_structurerule2bv( LDAPStructureRule * sr, struct berval *bv ) { safe_string * ss; if ( !sr || !bv ) return NULL; ss = new_safe_string(256); if ( !ss ) return NULL; print_literal(ss,"("/*)*/); print_whsp(ss); print_ruleid(ss, sr->sr_ruleid); print_whsp(ss); if ( sr->sr_names ) { print_literal(ss,"NAME"); print_qdescrs(ss,sr->sr_names); } if ( sr->sr_desc ) { print_literal(ss,"DESC"); print_qdstring(ss,sr->sr_desc); } if ( sr->sr_obsolete ) { print_literal(ss, "OBSOLETE"); print_whsp(ss); } print_literal(ss,"FORM"); print_whsp(ss); print_woid(ss,sr->sr_nameform); print_whsp(ss); if ( sr->sr_nsup_ruleids ) { print_literal(ss,"SUP"); print_whsp(ss); print_ruleids(ss,sr->sr_nsup_ruleids,sr->sr_sup_ruleids); print_whsp(ss); } print_whsp(ss); print_extensions(ss, sr->sr_extensions); print_literal(ss, /*(*/")"); bv->bv_val = safe_strdup(ss); bv->bv_len = ss->pos; safe_string_free(ss); return(bv); } char * ldap_nameform2str( LDAPNameForm * nf ) { struct berval bv; if (ldap_nameform2bv( nf, &bv )) return(bv.bv_val); else return NULL; } struct berval * ldap_nameform2bv( LDAPNameForm * nf, struct berval *bv ) { safe_string * ss; if ( !nf || !bv ) return NULL; ss = new_safe_string(256); if ( !ss ) return NULL; print_literal(ss,"("/*)*/); print_whsp(ss); print_numericoid(ss, nf->nf_oid); print_whsp(ss); if ( nf->nf_names ) { print_literal(ss,"NAME"); print_qdescrs(ss,nf->nf_names); } if ( nf->nf_desc ) { print_literal(ss,"DESC"); print_qdstring(ss,nf->nf_desc); } if ( nf->nf_obsolete ) { print_literal(ss, "OBSOLETE"); print_whsp(ss); } print_literal(ss,"OC"); print_whsp(ss); print_woid(ss,nf->nf_objectclass); print_whsp(ss); print_literal(ss,"MUST"); print_whsp(ss); print_oids(ss,nf->nf_at_oids_must); print_whsp(ss); if ( nf->nf_at_oids_may ) { print_literal(ss,"MAY"); print_whsp(ss); print_oids(ss,nf->nf_at_oids_may); print_whsp(ss); } print_whsp(ss); print_extensions(ss, nf->nf_extensions); print_literal(ss, /*(*/")"); bv->bv_val = safe_strdup(ss); bv->bv_len = ss->pos; safe_string_free(ss); return(bv); } char * ldap_attributetype2str( LDAPAttributeType * at ) { struct berval bv; if (ldap_attributetype2bv( at, &bv )) return(bv.bv_val); else return NULL; } struct berval * ldap_attributetype2bv( LDAPAttributeType * at, struct berval *bv ) { safe_string * ss; if ( !at || !bv ) return NULL; ss = new_safe_string(256); if ( !ss ) return NULL; print_literal(ss,"("/*)*/); print_whsp(ss); print_numericoid(ss, at->at_oid); print_whsp(ss); if ( at->at_names ) { print_literal(ss,"NAME"); print_qdescrs(ss,at->at_names); } if ( at->at_desc ) { print_literal(ss,"DESC"); print_qdstring(ss,at->at_desc); } if ( at->at_obsolete ) { print_literal(ss, "OBSOLETE"); print_whsp(ss); } if ( at->at_sup_oid ) { print_literal(ss,"SUP"); print_woid(ss,at->at_sup_oid); } if ( at->at_equality_oid ) { print_literal(ss,"EQUALITY"); print_woid(ss,at->at_equality_oid); } if ( at->at_ordering_oid ) { print_literal(ss,"ORDERING"); print_woid(ss,at->at_ordering_oid); } if ( at->at_substr_oid ) { print_literal(ss,"SUBSTR"); print_woid(ss,at->at_substr_oid); } if ( at->at_syntax_oid ) { print_literal(ss,"SYNTAX"); print_whsp(ss); print_noidlen(ss,at->at_syntax_oid,at->at_syntax_len); print_whsp(ss); } if ( at->at_single_value == LDAP_SCHEMA_YES ) { print_literal(ss,"SINGLE-VALUE"); print_whsp(ss); } if ( at->at_collective == LDAP_SCHEMA_YES ) { print_literal(ss,"COLLECTIVE"); print_whsp(ss); } if ( at->at_no_user_mod == LDAP_SCHEMA_YES ) { print_literal(ss,"NO-USER-MODIFICATION"); print_whsp(ss); } if ( at->at_usage != LDAP_SCHEMA_USER_APPLICATIONS ) { print_literal(ss,"USAGE"); print_whsp(ss); switch (at->at_usage) { case LDAP_SCHEMA_DIRECTORY_OPERATION: print_literal(ss,"directoryOperation"); break; case LDAP_SCHEMA_DISTRIBUTED_OPERATION: print_literal(ss,"distributedOperation"); break; case LDAP_SCHEMA_DSA_OPERATION: print_literal(ss,"dSAOperation"); break; default: print_literal(ss,"UNKNOWN"); break; } } print_whsp(ss); print_extensions(ss, at->at_extensions); print_literal(ss,/*(*/")"); bv->bv_val = safe_strdup(ss); bv->bv_len = ss->pos; safe_string_free(ss); return(bv); } /* * Now come the parsers. There is one parser for each entity type: * objectclasses, attributetypes, etc. * * Each of them is written as a recursive-descent parser, except that * none of them is really recursive. But the idea is kept: there * is one routine per non-terminal that eithers gobbles lexical tokens * or calls lower-level routines, etc. * * The scanner is implemented in the routine get_token. Actually, * get_token is more than a scanner and will return tokens that are * in fact non-terminals in the grammar. So you can see the whole * approach as the combination of a low-level bottom-up recognizer * combined with a scanner and a number of top-down parsers. Or just * consider that the real grammars recognized by the parsers are not * those of the standards. As a matter of fact, our parsers are more * liberal than the spec when there is no ambiguity. * * The difference is pretty academic (modulo bugs or incorrect * interpretation of the specs). */ typedef enum tk_t { TK_NOENDQUOTE = -2, TK_OUTOFMEM = -1, TK_EOS = 0, TK_UNEXPCHAR = 1, TK_BAREWORD = 2, TK_QDSTRING = 3, TK_LEFTPAREN = 4, TK_RIGHTPAREN = 5, TK_DOLLAR = 6, TK_QDESCR = TK_QDSTRING } tk_t; static tk_t get_token( const char ** sp, char ** token_val ) { tk_t kind; const char * p; const char * q; char * res; *token_val = NULL; switch (**sp) { case '\0': kind = TK_EOS; (*sp)++; break; case '(': kind = TK_LEFTPAREN; (*sp)++; break; case ')': kind = TK_RIGHTPAREN; (*sp)++; break; case '$': kind = TK_DOLLAR; (*sp)++; break; case '\'': kind = TK_QDSTRING; (*sp)++; p = *sp; while ( **sp != '\'' && **sp != '\0' ) (*sp)++; if ( **sp == '\'' ) { q = *sp; res = LDAP_MALLOC(q-p+1); if ( !res ) { kind = TK_OUTOFMEM; } else { strncpy(res,p,q-p); res[q-p] = '\0'; *token_val = res; } (*sp)++; } else { kind = TK_NOENDQUOTE; } break; default: kind = TK_BAREWORD; p = *sp; while ( !LDAP_SPACE(**sp) && **sp != '(' && **sp != ')' && **sp != '$' && **sp != '\'' && /* for suggested minimum upper bound on the number * of characters (RFC 4517) */ **sp != '{' && **sp != '\0' ) (*sp)++; q = *sp; res = LDAP_MALLOC(q-p+1); if ( !res ) { kind = TK_OUTOFMEM; } else { strncpy(res,p,q-p); res[q-p] = '\0'; *token_val = res; } break; /* kind = TK_UNEXPCHAR; */ /* break; */ } return kind; } /* Gobble optional whitespace */ static void parse_whsp(const char **sp) { while (LDAP_SPACE(**sp)) (*sp)++; } /* TBC:!! * General note for all parsers: to guarantee the algorithm halts they * must always advance the pointer even when an error is found. For * this one is not that important since an error here is fatal at the * upper layers, but it is a simple strategy that will not get in * endless loops. */ /* Parse a sequence of dot-separated decimal strings */ char * ldap_int_parse_numericoid(const char **sp, int *code, const int flags) { char * res = NULL; const char * start = *sp; int len; int quoted = 0; /* Netscape puts the SYNTAX value in quotes (incorrectly) */ if ( flags & LDAP_SCHEMA_ALLOW_QUOTED && **sp == '\'' ) { quoted = 1; (*sp)++; start++; } /* Each iteration of this loop gets one decimal string */ while (**sp) { if ( !LDAP_DIGIT(**sp) ) { /* * Initial char is not a digit or char after dot is * not a digit */ *code = LDAP_SCHERR_NODIGIT; return NULL; } (*sp)++; while ( LDAP_DIGIT(**sp) ) (*sp)++; if ( **sp != '.' ) break; /* Otherwise, gobble the dot and loop again */ (*sp)++; } /* Now *sp points at the char past the numericoid. Perfect. */ len = *sp - start; if ( flags & LDAP_SCHEMA_ALLOW_QUOTED && quoted ) { if ( **sp == '\'' ) { (*sp)++; } else { *code = LDAP_SCHERR_UNEXPTOKEN; return NULL; } } if (flags & LDAP_SCHEMA_SKIP) { res = (char *)start; } else { res = LDAP_MALLOC(len+1); if (!res) { *code = LDAP_SCHERR_OUTOFMEM; return(NULL); } strncpy(res,start,len); res[len] = '\0'; } return(res); } /* Parse a sequence of dot-separated decimal strings */ int ldap_int_parse_ruleid(const char **sp, int *code, const int flags, int *ruleid) { *ruleid=0; if ( !LDAP_DIGIT(**sp) ) { *code = LDAP_SCHERR_NODIGIT; return -1; } *ruleid = (**sp) - '0'; (*sp)++; while ( LDAP_DIGIT(**sp) ) { *ruleid *= 10; *ruleid += (**sp) - '0'; (*sp)++; } return 0; } /* Parse a qdescr or a list of them enclosed in () */ static char ** parse_qdescrs(const char **sp, int *code) { char ** res; char ** res1; tk_t kind; char * sval; int size; int pos; parse_whsp(sp); kind = get_token(sp,&sval); if ( kind == TK_LEFTPAREN ) { /* Let's presume there will be at least 2 entries */ size = 3; res = LDAP_CALLOC(3,sizeof(char *)); if ( !res ) { *code = LDAP_SCHERR_OUTOFMEM; return NULL; } pos = 0; while (1) { parse_whsp(sp); kind = get_token(sp,&sval); if ( kind == TK_RIGHTPAREN ) break; if ( kind == TK_QDESCR ) { if ( pos == size-2 ) { size++; res1 = LDAP_REALLOC(res,size*sizeof(char *)); if ( !res1 ) { LDAP_VFREE(res); LDAP_FREE(sval); *code = LDAP_SCHERR_OUTOFMEM; return(NULL); } res = res1; } res[pos++] = sval; res[pos] = NULL; parse_whsp(sp); } else { LDAP_VFREE(res); LDAP_FREE(sval); *code = LDAP_SCHERR_UNEXPTOKEN; return(NULL); } } parse_whsp(sp); return(res); } else if ( kind == TK_QDESCR ) { res = LDAP_CALLOC(2,sizeof(char *)); if ( !res ) { *code = LDAP_SCHERR_OUTOFMEM; return NULL; } res[0] = sval; res[1] = NULL; parse_whsp(sp); return res; } else { LDAP_FREE(sval); *code = LDAP_SCHERR_BADNAME; return NULL; } } /* Parse a woid */ static char * parse_woid(const char **sp, int *code) { char * sval; tk_t kind; parse_whsp(sp); kind = get_token(sp, &sval); if ( kind != TK_BAREWORD ) { LDAP_FREE(sval); *code = LDAP_SCHERR_UNEXPTOKEN; return NULL; } parse_whsp(sp); return sval; } /* Parse a noidlen */ static char * parse_noidlen(const char **sp, int *code, int *len, int flags) { char * sval; const char *savepos; int quoted = 0; int allow_quoted = ( flags & LDAP_SCHEMA_ALLOW_QUOTED ); int allow_oidmacro = ( flags & LDAP_SCHEMA_ALLOW_OID_MACRO ); *len = 0; /* Netscape puts the SYNTAX value in quotes (incorrectly) */ if ( allow_quoted && **sp == '\'' ) { quoted = 1; (*sp)++; } savepos = *sp; sval = ldap_int_parse_numericoid(sp, code, 0); if ( !sval ) { if ( allow_oidmacro && *sp == savepos && *code == LDAP_SCHERR_NODIGIT ) { if ( get_token(sp, &sval) != TK_BAREWORD ) { if ( sval != NULL ) { LDAP_FREE(sval); } return NULL; } } else { return NULL; } } if ( **sp == '{' /*}*/ ) { (*sp)++; *len = atoi(*sp); while ( LDAP_DIGIT(**sp) ) (*sp)++; if ( **sp != /*{*/ '}' ) { *code = LDAP_SCHERR_UNEXPTOKEN; LDAP_FREE(sval); return NULL; } (*sp)++; } if ( allow_quoted && quoted ) { if ( **sp == '\'' ) { (*sp)++; } else { *code = LDAP_SCHERR_UNEXPTOKEN; LDAP_FREE(sval); return NULL; } } return sval; } /* * Next routine will accept a qdstring in place of an oid if * allow_quoted is set. This is necessary to interoperate with * Netscape Directory server that will improperly quote each oid (at * least those of the descr kind) in the SUP clause. */ /* Parse a woid or a $-separated list of them enclosed in () */ static char ** parse_oids(const char **sp, int *code, const int allow_quoted) { char ** res; char ** res1; tk_t kind; char * sval; int size; int pos; /* * Strictly speaking, doing this here accepts whsp before the * ( at the begining of an oidlist, but this is harmless. Also, * we are very liberal in what we accept as an OID. Maybe * refine later. */ parse_whsp(sp); kind = get_token(sp,&sval); if ( kind == TK_LEFTPAREN ) { /* Let's presume there will be at least 2 entries */ size = 3; res = LDAP_CALLOC(3,sizeof(char *)); if ( !res ) { *code = LDAP_SCHERR_OUTOFMEM; return NULL; } pos = 0; parse_whsp(sp); kind = get_token(sp,&sval); if ( kind == TK_BAREWORD || ( allow_quoted && kind == TK_QDSTRING ) ) { res[pos++] = sval; res[pos] = NULL; } else if ( kind == TK_RIGHTPAREN ) { /* FIXME: be liberal in what we accept... */ parse_whsp(sp); LDAP_FREE(res); return NULL; } else { *code = LDAP_SCHERR_UNEXPTOKEN; LDAP_FREE(sval); LDAP_VFREE(res); return NULL; } parse_whsp(sp); while (1) { kind = get_token(sp,&sval); if ( kind == TK_RIGHTPAREN ) break; if ( kind == TK_DOLLAR ) { parse_whsp(sp); kind = get_token(sp,&sval); if ( kind == TK_BAREWORD || ( allow_quoted && kind == TK_QDSTRING ) ) { if ( pos == size-2 ) { size++; res1 = LDAP_REALLOC(res,size*sizeof(char *)); if ( !res1 ) { LDAP_FREE(sval); LDAP_VFREE(res); *code = LDAP_SCHERR_OUTOFMEM; return(NULL); } res = res1; } res[pos++] = sval; res[pos] = NULL; } else { *code = LDAP_SCHERR_UNEXPTOKEN; LDAP_FREE(sval); LDAP_VFREE(res); return NULL; } parse_whsp(sp); } else { *code = LDAP_SCHERR_UNEXPTOKEN; LDAP_FREE(sval); LDAP_VFREE(res); return NULL; } } parse_whsp(sp); return(res); } else if ( kind == TK_BAREWORD || ( allow_quoted && kind == TK_QDSTRING ) ) { res = LDAP_CALLOC(2,sizeof(char *)); if ( !res ) { LDAP_FREE(sval); *code = LDAP_SCHERR_OUTOFMEM; return NULL; } res[0] = sval; res[1] = NULL; parse_whsp(sp); return res; } else { LDAP_FREE(sval); *code = LDAP_SCHERR_BADNAME; return NULL; } } static int add_extension(LDAPSchemaExtensionItem ***extensions, char * name, char ** values) { int n; LDAPSchemaExtensionItem **tmp, *ext; ext = LDAP_CALLOC(1, sizeof(LDAPSchemaExtensionItem)); if ( !ext ) return 1; ext->lsei_name = name; ext->lsei_values = values; if ( !*extensions ) { *extensions = LDAP_CALLOC(2, sizeof(LDAPSchemaExtensionItem *)); if ( !*extensions ) { LDAP_FREE( ext ); return 1; } n = 0; } else { for ( n=0; (*extensions)[n] != NULL; n++ ) ; tmp = LDAP_REALLOC(*extensions, (n+2)*sizeof(LDAPSchemaExtensionItem *)); if ( !tmp ) { LDAP_FREE( ext ); return 1; } *extensions = tmp; } (*extensions)[n] = ext; (*extensions)[n+1] = NULL; return 0; } static void free_extensions(LDAPSchemaExtensionItem **extensions) { LDAPSchemaExtensionItem **ext; if ( extensions ) { for ( ext = extensions; *ext != NULL; ext++ ) { LDAP_FREE((*ext)->lsei_name); LDAP_VFREE((*ext)->lsei_values); LDAP_FREE(*ext); } LDAP_FREE(extensions); } } void ldap_syntax_free( LDAPSyntax * syn ) { if ( !syn ) return; LDAP_FREE(syn->syn_oid); if (syn->syn_names) LDAP_VFREE(syn->syn_names); if (syn->syn_desc) LDAP_FREE(syn->syn_desc); free_extensions(syn->syn_extensions); LDAP_FREE(syn); } LDAPSyntax * ldap_str2syntax( LDAP_CONST char * s, int * code, LDAP_CONST char ** errp, LDAP_CONST unsigned flags ) { tk_t kind; const char * ss = s; char * sval; int seen_name = 0; int seen_desc = 0; LDAPSyntax * syn; char ** ext_vals; if ( !s ) { *code = LDAP_SCHERR_EMPTY; *errp = ""; return NULL; } *errp = s; syn = LDAP_CALLOC(1,sizeof(LDAPSyntax)); if ( !syn ) { *code = LDAP_SCHERR_OUTOFMEM; return NULL; } kind = get_token(&ss,&sval); if ( kind != TK_LEFTPAREN ) { LDAP_FREE(sval); *code = LDAP_SCHERR_NOLEFTPAREN; ldap_syntax_free(syn); return NULL; } parse_whsp(&ss); syn->syn_oid = ldap_int_parse_numericoid(&ss,code,0); if ( !syn->syn_oid ) { *errp = ss; ldap_syntax_free(syn); return NULL; } parse_whsp(&ss); /* * Beyond this point we will be liberal and accept the items * in any order. */ while (1) { kind = get_token(&ss,&sval); switch (kind) { case TK_EOS: *code = LDAP_SCHERR_NORIGHTPAREN; *errp = EndOfInput; ldap_syntax_free(syn); return NULL; case TK_RIGHTPAREN: return syn; case TK_BAREWORD: if ( !strcasecmp(sval,"NAME") ) { LDAP_FREE(sval); if ( seen_name ) { *code = LDAP_SCHERR_DUPOPT; *errp = ss; ldap_syntax_free(syn); return(NULL); } seen_name = 1; syn->syn_names = parse_qdescrs(&ss,code); if ( !syn->syn_names ) { if ( *code != LDAP_SCHERR_OUTOFMEM ) *code = LDAP_SCHERR_BADNAME; *errp = ss; ldap_syntax_free(syn); return NULL; } } else if ( !strcasecmp(sval,"DESC") ) { LDAP_FREE(sval); if ( seen_desc ) { *code = LDAP_SCHERR_DUPOPT; *errp = ss; ldap_syntax_free(syn); return(NULL); } seen_desc = 1; parse_whsp(&ss); kind = get_token(&ss,&sval); if ( kind != TK_QDSTRING ) { *code = LDAP_SCHERR_UNEXPTOKEN; *errp = ss; LDAP_FREE(sval); ldap_syntax_free(syn); return NULL; } syn->syn_desc = sval; parse_whsp(&ss); } else if ( sval[0] == 'X' && sval[1] == '-' ) { /* Should be parse_qdstrings */ ext_vals = parse_qdescrs(&ss, code); if ( !ext_vals ) { *errp = ss; ldap_syntax_free(syn); return NULL; } if ( add_extension(&syn->syn_extensions, sval, ext_vals) ) { *code = LDAP_SCHERR_OUTOFMEM; *errp = ss; LDAP_FREE(sval); ldap_syntax_free(syn); return NULL; } } else { *code = LDAP_SCHERR_UNEXPTOKEN; *errp = ss; LDAP_FREE(sval); ldap_syntax_free(syn); return NULL; } break; default: *code = LDAP_SCHERR_UNEXPTOKEN; *errp = ss; LDAP_FREE(sval); ldap_syntax_free(syn); return NULL; } } } void ldap_matchingrule_free( LDAPMatchingRule * mr ) { if (!mr) return; LDAP_FREE(mr->mr_oid); if (mr->mr_names) LDAP_VFREE(mr->mr_names); if (mr->mr_desc) LDAP_FREE(mr->mr_desc); if (mr->mr_syntax_oid) LDAP_FREE(mr->mr_syntax_oid); free_extensions(mr->mr_extensions); LDAP_FREE(mr); } LDAPMatchingRule * ldap_str2matchingrule( LDAP_CONST char * s, int * code, LDAP_CONST char ** errp, LDAP_CONST unsigned flags ) { tk_t kind; const char * ss = s; char * sval; int seen_name = 0; int seen_desc = 0; int seen_obsolete = 0; int seen_syntax = 0; LDAPMatchingRule * mr; char ** ext_vals; const char * savepos; if ( !s ) { *code = LDAP_SCHERR_EMPTY; *errp = ""; return NULL; } *errp = s; mr = LDAP_CALLOC(1,sizeof(LDAPMatchingRule)); if ( !mr ) { *code = LDAP_SCHERR_OUTOFMEM; return NULL; } kind = get_token(&ss,&sval); if ( kind != TK_LEFTPAREN ) { *code = LDAP_SCHERR_NOLEFTPAREN; LDAP_FREE(sval); ldap_matchingrule_free(mr); return NULL; } parse_whsp(&ss); savepos = ss; mr->mr_oid = ldap_int_parse_numericoid(&ss,code,flags); if ( !mr->mr_oid ) { if ( flags & LDAP_SCHEMA_ALLOW_NO_OID ) { /* Backtracking */ ss = savepos; kind = get_token(&ss,&sval); if ( kind == TK_BAREWORD ) { if ( !strcasecmp(sval, "NAME") || !strcasecmp(sval, "DESC") || !strcasecmp(sval, "OBSOLETE") || !strcasecmp(sval, "SYNTAX") || !strncasecmp(sval, "X-", 2) ) { /* Missing OID, backtrack */ ss = savepos; } else { /* Non-numerical OID, ignore */ } } LDAP_FREE(sval); } else { *errp = ss; ldap_matchingrule_free(mr); return NULL; } } parse_whsp(&ss); /* * Beyond this point we will be liberal and accept the items * in any order. */ while (1) { kind = get_token(&ss,&sval); switch (kind) { case TK_EOS: *code = LDAP_SCHERR_NORIGHTPAREN; *errp = EndOfInput; ldap_matchingrule_free(mr); return NULL; case TK_RIGHTPAREN: if( !seen_syntax ) { *code = LDAP_SCHERR_MISSING; ldap_matchingrule_free(mr); return NULL; } return mr; case TK_BAREWORD: if ( !strcasecmp(sval,"NAME") ) { LDAP_FREE(sval); if ( seen_name ) { *code = LDAP_SCHERR_DUPOPT; *errp = ss; ldap_matchingrule_free(mr); return(NULL); } seen_name = 1; mr->mr_names = parse_qdescrs(&ss,code); if ( !mr->mr_names ) { if ( *code != LDAP_SCHERR_OUTOFMEM ) *code = LDAP_SCHERR_BADNAME; *errp = ss; ldap_matchingrule_free(mr); return NULL; } } else if ( !strcasecmp(sval,"DESC") ) { LDAP_FREE(sval); if ( seen_desc ) { *code = LDAP_SCHERR_DUPOPT; *errp = ss; ldap_matchingrule_free(mr); return(NULL); } seen_desc = 1; parse_whsp(&ss); kind = get_token(&ss,&sval); if ( kind != TK_QDSTRING ) { *code = LDAP_SCHERR_UNEXPTOKEN; *errp = ss; LDAP_FREE(sval); ldap_matchingrule_free(mr); return NULL; } mr->mr_desc = sval; parse_whsp(&ss); } else if ( !strcasecmp(sval,"OBSOLETE") ) { LDAP_FREE(sval); if ( seen_obsolete ) { *code = LDAP_SCHERR_DUPOPT; *errp = ss; ldap_matchingrule_free(mr); return(NULL); } seen_obsolete = 1; mr->mr_obsolete = LDAP_SCHEMA_YES; parse_whsp(&ss); } else if ( !strcasecmp(sval,"SYNTAX") ) { LDAP_FREE(sval); if ( seen_syntax ) { *code = LDAP_SCHERR_DUPOPT; *errp = ss; ldap_matchingrule_free(mr); return(NULL); } seen_syntax = 1; parse_whsp(&ss); mr->mr_syntax_oid = ldap_int_parse_numericoid(&ss,code,flags); if ( !mr->mr_syntax_oid ) { *errp = ss; ldap_matchingrule_free(mr); return NULL; } parse_whsp(&ss); } else if ( sval[0] == 'X' && sval[1] == '-' ) { /* Should be parse_qdstrings */ ext_vals = parse_qdescrs(&ss, code); if ( !ext_vals ) { *errp = ss; ldap_matchingrule_free(mr); return NULL; } if ( add_extension(&mr->mr_extensions, sval, ext_vals) ) { *code = LDAP_SCHERR_OUTOFMEM; *errp = ss; LDAP_FREE(sval); ldap_matchingrule_free(mr); return NULL; } } else { *code = LDAP_SCHERR_UNEXPTOKEN; *errp = ss; LDAP_FREE(sval); ldap_matchingrule_free(mr); return NULL; } break; default: *code = LDAP_SCHERR_UNEXPTOKEN; *errp = ss; LDAP_FREE(sval); ldap_matchingrule_free(mr); return NULL; } } } void ldap_matchingruleuse_free( LDAPMatchingRuleUse * mru ) { if (!mru) return; LDAP_FREE(mru->mru_oid); if (mru->mru_names) LDAP_VFREE(mru->mru_names); if (mru->mru_desc) LDAP_FREE(mru->mru_desc); if (mru->mru_applies_oids) LDAP_VFREE(mru->mru_applies_oids); free_extensions(mru->mru_extensions); LDAP_FREE(mru); } LDAPMatchingRuleUse * ldap_str2matchingruleuse( LDAP_CONST char * s, int * code, LDAP_CONST char ** errp, LDAP_CONST unsigned flags ) { tk_t kind; const char * ss = s; char * sval; int seen_name = 0; int seen_desc = 0; int seen_obsolete = 0; int seen_applies = 0; LDAPMatchingRuleUse * mru; char ** ext_vals; const char * savepos; if ( !s ) { *code = LDAP_SCHERR_EMPTY; *errp = ""; return NULL; } *errp = s; mru = LDAP_CALLOC(1,sizeof(LDAPMatchingRuleUse)); if ( !mru ) { *code = LDAP_SCHERR_OUTOFMEM; return NULL; } kind = get_token(&ss,&sval); if ( kind != TK_LEFTPAREN ) { *code = LDAP_SCHERR_NOLEFTPAREN; LDAP_FREE(sval); ldap_matchingruleuse_free(mru); return NULL; } parse_whsp(&ss); savepos = ss; mru->mru_oid = ldap_int_parse_numericoid(&ss,code,flags); if ( !mru->mru_oid ) { if ( flags & LDAP_SCHEMA_ALLOW_NO_OID ) { /* Backtracking */ ss = savepos; kind = get_token(&ss,&sval); if ( kind == TK_BAREWORD ) { if ( !strcasecmp(sval, "NAME") || !strcasecmp(sval, "DESC") || !strcasecmp(sval, "OBSOLETE") || !strcasecmp(sval, "APPLIES") || !strncasecmp(sval, "X-", 2) ) { /* Missing OID, backtrack */ ss = savepos; } else { /* Non-numerical OID, ignore */ } } LDAP_FREE(sval); } else { *errp = ss; ldap_matchingruleuse_free(mru); return NULL; } } parse_whsp(&ss); /* * Beyond this point we will be liberal and accept the items * in any order. */ while (1) { kind = get_token(&ss,&sval); switch (kind) { case TK_EOS: *code = LDAP_SCHERR_NORIGHTPAREN; *errp = EndOfInput; ldap_matchingruleuse_free(mru); return NULL; case TK_RIGHTPAREN: if( !seen_applies ) { *code = LDAP_SCHERR_MISSING; ldap_matchingruleuse_free(mru); return NULL; } return mru; case TK_BAREWORD: if ( !strcasecmp(sval,"NAME") ) { LDAP_FREE(sval); if ( seen_name ) { *code = LDAP_SCHERR_DUPOPT; *errp = ss; ldap_matchingruleuse_free(mru); return(NULL); } seen_name = 1; mru->mru_names = parse_qdescrs(&ss,code); if ( !mru->mru_names ) { if ( *code != LDAP_SCHERR_OUTOFMEM ) *code = LDAP_SCHERR_BADNAME; *errp = ss; ldap_matchingruleuse_free(mru); return NULL; } } else if ( !strcasecmp(sval,"DESC") ) { LDAP_FREE(sval); if ( seen_desc ) { *code = LDAP_SCHERR_DUPOPT; *errp = ss; ldap_matchingruleuse_free(mru); return(NULL); } seen_desc = 1; parse_whsp(&ss); kind = get_token(&ss,&sval); if ( kind != TK_QDSTRING ) { *code = LDAP_SCHERR_UNEXPTOKEN; *errp = ss; LDAP_FREE(sval); ldap_matchingruleuse_free(mru); return NULL; } mru->mru_desc = sval; parse_whsp(&ss); } else if ( !strcasecmp(sval,"OBSOLETE") ) { LDAP_FREE(sval); if ( seen_obsolete ) { *code = LDAP_SCHERR_DUPOPT; *errp = ss; ldap_matchingruleuse_free(mru); return(NULL); } seen_obsolete = 1; mru->mru_obsolete = LDAP_SCHEMA_YES; parse_whsp(&ss); } else if ( !strcasecmp(sval,"APPLIES") ) { LDAP_FREE(sval); if ( seen_applies ) { *code = LDAP_SCHERR_DUPOPT; *errp = ss; ldap_matchingruleuse_free(mru); return(NULL); } seen_applies = 1; mru->mru_applies_oids = parse_oids(&ss, code, flags); if ( !mru->mru_applies_oids && *code != LDAP_SUCCESS ) { *errp = ss; ldap_matchingruleuse_free(mru); return NULL; } } else if ( sval[0] == 'X' && sval[1] == '-' ) { /* Should be parse_qdstrings */ ext_vals = parse_qdescrs(&ss, code); if ( !ext_vals ) { *errp = ss; ldap_matchingruleuse_free(mru); return NULL; } if ( add_extension(&mru->mru_extensions, sval, ext_vals) ) { *code = LDAP_SCHERR_OUTOFMEM; *errp = ss; LDAP_FREE(sval); ldap_matchingruleuse_free(mru); return NULL; } } else { *code = LDAP_SCHERR_UNEXPTOKEN; *errp = ss; LDAP_FREE(sval); ldap_matchingruleuse_free(mru); return NULL; } break; default: *code = LDAP_SCHERR_UNEXPTOKEN; *errp = ss; LDAP_FREE(sval); ldap_matchingruleuse_free(mru); return NULL; } } } void ldap_attributetype_free(LDAPAttributeType * at) { if (!at) return; LDAP_FREE(at->at_oid); if (at->at_names) LDAP_VFREE(at->at_names); if (at->at_desc) LDAP_FREE(at->at_desc); if (at->at_sup_oid) LDAP_FREE(at->at_sup_oid); if (at->at_equality_oid) LDAP_FREE(at->at_equality_oid); if (at->at_ordering_oid) LDAP_FREE(at->at_ordering_oid); if (at->at_substr_oid) LDAP_FREE(at->at_substr_oid); if (at->at_syntax_oid) LDAP_FREE(at->at_syntax_oid); free_extensions(at->at_extensions); LDAP_FREE(at); } LDAPAttributeType * ldap_str2attributetype( LDAP_CONST char * s, int * code, LDAP_CONST char ** errp, LDAP_CONST unsigned flags ) { tk_t kind; const char * ss = s; char * sval; int seen_name = 0; int seen_desc = 0; int seen_obsolete = 0; int seen_sup = 0; int seen_equality = 0; int seen_ordering = 0; int seen_substr = 0; int seen_syntax = 0; int seen_usage = 0; LDAPAttributeType * at; char ** ext_vals; const char * savepos; if ( !s ) { *code = LDAP_SCHERR_EMPTY; *errp = ""; return NULL; } *errp = s; at = LDAP_CALLOC(1,sizeof(LDAPAttributeType)); if ( !at ) { *code = LDAP_SCHERR_OUTOFMEM; return NULL; } kind = get_token(&ss,&sval); if ( kind != TK_LEFTPAREN ) { *code = LDAP_SCHERR_NOLEFTPAREN; LDAP_FREE(sval); ldap_attributetype_free(at); return NULL; } /* * Definitions MUST begin with an OID in the numericoid format. * However, this routine is used by clients to parse the response * from servers and very well known servers will provide an OID * in the wrong format or even no OID at all. We do our best to * extract info from those servers. */ parse_whsp(&ss); savepos = ss; at->at_oid = ldap_int_parse_numericoid(&ss,code,0); if ( !at->at_oid ) { if ( ( flags & ( LDAP_SCHEMA_ALLOW_NO_OID | LDAP_SCHEMA_ALLOW_OID_MACRO ) ) && (ss == savepos) ) { /* Backtracking */ ss = savepos; kind = get_token(&ss,&sval); if ( kind == TK_BAREWORD ) { if ( !strcasecmp(sval, "NAME") || !strcasecmp(sval, "DESC") || !strcasecmp(sval, "OBSOLETE") || !strcasecmp(sval, "SUP") || !strcasecmp(sval, "EQUALITY") || !strcasecmp(sval, "ORDERING") || !strcasecmp(sval, "SUBSTR") || !strcasecmp(sval, "SYNTAX") || !strcasecmp(sval, "SINGLE-VALUE") || !strcasecmp(sval, "COLLECTIVE") || !strcasecmp(sval, "NO-USER-MODIFICATION") || !strcasecmp(sval, "USAGE") || !strncasecmp(sval, "X-", 2) ) { /* Missing OID, backtrack */ ss = savepos; } else if ( flags & LDAP_SCHEMA_ALLOW_OID_MACRO) { /* Non-numerical OID ... */ int len = ss-savepos; at->at_oid = LDAP_MALLOC(len+1); strncpy(at->at_oid, savepos, len); at->at_oid[len] = 0; } } LDAP_FREE(sval); } else { *errp = ss; ldap_attributetype_free(at); return NULL; } } parse_whsp(&ss); /* * Beyond this point we will be liberal and accept the items * in any order. */ while (1) { kind = get_token(&ss,&sval); switch (kind) { case TK_EOS: *code = LDAP_SCHERR_NORIGHTPAREN; *errp = EndOfInput; ldap_attributetype_free(at); return NULL; case TK_RIGHTPAREN: return at; case TK_BAREWORD: if ( !strcasecmp(sval,"NAME") ) { LDAP_FREE(sval); if ( seen_name ) { *code = LDAP_SCHERR_DUPOPT; *errp = ss; ldap_attributetype_free(at); return(NULL); } seen_name = 1; at->at_names = parse_qdescrs(&ss,code); if ( !at->at_names ) { if ( *code != LDAP_SCHERR_OUTOFMEM ) *code = LDAP_SCHERR_BADNAME; *errp = ss; ldap_attributetype_free(at); return NULL; } } else if ( !strcasecmp(sval,"DESC") ) { LDAP_FREE(sval); if ( seen_desc ) { *code = LDAP_SCHERR_DUPOPT; *errp = ss; ldap_attributetype_free(at); return(NULL); } seen_desc = 1; parse_whsp(&ss); kind = get_token(&ss,&sval); if ( kind != TK_QDSTRING ) { *code = LDAP_SCHERR_UNEXPTOKEN; *errp = ss; LDAP_FREE(sval); ldap_attributetype_free(at); return NULL; } at->at_desc = sval; parse_whsp(&ss); } else if ( !strcasecmp(sval,"OBSOLETE") ) { LDAP_FREE(sval); if ( seen_obsolete ) { *code = LDAP_SCHERR_DUPOPT; *errp = ss; ldap_attributetype_free(at); return(NULL); } seen_obsolete = 1; at->at_obsolete = LDAP_SCHEMA_YES; parse_whsp(&ss); } else if ( !strcasecmp(sval,"SUP") ) { LDAP_FREE(sval); if ( seen_sup ) { *code = LDAP_SCHERR_DUPOPT; *errp = ss; ldap_attributetype_free(at); return(NULL); } seen_sup = 1; at->at_sup_oid = parse_woid(&ss,code); if ( !at->at_sup_oid ) { *errp = ss; ldap_attributetype_free(at); return NULL; } } else if ( !strcasecmp(sval,"EQUALITY") ) { LDAP_FREE(sval); if ( seen_equality ) { *code = LDAP_SCHERR_DUPOPT; *errp = ss; ldap_attributetype_free(at); return(NULL); } seen_equality = 1; at->at_equality_oid = parse_woid(&ss,code); if ( !at->at_equality_oid ) { *errp = ss; ldap_attributetype_free(at); return NULL; } } else if ( !strcasecmp(sval,"ORDERING") ) { LDAP_FREE(sval); if ( seen_ordering ) { *code = LDAP_SCHERR_DUPOPT; *errp = ss; ldap_attributetype_free(at); return(NULL); } seen_ordering = 1; at->at_ordering_oid = parse_woid(&ss,code); if ( !at->at_ordering_oid ) { *errp = ss; ldap_attributetype_free(at); return NULL; } } else if ( !strcasecmp(sval,"SUBSTR") ) { LDAP_FREE(sval); if ( seen_substr ) { *code = LDAP_SCHERR_DUPOPT; *errp = ss; ldap_attributetype_free(at); return(NULL); } seen_substr = 1; at->at_substr_oid = parse_woid(&ss,code); if ( !at->at_substr_oid ) { *errp = ss; ldap_attributetype_free(at); return NULL; } } else if ( !strcasecmp(sval,"SYNTAX") ) { LDAP_FREE(sval); if ( seen_syntax ) { *code = LDAP_SCHERR_DUPOPT; *errp = ss; ldap_attributetype_free(at); return(NULL); } seen_syntax = 1; parse_whsp(&ss); savepos = ss; at->at_syntax_oid = parse_noidlen(&ss, code, &at->at_syntax_len, flags); if ( !at->at_syntax_oid ) { if ( flags & LDAP_SCHEMA_ALLOW_OID_MACRO ) { kind = get_token(&ss,&sval); if (kind == TK_BAREWORD) { char *sp = strchr(sval, '{'); at->at_syntax_oid = sval; if (sp) { *sp++ = 0; at->at_syntax_len = atoi(sp); while ( LDAP_DIGIT(*sp) ) sp++; if ( *sp != '}' ) { *code = LDAP_SCHERR_UNEXPTOKEN; *errp = ss; ldap_attributetype_free(at); return NULL; } } } } else { *errp = ss; ldap_attributetype_free(at); return NULL; } } parse_whsp(&ss); } else if ( !strcasecmp(sval,"SINGLE-VALUE") ) { LDAP_FREE(sval); if ( at->at_single_value ) { *code = LDAP_SCHERR_DUPOPT; *errp = ss; ldap_attributetype_free(at); return(NULL); } at->at_single_value = LDAP_SCHEMA_YES; parse_whsp(&ss); } else if ( !strcasecmp(sval,"COLLECTIVE") ) { LDAP_FREE(sval); if ( at->at_collective ) { *code = LDAP_SCHERR_DUPOPT; *errp = ss; ldap_attributetype_free(at); return(NULL); } at->at_collective = LDAP_SCHEMA_YES; parse_whsp(&ss); } else if ( !strcasecmp(sval,"NO-USER-MODIFICATION") ) { LDAP_FREE(sval); if ( at->at_no_user_mod ) { *code = LDAP_SCHERR_DUPOPT; *errp = ss; ldap_attributetype_free(at); return(NULL); } at->at_no_user_mod = LDAP_SCHEMA_YES; parse_whsp(&ss); } else if ( !strcasecmp(sval,"USAGE") ) { LDAP_FREE(sval); if ( seen_usage ) { *code = LDAP_SCHERR_DUPOPT; *errp = ss; ldap_attributetype_free(at); return(NULL); } seen_usage = 1; parse_whsp(&ss); kind = get_token(&ss,&sval); if ( kind != TK_BAREWORD ) { *code = LDAP_SCHERR_UNEXPTOKEN; *errp = ss; LDAP_FREE(sval); ldap_attributetype_free(at); return NULL; } if ( !strcasecmp(sval,"userApplications") ) at->at_usage = LDAP_SCHEMA_USER_APPLICATIONS; else if ( !strcasecmp(sval,"directoryOperation") ) at->at_usage = LDAP_SCHEMA_DIRECTORY_OPERATION; else if ( !strcasecmp(sval,"distributedOperation") ) at->at_usage = LDAP_SCHEMA_DISTRIBUTED_OPERATION; else if ( !strcasecmp(sval,"dSAOperation") ) at->at_usage = LDAP_SCHEMA_DSA_OPERATION; else { *code = LDAP_SCHERR_UNEXPTOKEN; *errp = ss; LDAP_FREE(sval); ldap_attributetype_free(at); return NULL; } LDAP_FREE(sval); parse_whsp(&ss); } else if ( sval[0] == 'X' && sval[1] == '-' ) { /* Should be parse_qdstrings */ ext_vals = parse_qdescrs(&ss, code); if ( !ext_vals ) { *errp = ss; ldap_attributetype_free(at); return NULL; } if ( add_extension(&at->at_extensions, sval, ext_vals) ) { *code = LDAP_SCHERR_OUTOFMEM; *errp = ss; LDAP_FREE(sval); ldap_attributetype_free(at); return NULL; } } else { *code = LDAP_SCHERR_UNEXPTOKEN; *errp = ss; LDAP_FREE(sval); ldap_attributetype_free(at); return NULL; } break; default: *code = LDAP_SCHERR_UNEXPTOKEN; *errp = ss; LDAP_FREE(sval); ldap_attributetype_free(at); return NULL; } } } void ldap_objectclass_free(LDAPObjectClass * oc) { if (!oc) return; LDAP_FREE(oc->oc_oid); if (oc->oc_names) LDAP_VFREE(oc->oc_names); if (oc->oc_desc) LDAP_FREE(oc->oc_desc); if (oc->oc_sup_oids) LDAP_VFREE(oc->oc_sup_oids); if (oc->oc_at_oids_must) LDAP_VFREE(oc->oc_at_oids_must); if (oc->oc_at_oids_may) LDAP_VFREE(oc->oc_at_oids_may); free_extensions(oc->oc_extensions); LDAP_FREE(oc); } LDAPObjectClass * ldap_str2objectclass( LDAP_CONST char * s, int * code, LDAP_CONST char ** errp, LDAP_CONST unsigned flags ) { tk_t kind; const char * ss = s; char * sval; int seen_name = 0; int seen_desc = 0; int seen_obsolete = 0; int seen_sup = 0; int seen_kind = 0; int seen_must = 0; int seen_may = 0; LDAPObjectClass * oc; char ** ext_vals; const char * savepos; if ( !s ) { *code = LDAP_SCHERR_EMPTY; *errp = ""; return NULL; } *errp = s; oc = LDAP_CALLOC(1,sizeof(LDAPObjectClass)); if ( !oc ) { *code = LDAP_SCHERR_OUTOFMEM; return NULL; } oc->oc_kind = LDAP_SCHEMA_STRUCTURAL; kind = get_token(&ss,&sval); if ( kind != TK_LEFTPAREN ) { *code = LDAP_SCHERR_NOLEFTPAREN; LDAP_FREE(sval); ldap_objectclass_free(oc); return NULL; } /* * Definitions MUST begin with an OID in the numericoid format. * However, this routine is used by clients to parse the response * from servers and very well known servers will provide an OID * in the wrong format or even no OID at all. We do our best to * extract info from those servers. */ parse_whsp(&ss); savepos = ss; oc->oc_oid = ldap_int_parse_numericoid(&ss,code,0); if ( !oc->oc_oid ) { if ( (flags & LDAP_SCHEMA_ALLOW_ALL) && (ss == savepos) ) { /* Backtracking */ ss = savepos; kind = get_token(&ss,&sval); if ( kind == TK_BAREWORD ) { if ( !strcasecmp(sval, "NAME") || !strcasecmp(sval, "DESC") || !strcasecmp(sval, "OBSOLETE") || !strcasecmp(sval, "SUP") || !strcasecmp(sval, "ABSTRACT") || !strcasecmp(sval, "STRUCTURAL") || !strcasecmp(sval, "AUXILIARY") || !strcasecmp(sval, "MUST") || !strcasecmp(sval, "MAY") || !strncasecmp(sval, "X-", 2) ) { /* Missing OID, backtrack */ ss = savepos; } else if ( flags & LDAP_SCHEMA_ALLOW_OID_MACRO ) { /* Non-numerical OID, ignore */ int len = ss-savepos; oc->oc_oid = LDAP_MALLOC(len+1); strncpy(oc->oc_oid, savepos, len); oc->oc_oid[len] = 0; } } LDAP_FREE(sval); *code = 0; } else { *errp = ss; ldap_objectclass_free(oc); return NULL; } } parse_whsp(&ss); /* * Beyond this point we will be liberal an accept the items * in any order. */ while (1) { kind = get_token(&ss,&sval); switch (kind) { case TK_EOS: *code = LDAP_SCHERR_NORIGHTPAREN; *errp = EndOfInput; ldap_objectclass_free(oc); return NULL; case TK_RIGHTPAREN: return oc; case TK_BAREWORD: if ( !strcasecmp(sval,"NAME") ) { LDAP_FREE(sval); if ( seen_name ) { *code = LDAP_SCHERR_DUPOPT; *errp = ss; ldap_objectclass_free(oc); return(NULL); } seen_name = 1; oc->oc_names = parse_qdescrs(&ss,code); if ( !oc->oc_names ) { if ( *code != LDAP_SCHERR_OUTOFMEM ) *code = LDAP_SCHERR_BADNAME; *errp = ss; ldap_objectclass_free(oc); return NULL; } } else if ( !strcasecmp(sval,"DESC") ) { LDAP_FREE(sval); if ( seen_desc ) { *code = LDAP_SCHERR_DUPOPT; *errp = ss; ldap_objectclass_free(oc); return(NULL); } seen_desc = 1; parse_whsp(&ss); kind = get_token(&ss,&sval); if ( kind != TK_QDSTRING ) { *code = LDAP_SCHERR_UNEXPTOKEN; *errp = ss; LDAP_FREE(sval); ldap_objectclass_free(oc); return NULL; } oc->oc_desc = sval; parse_whsp(&ss); } else if ( !strcasecmp(sval,"OBSOLETE") ) { LDAP_FREE(sval); if ( seen_obsolete ) { *code = LDAP_SCHERR_DUPOPT; *errp = ss; ldap_objectclass_free(oc); return(NULL); } seen_obsolete = 1; oc->oc_obsolete = LDAP_SCHEMA_YES; parse_whsp(&ss); } else if ( !strcasecmp(sval,"SUP") ) { LDAP_FREE(sval); if ( seen_sup ) { *code = LDAP_SCHERR_DUPOPT; *errp = ss; ldap_objectclass_free(oc); return(NULL); } seen_sup = 1; oc->oc_sup_oids = parse_oids(&ss, code, flags); if ( !oc->oc_sup_oids && *code != LDAP_SUCCESS ) { *errp = ss; ldap_objectclass_free(oc); return NULL; } *code = 0; } else if ( !strcasecmp(sval,"ABSTRACT") ) { LDAP_FREE(sval); if ( seen_kind ) { *code = LDAP_SCHERR_DUPOPT; *errp = ss; ldap_objectclass_free(oc); return(NULL); } seen_kind = 1; oc->oc_kind = LDAP_SCHEMA_ABSTRACT; parse_whsp(&ss); } else if ( !strcasecmp(sval,"STRUCTURAL") ) { LDAP_FREE(sval); if ( seen_kind ) { *code = LDAP_SCHERR_DUPOPT; *errp = ss; ldap_objectclass_free(oc); return(NULL); } seen_kind = 1; oc->oc_kind = LDAP_SCHEMA_STRUCTURAL; parse_whsp(&ss); } else if ( !strcasecmp(sval,"AUXILIARY") ) { LDAP_FREE(sval); if ( seen_kind ) { *code = LDAP_SCHERR_DUPOPT; *errp = ss; ldap_objectclass_free(oc); return(NULL); } seen_kind = 1; oc->oc_kind = LDAP_SCHEMA_AUXILIARY; parse_whsp(&ss); } else if ( !strcasecmp(sval,"MUST") ) { LDAP_FREE(sval); if ( seen_must ) { *code = LDAP_SCHERR_DUPOPT; *errp = ss; ldap_objectclass_free(oc); return(NULL); } seen_must = 1; oc->oc_at_oids_must = parse_oids(&ss,code,0); if ( !oc->oc_at_oids_must && *code != LDAP_SUCCESS ) { *errp = ss; ldap_objectclass_free(oc); return NULL; } *code = 0; parse_whsp(&ss); } else if ( !strcasecmp(sval,"MAY") ) { LDAP_FREE(sval); if ( seen_may ) { *code = LDAP_SCHERR_DUPOPT; *errp = ss; ldap_objectclass_free(oc); return(NULL); } seen_may = 1; oc->oc_at_oids_may = parse_oids(&ss,code,0); if ( !oc->oc_at_oids_may && *code != LDAP_SUCCESS ) { *errp = ss; ldap_objectclass_free(oc); return NULL; } *code = 0; parse_whsp(&ss); } else if ( sval[0] == 'X' && sval[1] == '-' ) { /* Should be parse_qdstrings */ ext_vals = parse_qdescrs(&ss, code); *code = 0; if ( !ext_vals ) { *errp = ss; ldap_objectclass_free(oc); return NULL; } if ( add_extension(&oc->oc_extensions, sval, ext_vals) ) { *code = LDAP_SCHERR_OUTOFMEM; *errp = ss; LDAP_FREE(sval); ldap_objectclass_free(oc); return NULL; } } else { *code = LDAP_SCHERR_UNEXPTOKEN; *errp = ss; LDAP_FREE(sval); ldap_objectclass_free(oc); return NULL; } break; default: *code = LDAP_SCHERR_UNEXPTOKEN; *errp = ss; LDAP_FREE(sval); ldap_objectclass_free(oc); return NULL; } } } void ldap_contentrule_free(LDAPContentRule * cr) { if (!cr) return; LDAP_FREE(cr->cr_oid); if (cr->cr_names) LDAP_VFREE(cr->cr_names); if (cr->cr_desc) LDAP_FREE(cr->cr_desc); if (cr->cr_oc_oids_aux) LDAP_VFREE(cr->cr_oc_oids_aux); if (cr->cr_at_oids_must) LDAP_VFREE(cr->cr_at_oids_must); if (cr->cr_at_oids_may) LDAP_VFREE(cr->cr_at_oids_may); if (cr->cr_at_oids_not) LDAP_VFREE(cr->cr_at_oids_not); free_extensions(cr->cr_extensions); LDAP_FREE(cr); } LDAPContentRule * ldap_str2contentrule( LDAP_CONST char * s, int * code, LDAP_CONST char ** errp, LDAP_CONST unsigned flags ) { tk_t kind; const char * ss = s; char * sval; int seen_name = 0; int seen_desc = 0; int seen_obsolete = 0; int seen_aux = 0; int seen_must = 0; int seen_may = 0; int seen_not = 0; LDAPContentRule * cr; char ** ext_vals; const char * savepos; if ( !s ) { *code = LDAP_SCHERR_EMPTY; *errp = ""; return NULL; } *errp = s; cr = LDAP_CALLOC(1,sizeof(LDAPContentRule)); if ( !cr ) { *code = LDAP_SCHERR_OUTOFMEM; return NULL; } kind = get_token(&ss,&sval); if ( kind != TK_LEFTPAREN ) { *code = LDAP_SCHERR_NOLEFTPAREN; LDAP_FREE(sval); ldap_contentrule_free(cr); return NULL; } /* * Definitions MUST begin with an OID in the numericoid format. */ parse_whsp(&ss); savepos = ss; cr->cr_oid = ldap_int_parse_numericoid(&ss,code,0); if ( !cr->cr_oid ) { if ( (flags & LDAP_SCHEMA_ALLOW_ALL) && (ss == savepos) ) { /* Backtracking */ ss = savepos; kind = get_token(&ss,&sval); if ( kind == TK_BAREWORD ) { if ( !strcasecmp(sval, "NAME") || !strcasecmp(sval, "DESC") || !strcasecmp(sval, "OBSOLETE") || !strcasecmp(sval, "AUX") || !strcasecmp(sval, "MUST") || !strcasecmp(sval, "MAY") || !strcasecmp(sval, "NOT") || !strncasecmp(sval, "X-", 2) ) { /* Missing OID, backtrack */ ss = savepos; } else if ( flags & LDAP_SCHEMA_ALLOW_OID_MACRO ) { /* Non-numerical OID, ignore */ int len = ss-savepos; cr->cr_oid = LDAP_MALLOC(len+1); strncpy(cr->cr_oid, savepos, len); cr->cr_oid[len] = 0; } } LDAP_FREE(sval); } else { *errp = ss; ldap_contentrule_free(cr); return NULL; } } parse_whsp(&ss); /* * Beyond this point we will be liberal an accept the items * in any order. */ while (1) { kind = get_token(&ss,&sval); switch (kind) { case TK_EOS: *code = LDAP_SCHERR_NORIGHTPAREN; *errp = EndOfInput; ldap_contentrule_free(cr); return NULL; case TK_RIGHTPAREN: return cr; case TK_BAREWORD: if ( !strcasecmp(sval,"NAME") ) { LDAP_FREE(sval); if ( seen_name ) { *code = LDAP_SCHERR_DUPOPT; *errp = ss; ldap_contentrule_free(cr); return(NULL); } seen_name = 1; cr->cr_names = parse_qdescrs(&ss,code); if ( !cr->cr_names ) { if ( *code != LDAP_SCHERR_OUTOFMEM ) *code = LDAP_SCHERR_BADNAME; *errp = ss; ldap_contentrule_free(cr); return NULL; } } else if ( !strcasecmp(sval,"DESC") ) { LDAP_FREE(sval); if ( seen_desc ) { *code = LDAP_SCHERR_DUPOPT; *errp = ss; ldap_contentrule_free(cr); return(NULL); } seen_desc = 1; parse_whsp(&ss); kind = get_token(&ss,&sval); if ( kind != TK_QDSTRING ) { *code = LDAP_SCHERR_UNEXPTOKEN; *errp = ss; LDAP_FREE(sval); ldap_contentrule_free(cr); return NULL; } cr->cr_desc = sval; parse_whsp(&ss); } else if ( !strcasecmp(sval,"OBSOLETE") ) { LDAP_FREE(sval); if ( seen_obsolete ) { *code = LDAP_SCHERR_DUPOPT; *errp = ss; ldap_contentrule_free(cr); return(NULL); } seen_obsolete = 1; cr->cr_obsolete = LDAP_SCHEMA_YES; parse_whsp(&ss); } else if ( !strcasecmp(sval,"AUX") ) { LDAP_FREE(sval); if ( seen_aux ) { *code = LDAP_SCHERR_DUPOPT; *errp = ss; ldap_contentrule_free(cr); return(NULL); } seen_aux = 1; cr->cr_oc_oids_aux = parse_oids(&ss,code,0); if ( !cr->cr_oc_oids_aux ) { *errp = ss; ldap_contentrule_free(cr); return NULL; } parse_whsp(&ss); } else if ( !strcasecmp(sval,"MUST") ) { LDAP_FREE(sval); if ( seen_must ) { *code = LDAP_SCHERR_DUPOPT; *errp = ss; ldap_contentrule_free(cr); return(NULL); } seen_must = 1; cr->cr_at_oids_must = parse_oids(&ss,code,0); if ( !cr->cr_at_oids_must && *code != LDAP_SUCCESS ) { *errp = ss; ldap_contentrule_free(cr); return NULL; } parse_whsp(&ss); } else if ( !strcasecmp(sval,"MAY") ) { LDAP_FREE(sval); if ( seen_may ) { *code = LDAP_SCHERR_DUPOPT; *errp = ss; ldap_contentrule_free(cr); return(NULL); } seen_may = 1; cr->cr_at_oids_may = parse_oids(&ss,code,0); if ( !cr->cr_at_oids_may && *code != LDAP_SUCCESS ) { *errp = ss; ldap_contentrule_free(cr); return NULL; } parse_whsp(&ss); } else if ( !strcasecmp(sval,"NOT") ) { LDAP_FREE(sval); if ( seen_not ) { *code = LDAP_SCHERR_DUPOPT; *errp = ss; ldap_contentrule_free(cr); return(NULL); } seen_not = 1; cr->cr_at_oids_not = parse_oids(&ss,code,0); if ( !cr->cr_at_oids_not && *code != LDAP_SUCCESS ) { *errp = ss; ldap_contentrule_free(cr); return NULL; } parse_whsp(&ss); } else if ( sval[0] == 'X' && sval[1] == '-' ) { /* Should be parse_qdstrings */ ext_vals = parse_qdescrs(&ss, code); if ( !ext_vals ) { *errp = ss; ldap_contentrule_free(cr); return NULL; } if ( add_extension(&cr->cr_extensions, sval, ext_vals) ) { *code = LDAP_SCHERR_OUTOFMEM; *errp = ss; LDAP_FREE(sval); ldap_contentrule_free(cr); return NULL; } } else { *code = LDAP_SCHERR_UNEXPTOKEN; *errp = ss; LDAP_FREE(sval); ldap_contentrule_free(cr); return NULL; } break; default: *code = LDAP_SCHERR_UNEXPTOKEN; *errp = ss; LDAP_FREE(sval); ldap_contentrule_free(cr); return NULL; } } } void ldap_structurerule_free(LDAPStructureRule * sr) { if (!sr) return; if (sr->sr_names) LDAP_VFREE(sr->sr_names); if (sr->sr_desc) LDAP_FREE(sr->sr_desc); if (sr->sr_nameform) LDAP_FREE(sr->sr_nameform); if (sr->sr_sup_ruleids) LDAP_FREE(sr->sr_sup_ruleids); free_extensions(sr->sr_extensions); LDAP_FREE(sr); } LDAPStructureRule * ldap_str2structurerule( LDAP_CONST char * s, int * code, LDAP_CONST char ** errp, LDAP_CONST unsigned flags ) { tk_t kind; int ret; const char * ss = s; char * sval; int seen_name = 0; int seen_desc = 0; int seen_obsolete = 0; int seen_nameform = 0; LDAPStructureRule * sr; char ** ext_vals; const char * savepos; if ( !s ) { *code = LDAP_SCHERR_EMPTY; *errp = ""; return NULL; } *errp = s; sr = LDAP_CALLOC(1,sizeof(LDAPStructureRule)); if ( !sr ) { *code = LDAP_SCHERR_OUTOFMEM; return NULL; } kind = get_token(&ss,&sval); if ( kind != TK_LEFTPAREN ) { *code = LDAP_SCHERR_NOLEFTPAREN; LDAP_FREE(sval); ldap_structurerule_free(sr); return NULL; } /* * Definitions MUST begin with a ruleid. */ parse_whsp(&ss); savepos = ss; ret = ldap_int_parse_ruleid(&ss,code,0,&sr->sr_ruleid); if ( ret ) { *errp = ss; ldap_structurerule_free(sr); return NULL; } parse_whsp(&ss); /* * Beyond this point we will be liberal an accept the items * in any order. */ while (1) { kind = get_token(&ss,&sval); switch (kind) { case TK_EOS: *code = LDAP_SCHERR_NORIGHTPAREN; *errp = EndOfInput; ldap_structurerule_free(sr); return NULL; case TK_RIGHTPAREN: if( !seen_nameform ) { *code = LDAP_SCHERR_MISSING; ldap_structurerule_free(sr); return NULL; } return sr; case TK_BAREWORD: if ( !strcasecmp(sval,"NAME") ) { LDAP_FREE(sval); if ( seen_name ) { *code = LDAP_SCHERR_DUPOPT; *errp = ss; ldap_structurerule_free(sr); return(NULL); } seen_name = 1; sr->sr_names = parse_qdescrs(&ss,code); if ( !sr->sr_names ) { if ( *code != LDAP_SCHERR_OUTOFMEM ) *code = LDAP_SCHERR_BADNAME; *errp = ss; ldap_structurerule_free(sr); return NULL; } } else if ( !strcasecmp(sval,"DESC") ) { LDAP_FREE(sval); if ( seen_desc ) { *code = LDAP_SCHERR_DUPOPT; *errp = ss; ldap_structurerule_free(sr); return(NULL); } seen_desc = 1; parse_whsp(&ss); kind = get_token(&ss,&sval); if ( kind != TK_QDSTRING ) { *code = LDAP_SCHERR_UNEXPTOKEN; *errp = ss; LDAP_FREE(sval); ldap_structurerule_free(sr); return NULL; } sr->sr_desc = sval; parse_whsp(&ss); } else if ( !strcasecmp(sval,"OBSOLETE") ) { LDAP_FREE(sval); if ( seen_obsolete ) { *code = LDAP_SCHERR_DUPOPT; *errp = ss; ldap_structurerule_free(sr); return(NULL); } seen_obsolete = 1; sr->sr_obsolete = LDAP_SCHEMA_YES; parse_whsp(&ss); } else if ( !strcasecmp(sval,"FORM") ) { LDAP_FREE(sval); if ( seen_nameform ) { *code = LDAP_SCHERR_DUPOPT; *errp = ss; ldap_structurerule_free(sr); return(NULL); } seen_nameform = 1; sr->sr_nameform = parse_woid(&ss,code); if ( !sr->sr_nameform ) { *errp = ss; ldap_structurerule_free(sr); return NULL; } parse_whsp(&ss); } else if ( sval[0] == 'X' && sval[1] == '-' ) { /* Should be parse_qdstrings */ ext_vals = parse_qdescrs(&ss, code); if ( !ext_vals ) { *errp = ss; ldap_structurerule_free(sr); return NULL; } if ( add_extension(&sr->sr_extensions, sval, ext_vals) ) { *code = LDAP_SCHERR_OUTOFMEM; *errp = ss; LDAP_FREE(sval); ldap_structurerule_free(sr); return NULL; } } else { *code = LDAP_SCHERR_UNEXPTOKEN; *errp = ss; LDAP_FREE(sval); ldap_structurerule_free(sr); return NULL; } break; default: *code = LDAP_SCHERR_UNEXPTOKEN; *errp = ss; LDAP_FREE(sval); ldap_structurerule_free(sr); return NULL; } } } void ldap_nameform_free(LDAPNameForm * nf) { if (!nf) return; LDAP_FREE(nf->nf_oid); if (nf->nf_names) LDAP_VFREE(nf->nf_names); if (nf->nf_desc) LDAP_FREE(nf->nf_desc); if (nf->nf_objectclass) LDAP_FREE(nf->nf_objectclass); if (nf->nf_at_oids_must) LDAP_VFREE(nf->nf_at_oids_must); if (nf->nf_at_oids_may) LDAP_VFREE(nf->nf_at_oids_may); free_extensions(nf->nf_extensions); LDAP_FREE(nf); } LDAPNameForm * ldap_str2nameform( LDAP_CONST char * s, int * code, LDAP_CONST char ** errp, LDAP_CONST unsigned flags ) { tk_t kind; const char * ss = s; char * sval; int seen_name = 0; int seen_desc = 0; int seen_obsolete = 0; int seen_class = 0; int seen_must = 0; int seen_may = 0; LDAPNameForm * nf; char ** ext_vals; const char * savepos; if ( !s ) { *code = LDAP_SCHERR_EMPTY; *errp = ""; return NULL; } *errp = s; nf = LDAP_CALLOC(1,sizeof(LDAPNameForm)); if ( !nf ) { *code = LDAP_SCHERR_OUTOFMEM; return NULL; } kind = get_token(&ss,&sval); if ( kind != TK_LEFTPAREN ) { *code = LDAP_SCHERR_NOLEFTPAREN; LDAP_FREE(sval); ldap_nameform_free(nf); return NULL; } /* * Definitions MUST begin with an OID in the numericoid format. * However, this routine is used by clients to parse the response * from servers and very well known servers will provide an OID * in the wrong format or even no OID at all. We do our best to * extract info from those servers. */ parse_whsp(&ss); savepos = ss; nf->nf_oid = ldap_int_parse_numericoid(&ss,code,0); if ( !nf->nf_oid ) { *errp = ss; ldap_nameform_free(nf); return NULL; } parse_whsp(&ss); /* * Beyond this point we will be liberal an accept the items * in any order. */ while (1) { kind = get_token(&ss,&sval); switch (kind) { case TK_EOS: *code = LDAP_SCHERR_NORIGHTPAREN; *errp = EndOfInput; ldap_nameform_free(nf); return NULL; case TK_RIGHTPAREN: if( !seen_class || !seen_must ) { *code = LDAP_SCHERR_MISSING; ldap_nameform_free(nf); return NULL; } return nf; case TK_BAREWORD: if ( !strcasecmp(sval,"NAME") ) { LDAP_FREE(sval); if ( seen_name ) { *code = LDAP_SCHERR_DUPOPT; *errp = ss; ldap_nameform_free(nf); return(NULL); } seen_name = 1; nf->nf_names = parse_qdescrs(&ss,code); if ( !nf->nf_names ) { if ( *code != LDAP_SCHERR_OUTOFMEM ) *code = LDAP_SCHERR_BADNAME; *errp = ss; ldap_nameform_free(nf); return NULL; } } else if ( !strcasecmp(sval,"DESC") ) { LDAP_FREE(sval); if ( seen_desc ) { *code = LDAP_SCHERR_DUPOPT; *errp = ss; ldap_nameform_free(nf); return(NULL); } seen_desc = 1; parse_whsp(&ss); kind = get_token(&ss,&sval); if ( kind != TK_QDSTRING ) { *code = LDAP_SCHERR_UNEXPTOKEN; *errp = ss; LDAP_FREE(sval); ldap_nameform_free(nf); return NULL; } nf->nf_desc = sval; parse_whsp(&ss); } else if ( !strcasecmp(sval,"OBSOLETE") ) { LDAP_FREE(sval); if ( seen_obsolete ) { *code = LDAP_SCHERR_DUPOPT; *errp = ss; ldap_nameform_free(nf); return(NULL); } seen_obsolete = 1; nf->nf_obsolete = LDAP_SCHEMA_YES; parse_whsp(&ss); } else if ( !strcasecmp(sval,"OC") ) { LDAP_FREE(sval); if ( seen_class ) { *code = LDAP_SCHERR_DUPOPT; *errp = ss; ldap_nameform_free(nf); return(NULL); } seen_class = 1; nf->nf_objectclass = parse_woid(&ss,code); if ( !nf->nf_objectclass ) { *errp = ss; ldap_nameform_free(nf); return NULL; } } else if ( !strcasecmp(sval,"MUST") ) { LDAP_FREE(sval); if ( seen_must ) { *code = LDAP_SCHERR_DUPOPT; *errp = ss; ldap_nameform_free(nf); return(NULL); } seen_must = 1; nf->nf_at_oids_must = parse_oids(&ss,code,0); if ( !nf->nf_at_oids_must && *code != LDAP_SUCCESS ) { *errp = ss; ldap_nameform_free(nf); return NULL; } parse_whsp(&ss); } else if ( !strcasecmp(sval,"MAY") ) { LDAP_FREE(sval); if ( seen_may ) { *code = LDAP_SCHERR_DUPOPT; *errp = ss; ldap_nameform_free(nf); return(NULL); } seen_may = 1; nf->nf_at_oids_may = parse_oids(&ss,code,0); if ( !nf->nf_at_oids_may && *code != LDAP_SUCCESS ) { *errp = ss; ldap_nameform_free(nf); return NULL; } parse_whsp(&ss); } else if ( sval[0] == 'X' && sval[1] == '-' ) { /* Should be parse_qdstrings */ ext_vals = parse_qdescrs(&ss, code); if ( !ext_vals ) { *errp = ss; ldap_nameform_free(nf); return NULL; } if ( add_extension(&nf->nf_extensions, sval, ext_vals) ) { *code = LDAP_SCHERR_OUTOFMEM; *errp = ss; LDAP_FREE(sval); ldap_nameform_free(nf); return NULL; } } else { *code = LDAP_SCHERR_UNEXPTOKEN; *errp = ss; LDAP_FREE(sval); ldap_nameform_free(nf); return NULL; } break; default: *code = LDAP_SCHERR_UNEXPTOKEN; *errp = ss; LDAP_FREE(sval); ldap_nameform_free(nf); return NULL; } } } static char *const err2text[] = { N_("Success"), N_("Out of memory"), N_("Unexpected token"), N_("Missing opening parenthesis"), N_("Missing closing parenthesis"), N_("Expecting digit"), N_("Expecting a name"), N_("Bad description"), N_("Bad superiors"), N_("Duplicate option"), N_("Unexpected end of data"), N_("Missing required field"), N_("Out of order field") }; char * ldap_scherr2str(int code) { if ( code < 0 || code >= (int)(sizeof(err2text)/sizeof(char *)) ) { return _("Unknown error"); } else { return _(err2text[code]); } } openldap-2.4.42+dfsg/libraries/libldap/ldif.c0000644000175000017500000004735012563404150017506 0ustar ryanryan/* ldif.c - routines for dealing with LDIF files */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (c) 1992-1996 Regents of the University of Michigan. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of Michigan at Ann Arbor. The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. This * software is provided ``as is'' without express or implied warranty. */ /* This work was originally developed by the University of Michigan * and distributed as part of U-MICH LDAP. */ #include "portable.h" #include #include #include #include #include #include int ldif_debug = 0; #include "ldap_log.h" #include "lber_pvt.h" #include "ldif.h" #define RIGHT2 0x03 #define RIGHT4 0x0f #define CONTINUED_LINE_MARKER '\r' #ifdef CSRIMALLOC #define ber_memalloc malloc #define ber_memcalloc calloc #define ber_memrealloc realloc #define ber_strdup strdup #endif static const char nib2b64[0x40] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; static const unsigned char b642nib[0x80] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff }; /* * ldif_parse_line - takes a line of the form "type:[:] value" and splits it * into components "type" and "value". if a double colon separates type from * value, then value is encoded in base 64, and parse_line un-decodes it * (in place) before returning. The type and value are stored in malloc'd * memory which must be freed by the caller. * * ldif_parse_line2 - operates in-place on input buffer, returning type * in-place. Will return value in-place if possible, (must malloc for * fetched URLs). If freeval is NULL, all return data will be malloc'd * and the input line will be unmodified. Otherwise freeval is set to * True if the value was malloc'd. */ int ldif_parse_line( LDAP_CONST char *line, char **typep, char **valuep, ber_len_t *vlenp ) { struct berval type, value; int rc = ldif_parse_line2( (char *)line, &type, &value, NULL ); *typep = type.bv_val; *valuep = value.bv_val; *vlenp = value.bv_len; return rc; } int ldif_parse_line2( char *line, struct berval *type, struct berval *value, int *freeval ) { char *s, *p, *d; char nib; int b64, url; BER_BVZERO( type ); BER_BVZERO( value ); /* skip any leading space */ while ( isspace( (unsigned char) *line ) ) { line++; } if ( freeval ) { *freeval = 0; } else { line = ber_strdup( line ); if( line == NULL ) { ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug, _("ldif_parse_line: line malloc failed\n")); return( -1 ); } } type->bv_val = line; s = strchr( type->bv_val, ':' ); if ( s == NULL ) { ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug, _("ldif_parse_line: missing ':' after %s\n"), type->bv_val ); if ( !freeval ) ber_memfree( line ); return( -1 ); } /* trim any space between type and : */ for ( p = &s[-1]; p > type->bv_val && isspace( * (unsigned char *) p ); p-- ) { *p = '\0'; } *s++ = '\0'; type->bv_len = s - type->bv_val - 1; url = 0; b64 = 0; if ( *s == '<' ) { s++; url = 1; } else if ( *s == ':' ) { /* base 64 encoded value */ s++; b64 = 1; } /* skip space between : and value */ while ( isspace( (unsigned char) *s ) ) { s++; } /* check for continued line markers that should be deleted */ for ( p = s, d = s; *p; p++ ) { if ( *p != CONTINUED_LINE_MARKER ) *d++ = *p; } *d = '\0'; if ( b64 ) { char *byte = s; if ( *s == '\0' ) { /* no value is present, error out */ ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug, _("ldif_parse_line: %s missing base64 value\n"), type->bv_val ); if ( !freeval ) ber_memfree( line ); return( -1 ); } byte = value->bv_val = s; for ( p = s, value->bv_len = 0; p < d; p += 4, value->bv_len += 3 ) { int i; for ( i = 0; i < 4; i++ ) { if ( p[i] != '=' && (p[i] & 0x80 || b642nib[ p[i] & 0x7f ] > 0x3f) ) { ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug, _("ldif_parse_line: %s: invalid base64 encoding" " char (%c) 0x%x\n"), type->bv_val, p[i], p[i] ); if ( !freeval ) ber_memfree( line ); return( -1 ); } } /* first digit */ nib = b642nib[ p[0] & 0x7f ]; byte[0] = nib << 2; /* second digit */ nib = b642nib[ p[1] & 0x7f ]; byte[0] |= nib >> 4; byte[1] = (nib & RIGHT4) << 4; /* third digit */ if ( p[2] == '=' ) { value->bv_len += 1; break; } nib = b642nib[ p[2] & 0x7f ]; byte[1] |= nib >> 2; byte[2] = (nib & RIGHT2) << 6; /* fourth digit */ if ( p[3] == '=' ) { value->bv_len += 2; break; } nib = b642nib[ p[3] & 0x7f ]; byte[2] |= nib; byte += 3; } s[ value->bv_len ] = '\0'; } else if ( url ) { if ( *s == '\0' ) { /* no value is present, error out */ ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug, _("ldif_parse_line: %s missing URL value\n"), type->bv_val ); if ( !freeval ) ber_memfree( line ); return( -1 ); } if( ldif_fetch_url( s, &value->bv_val, &value->bv_len ) ) { ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug, _("ldif_parse_line: %s: URL \"%s\" fetch failed\n"), type->bv_val, s ); if ( !freeval ) ber_memfree( line ); return( -1 ); } if ( freeval ) *freeval = 1; } else { value->bv_val = s; value->bv_len = (int) (d - s); } if ( !freeval ) { struct berval bv = *type; ber_dupbv( type, &bv ); if( BER_BVISNULL( type )) { ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug, _("ldif_parse_line: type malloc failed\n")); if( url ) ber_memfree( value->bv_val ); ber_memfree( line ); return( -1 ); } if( !url ) { bv = *value; ber_dupbv( value, &bv ); if( BER_BVISNULL( value )) { ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug, _("ldif_parse_line: value malloc failed\n")); ber_memfree( type->bv_val ); ber_memfree( line ); return( -1 ); } } ber_memfree( line ); } return( 0 ); } /* * ldif_getline - return the next "line" (minus newline) of input from a * string buffer of lines separated by newlines, terminated by \n\n * or \0. this routine handles continued lines, bundling them into * a single big line before returning. if a line begins with a white * space character, it is a continuation of the previous line. the white * space character (nb: only one char), and preceeding newline are changed * into CONTINUED_LINE_MARKER chars, to be deleted later by the * ldif_parse_line() routine above. * * ldif_getline will skip over any line which starts '#'. * * ldif_getline takes a pointer to a pointer to the buffer on the first call, * which it updates and must be supplied on subsequent calls. */ int ldif_countlines( LDAP_CONST char *buf ) { char *nl; int ret = 0; if ( !buf ) return ret; for ( nl = strchr(buf, '\n'); nl; nl = strchr(nl, '\n') ) { nl++; if ( *nl != ' ' ) ret++; } return ret; } char * ldif_getline( char **next ) { char *line; do { if ( *next == NULL || **next == '\n' || **next == '\0' ) { return( NULL ); } line = *next; while ( (*next = strchr( *next, '\n' )) != NULL ) { #if CONTINUED_LINE_MARKER != '\r' if ( (*next)[-1] == '\r' ) { (*next)[-1] = CONTINUED_LINE_MARKER; } #endif if ( (*next)[1] != ' ' ) { if ( (*next)[1] == '\r' && (*next)[2] == '\n' ) { *(*next)++ = '\0'; } *(*next)++ = '\0'; break; } **next = CONTINUED_LINE_MARKER; (*next)[1] = CONTINUED_LINE_MARKER; (*next)++; } } while( *line == '#' ); return( line ); } /* * name and OID of attributeTypes that must be base64 encoded in any case */ typedef struct must_b64_encode_s { struct berval name; struct berval oid; } must_b64_encode_s; static must_b64_encode_s default_must_b64_encode[] = { { BER_BVC( "userPassword" ), BER_BVC( "2.5.4.35" ) }, { BER_BVNULL, BER_BVNULL } }; static must_b64_encode_s *must_b64_encode = default_must_b64_encode; /* * register name and OID of attributeTypes that must always be base64 * encoded * * NOTE: this routine mallocs memory in a static struct which must * be explicitly freed when no longer required */ int ldif_must_b64_encode_register( LDAP_CONST char *name, LDAP_CONST char *oid ) { int i; ber_len_t len; assert( must_b64_encode != NULL ); assert( name != NULL ); assert( oid != NULL ); len = strlen( name ); for ( i = 0; !BER_BVISNULL( &must_b64_encode[i].name ); i++ ) { if ( len != must_b64_encode[i].name.bv_len ) { continue; } if ( strcasecmp( name, must_b64_encode[i].name.bv_val ) == 0 ) { break; } } if ( !BER_BVISNULL( &must_b64_encode[i].name ) ) { return 1; } for ( i = 0; !BER_BVISNULL( &must_b64_encode[i].name ); i++ ) /* just count */ ; if ( must_b64_encode == default_must_b64_encode ) { must_b64_encode = ber_memalloc( sizeof( must_b64_encode_s ) * ( i + 2 ) ); for ( i = 0; !BER_BVISNULL( &default_must_b64_encode[i].name ); i++ ) { ber_dupbv( &must_b64_encode[i].name, &default_must_b64_encode[i].name ); ber_dupbv( &must_b64_encode[i].oid, &default_must_b64_encode[i].oid ); } } else { must_b64_encode_s *tmp; tmp = ber_memrealloc( must_b64_encode, sizeof( must_b64_encode_s ) * ( i + 2 ) ); if ( tmp == NULL ) { return 1; } must_b64_encode = tmp; } ber_str2bv( name, len, 1, &must_b64_encode[i].name ); ber_str2bv( oid, 0, 1, &must_b64_encode[i].oid ); BER_BVZERO( &must_b64_encode[i + 1].name ); return 0; } void ldif_must_b64_encode_release( void ) { int i; assert( must_b64_encode != NULL ); if ( must_b64_encode == default_must_b64_encode ) { return; } for ( i = 0; !BER_BVISNULL( &must_b64_encode[i].name ); i++ ) { ber_memfree( must_b64_encode[i].name.bv_val ); ber_memfree( must_b64_encode[i].oid.bv_val ); } ber_memfree( must_b64_encode ); must_b64_encode = default_must_b64_encode; } /* * returns 1 iff the string corresponds to the name or the OID of any * of the attributeTypes listed in must_b64_encode */ static int ldif_must_b64_encode( LDAP_CONST char *s ) { int i; struct berval bv; assert( must_b64_encode != NULL ); assert( s != NULL ); ber_str2bv( s, 0, 0, &bv ); for ( i = 0; !BER_BVISNULL( &must_b64_encode[i].name ); i++ ) { if ( ber_bvstrcasecmp( &must_b64_encode[i].name, &bv ) == 0 || ber_bvcmp( &must_b64_encode[i].oid, &bv ) == 0 ) { return 1; } } return 0; } /* compatibility with U-Mich off by two bug */ #define LDIF_KLUDGE 2 /* NOTE: only preserved for binary compatibility */ void ldif_sput( char **out, int type, LDAP_CONST char *name, LDAP_CONST char *val, ber_len_t vlen ) { ldif_sput_wrap( out, type, name, val, vlen, LDIF_LINE_WIDTH+LDIF_KLUDGE ); } void ldif_sput_wrap( char **out, int type, LDAP_CONST char *name, LDAP_CONST char *val, ber_len_t vlen, ber_len_t wrap ) { const unsigned char *byte, *stop; unsigned char buf[3]; unsigned long bits; char *save; int pad; int namelen = 0; ber_len_t savelen; ber_len_t len=0; ber_len_t i; if ( !wrap ) wrap = LDIF_LINE_WIDTH+LDIF_KLUDGE; /* prefix */ switch( type ) { case LDIF_PUT_COMMENT: *(*out)++ = '#'; len++; if( vlen ) { *(*out)++ = ' '; len++; } break; case LDIF_PUT_SEP: *(*out)++ = '\n'; return; } /* name (attribute type) */ if( name != NULL ) { /* put the name + ":" */ namelen = strlen(name); strcpy(*out, name); *out += namelen; len += namelen; if( type != LDIF_PUT_COMMENT ) { *(*out)++ = ':'; len++; } } #ifdef LDAP_DEBUG else { assert( type == LDIF_PUT_COMMENT ); } #endif if( vlen == 0 ) { *(*out)++ = '\n'; return; } switch( type ) { case LDIF_PUT_NOVALUE: *(*out)++ = '\n'; return; case LDIF_PUT_URL: /* url value */ *(*out)++ = '<'; len++; break; case LDIF_PUT_B64: /* base64 value */ *(*out)++ = ':'; len++; break; } switch( type ) { case LDIF_PUT_TEXT: case LDIF_PUT_URL: case LDIF_PUT_B64: *(*out)++ = ' '; len++; /* fall-thru */ case LDIF_PUT_COMMENT: /* pre-encoded names */ for ( i=0; i < vlen; i++ ) { if ( len > wrap ) { *(*out)++ = '\n'; *(*out)++ = ' '; len = 1; } *(*out)++ = val[i]; len++; } *(*out)++ = '\n'; return; } save = *out; savelen = len; *(*out)++ = ' '; len++; stop = (const unsigned char *) (val + vlen); if ( type == LDIF_PUT_VALUE && isgraph( (unsigned char) val[0] ) && val[0] != ':' && val[0] != '<' && isgraph( (unsigned char) val[vlen-1] ) #ifndef LDAP_BINARY_DEBUG && strstr( name, ";binary" ) == NULL #endif #ifndef LDAP_PASSWD_DEBUG && !ldif_must_b64_encode( name ) #endif ) { int b64 = 0; for ( byte = (const unsigned char *) val; byte < stop; byte++, len++ ) { if ( !isascii( *byte ) || !isprint( *byte ) ) { b64 = 1; break; } if ( len >= wrap ) { *(*out)++ = '\n'; *(*out)++ = ' '; len = 1; } *(*out)++ = *byte; } if( !b64 ) { *(*out)++ = '\n'; return; } } *out = save; *(*out)++ = ':'; *(*out)++ = ' '; len = savelen + 2; /* convert to base 64 (3 bytes => 4 base 64 digits) */ for ( byte = (const unsigned char *) val; byte < stop - 2; byte += 3 ) { bits = (byte[0] & 0xff) << 16; bits |= (byte[1] & 0xff) << 8; bits |= (byte[2] & 0xff); for ( i = 0; i < 4; i++, len++, bits <<= 6 ) { if ( len >= wrap ) { *(*out)++ = '\n'; *(*out)++ = ' '; len = 1; } /* get b64 digit from high order 6 bits */ *(*out)++ = nib2b64[ (bits & 0xfc0000L) >> 18 ]; } } /* add padding if necessary */ if ( byte < stop ) { for ( i = 0; byte + i < stop; i++ ) { buf[i] = byte[i]; } for ( pad = 0; i < 3; i++, pad++ ) { buf[i] = '\0'; } byte = buf; bits = (byte[0] & 0xff) << 16; bits |= (byte[1] & 0xff) << 8; bits |= (byte[2] & 0xff); for ( i = 0; i < 4; i++, len++, bits <<= 6 ) { if ( len >= wrap ) { *(*out)++ = '\n'; *(*out)++ = ' '; len = 1; } if( i + pad < 4 ) { /* get b64 digit from low order 6 bits */ *(*out)++ = nib2b64[ (bits & 0xfc0000L) >> 18 ]; } else { *(*out)++ = '='; } } } *(*out)++ = '\n'; } /* * ldif_type_and_value return BER malloc'd, zero-terminated LDIF line */ /* NOTE: only preserved for binary compatibility */ char * ldif_put( int type, LDAP_CONST char *name, LDAP_CONST char *val, ber_len_t vlen ) { return ldif_put_wrap( type, name, val, vlen, LDIF_LINE_WIDTH ); } char * ldif_put_wrap( int type, LDAP_CONST char *name, LDAP_CONST char *val, ber_len_t vlen, ber_len_t wrap ) { char *buf, *p; ber_len_t nlen; nlen = ( name != NULL ) ? strlen( name ) : 0; buf = (char *) ber_memalloc( LDIF_SIZE_NEEDED_WRAP( nlen, vlen, wrap ) + 1 ); if ( buf == NULL ) { ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug, _("ldif_type_and_value: malloc failed!")); return NULL; } p = buf; ldif_sput_wrap( &p, type, name, val, vlen, wrap ); *p = '\0'; return( buf ); } int ldif_is_not_printable( LDAP_CONST char *val, ber_len_t vlen ) { if( vlen == 0 || val == NULL ) { return -1; } if( isgraph( (unsigned char) val[0] ) && val[0] != ':' && val[0] != '<' && isgraph( (unsigned char) val[vlen-1] ) ) { ber_len_t i; for ( i = 0; val[i]; i++ ) { if ( !isascii( val[i] ) || !isprint( (unsigned char) val[i] ) ) { return 1; } } return 0; } return 1; } LDIFFP * ldif_open( LDAP_CONST char *file, LDAP_CONST char *mode ) { FILE *fp = fopen( file, mode ); LDIFFP *lfp = NULL; if ( fp ) { lfp = ber_memalloc( sizeof( LDIFFP )); lfp->fp = fp; lfp->prev = NULL; } return lfp; } void ldif_close( LDIFFP *lfp ) { LDIFFP *prev; while ( lfp ) { fclose( lfp->fp ); prev = lfp->prev; ber_memfree( lfp ); lfp = prev; } } #define LDIF_MAXLINE 4096 /* * ldif_read_record - read an ldif record. Return 1 for success, 0 for EOF, * -1 for error. */ int ldif_read_record( LDIFFP *lfp, unsigned long *lno, /* ptr to line number counter */ char **bufp, /* ptr to malloced output buffer */ int *buflenp ) /* ptr to length of *bufp */ { char line[LDIF_MAXLINE], *nbufp; ber_len_t lcur = 0, len; int last_ch = '\n', found_entry = 0, stop, top_comment = 0; for ( stop = 0; !stop; last_ch = line[len-1] ) { /* If we're at the end of this file, see if we should pop * back to a previous file. (return from an include) */ while ( feof( lfp->fp )) { if ( lfp->prev ) { LDIFFP *tmp = lfp->prev; fclose( lfp->fp ); *lfp = *tmp; ber_memfree( tmp ); } else { stop = 1; break; } } if ( !stop ) { if ( fgets( line, sizeof( line ), lfp->fp ) == NULL ) { stop = 1; len = 0; } else { len = strlen( line ); } } if ( stop ) { /* Add \n in case the file does not end with newline */ if (last_ch != '\n') { len = 1; line[0] = '\n'; line[1] = '\0'; goto last; } break; } /* Squash \r\n to \n */ if ( len > 1 && line[len-2] == '\r' ) { len--; line[len-1] = '\n'; } if ( last_ch == '\n' ) { (*lno)++; if ( line[0] == '\n' ) { if ( !found_entry ) { lcur = 0; top_comment = 0; continue; } break; } if ( !found_entry ) { if ( line[0] == '#' ) { top_comment = 1; } else if ( ! ( top_comment && line[0] == ' ' ) ) { /* Found a new entry */ found_entry = 1; if ( isdigit( (unsigned char) line[0] ) ) { /* skip index */ continue; } if ( !strncasecmp( line, "include:", STRLENOF("include:"))) { FILE *fp2; char *ptr; found_entry = 0; if ( line[len-1] == '\n' ) { len--; line[len] = '\0'; } ptr = line + STRLENOF("include:"); while (isspace((unsigned char) *ptr)) ptr++; fp2 = ldif_open_url( ptr ); if ( fp2 ) { LDIFFP *lnew = ber_memalloc( sizeof( LDIFFP )); if ( lnew == NULL ) { fclose( fp2 ); return 0; } lnew->prev = lfp->prev; lnew->fp = lfp->fp; lfp->prev = lnew; lfp->fp = fp2; line[len] = '\n'; len++; continue; } else { /* We failed to open the file, this should * be reported as an error somehow. */ ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug, _("ldif_read_record: include %s failed\n"), ptr ); return -1; } } } } } last: if ( *buflenp - lcur <= len ) { *buflenp += len + LDIF_MAXLINE; nbufp = ber_memrealloc( *bufp, *buflenp ); if( nbufp == NULL ) { return 0; } *bufp = nbufp; } strcpy( *bufp + lcur, line ); lcur += len; } return( found_entry ); } openldap-2.4.42+dfsg/libraries/libldap/result.c0000644000175000017500000010561512563404150020105 0ustar ryanryan/* result.c - wait for an ldap result */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (c) 1990 Regents of the University of Michigan. * All rights reserved. */ /* This notice applies to changes, created by or for Novell, Inc., * to preexisting works for which notices appear elsewhere in this file. * * Copyright (C) 1999, 2000 Novell, Inc. All Rights Reserved. * * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND TREATIES. * USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO VERSION * 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS AVAILABLE AT * HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE" IN THE * TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION OF THIS * WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP PUBLIC * LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT THE * PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY. *--- * Modification to OpenLDAP source by Novell, Inc. * April 2000 sfs Add code to process V3 referrals and search results *--- * Note: A verbatim copy of version 2.0.1 of the OpenLDAP Public License * can be found in the file "build/LICENSE-2.0.1" in this distribution * of OpenLDAP Software. */ /* * LDAPv3 (RFC 4511) * LDAPResult ::= SEQUENCE { * resultCode ENUMERATED { ... }, * matchedDN LDAPDN, * diagnosticMessage LDAPString, * referral [3] Referral OPTIONAL * } * Referral ::= SEQUENCE OF LDAPURL (one or more) * LDAPURL ::= LDAPString (limited to URL chars) */ #include "portable.h" #include #include #include #include #include #include #include #include "ldap-int.h" #include "ldap_log.h" #include "lutil.h" static int ldap_abandoned LDAP_P(( LDAP *ld, ber_int_t msgid )); static int ldap_mark_abandoned LDAP_P(( LDAP *ld, ber_int_t msgid )); static int wait4msg LDAP_P(( LDAP *ld, ber_int_t msgid, int all, struct timeval *timeout, LDAPMessage **result )); static ber_tag_t try_read1msg LDAP_P(( LDAP *ld, ber_int_t msgid, int all, LDAPConn *lc, LDAPMessage **result )); static ber_tag_t build_result_ber LDAP_P(( LDAP *ld, BerElement **bp, LDAPRequest *lr )); static void merge_error_info LDAP_P(( LDAP *ld, LDAPRequest *parentr, LDAPRequest *lr )); static LDAPMessage * chkResponseList LDAP_P(( LDAP *ld, int msgid, int all)); #define LDAP_MSG_X_KEEP_LOOKING (-2) /* * ldap_result - wait for an ldap result response to a message from the * ldap server. If msgid is LDAP_RES_ANY (-1), any message will be * accepted. If msgid is LDAP_RES_UNSOLICITED (0), any unsolicited * message is accepted. Otherwise ldap_result will wait for a response * with msgid. If all is LDAP_MSG_ONE (0) the first message with id * msgid will be accepted, otherwise, ldap_result will wait for all * responses with id msgid and then return a pointer to the entire list * of messages. In general, this is only useful for search responses, * which can be of three message types (zero or more entries, zero or * search references, followed by an ldap result). An extension to * LDAPv3 allows partial extended responses to be returned in response * to any request. The type of the first message received is returned. * When waiting, any messages that have been abandoned/discarded are * discarded. * * Example: * ldap_result( s, msgid, all, timeout, result ) */ int ldap_result( LDAP *ld, int msgid, int all, struct timeval *timeout, LDAPMessage **result ) { int rc; assert( ld != NULL ); assert( result != NULL ); Debug( LDAP_DEBUG_TRACE, "ldap_result ld %p msgid %d\n", (void *)ld, msgid, 0 ); LDAP_MUTEX_LOCK( &ld->ld_res_mutex ); rc = wait4msg( ld, msgid, all, timeout, result ); LDAP_MUTEX_UNLOCK( &ld->ld_res_mutex ); return rc; } /* protected by res_mutex */ static LDAPMessage * chkResponseList( LDAP *ld, int msgid, int all) { LDAPMessage *lm, **lastlm, *nextlm; int cnt = 0; /* * Look through the list of responses we have received on * this association and see if the response we're interested in * is there. If it is, return it. If not, call wait4msg() to * wait until it arrives or timeout occurs. */ LDAP_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex ); Debug( LDAP_DEBUG_TRACE, "ldap_chkResponseList ld %p msgid %d all %d\n", (void *)ld, msgid, all ); lastlm = &ld->ld_responses; for ( lm = ld->ld_responses; lm != NULL; lm = nextlm ) { nextlm = lm->lm_next; ++cnt; if ( ldap_abandoned( ld, lm->lm_msgid ) ) { Debug( LDAP_DEBUG_ANY, "response list msg abandoned, " "msgid %d message type %s\n", lm->lm_msgid, ldap_int_msgtype2str( lm->lm_msgtype ), 0 ); switch ( lm->lm_msgtype ) { case LDAP_RES_SEARCH_ENTRY: case LDAP_RES_SEARCH_REFERENCE: case LDAP_RES_INTERMEDIATE: break; default: /* there's no need to keep the id * in the abandoned list any longer */ ldap_mark_abandoned( ld, lm->lm_msgid ); break; } /* Remove this entry from list */ *lastlm = nextlm; ldap_msgfree( lm ); continue; } if ( msgid == LDAP_RES_ANY || lm->lm_msgid == msgid ) { LDAPMessage *tmp; if ( all == LDAP_MSG_ONE || all == LDAP_MSG_RECEIVED || msgid == LDAP_RES_UNSOLICITED ) { break; } tmp = lm->lm_chain_tail; if ( tmp->lm_msgtype == LDAP_RES_SEARCH_ENTRY || tmp->lm_msgtype == LDAP_RES_SEARCH_REFERENCE || tmp->lm_msgtype == LDAP_RES_INTERMEDIATE ) { tmp = NULL; } if ( tmp == NULL ) { lm = NULL; } break; } lastlm = &lm->lm_next; } if ( lm != NULL ) { /* Found an entry, remove it from the list */ if ( all == LDAP_MSG_ONE && lm->lm_chain != NULL ) { *lastlm = lm->lm_chain; lm->lm_chain->lm_next = lm->lm_next; lm->lm_chain->lm_chain_tail = ( lm->lm_chain_tail != lm ) ? lm->lm_chain_tail : lm->lm_chain; lm->lm_chain = NULL; lm->lm_chain_tail = NULL; } else { *lastlm = lm->lm_next; } lm->lm_next = NULL; } #ifdef LDAP_DEBUG if ( lm == NULL) { Debug( LDAP_DEBUG_TRACE, "ldap_chkResponseList returns ld %p NULL\n", (void *)ld, 0, 0); } else { Debug( LDAP_DEBUG_TRACE, "ldap_chkResponseList returns ld %p msgid %d, type 0x%02lx\n", (void *)ld, lm->lm_msgid, (unsigned long)lm->lm_msgtype ); } #endif return lm; } /* protected by res_mutex */ static int wait4msg( LDAP *ld, ber_int_t msgid, int all, struct timeval *timeout, LDAPMessage **result ) { int rc; struct timeval tv = { 0 }, tv0 = { 0 }, start_time_tv = { 0 }, *tvp = NULL; LDAPConn *lc; assert( ld != NULL ); assert( result != NULL ); LDAP_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex ); if ( timeout == NULL && ld->ld_options.ldo_tm_api.tv_sec >= 0 ) { tv = ld->ld_options.ldo_tm_api; timeout = &tv; } #ifdef LDAP_DEBUG if ( timeout == NULL ) { Debug( LDAP_DEBUG_TRACE, "wait4msg ld %p msgid %d (infinite timeout)\n", (void *)ld, msgid, 0 ); } else { Debug( LDAP_DEBUG_TRACE, "wait4msg ld %p msgid %d (timeout %ld usec)\n", (void *)ld, msgid, (long)timeout->tv_sec * 1000000 + timeout->tv_usec ); } #endif /* LDAP_DEBUG */ if ( timeout != NULL && timeout->tv_sec != -1 ) { tv0 = *timeout; tv = *timeout; tvp = &tv; #ifdef HAVE_GETTIMEOFDAY gettimeofday( &start_time_tv, NULL ); #else /* ! HAVE_GETTIMEOFDAY */ start_time_tv.tv_sec = time( NULL ); start_time_tv.tv_usec = 0; #endif /* ! HAVE_GETTIMEOFDAY */ } rc = LDAP_MSG_X_KEEP_LOOKING; while ( rc == LDAP_MSG_X_KEEP_LOOKING ) { #ifdef LDAP_DEBUG if ( ldap_debug & LDAP_DEBUG_TRACE ) { Debug( LDAP_DEBUG_TRACE, "wait4msg continue ld %p msgid %d all %d\n", (void *)ld, msgid, all ); ldap_dump_connection( ld, ld->ld_conns, 1 ); LDAP_MUTEX_LOCK( &ld->ld_req_mutex ); ldap_dump_requests_and_responses( ld ); LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex ); } #endif /* LDAP_DEBUG */ if ( ( *result = chkResponseList( ld, msgid, all ) ) != NULL ) { rc = (*result)->lm_msgtype; } else { int lc_ready = 0; LDAP_MUTEX_LOCK( &ld->ld_conn_mutex ); for ( lc = ld->ld_conns; lc != NULL; lc = lc->lconn_next ) { if ( ber_sockbuf_ctrl( lc->lconn_sb, LBER_SB_OPT_DATA_READY, NULL ) ) { lc_ready = 2; /* ready at ber level, not socket level */ break; } } if ( !lc_ready ) { int err; rc = ldap_int_select( ld, tvp ); if ( rc == -1 ) { err = sock_errno(); #ifdef LDAP_DEBUG Debug( LDAP_DEBUG_TRACE, "ldap_int_select returned -1: errno %d\n", err, 0, 0 ); #endif } if ( rc == 0 || ( rc == -1 && ( !LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_RESTART) || err != EINTR ) ) ) { ld->ld_errno = (rc == -1 ? LDAP_SERVER_DOWN : LDAP_TIMEOUT); LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); return( rc ); } if ( rc == -1 ) { rc = LDAP_MSG_X_KEEP_LOOKING; /* select interrupted: loop */ } else { lc_ready = 1; } } if ( lc_ready ) { LDAPConn *lnext; int serviced = 0; rc = LDAP_MSG_X_KEEP_LOOKING; LDAP_MUTEX_LOCK( &ld->ld_req_mutex ); if ( ld->ld_requests && ld->ld_requests->lr_status == LDAP_REQST_WRITING && ldap_is_write_ready( ld, ld->ld_requests->lr_conn->lconn_sb ) ) { serviced = 1; ldap_int_flush_request( ld, ld->ld_requests ); } for ( lc = ld->ld_conns; rc == LDAP_MSG_X_KEEP_LOOKING && lc != NULL; lc = lnext ) { if ( lc->lconn_status == LDAP_CONNST_CONNECTED && ldap_is_read_ready( ld, lc->lconn_sb ) ) { serviced = 1; /* Don't let it get freed out from under us */ ++lc->lconn_refcnt; rc = try_read1msg( ld, msgid, all, lc, result ); lnext = lc->lconn_next; /* Only take locks if we're really freeing */ if ( lc->lconn_refcnt <= 1 ) { ldap_free_connection( ld, lc, 0, 1 ); } else { --lc->lconn_refcnt; } } else { lnext = lc->lconn_next; } } LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex ); /* Quit looping if no one handled any socket events */ if (!serviced && lc_ready == 1) rc = -1; } LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); } if ( rc == LDAP_MSG_X_KEEP_LOOKING && tvp != NULL ) { struct timeval curr_time_tv = { 0 }, delta_time_tv = { 0 }; #ifdef HAVE_GETTIMEOFDAY gettimeofday( &curr_time_tv, NULL ); #else /* ! HAVE_GETTIMEOFDAY */ curr_time_tv.tv_sec = time( NULL ); curr_time_tv.tv_usec = 0; #endif /* ! HAVE_GETTIMEOFDAY */ /* delta_time = tmp_time - start_time */ delta_time_tv.tv_sec = curr_time_tv.tv_sec - start_time_tv.tv_sec; delta_time_tv.tv_usec = curr_time_tv.tv_usec - start_time_tv.tv_usec; if ( delta_time_tv.tv_usec < 0 ) { delta_time_tv.tv_sec--; delta_time_tv.tv_usec += 1000000; } /* tv0 < delta_time ? */ if ( ( tv0.tv_sec < delta_time_tv.tv_sec ) || ( ( tv0.tv_sec == delta_time_tv.tv_sec ) && ( tv0.tv_usec < delta_time_tv.tv_usec ) ) ) { rc = 0; /* timed out */ ld->ld_errno = LDAP_TIMEOUT; break; } /* tv0 -= delta_time */ tv0.tv_sec -= delta_time_tv.tv_sec; tv0.tv_usec -= delta_time_tv.tv_usec; if ( tv0.tv_usec < 0 ) { tv0.tv_sec--; tv0.tv_usec += 1000000; } tv.tv_sec = tv0.tv_sec; tv.tv_usec = tv0.tv_usec; Debug( LDAP_DEBUG_TRACE, "wait4msg ld %p %ld s %ld us to go\n", (void *)ld, (long) tv.tv_sec, (long) tv.tv_usec ); start_time_tv.tv_sec = curr_time_tv.tv_sec; start_time_tv.tv_usec = curr_time_tv.tv_usec; } } return( rc ); } /* protected by res_mutex, conn_mutex and req_mutex */ static ber_tag_t try_read1msg( LDAP *ld, ber_int_t msgid, int all, LDAPConn *lc, LDAPMessage **result ) { BerElement *ber; LDAPMessage *newmsg, *l, *prev; ber_int_t id; ber_tag_t tag; ber_len_t len; int foundit = 0; LDAPRequest *lr, *tmplr, dummy_lr = { 0 }; BerElement tmpber; int rc, refer_cnt, hadref, simple_request, err; ber_int_t lderr; #ifdef LDAP_CONNECTIONLESS LDAPMessage *tmp = NULL, *chain_head = NULL; int moremsgs = 0, isv2 = 0; #endif assert( ld != NULL ); assert( lc != NULL ); LDAP_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex ); LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex ); LDAP_ASSERT_MUTEX_OWNER( &ld->ld_req_mutex ); Debug( LDAP_DEBUG_TRACE, "read1msg: ld %p msgid %d all %d\n", (void *)ld, msgid, all ); retry: if ( lc->lconn_ber == NULL ) { lc->lconn_ber = ldap_alloc_ber_with_options( ld ); if ( lc->lconn_ber == NULL ) { return -1; } } ber = lc->lconn_ber; assert( LBER_VALID (ber) ); /* get the next message */ sock_errset(0); #ifdef LDAP_CONNECTIONLESS if ( LDAP_IS_UDP(ld) ) { struct sockaddr_storage from; ber_int_sb_read( lc->lconn_sb, &from, sizeof(struct sockaddr_storage) ); if ( ld->ld_options.ldo_version == LDAP_VERSION2 ) isv2 = 1; } nextresp3: #endif tag = ber_get_next( lc->lconn_sb, &len, ber ); switch ( tag ) { case LDAP_TAG_MESSAGE: /* * We read a complete message. * The connection should no longer need this ber. */ lc->lconn_ber = NULL; break; case LBER_DEFAULT: err = sock_errno(); #ifdef LDAP_DEBUG Debug( LDAP_DEBUG_CONNS, "ber_get_next failed.\n", 0, 0, 0 ); #endif if ( err == EWOULDBLOCK ) return LDAP_MSG_X_KEEP_LOOKING; if ( err == EAGAIN ) return LDAP_MSG_X_KEEP_LOOKING; ld->ld_errno = LDAP_SERVER_DOWN; --lc->lconn_refcnt; lc->lconn_status = 0; return -1; default: ld->ld_errno = LDAP_LOCAL_ERROR; return -1; } /* message id */ if ( ber_get_int( ber, &id ) == LBER_ERROR ) { ber_free( ber, 1 ); ld->ld_errno = LDAP_DECODING_ERROR; return( -1 ); } /* id == 0 iff unsolicited notification message (RFC 4511) */ /* id < 0 is invalid, just toss it. FIXME: should we disconnect? */ if ( id < 0 ) { goto retry_ber; } /* if it's been abandoned, toss it */ if ( id > 0 ) { if ( ldap_abandoned( ld, id ) ) { /* the message type */ tag = ber_peek_tag( ber, &len ); switch ( tag ) { case LDAP_RES_SEARCH_ENTRY: case LDAP_RES_SEARCH_REFERENCE: case LDAP_RES_INTERMEDIATE: case LBER_ERROR: break; default: /* there's no need to keep the id * in the abandoned list any longer */ ldap_mark_abandoned( ld, id ); break; } Debug( LDAP_DEBUG_ANY, "abandoned/discarded ld %p msgid %d message type %s\n", (void *)ld, id, ldap_int_msgtype2str( tag ) ); retry_ber: ber_free( ber, 1 ); if ( ber_sockbuf_ctrl( lc->lconn_sb, LBER_SB_OPT_DATA_READY, NULL ) ) { goto retry; } return( LDAP_MSG_X_KEEP_LOOKING ); /* continue looking */ } lr = ldap_find_request_by_msgid( ld, id ); if ( lr == NULL ) { const char *msg = "unknown"; /* the message type */ tag = ber_peek_tag( ber, &len ); switch ( tag ) { case LBER_ERROR: break; default: msg = ldap_int_msgtype2str( tag ); break; } Debug( LDAP_DEBUG_ANY, "no request for response on ld %p msgid %d message type %s (tossing)\n", (void *)ld, id, msg ); goto retry_ber; } #ifdef LDAP_CONNECTIONLESS if ( LDAP_IS_UDP(ld) && isv2 ) { ber_scanf(ber, "x{"); } nextresp2: ; #endif } /* the message type */ tag = ber_peek_tag( ber, &len ); if ( tag == LBER_ERROR ) { ld->ld_errno = LDAP_DECODING_ERROR; ber_free( ber, 1 ); return( -1 ); } Debug( LDAP_DEBUG_TRACE, "read1msg: ld %p msgid %d message type %s\n", (void *)ld, id, ldap_int_msgtype2str( tag ) ); if ( id == 0 ) { /* unsolicited notification message (RFC 4511) */ if ( tag != LDAP_RES_EXTENDED ) { /* toss it */ goto retry_ber; /* strictly speaking, it's an error; from RFC 4511: 4.4. Unsolicited Notification An unsolicited notification is an LDAPMessage sent from the server to the client that is not in response to any LDAPMessage received by the server. It is used to signal an extraordinary condition in the server or in the LDAP session between the client and the server. The notification is of an advisory nature, and the server will not expect any response to be returned from the client. The unsolicited notification is structured as an LDAPMessage in which the messageID is zero and protocolOp is set to the extendedResp choice using the ExtendedResponse type (See Section 4.12). The responseName field of the ExtendedResponse always contains an LDAPOID that is unique for this notification. * however, since unsolicited responses * are of advisory nature, better * toss it, right now */ #if 0 ld->ld_errno = LDAP_DECODING_ERROR; ber_free( ber, 1 ); return( -1 ); #endif } lr = &dummy_lr; } id = lr->lr_origid; refer_cnt = 0; hadref = simple_request = 0; rc = LDAP_MSG_X_KEEP_LOOKING; /* default is to keep looking (no response found) */ lr->lr_res_msgtype = tag; /* * Check for V3 search reference */ if ( tag == LDAP_RES_SEARCH_REFERENCE ) { if ( ld->ld_version > LDAP_VERSION2 ) { /* This is a V3 search reference */ if ( LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_REFERRALS) || lr->lr_parent != NULL ) { char **refs = NULL; tmpber = *ber; /* Get the referral list */ if ( ber_scanf( &tmpber, "{v}", &refs ) == LBER_ERROR ) { rc = LDAP_DECODING_ERROR; } else { /* Note: refs array is freed by ldap_chase_v3referrals */ refer_cnt = ldap_chase_v3referrals( ld, lr, refs, 1, &lr->lr_res_error, &hadref ); if ( refer_cnt > 0 ) { /* successfully chased reference */ /* If haven't got end search, set chasing referrals */ if ( lr->lr_status != LDAP_REQST_COMPLETED ) { lr->lr_status = LDAP_REQST_CHASINGREFS; Debug( LDAP_DEBUG_TRACE, "read1msg: search ref chased, " "mark request chasing refs, " "id = %d\n", lr->lr_msgid, 0, 0 ); } } } } } } else if ( tag != LDAP_RES_SEARCH_ENTRY && tag != LDAP_RES_INTERMEDIATE ) { /* All results that just return a status, i.e. don't return data * go through the following code. This code also chases V2 referrals * and checks if all referrals have been chased. */ char *lr_res_error = NULL; tmpber = *ber; /* struct copy */ if ( ber_scanf( &tmpber, "{eAA", &lderr, &lr->lr_res_matched, &lr_res_error ) != LBER_ERROR ) { if ( lr_res_error != NULL ) { if ( lr->lr_res_error != NULL ) { (void)ldap_append_referral( ld, &lr->lr_res_error, lr_res_error ); LDAP_FREE( (char *)lr_res_error ); } else { lr->lr_res_error = lr_res_error; } lr_res_error = NULL; } /* Do we need to check for referrals? */ if ( tag != LDAP_RES_BIND && ( LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_REFERRALS) || lr->lr_parent != NULL )) { char **refs = NULL; ber_len_t len; /* Check if V3 referral */ if ( ber_peek_tag( &tmpber, &len ) == LDAP_TAG_REFERRAL ) { if ( ld->ld_version > LDAP_VERSION2 ) { /* Get the referral list */ if ( ber_scanf( &tmpber, "{v}", &refs) == LBER_ERROR) { rc = LDAP_DECODING_ERROR; lr->lr_status = LDAP_REQST_COMPLETED; Debug( LDAP_DEBUG_TRACE, "read1msg: referral decode error, " "mark request completed, ld %p msgid %d\n", (void *)ld, lr->lr_msgid, 0 ); } else { /* Chase the referral * refs array is freed by ldap_chase_v3referrals */ refer_cnt = ldap_chase_v3referrals( ld, lr, refs, 0, &lr->lr_res_error, &hadref ); lr->lr_status = LDAP_REQST_COMPLETED; Debug( LDAP_DEBUG_TRACE, "read1msg: referral %s chased, " "mark request completed, ld %p msgid %d\n", refer_cnt > 0 ? "" : "not", (void *)ld, lr->lr_msgid); if ( refer_cnt < 0 ) { refer_cnt = 0; } } } } else { switch ( lderr ) { case LDAP_SUCCESS: case LDAP_COMPARE_TRUE: case LDAP_COMPARE_FALSE: break; default: if ( lr->lr_res_error == NULL ) { break; } /* pedantic, should never happen */ if ( lr->lr_res_error[ 0 ] == '\0' ) { LDAP_FREE( lr->lr_res_error ); lr->lr_res_error = NULL; break; } /* V2 referrals are in error string */ refer_cnt = ldap_chase_referrals( ld, lr, &lr->lr_res_error, -1, &hadref ); lr->lr_status = LDAP_REQST_COMPLETED; Debug( LDAP_DEBUG_TRACE, "read1msg: V2 referral chased, " "mark request completed, id = %d\n", lr->lr_msgid, 0, 0 ); break; } } } /* save errno, message, and matched string */ if ( !hadref || lr->lr_res_error == NULL ) { lr->lr_res_errno = lderr == LDAP_PARTIAL_RESULTS ? LDAP_SUCCESS : lderr; } else if ( ld->ld_errno != LDAP_SUCCESS ) { lr->lr_res_errno = ld->ld_errno; } else { lr->lr_res_errno = LDAP_PARTIAL_RESULTS; } } /* in any case, don't leave any lr_res_error 'round */ if ( lr_res_error ) { LDAP_FREE( lr_res_error ); } Debug( LDAP_DEBUG_TRACE, "read1msg: ld %p %d new referrals\n", (void *)ld, refer_cnt, 0 ); if ( refer_cnt != 0 ) { /* chasing referrals */ ber_free( ber, 1 ); ber = NULL; if ( refer_cnt < 0 ) { ldap_return_request( ld, lr, 0 ); return( -1 ); /* fatal error */ } lr->lr_res_errno = LDAP_SUCCESS; /* sucessfully chased referral */ if ( lr->lr_res_matched ) { LDAP_FREE( lr->lr_res_matched ); lr->lr_res_matched = NULL; } } else { if ( lr->lr_outrefcnt <= 0 && lr->lr_parent == NULL ) { /* request without any referrals */ simple_request = ( hadref ? 0 : 1 ); } else { /* request with referrals or child request */ ber_free( ber, 1 ); ber = NULL; } lr->lr_status = LDAP_REQST_COMPLETED; /* declare this request done */ Debug( LDAP_DEBUG_TRACE, "read1msg: mark request completed, ld %p msgid %d\n", (void *)ld, lr->lr_msgid, 0); tmplr = lr; while ( lr->lr_parent != NULL ) { merge_error_info( ld, lr->lr_parent, lr ); lr = lr->lr_parent; if ( --lr->lr_outrefcnt > 0 ) { break; /* not completely done yet */ } } /* ITS#6744: Original lr was refcounted when we retrieved it, * must release it now that we're working with the parent */ if ( tmplr->lr_parent ) { ldap_return_request( ld, tmplr, 0 ); } /* Check if all requests are finished, lr is now parent */ tmplr = lr; if ( tmplr->lr_status == LDAP_REQST_COMPLETED ) { for ( tmplr = lr->lr_child; tmplr != NULL; tmplr = tmplr->lr_refnext ) { if ( tmplr->lr_status != LDAP_REQST_COMPLETED ) break; } } /* This is the parent request if the request has referrals */ if ( lr->lr_outrefcnt <= 0 && lr->lr_parent == NULL && tmplr == NULL ) { id = lr->lr_msgid; tag = lr->lr_res_msgtype; Debug( LDAP_DEBUG_TRACE, "request done: ld %p msgid %d\n", (void *)ld, id, 0 ); Debug( LDAP_DEBUG_TRACE, "res_errno: %d, res_error: <%s>, " "res_matched: <%s>\n", lr->lr_res_errno, lr->lr_res_error ? lr->lr_res_error : "", lr->lr_res_matched ? lr->lr_res_matched : "" ); if ( !simple_request ) { ber_free( ber, 1 ); ber = NULL; if ( build_result_ber( ld, &ber, lr ) == LBER_ERROR ) { rc = -1; /* fatal error */ } } if ( lr != &dummy_lr ) { ldap_return_request( ld, lr, 1 ); } lr = NULL; } /* * RFC 4511 unsolicited (id == 0) responses * shouldn't necessarily end the connection */ if ( lc != NULL && id != 0 ) { --lc->lconn_refcnt; lc = NULL; } } } if ( lr != NULL ) { if ( lr != &dummy_lr ) { ldap_return_request( ld, lr, 0 ); } lr = NULL; } if ( ber == NULL ) { return( rc ); } /* try to handle unsolicited responses as appropriate */ if ( id == 0 && msgid > LDAP_RES_UNSOLICITED ) { int is_nod = 0; tag = ber_peek_tag( &tmpber, &len ); /* we have a res oid */ if ( tag == LDAP_TAG_EXOP_RES_OID ) { static struct berval bv_nod = BER_BVC( LDAP_NOTICE_OF_DISCONNECTION ); struct berval resoid = BER_BVNULL; if ( ber_scanf( &tmpber, "m", &resoid ) == LBER_ERROR ) { ld->ld_errno = LDAP_DECODING_ERROR; ber_free( ber, 1 ); return -1; } assert( !BER_BVISEMPTY( &resoid ) ); is_nod = ber_bvcmp( &resoid, &bv_nod ) == 0; tag = ber_peek_tag( &tmpber, &len ); } #if 0 /* don't need right now */ /* we have res data */ if ( tag == LDAP_TAG_EXOP_RES_VALUE ) { struct berval resdata; if ( ber_scanf( &tmpber, "m", &resdata ) == LBER_ERROR ) { ld->ld_errno = LDAP_DECODING_ERROR; ber_free( ber, 0 ); return ld->ld_errno; } /* use it... */ } #endif /* handle RFC 4511 "Notice of Disconnection" locally */ if ( is_nod ) { if ( tag == LDAP_TAG_EXOP_RES_VALUE ) { ld->ld_errno = LDAP_DECODING_ERROR; ber_free( ber, 1 ); return -1; } /* get rid of the connection... */ if ( lc != NULL ) { --lc->lconn_refcnt; } /* need to return -1, because otherwise * a valid result is expected */ ld->ld_errno = lderr; return -1; } } /* make a new ldap message */ newmsg = (LDAPMessage *) LDAP_CALLOC( 1, sizeof(LDAPMessage) ); if ( newmsg == NULL ) { ld->ld_errno = LDAP_NO_MEMORY; return( -1 ); } newmsg->lm_msgid = (int)id; newmsg->lm_msgtype = tag; newmsg->lm_ber = ber; newmsg->lm_chain_tail = newmsg; #ifdef LDAP_CONNECTIONLESS /* CLDAP replies all fit in a single datagram. In LDAPv2 RFC1798 * the responses are all a sequence wrapped in one message. In * LDAPv3 each response is in its own message. The datagram must * end with a SearchResult. We can't just parse each response in * separate calls to try_read1msg because the header info is only * present at the beginning of the datagram, not at the beginning * of each response. So parse all the responses at once and queue * them up, then pull off the first response to return to the * caller when all parsing is complete. */ if ( LDAP_IS_UDP(ld) ) { /* If not a result, look for more */ if ( tag != LDAP_RES_SEARCH_RESULT ) { int ok = 0; moremsgs = 1; if (isv2) { /* LDAPv2: dup the current ber, skip past the current * response, and see if there are any more after it. */ ber = ber_dup( ber ); ber_scanf( ber, "x" ); if ( ber_peek_tag( ber, &len ) != LBER_DEFAULT ) { /* There's more - dup the ber buffer so they can all be * individually freed by ldap_msgfree. */ struct berval bv; ber_get_option( ber, LBER_OPT_BER_REMAINING_BYTES, &len ); bv.bv_val = LDAP_MALLOC( len ); if ( bv.bv_val ) { ok = 1; ber_read( ber, bv.bv_val, len ); bv.bv_len = len; ber_init2( ber, &bv, ld->ld_lberoptions ); } } } else { /* LDAPv3: Just allocate a new ber. Since this is a buffered * datagram, if the sockbuf is readable we still have data * to parse. */ ber = ldap_alloc_ber_with_options( ld ); if ( ber_sockbuf_ctrl( lc->lconn_sb, LBER_SB_OPT_DATA_READY, NULL ) ) ok = 1; } /* set up response chain */ if ( tmp == NULL ) { newmsg->lm_next = ld->ld_responses; ld->ld_responses = newmsg; chain_head = newmsg; } else { tmp->lm_chain = newmsg; } chain_head->lm_chain_tail = newmsg; tmp = newmsg; /* "ok" means there's more to parse */ if ( ok ) { if ( isv2 ) { goto nextresp2; } else { goto nextresp3; } } else { /* got to end of datagram without a SearchResult. Free * our dup'd ber, but leave any buffer alone. For v2 case, * the previous response is still using this buffer. For v3, * the new ber has no buffer to free yet. */ ber_free( ber, 0 ); return -1; } } else if ( moremsgs ) { /* got search result, and we had multiple responses in 1 datagram. * stick the result onto the end of the chain, and then pull the * first response off the head of the chain. */ tmp->lm_chain = newmsg; chain_head->lm_chain_tail = newmsg; *result = chkResponseList( ld, msgid, all ); ld->ld_errno = LDAP_SUCCESS; return( (*result)->lm_msgtype ); } } #endif /* LDAP_CONNECTIONLESS */ /* is this the one we're looking for? */ if ( msgid == LDAP_RES_ANY || id == msgid ) { if ( all == LDAP_MSG_ONE || ( newmsg->lm_msgtype != LDAP_RES_SEARCH_RESULT && newmsg->lm_msgtype != LDAP_RES_SEARCH_ENTRY && newmsg->lm_msgtype != LDAP_RES_INTERMEDIATE && newmsg->lm_msgtype != LDAP_RES_SEARCH_REFERENCE ) ) { *result = newmsg; ld->ld_errno = LDAP_SUCCESS; return( tag ); } else if ( newmsg->lm_msgtype == LDAP_RES_SEARCH_RESULT) { foundit = 1; /* return the chain later */ } } /* * if not, we must add it to the list of responses. if * the msgid is already there, it must be part of an existing * search response. */ prev = NULL; for ( l = ld->ld_responses; l != NULL; l = l->lm_next ) { if ( l->lm_msgid == newmsg->lm_msgid ) { break; } prev = l; } /* not part of an existing search response */ if ( l == NULL ) { if ( foundit ) { *result = newmsg; goto exit; } newmsg->lm_next = ld->ld_responses; ld->ld_responses = newmsg; goto exit; } Debug( LDAP_DEBUG_TRACE, "adding response ld %p msgid %d type %ld:\n", (void *)ld, newmsg->lm_msgid, (long) newmsg->lm_msgtype ); /* part of a search response - add to end of list of entries */ l->lm_chain_tail->lm_chain = newmsg; l->lm_chain_tail = newmsg; /* return the whole chain if that's what we were looking for */ if ( foundit ) { if ( prev == NULL ) { ld->ld_responses = l->lm_next; } else { prev->lm_next = l->lm_next; } *result = l; } exit: if ( foundit ) { ld->ld_errno = LDAP_SUCCESS; return( tag ); } if ( lc && ber_sockbuf_ctrl( lc->lconn_sb, LBER_SB_OPT_DATA_READY, NULL ) ) { goto retry; } return( LDAP_MSG_X_KEEP_LOOKING ); /* continue looking */ } static ber_tag_t build_result_ber( LDAP *ld, BerElement **bp, LDAPRequest *lr ) { ber_len_t len; ber_tag_t tag; ber_int_t along; BerElement *ber; *bp = NULL; ber = ldap_alloc_ber_with_options( ld ); if( ber == NULL ) { ld->ld_errno = LDAP_NO_MEMORY; return LBER_ERROR; } if ( ber_printf( ber, "{it{ess}}", lr->lr_msgid, lr->lr_res_msgtype, lr->lr_res_errno, lr->lr_res_matched ? lr->lr_res_matched : "", lr->lr_res_error ? lr->lr_res_error : "" ) == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( LBER_ERROR ); } ber_reset( ber, 1 ); if ( ber_skip_tag( ber, &len ) == LBER_ERROR ) { ld->ld_errno = LDAP_DECODING_ERROR; ber_free( ber, 1 ); return( LBER_ERROR ); } if ( ber_get_enum( ber, &along ) == LBER_ERROR ) { ld->ld_errno = LDAP_DECODING_ERROR; ber_free( ber, 1 ); return( LBER_ERROR ); } tag = ber_peek_tag( ber, &len ); if ( tag == LBER_ERROR ) { ld->ld_errno = LDAP_DECODING_ERROR; ber_free( ber, 1 ); return( LBER_ERROR ); } *bp = ber; return tag; } /* * Merge error information in "lr" with "parentr" error code and string. */ static void merge_error_info( LDAP *ld, LDAPRequest *parentr, LDAPRequest *lr ) { if ( lr->lr_res_errno == LDAP_PARTIAL_RESULTS ) { parentr->lr_res_errno = lr->lr_res_errno; if ( lr->lr_res_error != NULL ) { (void)ldap_append_referral( ld, &parentr->lr_res_error, lr->lr_res_error ); } } else if ( lr->lr_res_errno != LDAP_SUCCESS && parentr->lr_res_errno == LDAP_SUCCESS ) { parentr->lr_res_errno = lr->lr_res_errno; if ( parentr->lr_res_error != NULL ) { LDAP_FREE( parentr->lr_res_error ); } parentr->lr_res_error = lr->lr_res_error; lr->lr_res_error = NULL; if ( LDAP_NAME_ERROR( lr->lr_res_errno ) ) { if ( parentr->lr_res_matched != NULL ) { LDAP_FREE( parentr->lr_res_matched ); } parentr->lr_res_matched = lr->lr_res_matched; lr->lr_res_matched = NULL; } } Debug( LDAP_DEBUG_TRACE, "merged parent (id %d) error info: ", parentr->lr_msgid, 0, 0 ); Debug( LDAP_DEBUG_TRACE, "result errno %d, error <%s>, matched <%s>\n", parentr->lr_res_errno, parentr->lr_res_error ? parentr->lr_res_error : "", parentr->lr_res_matched ? parentr->lr_res_matched : "" ); } int ldap_msgtype( LDAPMessage *lm ) { assert( lm != NULL ); return ( lm != NULL ) ? (int)lm->lm_msgtype : -1; } int ldap_msgid( LDAPMessage *lm ) { assert( lm != NULL ); return ( lm != NULL ) ? lm->lm_msgid : -1; } const char * ldap_int_msgtype2str( ber_tag_t tag ) { switch( tag ) { case LDAP_RES_ADD: return "add"; case LDAP_RES_BIND: return "bind"; case LDAP_RES_COMPARE: return "compare"; case LDAP_RES_DELETE: return "delete"; case LDAP_RES_EXTENDED: return "extended-result"; case LDAP_RES_INTERMEDIATE: return "intermediate"; case LDAP_RES_MODIFY: return "modify"; case LDAP_RES_RENAME: return "rename"; case LDAP_RES_SEARCH_ENTRY: return "search-entry"; case LDAP_RES_SEARCH_REFERENCE: return "search-reference"; case LDAP_RES_SEARCH_RESULT: return "search-result"; } return "unknown"; } int ldap_msgfree( LDAPMessage *lm ) { LDAPMessage *next; int type = 0; Debug( LDAP_DEBUG_TRACE, "ldap_msgfree\n", 0, 0, 0 ); for ( ; lm != NULL; lm = next ) { next = lm->lm_chain; type = lm->lm_msgtype; ber_free( lm->lm_ber, 1 ); LDAP_FREE( (char *) lm ); } return type; } /* * ldap_msgdelete - delete a message. It returns: * 0 if the entire message was deleted * -1 if the message was not found, or only part of it was found */ int ldap_msgdelete( LDAP *ld, int msgid ) { LDAPMessage *lm, *prev; int rc = 0; assert( ld != NULL ); Debug( LDAP_DEBUG_TRACE, "ldap_msgdelete ld=%p msgid=%d\n", (void *)ld, msgid, 0 ); LDAP_MUTEX_LOCK( &ld->ld_res_mutex ); prev = NULL; for ( lm = ld->ld_responses; lm != NULL; lm = lm->lm_next ) { if ( lm->lm_msgid == msgid ) { break; } prev = lm; } if ( lm == NULL ) { rc = -1; } else { if ( prev == NULL ) { ld->ld_responses = lm->lm_next; } else { prev->lm_next = lm->lm_next; } } LDAP_MUTEX_UNLOCK( &ld->ld_res_mutex ); if ( lm ) { switch ( ldap_msgfree( lm ) ) { case LDAP_RES_SEARCH_ENTRY: case LDAP_RES_SEARCH_REFERENCE: case LDAP_RES_INTERMEDIATE: rc = -1; break; default: break; } } return rc; } /* * ldap_abandoned * * return the location of the message id in the array of abandoned * message ids, or -1 */ static int ldap_abandoned( LDAP *ld, ber_int_t msgid ) { int ret, idx; assert( msgid >= 0 ); LDAP_MUTEX_LOCK( &ld->ld_abandon_mutex ); ret = ldap_int_bisect_find( ld->ld_abandoned, ld->ld_nabandoned, msgid, &idx ); LDAP_MUTEX_UNLOCK( &ld->ld_abandon_mutex ); return ret; } /* * ldap_mark_abandoned */ static int ldap_mark_abandoned( LDAP *ld, ber_int_t msgid ) { int ret, idx; assert( msgid >= 0 ); LDAP_MUTEX_LOCK( &ld->ld_abandon_mutex ); ret = ldap_int_bisect_find( ld->ld_abandoned, ld->ld_nabandoned, msgid, &idx ); if (ret <= 0) { /* error or already deleted by another thread */ LDAP_MUTEX_UNLOCK( &ld->ld_abandon_mutex ); return ret; } /* still in abandoned array, so delete */ ret = ldap_int_bisect_delete( &ld->ld_abandoned, &ld->ld_nabandoned, msgid, idx ); LDAP_MUTEX_UNLOCK( &ld->ld_abandon_mutex ); return ret; } openldap-2.4.42+dfsg/libraries/libldap/charray.c0000644000175000017500000001000712563404150020206 0ustar ryanryan/* charray.c - routines for dealing with char * arrays */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #include "portable.h" #include #include #include #include "ldap-int.h" int ldap_charray_add( char ***a, const char *s ) { int n; if ( *a == NULL ) { *a = (char **) LDAP_MALLOC( 2 * sizeof(char *) ); n = 0; if( *a == NULL ) { return -1; } } else { char **new; for ( n = 0; *a != NULL && (*a)[n] != NULL; n++ ) { ; /* NULL */ } new = (char **) LDAP_REALLOC( (char *) *a, (n + 2) * sizeof(char *) ); if( new == NULL ) { /* caller is required to call ldap_charray_free(*a) */ return -1; } *a = new; } (*a)[n] = LDAP_STRDUP(s); if( (*a)[n] == NULL ) { return 1; } (*a)[++n] = NULL; return 0; } int ldap_charray_merge( char ***a, char **s ) { int i, n, nn; char **aa; for ( n = 0; *a != NULL && (*a)[n] != NULL; n++ ) { ; /* NULL */ } for ( nn = 0; s[nn] != NULL; nn++ ) { ; /* NULL */ } aa = (char **) LDAP_REALLOC( (char *) *a, (n + nn + 1) * sizeof(char *) ); if( aa == NULL ) { return -1; } *a = aa; for ( i = 0; i < nn; i++ ) { (*a)[n + i] = LDAP_STRDUP(s[i]); if( (*a)[n + i] == NULL ) { for( --i ; i >= 0 ; i-- ) { LDAP_FREE( (*a)[n + i] ); (*a)[n + i] = NULL; } return -1; } } (*a)[n + nn] = NULL; return 0; } void ldap_charray_free( char **a ) { char **p; if ( a == NULL ) { return; } for ( p = a; *p != NULL; p++ ) { if ( *p != NULL ) { LDAP_FREE( *p ); } } LDAP_FREE( (char *) a ); } int ldap_charray_inlist( char **a, const char *s ) { int i; if( a == NULL ) return 0; for ( i=0; a[i] != NULL; i++ ) { if ( strcasecmp( s, a[i] ) == 0 ) { return 1; } } return 0; } char ** ldap_charray_dup( char **a ) { int i; char **new; for ( i = 0; a[i] != NULL; i++ ) ; /* NULL */ new = (char **) LDAP_MALLOC( (i + 1) * sizeof(char *) ); if( new == NULL ) { return NULL; } for ( i = 0; a[i] != NULL; i++ ) { new[i] = LDAP_STRDUP( a[i] ); if( new[i] == NULL ) { for( --i ; i >= 0 ; i-- ) { LDAP_FREE( new[i] ); } LDAP_FREE( new ); return NULL; } } new[i] = NULL; return( new ); } char ** ldap_str2charray( const char *str_in, const char *brkstr ) { char **res; char *str, *s; char *lasts; int i; /* protect the input string from strtok */ str = LDAP_STRDUP( str_in ); if( str == NULL ) { return NULL; } i = 1; for ( s = str; ; LDAP_UTF8_INCR(s) ) { s = ldap_utf8_strpbrk( s, brkstr ); if ( !s ) break; i++; } res = (char **) LDAP_MALLOC( (i + 1) * sizeof(char *) ); if( res == NULL ) { LDAP_FREE( str ); return NULL; } i = 0; for ( s = ldap_utf8_strtok( str, brkstr, &lasts ); s != NULL; s = ldap_utf8_strtok( NULL, brkstr, &lasts ) ) { res[i] = LDAP_STRDUP( s ); if(res[i] == NULL) { for( --i ; i >= 0 ; i-- ) { LDAP_FREE( res[i] ); } LDAP_FREE( res ); LDAP_FREE( str ); return NULL; } i++; } res[i] = NULL; LDAP_FREE( str ); return( res ); } char * ldap_charray2str( char **a, const char *sep ) { char *s, **v, *p; int len; int slen; if( sep == NULL ) sep = " "; slen = strlen( sep ); len = 0; for ( v = a; *v != NULL; v++ ) { len += strlen( *v ) + slen; } if ( len == 0 ) { return NULL; } /* trim extra sep len */ len -= slen; s = LDAP_MALLOC ( len + 1 ); if ( s == NULL ) { return NULL; } p = s; for ( v = a; *v != NULL; v++ ) { if ( v != a ) { strncpy( p, sep, slen ); p += slen; } len = strlen( *v ); strncpy( p, *v, len ); p += len; } *p = '\0'; return s; } openldap-2.4.42+dfsg/libraries/libldap/tls_g.c0000644000175000017500000005172112563404150017675 0ustar ryanryan/* tls_g.c - Handle tls/ssl using GNUTLS. */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 2008-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* ACKNOWLEDGEMENTS: GNUTLS support written by Howard Chu and * Emily Backes; sponsored by The Written Word (thewrittenword.com) * and Stanford University (stanford.edu). */ #include "portable.h" #ifdef HAVE_GNUTLS #include "ldap_config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "ldap-int.h" #include "ldap-tls.h" #include #include #define DH_BITS (1024) typedef struct tlsg_ctx { struct ldapoptions *lo; gnutls_certificate_credentials_t cred; gnutls_dh_params_t dh_params; unsigned long verify_depth; int refcount; gnutls_priority_t prios; #ifdef LDAP_R_COMPILE ldap_pvt_thread_mutex_t ref_mutex; #endif } tlsg_ctx; typedef struct tlsg_session { gnutls_session_t session; tlsg_ctx *ctx; struct berval peer_der_dn; } tlsg_session; static int tlsg_parse_ciphers( tlsg_ctx *ctx, char *suites ); static int tlsg_cert_verify( tlsg_session *s ); #ifdef LDAP_R_COMPILE static int tlsg_mutex_init( void **priv ) { int err = 0; ldap_pvt_thread_mutex_t *lock = LDAP_MALLOC( sizeof( ldap_pvt_thread_mutex_t )); if ( !lock ) err = ENOMEM; if ( !err ) { err = ldap_pvt_thread_mutex_init( lock ); if ( err ) LDAP_FREE( lock ); else *priv = lock; } return err; } static int tlsg_mutex_destroy( void **lock ) { int err = ldap_pvt_thread_mutex_destroy( *lock ); LDAP_FREE( *lock ); return err; } static int tlsg_mutex_lock( void **lock ) { return ldap_pvt_thread_mutex_lock( *lock ); } static int tlsg_mutex_unlock( void **lock ) { return ldap_pvt_thread_mutex_unlock( *lock ); } static void tlsg_thr_init( void ) { gnutls_global_set_mutex (tlsg_mutex_init, tlsg_mutex_destroy, tlsg_mutex_lock, tlsg_mutex_unlock); } #endif /* LDAP_R_COMPILE */ /* * Initialize TLS subsystem. Should be called only once. */ static int tlsg_init( void ) { gnutls_global_init(); return 0; } /* * Tear down the TLS subsystem. Should only be called once. */ static void tlsg_destroy( void ) { gnutls_global_deinit(); } static tls_ctx * tlsg_ctx_new ( struct ldapoptions *lo ) { tlsg_ctx *ctx; ctx = ber_memcalloc ( 1, sizeof (*ctx) ); if ( ctx ) { ctx->lo = lo; if ( gnutls_certificate_allocate_credentials( &ctx->cred )) { ber_memfree( ctx ); return NULL; } ctx->refcount = 1; gnutls_priority_init( &ctx->prios, "NORMAL", NULL ); #ifdef LDAP_R_COMPILE ldap_pvt_thread_mutex_init( &ctx->ref_mutex ); #endif } return (tls_ctx *)ctx; } static void tlsg_ctx_ref( tls_ctx *ctx ) { tlsg_ctx *c = (tlsg_ctx *)ctx; LDAP_MUTEX_LOCK( &c->ref_mutex ); c->refcount++; LDAP_MUTEX_UNLOCK( &c->ref_mutex ); } static void tlsg_ctx_free ( tls_ctx *ctx ) { tlsg_ctx *c = (tlsg_ctx *)ctx; int refcount; if ( !c ) return; LDAP_MUTEX_LOCK( &c->ref_mutex ); refcount = --c->refcount; LDAP_MUTEX_UNLOCK( &c->ref_mutex ); if ( refcount ) return; gnutls_priority_deinit( c->prios ); gnutls_certificate_free_credentials( c->cred ); ber_memfree ( c ); } static int tlsg_getfile( const char *path, gnutls_datum_t *buf ) { int rc = -1, fd; struct stat st; fd = open( path, O_RDONLY ); if ( fd >= 0 && fstat( fd, &st ) == 0 ) { buf->size = st.st_size; buf->data = LDAP_MALLOC( st.st_size + 1 ); if ( buf->data ) { rc = read( fd, buf->data, st.st_size ); close( fd ); if ( rc < st.st_size ) rc = -1; else rc = 0; } } return rc; } /* This is the GnuTLS default */ #define VERIFY_DEPTH 6 /* * initialize a new TLS context */ static int tlsg_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server ) { tlsg_ctx *ctx = lo->ldo_tls_ctx; int rc; if ( lo->ldo_tls_ciphersuite && tlsg_parse_ciphers( ctx, lt->lt_ciphersuite )) { Debug( LDAP_DEBUG_ANY, "TLS: could not set cipher list %s.\n", lo->ldo_tls_ciphersuite, 0, 0 ); return -1; } if (lo->ldo_tls_cacertdir != NULL) { Debug( LDAP_DEBUG_ANY, "TLS: warning: cacertdir not implemented for gnutls\n", NULL, NULL, NULL ); } if (lo->ldo_tls_cacertfile != NULL) { rc = gnutls_certificate_set_x509_trust_file( ctx->cred, lt->lt_cacertfile, GNUTLS_X509_FMT_PEM ); if ( rc < 0 ) return -1; } if ( lo->ldo_tls_certfile && lo->ldo_tls_keyfile ) { gnutls_x509_privkey_t key; gnutls_datum_t buf; gnutls_x509_crt_t certs[VERIFY_DEPTH]; unsigned int max = VERIFY_DEPTH; rc = gnutls_x509_privkey_init( &key ); if ( rc ) return -1; /* OpenSSL builds the cert chain for us, but GnuTLS * expects it to be present in the certfile. If it's * not, we have to build it ourselves. So we have to * do some special checks here... */ rc = tlsg_getfile( lt->lt_keyfile, &buf ); if ( rc ) return -1; rc = gnutls_x509_privkey_import( key, &buf, GNUTLS_X509_FMT_PEM ); LDAP_FREE( buf.data ); if ( rc < 0 ) return rc; rc = tlsg_getfile( lt->lt_certfile, &buf ); if ( rc ) return -1; rc = gnutls_x509_crt_list_import( certs, &max, &buf, GNUTLS_X509_FMT_PEM, 0 ); LDAP_FREE( buf.data ); if ( rc < 0 ) return rc; /* If there's only one cert and it's not self-signed, * then we have to build the cert chain. */ if ( max == 1 && !gnutls_x509_crt_check_issuer( certs[0], certs[0] )) { unsigned int i; for ( i = 1; icred, certs[i-1], &certs[i], 0 )) break; max++; /* If this CA is self-signed, we're done */ if ( gnutls_x509_crt_check_issuer( certs[i], certs[i] )) break; } } rc = gnutls_certificate_set_x509_key( ctx->cred, certs, max, key ); if ( rc ) return -1; } else if ( lo->ldo_tls_certfile || lo->ldo_tls_keyfile ) { Debug( LDAP_DEBUG_ANY, "TLS: only one of certfile and keyfile specified\n", NULL, NULL, NULL ); return -1; } if ( lo->ldo_tls_dhfile ) { Debug( LDAP_DEBUG_ANY, "TLS: warning: ignoring dhfile\n", NULL, NULL, NULL ); } if ( lo->ldo_tls_crlfile ) { rc = gnutls_certificate_set_x509_crl_file( ctx->cred, lt->lt_crlfile, GNUTLS_X509_FMT_PEM ); if ( rc < 0 ) return -1; rc = 0; } /* FIXME: ITS#5992 - this should go be configurable, * and V1 CA certs should be phased out ASAP. */ gnutls_certificate_set_verify_flags( ctx->cred, GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT ); if ( is_server ) { gnutls_dh_params_init(&ctx->dh_params); gnutls_dh_params_generate2(ctx->dh_params, DH_BITS); } return 0; } static tls_session * tlsg_session_new ( tls_ctx * ctx, int is_server ) { tlsg_ctx *c = (tlsg_ctx *)ctx; tlsg_session *session; session = ber_memcalloc ( 1, sizeof (*session) ); if ( !session ) return NULL; session->ctx = c; gnutls_init( &session->session, is_server ? GNUTLS_SERVER : GNUTLS_CLIENT ); gnutls_priority_set( session->session, c->prios ); if ( c->cred ) gnutls_credentials_set( session->session, GNUTLS_CRD_CERTIFICATE, c->cred ); if ( is_server ) { int flag = 0; if ( c->lo->ldo_tls_require_cert ) { flag = GNUTLS_CERT_REQUEST; if ( c->lo->ldo_tls_require_cert == LDAP_OPT_X_TLS_DEMAND || c->lo->ldo_tls_require_cert == LDAP_OPT_X_TLS_HARD ) flag = GNUTLS_CERT_REQUIRE; gnutls_certificate_server_set_request( session->session, flag ); } } return (tls_session *)session; } static int tlsg_session_accept( tls_session *session ) { tlsg_session *s = (tlsg_session *)session; int rc; rc = gnutls_handshake( s->session ); if ( rc == 0 && s->ctx->lo->ldo_tls_require_cert != LDAP_OPT_X_TLS_NEVER ) { const gnutls_datum_t *peer_cert_list; unsigned int list_size; peer_cert_list = gnutls_certificate_get_peers( s->session, &list_size ); if ( !peer_cert_list && s->ctx->lo->ldo_tls_require_cert == LDAP_OPT_X_TLS_TRY ) rc = 0; else { rc = tlsg_cert_verify( s ); if ( rc && s->ctx->lo->ldo_tls_require_cert == LDAP_OPT_X_TLS_ALLOW ) rc = 0; } } return rc; } static int tlsg_session_connect( LDAP *ld, tls_session *session ) { return tlsg_session_accept( session); } static int tlsg_session_upflags( Sockbuf *sb, tls_session *session, int rc ) { tlsg_session *s = (tlsg_session *)session; if ( rc != GNUTLS_E_INTERRUPTED && rc != GNUTLS_E_AGAIN ) return 0; switch (gnutls_record_get_direction (s->session)) { case 0: sb->sb_trans_needs_read = 1; return 1; case 1: sb->sb_trans_needs_write = 1; return 1; } return 0; } static char * tlsg_session_errmsg( tls_session *sess, int rc, char *buf, size_t len ) { return (char *)gnutls_strerror( rc ); } static void tlsg_x509_cert_dn( struct berval *cert, struct berval *dn, int get_subject ) { BerElementBuffer berbuf; BerElement *ber = (BerElement *)&berbuf; ber_tag_t tag; ber_len_t len; ber_int_t i; ber_init2( ber, cert, LBER_USE_DER ); tag = ber_skip_tag( ber, &len ); /* Sequence */ tag = ber_skip_tag( ber, &len ); /* Sequence */ tag = ber_peek_tag( ber, &len ); /* Context + Constructed (version) */ if ( tag == 0xa0 ) { /* Version is optional */ tag = ber_skip_tag( ber, &len ); tag = ber_get_int( ber, &i ); /* Int: Version */ } tag = ber_skip_tag( ber, &len ); /* Int: Serial (can be longer than ber_int_t) */ ber_skip_data( ber, len ); tag = ber_skip_tag( ber, &len ); /* Sequence: Signature */ ber_skip_data( ber, len ); if ( !get_subject ) { tag = ber_peek_tag( ber, &len ); /* Sequence: Issuer DN */ } else { tag = ber_skip_tag( ber, &len ); ber_skip_data( ber, len ); tag = ber_skip_tag( ber, &len ); /* Sequence: Validity */ ber_skip_data( ber, len ); tag = ber_peek_tag( ber, &len ); /* Sequence: Subject DN */ } len = ber_ptrlen( ber ); dn->bv_val = cert->bv_val + len; dn->bv_len = cert->bv_len - len; } static int tlsg_session_my_dn( tls_session *session, struct berval *der_dn ) { tlsg_session *s = (tlsg_session *)session; const gnutls_datum_t *x; struct berval bv; x = gnutls_certificate_get_ours( s->session ); if (!x) return LDAP_INVALID_CREDENTIALS; bv.bv_val = (char *) x->data; bv.bv_len = x->size; tlsg_x509_cert_dn( &bv, der_dn, 1 ); return 0; } static int tlsg_session_peer_dn( tls_session *session, struct berval *der_dn ) { tlsg_session *s = (tlsg_session *)session; if ( !s->peer_der_dn.bv_val ) { const gnutls_datum_t *peer_cert_list; unsigned int list_size; struct berval bv; peer_cert_list = gnutls_certificate_get_peers( s->session, &list_size ); if ( !peer_cert_list ) return LDAP_INVALID_CREDENTIALS; bv.bv_len = peer_cert_list->size; bv.bv_val = (char *) peer_cert_list->data; tlsg_x509_cert_dn( &bv, &s->peer_der_dn, 1 ); } *der_dn = s->peer_der_dn; return 0; } /* what kind of hostname were we given? */ #define IS_DNS 0 #define IS_IP4 1 #define IS_IP6 2 #define CN_OID "2.5.4.3" static int tlsg_session_chkhost( LDAP *ld, tls_session *session, const char *name_in ) { tlsg_session *s = (tlsg_session *)session; int i, ret; const gnutls_datum_t *peer_cert_list; unsigned int list_size; char altname[NI_MAXHOST]; size_t altnamesize; gnutls_x509_crt_t cert; const char *name; char *ptr; char *domain = NULL; #ifdef LDAP_PF_INET6 struct in6_addr addr; #else struct in_addr addr; #endif int len1 = 0, len2 = 0; int ntype = IS_DNS; if( ldap_int_hostname && ( !name_in || !strcasecmp( name_in, "localhost" ) ) ) { name = ldap_int_hostname; } else { name = name_in; } peer_cert_list = gnutls_certificate_get_peers( s->session, &list_size ); if ( !peer_cert_list ) { Debug( LDAP_DEBUG_ANY, "TLS: unable to get peer certificate.\n", 0, 0, 0 ); /* If this was a fatal condition, things would have * aborted long before now. */ return LDAP_SUCCESS; } ret = gnutls_x509_crt_init( &cert ); if ( ret < 0 ) return LDAP_LOCAL_ERROR; ret = gnutls_x509_crt_import( cert, peer_cert_list, GNUTLS_X509_FMT_DER ); if ( ret ) { gnutls_x509_crt_deinit( cert ); return LDAP_LOCAL_ERROR; } #ifdef LDAP_PF_INET6 if (inet_pton(AF_INET6, name, &addr)) { ntype = IS_IP6; } else #endif if ((ptr = strrchr(name, '.')) && isdigit((unsigned char)ptr[1])) { if (inet_aton(name, (struct in_addr *)&addr)) ntype = IS_IP4; } if (ntype == IS_DNS) { len1 = strlen(name); domain = strchr(name, '.'); if (domain) { len2 = len1 - (domain-name); } } for ( i=0, ret=0; ret >= 0; i++ ) { altnamesize = sizeof(altname); ret = gnutls_x509_crt_get_subject_alt_name( cert, i, altname, &altnamesize, NULL ); if ( ret < 0 ) break; /* ignore empty */ if ( altnamesize == 0 ) continue; if ( ret == GNUTLS_SAN_DNSNAME ) { if (ntype != IS_DNS) continue; /* Is this an exact match? */ if ((len1 == altnamesize) && !strncasecmp(name, altname, len1)) { break; } /* Is this a wildcard match? */ if (domain && (altname[0] == '*') && (altname[1] == '.') && (len2 == altnamesize-1) && !strncasecmp(domain, &altname[1], len2)) { break; } } else if ( ret == GNUTLS_SAN_IPADDRESS ) { if (ntype == IS_DNS) continue; #ifdef LDAP_PF_INET6 if (ntype == IS_IP6 && altnamesize != sizeof(struct in6_addr)) { continue; } else #endif if (ntype == IS_IP4 && altnamesize != sizeof(struct in_addr)) { continue; } if (!memcmp(altname, &addr, altnamesize)) { break; } } } if ( ret >= 0 ) { ret = LDAP_SUCCESS; } else { /* find the last CN */ i=0; do { altnamesize = 0; ret = gnutls_x509_crt_get_dn_by_oid( cert, CN_OID, i, 1, altname, &altnamesize ); if ( ret == GNUTLS_E_SHORT_MEMORY_BUFFER ) i++; else break; } while ( 1 ); if ( i ) { altnamesize = sizeof(altname); ret = gnutls_x509_crt_get_dn_by_oid( cert, CN_OID, i-1, 0, altname, &altnamesize ); } if ( ret < 0 ) { Debug( LDAP_DEBUG_ANY, "TLS: unable to get common name from peer certificate.\n", 0, 0, 0 ); ret = LDAP_CONNECT_ERROR; if ( ld->ld_error ) { LDAP_FREE( ld->ld_error ); } ld->ld_error = LDAP_STRDUP( _("TLS: unable to get CN from peer certificate")); } else { ret = LDAP_LOCAL_ERROR; if ( !len1 ) len1 = strlen( name ); if ( len1 == altnamesize && strncasecmp(name, altname, altnamesize) == 0 ) { ret = LDAP_SUCCESS; } else if (( altname[0] == '*' ) && ( altname[1] == '.' )) { /* Is this a wildcard match? */ if( domain && (len2 == altnamesize-1) && !strncasecmp(domain, &altname[1], len2)) { ret = LDAP_SUCCESS; } } } if( ret == LDAP_LOCAL_ERROR ) { altname[altnamesize] = '\0'; Debug( LDAP_DEBUG_ANY, "TLS: hostname (%s) does not match " "common name in certificate (%s).\n", name, altname, 0 ); ret = LDAP_CONNECT_ERROR; if ( ld->ld_error ) { LDAP_FREE( ld->ld_error ); } ld->ld_error = LDAP_STRDUP( _("TLS: hostname does not match CN in peer certificate")); } } gnutls_x509_crt_deinit( cert ); return ret; } static int tlsg_session_strength( tls_session *session ) { tlsg_session *s = (tlsg_session *)session; gnutls_cipher_algorithm_t c; c = gnutls_cipher_get( s->session ); return gnutls_cipher_get_key_size( c ) * 8; } /* suites is a string of colon-separated cipher suite names. */ static int tlsg_parse_ciphers( tlsg_ctx *ctx, char *suites ) { const char *err; int rc = gnutls_priority_init( &ctx->prios, suites, &err ); if ( rc ) ctx->prios = NULL; return rc; } /* * TLS support for LBER Sockbufs */ struct tls_data { tlsg_session *session; Sockbuf_IO_Desc *sbiod; }; static ssize_t tlsg_recv( gnutls_transport_ptr_t ptr, void *buf, size_t len ) { struct tls_data *p; if ( buf == NULL || len <= 0 ) return 0; p = (struct tls_data *)ptr; if ( p == NULL || p->sbiod == NULL ) { return 0; } return LBER_SBIOD_READ_NEXT( p->sbiod, buf, len ); } static ssize_t tlsg_send( gnutls_transport_ptr_t ptr, const void *buf, size_t len ) { struct tls_data *p; if ( buf == NULL || len <= 0 ) return 0; p = (struct tls_data *)ptr; if ( p == NULL || p->sbiod == NULL ) { return 0; } return LBER_SBIOD_WRITE_NEXT( p->sbiod, (char *)buf, len ); } static int tlsg_sb_setup( Sockbuf_IO_Desc *sbiod, void *arg ) { struct tls_data *p; tlsg_session *session = arg; assert( sbiod != NULL ); p = LBER_MALLOC( sizeof( *p ) ); if ( p == NULL ) { return -1; } gnutls_transport_set_ptr( session->session, (gnutls_transport_ptr)p ); gnutls_transport_set_pull_function( session->session, tlsg_recv ); gnutls_transport_set_push_function( session->session, tlsg_send ); p->session = session; p->sbiod = sbiod; sbiod->sbiod_pvt = p; return 0; } static int tlsg_sb_remove( Sockbuf_IO_Desc *sbiod ) { struct tls_data *p; assert( sbiod != NULL ); assert( sbiod->sbiod_pvt != NULL ); p = (struct tls_data *)sbiod->sbiod_pvt; gnutls_deinit ( p->session->session ); LBER_FREE( p->session ); LBER_FREE( sbiod->sbiod_pvt ); sbiod->sbiod_pvt = NULL; return 0; } static int tlsg_sb_close( Sockbuf_IO_Desc *sbiod ) { struct tls_data *p; assert( sbiod != NULL ); assert( sbiod->sbiod_pvt != NULL ); p = (struct tls_data *)sbiod->sbiod_pvt; gnutls_bye ( p->session->session, GNUTLS_SHUT_WR ); return 0; } static int tlsg_sb_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) { struct tls_data *p; assert( sbiod != NULL ); assert( sbiod->sbiod_pvt != NULL ); p = (struct tls_data *)sbiod->sbiod_pvt; if ( opt == LBER_SB_OPT_GET_SSL ) { *((tlsg_session **)arg) = p->session; return 1; } else if ( opt == LBER_SB_OPT_DATA_READY ) { if( gnutls_record_check_pending( p->session->session ) > 0 ) { return 1; } } return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg ); } static ber_slen_t tlsg_sb_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) { struct tls_data *p; ber_slen_t ret; assert( sbiod != NULL ); assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); p = (struct tls_data *)sbiod->sbiod_pvt; ret = gnutls_record_recv ( p->session->session, buf, len ); switch (ret) { case GNUTLS_E_INTERRUPTED: case GNUTLS_E_AGAIN: sbiod->sbiod_sb->sb_trans_needs_read = 1; sock_errset(EWOULDBLOCK); ret = 0; break; case GNUTLS_E_REHANDSHAKE: for ( ret = gnutls_handshake ( p->session->session ); ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN; ret = gnutls_handshake ( p->session->session ) ); sbiod->sbiod_sb->sb_trans_needs_read = 1; ret = 0; break; default: sbiod->sbiod_sb->sb_trans_needs_read = 0; } return ret; } static ber_slen_t tlsg_sb_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) { struct tls_data *p; ber_slen_t ret; assert( sbiod != NULL ); assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); p = (struct tls_data *)sbiod->sbiod_pvt; ret = gnutls_record_send ( p->session->session, (char *)buf, len ); if ( ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN ) { sbiod->sbiod_sb->sb_trans_needs_write = 1; sock_errset(EWOULDBLOCK); ret = 0; } else { sbiod->sbiod_sb->sb_trans_needs_write = 0; } return ret; } static Sockbuf_IO tlsg_sbio = { tlsg_sb_setup, /* sbi_setup */ tlsg_sb_remove, /* sbi_remove */ tlsg_sb_ctrl, /* sbi_ctrl */ tlsg_sb_read, /* sbi_read */ tlsg_sb_write, /* sbi_write */ tlsg_sb_close /* sbi_close */ }; /* Certs are not automatically varified during the handshake */ static int tlsg_cert_verify( tlsg_session *ssl ) { unsigned int status = 0; int err; time_t now = time(0); time_t peertime; err = gnutls_certificate_verify_peers2( ssl->session, &status ); if ( err < 0 ) { Debug( LDAP_DEBUG_ANY,"TLS: gnutls_certificate_verify_peers2 failed %d\n", err,0,0 ); return -1; } if ( status ) { Debug( LDAP_DEBUG_TRACE,"TLS: peer cert untrusted or revoked (0x%x)\n", status, 0,0 ); return -1; } peertime = gnutls_certificate_expiration_time_peers( ssl->session ); if ( peertime == (time_t) -1 ) { Debug( LDAP_DEBUG_ANY, "TLS: gnutls_certificate_expiration_time_peers failed\n", 0, 0, 0 ); return -1; } if ( peertime < now ) { Debug( LDAP_DEBUG_ANY, "TLS: peer certificate is expired\n", 0, 0, 0 ); return -1; } peertime = gnutls_certificate_activation_time_peers( ssl->session ); if ( peertime == (time_t) -1 ) { Debug( LDAP_DEBUG_ANY, "TLS: gnutls_certificate_activation_time_peers failed\n", 0, 0, 0 ); return -1; } if ( peertime > now ) { Debug( LDAP_DEBUG_ANY, "TLS: peer certificate not yet active\n", 0, 0, 0 ); return -1; } return 0; } tls_impl ldap_int_tls_impl = { "GnuTLS", tlsg_init, tlsg_destroy, tlsg_ctx_new, tlsg_ctx_ref, tlsg_ctx_free, tlsg_ctx_init, tlsg_session_new, tlsg_session_connect, tlsg_session_accept, tlsg_session_upflags, tlsg_session_errmsg, tlsg_session_my_dn, tlsg_session_peer_dn, tlsg_session_chkhost, tlsg_session_strength, &tlsg_sbio, #ifdef LDAP_R_COMPILE tlsg_thr_init, #else NULL, #endif 0 }; #endif /* HAVE_GNUTLS */ openldap-2.4.42+dfsg/libraries/libldap/filter.c0000644000175000017500000005002412563404150020045 0ustar ryanryan/* search.c */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (c) 1990 Regents of the University of Michigan. * All rights reserved. */ #include "portable.h" #include #include #include #include #include #include "ldap-int.h" static int put_simple_vrFilter LDAP_P(( BerElement *ber, char *str )); static int put_vrFilter_list LDAP_P(( BerElement *ber, char *str )); static char *put_complex_filter LDAP_P(( BerElement *ber, char *str, ber_tag_t tag, int not )); static int put_simple_filter LDAP_P(( BerElement *ber, char *str )); static int put_substring_filter LDAP_P(( BerElement *ber, char *type, char *str, char *nextstar )); static int put_filter_list LDAP_P(( BerElement *ber, char *str, ber_tag_t tag )); static int ldap_is_oid ( const char *str ) { int i; if( LDAP_ALPHA( str[0] )) { for( i=1; str[i]; i++ ) { if( !LDAP_LDH( str[i] )) { return 0; } } return 1; } else if LDAP_DIGIT( str[0] ) { int dot=0; for( i=1; str[i]; i++ ) { if( LDAP_DIGIT( str[i] )) { dot=0; } else if ( str[i] == '.' ) { if( ++dot > 1 ) return 0; } else { return 0; } } return !dot; } return 0; } static int ldap_is_desc ( const char *str ) { int i; if( LDAP_ALPHA( str[0] )) { for( i=1; str[i]; i++ ) { if( str[i] == ';' ) { str = &str[i+1]; goto options; } if( !LDAP_LDH( str[i] )) { return 0; } } return 1; } else if LDAP_DIGIT( str[0] ) { int dot=0; for( i=1; str[i]; i++ ) { if( str[i] == ';' ) { if( dot ) return 0; str = &str[i+1]; goto options; } if( LDAP_DIGIT( str[i] )) { dot=0; } else if ( str[i] == '.' ) { if( ++dot > 1 ) return 0; } else { return 0; } } return !dot; } return 0; options: if( !LDAP_LDH( str[0] )) { return 0; } for( i=1; str[i]; i++ ) { if( str[i] == ';' ) { str = &str[i+1]; goto options; } if( !LDAP_LDH( str[i] )) { return 0; } } return 1; } static char * find_right_paren( char *s ) { int balance, escape; balance = 1; escape = 0; while ( *s && balance ) { if ( !escape ) { if ( *s == '(' ) { balance++; } else if ( *s == ')' ) { balance--; } } escape = ( *s == '\\' && !escape ); if ( balance ) s++; } return *s ? s : NULL; } static int hex2value( int c ) { if( c >= '0' && c <= '9' ) { return c - '0'; } if( c >= 'A' && c <= 'F' ) { return c + (10 - (int) 'A'); } if( c >= 'a' && c <= 'f' ) { return c + (10 - (int) 'a'); } return -1; } char * ldap_pvt_find_wildcard( const char *s ) { for( ; *s; s++ ) { switch( *s ) { case '*': /* found wildcard */ return (char *) s; case '(': case ')': return NULL; case '\\': if( s[1] == '\0' ) return NULL; if( LDAP_HEX( s[1] ) && LDAP_HEX( s[2] ) ) { s+=2; } else switch( s[1] ) { default: return NULL; /* allow RFC 1960 escapes */ case '*': case '(': case ')': case '\\': s++; } } } return (char *) s; } /* unescape filter value */ /* support both LDAP v2 and v3 escapes */ /* output can include nul characters! */ ber_slen_t ldap_pvt_filter_value_unescape( char *fval ) { ber_slen_t r, v; int v1, v2; for( r=v=0; fval[v] != '\0'; v++ ) { switch( fval[v] ) { case '(': case ')': case '*': return -1; case '\\': /* escape */ v++; if ( fval[v] == '\0' ) { /* escape at end of string */ return -1; } if (( v1 = hex2value( fval[v] )) >= 0 ) { /* LDAPv3 escape */ if (( v2 = hex2value( fval[v+1] )) < 0 ) { /* must be two digit code */ return -1; } fval[r++] = v1 * 16 + v2; v++; } else { /* LDAPv2 escape */ switch( fval[v] ) { case '(': case ')': case '*': case '\\': fval[r++] = fval[v]; break; default: /* illegal escape */ return -1; } } break; default: fval[r++] = fval[v]; } } fval[r] = '\0'; return r; } static char * put_complex_filter( BerElement *ber, char *str, ber_tag_t tag, int not ) { char *next; /* * We have (x(filter)...) with str sitting on * the x. We have to find the paren matching * the one before the x and put the intervening * filters by calling put_filter_list(). */ /* put explicit tag */ if ( ber_printf( ber, "t{" /*"}"*/, tag ) == -1 ) { return NULL; } str++; if ( (next = find_right_paren( str )) == NULL ) { return NULL; } *next = '\0'; if ( put_filter_list( ber, str, tag ) == -1 ) { return NULL; } /* close the '(' */ *next++ = ')'; /* flush explicit tagged thang */ if ( ber_printf( ber, /*"{"*/ "N}" ) == -1 ) { return NULL; } return next; } int ldap_pvt_put_filter( BerElement *ber, const char *str_in ) { int rc; char *freeme; char *str; char *next; int parens, balance, escape; /* * A Filter looks like this (RFC 4511 as extended by RFC 4526): * Filter ::= CHOICE { * and [0] SET SIZE (0..MAX) OF filter Filter, * or [1] SET SIZE (0..MAX) OF filter Filter, * not [2] Filter, * equalityMatch [3] AttributeValueAssertion, * substrings [4] SubstringFilter, * greaterOrEqual [5] AttributeValueAssertion, * lessOrEqual [6] AttributeValueAssertion, * present [7] AttributeDescription, * approxMatch [8] AttributeValueAssertion, * extensibleMatch [9] MatchingRuleAssertion, * ... } * * SubstringFilter ::= SEQUENCE { * type AttributeDescription, * substrings SEQUENCE SIZE (1..MAX) OF substring CHOICE { * initial [0] AssertionValue, -- only once * any [1] AssertionValue, * final [2] AssertionValue -- only once * } * } * * MatchingRuleAssertion ::= SEQUENCE { * matchingRule [1] MatchingRuleId OPTIONAL, * type [2] AttributeDescription OPTIONAL, * matchValue [3] AssertionValue, * dnAttributes [4] BOOLEAN DEFAULT FALSE } * * Note: tags in a CHOICE are always explicit */ Debug( LDAP_DEBUG_TRACE, "put_filter: \"%s\"\n", str_in, 0, 0 ); freeme = LDAP_STRDUP( str_in ); if( freeme == NULL ) return LDAP_NO_MEMORY; str = freeme; parens = 0; while ( *str ) { switch ( *str ) { case '(': /*')'*/ str++; parens++; /* skip spaces */ while( LDAP_SPACE( *str ) ) str++; switch ( *str ) { case '&': Debug( LDAP_DEBUG_TRACE, "put_filter: AND\n", 0, 0, 0 ); str = put_complex_filter( ber, str, LDAP_FILTER_AND, 0 ); if( str == NULL ) { rc = -1; goto done; } parens--; break; case '|': Debug( LDAP_DEBUG_TRACE, "put_filter: OR\n", 0, 0, 0 ); str = put_complex_filter( ber, str, LDAP_FILTER_OR, 0 ); if( str == NULL ) { rc = -1; goto done; } parens--; break; case '!': Debug( LDAP_DEBUG_TRACE, "put_filter: NOT\n", 0, 0, 0 ); str = put_complex_filter( ber, str, LDAP_FILTER_NOT, 0 ); if( str == NULL ) { rc = -1; goto done; } parens--; break; case '(': rc = -1; goto done; default: Debug( LDAP_DEBUG_TRACE, "put_filter: simple\n", 0, 0, 0 ); balance = 1; escape = 0; next = str; while ( *next && balance ) { if ( escape == 0 ) { if ( *next == '(' ) { balance++; } else if ( *next == ')' ) { balance--; } } if ( *next == '\\' && ! escape ) { escape = 1; } else { escape = 0; } if ( balance ) next++; } if ( balance != 0 ) { rc = -1; goto done; } *next = '\0'; if ( put_simple_filter( ber, str ) == -1 ) { rc = -1; goto done; } *next++ = /*'('*/ ')'; str = next; parens--; break; } break; case /*'('*/ ')': Debug( LDAP_DEBUG_TRACE, "put_filter: end\n", 0, 0, 0 ); if ( ber_printf( ber, /*"["*/ "]" ) == -1 ) { rc = -1; goto done; } str++; parens--; break; case ' ': str++; break; default: /* assume it's a simple type=value filter */ Debug( LDAP_DEBUG_TRACE, "put_filter: default\n", 0, 0, 0 ); next = strchr( str, '\0' ); if ( put_simple_filter( ber, str ) == -1 ) { rc = -1; goto done; } str = next; break; } if ( !parens ) break; } rc = ( parens || *str ) ? -1 : 0; done: LDAP_FREE( freeme ); return rc; } /* * Put a list of filters like this "(filter1)(filter2)..." */ static int put_filter_list( BerElement *ber, char *str, ber_tag_t tag ) { char *next = NULL; char save; Debug( LDAP_DEBUG_TRACE, "put_filter_list \"%s\"\n", str, 0, 0 ); while ( *str ) { while ( *str && LDAP_SPACE( (unsigned char) *str ) ) { str++; } if ( *str == '\0' ) break; if ( (next = find_right_paren( str + 1 )) == NULL ) { return -1; } save = *++next; /* now we have "(filter)" with str pointing to it */ *next = '\0'; if ( ldap_pvt_put_filter( ber, str ) == -1 ) return -1; *next = save; str = next; if( tag == LDAP_FILTER_NOT ) break; } if( tag == LDAP_FILTER_NOT && ( next == NULL || *str )) { return -1; } return 0; } static int put_simple_filter( BerElement *ber, char *str ) { char *s; char *value; ber_tag_t ftype; int rc = -1; Debug( LDAP_DEBUG_TRACE, "put_simple_filter: \"%s\"\n", str, 0, 0 ); str = LDAP_STRDUP( str ); if( str == NULL ) return -1; if ( (s = strchr( str, '=' )) == NULL ) { goto done; } value = s + 1; *s-- = '\0'; switch ( *s ) { case '<': ftype = LDAP_FILTER_LE; *s = '\0'; break; case '>': ftype = LDAP_FILTER_GE; *s = '\0'; break; case '~': ftype = LDAP_FILTER_APPROX; *s = '\0'; break; case ':': /* RFC 4515 extensible filters are off the form: * type [:dn] [:rule] := value * or [:dn]:rule := value */ ftype = LDAP_FILTER_EXT; *s = '\0'; { char *dn = strchr( str, ':' ); char *rule = NULL; if( dn != NULL ) { *dn++ = '\0'; rule = strchr( dn, ':' ); if( rule == NULL ) { /* one colon */ if ( strcasecmp(dn, "dn") == 0 ) { /* must have attribute */ if( !ldap_is_desc( str ) ) { goto done; } rule = ""; } else { rule = dn; dn = NULL; } } else { /* two colons */ *rule++ = '\0'; if ( strcasecmp(dn, "dn") != 0 ) { /* must have "dn" */ goto done; } } } if ( *str == '\0' && ( !rule || *rule == '\0' ) ) { /* must have either type or rule */ goto done; } if ( *str != '\0' && !ldap_is_desc( str ) ) { goto done; } if ( rule && *rule != '\0' && !ldap_is_oid( rule ) ) { goto done; } rc = ber_printf( ber, "t{" /*"}"*/, ftype ); if( rc != -1 && rule && *rule != '\0' ) { rc = ber_printf( ber, "ts", LDAP_FILTER_EXT_OID, rule ); } if( rc != -1 && *str != '\0' ) { rc = ber_printf( ber, "ts", LDAP_FILTER_EXT_TYPE, str ); } if( rc != -1 ) { ber_slen_t len = ldap_pvt_filter_value_unescape( value ); if( len >= 0 ) { rc = ber_printf( ber, "to", LDAP_FILTER_EXT_VALUE, value, len ); } else { rc = -1; } } if( rc != -1 && dn ) { rc = ber_printf( ber, "tb", LDAP_FILTER_EXT_DNATTRS, (ber_int_t) 1 ); } if( rc != -1 ) { rc = ber_printf( ber, /*"{"*/ "N}" ); } } goto done; default: if( !ldap_is_desc( str ) ) { goto done; } else { char *nextstar = ldap_pvt_find_wildcard( value ); if ( nextstar == NULL ) { goto done; } else if ( *nextstar == '\0' ) { ftype = LDAP_FILTER_EQUALITY; } else if ( strcmp( value, "*" ) == 0 ) { ftype = LDAP_FILTER_PRESENT; } else { rc = put_substring_filter( ber, str, value, nextstar ); goto done; } } break; } if( !ldap_is_desc( str ) ) goto done; if ( ftype == LDAP_FILTER_PRESENT ) { rc = ber_printf( ber, "ts", ftype, str ); } else { ber_slen_t len = ldap_pvt_filter_value_unescape( value ); if( len >= 0 ) { rc = ber_printf( ber, "t{soN}", ftype, str, value, len ); } } done: if( rc != -1 ) rc = 0; LDAP_FREE( str ); return rc; } static int put_substring_filter( BerElement *ber, char *type, char *val, char *nextstar ) { int gotstar = 0; ber_tag_t ftype = LDAP_FILTER_SUBSTRINGS; Debug( LDAP_DEBUG_TRACE, "put_substring_filter \"%s=%s\"\n", type, val, 0 ); if ( ber_printf( ber, "t{s{" /*"}}"*/, ftype, type ) == -1 ) { return -1; } for( ; *val; val=nextstar ) { if ( gotstar ) nextstar = ldap_pvt_find_wildcard( val ); if ( nextstar == NULL ) { return -1; } if ( *nextstar == '\0' ) { ftype = LDAP_SUBSTRING_FINAL; } else { *nextstar++ = '\0'; if ( gotstar++ == 0 ) { ftype = LDAP_SUBSTRING_INITIAL; } else { ftype = LDAP_SUBSTRING_ANY; } } if ( *val != '\0' || ftype == LDAP_SUBSTRING_ANY ) { ber_slen_t len = ldap_pvt_filter_value_unescape( val ); if ( len <= 0 ) { return -1; } if ( ber_printf( ber, "to", ftype, val, len ) == -1 ) { return -1; } } } if ( ber_printf( ber, /*"{{"*/ "N}N}" ) == -1 ) { return -1; } return 0; } static int put_vrFilter( BerElement *ber, const char *str_in ) { int rc; char *freeme; char *str; char *next; int parens, balance, escape; /* * A ValuesReturnFilter looks like this: * * ValuesReturnFilter ::= SEQUENCE OF SimpleFilterItem * SimpleFilterItem ::= CHOICE { * equalityMatch [3] AttributeValueAssertion, * substrings [4] SubstringFilter, * greaterOrEqual [5] AttributeValueAssertion, * lessOrEqual [6] AttributeValueAssertion, * present [7] AttributeType, * approxMatch [8] AttributeValueAssertion, * extensibleMatch [9] SimpleMatchingAssertion -- LDAPv3 * } * * SubstringFilter ::= SEQUENCE { * type AttributeType, * SEQUENCE OF CHOICE { * initial [0] IA5String, * any [1] IA5String, * final [2] IA5String * } * } * * SimpleMatchingAssertion ::= SEQUENCE { -- LDAPv3 * matchingRule [1] MatchingRuleId OPTIONAL, * type [2] AttributeDescription OPTIONAL, * matchValue [3] AssertionValue } * * (Source: RFC 3876) */ Debug( LDAP_DEBUG_TRACE, "put_vrFilter: \"%s\"\n", str_in, 0, 0 ); freeme = LDAP_STRDUP( str_in ); if( freeme == NULL ) return LDAP_NO_MEMORY; str = freeme; parens = 0; while ( *str ) { switch ( *str ) { case '(': /*')'*/ str++; parens++; /* skip spaces */ while( LDAP_SPACE( *str ) ) str++; switch ( *str ) { case '(': if ( (next = find_right_paren( str )) == NULL ) { rc = -1; goto done; } *next = '\0'; if ( put_vrFilter_list( ber, str ) == -1 ) { rc = -1; goto done; } /* close the '(' */ *next++ = ')'; str = next; parens--; break; default: Debug( LDAP_DEBUG_TRACE, "put_vrFilter: simple\n", 0, 0, 0 ); balance = 1; escape = 0; next = str; while ( *next && balance ) { if ( escape == 0 ) { if ( *next == '(' ) { balance++; } else if ( *next == ')' ) { balance--; } } if ( *next == '\\' && ! escape ) { escape = 1; } else { escape = 0; } if ( balance ) next++; } if ( balance != 0 ) { rc = -1; goto done; } *next = '\0'; if ( put_simple_vrFilter( ber, str ) == -1 ) { rc = -1; goto done; } *next++ = /*'('*/ ')'; str = next; parens--; break; } break; case /*'('*/ ')': Debug( LDAP_DEBUG_TRACE, "put_vrFilter: end\n", 0, 0, 0 ); if ( ber_printf( ber, /*"["*/ "]" ) == -1 ) { rc = -1; goto done; } str++; parens--; break; case ' ': str++; break; default: /* assume it's a simple type=value filter */ Debug( LDAP_DEBUG_TRACE, "put_vrFilter: default\n", 0, 0, 0 ); next = strchr( str, '\0' ); if ( put_simple_vrFilter( ber, str ) == -1 ) { rc = -1; goto done; } str = next; break; } } rc = parens ? -1 : 0; done: LDAP_FREE( freeme ); return rc; } int ldap_put_vrFilter( BerElement *ber, const char *str_in ) { int rc =0; if ( ber_printf( ber, "{" /*"}"*/ ) == -1 ) { return -1; } rc = put_vrFilter( ber, str_in ); if ( ber_printf( ber, /*"{"*/ "N}" ) == -1 ) { rc = -1; } return rc; } static int put_vrFilter_list( BerElement *ber, char *str ) { char *next = NULL; char save; Debug( LDAP_DEBUG_TRACE, "put_vrFilter_list \"%s\"\n", str, 0, 0 ); while ( *str ) { while ( *str && LDAP_SPACE( (unsigned char) *str ) ) { str++; } if ( *str == '\0' ) break; if ( (next = find_right_paren( str + 1 )) == NULL ) { return -1; } save = *++next; /* now we have "(filter)" with str pointing to it */ *next = '\0'; if ( put_vrFilter( ber, str ) == -1 ) return -1; *next = save; str = next; } return 0; } static int put_simple_vrFilter( BerElement *ber, char *str ) { char *s; char *value; ber_tag_t ftype; int rc = -1; Debug( LDAP_DEBUG_TRACE, "put_simple_vrFilter: \"%s\"\n", str, 0, 0 ); str = LDAP_STRDUP( str ); if( str == NULL ) return -1; if ( (s = strchr( str, '=' )) == NULL ) { goto done; } value = s + 1; *s-- = '\0'; switch ( *s ) { case '<': ftype = LDAP_FILTER_LE; *s = '\0'; break; case '>': ftype = LDAP_FILTER_GE; *s = '\0'; break; case '~': ftype = LDAP_FILTER_APPROX; *s = '\0'; break; case ':': /* According to ValuesReturnFilter control definition * extensible filters are off the form: * type [:rule] := value * or :rule := value */ ftype = LDAP_FILTER_EXT; *s = '\0'; { char *rule = strchr( str, ':' ); if( rule == NULL ) { /* must have attribute */ if( !ldap_is_desc( str ) ) { goto done; } rule = ""; } else { *rule++ = '\0'; } if ( *str == '\0' && ( !rule || *rule == '\0' ) ) { /* must have either type or rule */ goto done; } if ( *str != '\0' && !ldap_is_desc( str ) ) { goto done; } if ( rule && *rule != '\0' && !ldap_is_oid( rule ) ) { goto done; } rc = ber_printf( ber, "t{" /*"}"*/, ftype ); if( rc != -1 && rule && *rule != '\0' ) { rc = ber_printf( ber, "ts", LDAP_FILTER_EXT_OID, rule ); } if( rc != -1 && *str != '\0' ) { rc = ber_printf( ber, "ts", LDAP_FILTER_EXT_TYPE, str ); } if( rc != -1 ) { ber_slen_t len = ldap_pvt_filter_value_unescape( value ); if( len >= 0 ) { rc = ber_printf( ber, "to", LDAP_FILTER_EXT_VALUE, value, len ); } else { rc = -1; } } if( rc != -1 ) { rc = ber_printf( ber, /*"{"*/ "N}" ); } } goto done; default: if( !ldap_is_desc( str ) ) { goto done; } else { char *nextstar = ldap_pvt_find_wildcard( value ); if ( nextstar == NULL ) { goto done; } else if ( *nextstar == '\0' ) { ftype = LDAP_FILTER_EQUALITY; } else if ( strcmp( value, "*" ) == 0 ) { ftype = LDAP_FILTER_PRESENT; } else { rc = put_substring_filter( ber, str, value, nextstar ); goto done; } } break; } if( !ldap_is_desc( str ) ) goto done; if ( ftype == LDAP_FILTER_PRESENT ) { rc = ber_printf( ber, "ts", ftype, str ); } else { ber_slen_t len = ldap_pvt_filter_value_unescape( value ); if( len >= 0 ) { rc = ber_printf( ber, "t{soN}", ftype, str, value, len ); } } done: if( rc != -1 ) rc = 0; LDAP_FREE( str ); return rc; } openldap-2.4.42+dfsg/libraries/libldap/add.c0000644000175000017500000001343312563404150017313 0ustar ryanryan/* add.c */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (c) 1990 Regents of the University of Michigan. * All rights reserved. */ #include "portable.h" #include #include #include #include #include "ldap-int.h" /* An LDAP Add Request/Response looks like this: * AddRequest ::= [APPLICATION 8] SEQUENCE { * entry LDAPDN, * attributes AttributeList } * * AttributeList ::= SEQUENCE OF attribute Attribute * * Attribute ::= PartialAttribute(WITH COMPONENTS { * ..., * vals (SIZE(1..MAX))}) * * PartialAttribute ::= SEQUENCE { * type AttributeDescription, * vals SET OF value AttributeValue } * * AttributeDescription ::= LDAPString * -- Constrained to [RFC4512] * * AttributeValue ::= OCTET STRING * * AddResponse ::= [APPLICATION 9] LDAPResult * (Source: RFC 4511) */ /* * ldap_add - initiate an ldap add operation. Parameters: * * ld LDAP descriptor * dn DN of the entry to add * mods List of attributes for the entry. This is a null- * terminated array of pointers to LDAPMod structures. * only the type and values in the structures need be * filled in. * * Example: * LDAPMod *attrs[] = { * { 0, "cn", { "babs jensen", "babs", 0 } }, * { 0, "sn", { "jensen", 0 } }, * { 0, "objectClass", { "person", 0 } }, * 0 * } * msgid = ldap_add( ld, dn, attrs ); */ int ldap_add( LDAP *ld, LDAP_CONST char *dn, LDAPMod **attrs ) { int rc; int msgid; rc = ldap_add_ext( ld, dn, attrs, NULL, NULL, &msgid ); if ( rc != LDAP_SUCCESS ) return -1; return msgid; } /* * ldap_add_ext - initiate an ldap extended add operation. Parameters: * * ld LDAP descriptor * dn DN of the entry to add * mods List of attributes for the entry. This is a null- * terminated array of pointers to LDAPMod structures. * only the type and values in the structures need be * filled in. * sctrl Server Controls * cctrl Client Controls * msgidp Message ID pointer * * Example: * LDAPMod *attrs[] = { * { 0, "cn", { "babs jensen", "babs", 0 } }, * { 0, "sn", { "jensen", 0 } }, * { 0, "objectClass", { "person", 0 } }, * 0 * } * rc = ldap_add_ext( ld, dn, attrs, NULL, NULL, &msgid ); */ int ldap_add_ext( LDAP *ld, LDAP_CONST char *dn, LDAPMod **attrs, LDAPControl **sctrls, LDAPControl **cctrls, int *msgidp ) { BerElement *ber; int i, rc; ber_int_t id; Debug( LDAP_DEBUG_TRACE, "ldap_add_ext\n", 0, 0, 0 ); assert( ld != NULL ); assert( LDAP_VALID( ld ) ); assert( dn != NULL ); assert( msgidp != NULL ); /* check client controls */ rc = ldap_int_client_controls( ld, cctrls ); if( rc != LDAP_SUCCESS ) return rc; /* create a message to send */ if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) { ld->ld_errno = LDAP_NO_MEMORY; return ld->ld_errno; } LDAP_NEXT_MSGID(ld, id); rc = ber_printf( ber, "{it{s{", /* '}}}' */ id, LDAP_REQ_ADD, dn ); if ( rc == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return ld->ld_errno; } /* allow attrs to be NULL ("touch"; should fail...) */ if ( attrs ) { /* for each attribute in the entry... */ for ( i = 0; attrs[i] != NULL; i++ ) { if ( ( attrs[i]->mod_op & LDAP_MOD_BVALUES) != 0 ) { int j; if ( attrs[i]->mod_bvalues == NULL ) { ld->ld_errno = LDAP_PARAM_ERROR; ber_free( ber, 1 ); return ld->ld_errno; } for ( j = 0; attrs[i]->mod_bvalues[ j ] != NULL; j++ ) { if ( attrs[i]->mod_bvalues[ j ]->bv_val == NULL ) { ld->ld_errno = LDAP_PARAM_ERROR; ber_free( ber, 1 ); return ld->ld_errno; } } rc = ber_printf( ber, "{s[V]N}", attrs[i]->mod_type, attrs[i]->mod_bvalues ); } else { if ( attrs[i]->mod_values == NULL ) { ld->ld_errno = LDAP_PARAM_ERROR; ber_free( ber, 1 ); return ld->ld_errno; } rc = ber_printf( ber, "{s[v]N}", attrs[i]->mod_type, attrs[i]->mod_values ); } if ( rc == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return ld->ld_errno; } } } if ( ber_printf( ber, /*{{*/ "N}N}" ) == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return ld->ld_errno; } /* Put Server Controls */ if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) { ber_free( ber, 1 ); return ld->ld_errno; } if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return ld->ld_errno; } /* send the message */ *msgidp = ldap_send_initial_request( ld, LDAP_REQ_ADD, dn, ber, id ); if(*msgidp < 0) return ld->ld_errno; return LDAP_SUCCESS; } int ldap_add_ext_s( LDAP *ld, LDAP_CONST char *dn, LDAPMod **attrs, LDAPControl **sctrls, LDAPControl **cctrls ) { int msgid, rc; LDAPMessage *res; rc = ldap_add_ext( ld, dn, attrs, sctrls, cctrls, &msgid ); if ( rc != LDAP_SUCCESS ) return( rc ); if ( ldap_result( ld, msgid, LDAP_MSG_ALL, (struct timeval *) NULL, &res ) == -1 || !res ) return( ld->ld_errno ); return( ldap_result2error( ld, res, 1 ) ); } int ldap_add_s( LDAP *ld, LDAP_CONST char *dn, LDAPMod **attrs ) { return ldap_add_ext_s( ld, dn, attrs, NULL, NULL ); } openldap-2.4.42+dfsg/libraries/libldap/error.c0000644000175000017500000002604012563404150017712 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #include "portable.h" #include #include #include #include #include #include "ldap-int.h" void ldap_int_error_init( void ) { } char * ldap_err2string( int err ) { char *m; Debug( LDAP_DEBUG_TRACE, "ldap_err2string\n", 0, 0, 0 ); switch ( err ) { # define C(code, message) case code: m = message; break /* LDAPv3 (RFC 4511) codes */ C(LDAP_SUCCESS, N_("Success")); C(LDAP_OPERATIONS_ERROR, N_("Operations error")); C(LDAP_PROTOCOL_ERROR, N_("Protocol error")); C(LDAP_TIMELIMIT_EXCEEDED, N_("Time limit exceeded")); C(LDAP_SIZELIMIT_EXCEEDED, N_("Size limit exceeded")); C(LDAP_COMPARE_FALSE, N_("Compare False")); C(LDAP_COMPARE_TRUE, N_("Compare True")); C(LDAP_STRONG_AUTH_NOT_SUPPORTED,N_("Authentication method not supported")); C(LDAP_STRONG_AUTH_REQUIRED, N_("Strong(er) authentication required")); C(LDAP_REFERRAL, N_("Referral")); C(LDAP_ADMINLIMIT_EXCEEDED, N_("Administrative limit exceeded")); C(LDAP_UNAVAILABLE_CRITICAL_EXTENSION, N_("Critical extension is unavailable")); C(LDAP_CONFIDENTIALITY_REQUIRED,N_("Confidentiality required")); C(LDAP_SASL_BIND_IN_PROGRESS, N_("SASL bind in progress")); C(LDAP_NO_SUCH_ATTRIBUTE, N_("No such attribute")); C(LDAP_UNDEFINED_TYPE, N_("Undefined attribute type")); C(LDAP_INAPPROPRIATE_MATCHING, N_("Inappropriate matching")); C(LDAP_CONSTRAINT_VIOLATION, N_("Constraint violation")); C(LDAP_TYPE_OR_VALUE_EXISTS, N_("Type or value exists")); C(LDAP_INVALID_SYNTAX, N_("Invalid syntax")); C(LDAP_NO_SUCH_OBJECT, N_("No such object")); C(LDAP_ALIAS_PROBLEM, N_("Alias problem")); C(LDAP_INVALID_DN_SYNTAX, N_("Invalid DN syntax")); C(LDAP_ALIAS_DEREF_PROBLEM, N_("Alias dereferencing problem")); C(LDAP_INAPPROPRIATE_AUTH, N_("Inappropriate authentication")); C(LDAP_INVALID_CREDENTIALS, N_("Invalid credentials")); C(LDAP_INSUFFICIENT_ACCESS, N_("Insufficient access")); C(LDAP_BUSY, N_("Server is busy")); C(LDAP_UNAVAILABLE, N_("Server is unavailable")); C(LDAP_UNWILLING_TO_PERFORM, N_("Server is unwilling to perform")); C(LDAP_LOOP_DETECT, N_("Loop detected")); C(LDAP_NAMING_VIOLATION, N_("Naming violation")); C(LDAP_OBJECT_CLASS_VIOLATION, N_("Object class violation")); C(LDAP_NOT_ALLOWED_ON_NONLEAF, N_("Operation not allowed on non-leaf")); C(LDAP_NOT_ALLOWED_ON_RDN, N_("Operation not allowed on RDN")); C(LDAP_ALREADY_EXISTS, N_("Already exists")); C(LDAP_NO_OBJECT_CLASS_MODS, N_("Cannot modify object class")); C(LDAP_AFFECTS_MULTIPLE_DSAS, N_("Operation affects multiple DSAs")); /* Virtual List View draft */ C(LDAP_VLV_ERROR, N_("Virtual List View error")); C(LDAP_OTHER, N_("Other (e.g., implementation specific) error")); /* LDAPv2 (RFC 1777) codes */ C(LDAP_PARTIAL_RESULTS, N_("Partial results and referral received")); C(LDAP_IS_LEAF, N_("Entry is a leaf")); /* Connection-less LDAP (CLDAP - RFC 1798) code */ C(LDAP_RESULTS_TOO_LARGE, N_("Results too large")); /* Cancel Operation (RFC 3909) codes */ C(LDAP_CANCELLED, N_("Cancelled")); C(LDAP_NO_SUCH_OPERATION, N_("No Operation to Cancel")); C(LDAP_TOO_LATE, N_("Too Late to Cancel")); C(LDAP_CANNOT_CANCEL, N_("Cannot Cancel")); /* Assert Control (RFC 4528 and old internet-draft) codes */ C(LDAP_ASSERTION_FAILED, N_("Assertion Failed")); C(LDAP_X_ASSERTION_FAILED, N_("Assertion Failed (X)")); /* Proxied Authorization Control (RFC 4370 and I-D) codes */ C(LDAP_PROXIED_AUTHORIZATION_DENIED, N_("Proxied Authorization Denied")); C(LDAP_X_PROXY_AUTHZ_FAILURE, N_("Proxy Authorization Failure (X)")); /* Content Sync Operation (RFC 4533 and I-D) codes */ C(LDAP_SYNC_REFRESH_REQUIRED, N_("Content Sync Refresh Required")); C(LDAP_X_SYNC_REFRESH_REQUIRED, N_("Content Sync Refresh Required (X)")); /* No-Op Control (draft-zeilenga-ldap-noop) code */ C(LDAP_X_NO_OPERATION, N_("No Operation (X)")); /* Client Update Protocol (RFC 3928) codes */ C(LDAP_CUP_RESOURCES_EXHAUSTED, N_("LCUP Resources Exhausted")); C(LDAP_CUP_SECURITY_VIOLATION, N_("LCUP Security Violation")); C(LDAP_CUP_INVALID_DATA, N_("LCUP Invalid Data")); C(LDAP_CUP_UNSUPPORTED_SCHEME, N_("LCUP Unsupported Scheme")); C(LDAP_CUP_RELOAD_REQUIRED, N_("LCUP Reload Required")); #ifdef LDAP_X_TXN /* Codes related to LDAP Transactions (draft-zeilenga-ldap-txn) */ C(LDAP_X_TXN_SPECIFY_OKAY, N_("TXN specify okay")); C(LDAP_X_TXN_ID_INVALID, N_("TXN ID is invalid")); #endif /* API codes - renumbered since draft-ietf-ldapext-ldap-c-api */ C(LDAP_SERVER_DOWN, N_("Can't contact LDAP server")); C(LDAP_LOCAL_ERROR, N_("Local error")); C(LDAP_ENCODING_ERROR, N_("Encoding error")); C(LDAP_DECODING_ERROR, N_("Decoding error")); C(LDAP_TIMEOUT, N_("Timed out")); C(LDAP_AUTH_UNKNOWN, N_("Unknown authentication method")); C(LDAP_FILTER_ERROR, N_("Bad search filter")); C(LDAP_USER_CANCELLED, N_("User cancelled operation")); C(LDAP_PARAM_ERROR, N_("Bad parameter to an ldap routine")); C(LDAP_NO_MEMORY, N_("Out of memory")); C(LDAP_CONNECT_ERROR, N_("Connect error")); C(LDAP_NOT_SUPPORTED, N_("Not Supported")); C(LDAP_CONTROL_NOT_FOUND, N_("Control not found")); C(LDAP_NO_RESULTS_RETURNED, N_("No results returned")); C(LDAP_MORE_RESULTS_TO_RETURN, N_("More results to return")); C(LDAP_CLIENT_LOOP, N_("Client Loop")); C(LDAP_REFERRAL_LIMIT_EXCEEDED, N_("Referral Limit Exceeded")); C(LDAP_X_CONNECTING, N_("Connecting (X)")); # undef C default: m = (LDAP_API_ERROR(err) ? N_("Unknown API error") : LDAP_E_ERROR(err) ? N_("Unknown (extension) error") : LDAP_X_ERROR(err) ? N_("Unknown (private extension) error") : N_("Unknown error")); break; } return _(m); } /* deprecated */ void ldap_perror( LDAP *ld, LDAP_CONST char *str ) { int i; assert( ld != NULL ); assert( LDAP_VALID( ld ) ); assert( str != NULL ); fprintf( stderr, "%s: %s (%d)\n", str ? str : "ldap_perror", ldap_err2string( ld->ld_errno ), ld->ld_errno ); if ( ld->ld_matched != NULL && ld->ld_matched[0] != '\0' ) { fprintf( stderr, _("\tmatched DN: %s\n"), ld->ld_matched ); } if ( ld->ld_error != NULL && ld->ld_error[0] != '\0' ) { fprintf( stderr, _("\tadditional info: %s\n"), ld->ld_error ); } if ( ld->ld_referrals != NULL && ld->ld_referrals[0] != NULL) { fprintf( stderr, _("\treferrals:\n") ); for (i=0; ld->ld_referrals[i]; i++) { fprintf( stderr, _("\t\t%s\n"), ld->ld_referrals[i] ); } } fflush( stderr ); } /* deprecated */ int ldap_result2error( LDAP *ld, LDAPMessage *r, int freeit ) { int rc, err; rc = ldap_parse_result( ld, r, &err, NULL, NULL, NULL, NULL, freeit ); return err != LDAP_SUCCESS ? err : rc; } /* * Parse LDAPResult Messages: * * LDAPResult ::= SEQUENCE { * resultCode ENUMERATED, * matchedDN LDAPDN, * errorMessage LDAPString, * referral [3] Referral OPTIONAL } * * including Bind results: * * BindResponse ::= [APPLICATION 1] SEQUENCE { * COMPONENTS OF LDAPResult, * serverSaslCreds [7] OCTET STRING OPTIONAL } * * and ExtendedOp results: * * ExtendedResponse ::= [APPLICATION 24] SEQUENCE { * COMPONENTS OF LDAPResult, * responseName [10] LDAPOID OPTIONAL, * response [11] OCTET STRING OPTIONAL } * */ int ldap_parse_result( LDAP *ld, LDAPMessage *r, int *errcodep, char **matcheddnp, char **errmsgp, char ***referralsp, LDAPControl ***serverctrls, int freeit ) { LDAPMessage *lm; ber_int_t errcode = LDAP_SUCCESS; ber_tag_t tag; BerElement *ber; Debug( LDAP_DEBUG_TRACE, "ldap_parse_result\n", 0, 0, 0 ); assert( ld != NULL ); assert( LDAP_VALID( ld ) ); assert( r != NULL ); if(errcodep != NULL) *errcodep = LDAP_SUCCESS; if(matcheddnp != NULL) *matcheddnp = NULL; if(errmsgp != NULL) *errmsgp = NULL; if(referralsp != NULL) *referralsp = NULL; if(serverctrls != NULL) *serverctrls = NULL; LDAP_MUTEX_LOCK( &ld->ld_res_mutex ); /* Find the result, last msg in chain... */ lm = r->lm_chain_tail; /* FIXME: either this is not possible (assert?) * or it should be handled */ if ( lm != NULL ) { switch ( lm->lm_msgtype ) { case LDAP_RES_SEARCH_ENTRY: case LDAP_RES_SEARCH_REFERENCE: case LDAP_RES_INTERMEDIATE: lm = NULL; break; default: break; } } if( lm == NULL ) { errcode = ld->ld_errno = LDAP_NO_RESULTS_RETURNED; LDAP_MUTEX_UNLOCK( &ld->ld_res_mutex ); goto done; } if ( ld->ld_error ) { LDAP_FREE( ld->ld_error ); ld->ld_error = NULL; } if ( ld->ld_matched ) { LDAP_FREE( ld->ld_matched ); ld->ld_matched = NULL; } if ( ld->ld_referrals ) { LDAP_VFREE( ld->ld_referrals ); ld->ld_referrals = NULL; } /* parse results */ ber = ber_dup( lm->lm_ber ); if ( ld->ld_version < LDAP_VERSION2 ) { tag = ber_scanf( ber, "{iA}", &ld->ld_errno, &ld->ld_error ); } else { ber_len_t len; tag = ber_scanf( ber, "{iAA" /*}*/, &ld->ld_errno, &ld->ld_matched, &ld->ld_error ); if( tag != LBER_ERROR ) { /* peek for referrals */ if( ber_peek_tag(ber, &len) == LDAP_TAG_REFERRAL ) { tag = ber_scanf( ber, "v", &ld->ld_referrals ); } } /* need to clean out misc items */ if( tag != LBER_ERROR ) { if( lm->lm_msgtype == LDAP_RES_BIND ) { /* look for sasl result creditials */ if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SASL_RES_CREDS ) { /* skip 'em */ tag = ber_scanf( ber, "x" ); } } else if( lm->lm_msgtype == LDAP_RES_EXTENDED ) { /* look for exop result oid or value */ if ( ber_peek_tag( ber, &len ) == LDAP_TAG_EXOP_RES_OID ) { /* skip 'em */ tag = ber_scanf( ber, "x" ); } if ( tag != LBER_ERROR && ber_peek_tag( ber, &len ) == LDAP_TAG_EXOP_RES_VALUE ) { /* skip 'em */ tag = ber_scanf( ber, "x" ); } } } if( tag != LBER_ERROR ) { int rc = ldap_pvt_get_controls( ber, serverctrls ); if( rc != LDAP_SUCCESS ) { tag = LBER_ERROR; } } if( tag != LBER_ERROR ) { tag = ber_scanf( ber, /*{*/"}" ); } } if ( tag == LBER_ERROR ) { ld->ld_errno = errcode = LDAP_DECODING_ERROR; } if( ber != NULL ) { ber_free( ber, 0 ); } /* return */ if( errcodep != NULL ) { *errcodep = ld->ld_errno; } if ( errcode == LDAP_SUCCESS ) { if( matcheddnp != NULL ) { if ( ld->ld_matched ) { *matcheddnp = LDAP_STRDUP( ld->ld_matched ); } } if( errmsgp != NULL ) { if ( ld->ld_error ) { *errmsgp = LDAP_STRDUP( ld->ld_error ); } } if( referralsp != NULL) { *referralsp = ldap_value_dup( ld->ld_referrals ); } } LDAP_MUTEX_UNLOCK( &ld->ld_res_mutex ); done: if ( freeit ) { ldap_msgfree( r ); } return errcode; } openldap-2.4.42+dfsg/libraries/libldap/pagectrl.c0000644000175000017500000001564112563404150020367 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * Copyright 2006 Hans Leidekker * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #include "portable.h" #include #include #include #include #include "ldap-int.h" /* --------------------------------------------------------------------------- ldap_create_page_control_value Create and encode the value of the paged results control (RFC 2696). ld (IN) An LDAP session handle pagesize (IN) Page size requested cookie (IN) Opaque structure used by the server to track its location in the search results. NULL on the first call. value (OUT) Control value, SHOULD be freed by calling ldap_memfree() when done. pagedResultsControl ::= SEQUENCE { controlType 1.2.840.113556.1.4.319, criticality BOOLEAN DEFAULT FALSE, controlValue searchControlValue } searchControlValue ::= SEQUENCE { size INTEGER (0..maxInt), -- requested page size from client -- result set size estimate from server cookie OCTET STRING } ---------------------------------------------------------------------------*/ int ldap_create_page_control_value( LDAP *ld, ber_int_t pagesize, struct berval *cookie, struct berval *value ) { BerElement *ber = NULL; ber_tag_t tag; struct berval null_cookie = { 0, NULL }; if ( ld == NULL || value == NULL || pagesize < 1 || pagesize > LDAP_MAXINT ) { if ( ld ) ld->ld_errno = LDAP_PARAM_ERROR; return LDAP_PARAM_ERROR; } assert( LDAP_VALID( ld ) ); value->bv_val = NULL; value->bv_len = 0; ld->ld_errno = LDAP_SUCCESS; if ( cookie == NULL ) { cookie = &null_cookie; } ber = ldap_alloc_ber_with_options( ld ); if ( ber == NULL ) { ld->ld_errno = LDAP_NO_MEMORY; return ld->ld_errno; } tag = ber_printf( ber, "{iO}", pagesize, cookie ); if ( tag == LBER_ERROR ) { ld->ld_errno = LDAP_ENCODING_ERROR; goto done; } if ( ber_flatten2( ber, value, 1 ) == -1 ) { ld->ld_errno = LDAP_NO_MEMORY; } done:; if ( ber != NULL ) { ber_free( ber, 1 ); } return ld->ld_errno; } /* --------------------------------------------------------------------------- ldap_create_page_control Create and encode a page control. ld (IN) An LDAP session handle pagesize (IN) Page size requested cookie (IN) Opaque structure used by the server to track its location in the search results. NULL on the first call. value (OUT) Control value, SHOULD be freed by calling ldap_memfree() when done. iscritical (IN) Criticality ctrlp (OUT) LDAP control, SHOULD be freed by calling ldap_control_free() when done. pagedResultsControl ::= SEQUENCE { controlType 1.2.840.113556.1.4.319, criticality BOOLEAN DEFAULT FALSE, controlValue searchControlValue } searchControlValue ::= SEQUENCE { size INTEGER (0..maxInt), -- requested page size from client -- result set size estimate from server cookie OCTET STRING } ---------------------------------------------------------------------------*/ int ldap_create_page_control( LDAP *ld, ber_int_t pagesize, struct berval *cookie, int iscritical, LDAPControl **ctrlp ) { struct berval value; if ( ctrlp == NULL ) { ld->ld_errno = LDAP_PARAM_ERROR; return ld->ld_errno; } ld->ld_errno = ldap_create_page_control_value( ld, pagesize, cookie, &value ); if ( ld->ld_errno == LDAP_SUCCESS ) { ld->ld_errno = ldap_control_create( LDAP_CONTROL_PAGEDRESULTS, iscritical, &value, 0, ctrlp ); if ( ld->ld_errno != LDAP_SUCCESS ) { LDAP_FREE( value.bv_val ); } } return ld->ld_errno; } /* --------------------------------------------------------------------------- ldap_parse_pageresponse_control Decode a page control. ld (IN) An LDAP session handle ctrl (IN) The page response control count (OUT) The number of entries in the page. cookie (OUT) Opaque cookie. Use ldap_memfree() to free the bv_val member of this structure. ---------------------------------------------------------------------------*/ int ldap_parse_pageresponse_control( LDAP *ld, LDAPControl *ctrl, ber_int_t *countp, struct berval *cookie ) { BerElement *ber; ber_tag_t tag; ber_int_t count; if ( ld == NULL || ctrl == NULL || cookie == NULL ) { if ( ld ) ld->ld_errno = LDAP_PARAM_ERROR; return LDAP_PARAM_ERROR; } /* Create a BerElement from the berval returned in the control. */ ber = ber_init( &ctrl->ldctl_value ); if ( ber == NULL ) { ld->ld_errno = LDAP_NO_MEMORY; return ld->ld_errno; } /* Extract the count and cookie from the control. */ tag = ber_scanf( ber, "{io}", &count, cookie ); ber_free( ber, 1 ); if ( tag == LBER_ERROR ) { ld->ld_errno = LDAP_DECODING_ERROR; } else { ld->ld_errno = LDAP_SUCCESS; if ( countp != NULL ) { *countp = (unsigned long)count; } } return ld->ld_errno; } /* --------------------------------------------------------------------------- ldap_parse_page_control Decode a page control. ld (IN) An LDAP session handle ctrls (IN) Response controls count (OUT) The number of entries in the page. cookie (OUT) Opaque cookie. Use ldap_memfree() to free the bv_val member of this structure. ---------------------------------------------------------------------------*/ int ldap_parse_page_control( LDAP *ld, LDAPControl **ctrls, ber_int_t *countp, struct berval **cookiep ) { LDAPControl *c; struct berval cookie; if ( cookiep == NULL ) { ld->ld_errno = LDAP_PARAM_ERROR; return ld->ld_errno; } if ( ctrls == NULL ) { ld->ld_errno = LDAP_CONTROL_NOT_FOUND; return ld->ld_errno; } c = ldap_control_find( LDAP_CONTROL_PAGEDRESULTS, ctrls, NULL ); if ( c == NULL ) { /* No page control was found. */ ld->ld_errno = LDAP_CONTROL_NOT_FOUND; return ld->ld_errno; } ld->ld_errno = ldap_parse_pageresponse_control( ld, c, countp, &cookie ); if ( ld->ld_errno == LDAP_SUCCESS ) { *cookiep = LDAP_MALLOC( sizeof( struct berval ) ); if ( *cookiep == NULL ) { ld->ld_errno = LDAP_NO_MEMORY; } else { **cookiep = cookie; } } return ld->ld_errno; } openldap-2.4.42+dfsg/libraries/libldap/extended.c0000644000175000017500000002040112563404150020354 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #include "portable.h" #include #include #include #include #include #include "ldap-int.h" #include "ldap_log.h" /* * LDAPv3 Extended Operation Request * ExtendedRequest ::= [APPLICATION 23] SEQUENCE { * requestName [0] LDAPOID, * requestValue [1] OCTET STRING OPTIONAL * } * * LDAPv3 Extended Operation Response * ExtendedResponse ::= [APPLICATION 24] SEQUENCE { * COMPONENTS OF LDAPResult, * responseName [10] LDAPOID OPTIONAL, * response [11] OCTET STRING OPTIONAL * } * * (Source RFC 4511) */ int ldap_extended_operation( LDAP *ld, LDAP_CONST char *reqoid, struct berval *reqdata, LDAPControl **sctrls, LDAPControl **cctrls, int *msgidp ) { BerElement *ber; int rc; ber_int_t id; Debug( LDAP_DEBUG_TRACE, "ldap_extended_operation\n", 0, 0, 0 ); assert( ld != NULL ); assert( LDAP_VALID( ld ) ); assert( reqoid != NULL && *reqoid != '\0' ); assert( msgidp != NULL ); /* must be version 3 (or greater) */ if ( ld->ld_version < LDAP_VERSION3 ) { ld->ld_errno = LDAP_NOT_SUPPORTED; return( ld->ld_errno ); } /* create a message to send */ if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) { ld->ld_errno = LDAP_NO_MEMORY; return( ld->ld_errno ); } LDAP_NEXT_MSGID( ld, id ); if ( reqdata != NULL ) { rc = ber_printf( ber, "{it{tstON}", /* '}' */ id, LDAP_REQ_EXTENDED, LDAP_TAG_EXOP_REQ_OID, reqoid, LDAP_TAG_EXOP_REQ_VALUE, reqdata ); } else { rc = ber_printf( ber, "{it{tsN}", /* '}' */ id, LDAP_REQ_EXTENDED, LDAP_TAG_EXOP_REQ_OID, reqoid ); } if( rc == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( ld->ld_errno ); } /* Put Server Controls */ if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) { ber_free( ber, 1 ); return ld->ld_errno; } if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( ld->ld_errno ); } /* send the message */ *msgidp = ldap_send_initial_request( ld, LDAP_REQ_EXTENDED, NULL, ber, id ); return( *msgidp < 0 ? ld->ld_errno : LDAP_SUCCESS ); } int ldap_extended_operation_s( LDAP *ld, LDAP_CONST char *reqoid, struct berval *reqdata, LDAPControl **sctrls, LDAPControl **cctrls, char **retoidp, struct berval **retdatap ) { int rc; int msgid; LDAPMessage *res; Debug( LDAP_DEBUG_TRACE, "ldap_extended_operation_s\n", 0, 0, 0 ); assert( ld != NULL ); assert( LDAP_VALID( ld ) ); assert( reqoid != NULL && *reqoid != '\0' ); rc = ldap_extended_operation( ld, reqoid, reqdata, sctrls, cctrls, &msgid ); if ( rc != LDAP_SUCCESS ) { return( rc ); } if ( ldap_result( ld, msgid, LDAP_MSG_ALL, (struct timeval *) NULL, &res ) == -1 || !res ) { return( ld->ld_errno ); } if ( retoidp != NULL ) *retoidp = NULL; if ( retdatap != NULL ) *retdatap = NULL; rc = ldap_parse_extended_result( ld, res, retoidp, retdatap, 0 ); if( rc != LDAP_SUCCESS ) { ldap_msgfree( res ); return rc; } return( ldap_result2error( ld, res, 1 ) ); } /* Parse an extended result */ int ldap_parse_extended_result ( LDAP *ld, LDAPMessage *res, char **retoidp, struct berval **retdatap, int freeit ) { BerElement *ber; ber_tag_t rc; ber_tag_t tag; ber_len_t len; struct berval *resdata; ber_int_t errcode; char *resoid; assert( ld != NULL ); assert( LDAP_VALID( ld ) ); assert( res != NULL ); Debug( LDAP_DEBUG_TRACE, "ldap_parse_extended_result\n", 0, 0, 0 ); if( ld->ld_version < LDAP_VERSION3 ) { ld->ld_errno = LDAP_NOT_SUPPORTED; return ld->ld_errno; } if( res->lm_msgtype != LDAP_RES_EXTENDED ) { ld->ld_errno = LDAP_PARAM_ERROR; return ld->ld_errno; } if( retoidp != NULL ) *retoidp = NULL; if( retdatap != NULL ) *retdatap = NULL; if ( ld->ld_error ) { LDAP_FREE( ld->ld_error ); ld->ld_error = NULL; } if ( ld->ld_matched ) { LDAP_FREE( ld->ld_matched ); ld->ld_matched = NULL; } ber = ber_dup( res->lm_ber ); if ( ber == NULL ) { ld->ld_errno = LDAP_NO_MEMORY; return ld->ld_errno; } rc = ber_scanf( ber, "{eAA" /*}*/, &errcode, &ld->ld_matched, &ld->ld_error ); if( rc == LBER_ERROR ) { ld->ld_errno = LDAP_DECODING_ERROR; ber_free( ber, 0 ); return ld->ld_errno; } resoid = NULL; resdata = NULL; tag = ber_peek_tag( ber, &len ); if( tag == LDAP_TAG_REFERRAL ) { /* skip over referral */ if( ber_scanf( ber, "x" ) == LBER_ERROR ) { ld->ld_errno = LDAP_DECODING_ERROR; ber_free( ber, 0 ); return ld->ld_errno; } tag = ber_peek_tag( ber, &len ); } if( tag == LDAP_TAG_EXOP_RES_OID ) { /* we have a resoid */ if( ber_scanf( ber, "a", &resoid ) == LBER_ERROR ) { ld->ld_errno = LDAP_DECODING_ERROR; ber_free( ber, 0 ); return ld->ld_errno; } assert( resoid[ 0 ] != '\0' ); tag = ber_peek_tag( ber, &len ); } if( tag == LDAP_TAG_EXOP_RES_VALUE ) { /* we have a resdata */ if( ber_scanf( ber, "O", &resdata ) == LBER_ERROR ) { ld->ld_errno = LDAP_DECODING_ERROR; ber_free( ber, 0 ); if( resoid != NULL ) LDAP_FREE( resoid ); return ld->ld_errno; } } ber_free( ber, 0 ); if( retoidp != NULL ) { *retoidp = resoid; } else { LDAP_FREE( resoid ); } if( retdatap != NULL ) { *retdatap = resdata; } else { ber_bvfree( resdata ); } ld->ld_errno = errcode; if( freeit ) { ldap_msgfree( res ); } return LDAP_SUCCESS; } /* Parse an extended partial */ int ldap_parse_intermediate ( LDAP *ld, LDAPMessage *res, char **retoidp, struct berval **retdatap, LDAPControl ***serverctrls, int freeit ) { BerElement *ber; ber_tag_t tag; ber_len_t len; struct berval *resdata; char *resoid; assert( ld != NULL ); assert( LDAP_VALID( ld ) ); assert( res != NULL ); Debug( LDAP_DEBUG_TRACE, "ldap_parse_intermediate\n", 0, 0, 0 ); if( ld->ld_version < LDAP_VERSION3 ) { ld->ld_errno = LDAP_NOT_SUPPORTED; return ld->ld_errno; } if( res->lm_msgtype != LDAP_RES_INTERMEDIATE ) { ld->ld_errno = LDAP_PARAM_ERROR; return ld->ld_errno; } if( retoidp != NULL ) *retoidp = NULL; if( retdatap != NULL ) *retdatap = NULL; if( serverctrls != NULL ) *serverctrls = NULL; ber = ber_dup( res->lm_ber ); if ( ber == NULL ) { ld->ld_errno = LDAP_NO_MEMORY; return ld->ld_errno; } tag = ber_scanf( ber, "{" /*}*/ ); if( tag == LBER_ERROR ) { ld->ld_errno = LDAP_DECODING_ERROR; ber_free( ber, 0 ); return ld->ld_errno; } resoid = NULL; resdata = NULL; tag = ber_peek_tag( ber, &len ); /* * NOTE: accept intermediate and extended response tag values * as older versions of slapd(8) incorrectly used extended * response tags. * Should be removed when 2.2 is moved to Historic. */ if( tag == LDAP_TAG_IM_RES_OID || tag == LDAP_TAG_EXOP_RES_OID ) { /* we have a resoid */ if( ber_scanf( ber, "a", &resoid ) == LBER_ERROR ) { ld->ld_errno = LDAP_DECODING_ERROR; ber_free( ber, 0 ); return ld->ld_errno; } assert( resoid[ 0 ] != '\0' ); tag = ber_peek_tag( ber, &len ); } if( tag == LDAP_TAG_IM_RES_VALUE || tag == LDAP_TAG_EXOP_RES_VALUE ) { /* we have a resdata */ if( ber_scanf( ber, "O", &resdata ) == LBER_ERROR ) { ld->ld_errno = LDAP_DECODING_ERROR; ber_free( ber, 0 ); if( resoid != NULL ) LDAP_FREE( resoid ); return ld->ld_errno; } } if ( serverctrls == NULL ) { ld->ld_errno = LDAP_SUCCESS; goto free_and_return; } if ( ber_scanf( ber, /*{*/ "}" ) == LBER_ERROR ) { ld->ld_errno = LDAP_DECODING_ERROR; goto free_and_return; } ld->ld_errno = ldap_pvt_get_controls( ber, serverctrls ); free_and_return: ber_free( ber, 0 ); if( retoidp != NULL ) { *retoidp = resoid; } else { LDAP_FREE( resoid ); } if( retdatap != NULL ) { *retdatap = resdata; } else { ber_bvfree( resdata ); } if( freeit ) { ldap_msgfree( res ); } return ld->ld_errno; } openldap-2.4.42+dfsg/libraries/libldap/getattr.c0000644000175000017500000000654612563404150020244 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (c) 1990 Regents of the University of Michigan. * All rights reserved. */ #include "portable.h" #include #include #include #include #include #include "ldap-int.h" char * ldap_first_attribute( LDAP *ld, LDAPMessage *entry, BerElement **berout ) { int rc; ber_tag_t tag; ber_len_t len = 0; char *attr; BerElement *ber; Debug( LDAP_DEBUG_TRACE, "ldap_first_attribute\n", 0, 0, 0 ); assert( ld != NULL ); assert( LDAP_VALID( ld ) ); assert( entry != NULL ); assert( berout != NULL ); *berout = NULL; ber = ldap_alloc_ber_with_options( ld ); if( ber == NULL ) { return NULL; } *ber = *entry->lm_ber; /* * Skip past the sequence, dn, sequence of sequence leaving * us at the first attribute. */ tag = ber_scanf( ber, "{xl{" /*}}*/, &len ); if( tag == LBER_ERROR ) { ld->ld_errno = LDAP_DECODING_ERROR; ber_free( ber, 0 ); return NULL; } /* set the length to avoid overrun */ rc = ber_set_option( ber, LBER_OPT_REMAINING_BYTES, &len ); if( rc != LBER_OPT_SUCCESS ) { ld->ld_errno = LDAP_LOCAL_ERROR; ber_free( ber, 0 ); return NULL; } if ( ber_pvt_ber_remaining( ber ) == 0 ) { assert( len == 0 ); ber_free( ber, 0 ); return NULL; } assert( len != 0 ); /* snatch the first attribute */ tag = ber_scanf( ber, "{ax}", &attr ); if( tag == LBER_ERROR ) { ld->ld_errno = LDAP_DECODING_ERROR; ber_free( ber, 0 ); return NULL; } *berout = ber; return attr; } /* ARGSUSED */ char * ldap_next_attribute( LDAP *ld, LDAPMessage *entry, BerElement *ber ) { ber_tag_t tag; char *attr; Debug( LDAP_DEBUG_TRACE, "ldap_next_attribute\n", 0, 0, 0 ); assert( ld != NULL ); assert( LDAP_VALID( ld ) ); assert( entry != NULL ); assert( ber != NULL ); if ( ber_pvt_ber_remaining( ber ) == 0 ) { return NULL; } /* skip sequence, snarf attribute type, skip values */ tag = ber_scanf( ber, "{ax}", &attr ); if( tag == LBER_ERROR ) { ld->ld_errno = LDAP_DECODING_ERROR; return NULL; } return attr; } /* Fetch attribute type and optionally fetch values. The type * and values are referenced in-place from the BerElement, they are * not dup'd into malloc'd memory. */ /* ARGSUSED */ int ldap_get_attribute_ber( LDAP *ld, LDAPMessage *entry, BerElement *ber, BerValue *attr, BerVarray *vals ) { ber_tag_t tag; int rc = LDAP_SUCCESS; Debug( LDAP_DEBUG_TRACE, "ldap_get_attribute_ber\n", 0, 0, 0 ); assert( ld != NULL ); assert( LDAP_VALID( ld ) ); assert( entry != NULL ); assert( ber != NULL ); assert( attr != NULL ); attr->bv_val = NULL; attr->bv_len = 0; if ( ber_pvt_ber_remaining( ber ) ) { ber_len_t siz = sizeof( BerValue ); /* skip sequence, snarf attribute type */ tag = ber_scanf( ber, vals ? "{mM}" : "{mx}", attr, vals, &siz, 0 ); if( tag == LBER_ERROR ) { rc = ld->ld_errno = LDAP_DECODING_ERROR; } } return rc; } openldap-2.4.42+dfsg/libraries/libldap/getvalues.c0000644000175000017500000000770212563404150020564 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (c) 1990 Regents of the University of Michigan. * All rights reserved. */ #include "portable.h" #include #include #include #include #include #include #include "ldap-int.h" char ** ldap_get_values( LDAP *ld, LDAPMessage *entry, LDAP_CONST char *target ) { BerElement ber; char *attr; int found = 0; char **vals; assert( ld != NULL ); assert( LDAP_VALID( ld ) ); assert( entry != NULL ); assert( target != NULL ); Debug( LDAP_DEBUG_TRACE, "ldap_get_values\n", 0, 0, 0 ); ber = *entry->lm_ber; /* skip sequence, dn, sequence of, and snag the first attr */ if ( ber_scanf( &ber, "{x{{a" /*}}}*/, &attr ) == LBER_ERROR ) { ld->ld_errno = LDAP_DECODING_ERROR; return( NULL ); } if ( strcasecmp( target, attr ) == 0 ) found = 1; /* break out on success, return out on error */ while ( ! found ) { LDAP_FREE(attr); attr = NULL; if ( ber_scanf( &ber, /*{*/ "x}{a" /*}*/, &attr ) == LBER_ERROR ) { ld->ld_errno = LDAP_DECODING_ERROR; return( NULL ); } if ( strcasecmp( target, attr ) == 0 ) break; } LDAP_FREE(attr); attr = NULL; /* * if we get this far, we've found the attribute and are sitting * just before the set of values. */ if ( ber_scanf( &ber, "[v]", &vals ) == LBER_ERROR ) { ld->ld_errno = LDAP_DECODING_ERROR; return( NULL ); } return( vals ); } struct berval ** ldap_get_values_len( LDAP *ld, LDAPMessage *entry, LDAP_CONST char *target ) { BerElement ber; char *attr; int found = 0; struct berval **vals; assert( ld != NULL ); assert( LDAP_VALID( ld ) ); assert( entry != NULL ); assert( target != NULL ); Debug( LDAP_DEBUG_TRACE, "ldap_get_values_len\n", 0, 0, 0 ); ber = *entry->lm_ber; /* skip sequence, dn, sequence of, and snag the first attr */ if ( ber_scanf( &ber, "{x{{a" /* }}} */, &attr ) == LBER_ERROR ) { ld->ld_errno = LDAP_DECODING_ERROR; return( NULL ); } if ( strcasecmp( target, attr ) == 0 ) found = 1; /* break out on success, return out on error */ while ( ! found ) { LDAP_FREE( attr ); attr = NULL; if ( ber_scanf( &ber, /*{*/ "x}{a" /*}*/, &attr ) == LBER_ERROR ) { ld->ld_errno = LDAP_DECODING_ERROR; return( NULL ); } if ( strcasecmp( target, attr ) == 0 ) break; } LDAP_FREE( attr ); attr = NULL; /* * if we get this far, we've found the attribute and are sitting * just before the set of values. */ if ( ber_scanf( &ber, "[V]", &vals ) == LBER_ERROR ) { ld->ld_errno = LDAP_DECODING_ERROR; return( NULL ); } return( vals ); } int ldap_count_values( char **vals ) { int i; if ( vals == NULL ) return( 0 ); for ( i = 0; vals[i] != NULL; i++ ) ; /* NULL */ return( i ); } int ldap_count_values_len( struct berval **vals ) { return( ldap_count_values( (char **) vals ) ); } void ldap_value_free( char **vals ) { LDAP_VFREE( vals ); } void ldap_value_free_len( struct berval **vals ) { ber_bvecfree( vals ); } char ** ldap_value_dup( char *const *vals ) { char **new; int i; if( vals == NULL ) { return NULL; } for( i=0; vals[i]; i++ ) { ; /* Count the number of values */ } if( i == 0 ) { return NULL; } new = LDAP_MALLOC( (i+1)*sizeof(char *) ); /* Alloc array of pointers */ if( new == NULL ) { return NULL; } for( i=0; vals[i]; i++ ) { new[i] = LDAP_STRDUP( vals[i] ); /* Dup each value */ if( new[i] == NULL ) { LDAP_VFREE( new ); return NULL; } } new[i] = NULL; return new; } openldap-2.4.42+dfsg/libraries/libldap/tls_o.c0000644000175000017500000007176012563404150017712 0ustar ryanryan/* tls_o.c - Handle tls/ssl using OpenSSL */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 2008-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* ACKNOWLEDGEMENTS: Rewritten by Howard Chu */ #include "portable.h" #ifdef HAVE_OPENSSL #include "ldap_config.h" #include #include #include #include #include #include #include #include #include #include #include "ldap-int.h" #include "ldap-tls.h" #ifdef HAVE_OPENSSL_SSL_H #include #include #include #include #include #elif defined( HAVE_SSL_H ) #include #endif typedef SSL_CTX tlso_ctx; typedef SSL tlso_session; static int tlso_opt_trace = 1; static void tlso_report_error( void ); static void tlso_info_cb( const SSL *ssl, int where, int ret ); static int tlso_verify_cb( int ok, X509_STORE_CTX *ctx ); static int tlso_verify_ok( int ok, X509_STORE_CTX *ctx ); static RSA * tlso_tmp_rsa_cb( SSL *ssl, int is_export, int key_length ); static DH * tlso_tmp_dh_cb( SSL *ssl, int is_export, int key_length ); typedef struct dhplist { struct dhplist *next; int keylength; DH *param; } dhplist; static dhplist *tlso_dhparams; static int tlso_seed_PRNG( const char *randfile ); #ifdef LDAP_R_COMPILE /* * provide mutexes for the OpenSSL library. */ static ldap_pvt_thread_mutex_t tlso_mutexes[CRYPTO_NUM_LOCKS]; static ldap_pvt_thread_mutex_t tlso_dh_mutex; static void tlso_locking_cb( int mode, int type, const char *file, int line ) { if ( mode & CRYPTO_LOCK ) { ldap_pvt_thread_mutex_lock( &tlso_mutexes[type] ); } else { ldap_pvt_thread_mutex_unlock( &tlso_mutexes[type] ); } } static unsigned long tlso_thread_self( void ) { /* FIXME: CRYPTO_set_id_callback only works when ldap_pvt_thread_t * is an integral type that fits in an unsigned long */ /* force an error if the ldap_pvt_thread_t type is too large */ enum { ok = sizeof( ldap_pvt_thread_t ) <= sizeof( unsigned long ) }; typedef struct { int dummy: ok ? 1 : -1; } Check[ok ? 1 : -1]; return (unsigned long) ldap_pvt_thread_self(); } static void tlso_thr_init( void ) { int i; for( i=0; i< CRYPTO_NUM_LOCKS ; i++ ) { ldap_pvt_thread_mutex_init( &tlso_mutexes[i] ); } ldap_pvt_thread_mutex_init( &tlso_dh_mutex ); CRYPTO_set_locking_callback( tlso_locking_cb ); CRYPTO_set_id_callback( tlso_thread_self ); } #endif /* LDAP_R_COMPILE */ static STACK_OF(X509_NAME) * tlso_ca_list( char * bundle, char * dir ) { STACK_OF(X509_NAME) *ca_list = NULL; if ( bundle ) { ca_list = SSL_load_client_CA_file( bundle ); } #if defined(HAVE_DIRENT_H) || defined(dirent) if ( dir ) { int freeit = 0; if ( !ca_list ) { ca_list = sk_X509_NAME_new_null(); freeit = 1; } if ( !SSL_add_dir_cert_subjects_to_stack( ca_list, dir ) && freeit ) { sk_X509_NAME_free( ca_list ); ca_list = NULL; } } #endif return ca_list; } /* * Initialize TLS subsystem. Should be called only once. */ static int tlso_init( void ) { struct ldapoptions *lo = LDAP_INT_GLOBAL_OPT(); #ifdef HAVE_EBCDIC { char *file = LDAP_STRDUP( lo->ldo_tls_randfile ); if ( file ) __atoe( file ); (void) tlso_seed_PRNG( file ); LDAP_FREE( file ); } #else (void) tlso_seed_PRNG( lo->ldo_tls_randfile ); #endif SSL_load_error_strings(); SSL_library_init(); OpenSSL_add_all_digests(); /* FIXME: mod_ssl does this */ X509V3_add_standard_extensions(); return 0; } /* * Tear down the TLS subsystem. Should only be called once. */ static void tlso_destroy( void ) { struct ldapoptions *lo = LDAP_INT_GLOBAL_OPT(); EVP_cleanup(); ERR_remove_state(0); ERR_free_strings(); if ( lo->ldo_tls_randfile ) { LDAP_FREE( lo->ldo_tls_randfile ); lo->ldo_tls_randfile = NULL; } } static tls_ctx * tlso_ctx_new( struct ldapoptions *lo ) { return (tls_ctx *) SSL_CTX_new( SSLv23_method() ); } static void tlso_ctx_ref( tls_ctx *ctx ) { tlso_ctx *c = (tlso_ctx *)ctx; CRYPTO_add( &c->references, 1, CRYPTO_LOCK_SSL_CTX ); } static void tlso_ctx_free ( tls_ctx *ctx ) { tlso_ctx *c = (tlso_ctx *)ctx; SSL_CTX_free( c ); } /* * initialize a new TLS context */ static int tlso_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server ) { tlso_ctx *ctx = (tlso_ctx *)lo->ldo_tls_ctx; int i; if ( is_server ) { SSL_CTX_set_session_id_context( ctx, (const unsigned char *) "OpenLDAP", sizeof("OpenLDAP")-1 ); } #ifdef SSL_OP_NO_TLSv1 #ifdef SSL_OP_NO_TLSv1_1 #ifdef SSL_OP_NO_TLSv1_2 if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_TLS1_2) SSL_CTX_set_options( ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2 ); else #endif if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_TLS1_1) SSL_CTX_set_options( ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 ); else #endif if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_TLS1_0) SSL_CTX_set_options( ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1); else #endif if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_SSL3 ) SSL_CTX_set_options( ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 ); else if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_SSL2 ) SSL_CTX_set_options( ctx, SSL_OP_NO_SSLv2 ); if ( lo->ldo_tls_ciphersuite && !SSL_CTX_set_cipher_list( ctx, lt->lt_ciphersuite ) ) { Debug( LDAP_DEBUG_ANY, "TLS: could not set cipher list %s.\n", lo->ldo_tls_ciphersuite, 0, 0 ); tlso_report_error(); return -1; } if (lo->ldo_tls_cacertfile != NULL || lo->ldo_tls_cacertdir != NULL) { if ( !SSL_CTX_load_verify_locations( ctx, lt->lt_cacertfile, lt->lt_cacertdir ) || !SSL_CTX_set_default_verify_paths( ctx ) ) { Debug( LDAP_DEBUG_ANY, "TLS: " "could not load verify locations (file:`%s',dir:`%s').\n", lo->ldo_tls_cacertfile ? lo->ldo_tls_cacertfile : "", lo->ldo_tls_cacertdir ? lo->ldo_tls_cacertdir : "", 0 ); tlso_report_error(); return -1; } if ( is_server ) { STACK_OF(X509_NAME) *calist; /* List of CA names to send to a client */ calist = tlso_ca_list( lt->lt_cacertfile, lt->lt_cacertdir ); if ( !calist ) { Debug( LDAP_DEBUG_ANY, "TLS: " "could not load client CA list (file:`%s',dir:`%s').\n", lo->ldo_tls_cacertfile ? lo->ldo_tls_cacertfile : "", lo->ldo_tls_cacertdir ? lo->ldo_tls_cacertdir : "", 0 ); tlso_report_error(); return -1; } SSL_CTX_set_client_CA_list( ctx, calist ); } } if ( lo->ldo_tls_certfile && !SSL_CTX_use_certificate_file( ctx, lt->lt_certfile, SSL_FILETYPE_PEM ) ) { Debug( LDAP_DEBUG_ANY, "TLS: could not use certificate `%s'.\n", lo->ldo_tls_certfile,0,0); tlso_report_error(); return -1; } /* Key validity is checked automatically if cert has already been set */ if ( lo->ldo_tls_keyfile && !SSL_CTX_use_PrivateKey_file( ctx, lt->lt_keyfile, SSL_FILETYPE_PEM ) ) { Debug( LDAP_DEBUG_ANY, "TLS: could not use key file `%s'.\n", lo->ldo_tls_keyfile,0,0); tlso_report_error(); return -1; } if ( lo->ldo_tls_dhfile ) { DH *dh = NULL; BIO *bio; dhplist *p; if (( bio=BIO_new_file( lt->lt_dhfile,"r" )) == NULL ) { Debug( LDAP_DEBUG_ANY, "TLS: could not use DH parameters file `%s'.\n", lo->ldo_tls_dhfile,0,0); tlso_report_error(); return -1; } while (( dh=PEM_read_bio_DHparams( bio, NULL, NULL, NULL ))) { p = LDAP_MALLOC( sizeof(dhplist) ); if ( p != NULL ) { p->keylength = DH_size( dh ) * 8; p->param = dh; p->next = tlso_dhparams; tlso_dhparams = p; } } BIO_free( bio ); } if ( tlso_opt_trace ) { SSL_CTX_set_info_callback( ctx, tlso_info_cb ); } i = SSL_VERIFY_NONE; if ( lo->ldo_tls_require_cert ) { i = SSL_VERIFY_PEER; if ( lo->ldo_tls_require_cert == LDAP_OPT_X_TLS_DEMAND || lo->ldo_tls_require_cert == LDAP_OPT_X_TLS_HARD ) { i |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; } } SSL_CTX_set_verify( ctx, i, lo->ldo_tls_require_cert == LDAP_OPT_X_TLS_ALLOW ? tlso_verify_ok : tlso_verify_cb ); SSL_CTX_set_tmp_rsa_callback( ctx, tlso_tmp_rsa_cb ); if ( lo->ldo_tls_dhfile ) { SSL_CTX_set_tmp_dh_callback( ctx, tlso_tmp_dh_cb ); } #ifdef HAVE_OPENSSL_CRL if ( lo->ldo_tls_crlcheck ) { X509_STORE *x509_s = SSL_CTX_get_cert_store( ctx ); if ( lo->ldo_tls_crlcheck == LDAP_OPT_X_TLS_CRL_PEER ) { X509_STORE_set_flags( x509_s, X509_V_FLAG_CRL_CHECK ); } else if ( lo->ldo_tls_crlcheck == LDAP_OPT_X_TLS_CRL_ALL ) { X509_STORE_set_flags( x509_s, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL ); } } #endif return 0; } static tls_session * tlso_session_new( tls_ctx *ctx, int is_server ) { tlso_ctx *c = (tlso_ctx *)ctx; return (tls_session *)SSL_new( c ); } static int tlso_session_connect( LDAP *ld, tls_session *sess ) { tlso_session *s = (tlso_session *)sess; /* Caller expects 0 = success, OpenSSL returns 1 = success */ return SSL_connect( s ) - 1; } static int tlso_session_accept( tls_session *sess ) { tlso_session *s = (tlso_session *)sess; /* Caller expects 0 = success, OpenSSL returns 1 = success */ return SSL_accept( s ) - 1; } static int tlso_session_upflags( Sockbuf *sb, tls_session *sess, int rc ) { tlso_session *s = (tlso_session *)sess; /* 1 was subtracted above, offset it back now */ rc = SSL_get_error(s, rc+1); if (rc == SSL_ERROR_WANT_READ) { sb->sb_trans_needs_read = 1; return 1; } else if (rc == SSL_ERROR_WANT_WRITE) { sb->sb_trans_needs_write = 1; return 1; } else if (rc == SSL_ERROR_WANT_CONNECT) { return 1; } return 0; } static char * tlso_session_errmsg( tls_session *sess, int rc, char *buf, size_t len ) { char err[256] = ""; const char *certerr=NULL; tlso_session *s = (tlso_session *)sess; rc = ERR_peek_error(); if ( rc ) { ERR_error_string_n( rc, err, sizeof(err) ); if ( ( ERR_GET_LIB(rc) == ERR_LIB_SSL ) && ( ERR_GET_REASON(rc) == SSL_R_CERTIFICATE_VERIFY_FAILED ) ) { int certrc = SSL_get_verify_result(s); certerr = (char *)X509_verify_cert_error_string(certrc); } snprintf(buf, len, "%s%s%s%s", err, certerr ? " (" :"", certerr ? certerr : "", certerr ? ")" : "" ); return buf; } return NULL; } static int tlso_session_my_dn( tls_session *sess, struct berval *der_dn ) { tlso_session *s = (tlso_session *)sess; X509 *x; X509_NAME *xn; x = SSL_get_certificate( s ); if (!x) return LDAP_INVALID_CREDENTIALS; xn = X509_get_subject_name(x); der_dn->bv_len = i2d_X509_NAME( xn, NULL ); der_dn->bv_val = xn->bytes->data; /* Don't X509_free, the session is still using it */ return 0; } static X509 * tlso_get_cert( SSL *s ) { /* If peer cert was bad, treat as if no cert was given */ if (SSL_get_verify_result(s)) { return NULL; } return SSL_get_peer_certificate(s); } static int tlso_session_peer_dn( tls_session *sess, struct berval *der_dn ) { tlso_session *s = (tlso_session *)sess; X509 *x = tlso_get_cert( s ); X509_NAME *xn; if ( !x ) return LDAP_INVALID_CREDENTIALS; xn = X509_get_subject_name(x); der_dn->bv_len = i2d_X509_NAME( xn, NULL ); der_dn->bv_val = xn->bytes->data; X509_free(x); return 0; } /* what kind of hostname were we given? */ #define IS_DNS 0 #define IS_IP4 1 #define IS_IP6 2 static int tlso_session_chkhost( LDAP *ld, tls_session *sess, const char *name_in ) { tlso_session *s = (tlso_session *)sess; int i, ret = LDAP_LOCAL_ERROR; X509 *x; const char *name; char *ptr; int ntype = IS_DNS, nlen; #ifdef LDAP_PF_INET6 struct in6_addr addr; #else struct in_addr addr; #endif if( ldap_int_hostname && ( !name_in || !strcasecmp( name_in, "localhost" ) ) ) { name = ldap_int_hostname; } else { name = name_in; } nlen = strlen(name); x = tlso_get_cert(s); if (!x) { Debug( LDAP_DEBUG_ANY, "TLS: unable to get peer certificate.\n", 0, 0, 0 ); /* If this was a fatal condition, things would have * aborted long before now. */ return LDAP_SUCCESS; } #ifdef LDAP_PF_INET6 if (inet_pton(AF_INET6, name, &addr)) { ntype = IS_IP6; } else #endif if ((ptr = strrchr(name, '.')) && isdigit((unsigned char)ptr[1])) { if (inet_aton(name, (struct in_addr *)&addr)) ntype = IS_IP4; } i = X509_get_ext_by_NID(x, NID_subject_alt_name, -1); if (i >= 0) { X509_EXTENSION *ex; STACK_OF(GENERAL_NAME) *alt; ex = X509_get_ext(x, i); alt = X509V3_EXT_d2i(ex); if (alt) { int n, len2 = 0; char *domain = NULL; GENERAL_NAME *gn; if (ntype == IS_DNS) { domain = strchr(name, '.'); if (domain) { len2 = nlen - (domain-name); } } n = sk_GENERAL_NAME_num(alt); for (i=0; itype == GEN_DNS) { if (ntype != IS_DNS) continue; sn = (char *) ASN1_STRING_data(gn->d.ia5); sl = ASN1_STRING_length(gn->d.ia5); /* ignore empty */ if (sl == 0) continue; /* Is this an exact match? */ if ((nlen == sl) && !strncasecmp(name, sn, nlen)) { break; } /* Is this a wildcard match? */ if (domain && (sn[0] == '*') && (sn[1] == '.') && (len2 == sl-1) && !strncasecmp(domain, &sn[1], len2)) { break; } } else if (gn->type == GEN_IPADD) { if (ntype == IS_DNS) continue; sn = (char *) ASN1_STRING_data(gn->d.ia5); sl = ASN1_STRING_length(gn->d.ia5); #ifdef LDAP_PF_INET6 if (ntype == IS_IP6 && sl != sizeof(struct in6_addr)) { continue; } else #endif if (ntype == IS_IP4 && sl != sizeof(struct in_addr)) { continue; } if (!memcmp(sn, &addr, sl)) { break; } } } GENERAL_NAMES_free(alt); if (i < n) { /* Found a match */ ret = LDAP_SUCCESS; } } } if (ret != LDAP_SUCCESS) { X509_NAME *xn; X509_NAME_ENTRY *ne; ASN1_OBJECT *obj; ASN1_STRING *cn = NULL; int navas; /* find the last CN */ obj = OBJ_nid2obj( NID_commonName ); if ( !obj ) goto no_cn; /* should never happen */ xn = X509_get_subject_name(x); navas = X509_NAME_entry_count( xn ); for ( i=navas-1; i>=0; i-- ) { ne = X509_NAME_get_entry( xn, i ); if ( !OBJ_cmp( ne->object, obj )) { cn = X509_NAME_ENTRY_get_data( ne ); break; } } if( !cn ) { no_cn: Debug( LDAP_DEBUG_ANY, "TLS: unable to get common name from peer certificate.\n", 0, 0, 0 ); ret = LDAP_CONNECT_ERROR; if ( ld->ld_error ) { LDAP_FREE( ld->ld_error ); } ld->ld_error = LDAP_STRDUP( _("TLS: unable to get CN from peer certificate")); } else if ( cn->length == nlen && strncasecmp( name, (char *) cn->data, nlen ) == 0 ) { ret = LDAP_SUCCESS; } else if (( cn->data[0] == '*' ) && ( cn->data[1] == '.' )) { char *domain = strchr(name, '.'); if( domain ) { int dlen; dlen = nlen - (domain-name); /* Is this a wildcard match? */ if ((dlen == cn->length-1) && !strncasecmp(domain, (char *) &cn->data[1], dlen)) { ret = LDAP_SUCCESS; } } } if( ret == LDAP_LOCAL_ERROR ) { Debug( LDAP_DEBUG_ANY, "TLS: hostname (%s) does not match " "common name in certificate (%.*s).\n", name, cn->length, cn->data ); ret = LDAP_CONNECT_ERROR; if ( ld->ld_error ) { LDAP_FREE( ld->ld_error ); } ld->ld_error = LDAP_STRDUP( _("TLS: hostname does not match CN in peer certificate")); } } X509_free(x); return ret; } static int tlso_session_strength( tls_session *sess ) { tlso_session *s = (tlso_session *)sess; return SSL_CIPHER_get_bits(SSL_get_current_cipher(s), NULL); } /* * TLS support for LBER Sockbufs */ struct tls_data { tlso_session *session; Sockbuf_IO_Desc *sbiod; }; static int tlso_bio_create( BIO *b ) { b->init = 1; b->num = 0; b->ptr = NULL; b->flags = 0; return 1; } static int tlso_bio_destroy( BIO *b ) { if ( b == NULL ) return 0; b->ptr = NULL; /* sb_tls_remove() will free it */ b->init = 0; b->flags = 0; return 1; } static int tlso_bio_read( BIO *b, char *buf, int len ) { struct tls_data *p; int ret; if ( buf == NULL || len <= 0 ) return 0; p = (struct tls_data *)b->ptr; if ( p == NULL || p->sbiod == NULL ) { return 0; } ret = LBER_SBIOD_READ_NEXT( p->sbiod, buf, len ); BIO_clear_retry_flags( b ); if ( ret < 0 ) { int err = sock_errno(); if ( err == EAGAIN || err == EWOULDBLOCK ) { BIO_set_retry_read( b ); } } return ret; } static int tlso_bio_write( BIO *b, const char *buf, int len ) { struct tls_data *p; int ret; if ( buf == NULL || len <= 0 ) return 0; p = (struct tls_data *)b->ptr; if ( p == NULL || p->sbiod == NULL ) { return 0; } ret = LBER_SBIOD_WRITE_NEXT( p->sbiod, (char *)buf, len ); BIO_clear_retry_flags( b ); if ( ret < 0 ) { int err = sock_errno(); if ( err == EAGAIN || err == EWOULDBLOCK ) { BIO_set_retry_write( b ); } } return ret; } static long tlso_bio_ctrl( BIO *b, int cmd, long num, void *ptr ) { if ( cmd == BIO_CTRL_FLUSH ) { /* The OpenSSL library needs this */ return 1; } return 0; } static int tlso_bio_gets( BIO *b, char *buf, int len ) { return -1; } static int tlso_bio_puts( BIO *b, const char *str ) { return tlso_bio_write( b, str, strlen( str ) ); } static BIO_METHOD tlso_bio_method = { ( 100 | 0x400 ), /* it's a source/sink BIO */ "sockbuf glue", tlso_bio_write, tlso_bio_read, tlso_bio_puts, tlso_bio_gets, tlso_bio_ctrl, tlso_bio_create, tlso_bio_destroy }; static int tlso_sb_setup( Sockbuf_IO_Desc *sbiod, void *arg ) { struct tls_data *p; BIO *bio; assert( sbiod != NULL ); p = LBER_MALLOC( sizeof( *p ) ); if ( p == NULL ) { return -1; } p->session = arg; p->sbiod = sbiod; bio = BIO_new( &tlso_bio_method ); bio->ptr = (void *)p; SSL_set_bio( p->session, bio, bio ); sbiod->sbiod_pvt = p; return 0; } static int tlso_sb_remove( Sockbuf_IO_Desc *sbiod ) { struct tls_data *p; assert( sbiod != NULL ); assert( sbiod->sbiod_pvt != NULL ); p = (struct tls_data *)sbiod->sbiod_pvt; SSL_free( p->session ); LBER_FREE( sbiod->sbiod_pvt ); sbiod->sbiod_pvt = NULL; return 0; } static int tlso_sb_close( Sockbuf_IO_Desc *sbiod ) { struct tls_data *p; assert( sbiod != NULL ); assert( sbiod->sbiod_pvt != NULL ); p = (struct tls_data *)sbiod->sbiod_pvt; SSL_shutdown( p->session ); return 0; } static int tlso_sb_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) { struct tls_data *p; assert( sbiod != NULL ); assert( sbiod->sbiod_pvt != NULL ); p = (struct tls_data *)sbiod->sbiod_pvt; if ( opt == LBER_SB_OPT_GET_SSL ) { *((tlso_session **)arg) = p->session; return 1; } else if ( opt == LBER_SB_OPT_DATA_READY ) { if( SSL_pending( p->session ) > 0 ) { return 1; } } return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg ); } static ber_slen_t tlso_sb_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) { struct tls_data *p; ber_slen_t ret; int err; assert( sbiod != NULL ); assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); p = (struct tls_data *)sbiod->sbiod_pvt; ret = SSL_read( p->session, (char *)buf, len ); #ifdef HAVE_WINSOCK errno = WSAGetLastError(); #endif err = SSL_get_error( p->session, ret ); if (err == SSL_ERROR_WANT_READ ) { sbiod->sbiod_sb->sb_trans_needs_read = 1; sock_errset(EWOULDBLOCK); } else sbiod->sbiod_sb->sb_trans_needs_read = 0; return ret; } static ber_slen_t tlso_sb_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) { struct tls_data *p; ber_slen_t ret; int err; assert( sbiod != NULL ); assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); p = (struct tls_data *)sbiod->sbiod_pvt; ret = SSL_write( p->session, (char *)buf, len ); #ifdef HAVE_WINSOCK errno = WSAGetLastError(); #endif err = SSL_get_error( p->session, ret ); if (err == SSL_ERROR_WANT_WRITE ) { sbiod->sbiod_sb->sb_trans_needs_write = 1; sock_errset(EWOULDBLOCK); } else { sbiod->sbiod_sb->sb_trans_needs_write = 0; } return ret; } static Sockbuf_IO tlso_sbio = { tlso_sb_setup, /* sbi_setup */ tlso_sb_remove, /* sbi_remove */ tlso_sb_ctrl, /* sbi_ctrl */ tlso_sb_read, /* sbi_read */ tlso_sb_write, /* sbi_write */ tlso_sb_close /* sbi_close */ }; /* Derived from openssl/apps/s_cb.c */ static void tlso_info_cb( const SSL *ssl, int where, int ret ) { int w; char *op; char *state = (char *) SSL_state_string_long( (SSL *)ssl ); w = where & ~SSL_ST_MASK; if ( w & SSL_ST_CONNECT ) { op = "SSL_connect"; } else if ( w & SSL_ST_ACCEPT ) { op = "SSL_accept"; } else { op = "undefined"; } #ifdef HAVE_EBCDIC if ( state ) { state = LDAP_STRDUP( state ); __etoa( state ); } #endif if ( where & SSL_CB_LOOP ) { Debug( LDAP_DEBUG_TRACE, "TLS trace: %s:%s\n", op, state, 0 ); } else if ( where & SSL_CB_ALERT ) { char *atype = (char *) SSL_alert_type_string_long( ret ); char *adesc = (char *) SSL_alert_desc_string_long( ret ); op = ( where & SSL_CB_READ ) ? "read" : "write"; #ifdef HAVE_EBCDIC if ( atype ) { atype = LDAP_STRDUP( atype ); __etoa( atype ); } if ( adesc ) { adesc = LDAP_STRDUP( adesc ); __etoa( adesc ); } #endif Debug( LDAP_DEBUG_TRACE, "TLS trace: SSL3 alert %s:%s:%s\n", op, atype, adesc ); #ifdef HAVE_EBCDIC if ( atype ) LDAP_FREE( atype ); if ( adesc ) LDAP_FREE( adesc ); #endif } else if ( where & SSL_CB_EXIT ) { if ( ret == 0 ) { Debug( LDAP_DEBUG_TRACE, "TLS trace: %s:failed in %s\n", op, state, 0 ); } else if ( ret < 0 ) { Debug( LDAP_DEBUG_TRACE, "TLS trace: %s:error in %s\n", op, state, 0 ); } } #ifdef HAVE_EBCDIC if ( state ) LDAP_FREE( state ); #endif } static int tlso_verify_cb( int ok, X509_STORE_CTX *ctx ) { X509 *cert; int errnum; int errdepth; X509_NAME *subject; X509_NAME *issuer; char *sname; char *iname; char *certerr = NULL; cert = X509_STORE_CTX_get_current_cert( ctx ); errnum = X509_STORE_CTX_get_error( ctx ); errdepth = X509_STORE_CTX_get_error_depth( ctx ); /* * X509_get_*_name return pointers to the internal copies of * those things requested. So do not free them. */ subject = X509_get_subject_name( cert ); issuer = X509_get_issuer_name( cert ); /* X509_NAME_oneline, if passed a NULL buf, allocate memomry */ sname = X509_NAME_oneline( subject, NULL, 0 ); iname = X509_NAME_oneline( issuer, NULL, 0 ); if ( !ok ) certerr = (char *)X509_verify_cert_error_string( errnum ); #ifdef HAVE_EBCDIC if ( sname ) __etoa( sname ); if ( iname ) __etoa( iname ); if ( certerr ) { certerr = LDAP_STRDUP( certerr ); __etoa( certerr ); } #endif Debug( LDAP_DEBUG_TRACE, "TLS certificate verification: depth: %d, err: %d, subject: %s,", errdepth, errnum, sname ? sname : "-unknown-" ); Debug( LDAP_DEBUG_TRACE, " issuer: %s\n", iname ? iname : "-unknown-", 0, 0 ); if ( !ok ) { Debug( LDAP_DEBUG_ANY, "TLS certificate verification: Error, %s\n", certerr, 0, 0 ); } if ( sname ) CRYPTO_free ( sname ); if ( iname ) CRYPTO_free ( iname ); #ifdef HAVE_EBCDIC if ( certerr ) LDAP_FREE( certerr ); #endif return ok; } static int tlso_verify_ok( int ok, X509_STORE_CTX *ctx ) { (void) tlso_verify_cb( ok, ctx ); return 1; } /* Inspired by ERR_print_errors in OpenSSL */ static void tlso_report_error( void ) { unsigned long l; char buf[200]; const char *file; int line; while ( ( l = ERR_get_error_line( &file, &line ) ) != 0 ) { ERR_error_string_n( l, buf, sizeof( buf ) ); #ifdef HAVE_EBCDIC if ( file ) { file = LDAP_STRDUP( file ); __etoa( (char *)file ); } __etoa( buf ); #endif Debug( LDAP_DEBUG_ANY, "TLS: %s %s:%d\n", buf, file, line ); #ifdef HAVE_EBCDIC if ( file ) LDAP_FREE( (void *)file ); #endif } } static RSA * tlso_tmp_rsa_cb( SSL *ssl, int is_export, int key_length ) { RSA *tmp_rsa; /* FIXME: Pregenerate the key on startup */ /* FIXME: Who frees the key? */ #if OPENSSL_VERSION_NUMBER >= 0x00908000 BIGNUM *bn = BN_new(); tmp_rsa = NULL; if ( bn ) { if ( BN_set_word( bn, RSA_F4 )) { tmp_rsa = RSA_new(); if ( tmp_rsa && !RSA_generate_key_ex( tmp_rsa, key_length, bn, NULL )) { RSA_free( tmp_rsa ); tmp_rsa = NULL; } } BN_free( bn ); } #else tmp_rsa = RSA_generate_key( key_length, RSA_F4, NULL, NULL ); #endif if ( !tmp_rsa ) { Debug( LDAP_DEBUG_ANY, "TLS: Failed to generate temporary %d-bit %s RSA key\n", key_length, is_export ? "export" : "domestic", 0 ); } return tmp_rsa; } static int tlso_seed_PRNG( const char *randfile ) { #ifndef URANDOM_DEVICE /* no /dev/urandom (or equiv) */ long total=0; char buffer[MAXPATHLEN]; if (randfile == NULL) { /* The seed file is $RANDFILE if defined, otherwise $HOME/.rnd. * If $HOME is not set or buffer too small to hold the pathname, * an error occurs. - From RAND_file_name() man page. * The fact is that when $HOME is NULL, .rnd is used. */ randfile = RAND_file_name( buffer, sizeof( buffer ) ); } else if (RAND_egd(randfile) > 0) { /* EGD socket */ return 0; } if (randfile == NULL) { Debug( LDAP_DEBUG_ANY, "TLS: Use configuration file or $RANDFILE to define seed PRNG\n", 0, 0, 0); return -1; } total = RAND_load_file(randfile, -1); if (RAND_status() == 0) { Debug( LDAP_DEBUG_ANY, "TLS: PRNG not been seeded with enough data\n", 0, 0, 0); return -1; } /* assume if there was enough bits to seed that it's okay * to write derived bits to the file */ RAND_write_file(randfile); #endif return 0; } struct dhinfo { int keylength; const char *pem; size_t size; }; /* From the OpenSSL 0.9.7 distro */ static const char tlso_dhpem512[] = "-----BEGIN DH PARAMETERS-----\n\ MEYCQQDaWDwW2YUiidDkr3VvTMqS3UvlM7gE+w/tlO+cikQD7VdGUNNpmdsp13Yn\n\ a6LT1BLiGPTdHghM9tgAPnxHdOgzAgEC\n\ -----END DH PARAMETERS-----\n"; static const char tlso_dhpem1024[] = "-----BEGIN DH PARAMETERS-----\n\ MIGHAoGBAJf2QmHKtQXdKCjhPx1ottPb0PMTBH9A6FbaWMsTuKG/K3g6TG1Z1fkq\n\ /Gz/PWk/eLI9TzFgqVAuPvr3q14a1aZeVUMTgo2oO5/y2UHe6VaJ+trqCTat3xlx\n\ /mNbIK9HA2RgPC3gWfVLZQrY+gz3ASHHR5nXWHEyvpuZm7m3h+irAgEC\n\ -----END DH PARAMETERS-----\n"; static const char tlso_dhpem2048[] = "-----BEGIN DH PARAMETERS-----\n\ MIIBCAKCAQEA7ZKJNYJFVcs7+6J2WmkEYb8h86tT0s0h2v94GRFS8Q7B4lW9aG9o\n\ AFO5Imov5Jo0H2XMWTKKvbHbSe3fpxJmw/0hBHAY8H/W91hRGXKCeyKpNBgdL8sh\n\ z22SrkO2qCnHJ6PLAMXy5fsKpFmFor2tRfCzrfnggTXu2YOzzK7q62bmqVdmufEo\n\ pT8igNcLpvZxk5uBDvhakObMym9mX3rAEBoe8PwttggMYiiw7NuJKO4MqD1llGkW\n\ aVM8U2ATsCun1IKHrRxynkE1/MJ86VHeYYX8GZt2YA8z+GuzylIOKcMH6JAWzMwA\n\ Gbatw6QwizOhr9iMjZ0B26TE3X8LvW84wwIBAg==\n\ -----END DH PARAMETERS-----\n"; static const char tlso_dhpem4096[] = "-----BEGIN DH PARAMETERS-----\n\ MIICCAKCAgEA/urRnb6vkPYc/KEGXWnbCIOaKitq7ySIq9dTH7s+Ri59zs77zty7\n\ vfVlSe6VFTBWgYjD2XKUFmtqq6CqXMhVX5ElUDoYDpAyTH85xqNFLzFC7nKrff/H\n\ TFKNttp22cZE9V0IPpzedPfnQkE7aUdmF9JnDyv21Z/818O93u1B4r0szdnmEvEF\n\ bKuIxEHX+bp0ZR7RqE1AeifXGJX3d6tsd2PMAObxwwsv55RGkn50vHO4QxtTARr1\n\ rRUV5j3B3oPMgC7Offxx+98Xn45B1/G0Prp11anDsR1PGwtaCYipqsvMwQUSJtyE\n\ EOQWk+yFkeMe4vWv367eEi0Sd/wnC+TSXBE3pYvpYerJ8n1MceI5GQTdarJ77OW9\n\ bGTHmxRsLSCM1jpLdPja5jjb4siAa6EHc4qN9c/iFKS3PQPJEnX7pXKBRs5f7AF3\n\ W3RIGt+G9IVNZfXaS7Z/iCpgzgvKCs0VeqN38QsJGtC1aIkwOeyjPNy2G6jJ4yqH\n\ ovXYt/0mc00vCWeSNS1wren0pR2EiLxX0ypjjgsU1mk/Z3b/+zVf7fZSIB+nDLjb\n\ NPtUlJCVGnAeBK1J1nG3TQicqowOXoM6ISkdaXj5GPJdXHab2+S7cqhKGv5qC7rR\n\ jT6sx7RUr0CNTxzLI7muV2/a4tGmj0PSdXQdsZ7tw7gbXlaWT1+MM2MCAQI=\n\ -----END DH PARAMETERS-----\n"; static const struct dhinfo tlso_dhpem[] = { { 512, tlso_dhpem512, sizeof(tlso_dhpem512) }, { 1024, tlso_dhpem1024, sizeof(tlso_dhpem1024) }, { 2048, tlso_dhpem2048, sizeof(tlso_dhpem2048) }, { 4096, tlso_dhpem4096, sizeof(tlso_dhpem4096) }, { 0, NULL, 0 } }; static DH * tlso_tmp_dh_cb( SSL *ssl, int is_export, int key_length ) { struct dhplist *p = NULL; BIO *b = NULL; DH *dh = NULL; int i; /* Do we have params of this length already? */ LDAP_MUTEX_LOCK( &tlso_dh_mutex ); for ( p = tlso_dhparams; p; p=p->next ) { if ( p->keylength == key_length ) { LDAP_MUTEX_UNLOCK( &tlso_dh_mutex ); return p->param; } } /* No - check for hardcoded params */ for (i=0; tlso_dhpem[i].keylength; i++) { if ( tlso_dhpem[i].keylength == key_length ) { b = BIO_new_mem_buf( (char *)tlso_dhpem[i].pem, tlso_dhpem[i].size ); break; } } if ( b ) { dh = PEM_read_bio_DHparams( b, NULL, NULL, NULL ); BIO_free( b ); } /* Generating on the fly is expensive/slow... */ if ( !dh ) { dh = DH_generate_parameters( key_length, DH_GENERATOR_2, NULL, NULL ); } if ( dh ) { p = LDAP_MALLOC( sizeof(struct dhplist) ); if ( p != NULL ) { p->keylength = key_length; p->param = dh; p->next = tlso_dhparams; tlso_dhparams = p; } } LDAP_MUTEX_UNLOCK( &tlso_dh_mutex ); return dh; } tls_impl ldap_int_tls_impl = { "OpenSSL", tlso_init, tlso_destroy, tlso_ctx_new, tlso_ctx_ref, tlso_ctx_free, tlso_ctx_init, tlso_session_new, tlso_session_connect, tlso_session_accept, tlso_session_upflags, tlso_session_errmsg, tlso_session_my_dn, tlso_session_peer_dn, tlso_session_chkhost, tlso_session_strength, &tlso_sbio, #ifdef LDAP_R_COMPILE tlso_thr_init, #else NULL, #endif 0 }; #endif /* HAVE_OPENSSL */ openldap-2.4.42+dfsg/libraries/libldap/compare.c0000644000175000017500000001000712563404150020203 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (c) 1990 Regents of the University of Michigan. * All rights reserved. */ #include "portable.h" #include #include #include #include #include "ldap-int.h" #include "ldap_log.h" /* The compare request looks like this: * CompareRequest ::= SEQUENCE { * entry DistinguishedName, * ava SEQUENCE { * type AttributeType, * value AttributeValue * } * } */ /* * ldap_compare_ext - perform an ldap extended compare operation. The dn * of the entry to compare to and the attribute and value to compare (in * attr and value) are supplied. The msgid of the response is returned. * * Example: * struct berval bvalue = { "secret", sizeof("secret")-1 }; * rc = ldap_compare( ld, "c=us@cn=bob", * "userPassword", &bvalue, * sctrl, cctrl, &msgid ) */ int ldap_compare_ext( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *attr, struct berval *bvalue, LDAPControl **sctrls, LDAPControl **cctrls, int *msgidp ) { int rc; BerElement *ber; ber_int_t id; Debug( LDAP_DEBUG_TRACE, "ldap_compare\n", 0, 0, 0 ); assert( ld != NULL ); assert( LDAP_VALID( ld ) ); assert( dn != NULL ); assert( attr != NULL ); assert( msgidp != NULL ); /* check client controls */ rc = ldap_int_client_controls( ld, cctrls ); if( rc != LDAP_SUCCESS ) return rc; /* create a message to send */ if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) { return( LDAP_NO_MEMORY ); } LDAP_NEXT_MSGID(ld, id); rc = ber_printf( ber, "{it{s{sON}N}", /* '}' */ id, LDAP_REQ_COMPARE, dn, attr, bvalue ); if ( rc == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( ld->ld_errno ); } /* Put Server Controls */ if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) { ber_free( ber, 1 ); return ld->ld_errno; } if( ber_printf( ber, /*{*/ "N}" ) == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( ld->ld_errno ); } /* send the message */ *msgidp = ldap_send_initial_request( ld, LDAP_REQ_COMPARE, dn, ber, id ); return ( *msgidp < 0 ? ld->ld_errno : LDAP_SUCCESS ); } /* * ldap_compare_ext - perform an ldap extended compare operation. The dn * of the entry to compare to and the attribute and value to compare (in * attr and value) are supplied. The msgid of the response is returned. * * Example: * msgid = ldap_compare( ld, "c=us@cn=bob", "userPassword", "secret" ) */ int ldap_compare( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *attr, LDAP_CONST char *value ) { int msgid; struct berval bvalue; assert( value != NULL ); bvalue.bv_val = (char *) value; bvalue.bv_len = (value == NULL) ? 0 : strlen( value ); return ldap_compare_ext( ld, dn, attr, &bvalue, NULL, NULL, &msgid ) == LDAP_SUCCESS ? msgid : -1; } int ldap_compare_ext_s( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *attr, struct berval *bvalue, LDAPControl **sctrl, LDAPControl **cctrl ) { int rc; int msgid; LDAPMessage *res; rc = ldap_compare_ext( ld, dn, attr, bvalue, sctrl, cctrl, &msgid ); if ( rc != LDAP_SUCCESS ) return( rc ); if ( ldap_result( ld, msgid, LDAP_MSG_ALL, (struct timeval *) NULL, &res ) == -1 || !res ) return( ld->ld_errno ); return( ldap_result2error( ld, res, 1 ) ); } int ldap_compare_s( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *attr, LDAP_CONST char *value ) { struct berval bvalue; assert( value != NULL ); bvalue.bv_val = (char *) value; bvalue.bv_len = (value == NULL) ? 0 : strlen( value ); return ldap_compare_ext_s( ld, dn, attr, &bvalue, NULL, NULL ); } openldap-2.4.42+dfsg/libraries/libldap/test.c0000644000175000017500000004574312563404150017553 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #include "portable.h" #include #include #include #include #include #include #include #include #ifdef HAVE_SYS_FILE_H #include #endif #ifdef HAVE_IO_H #include #endif #include /* including the "internal" defs is legit and nec. since this test routine has * a-priori knowledge of libldap internal workings. * hodges@stanford.edu 5-Feb-96 */ #include "ldap-int.h" /* local functions */ static char *get_line LDAP_P(( char *line, int len, FILE *fp, const char *prompt )); static char **get_list LDAP_P(( const char *prompt )); static int file_read LDAP_P(( const char *path, struct berval *bv )); static LDAPMod **get_modlist LDAP_P(( const char *prompt1, const char *prompt2, const char *prompt3 )); static void handle_result LDAP_P(( LDAP *ld, LDAPMessage *lm )); static void print_ldap_result LDAP_P(( LDAP *ld, LDAPMessage *lm, const char *s )); static void print_search_entry LDAP_P(( LDAP *ld, LDAPMessage *res )); static void free_list LDAP_P(( char **list )); static char *dnsuffix; static char * get_line( char *line, int len, FILE *fp, const char *prompt ) { fputs(prompt, stdout); if ( fgets( line, len, fp ) == NULL ) return( NULL ); line[ strlen( line ) - 1 ] = '\0'; return( line ); } static char ** get_list( const char *prompt ) { static char buf[256]; int num; char **result; num = 0; result = (char **) 0; while ( 1 ) { get_line( buf, sizeof(buf), stdin, prompt ); if ( *buf == '\0' ) break; if ( result == (char **) 0 ) result = (char **) malloc( sizeof(char *) ); else result = (char **) realloc( result, sizeof(char *) * (num + 1) ); result[num++] = (char *) strdup( buf ); } if ( result == (char **) 0 ) return( NULL ); result = (char **) realloc( result, sizeof(char *) * (num + 1) ); result[num] = NULL; return( result ); } static void free_list( char **list ) { int i; if ( list != NULL ) { for ( i = 0; list[ i ] != NULL; ++i ) { free( list[ i ] ); } free( (char *)list ); } } static int file_read( const char *path, struct berval *bv ) { FILE *fp; ber_slen_t rlen; int eof; if (( fp = fopen( path, "r" )) == NULL ) { perror( path ); return( -1 ); } if ( fseek( fp, 0L, SEEK_END ) != 0 ) { perror( path ); fclose( fp ); return( -1 ); } bv->bv_len = ftell( fp ); if (( bv->bv_val = (char *)malloc( bv->bv_len )) == NULL ) { perror( "malloc" ); fclose( fp ); return( -1 ); } if ( fseek( fp, 0L, SEEK_SET ) != 0 ) { perror( path ); fclose( fp ); return( -1 ); } rlen = fread( bv->bv_val, 1, bv->bv_len, fp ); eof = feof( fp ); fclose( fp ); if ( (ber_len_t) rlen != bv->bv_len ) { perror( path ); free( bv->bv_val ); return( -1 ); } return( bv->bv_len ); } static LDAPMod ** get_modlist( const char *prompt1, const char *prompt2, const char *prompt3 ) { static char buf[256]; int num; LDAPMod tmp = { 0 }; LDAPMod **result; struct berval **bvals; num = 0; result = NULL; while ( 1 ) { if ( prompt1 ) { get_line( buf, sizeof(buf), stdin, prompt1 ); tmp.mod_op = atoi( buf ); if ( tmp.mod_op == -1 || buf[0] == '\0' ) break; } get_line( buf, sizeof(buf), stdin, prompt2 ); if ( buf[0] == '\0' ) break; tmp.mod_type = strdup( buf ); tmp.mod_values = get_list( prompt3 ); if ( tmp.mod_values != NULL ) { int i; for ( i = 0; tmp.mod_values[i] != NULL; ++i ) ; bvals = (struct berval **)calloc( i + 1, sizeof( struct berval *)); for ( i = 0; tmp.mod_values[i] != NULL; ++i ) { bvals[i] = (struct berval *)malloc( sizeof( struct berval )); if ( strncmp( tmp.mod_values[i], "{FILE}", 6 ) == 0 ) { if ( file_read( tmp.mod_values[i] + 6, bvals[i] ) < 0 ) { free( bvals ); for ( i = 0; ibv_val = tmp.mod_values[i]; bvals[i]->bv_len = strlen( tmp.mod_values[i] ); } } tmp.mod_bvalues = bvals; tmp.mod_op |= LDAP_MOD_BVALUES; } if ( result == NULL ) result = (LDAPMod **) malloc( sizeof(LDAPMod *) ); else result = (LDAPMod **) realloc( result, sizeof(LDAPMod *) * (num + 1) ); result[num] = (LDAPMod *) malloc( sizeof(LDAPMod) ); *(result[num]) = tmp; /* struct copy */ num++; } if ( result == NULL ) return( NULL ); result = (LDAPMod **) realloc( result, sizeof(LDAPMod *) * (num + 1) ); result[num] = NULL; return( result ); } static int bind_prompt( LDAP *ld, LDAP_CONST char *url, ber_tag_t request, ber_int_t msgid, void *params ) { static char dn[256], passwd[256]; int authmethod; printf("rebind for request=%ld msgid=%ld url=%s\n", request, (long) msgid, url ); authmethod = LDAP_AUTH_SIMPLE; get_line( dn, sizeof(dn), stdin, "re-bind dn? " ); strcat( dn, dnsuffix ); if ( authmethod == LDAP_AUTH_SIMPLE && dn[0] != '\0' ) { get_line( passwd, sizeof(passwd), stdin, "re-bind password? " ); } else { passwd[0] = '\0'; } return ldap_bind_s( ld, dn, passwd, authmethod); } int main( int argc, char **argv ) { LDAP *ld = NULL; int i, c, port, errflg, method, id, msgtype; char line[256], command1, command2, command3; char passwd[64], dn[256], rdn[64], attr[64], value[256]; char filter[256], *host, **types; char **exdn; static const char usage[] = "usage: %s [-u] [-h host] [-d level] [-s dnsuffix] [-p port] [-t file] [-T file]\n"; int bound, all, scope, attrsonly; LDAPMessage *res; LDAPMod **mods, **attrs; struct timeval timeout; char *copyfname = NULL; int copyoptions = 0; LDAPURLDesc *ludp; host = NULL; port = LDAP_PORT; dnsuffix = ""; errflg = 0; while (( c = getopt( argc, argv, "h:d:s:p:t:T:" )) != -1 ) { switch( c ) { case 'd': #ifdef LDAP_DEBUG ldap_debug = atoi( optarg ); #ifdef LBER_DEBUG if ( ldap_debug & LDAP_DEBUG_PACKETS ) { ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &ldap_debug ); } #endif #else printf( "Compile with -DLDAP_DEBUG for debugging\n" ); #endif break; case 'h': host = optarg; break; case 's': dnsuffix = optarg; break; case 'p': port = atoi( optarg ); break; case 't': /* copy ber's to given file */ copyfname = strdup( optarg ); /* copyoptions = LBER_TO_FILE; */ break; case 'T': /* only output ber's to given file */ copyfname = strdup( optarg ); /* copyoptions = (LBER_TO_FILE | LBER_TO_FILE_ONLY); */ break; default: ++errflg; } } if ( host == NULL && optind == argc - 1 ) { host = argv[ optind ]; ++optind; } if ( errflg || optind < argc - 1 ) { fprintf( stderr, usage, argv[ 0 ] ); exit( EXIT_FAILURE ); } printf( "ldap_init( %s, %d )\n", host == NULL ? "(null)" : host, port ); ld = ldap_init( host, port ); if ( ld == NULL ) { perror( "ldap_init" ); exit( EXIT_FAILURE ); } if ( copyfname != NULL ) { if ( ( ld->ld_sb->sb_fd = open( copyfname, O_WRONLY|O_CREAT|O_EXCL, 0600 )) == -1 ) { perror( copyfname ); exit ( EXIT_FAILURE ); } ld->ld_sb->sb_options = copyoptions; } bound = 0; timeout.tv_sec = 0; timeout.tv_usec = 0; (void) memset( line, '\0', sizeof(line) ); while ( get_line( line, sizeof(line), stdin, "\ncommand? " ) != NULL ) { command1 = line[0]; command2 = line[1]; command3 = line[2]; switch ( command1 ) { case 'a': /* add or abandon */ switch ( command2 ) { case 'd': /* add */ get_line( dn, sizeof(dn), stdin, "dn? " ); strcat( dn, dnsuffix ); if ( (attrs = get_modlist( NULL, "attr? ", "value? " )) == NULL ) break; if ( (id = ldap_add( ld, dn, attrs )) == -1 ) ldap_perror( ld, "ldap_add" ); else printf( "Add initiated with id %d\n", id ); break; case 'b': /* abandon */ get_line( line, sizeof(line), stdin, "msgid? " ); id = atoi( line ); if ( ldap_abandon( ld, id ) != 0 ) ldap_perror( ld, "ldap_abandon" ); else printf( "Abandon successful\n" ); break; default: printf( "Possibilities: [ad]d, [ab]ort\n" ); } break; case 'b': /* asynch bind */ method = LDAP_AUTH_SIMPLE; get_line( dn, sizeof(dn), stdin, "dn? " ); strcat( dn, dnsuffix ); if ( method == LDAP_AUTH_SIMPLE && dn[0] != '\0' ) get_line( passwd, sizeof(passwd), stdin, "password? " ); else passwd[0] = '\0'; if ( ldap_bind( ld, dn, passwd, method ) == -1 ) { fprintf( stderr, "ldap_bind failed\n" ); ldap_perror( ld, "ldap_bind" ); } else { printf( "Bind initiated\n" ); bound = 1; } break; case 'B': /* synch bind */ method = LDAP_AUTH_SIMPLE; get_line( dn, sizeof(dn), stdin, "dn? " ); strcat( dn, dnsuffix ); if ( dn[0] != '\0' ) get_line( passwd, sizeof(passwd), stdin, "password? " ); else passwd[0] = '\0'; if ( ldap_bind_s( ld, dn, passwd, method ) != LDAP_SUCCESS ) { fprintf( stderr, "ldap_bind_s failed\n" ); ldap_perror( ld, "ldap_bind_s" ); } else { printf( "Bind successful\n" ); bound = 1; } break; case 'c': /* compare */ get_line( dn, sizeof(dn), stdin, "dn? " ); strcat( dn, dnsuffix ); get_line( attr, sizeof(attr), stdin, "attr? " ); get_line( value, sizeof(value), stdin, "value? " ); if ( (id = ldap_compare( ld, dn, attr, value )) == -1 ) ldap_perror( ld, "ldap_compare" ); else printf( "Compare initiated with id %d\n", id ); break; case 'd': /* turn on debugging */ #ifdef LDAP_DEBUG get_line( line, sizeof(line), stdin, "debug level? " ); ldap_debug = atoi( line ); #ifdef LBER_DEBUG if ( ldap_debug & LDAP_DEBUG_PACKETS ) { ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &ldap_debug ); } #endif #else printf( "Compile with -DLDAP_DEBUG for debugging\n" ); #endif break; case 'E': /* explode a dn */ get_line( line, sizeof(line), stdin, "dn? " ); exdn = ldap_explode_dn( line, 0 ); for ( i = 0; exdn != NULL && exdn[i] != NULL; i++ ) { printf( "\t%s\n", exdn[i] ); } break; case 'g': /* set next msgid */ get_line( line, sizeof(line), stdin, "msgid? " ); ld->ld_msgid = atoi( line ); break; case 'v': /* set version number */ get_line( line, sizeof(line), stdin, "version? " ); ld->ld_version = atoi( line ); break; case 'm': /* modify or modifyrdn */ if ( strncmp( line, "modify", 4 ) == 0 ) { get_line( dn, sizeof(dn), stdin, "dn? " ); strcat( dn, dnsuffix ); if ( (mods = get_modlist( "mod (0=>add, 1=>delete, 2=>replace -1=>done)? ", "attribute type? ", "attribute value? " )) == NULL ) break; if ( (id = ldap_modify( ld, dn, mods )) == -1 ) ldap_perror( ld, "ldap_modify" ); else printf( "Modify initiated with id %d\n", id ); } else if ( strncmp( line, "modrdn", 4 ) == 0 ) { get_line( dn, sizeof(dn), stdin, "dn? " ); strcat( dn, dnsuffix ); get_line( rdn, sizeof(rdn), stdin, "newrdn? " ); if ( (id = ldap_modrdn( ld, dn, rdn )) == -1 ) ldap_perror( ld, "ldap_modrdn" ); else printf( "Modrdn initiated with id %d\n", id ); } else { printf( "Possibilities: [modi]fy, [modr]dn\n" ); } break; case 'q': /* quit */ ldap_unbind( ld ); exit( EXIT_SUCCESS ); break; case 'r': /* result or remove */ switch ( command3 ) { case 's': /* result */ get_line( line, sizeof(line), stdin, "msgid (-1=>any)? " ); if ( line[0] == '\0' ) id = -1; else id = atoi( line ); get_line( line, sizeof(line), stdin, "all (0=>any, 1=>all)? " ); if ( line[0] == '\0' ) all = 1; else all = atoi( line ); if (( msgtype = ldap_result( ld, id, all, &timeout, &res )) < 1 ) { ldap_perror( ld, "ldap_result" ); break; } printf( "\nresult: msgtype %d msgid %d\n", msgtype, res->lm_msgid ); handle_result( ld, res ); res = NULL; break; case 'm': /* remove */ get_line( dn, sizeof(dn), stdin, "dn? " ); strcat( dn, dnsuffix ); if ( (id = ldap_delete( ld, dn )) == -1 ) ldap_perror( ld, "ldap_delete" ); else printf( "Remove initiated with id %d\n", id ); break; default: printf( "Possibilities: [rem]ove, [res]ult\n" ); break; } break; case 's': /* search */ get_line( dn, sizeof(dn), stdin, "searchbase? " ); strcat( dn, dnsuffix ); get_line( line, sizeof(line), stdin, "scope (0=baseObject, 1=oneLevel, 2=subtree, 3=children)? " ); scope = atoi( line ); get_line( filter, sizeof(filter), stdin, "search filter (e.g. sn=jones)? " ); types = get_list( "attrs to return? " ); get_line( line, sizeof(line), stdin, "attrsonly (0=attrs&values, 1=attrs only)? " ); attrsonly = atoi( line ); if (( id = ldap_search( ld, dn, scope, filter, types, attrsonly )) == -1 ) { ldap_perror( ld, "ldap_search" ); } else { printf( "Search initiated with id %d\n", id ); } free_list( types ); break; case 't': /* set timeout value */ get_line( line, sizeof(line), stdin, "timeout? " ); timeout.tv_sec = atoi( line ); break; case 'p': /* parse LDAP URL */ get_line( line, sizeof(line), stdin, "LDAP URL? " ); if (( i = ldap_url_parse( line, &ludp )) != 0 ) { fprintf( stderr, "ldap_url_parse: error %d\n", i ); } else { printf( "\t host: " ); if ( ludp->lud_host == NULL ) { printf( "DEFAULT\n" ); } else { printf( "<%s>\n", ludp->lud_host ); } printf( "\t port: " ); if ( ludp->lud_port == 0 ) { printf( "DEFAULT\n" ); } else { printf( "%d\n", ludp->lud_port ); } printf( "\t dn: <%s>\n", ludp->lud_dn ); printf( "\t attrs:" ); if ( ludp->lud_attrs == NULL ) { printf( " ALL" ); } else { for ( i = 0; ludp->lud_attrs[ i ] != NULL; ++i ) { printf( " <%s>", ludp->lud_attrs[ i ] ); } } printf( "\n\t scope: %s\n", ludp->lud_scope == LDAP_SCOPE_BASE ? "baseObject" : ludp->lud_scope == LDAP_SCOPE_ONELEVEL ? "oneLevel" : ludp->lud_scope == LDAP_SCOPE_SUBTREE ? "subtree" #ifdef LDAP_SCOPE_SUBORDINATE : ludp->lud_scope == LDAP_SCOPE_SUBORDINATE ? "children" #endif : "**invalid**" ); printf( "\tfilter: <%s>\n", ludp->lud_filter ); ldap_free_urldesc( ludp ); } break; case 'n': /* set dn suffix, for convenience */ get_line( line, sizeof(line), stdin, "DN suffix? " ); strcpy( dnsuffix, line ); break; case 'o': /* set ldap options */ get_line( line, sizeof(line), stdin, "alias deref (0=never, 1=searching, 2=finding, 3=always)?" ); ld->ld_deref = atoi( line ); get_line( line, sizeof(line), stdin, "timelimit?" ); ld->ld_timelimit = atoi( line ); get_line( line, sizeof(line), stdin, "sizelimit?" ); ld->ld_sizelimit = atoi( line ); LDAP_BOOL_ZERO(&ld->ld_options); get_line( line, sizeof(line), stdin, "Recognize and chase referrals (0=no, 1=yes)?" ); if ( atoi( line ) != 0 ) { LDAP_BOOL_SET(&ld->ld_options, LDAP_BOOL_REFERRALS); get_line( line, sizeof(line), stdin, "Prompt for bind credentials when chasing referrals (0=no, 1=yes)?" ); if ( atoi( line ) != 0 ) { ldap_set_rebind_proc( ld, bind_prompt, NULL ); } } break; case '?': /* help */ printf( "Commands: [ad]d [ab]andon [b]ind\n" " [B]ind async [c]ompare\n" " [modi]fy [modr]dn [rem]ove\n" " [res]ult [s]earch [q]uit/unbind\n\n" " [d]ebug set ms[g]id\n" " d[n]suffix [t]imeout [v]ersion\n" " [?]help [o]ptions" " [E]xplode dn [p]arse LDAP URL\n" ); break; default: printf( "Invalid command. Type ? for help.\n" ); break; } (void) memset( line, '\0', sizeof(line) ); } return( 0 ); } static void handle_result( LDAP *ld, LDAPMessage *lm ) { switch ( lm->lm_msgtype ) { case LDAP_RES_COMPARE: printf( "Compare result\n" ); print_ldap_result( ld, lm, "compare" ); break; case LDAP_RES_SEARCH_RESULT: printf( "Search result\n" ); print_ldap_result( ld, lm, "search" ); break; case LDAP_RES_SEARCH_ENTRY: printf( "Search entry\n" ); print_search_entry( ld, lm ); break; case LDAP_RES_ADD: printf( "Add result\n" ); print_ldap_result( ld, lm, "add" ); break; case LDAP_RES_DELETE: printf( "Delete result\n" ); print_ldap_result( ld, lm, "delete" ); break; case LDAP_RES_MODRDN: printf( "ModRDN result\n" ); print_ldap_result( ld, lm, "modrdn" ); break; case LDAP_RES_BIND: printf( "Bind result\n" ); print_ldap_result( ld, lm, "bind" ); break; default: printf( "Unknown result type 0x%lx\n", (unsigned long) lm->lm_msgtype ); print_ldap_result( ld, lm, "unknown" ); } } static void print_ldap_result( LDAP *ld, LDAPMessage *lm, const char *s ) { ldap_result2error( ld, lm, 1 ); ldap_perror( ld, s ); /* if ( ld->ld_error != NULL && *ld->ld_error != '\0' ) fprintf( stderr, "Additional info: %s\n", ld->ld_error ); if ( LDAP_NAME_ERROR( ld->ld_errno ) && ld->ld_matched != NULL ) fprintf( stderr, "Matched DN: %s\n", ld->ld_matched ); */ } static void print_search_entry( LDAP *ld, LDAPMessage *res ) { LDAPMessage *e; for ( e = ldap_first_entry( ld, res ); e != NULL; e = ldap_next_entry( ld, e ) ) { BerElement *ber = NULL; char *a, *dn, *ufn; if ( e->lm_msgtype == LDAP_RES_SEARCH_RESULT ) break; dn = ldap_get_dn( ld, e ); printf( "\tDN: %s\n", dn ); ufn = ldap_dn2ufn( dn ); printf( "\tUFN: %s\n", ufn ); free( dn ); free( ufn ); for ( a = ldap_first_attribute( ld, e, &ber ); a != NULL; a = ldap_next_attribute( ld, e, ber ) ) { struct berval **vals; printf( "\t\tATTR: %s\n", a ); if ( (vals = ldap_get_values_len( ld, e, a )) == NULL ) { printf( "\t\t\t(no values)\n" ); } else { int i; for ( i = 0; vals[i] != NULL; i++ ) { int j, nonascii; nonascii = 0; for ( j = 0; (ber_len_t) j < vals[i]->bv_len; j++ ) if ( !isascii( vals[i]->bv_val[j] ) ) { nonascii = 1; break; } if ( nonascii ) { printf( "\t\t\tlength (%ld) (not ascii)\n", vals[i]->bv_len ); #ifdef BPRINT_NONASCII ber_bprint( vals[i]->bv_val, vals[i]->bv_len ); #endif /* BPRINT_NONASCII */ continue; } printf( "\t\t\tlength (%ld) %s\n", vals[i]->bv_len, vals[i]->bv_val ); } ber_bvecfree( vals ); } } if(ber != NULL) { ber_free( ber, 0 ); } } if ( res->lm_msgtype == LDAP_RES_SEARCH_RESULT || res->lm_chain != NULL ) print_ldap_result( ld, res, "search" ); } openldap-2.4.42+dfsg/libraries/libldap/open.c0000644000175000017500000003357512563404150017535 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (c) 1995 Regents of the University of Michigan. * All rights reserved. */ #include "portable.h" #include #ifdef HAVE_LIMITS_H #include #endif #include #include #include #include #include #include #include "ldap-int.h" #include "ldap_log.h" /* Caller must hold the conn_mutex since simultaneous accesses are possible */ int ldap_open_defconn( LDAP *ld ) { ld->ld_defconn = ldap_new_connection( ld, &ld->ld_options.ldo_defludp, 1, 1, NULL, 0, 0 ); if( ld->ld_defconn == NULL ) { ld->ld_errno = LDAP_SERVER_DOWN; return -1; } ++ld->ld_defconn->lconn_refcnt; /* so it never gets closed/freed */ return 0; } /* * ldap_open - initialize and connect to an ldap server. A magic cookie to * be used for future communication is returned on success, NULL on failure. * "host" may be a space-separated list of hosts or IP addresses * * Example: * LDAP *ld; * ld = ldap_open( hostname, port ); */ LDAP * ldap_open( LDAP_CONST char *host, int port ) { int rc; LDAP *ld; Debug( LDAP_DEBUG_TRACE, "ldap_open(%s, %d)\n", host, port, 0 ); ld = ldap_init( host, port ); if ( ld == NULL ) { return( NULL ); } LDAP_MUTEX_LOCK( &ld->ld_conn_mutex ); rc = ldap_open_defconn( ld ); LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); if( rc < 0 ) { ldap_ld_free( ld, 0, NULL, NULL ); ld = NULL; } Debug( LDAP_DEBUG_TRACE, "ldap_open: %s\n", ld != NULL ? "succeeded" : "failed", 0, 0 ); return ld; } int ldap_create( LDAP **ldp ) { LDAP *ld; struct ldapoptions *gopts; *ldp = NULL; /* Get pointer to global option structure */ if ( (gopts = LDAP_INT_GLOBAL_OPT()) == NULL) { return LDAP_NO_MEMORY; } /* Initialize the global options, if not already done. */ if( gopts->ldo_valid != LDAP_INITIALIZED ) { ldap_int_initialize(gopts, NULL); if ( gopts->ldo_valid != LDAP_INITIALIZED ) return LDAP_LOCAL_ERROR; } Debug( LDAP_DEBUG_TRACE, "ldap_create\n", 0, 0, 0 ); if ( (ld = (LDAP *) LDAP_CALLOC( 1, sizeof(LDAP) )) == NULL ) { return( LDAP_NO_MEMORY ); } if ( (ld->ldc = (struct ldap_common *) LDAP_CALLOC( 1, sizeof(struct ldap_common) )) == NULL ) { LDAP_FREE( (char *)ld ); return( LDAP_NO_MEMORY ); } /* copy the global options */ LDAP_MUTEX_LOCK( &gopts->ldo_mutex ); AC_MEMCPY(&ld->ld_options, gopts, sizeof(ld->ld_options)); #ifdef LDAP_R_COMPILE /* Properly initialize the structs mutex */ ldap_pvt_thread_mutex_init( &(ld->ld_ldopts_mutex) ); #endif LDAP_MUTEX_UNLOCK( &gopts->ldo_mutex ); ld->ld_valid = LDAP_VALID_SESSION; /* but not pointers to malloc'ed items */ ld->ld_options.ldo_sctrls = NULL; ld->ld_options.ldo_cctrls = NULL; ld->ld_options.ldo_defludp = NULL; ld->ld_options.ldo_conn_cbs = NULL; #ifdef HAVE_CYRUS_SASL ld->ld_options.ldo_def_sasl_mech = gopts->ldo_def_sasl_mech ? LDAP_STRDUP( gopts->ldo_def_sasl_mech ) : NULL; ld->ld_options.ldo_def_sasl_realm = gopts->ldo_def_sasl_realm ? LDAP_STRDUP( gopts->ldo_def_sasl_realm ) : NULL; ld->ld_options.ldo_def_sasl_authcid = gopts->ldo_def_sasl_authcid ? LDAP_STRDUP( gopts->ldo_def_sasl_authcid ) : NULL; ld->ld_options.ldo_def_sasl_authzid = gopts->ldo_def_sasl_authzid ? LDAP_STRDUP( gopts->ldo_def_sasl_authzid ) : NULL; #endif #ifdef HAVE_TLS /* We explicitly inherit the SSL_CTX, don't need the names/paths. Leave * them empty to allow new SSL_CTX's to be created from scratch. */ memset( &ld->ld_options.ldo_tls_info, 0, sizeof( ld->ld_options.ldo_tls_info )); ld->ld_options.ldo_tls_ctx = NULL; #endif if ( gopts->ldo_defludp ) { ld->ld_options.ldo_defludp = ldap_url_duplist(gopts->ldo_defludp); if ( ld->ld_options.ldo_defludp == NULL ) goto nomem; } if (( ld->ld_selectinfo = ldap_new_select_info()) == NULL ) goto nomem; ld->ld_lberoptions = LBER_USE_DER; ld->ld_sb = ber_sockbuf_alloc( ); if ( ld->ld_sb == NULL ) goto nomem; #ifdef LDAP_R_COMPILE ldap_pvt_thread_mutex_init( &ld->ld_msgid_mutex ); ldap_pvt_thread_mutex_init( &ld->ld_conn_mutex ); ldap_pvt_thread_mutex_init( &ld->ld_req_mutex ); ldap_pvt_thread_mutex_init( &ld->ld_res_mutex ); ldap_pvt_thread_mutex_init( &ld->ld_abandon_mutex ); ldap_pvt_thread_mutex_init( &ld->ld_ldcmutex ); #endif ld->ld_ldcrefcnt = 1; *ldp = ld; return LDAP_SUCCESS; nomem: ldap_free_select_info( ld->ld_selectinfo ); ldap_free_urllist( ld->ld_options.ldo_defludp ); #ifdef HAVE_CYRUS_SASL LDAP_FREE( ld->ld_options.ldo_def_sasl_authzid ); LDAP_FREE( ld->ld_options.ldo_def_sasl_authcid ); LDAP_FREE( ld->ld_options.ldo_def_sasl_realm ); LDAP_FREE( ld->ld_options.ldo_def_sasl_mech ); #endif LDAP_FREE( (char *)ld ); return LDAP_NO_MEMORY; } /* * ldap_init - initialize the LDAP library. A magic cookie to be used for * future communication is returned on success, NULL on failure. * "host" may be a space-separated list of hosts or IP addresses * * Example: * LDAP *ld; * ld = ldap_init( host, port ); */ LDAP * ldap_init( LDAP_CONST char *defhost, int defport ) { LDAP *ld; int rc; rc = ldap_create(&ld); if ( rc != LDAP_SUCCESS ) return NULL; if (defport != 0) ld->ld_options.ldo_defport = defport; if (defhost != NULL) { rc = ldap_set_option(ld, LDAP_OPT_HOST_NAME, defhost); if ( rc != LDAP_SUCCESS ) { ldap_ld_free(ld, 1, NULL, NULL); return NULL; } } return( ld ); } int ldap_initialize( LDAP **ldp, LDAP_CONST char *url ) { int rc; LDAP *ld; *ldp = NULL; rc = ldap_create(&ld); if ( rc != LDAP_SUCCESS ) return rc; if (url != NULL) { rc = ldap_set_option(ld, LDAP_OPT_URI, url); if ( rc != LDAP_SUCCESS ) { ldap_ld_free(ld, 1, NULL, NULL); return rc; } #ifdef LDAP_CONNECTIONLESS if (ldap_is_ldapc_url(url)) LDAP_IS_UDP(ld) = 1; #endif } *ldp = ld; return LDAP_SUCCESS; } int ldap_init_fd( ber_socket_t fd, int proto, LDAP_CONST char *url, LDAP **ldp ) { int rc; LDAP *ld; LDAPConn *conn; #ifdef LDAP_CONNECTIONLESS ber_socklen_t len; #endif *ldp = NULL; rc = ldap_create( &ld ); if( rc != LDAP_SUCCESS ) return( rc ); if (url != NULL) { rc = ldap_set_option(ld, LDAP_OPT_URI, url); if ( rc != LDAP_SUCCESS ) { ldap_ld_free(ld, 1, NULL, NULL); return rc; } } LDAP_MUTEX_LOCK( &ld->ld_conn_mutex ); /* Attach the passed socket as the LDAP's connection */ conn = ldap_new_connection( ld, NULL, 1, 0, NULL, 0, 0 ); if( conn == NULL ) { ldap_unbind_ext( ld, NULL, NULL ); return( LDAP_NO_MEMORY ); } if( url ) conn->lconn_server = ldap_url_dup( ld->ld_options.ldo_defludp ); ber_sockbuf_ctrl( conn->lconn_sb, LBER_SB_OPT_SET_FD, &fd ); ld->ld_defconn = conn; ++ld->ld_defconn->lconn_refcnt; /* so it never gets closed/freed */ LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); switch( proto ) { case LDAP_PROTO_TCP: #ifdef LDAP_DEBUG ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug, LBER_SBIOD_LEVEL_PROVIDER, (void *)"tcp_" ); #endif ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_tcp, LBER_SBIOD_LEVEL_PROVIDER, NULL ); break; #ifdef LDAP_CONNECTIONLESS case LDAP_PROTO_UDP: LDAP_IS_UDP(ld) = 1; if( ld->ld_options.ldo_peer ) ldap_memfree( ld->ld_options.ldo_peer ); ld->ld_options.ldo_peer = ldap_memcalloc( 1, sizeof( struct sockaddr_storage ) ); len = sizeof( struct sockaddr_storage ); if( getpeername ( fd, ld->ld_options.ldo_peer, &len ) < 0) { ldap_unbind_ext( ld, NULL, NULL ); return( AC_SOCKET_ERROR ); } #ifdef LDAP_DEBUG ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug, LBER_SBIOD_LEVEL_PROVIDER, (void *)"udp_" ); #endif ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_udp, LBER_SBIOD_LEVEL_PROVIDER, NULL ); ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_readahead, LBER_SBIOD_LEVEL_PROVIDER, NULL ); break; #endif /* LDAP_CONNECTIONLESS */ case LDAP_PROTO_IPC: #ifdef LDAP_DEBUG ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug, LBER_SBIOD_LEVEL_PROVIDER, (void *)"ipc_" ); #endif ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_fd, LBER_SBIOD_LEVEL_PROVIDER, NULL ); break; case LDAP_PROTO_EXT: /* caller must supply sockbuf handlers */ break; default: ldap_unbind_ext( ld, NULL, NULL ); return LDAP_PARAM_ERROR; } #ifdef LDAP_DEBUG ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug, INT_MAX, (void *)"ldap_" ); #endif /* Add the connection to the *LDAP's select pool */ ldap_mark_select_read( ld, conn->lconn_sb ); *ldp = ld; return LDAP_SUCCESS; } /* Protected by ld_conn_mutex */ int ldap_int_open_connection( LDAP *ld, LDAPConn *conn, LDAPURLDesc *srv, int async ) { int rc = -1; int proto; Debug( LDAP_DEBUG_TRACE, "ldap_int_open_connection\n", 0, 0, 0 ); switch ( proto = ldap_pvt_url_scheme2proto( srv->lud_scheme ) ) { case LDAP_PROTO_TCP: rc = ldap_connect_to_host( ld, conn->lconn_sb, proto, srv, async ); if ( rc == -1 ) return rc; #ifdef LDAP_DEBUG ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug, LBER_SBIOD_LEVEL_PROVIDER, (void *)"tcp_" ); #endif ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_tcp, LBER_SBIOD_LEVEL_PROVIDER, NULL ); break; #ifdef LDAP_CONNECTIONLESS case LDAP_PROTO_UDP: LDAP_IS_UDP(ld) = 1; rc = ldap_connect_to_host( ld, conn->lconn_sb, proto, srv, async ); if ( rc == -1 ) return rc; #ifdef LDAP_DEBUG ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug, LBER_SBIOD_LEVEL_PROVIDER, (void *)"udp_" ); #endif ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_udp, LBER_SBIOD_LEVEL_PROVIDER, NULL ); ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_readahead, LBER_SBIOD_LEVEL_PROVIDER, NULL ); break; #endif case LDAP_PROTO_IPC: #ifdef LDAP_PF_LOCAL /* only IPC mechanism supported is PF_LOCAL (PF_UNIX) */ rc = ldap_connect_to_path( ld, conn->lconn_sb, srv, async ); if ( rc == -1 ) return rc; #ifdef LDAP_DEBUG ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug, LBER_SBIOD_LEVEL_PROVIDER, (void *)"ipc_" ); #endif ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_fd, LBER_SBIOD_LEVEL_PROVIDER, NULL ); break; #endif /* LDAP_PF_LOCAL */ default: return -1; break; } conn->lconn_created = time( NULL ); #ifdef LDAP_DEBUG ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug, INT_MAX, (void *)"ldap_" ); #endif #ifdef LDAP_CONNECTIONLESS if( proto == LDAP_PROTO_UDP ) return 0; #endif #ifdef HAVE_TLS if (rc == 0 && ( ld->ld_options.ldo_tls_mode == LDAP_OPT_X_TLS_HARD || strcmp( srv->lud_scheme, "ldaps" ) == 0 )) { ++conn->lconn_refcnt; /* avoid premature free */ rc = ldap_int_tls_start( ld, conn, srv ); --conn->lconn_refcnt; if (rc != LDAP_SUCCESS) { return -1; } } #endif return( 0 ); } /* * ldap_open_internal_connection - open connection and set file descriptor * * note: ldap_init_fd() may be preferable */ int ldap_open_internal_connection( LDAP **ldp, ber_socket_t *fdp ) { int rc; LDAPConn *c; LDAPRequest *lr; LDAP *ld; rc = ldap_create( &ld ); if( rc != LDAP_SUCCESS ) { *ldp = NULL; return( rc ); } /* Make it appear that a search request, msgid 0, was sent */ lr = (LDAPRequest *)LDAP_CALLOC( 1, sizeof( LDAPRequest )); if( lr == NULL ) { ldap_unbind_ext( ld, NULL, NULL ); *ldp = NULL; return( LDAP_NO_MEMORY ); } memset(lr, 0, sizeof( LDAPRequest )); lr->lr_msgid = 0; lr->lr_status = LDAP_REQST_INPROGRESS; lr->lr_res_errno = LDAP_SUCCESS; /* no mutex lock needed, we just created this ld here */ ld->ld_requests = lr; LDAP_MUTEX_LOCK( &ld->ld_conn_mutex ); /* Attach the passed socket as the *LDAP's connection */ c = ldap_new_connection( ld, NULL, 1, 0, NULL, 0, 0 ); if( c == NULL ) { ldap_unbind_ext( ld, NULL, NULL ); *ldp = NULL; LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); return( LDAP_NO_MEMORY ); } ber_sockbuf_ctrl( c->lconn_sb, LBER_SB_OPT_SET_FD, fdp ); #ifdef LDAP_DEBUG ber_sockbuf_add_io( c->lconn_sb, &ber_sockbuf_io_debug, LBER_SBIOD_LEVEL_PROVIDER, (void *)"int_" ); #endif ber_sockbuf_add_io( c->lconn_sb, &ber_sockbuf_io_tcp, LBER_SBIOD_LEVEL_PROVIDER, NULL ); ld->ld_defconn = c; LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); /* Add the connection to the *LDAP's select pool */ ldap_mark_select_read( ld, c->lconn_sb ); /* Make this connection an LDAP V3 protocol connection */ rc = LDAP_VERSION3; ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &rc ); *ldp = ld; ++ld->ld_defconn->lconn_refcnt; /* so it never gets closed/freed */ return( LDAP_SUCCESS ); } LDAP * ldap_dup( LDAP *old ) { LDAP *ld; if ( old == NULL ) { return( NULL ); } Debug( LDAP_DEBUG_TRACE, "ldap_dup\n", 0, 0, 0 ); if ( (ld = (LDAP *) LDAP_CALLOC( 1, sizeof(LDAP) )) == NULL ) { return( NULL ); } LDAP_MUTEX_LOCK( &old->ld_ldcmutex ); ld->ldc = old->ldc; old->ld_ldcrefcnt++; LDAP_MUTEX_UNLOCK( &old->ld_ldcmutex ); return ( ld ); } int ldap_int_check_async_open( LDAP *ld, ber_socket_t sd ) { struct timeval tv = { 0 }; int rc; rc = ldap_int_poll( ld, sd, &tv, 1 ); switch ( rc ) { case 0: /* now ready to start tls */ ld->ld_defconn->lconn_status = LDAP_CONNST_CONNECTED; break; default: ld->ld_errno = LDAP_CONNECT_ERROR; return -1; case -2: /* connect not completed yet */ ld->ld_errno = LDAP_X_CONNECTING; return rc; } #ifdef HAVE_TLS if ( ld->ld_options.ldo_tls_mode == LDAP_OPT_X_TLS_HARD || !strcmp( ld->ld_defconn->lconn_server->lud_scheme, "ldaps" )) { ++ld->ld_defconn->lconn_refcnt; /* avoid premature free */ rc = ldap_int_tls_start( ld, ld->ld_defconn, ld->ld_defconn->lconn_server ); --ld->ld_defconn->lconn_refcnt; } #endif return rc; } openldap-2.4.42+dfsg/libraries/libldap/os-ip.c0000644000175000017500000005653412563404150017623 0ustar ryanryan/* os-ip.c -- platform-specific TCP & UDP related code */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * Portions Copyright 1999 Lars Uffmann. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (c) 1995 Regents of the University of Michigan. * All rights reserved. */ /* Significant additional contributors include: * Lars Uffman */ #include "portable.h" #include #include #include #include #include #include #include #ifdef HAVE_IO_H #include #endif /* HAVE_IO_H */ #ifdef HAVE_FCNTL_H #include #endif #include "ldap-int.h" #if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP ) # ifdef LDAP_PF_INET6 int ldap_int_inet4or6 = AF_UNSPEC; # else int ldap_int_inet4or6 = AF_INET; # endif #endif #ifdef LDAP_DEBUG #define osip_debug(ld,fmt,arg1,arg2,arg3) \ do { \ ldap_log_printf(NULL, LDAP_DEBUG_TRACE, fmt, arg1, arg2, arg3); \ } while(0) #else #define osip_debug(ld,fmt,arg1,arg2,arg3) ((void)0) #endif /* LDAP_DEBUG */ static void ldap_pvt_set_errno(int err) { sock_errset(err); } int ldap_int_timeval_dup( struct timeval **dest, const struct timeval *src ) { struct timeval *new; assert( dest != NULL ); if (src == NULL) { *dest = NULL; return 0; } new = (struct timeval *) LDAP_MALLOC(sizeof(struct timeval)); if( new == NULL ) { *dest = NULL; return 1; } AC_MEMCPY( (char *) new, (const char *) src, sizeof(struct timeval)); *dest = new; return 0; } static int ldap_pvt_ndelay_on(LDAP *ld, int fd) { osip_debug(ld, "ldap_ndelay_on: %d\n",fd,0,0); return ber_pvt_socket_set_nonblock( fd, 1 ); } static int ldap_pvt_ndelay_off(LDAP *ld, int fd) { osip_debug(ld, "ldap_ndelay_off: %d\n",fd,0,0); return ber_pvt_socket_set_nonblock( fd, 0 ); } static ber_socket_t ldap_int_socket(LDAP *ld, int family, int type ) { ber_socket_t s = socket(family, type, 0); osip_debug(ld, "ldap_new_socket: %d\n",s,0,0); #ifdef FD_CLOEXEC fcntl(s, F_SETFD, FD_CLOEXEC); #endif return ( s ); } static int ldap_pvt_close_socket(LDAP *ld, int s) { osip_debug(ld, "ldap_close_socket: %d\n",s,0,0); return tcp_close(s); } static int ldap_int_prepare_socket(LDAP *ld, int s, int proto ) { osip_debug( ld, "ldap_prepare_socket: %d\n", s, 0, 0 ); #if defined( SO_KEEPALIVE ) || defined( TCP_NODELAY ) if ( proto == LDAP_PROTO_TCP ) { int dummy = 1; #ifdef SO_KEEPALIVE if ( setsockopt( s, SOL_SOCKET, SO_KEEPALIVE, (char*) &dummy, sizeof(dummy) ) == AC_SOCKET_ERROR ) { osip_debug( ld, "ldap_prepare_socket: " "setsockopt(%d, SO_KEEPALIVE) failed (ignored).\n", s, 0, 0 ); } if ( ld->ld_options.ldo_keepalive_idle > 0 ) { #ifdef TCP_KEEPIDLE if ( setsockopt( s, IPPROTO_TCP, TCP_KEEPIDLE, (void*) &ld->ld_options.ldo_keepalive_idle, sizeof(ld->ld_options.ldo_keepalive_idle) ) == AC_SOCKET_ERROR ) { osip_debug( ld, "ldap_prepare_socket: " "setsockopt(%d, TCP_KEEPIDLE) failed (ignored).\n", s, 0, 0 ); } #else osip_debug( ld, "ldap_prepare_socket: " "sockopt TCP_KEEPIDLE not supported on this system.\n", 0, 0, 0 ); #endif /* TCP_KEEPIDLE */ } if ( ld->ld_options.ldo_keepalive_probes > 0 ) { #ifdef TCP_KEEPCNT if ( setsockopt( s, IPPROTO_TCP, TCP_KEEPCNT, (void*) &ld->ld_options.ldo_keepalive_probes, sizeof(ld->ld_options.ldo_keepalive_probes) ) == AC_SOCKET_ERROR ) { osip_debug( ld, "ldap_prepare_socket: " "setsockopt(%d, TCP_KEEPCNT) failed (ignored).\n", s, 0, 0 ); } #else osip_debug( ld, "ldap_prepare_socket: " "sockopt TCP_KEEPCNT not supported on this system.\n", 0, 0, 0 ); #endif /* TCP_KEEPCNT */ } if ( ld->ld_options.ldo_keepalive_interval > 0 ) { #ifdef TCP_KEEPINTVL if ( setsockopt( s, IPPROTO_TCP, TCP_KEEPINTVL, (void*) &ld->ld_options.ldo_keepalive_interval, sizeof(ld->ld_options.ldo_keepalive_interval) ) == AC_SOCKET_ERROR ) { osip_debug( ld, "ldap_prepare_socket: " "setsockopt(%d, TCP_KEEPINTVL) failed (ignored).\n", s, 0, 0 ); } #else osip_debug( ld, "ldap_prepare_socket: " "sockopt TCP_KEEPINTVL not supported on this system.\n", 0, 0, 0 ); #endif /* TCP_KEEPINTVL */ } #endif /* SO_KEEPALIVE */ #ifdef TCP_NODELAY if ( setsockopt( s, IPPROTO_TCP, TCP_NODELAY, (char*) &dummy, sizeof(dummy) ) == AC_SOCKET_ERROR ) { osip_debug( ld, "ldap_prepare_socket: " "setsockopt(%d, TCP_NODELAY) failed (ignored).\n", s, 0, 0 ); } #endif /* TCP_NODELAY */ } #endif /* SO_KEEPALIVE || TCP_NODELAY */ return 0; } #ifndef HAVE_WINSOCK #undef TRACE #define TRACE do { \ osip_debug(ld, \ "ldap_is_socket_ready: error on socket %d: errno: %d (%s)\n", \ s, \ errno, \ sock_errstr(errno) ); \ } while( 0 ) /* * check the socket for errors after select returned. */ static int ldap_pvt_is_socket_ready(LDAP *ld, int s) { osip_debug(ld, "ldap_is_sock_ready: %d\n",s,0,0); #if defined( notyet ) /* && defined( SO_ERROR ) */ { int so_errno; ber_socklen_t dummy = sizeof(so_errno); if ( getsockopt( s, SOL_SOCKET, SO_ERROR, &so_errno, &dummy ) == AC_SOCKET_ERROR ) { return -1; } if ( so_errno ) { ldap_pvt_set_errno(so_errno); TRACE; return -1; } return 0; } #else { /* error slippery */ #ifdef LDAP_PF_INET6 struct sockaddr_storage sin; #else struct sockaddr_in sin; #endif char ch; ber_socklen_t dummy = sizeof(sin); if ( getpeername( s, (struct sockaddr *) &sin, &dummy ) == AC_SOCKET_ERROR ) { /* XXX: needs to be replace with ber_stream_read() */ (void)read(s, &ch, 1); TRACE; return -1; } return 0; } #endif return -1; } #undef TRACE #endif /* HAVE_WINSOCK */ /* NOTE: this is identical to analogous code in os-local.c */ int ldap_int_poll( LDAP *ld, ber_socket_t s, struct timeval *tvp, int wr ) { int rc; osip_debug(ld, "ldap_int_poll: fd: %d tm: %ld\n", s, tvp ? tvp->tv_sec : -1L, 0); #ifdef HAVE_POLL { struct pollfd fd; int timeout = INFTIM; short event = wr ? POLL_WRITE : POLL_READ; fd.fd = s; fd.events = event; if ( tvp != NULL ) { timeout = TV2MILLISEC( tvp ); } do { fd.revents = 0; rc = poll( &fd, 1, timeout ); } while ( rc == AC_SOCKET_ERROR && errno == EINTR && LDAP_BOOL_GET( &ld->ld_options, LDAP_BOOL_RESTART ) ); if ( rc == AC_SOCKET_ERROR ) { return rc; } if ( timeout == 0 && rc == 0 ) { return -2; } if ( fd.revents & event ) { if ( ldap_pvt_is_socket_ready( ld, s ) == -1 ) { return -1; } if ( ldap_pvt_ndelay_off( ld, s ) == -1 ) { return -1; } return 0; } } #else { fd_set wfds, *z = NULL; #ifdef HAVE_WINSOCK fd_set efds; #endif struct timeval tv = { 0 }; #if defined( FD_SETSIZE ) && !defined( HAVE_WINSOCK ) if ( s >= FD_SETSIZE ) { rc = AC_SOCKET_ERROR; tcp_close( s ); ldap_pvt_set_errno( EMFILE ); return rc; } #endif if ( tvp != NULL ) { tv = *tvp; } do { FD_ZERO(&wfds); FD_SET(s, &wfds ); #ifdef HAVE_WINSOCK FD_ZERO(&efds); FD_SET(s, &efds ); #endif rc = select( ldap_int_tblsize, z, &wfds, #ifdef HAVE_WINSOCK &efds, #else z, #endif tvp ? &tv : NULL ); } while ( rc == AC_SOCKET_ERROR && errno == EINTR && LDAP_BOOL_GET( &ld->ld_options, LDAP_BOOL_RESTART ) ); if ( rc == AC_SOCKET_ERROR ) { return rc; } if ( rc == 0 && tvp && tvp->tv_sec == 0 && tvp->tv_usec == 0 ) { return -2; } #ifdef HAVE_WINSOCK /* This means the connection failed */ if ( FD_ISSET(s, &efds) ) { int so_errno; ber_socklen_t dummy = sizeof(so_errno); if ( getsockopt( s, SOL_SOCKET, SO_ERROR, (char *) &so_errno, &dummy ) == AC_SOCKET_ERROR || !so_errno ) { /* impossible */ so_errno = WSAGetLastError(); } ldap_pvt_set_errno( so_errno ); osip_debug(ld, "ldap_int_poll: error on socket %d: " "errno: %d (%s)\n", s, errno, sock_errstr( errno )); return -1; } #endif if ( FD_ISSET(s, &wfds) ) { #ifndef HAVE_WINSOCK if ( ldap_pvt_is_socket_ready( ld, s ) == -1 ) { return -1; } #endif if ( ldap_pvt_ndelay_off(ld, s) == -1 ) { return -1; } return 0; } } #endif osip_debug(ld, "ldap_int_poll: timed out\n",0,0,0); ldap_pvt_set_errno( ETIMEDOUT ); return -1; } static int ldap_pvt_connect(LDAP *ld, ber_socket_t s, struct sockaddr *sin, ber_socklen_t addrlen, int async) { int rc, err; struct timeval tv, *opt_tv = NULL; #ifdef LDAP_CONNECTIONLESS /* We could do a connect() but that would interfere with * attempts to poll a broadcast address */ if (LDAP_IS_UDP(ld)) { if (ld->ld_options.ldo_peer) ldap_memfree(ld->ld_options.ldo_peer); ld->ld_options.ldo_peer=ldap_memcalloc(1, sizeof(struct sockaddr_storage)); AC_MEMCPY(ld->ld_options.ldo_peer,sin,addrlen); return ( 0 ); } #endif if ( ld->ld_options.ldo_tm_net.tv_sec >= 0 ) { tv = ld->ld_options.ldo_tm_net; opt_tv = &tv; } osip_debug(ld, "ldap_pvt_connect: fd: %d tm: %ld async: %d\n", s, opt_tv ? tv.tv_sec : -1L, async); if ( opt_tv && ldap_pvt_ndelay_on(ld, s) == -1 ) return ( -1 ); do{ osip_debug(ld, "attempting to connect: \n", 0, 0, 0); if ( connect(s, sin, addrlen) != AC_SOCKET_ERROR ) { osip_debug(ld, "connect success\n", 0, 0, 0); if ( opt_tv && ldap_pvt_ndelay_off(ld, s) == -1 ) return ( -1 ); return ( 0 ); } err = sock_errno(); osip_debug(ld, "connect errno: %d\n", err, 0, 0); } while(err == EINTR && LDAP_BOOL_GET( &ld->ld_options, LDAP_BOOL_RESTART )); if ( err != EINPROGRESS && err != EWOULDBLOCK ) { return ( -1 ); } if ( async ) { /* caller will call ldap_int_poll() as appropriate? */ return ( -2 ); } rc = ldap_int_poll( ld, s, opt_tv, 1 ); osip_debug(ld, "ldap_pvt_connect: %d\n", rc, 0, 0); return rc; } #ifndef HAVE_INET_ATON int ldap_pvt_inet_aton( const char *host, struct in_addr *in) { unsigned long u = inet_addr( host ); #ifdef INADDR_NONE if ( u == INADDR_NONE ) return 0; #endif if ( u == 0xffffffffUL || u == (unsigned long) -1L ) return 0; in->s_addr = u; return 1; } #endif int ldap_int_connect_cbs(LDAP *ld, Sockbuf *sb, ber_socket_t *s, LDAPURLDesc *srv, struct sockaddr *addr) { struct ldapoptions *lo; ldaplist *ll; ldap_conncb *cb; int rc; ber_sockbuf_ctrl( sb, LBER_SB_OPT_SET_FD, s ); /* Invoke all handle-specific callbacks first */ lo = &ld->ld_options; for (ll = lo->ldo_conn_cbs; ll; ll = ll->ll_next) { cb = ll->ll_data; rc = cb->lc_add( ld, sb, srv, addr, cb ); /* on any failure, call the teardown functions for anything * that previously succeeded */ if ( rc ) { ldaplist *l2; for (l2 = lo->ldo_conn_cbs; l2 != ll; l2 = l2->ll_next) { cb = l2->ll_data; cb->lc_del( ld, sb, cb ); } /* a failure might have implicitly closed the fd */ ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, s ); return rc; } } lo = LDAP_INT_GLOBAL_OPT(); for (ll = lo->ldo_conn_cbs; ll; ll = ll->ll_next) { cb = ll->ll_data; rc = cb->lc_add( ld, sb, srv, addr, cb ); if ( rc ) { ldaplist *l2; for (l2 = lo->ldo_conn_cbs; l2 != ll; l2 = l2->ll_next) { cb = l2->ll_data; cb->lc_del( ld, sb, cb ); } lo = &ld->ld_options; for (l2 = lo->ldo_conn_cbs; l2; l2 = l2->ll_next) { cb = l2->ll_data; cb->lc_del( ld, sb, cb ); } ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, s ); return rc; } } return 0; } int ldap_connect_to_host(LDAP *ld, Sockbuf *sb, int proto, LDAPURLDesc *srv, int async ) { int rc; int socktype, port; ber_socket_t s = AC_SOCKET_INVALID; char *host; #if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP ) char serv[7]; int err; struct addrinfo hints, *res, *sai; #else int i; int use_hp = 0; struct hostent *hp = NULL; struct hostent he_buf; struct in_addr in; char *ha_buf=NULL; #endif if ( srv->lud_host == NULL || *srv->lud_host == 0 ) { host = "localhost"; } else { host = srv->lud_host; } port = srv->lud_port; if( !port ) { if( strcmp(srv->lud_scheme, "ldaps") == 0 ) { port = LDAPS_PORT; } else { port = LDAP_PORT; } } switch(proto) { case LDAP_PROTO_TCP: socktype = SOCK_STREAM; osip_debug( ld, "ldap_connect_to_host: TCP %s:%d\n", host, port, 0); break; case LDAP_PROTO_UDP: socktype = SOCK_DGRAM; osip_debug( ld, "ldap_connect_to_host: UDP %s:%d\n", host, port, 0); break; default: osip_debug( ld, "ldap_connect_to_host: unknown proto: %d\n", proto, 0, 0 ); return -1; } #if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP ) memset( &hints, '\0', sizeof(hints) ); #ifdef USE_AI_ADDRCONFIG /* FIXME: configure test needed */ /* Use AI_ADDRCONFIG only on systems where its known to be needed. */ hints.ai_flags = AI_ADDRCONFIG; #endif hints.ai_family = ldap_int_inet4or6; hints.ai_socktype = socktype; snprintf(serv, sizeof serv, "%d", port ); /* most getaddrinfo(3) use non-threadsafe resolver libraries */ LDAP_MUTEX_LOCK(&ldap_int_resolv_mutex); err = getaddrinfo( host, serv, &hints, &res ); LDAP_MUTEX_UNLOCK(&ldap_int_resolv_mutex); if ( err != 0 ) { osip_debug(ld, "ldap_connect_to_host: getaddrinfo failed: %s\n", AC_GAI_STRERROR(err), 0, 0); return -1; } rc = -1; for( sai=res; sai != NULL; sai=sai->ai_next) { if( sai->ai_addr == NULL ) { osip_debug(ld, "ldap_connect_to_host: getaddrinfo " "ai_addr is NULL?\n", 0, 0, 0); continue; } /* we assume AF_x and PF_x are equal for all x */ s = ldap_int_socket( ld, sai->ai_family, socktype ); if ( s == AC_SOCKET_INVALID ) { continue; } if ( ldap_int_prepare_socket(ld, s, proto ) == -1 ) { ldap_pvt_close_socket(ld, s); break; } switch (sai->ai_family) { #ifdef LDAP_PF_INET6 case AF_INET6: { char addr[INET6_ADDRSTRLEN]; inet_ntop( AF_INET6, &((struct sockaddr_in6 *)sai->ai_addr)->sin6_addr, addr, sizeof addr); osip_debug(ld, "ldap_connect_to_host: Trying %s %s\n", addr, serv, 0); } break; #endif case AF_INET: { char addr[INET_ADDRSTRLEN]; inet_ntop( AF_INET, &((struct sockaddr_in *)sai->ai_addr)->sin_addr, addr, sizeof addr); osip_debug(ld, "ldap_connect_to_host: Trying %s:%s\n", addr, serv, 0); } break; } rc = ldap_pvt_connect( ld, s, sai->ai_addr, sai->ai_addrlen, async ); if ( rc == 0 || rc == -2 ) { err = ldap_int_connect_cbs( ld, sb, &s, srv, sai->ai_addr ); if ( err ) rc = err; else break; } ldap_pvt_close_socket(ld, s); } freeaddrinfo(res); #else if (! inet_aton( host, &in ) ) { int local_h_errno; rc = ldap_pvt_gethostbyname_a( host, &he_buf, &ha_buf, &hp, &local_h_errno ); if ( (rc < 0) || (hp == NULL) ) { #ifdef HAVE_WINSOCK ldap_pvt_set_errno( WSAGetLastError() ); #else /* not exactly right, but... */ ldap_pvt_set_errno( EHOSTUNREACH ); #endif if (ha_buf) LDAP_FREE(ha_buf); return -1; } use_hp = 1; } rc = s = -1; for ( i = 0; !use_hp || (hp->h_addr_list[i] != 0); ++i, rc = -1 ) { struct sockaddr_in sin; s = ldap_int_socket( ld, PF_INET, socktype ); if ( s == AC_SOCKET_INVALID ) { /* use_hp ? continue : break; */ break; } if ( ldap_int_prepare_socket( ld, s, proto ) == -1 ) { ldap_pvt_close_socket(ld, s); break; } (void)memset((char *)&sin, '\0', sizeof sin); sin.sin_family = AF_INET; sin.sin_port = htons((unsigned short) port); if( use_hp ) { AC_MEMCPY( &sin.sin_addr, hp->h_addr_list[i], sizeof(sin.sin_addr) ); } else { AC_MEMCPY( &sin.sin_addr, &in.s_addr, sizeof(sin.sin_addr) ); } #ifdef HAVE_INET_NTOA_B { /* for VxWorks */ char address[INET_ADDR_LEN]; inet_ntoa_b(sin.sin_address, address); osip_debug(ld, "ldap_connect_to_host: Trying %s:%d\n", address, port, 0); } #else osip_debug(ld, "ldap_connect_to_host: Trying %s:%d\n", inet_ntoa(sin.sin_addr), port, 0); #endif rc = ldap_pvt_connect(ld, s, (struct sockaddr *)&sin, sizeof(sin), async); if ( (rc == 0) || (rc == -2) ) { int err = ldap_int_connect_cbs( ld, sb, &s, srv, (struct sockaddr *)&sin ); if ( err ) rc = err; else break; } ldap_pvt_close_socket(ld, s); if (!use_hp) break; } if (ha_buf) LDAP_FREE(ha_buf); #endif return rc; } #if defined( HAVE_CYRUS_SASL ) char * ldap_host_connected_to( Sockbuf *sb, const char *host ) { ber_socklen_t len; #ifdef LDAP_PF_INET6 struct sockaddr_storage sabuf; #else struct sockaddr sabuf; #endif struct sockaddr *sa = (struct sockaddr *) &sabuf; ber_socket_t sd; (void)memset( (char *)sa, '\0', sizeof sabuf ); len = sizeof sabuf; ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); if ( getpeername( sd, sa, &len ) == -1 ) { return( NULL ); } /* * do a reverse lookup on the addr to get the official hostname. * this is necessary for kerberos to work right, since the official * hostname is used as the kerberos instance. */ switch (sa->sa_family) { #ifdef LDAP_PF_LOCAL case AF_LOCAL: return LDAP_STRDUP( ldap_int_hostname ); #endif #ifdef LDAP_PF_INET6 case AF_INET6: { struct in6_addr localhost = IN6ADDR_LOOPBACK_INIT; if( memcmp ( &((struct sockaddr_in6 *)sa)->sin6_addr, &localhost, sizeof(localhost)) == 0 ) { return LDAP_STRDUP( ldap_int_hostname ); } } break; #endif case AF_INET: { struct in_addr localhost; localhost.s_addr = htonl( INADDR_ANY ); if( memcmp ( &((struct sockaddr_in *)sa)->sin_addr, &localhost, sizeof(localhost) ) == 0 ) { return LDAP_STRDUP( ldap_int_hostname ); } #ifdef INADDR_LOOPBACK localhost.s_addr = htonl( INADDR_LOOPBACK ); if( memcmp ( &((struct sockaddr_in *)sa)->sin_addr, &localhost, sizeof(localhost) ) == 0 ) { return LDAP_STRDUP( ldap_int_hostname ); } #endif } break; default: return( NULL ); break; } { char *herr; #ifdef NI_MAXHOST char hbuf[NI_MAXHOST]; #elif defined( MAXHOSTNAMELEN ) char hbuf[MAXHOSTNAMELEN]; #else char hbuf[256]; #endif hbuf[0] = 0; if (ldap_pvt_get_hname( sa, len, hbuf, sizeof(hbuf), &herr ) == 0 && hbuf[0] ) { return LDAP_STRDUP( hbuf ); } } return host ? LDAP_STRDUP( host ) : NULL; } #endif struct selectinfo { #ifdef HAVE_POLL /* for UNIX poll(2) */ int si_maxfd; struct pollfd si_fds[FD_SETSIZE]; #else /* for UNIX select(2) */ fd_set si_readfds; fd_set si_writefds; fd_set si_use_readfds; fd_set si_use_writefds; #endif }; void ldap_mark_select_write( LDAP *ld, Sockbuf *sb ) { struct selectinfo *sip; ber_socket_t sd; sip = (struct selectinfo *)ld->ld_selectinfo; ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); #ifdef HAVE_POLL /* for UNIX poll(2) */ { int empty=-1; int i; for(i=0; i < sip->si_maxfd; i++) { if( sip->si_fds[i].fd == sd ) { sip->si_fds[i].events |= POLL_WRITE; return; } if( empty==-1 && sip->si_fds[i].fd == -1 ) { empty=i; } } if( empty == -1 ) { if( sip->si_maxfd >= FD_SETSIZE ) { /* FIXME */ return; } empty = sip->si_maxfd++; } sip->si_fds[empty].fd = sd; sip->si_fds[empty].events = POLL_WRITE; } #else /* for UNIX select(2) */ if ( !FD_ISSET( sd, &sip->si_writefds )) { FD_SET( sd, &sip->si_writefds ); } #endif } void ldap_mark_select_read( LDAP *ld, Sockbuf *sb ) { struct selectinfo *sip; ber_socket_t sd; sip = (struct selectinfo *)ld->ld_selectinfo; ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); #ifdef HAVE_POLL /* for UNIX poll(2) */ { int empty=-1; int i; for(i=0; i < sip->si_maxfd; i++) { if( sip->si_fds[i].fd == sd ) { sip->si_fds[i].events |= POLL_READ; return; } if( empty==-1 && sip->si_fds[i].fd == -1 ) { empty=i; } } if( empty == -1 ) { if( sip->si_maxfd >= FD_SETSIZE ) { /* FIXME */ return; } empty = sip->si_maxfd++; } sip->si_fds[empty].fd = sd; sip->si_fds[empty].events = POLL_READ; } #else /* for UNIX select(2) */ if ( !FD_ISSET( sd, &sip->si_readfds )) { FD_SET( sd, &sip->si_readfds ); } #endif } void ldap_mark_select_clear( LDAP *ld, Sockbuf *sb ) { struct selectinfo *sip; ber_socket_t sd; sip = (struct selectinfo *)ld->ld_selectinfo; ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); #ifdef HAVE_POLL /* for UNIX poll(2) */ { int i; for(i=0; i < sip->si_maxfd; i++) { if( sip->si_fds[i].fd == sd ) { sip->si_fds[i].fd = -1; } } } #else /* for UNIX select(2) */ FD_CLR( sd, &sip->si_writefds ); FD_CLR( sd, &sip->si_readfds ); #endif } void ldap_clear_select_write( LDAP *ld, Sockbuf *sb ) { struct selectinfo *sip; ber_socket_t sd; sip = (struct selectinfo *)ld->ld_selectinfo; ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); #ifdef HAVE_POLL /* for UNIX poll(2) */ { int i; for(i=0; i < sip->si_maxfd; i++) { if( sip->si_fds[i].fd == sd ) { sip->si_fds[i].events &= ~POLL_WRITE; } } } #else /* for UNIX select(2) */ FD_CLR( sd, &sip->si_writefds ); #endif } int ldap_is_write_ready( LDAP *ld, Sockbuf *sb ) { struct selectinfo *sip; ber_socket_t sd; sip = (struct selectinfo *)ld->ld_selectinfo; ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); #ifdef HAVE_POLL /* for UNIX poll(2) */ { int i; for(i=0; i < sip->si_maxfd; i++) { if( sip->si_fds[i].fd == sd ) { return sip->si_fds[i].revents & POLL_WRITE; } } return 0; } #else /* for UNIX select(2) */ return( FD_ISSET( sd, &sip->si_use_writefds )); #endif } int ldap_is_read_ready( LDAP *ld, Sockbuf *sb ) { struct selectinfo *sip; ber_socket_t sd; sip = (struct selectinfo *)ld->ld_selectinfo; if (ber_sockbuf_ctrl( sb, LBER_SB_OPT_DATA_READY, NULL )) return 1; ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); #ifdef HAVE_POLL /* for UNIX poll(2) */ { int i; for(i=0; i < sip->si_maxfd; i++) { if( sip->si_fds[i].fd == sd ) { return sip->si_fds[i].revents & POLL_READ; } } return 0; } #else /* for UNIX select(2) */ return( FD_ISSET( sd, &sip->si_use_readfds )); #endif } void * ldap_new_select_info( void ) { struct selectinfo *sip; sip = (struct selectinfo *)LDAP_CALLOC( 1, sizeof( struct selectinfo )); if ( sip == NULL ) return NULL; #ifdef HAVE_POLL /* for UNIX poll(2) */ /* sip->si_maxfd=0 */ #else /* for UNIX select(2) */ FD_ZERO( &sip->si_readfds ); FD_ZERO( &sip->si_writefds ); #endif return( (void *)sip ); } void ldap_free_select_info( void *sip ) { LDAP_FREE( sip ); } #ifndef HAVE_POLL int ldap_int_tblsize = 0; void ldap_int_ip_init( void ) { #if defined( HAVE_SYSCONF ) long tblsize = sysconf( _SC_OPEN_MAX ); if( tblsize > INT_MAX ) tblsize = INT_MAX; #elif defined( HAVE_GETDTABLESIZE ) int tblsize = getdtablesize(); #else int tblsize = FD_SETSIZE; #endif /* !USE_SYSCONF */ #ifdef FD_SETSIZE if( tblsize > FD_SETSIZE ) tblsize = FD_SETSIZE; #endif /* FD_SETSIZE */ ldap_int_tblsize = tblsize; } #endif int ldap_int_select( LDAP *ld, struct timeval *timeout ) { int rc; struct selectinfo *sip; Debug( LDAP_DEBUG_TRACE, "ldap_int_select\n", 0, 0, 0 ); #ifndef HAVE_POLL if ( ldap_int_tblsize == 0 ) ldap_int_ip_init(); #endif sip = (struct selectinfo *)ld->ld_selectinfo; assert( sip != NULL ); #ifdef HAVE_POLL { int to = timeout ? TV2MILLISEC( timeout ) : INFTIM; rc = poll( sip->si_fds, sip->si_maxfd, to ); } #else sip->si_use_readfds = sip->si_readfds; sip->si_use_writefds = sip->si_writefds; rc = select( ldap_int_tblsize, &sip->si_use_readfds, &sip->si_use_writefds, NULL, timeout ); #endif return rc; } openldap-2.4.42+dfsg/libraries/libldap/turn.c0000644000175000017500000000405212563404150017550 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 2005-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* ACKNOWLEDGEMENTS: * This program was orignally developed by Kurt D. Zeilenga for inclusion in * OpenLDAP Software. */ /* * LDAPv3 Turn Operation Request */ #include "portable.h" #include #include #include #include #include #include "ldap-int.h" #include "ldap_log.h" int ldap_turn( LDAP *ld, int mutual, LDAP_CONST char* identifier, LDAPControl **sctrls, LDAPControl **cctrls, int *msgidp ) { #ifdef LDAP_EXOP_X_TURN BerElement *turnvalber = NULL; struct berval *turnvalp = NULL; int rc; turnvalber = ber_alloc_t( LBER_USE_DER ); if( mutual ) { ber_printf( turnvalber, "{bs}", mutual, identifier ); } else { ber_printf( turnvalber, "{s}", identifier ); } ber_flatten( turnvalber, &turnvalp ); rc = ldap_extended_operation( ld, LDAP_EXOP_X_TURN, turnvalp, sctrls, cctrls, msgidp ); ber_free( turnvalber, 1 ); return rc; #else return LDAP_CONTROL_NOT_FOUND; #endif } int ldap_turn_s( LDAP *ld, int mutual, LDAP_CONST char* identifier, LDAPControl **sctrls, LDAPControl **cctrls ) { #ifdef LDAP_EXOP_X_TURN BerElement *turnvalber = NULL; struct berval *turnvalp = NULL; int rc; turnvalber = ber_alloc_t( LBER_USE_DER ); if( mutual ) { ber_printf( turnvalber, "{bs}", 0xFF, identifier ); } else { ber_printf( turnvalber, "{s}", identifier ); } ber_flatten( turnvalber, &turnvalp ); rc = ldap_extended_operation_s( ld, LDAP_EXOP_X_TURN, turnvalp, sctrls, cctrls, NULL, NULL ); ber_free( turnvalber, 1 ); return rc; #else return LDAP_CONTROL_NOT_FOUND; #endif } openldap-2.4.42+dfsg/libraries/liblutil/0000755000175000017500000000000012563404150016624 5ustar ryanryanopenldap-2.4.42+dfsg/libraries/liblutil/testavl.c0000644000175000017500000000732612563404150020462 0ustar ryanryan/* testavl.c - Test Tim Howes AVL code */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (c) 1993 Regents of the University of Michigan. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of Michigan at Ann Arbor. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. */ /* ACKNOWLEDGEMENTS: * This work was originally developed by the University of Michigan * (as part of U-MICH LDAP). */ #include "portable.h" #include #include #include #define AVL_INTERNAL #define AVL_NONREENTRANT #include "avl.h" static void ravl_print LDAP_P(( Avlnode *root, int depth )); static void myprint LDAP_P(( Avlnode *root )); static int avl_strcmp LDAP_P(( const void *s, const void *t )); int main( int argc, char **argv ) { Avlnode *tree = NULL; char command[ 10 ]; char name[ 80 ]; char *p; printf( "> " ); while ( fgets( command, sizeof( command ), stdin ) != NULL ) { switch( *command ) { case 'n': /* new tree */ ( void ) avl_free( tree, free ); tree = NULL; break; case 'p': /* print */ ( void ) myprint( tree ); break; case 't': /* traverse with first, next */ #ifdef AVL_NONREENTRANT printf( "***\n" ); for ( p = (char * ) avl_getfirst( tree ); p != NULL; p = (char *) avl_getnext()) printf( "%s\n", p ); printf( "***\n" ); #else printf( "*** reentrant interface not implemented ***" ); #endif break; case 'f': /* find */ printf( "data? " ); if ( fgets( name, sizeof( name ), stdin ) == NULL ) exit( EXIT_SUCCESS ); name[ strlen( name ) - 1 ] = '\0'; if ( (p = (char *) avl_find( tree, name, avl_strcmp )) == NULL ) printf( "Not found.\n\n" ); else printf( "%s\n\n", p ); break; case 'i': /* insert */ printf( "data? " ); if ( fgets( name, sizeof( name ), stdin ) == NULL ) exit( EXIT_SUCCESS ); name[ strlen( name ) - 1 ] = '\0'; if ( avl_insert( &tree, strdup( name ), avl_strcmp, avl_dup_error ) != 0 ) printf( "\nNot inserted!\n" ); break; case 'd': /* delete */ printf( "data? " ); if ( fgets( name, sizeof( name ), stdin ) == NULL ) exit( EXIT_SUCCESS ); name[ strlen( name ) - 1 ] = '\0'; if ( avl_delete( &tree, name, avl_strcmp ) == NULL ) printf( "\nNot found!\n" ); break; case 'q': /* quit */ exit( EXIT_SUCCESS ); break; case '\n': break; default: printf("Commands: insert, delete, print, new, quit\n"); } printf( "> " ); } return( 0 ); } static void ravl_print( Avlnode *root, int depth ) { int i; if ( root == 0 ) return; ravl_print( root->avl_right, depth+1 ); for ( i = 0; i < depth; i++ ) printf( " " ); printf( "%s %d\n", (char *) root->avl_data, root->avl_bf ); ravl_print( root->avl_left, depth+1 ); } static void myprint( Avlnode *root ) { printf( "********\n" ); if ( root == 0 ) printf( "\tNULL\n" ); else ravl_print( root, 0 ); printf( "********\n" ); } static int avl_strcmp( const void *s, const void *t ) { return strcmp( s, t ); } openldap-2.4.42+dfsg/libraries/liblutil/slapdmsg.mc0000644000175000017500000000153412563404150020762 0ustar ryanryan;// ;// This file contains message strings for the OpenLDAP slapd service. ;// ;// This file should be compiled as follows ;// mc -v slapdmsg.mc -r $(IntDir) ;// rc /v /r $(IntDir)\slapdmsg.rc ;// The mc (message compiler) command generates the .rc and .h files from this file. The ;// rc (resource compiler) takes the .rc file and produces a .res file that can be linked ;// with the final executable application. The application is then registered as a message ;// source with by creating the appropriate entries in the system registry. ;// MessageID=0x500 Severity=Informational SymbolicName=MSG_SVC_STARTED Facility=Application Language=English OpenLDAP service started. debuglevel=%1, conffile=%2, urls=%3 . MessageID=0x501 Severity=Informational SymbolicName=MSG_SVC_STOPPED Facility=Application Language=English OpenLDAP service stopped. . openldap-2.4.42+dfsg/libraries/liblutil/avl.c0000644000175000017500000003655312563404150017566 0ustar ryanryan/* avl.c - routines to implement an avl tree */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (c) 1993 Regents of the University of Michigan. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of Michigan at Ann Arbor. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. */ /* ACKNOWLEDGEMENTS: * This work was originally developed by the University of Michigan * (as part of U-MICH LDAP). Additional significant contributors * include: * Howard Y. Chu * Hallvard B. Furuseth * Kurt D. Zeilenga */ #include "portable.h" #include #include #include #ifdef CSRIMALLOC #define ber_memalloc malloc #define ber_memrealloc realloc #define ber_memfree free #else #include "lber.h" #endif #define AVL_INTERNAL #include "avl.h" /* Maximum tree depth this host's address space could support */ #define MAX_TREE_DEPTH (sizeof(void *) * CHAR_BIT) static const int avl_bfs[] = {LH, RH}; /* * avl_insert -- insert a node containing data data into the avl tree * with root root. fcmp is a function to call to compare the data portion * of two nodes. it should take two arguments and return <, >, or == 0, * depending on whether its first argument is <, >, or == its second * argument (like strcmp, e.g.). fdup is a function to call when a duplicate * node is inserted. it should return 0, or -1 and its return value * will be the return value from avl_insert in the case of a duplicate node. * the function will be called with the original node's data as its first * argument and with the incoming duplicate node's data as its second * argument. this could be used, for example, to keep a count with each * node. * * NOTE: this routine may malloc memory */ int avl_insert( Avlnode ** root, void *data, AVL_CMP fcmp, AVL_DUP fdup ) { Avlnode *t, *p, *s, *q, *r; int a, cmp, ncmp; if ( *root == NULL ) { if (( r = (Avlnode *) ber_memalloc( sizeof( Avlnode ))) == NULL ) { return( -1 ); } r->avl_link[0] = r->avl_link[1] = NULL; r->avl_data = data; r->avl_bf = EH; *root = r; return( 0 ); } t = NULL; s = p = *root; /* find insertion point */ while (1) { cmp = fcmp( data, p->avl_data ); if ( cmp == 0 ) return (*fdup)( p->avl_data, data ); cmp = (cmp > 0); q = p->avl_link[cmp]; if (q == NULL) { /* insert */ if (( q = (Avlnode *) ber_memalloc( sizeof( Avlnode ))) == NULL ) { return( -1 ); } q->avl_link[0] = q->avl_link[1] = NULL; q->avl_data = data; q->avl_bf = EH; p->avl_link[cmp] = q; break; } else if ( q->avl_bf ) { t = p; s = q; } p = q; } /* adjust balance factors */ cmp = fcmp( data, s->avl_data ) > 0; r = p = s->avl_link[cmp]; a = avl_bfs[cmp]; while ( p != q ) { cmp = fcmp( data, p->avl_data ) > 0; p->avl_bf = avl_bfs[cmp]; p = p->avl_link[cmp]; } /* checks and balances */ if ( s->avl_bf == EH ) { s->avl_bf = a; return 0; } else if ( s->avl_bf == -a ) { s->avl_bf = EH; return 0; } else if ( s->avl_bf == a ) { cmp = (a > 0); ncmp = !cmp; if ( r->avl_bf == a ) { /* single rotation */ p = r; s->avl_link[cmp] = r->avl_link[ncmp]; r->avl_link[ncmp] = s; s->avl_bf = 0; r->avl_bf = 0; } else if ( r->avl_bf == -a ) { /* double rotation */ p = r->avl_link[ncmp]; r->avl_link[ncmp] = p->avl_link[cmp]; p->avl_link[cmp] = r; s->avl_link[cmp] = p->avl_link[ncmp]; p->avl_link[ncmp] = s; if ( p->avl_bf == a ) { s->avl_bf = -a; r->avl_bf = 0; } else if ( p->avl_bf == -a ) { s->avl_bf = 0; r->avl_bf = a; } else { s->avl_bf = 0; r->avl_bf = 0; } p->avl_bf = 0; } /* Update parent */ if ( t == NULL ) *root = p; else if ( s == t->avl_right ) t->avl_right = p; else t->avl_left = p; } return 0; } void* avl_delete( Avlnode **root, void* data, AVL_CMP fcmp ) { Avlnode *p, *q, *r, *top; int side, side_bf, shorter, nside; /* parent stack */ Avlnode *pptr[MAX_TREE_DEPTH]; unsigned char pdir[MAX_TREE_DEPTH]; int depth = 0; if ( *root == NULL ) return NULL; p = *root; while (1) { side = fcmp( data, p->avl_data ); if ( !side ) break; side = ( side > 0 ); pdir[depth] = side; pptr[depth++] = p; p = p->avl_link[side]; if ( p == NULL ) return p; } data = p->avl_data; /* If this node has two children, swap so we are deleting a node with * at most one child. */ if ( p->avl_link[0] && p->avl_link[1] ) { /* find the immediate predecessor */ q = p->avl_link[0]; side = depth; pdir[depth++] = 0; while (q->avl_link[1]) { pdir[depth] = 1; pptr[depth++] = q; q = q->avl_link[1]; } /* swap links */ r = p->avl_link[0]; p->avl_link[0] = q->avl_link[0]; q->avl_link[0] = r; q->avl_link[1] = p->avl_link[1]; p->avl_link[1] = NULL; q->avl_bf = p->avl_bf; /* fix stack positions: old parent of p points to q */ pptr[side] = q; if ( side ) { r = pptr[side-1]; r->avl_link[pdir[side-1]] = q; } else { *root = q; } /* new parent of p points to p */ if ( depth-side > 1 ) { r = pptr[depth-1]; r->avl_link[1] = p; } else { q->avl_link[0] = p; } } /* now

has at most one child, get it */ q = p->avl_link[0] ? p->avl_link[0] : p->avl_link[1]; ber_memfree( p ); if ( !depth ) { *root = q; return data; } /* set the child into p's parent */ depth--; p = pptr[depth]; side = pdir[depth]; p->avl_link[side] = q; top = NULL; shorter = 1; while ( shorter ) { p = pptr[depth]; side = pdir[depth]; nside = !side; side_bf = avl_bfs[side]; /* case 1: height unchanged */ if ( p->avl_bf == EH ) { /* Tree is now heavier on opposite side */ p->avl_bf = avl_bfs[nside]; shorter = 0; } else if ( p->avl_bf == side_bf ) { /* case 2: taller subtree shortened, height reduced */ p->avl_bf = EH; } else { /* case 3: shorter subtree shortened */ if ( depth ) top = pptr[depth-1]; /* p->parent; */ else top = NULL; /* set to the taller of the two subtrees of

*/ q = p->avl_link[nside]; if ( q->avl_bf == EH ) { /* case 3a: height unchanged, single rotate */ p->avl_link[nside] = q->avl_link[side]; q->avl_link[side] = p; shorter = 0; q->avl_bf = side_bf; p->avl_bf = (- side_bf); } else if ( q->avl_bf == p->avl_bf ) { /* case 3b: height reduced, single rotate */ p->avl_link[nside] = q->avl_link[side]; q->avl_link[side] = p; shorter = 1; q->avl_bf = EH; p->avl_bf = EH; } else { /* case 3c: height reduced, balance factors opposite */ r = q->avl_link[side]; q->avl_link[side] = r->avl_link[nside]; r->avl_link[nside] = q; p->avl_link[nside] = r->avl_link[side]; r->avl_link[side] = p; if ( r->avl_bf == side_bf ) { q->avl_bf = (- side_bf); p->avl_bf = EH; } else if ( r->avl_bf == (- side_bf)) { q->avl_bf = EH; p->avl_bf = side_bf; } else { q->avl_bf = EH; p->avl_bf = EH; } r->avl_bf = EH; q = r; } /* a rotation has caused (or in case 3c) to become * the root. let

's former parent know this. */ if ( top == NULL ) { *root = q; } else if (top->avl_link[0] == p) { top->avl_link[0] = q; } else { top->avl_link[1] = q; } /* end case 3 */ p = q; } if ( !depth ) break; depth--; } /* end while(shorter) */ return data; } static int avl_inapply( Avlnode *root, AVL_APPLY fn, void* arg, int stopflag ) { if ( root == 0 ) return( AVL_NOMORE ); if ( root->avl_left != 0 ) if ( avl_inapply( root->avl_left, fn, arg, stopflag ) == stopflag ) return( stopflag ); if ( (*fn)( root->avl_data, arg ) == stopflag ) return( stopflag ); if ( root->avl_right == 0 ) return( AVL_NOMORE ); else return( avl_inapply( root->avl_right, fn, arg, stopflag ) ); } static int avl_postapply( Avlnode *root, AVL_APPLY fn, void* arg, int stopflag ) { if ( root == 0 ) return( AVL_NOMORE ); if ( root->avl_left != 0 ) if ( avl_postapply( root->avl_left, fn, arg, stopflag ) == stopflag ) return( stopflag ); if ( root->avl_right != 0 ) if ( avl_postapply( root->avl_right, fn, arg, stopflag ) == stopflag ) return( stopflag ); return( (*fn)( root->avl_data, arg ) ); } static int avl_preapply( Avlnode *root, AVL_APPLY fn, void* arg, int stopflag ) { if ( root == 0 ) return( AVL_NOMORE ); if ( (*fn)( root->avl_data, arg ) == stopflag ) return( stopflag ); if ( root->avl_left != 0 ) if ( avl_preapply( root->avl_left, fn, arg, stopflag ) == stopflag ) return( stopflag ); if ( root->avl_right == 0 ) return( AVL_NOMORE ); else return( avl_preapply( root->avl_right, fn, arg, stopflag ) ); } /* * avl_apply -- avl tree root is traversed, function fn is called with * arguments arg and the data portion of each node. if fn returns stopflag, * the traversal is cut short, otherwise it continues. Do not use -6 as * a stopflag, as this is what is used to indicate the traversal ran out * of nodes. */ int avl_apply( Avlnode *root, AVL_APPLY fn, void* arg, int stopflag, int type ) { switch ( type ) { case AVL_INORDER: return( avl_inapply( root, fn, arg, stopflag ) ); case AVL_PREORDER: return( avl_preapply( root, fn, arg, stopflag ) ); case AVL_POSTORDER: return( avl_postapply( root, fn, arg, stopflag ) ); default: fprintf( stderr, "Invalid traversal type %d\n", type ); return( -1 ); } /* NOTREACHED */ } /* * avl_prefixapply - traverse avl tree root, applying function fprefix * to any nodes that match. fcmp is called with data as its first arg * and the current node's data as its second arg. it should return * 0 if they match, < 0 if data is less, and > 0 if data is greater. * the idea is to efficiently find all nodes that are prefixes of * some key... Like avl_apply, this routine also takes a stopflag * and will return prematurely if fmatch returns this value. Otherwise, * AVL_NOMORE is returned. */ int avl_prefixapply( Avlnode *root, void* data, AVL_CMP fmatch, void* marg, AVL_CMP fcmp, void* carg, int stopflag ) { int cmp; if ( root == 0 ) return( AVL_NOMORE ); cmp = (*fcmp)( data, root->avl_data /* , carg */); if ( cmp == 0 ) { if ( (*fmatch)( root->avl_data, marg ) == stopflag ) return( stopflag ); if ( root->avl_left != 0 ) if ( avl_prefixapply( root->avl_left, data, fmatch, marg, fcmp, carg, stopflag ) == stopflag ) return( stopflag ); if ( root->avl_right != 0 ) return( avl_prefixapply( root->avl_right, data, fmatch, marg, fcmp, carg, stopflag ) ); else return( AVL_NOMORE ); } else if ( cmp < 0 ) { if ( root->avl_left != 0 ) return( avl_prefixapply( root->avl_left, data, fmatch, marg, fcmp, carg, stopflag ) ); } else { if ( root->avl_right != 0 ) return( avl_prefixapply( root->avl_right, data, fmatch, marg, fcmp, carg, stopflag ) ); } return( AVL_NOMORE ); } /* * avl_free -- traverse avltree root, freeing the memory it is using. * the dfree() is called to free the data portion of each node. The * number of items actually freed is returned. */ int avl_free( Avlnode *root, AVL_FREE dfree ) { int nleft, nright; if ( root == 0 ) return( 0 ); nleft = nright = 0; if ( root->avl_left != 0 ) nleft = avl_free( root->avl_left, dfree ); if ( root->avl_right != 0 ) nright = avl_free( root->avl_right, dfree ); if ( dfree ) (*dfree)( root->avl_data ); ber_memfree( root ); return( nleft + nright + 1 ); } /* * avl_find -- search avltree root for a node with data data. the function * cmp is used to compare things. it is called with data as its first arg * and the current node data as its second. it should return 0 if they match, * < 0 if arg1 is less than arg2 and > 0 if arg1 is greater than arg2. */ Avlnode * avl_find2( Avlnode *root, const void *data, AVL_CMP fcmp ) { int cmp; while ( root != 0 && (cmp = (*fcmp)( data, root->avl_data )) != 0 ) { cmp = cmp > 0; root = root->avl_link[cmp]; } return root; } void* avl_find( Avlnode *root, const void* data, AVL_CMP fcmp ) { int cmp; while ( root != 0 && (cmp = (*fcmp)( data, root->avl_data )) != 0 ) { cmp = cmp > 0; root = root->avl_link[cmp]; } return( root ? root->avl_data : 0 ); } /* * avl_find_lin -- search avltree root linearly for a node with data data. * the function cmp is used to compare things. it is called with data as its * first arg and the current node data as its second. it should return 0 if * they match, non-zero otherwise. */ void* avl_find_lin( Avlnode *root, const void* data, AVL_CMP fcmp ) { void* res; if ( root == 0 ) return( NULL ); if ( (*fcmp)( data, root->avl_data ) == 0 ) return( root->avl_data ); if ( root->avl_left != 0 ) if ( (res = avl_find_lin( root->avl_left, data, fcmp )) != NULL ) return( res ); if ( root->avl_right == 0 ) return( NULL ); else return( avl_find_lin( root->avl_right, data, fcmp ) ); } /* NON-REENTRANT INTERFACE */ static void* *avl_list; static int avl_maxlist; static int avl_nextlist; #define AVL_GRABSIZE 100 /* ARGSUSED */ static int avl_buildlist( void* data, void* arg ) { static int slots; if ( avl_list == (void* *) 0 ) { avl_list = (void* *) ber_memalloc(AVL_GRABSIZE * sizeof(void*)); slots = AVL_GRABSIZE; avl_maxlist = 0; } else if ( avl_maxlist == slots ) { slots += AVL_GRABSIZE; avl_list = (void* *) ber_memrealloc( (char *) avl_list, (unsigned) slots * sizeof(void*)); } avl_list[ avl_maxlist++ ] = data; return( 0 ); } /* * avl_getfirst() and avl_getnext() are provided as alternate tree * traversal methods, to be used when a single function cannot be * provided to be called with every node in the tree. avl_getfirst() * traverses the tree and builds a linear list of all the nodes, * returning the first node. avl_getnext() returns the next thing * on the list built by avl_getfirst(). This means that avl_getfirst() * can take a while, and that the tree should not be messed with while * being traversed in this way, and that multiple traversals (even of * different trees) cannot be active at once. */ void* avl_getfirst( Avlnode *root ) { if ( avl_list ) { ber_memfree( (char *) avl_list); avl_list = (void* *) 0; } avl_maxlist = 0; avl_nextlist = 0; if ( root == 0 ) return( 0 ); (void) avl_apply( root, avl_buildlist, (void*) 0, -1, AVL_INORDER ); return( avl_list[ avl_nextlist++ ] ); } void* avl_getnext( void ) { if ( avl_list == 0 ) return( 0 ); if ( avl_nextlist == avl_maxlist ) { ber_memfree( (void*) avl_list); avl_list = (void* *) 0; return( 0 ); } return( avl_list[ avl_nextlist++ ] ); } /* end non-reentrant code */ int avl_dup_error( void* left, void* right ) { return( -1 ); } int avl_dup_ok( void* left, void* right ) { return( 0 ); } openldap-2.4.42+dfsg/libraries/liblutil/Makefile.in0000644000175000017500000000312212563404150020667 0ustar ryanryan# Makefile for -llutil # $OpenLDAP$ ## This work is part of OpenLDAP Software . ## ## Copyright 1998-2015 The OpenLDAP Foundation. ## All rights reserved. ## ## Redistribution and use in source and binary forms, with or without ## modification, are permitted only as authorized by the OpenLDAP ## Public License. ## ## A copy of this license is available in the file LICENSE in the ## top-level directory of the distribution or, alternatively, at ## . LIBRARY = liblutil.a PROGRAM = testavl LDAP_INCDIR= ../../include LDAP_LIBDIR= ../../libraries NT_SRCS = ntservice.c NT_OBJS = ntservice.o slapdmsg.res UNIX_SRCS = detach.c UNIX_OBJS = detach.o XLIBS = $(LIBRARY) $(LDAP_LIBLBER_LA) SRCS = base64.c entropy.c sasl.c signal.c hash.c passfile.c \ md5.c passwd.c sha1.c getpass.c lockf.c utils.c uuid.c sockpair.c \ avl.c tavl.c \ testavl.c \ meter.c \ @LIBSRCS@ $(@PLAT@_SRCS) OBJS = base64.o entropy.o sasl.o signal.o hash.o passfile.o \ md5.o passwd.o sha1.o getpass.o lockf.o utils.o uuid.o sockpair.o \ avl.o tavl.o \ meter.o \ @LIBOBJS@ $(@PLAT@_OBJS) testavl: $(XLIBS) testavl.o (LTLINK) -o $@ testavl.o $(LIBS) testtavl: $(XLIBS) testtavl.o (LTLINK) -o $@ testtavl.o $(LIBS) # These rules are for a Mingw32 build, specifically. # It's ok for them to be here because the clean rule is harmless, and # slapdmsg.res won't get built unless it's declared in OBJS. slapdmsg.bin: FORCE @if [ ! -f $@ ]; then cp $(srcdir)/$@ .; fi slapdmsg.res: slapdmsg.rc slapdmsg.bin windres $< -O coff -o $@ clean-local: $(RM) *.res openldap-2.4.42+dfsg/libraries/liblutil/base64.c0000644000175000017500000002311512563404150020056 0ustar ryanryan/* base64.c -- routines to encode/decode base64 data */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * Portions Copyright 1998-2003 Kurt D. Zeilenga. * Portions Copyright 1995 IBM Corporation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (c) 1996, 1998 by Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. */ /* This work is based upon Base64 routines (developed by IBM) found * Berkeley Internet Name Daemon (BIND) as distributed by ISC. They * were adapted for inclusion in OpenLDAP Software by Kurt D. Zeilenga. */ #include "portable.h" #include #include #include #include /* include socket.h to get sys/types.h and/or winsock2.h */ #include #include "lutil.h" static const char Base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; static const char Pad64 = '='; /* (From RFC1521 and draft-ietf-dnssec-secext-03.txt) The following encoding technique is taken from RFC 1521 by Borenstein and Freed. It is reproduced here in a slightly edited form for convenience. A 65-character subset of US-ASCII is used, enabling 6 bits to be represented per printable character. (The extra 65th character, "=", is used to signify a special processing function.) The encoding process represents 24-bit groups of input bits as output strings of 4 encoded characters. Proceeding from left to right, a 24-bit input group is formed by concatenating 3 8-bit input groups. These 24 bits are then treated as 4 concatenated 6-bit groups, each of which is translated into a single digit in the base64 alphabet. Each 6-bit group is used as an index into an array of 64 printable characters. The character referenced by the index is placed in the output string. Table 1: The Base64 Alphabet Value Encoding Value Encoding Value Encoding Value Encoding 0 A 17 R 34 i 51 z 1 B 18 S 35 j 52 0 2 C 19 T 36 k 53 1 3 D 20 U 37 l 54 2 4 E 21 V 38 m 55 3 5 F 22 W 39 n 56 4 6 G 23 X 40 o 57 5 7 H 24 Y 41 p 58 6 8 I 25 Z 42 q 59 7 9 J 26 a 43 r 60 8 10 K 27 b 44 s 61 9 11 L 28 c 45 t 62 + 12 M 29 d 46 u 63 / 13 N 30 e 47 v 14 O 31 f 48 w (pad) = 15 P 32 g 49 x 16 Q 33 h 50 y Special processing is performed if fewer than 24 bits are available at the end of the data being encoded. A full encoding quantum is always completed at the end of a quantity. When fewer than 24 input bits are available in an input group, zero bits are added (on the right) to form an integral number of 6-bit groups. Padding at the end of the data is performed using the '=' character. Since all base64 input is an integral number of octets, only the ------------------------------------------------- following cases can arise: (1) the final quantum of encoding input is an integral multiple of 24 bits; here, the final unit of encoded output will be an integral multiple of 4 characters with no "=" padding, (2) the final quantum of encoding input is exactly 8 bits; here, the final unit of encoded output will be two characters followed by two "=" padding characters, or (3) the final quantum of encoding input is exactly 16 bits; here, the final unit of encoded output will be three characters followed by one "=" padding character. */ int lutil_b64_ntop( u_char const *src, size_t srclength, char *target, size_t targsize) { size_t datalength = 0; u_char input[3]; u_char output[4]; size_t i; while (2 < srclength) { input[0] = *src++; input[1] = *src++; input[2] = *src++; srclength -= 3; output[0] = input[0] >> 2; output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); output[3] = input[2] & 0x3f; assert(output[0] < 64); assert(output[1] < 64); assert(output[2] < 64); assert(output[3] < 64); if (datalength + 4 > targsize) return (-1); target[datalength++] = Base64[output[0]]; target[datalength++] = Base64[output[1]]; target[datalength++] = Base64[output[2]]; target[datalength++] = Base64[output[3]]; } /* Now we worry about padding. */ if (0 != srclength) { /* Get what's left. */ input[0] = input[1] = input[2] = '\0'; for (i = 0; i < srclength; i++) input[i] = *src++; output[0] = input[0] >> 2; output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); assert(output[0] < 64); assert(output[1] < 64); assert(output[2] < 64); if (datalength + 4 > targsize) return (-1); target[datalength++] = Base64[output[0]]; target[datalength++] = Base64[output[1]]; if (srclength == 1) target[datalength++] = Pad64; else target[datalength++] = Base64[output[2]]; target[datalength++] = Pad64; } if (datalength >= targsize) return (-1); target[datalength] = '\0'; /* Returned value doesn't count \0. */ return (datalength); } /* skips all whitespace anywhere. converts characters, four at a time, starting at (or after) src from base - 64 numbers into three 8 bit bytes in the target area. it returns the number of data bytes stored at the target, or -1 on error. */ int lutil_b64_pton( char const *src, u_char *target, size_t targsize) { int tarindex, state, ch; char *pos; state = 0; tarindex = 0; while ((ch = *src++) != '\0') { if (isascii(ch) && isspace(ch)) /* Skip whitespace anywhere. */ continue; if (ch == Pad64) break; pos = strchr(Base64, ch); if (pos == 0) /* A non-base64 character. */ return (-1); switch (state) { case 0: if (target) { if ((size_t)tarindex >= targsize) return (-1); target[tarindex] = (pos - Base64) << 2; } state = 1; break; case 1: if (target) { if ((size_t)tarindex + 1 >= targsize) return (-1); target[tarindex] |= (pos - Base64) >> 4; target[tarindex+1] = ((pos - Base64) & 0x0f) << 4 ; } tarindex++; state = 2; break; case 2: if (target) { if ((size_t)tarindex + 1 >= targsize) return (-1); target[tarindex] |= (pos - Base64) >> 2; target[tarindex+1] = ((pos - Base64) & 0x03) << 6; } tarindex++; state = 3; break; case 3: if (target) { if ((size_t)tarindex >= targsize) return (-1); target[tarindex] |= (pos - Base64); } tarindex++; state = 0; break; default: abort(); } } /* * We are done decoding Base-64 chars. Let's see if we ended * on a byte boundary, and/or with erroneous trailing characters. */ if (ch == Pad64) { /* We got a pad char. */ ch = *src++; /* Skip it, get next. */ switch (state) { case 0: /* Invalid = in first position */ case 1: /* Invalid = in second position */ return (-1); case 2: /* Valid, means one byte of info */ /* Skip any number of spaces. */ for ((void)NULL; ch != '\0'; ch = *src++) if (! (isascii(ch) && isspace(ch))) break; /* Make sure there is another trailing = sign. */ if (ch != Pad64) return (-1); ch = *src++; /* Skip the = */ /* Fall through to "single trailing =" case. */ /* FALLTHROUGH */ case 3: /* Valid, means two bytes of info */ /* * We know this char is an =. Is there anything but * whitespace after it? */ for ((void)NULL; ch != '\0'; ch = *src++) if (! (isascii(ch) && isspace(ch))) return (-1); /* * Now make sure for cases 2 and 3 that the "extra" * bits that slopped past the last full byte were * zeros. If we don't check them, they become a * subliminal channel. */ if (target && target[tarindex] != 0) return (-1); } } else { /* * We ended by seeing the end of the string. Make sure we * have no partial bytes lying around. */ if (state != 0) return (-1); } return (tarindex); } openldap-2.4.42+dfsg/libraries/liblutil/setproctitle.c0000644000175000017500000000376712563404150021526 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (c) 1990,1991 Regents of the University of Michigan. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of Michigan at Ann Arbor. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. */ #include "portable.h" #ifndef HAVE_SETPROCTITLE #include #include #include #include #include char **Argv; /* pointer to original (main's) argv */ int Argc; /* original argc */ /* * takes a printf-style format string (fmt) and up to three parameters (a,b,c) * this clobbers the original argv... */ /* VARARGS */ void setproctitle( const char *fmt, ... ) { static char *endargv = (char *)0; char *s; int i; char buf[ 1024 ]; va_list ap; va_start(ap, fmt); buf[sizeof(buf) - 1] = '\0'; vsnprintf( buf, sizeof(buf)-1, fmt, ap ); va_end(ap); if ( endargv == (char *)0 ) { /* set pointer to end of original argv */ endargv = Argv[ Argc-1 ] + strlen( Argv[ Argc-1 ] ); } /* make ps print "([prog name])" */ s = Argv[0]; *s++ = '-'; i = strlen( buf ); if ( i > endargv - s - 2 ) { i = endargv - s - 2; buf[ i ] = '\0'; } strcpy( s, buf ); s += i; while ( s < endargv ) *s++ = ' '; } #endif /* NOSETPROCTITLE */ openldap-2.4.42+dfsg/libraries/liblutil/getpeereid.c0000644000175000017500000001172412563404150021112 0ustar ryanryan/* getpeereid.c */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 2000-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #ifndef _GNU_SOURCE #define _GNU_SOURCE 1 /* Needed for glibc struct ucred */ #endif #include "portable.h" #ifndef HAVE_GETPEEREID #include #include #include #include #ifdef HAVE_GETPEERUCRED #include #endif #ifdef LDAP_PF_LOCAL_SENDMSG #include #ifdef HAVE_SYS_UIO_H #include #endif #include #endif #ifdef HAVE_SYS_UCRED_H #ifdef HAVE_GRP_H #include /* for NGROUPS on Tru64 5.1 */ #endif #include #endif #include int lutil_getpeereid( int s, uid_t *euid, gid_t *egid #ifdef LDAP_PF_LOCAL_SENDMSG , struct berval *peerbv #endif ) { #ifdef LDAP_PF_LOCAL #if defined( HAVE_GETPEERUCRED ) ucred_t *uc = NULL; if( getpeerucred( s, &uc ) == 0 ) { *euid = ucred_geteuid( uc ); *egid = ucred_getegid( uc ); ucred_free( uc ); return 0; } #elif defined( SO_PEERCRED ) struct ucred peercred; ber_socklen_t peercredlen = sizeof peercred; if(( getsockopt( s, SOL_SOCKET, SO_PEERCRED, (void *)&peercred, &peercredlen ) == 0 ) && ( peercredlen == sizeof peercred )) { *euid = peercred.uid; *egid = peercred.gid; return 0; } #elif defined( LOCAL_PEERCRED ) struct xucred peercred; ber_socklen_t peercredlen = sizeof peercred; if(( getsockopt( s, LOCAL_PEERCRED, 1, (void *)&peercred, &peercredlen ) == 0 ) && ( peercred.cr_version == XUCRED_VERSION )) { *euid = peercred.cr_uid; *egid = peercred.cr_gid; return 0; } #elif defined( LDAP_PF_LOCAL_SENDMSG ) && defined( MSG_WAITALL ) int err, fd; struct iovec iov; struct msghdr msg = {0}; # ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL # ifndef CMSG_SPACE # define CMSG_SPACE(len) (_CMSG_ALIGN(sizeof(struct cmsghdr)) + _CMSG_ALIGN(len)) # endif # ifndef CMSG_LEN # define CMSG_LEN(len) (_CMSG_ALIGN(sizeof(struct cmsghdr)) + (len)) # endif struct { struct cmsghdr cm; int fd; } control_st; struct cmsghdr *cmsg; # endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */ struct stat st; struct sockaddr_un lname, rname; ber_socklen_t llen, rlen; rlen = sizeof(rname); llen = sizeof(lname); memset( &lname, 0, sizeof( lname )); getsockname(s, (struct sockaddr *)&lname, &llen); iov.iov_base = peerbv->bv_val; iov.iov_len = peerbv->bv_len; msg.msg_iov = &iov; msg.msg_iovlen = 1; peerbv->bv_len = 0; # ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL msg.msg_control = &control_st; msg.msg_controllen = sizeof( struct cmsghdr ) + sizeof( int ); /* no padding! */ cmsg = CMSG_FIRSTHDR( &msg ); # else msg.msg_accrights = (char *)&fd; msg.msg_accrightslen = sizeof(fd); # endif /* * AIX returns a bogus file descriptor if recvmsg() is * called with MSG_PEEK (is this a bug?). Hence we need * to receive the Abandon PDU. */ err = recvmsg( s, &msg, MSG_WAITALL ); if( err >= 0 && # ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL cmsg->cmsg_len == CMSG_LEN( sizeof(int) ) && cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS # else msg.msg_accrightslen == sizeof(int) # endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL*/ ) { int mode = S_IFIFO|S_ISUID|S_IRWXU; /* We must receive a valid descriptor, it must be a pipe, * it must only be accessible by its owner, and it must * have the name of our socket written on it. */ peerbv->bv_len = err; # ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL fd = (*(int *)CMSG_DATA( cmsg )); # endif err = fstat( fd, &st ); if ( err == 0 ) rlen = read(fd, &rname, rlen); close(fd); if( err == 0 && st.st_mode == mode && llen == rlen && !memcmp(&lname, &rname, llen)) { *euid = st.st_uid; *egid = st.st_gid; return 0; } } #elif defined(SOCKCREDSIZE) struct msghdr msg; ber_socklen_t crmsgsize; void *crmsg; struct cmsghdr *cmp; struct sockcred *sc; memset(&msg, 0, sizeof msg); crmsgsize = CMSG_SPACE(SOCKCREDSIZE(NGROUPS)); if (crmsgsize == 0) goto sc_err; crmsg = malloc(crmsgsize); if (crmsg == NULL) goto sc_err; memset(crmsg, 0, crmsgsize); msg.msg_control = crmsg; msg.msg_controllen = crmsgsize; if (recvmsg(s, &msg, 0) < 0) { free(crmsg); goto sc_err; } if (msg.msg_controllen == 0 || (msg.msg_flags & MSG_CTRUNC) != 0) { free(crmsg); goto sc_err; } cmp = CMSG_FIRSTHDR(&msg); if (cmp->cmsg_level != SOL_SOCKET || cmp->cmsg_type != SCM_CREDS) { printf("nocreds\n"); goto sc_err; } sc = (struct sockcred *)(void *)CMSG_DATA(cmp); *euid = sc->sc_euid; *egid = sc->sc_egid; free(crmsg); return 0; sc_err: #endif #endif /* LDAP_PF_LOCAL */ return -1; } #endif /* HAVE_GETPEEREID */ openldap-2.4.42+dfsg/libraries/liblutil/lockf.c0000644000175000017500000000464112563404150020073 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* * File Locking Routines * * Implementations (in order of preference) * - lockf * - fcntl * - flock * * Other implementations will be added as needed. * * NOTE: lutil_lockf() MUST block until an exclusive lock is acquired. */ #include "portable.h" #include #include #undef LOCK_API #if defined(HAVE_LOCKF) && defined(F_LOCK) # define USE_LOCKF 1 # define LOCK_API "lockf" #endif #if !defined(LOCK_API) && defined(HAVE_FCNTL) # ifdef HAVE_FCNTL_H # include # endif # ifdef F_WRLCK # define USE_FCNTL 1 # define LOCK_API "fcntl" # endif #endif #if !defined(LOCK_API) && defined(HAVE_FLOCK) # ifdef HAVE_SYS_FILE_H # include # endif # define USE_FLOCK 1 # define LOCK_API "flock" #endif #if !defined(USE_LOCKF) && !defined(USE_FCNTL) && !defined(USE_FLOCK) int lutil_lockf ( int fd ) { fd = fd; return 0; } int lutil_unlockf ( int fd ) { fd = fd; return 0; } #endif #ifdef USE_LOCKF int lutil_lockf ( int fd ) { /* use F_LOCK instead of F_TLOCK, ie: block */ return lockf( fd, F_LOCK, 0 ); } int lutil_unlockf ( int fd ) { return lockf( fd, F_ULOCK, 0 ); } #endif #ifdef USE_FCNTL int lutil_lockf ( int fd ) { struct flock file_lock; memset( &file_lock, '\0', sizeof( file_lock ) ); file_lock.l_type = F_WRLCK; file_lock.l_whence = SEEK_SET; file_lock.l_start = 0; file_lock.l_len = 0; /* use F_SETLKW instead of F_SETLK, ie: block */ return( fcntl( fd, F_SETLKW, &file_lock ) ); } int lutil_unlockf ( int fd ) { struct flock file_lock; memset( &file_lock, '\0', sizeof( file_lock ) ); file_lock.l_type = F_UNLCK; file_lock.l_whence = SEEK_SET; file_lock.l_start = 0; file_lock.l_len = 0; return( fcntl ( fd, F_SETLKW, &file_lock ) ); } #endif #ifdef USE_FLOCK int lutil_lockf ( int fd ) { /* use LOCK_EX instead of LOCK_EX|LOCK_NB, ie: block */ return flock( fd, LOCK_EX ); } int lutil_unlockf ( int fd ) { return flock( fd, LOCK_UN ); } #endif openldap-2.4.42+dfsg/libraries/liblutil/ntservice.c0000644000175000017500000003540312563404150020777 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* * NT Service manager utilities for OpenLDAP services */ #include "portable.h" #ifdef HAVE_NT_SERVICE_MANAGER #include #include #include #include #include #include #include "ldap_pvt_thread.h" #include "ldap_defaults.h" #include "slapdmsg.h" #define SCM_NOTIFICATION_INTERVAL 5000 #define THIRTY_SECONDS (30 * 1000) int is_NT_Service; /* is this is an NT service? */ SERVICE_STATUS lutil_ServiceStatus; SERVICE_STATUS_HANDLE hlutil_ServiceStatus; ldap_pvt_thread_cond_t started_event, stopped_event; ldap_pvt_thread_t start_status_tid, stop_status_tid; void (*stopfunc)(int); static char *GetLastErrorString( void ); int lutil_srv_install(LPCTSTR lpszServiceName, LPCTSTR lpszDisplayName, LPCTSTR lpszBinaryPathName, int auto_start) { HKEY hKey; DWORD dwValue, dwDisposition; SC_HANDLE schSCManager, schService; char *sp = strchr( lpszBinaryPathName, ' '); if ( sp ) *sp = '\0'; fprintf( stderr, "The install path is %s.\n", lpszBinaryPathName ); if ( sp ) *sp = ' '; if ((schSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_CONNECT|SC_MANAGER_CREATE_SERVICE ) ) != NULL ) { if ((schService = CreateService( schSCManager, lpszServiceName, lpszDisplayName, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, auto_start ? SERVICE_AUTO_START : SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, lpszBinaryPathName, NULL, NULL, NULL, NULL, NULL)) != NULL) { char regpath[132]; CloseServiceHandle(schService); CloseServiceHandle(schSCManager); snprintf( regpath, sizeof regpath, "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\%s", lpszServiceName ); /* Create the registry key for event logging to the Windows NT event log. */ if ( RegCreateKeyEx(HKEY_LOCAL_MACHINE, regpath, 0, "REG_SZ", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dwDisposition) != ERROR_SUCCESS) { fprintf( stderr, "RegCreateKeyEx() failed. GetLastError=%lu (%s)\n", GetLastError(), GetLastErrorString() ); RegCloseKey(hKey); return(0); } if ( sp ) *sp = '\0'; if ( RegSetValueEx(hKey, "EventMessageFile", 0, REG_EXPAND_SZ, lpszBinaryPathName, strlen(lpszBinaryPathName) + 1) != ERROR_SUCCESS) { fprintf( stderr, "RegSetValueEx(EventMessageFile) failed. GetLastError=%lu (%s)\n", GetLastError(), GetLastErrorString() ); RegCloseKey(hKey); return(0); } dwValue = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE; if ( RegSetValueEx(hKey, "TypesSupported", 0, REG_DWORD, (LPBYTE) &dwValue, sizeof(DWORD)) != ERROR_SUCCESS) { fprintf( stderr, "RegCreateKeyEx(TypesSupported) failed. GetLastError=%lu (%s)\n", GetLastError(), GetLastErrorString() ); RegCloseKey(hKey); return(0); } RegCloseKey(hKey); return(1); } else { fprintf( stderr, "CreateService() failed. GetLastError=%lu (%s)\n", GetLastError(), GetLastErrorString() ); CloseServiceHandle(schSCManager); return(0); } } else fprintf( stderr, "OpenSCManager() failed. GetLastError=%lu (%s)\n", GetLastError(), GetLastErrorString() ); return(0); } int lutil_srv_remove(LPCTSTR lpszServiceName, LPCTSTR lpszBinaryPathName) { SC_HANDLE schSCManager, schService; fprintf( stderr, "The installed path is %s.\n", lpszBinaryPathName ); if ((schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT|SC_MANAGER_CREATE_SERVICE)) != NULL ) { if ((schService = OpenService(schSCManager, lpszServiceName, DELETE)) != NULL) { if ( DeleteService(schService) == TRUE) { CloseServiceHandle(schService); CloseServiceHandle(schSCManager); return(1); } else { fprintf( stderr, "DeleteService() failed. GetLastError=%lu (%s)\n", GetLastError(), GetLastErrorString() ); fprintf( stderr, "The %s service has not been removed.\n", lpszBinaryPathName); CloseServiceHandle(schService); CloseServiceHandle(schSCManager); return(0); } } else { fprintf( stderr, "OpenService() failed. GetLastError=%lu (%s)\n", GetLastError(), GetLastErrorString() ); CloseServiceHandle(schSCManager); return(0); } } else fprintf( stderr, "OpenSCManager() failed. GetLastError=%lu (%s)\n", GetLastError(), GetLastErrorString() ); return(0); } #if 0 /* unused */ DWORD svc_installed (LPTSTR lpszServiceName, LPTSTR lpszBinaryPathName) { char buf[256]; HKEY key; DWORD rc; DWORD type; long len; strcpy(buf, TEXT("SYSTEM\\CurrentControlSet\\Services\\")); strcat(buf, lpszServiceName); if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, buf, 0, KEY_QUERY_VALUE, &key) != ERROR_SUCCESS) return(-1); rc = 0; if (lpszBinaryPathName) { len = sizeof(buf); if (RegQueryValueEx(key, "ImagePath", NULL, &type, buf, &len) == ERROR_SUCCESS) { if (strcmp(lpszBinaryPathName, buf)) rc = -1; } } RegCloseKey(key); return(rc); } DWORD svc_running (LPTSTR lpszServiceName) { SC_HANDLE service; SC_HANDLE scm; DWORD rc; SERVICE_STATUS ss; if (!(scm = OpenSCManager(NULL, NULL, GENERIC_READ))) return(GetLastError()); rc = 1; service = OpenService(scm, lpszServiceName, SERVICE_QUERY_STATUS); if (service) { if (!QueryServiceStatus(service, &ss)) rc = GetLastError(); else if (ss.dwCurrentState != SERVICE_STOPPED) rc = 0; CloseServiceHandle(service); } CloseServiceHandle(scm); return(rc); } #endif static void *start_status_routine( void *ptr ) { DWORD wait_result; int done = 0; while ( !done ) { wait_result = WaitForSingleObject( started_event, SCM_NOTIFICATION_INTERVAL ); switch ( wait_result ) { case WAIT_ABANDONED: case WAIT_OBJECT_0: /* the object that we were waiting for has been destroyed (ABANDONED) or * signalled (TIMEOUT_0). We can assume that the startup process is * complete and tell the Service Control Manager that we are now runnng */ lutil_ServiceStatus.dwCurrentState = SERVICE_RUNNING; lutil_ServiceStatus.dwWin32ExitCode = NO_ERROR; lutil_ServiceStatus.dwCheckPoint++; lutil_ServiceStatus.dwWaitHint = 1000; SetServiceStatus(hlutil_ServiceStatus, &lutil_ServiceStatus); done = 1; break; case WAIT_TIMEOUT: /* We've waited for the required time, so send an update to the Service Control * Manager saying to wait again. */ lutil_ServiceStatus.dwCheckPoint++; lutil_ServiceStatus.dwWaitHint = SCM_NOTIFICATION_INTERVAL * 2; SetServiceStatus(hlutil_ServiceStatus, &lutil_ServiceStatus); break; case WAIT_FAILED: /* theres been some problem with WaitForSingleObject so tell the Service * Control Manager to wait 30 seconds before deploying its assasin and * then leave the thread. */ lutil_ServiceStatus.dwCheckPoint++; lutil_ServiceStatus.dwWaitHint = THIRTY_SECONDS; SetServiceStatus(hlutil_ServiceStatus, &lutil_ServiceStatus); done = 1; break; } } ldap_pvt_thread_exit(NULL); return NULL; } static void *stop_status_routine( void *ptr ) { DWORD wait_result; int done = 0; while ( !done ) { wait_result = WaitForSingleObject( stopped_event, SCM_NOTIFICATION_INTERVAL ); switch ( wait_result ) { case WAIT_ABANDONED: case WAIT_OBJECT_0: /* the object that we were waiting for has been destroyed (ABANDONED) or * signalled (TIMEOUT_0). The shutting down process is therefore complete * and the final SERVICE_STOPPED message will be sent to the service control * manager prior to the process terminating. */ done = 1; break; case WAIT_TIMEOUT: /* We've waited for the required time, so send an update to the Service Control * Manager saying to wait again. */ lutil_ServiceStatus.dwCheckPoint++; lutil_ServiceStatus.dwWaitHint = SCM_NOTIFICATION_INTERVAL * 2; SetServiceStatus(hlutil_ServiceStatus, &lutil_ServiceStatus); break; case WAIT_FAILED: /* theres been some problem with WaitForSingleObject so tell the Service * Control Manager to wait 30 seconds before deploying its assasin and * then leave the thread. */ lutil_ServiceStatus.dwCheckPoint++; lutil_ServiceStatus.dwWaitHint = THIRTY_SECONDS; SetServiceStatus(hlutil_ServiceStatus, &lutil_ServiceStatus); done = 1; break; } } ldap_pvt_thread_exit(NULL); return NULL; } static void WINAPI lutil_ServiceCtrlHandler( IN DWORD Opcode) { switch (Opcode) { case SERVICE_CONTROL_STOP: case SERVICE_CONTROL_SHUTDOWN: lutil_ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING; lutil_ServiceStatus.dwCheckPoint++; lutil_ServiceStatus.dwWaitHint = SCM_NOTIFICATION_INTERVAL * 2; SetServiceStatus(hlutil_ServiceStatus, &lutil_ServiceStatus); ldap_pvt_thread_cond_init( &stopped_event ); if ( stopped_event == NULL ) { /* the event was not created. We will ask the service control manager for 30 * seconds to shutdown */ lutil_ServiceStatus.dwCheckPoint++; lutil_ServiceStatus.dwWaitHint = THIRTY_SECONDS; SetServiceStatus(hlutil_ServiceStatus, &lutil_ServiceStatus); } else { /* start a thread to report the progress to the service control manager * until the stopped_event is fired. */ if ( ldap_pvt_thread_create( &stop_status_tid, 0, stop_status_routine, NULL ) == 0 ) { } else { /* failed to create the thread that tells the Service Control Manager that the * service stopping is proceeding. * tell the Service Control Manager to wait another 30 seconds before deploying its * assasin. */ lutil_ServiceStatus.dwCheckPoint++; lutil_ServiceStatus.dwWaitHint = THIRTY_SECONDS; SetServiceStatus(hlutil_ServiceStatus, &lutil_ServiceStatus); } } stopfunc( -1 ); break; case SERVICE_CONTROL_INTERROGATE: SetServiceStatus(hlutil_ServiceStatus, &lutil_ServiceStatus); break; } return; } void *lutil_getRegParam( char *svc, char *value ) { HKEY hkey; char path[255]; DWORD vType; static char vValue[1024]; DWORD valLen = sizeof( vValue ); if ( svc != NULL ) snprintf ( path, sizeof path, "SOFTWARE\\%s", svc ); else snprintf ( path, sizeof path, "SOFTWARE\\OpenLDAP\\Parameters" ); if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, path, 0, KEY_READ, &hkey ) != ERROR_SUCCESS ) { return NULL; } if ( RegQueryValueEx( hkey, value, NULL, &vType, vValue, &valLen ) != ERROR_SUCCESS ) { RegCloseKey( hkey ); return NULL; } RegCloseKey( hkey ); switch ( vType ) { case REG_BINARY: case REG_DWORD: return (void*)&vValue; case REG_SZ: return (void*)&vValue; } return (void*)NULL; } void lutil_LogStartedEvent( char *svc, int slap_debug, char *configfile, char *urls ) { char *Inserts[5]; WORD i = 0, j; HANDLE hEventLog; hEventLog = RegisterEventSource( NULL, svc ); Inserts[i] = (char *)malloc( 20 ); itoa( slap_debug, Inserts[i++], 10 ); Inserts[i++] = strdup( configfile ); Inserts[i++] = strdup( urls ? urls : "ldap:///" ); ReportEvent( hEventLog, EVENTLOG_INFORMATION_TYPE, 0, MSG_SVC_STARTED, NULL, i, 0, (LPCSTR *) Inserts, NULL ); for ( j = 0; j < i; j++ ) ldap_memfree( Inserts[j] ); DeregisterEventSource( hEventLog ); } void lutil_LogStoppedEvent( char *svc ) { HANDLE hEventLog; hEventLog = RegisterEventSource( NULL, svc ); ReportEvent( hEventLog, EVENTLOG_INFORMATION_TYPE, 0, MSG_SVC_STOPPED, NULL, 0, 0, NULL, NULL ); DeregisterEventSource( hEventLog ); } void lutil_CommenceStartupProcessing( char *lpszServiceName, void (*stopper)(int) ) { hlutil_ServiceStatus = RegisterServiceCtrlHandler( lpszServiceName, (LPHANDLER_FUNCTION)lutil_ServiceCtrlHandler); stopfunc = stopper; /* initialize the Service Status structure */ lutil_ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; lutil_ServiceStatus.dwCurrentState = SERVICE_START_PENDING; lutil_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN; lutil_ServiceStatus.dwWin32ExitCode = NO_ERROR; lutil_ServiceStatus.dwServiceSpecificExitCode = 0; lutil_ServiceStatus.dwCheckPoint = 1; lutil_ServiceStatus.dwWaitHint = SCM_NOTIFICATION_INTERVAL * 2; SetServiceStatus(hlutil_ServiceStatus, &lutil_ServiceStatus); /* start up a thread to keep sending SERVICE_START_PENDING to the Service Control Manager * until the slapd listener is completed and listening. Only then should we send * SERVICE_RUNNING to the Service Control Manager. */ ldap_pvt_thread_cond_init( &started_event ); if ( started_event == NULL) { /* failed to create the event to determine when the startup process is complete so * tell the Service Control Manager to wait another 30 seconds before deploying its * assasin */ lutil_ServiceStatus.dwCheckPoint++; lutil_ServiceStatus.dwWaitHint = THIRTY_SECONDS; SetServiceStatus(hlutil_ServiceStatus, &lutil_ServiceStatus); } else { /* start a thread to report the progress to the service control manager * until the started_event is fired. */ if ( ldap_pvt_thread_create( &start_status_tid, 0, start_status_routine, NULL ) == 0 ) { } else { /* failed to create the thread that tells the Service Control Manager that the * service startup is proceeding. * tell the Service Control Manager to wait another 30 seconds before deploying its * assasin. */ lutil_ServiceStatus.dwCheckPoint++; lutil_ServiceStatus.dwWaitHint = THIRTY_SECONDS; SetServiceStatus(hlutil_ServiceStatus, &lutil_ServiceStatus); } } } void lutil_ReportShutdownComplete( ) { if ( is_NT_Service ) { /* stop sending SERVICE_STOP_PENDING messages to the Service Control Manager */ ldap_pvt_thread_cond_signal( &stopped_event ); ldap_pvt_thread_cond_destroy( &stopped_event ); /* wait for the thread sending the SERVICE_STOP_PENDING messages to the Service Control Manager to die. * if the wait fails then put ourselves to sleep for half the Service Control Manager update interval */ if (ldap_pvt_thread_join( stop_status_tid, (void *) NULL ) == -1) ldap_pvt_thread_sleep( SCM_NOTIFICATION_INTERVAL / 2 ); lutil_ServiceStatus.dwCurrentState = SERVICE_STOPPED; lutil_ServiceStatus.dwCheckPoint++; lutil_ServiceStatus.dwWaitHint = SCM_NOTIFICATION_INTERVAL; SetServiceStatus(hlutil_ServiceStatus, &lutil_ServiceStatus); } } static char *GetErrorString( int err ) { static char msgBuf[1024]; FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), msgBuf, 1024, NULL ); return msgBuf; } static char *GetLastErrorString( void ) { return GetErrorString( GetLastError() ); } #endif openldap-2.4.42+dfsg/libraries/liblutil/uuid.c0000644000175000017500000002360612563404150017745 0ustar ryanryan/* uuid.c -- Universally Unique Identifier routines */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 2000-2015 The OpenLDAP Foundation. * Portions Copyright 2000-2003 Kurt D. Zeilenga. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright 2000, John E. Schimmel, All rights reserved. * This software is not subject to any license of Mirapoint, Inc. * * This is free software; you can redistribute and use it * under the same terms as OpenLDAP itself. */ /* This work was initially developed by John E. Schimmel and adapted * for inclusion in OpenLDAP Software by Kurt D. Zeilenga. */ /* * Sorry this file is so scary, but it needs to run on a wide range of * platforms. The only exported routine is lutil_uuidstr() which is all * that LDAP cares about. It generates a new uuid and returns it in * in string form. */ #include "portable.h" #include #include #include #include #include /* get memcmp() */ #ifdef HAVE_UUID_TO_STR # include #elif defined( HAVE_UUID_GENERATE ) # include #elif defined( _WIN32 ) # include #else # include # include # ifdef HAVE_SYS_SYSCTL_H # include # include # include # endif #endif #include /* not needed for Windows */ #if !defined(HAVE_UUID_TO_STR) && !defined(HAVE_UUID_GENERATE) && !defined(_WIN32) static unsigned char * lutil_eaddr( void ) { static unsigned char zero[6]; static unsigned char eaddr[6]; #ifdef HAVE_SYS_SYSCTL_H size_t needed; int mib[6]; char *buf, *next, *lim; struct if_msghdr *ifm; struct sockaddr_dl *sdl; if (memcmp(eaddr, zero, sizeof(eaddr))) { return eaddr; } mib[0] = CTL_NET; mib[1] = PF_ROUTE; mib[3] = 0; mib[3] = 0; mib[4] = NET_RT_IFLIST; mib[5] = 0; if (sysctl(mib, sizeof(mib), NULL, &needed, NULL, 0) < 0) { return NULL; } buf = malloc(needed); if( buf == NULL ) return NULL; if (sysctl(mib, sizeof(mib), buf, &needed, NULL, 0) < 0) { free(buf); return NULL; } lim = buf + needed; for (next = buf; next < lim; next += ifm->ifm_msglen) { ifm = (struct if_msghdr *)next; sdl = (struct sockaddr_dl *)(ifm + 1); if ( sdl->sdl_family != AF_LINK || sdl->sdl_alen == 6 ) { AC_MEMCPY(eaddr, (unsigned char *)sdl->sdl_data + sdl->sdl_nlen, sizeof(eaddr)); free(buf); return eaddr; } } free(buf); return NULL; #elif defined( SIOCGIFADDR ) && defined( AFLINK ) char buf[sizeof(struct ifreq) * 32]; struct ifconf ifc; struct ifreq *ifr; struct sockaddr *sa; struct sockaddr_dl *sdl; unsigned char *p; int s, i; if (memcmp(eaddr, zero, sizeof(eaddr))) { return eaddr; } s = socket( AF_INET, SOCK_DGRAM, 0 ); if ( s < 0 ) { return NULL; } ifc.ifc_len = sizeof( buf ); ifc.ifc_buf = buf; memset( buf, 0, sizeof( buf ) ); i = ioctl( s, SIOCGIFCONF, (char *)&ifc ); close( s ); if( i < 0 ) { return NULL; } for ( i = 0; i < ifc.ifc_len; ) { ifr = (struct ifreq *)&ifc.ifc_buf[i]; sa = &ifr->ifr_addr; if ( sa->sa_len > sizeof( ifr->ifr_addr ) ) { i += sizeof( ifr->ifr_name ) + sa->sa_len; } else { i += sizeof( *ifr ); } if ( sa->sa_family != AF_LINK ) { continue; } sdl = (struct sockaddr_dl *)sa; if ( sdl->sdl_alen == 6 ) { AC_MEMCPY(eaddr, (unsigned char *)sdl->sdl_data + sdl->sdl_nlen, sizeof(eaddr)); return eaddr; } } return NULL; #else if (memcmp(eaddr, zero, sizeof(eaddr)) == 0) { /* XXX - who knows? */ lutil_entropy( eaddr, sizeof(eaddr) ); eaddr[0] |= 0x01; /* turn it into a multicast address */ } return eaddr; #endif } #if (ULONG_MAX >> 31 >> 31) > 1 || defined HAVE_LONG_LONG #if (ULONG_MAX >> 31 >> 31) > 1 typedef unsigned long UI64; /* 100 usec intervals from 10/10/1582 to 1/1/1970 */ # define UUID_TPLUS 0x01B21DD2138140ul #else typedef unsigned long long UI64; # define UUID_TPLUS 0x01B21DD2138140ull #endif #define high32(i) ((unsigned long) ((i) >> 32)) #define low32(i) ((unsigned long) (i) & 0xFFFFFFFFul) #define set_add64(res, i) ((res) += (i)) #define set_add64l(res, i) ((res) += (i)) #define mul64ll(i1, i2) ((UI64) (i1) * (i2)) #else /* ! (ULONG_MAX >= 64 bits || HAVE_LONG_LONG) */ typedef struct { unsigned long high, low; } UI64; static const UI64 UUID_TPLUS = { 0x01B21Dul, 0xD2138140ul }; #define high32(i) ((i).high) #define low32(i) ((i).low) /* res += ui64 */ #define set_add64(res, ui64) \ { \ res.high += ui64.high; \ res.low = (res.low + ui64.low) & 0xFFFFFFFFul; \ if (res.low < ui64.low) res.high++; \ } /* res += ul32 */ #define set_add64l(res, ul32) \ { \ res.low = (res.low + ul32) & 0xFFFFFFFFul; \ if (res.low < ul32) res.high++; \ } /* compute i1 * i2 */ static UI64 mul64ll(unsigned long i1, unsigned long i2) { const unsigned int high1 = (i1 >> 16), low1 = (i1 & 0xffff); const unsigned int high2 = (i2 >> 16), low2 = (i2 & 0xffff); UI64 res; unsigned long tmp; res.high = (unsigned long) high1 * high2; res.low = (unsigned long) low1 * low2; tmp = (unsigned long) low1 * high2; res.high += (tmp >> 16); tmp = (tmp << 16) & 0xFFFFFFFFul; res.low = (res.low + tmp) & 0xFFFFFFFFul; if (res.low < tmp) res.high++; tmp = (unsigned long) low2 * high1; res.high += (tmp >> 16); tmp = (tmp << 16) & 0xFFFFFFFFul; res.low = (res.low + tmp) & 0xFFFFFFFFul; if (res.low < tmp) res.high++; return res; } #endif /* ULONG_MAX >= 64 bits || HAVE_LONG_LONG */ #endif /* !HAVE_UUID_TO_STR && !HAVE_UUID_GENERATE && !_WIN32 */ /* ** All we really care about is an ISO UUID string. The format of a UUID is: ** field octet note ** time_low 0-3 low field of the timestamp ** time_mid 4-5 middle field of timestamp ** time_hi_and_version 6-7 high field of timestamp and ** version number ** clock_seq_hi_and_resv 8 high field of clock sequence ** and variant ** clock_seq_low 9 low field of clock sequence ** node 10-15 spacially unique identifier ** ** We use DCE version one, and the DCE variant. Our unique identifier is ** the first ethernet address on the system. */ size_t lutil_uuidstr( char *buf, size_t len ) { #ifdef HAVE_UUID_TO_STR uuid_t uu = {0}; unsigned rc; char *s; size_t l; uuid_create( &uu, &rc ); if ( rc != uuid_s_ok ) { return 0; } uuid_to_str( &uu, &s, &rc ); if ( rc != uuid_s_ok ) { return 0; } l = strlen( s ); if ( l >= len ) { free( s ); return 0; } strncpy( buf, s, len ); free( s ); return l; #elif defined( HAVE_UUID_GENERATE ) uuid_t uu; uuid_generate( uu ); uuid_unparse_lower( uu, buf ); return strlen( buf ); #elif defined( _WIN32 ) UUID uuid; unsigned char *uuidstr; size_t uuidlen; if( UuidCreate( &uuid ) != RPC_S_OK ) { return 0; } if( UuidToString( &uuid, &uuidstr ) != RPC_S_OK ) { return 0; } uuidlen = strlen( uuidstr ); if( uuidlen >= len ) { return 0; } strncpy( buf, uuidstr, len ); RpcStringFree( &uuidstr ); return uuidlen; #else struct timeval tv; UI64 tl; unsigned char *nl; unsigned short t2, t3, s1; unsigned long t1, tl_high; unsigned int rc; /* * Theoretically we should delay if seq wraps within 100usec but for now * systems are not fast enough to worry about it. */ static int inited = 0; static unsigned short seq; if (!inited) { lutil_entropy( (unsigned char *) &seq, sizeof(seq) ); inited++; } #ifdef HAVE_GETTIMEOFDAY gettimeofday( &tv, 0 ); #else time( &tv.tv_sec ); tv.tv_usec = 0; #endif tl = mul64ll(tv.tv_sec, 10000000UL); set_add64l(tl, tv.tv_usec * 10UL); set_add64(tl, UUID_TPLUS); nl = lutil_eaddr(); t1 = low32(tl); /* time_low */ tl_high = high32(tl); t2 = tl_high & 0xffff; /* time_mid */ t3 = ((tl_high >> 16) & 0x0fff) | 0x1000; /* time_hi_and_version */ s1 = ( ++seq & 0x1fff ) | 0x8000; /* clock_seq_and_reserved */ rc = snprintf( buf, len, "%08lx-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x", t1, (unsigned) t2, (unsigned) t3, (unsigned) s1, (unsigned) nl[0], (unsigned) nl[1], (unsigned) nl[2], (unsigned) nl[3], (unsigned) nl[4], (unsigned) nl[5] ); return rc < len ? rc : 0; #endif } int lutil_uuidstr_from_normalized( char *uuid, size_t uuidlen, char *buf, size_t buflen ) { unsigned char nibble; int i, d = 0; assert( uuid != NULL ); assert( buf != NULL ); if ( uuidlen != 16 ) return -1; if ( buflen < 36 ) return -1; for ( i = 0; i < 16; i++ ) { if ( i == 4 || i == 6 || i == 8 || i == 10 ) { buf[(i<<1)+d] = '-'; d += 1; } nibble = (uuid[i] >> 4) & 0xF; if ( nibble < 10 ) { buf[(i<<1)+d] = nibble + '0'; } else { buf[(i<<1)+d] = nibble - 10 + 'a'; } nibble = (uuid[i]) & 0xF; if ( nibble < 10 ) { buf[(i<<1)+d+1] = nibble + '0'; } else { buf[(i<<1)+d+1] = nibble - 10 + 'a'; } } if ( buflen > 36 ) buf[36] = '\0'; return 36; } #ifdef TEST int main(int argc, char **argv) { char buf1[8], buf2[64]; #ifndef HAVE_UUID_TO_STR unsigned char *p = lutil_eaddr(); if( p ) { printf( "Ethernet Address: %02x:%02x:%02x:%02x:%02x:%02x\n", (unsigned) p[0], (unsigned) p[1], (unsigned) p[2], (unsigned) p[3], (unsigned) p[4], (unsigned) p[5]); } #endif if ( lutil_uuidstr( buf1, sizeof( buf1 ) ) ) { printf( "UUID: %s\n", buf1 ); } else { fprintf( stderr, "too short: %ld\n", (long) sizeof( buf1 ) ); } if ( lutil_uuidstr( buf2, sizeof( buf2 ) ) ) { printf( "UUID: %s\n", buf2 ); } else { fprintf( stderr, "too short: %ld\n", (long) sizeof( buf2 ) ); } if ( lutil_uuidstr( buf2, sizeof( buf2 ) ) ) { printf( "UUID: %s\n", buf2 ); } else { fprintf( stderr, "too short: %ld\n", (long) sizeof( buf2 ) ); } return 0; } #endif openldap-2.4.42+dfsg/libraries/liblutil/sasl.c0000644000175000017500000001154712563404150017742 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #include "portable.h" #ifdef HAVE_CYRUS_SASL #include #include #include #include #ifdef HAVE_SASL_SASL_H #include #else #include #endif #include #include "ldap_pvt.h" #include "lutil_ldap.h" typedef struct lutil_sasl_defaults_s { char *mech; char *realm; char *authcid; char *passwd; char *authzid; char **resps; int nresps; } lutilSASLdefaults; void lutil_sasl_freedefs( void *defaults ) { lutilSASLdefaults *defs = defaults; assert( defs != NULL ); if (defs->mech) ber_memfree(defs->mech); if (defs->realm) ber_memfree(defs->realm); if (defs->authcid) ber_memfree(defs->authcid); if (defs->passwd) ber_memfree(defs->passwd); if (defs->authzid) ber_memfree(defs->authzid); if (defs->resps) ldap_charray_free(defs->resps); ber_memfree(defs); } void * lutil_sasl_defaults( LDAP *ld, char *mech, char *realm, char *authcid, char *passwd, char *authzid ) { lutilSASLdefaults *defaults; defaults = ber_memalloc( sizeof( lutilSASLdefaults ) ); if( defaults == NULL ) return NULL; defaults->mech = mech ? ber_strdup(mech) : NULL; defaults->realm = realm ? ber_strdup(realm) : NULL; defaults->authcid = authcid ? ber_strdup(authcid) : NULL; defaults->passwd = passwd ? ber_strdup(passwd) : NULL; defaults->authzid = authzid ? ber_strdup(authzid) : NULL; if( defaults->mech == NULL ) { ldap_get_option( ld, LDAP_OPT_X_SASL_MECH, &defaults->mech ); } if( defaults->realm == NULL ) { ldap_get_option( ld, LDAP_OPT_X_SASL_REALM, &defaults->realm ); } if( defaults->authcid == NULL ) { ldap_get_option( ld, LDAP_OPT_X_SASL_AUTHCID, &defaults->authcid ); } if( defaults->authzid == NULL ) { ldap_get_option( ld, LDAP_OPT_X_SASL_AUTHZID, &defaults->authzid ); } defaults->resps = NULL; defaults->nresps = 0; return defaults; } static int interaction( unsigned flags, sasl_interact_t *interact, lutilSASLdefaults *defaults ) { const char *dflt = interact->defresult; char input[1024]; int noecho=0; int challenge=0; switch( interact->id ) { case SASL_CB_GETREALM: if( defaults ) dflt = defaults->realm; break; case SASL_CB_AUTHNAME: if( defaults ) dflt = defaults->authcid; break; case SASL_CB_PASS: if( defaults ) dflt = defaults->passwd; noecho = 1; break; case SASL_CB_USER: if( defaults ) dflt = defaults->authzid; break; case SASL_CB_NOECHOPROMPT: noecho = 1; challenge = 1; break; case SASL_CB_ECHOPROMPT: challenge = 1; break; } if( dflt && !*dflt ) dflt = NULL; if( flags != LDAP_SASL_INTERACTIVE && ( dflt || interact->id == SASL_CB_USER ) ) { goto use_default; } if( flags == LDAP_SASL_QUIET ) { /* don't prompt */ return LDAP_OTHER; } if( challenge ) { if( interact->challenge ) { fprintf( stderr, _("Challenge: %s\n"), interact->challenge ); } } if( dflt ) { fprintf( stderr, _("Default: %s\n"), dflt ); } snprintf( input, sizeof input, "%s: ", interact->prompt ? interact->prompt : _("Interact") ); if( noecho ) { interact->result = (char *) getpassphrase( input ); interact->len = interact->result ? strlen( interact->result ) : 0; } else { /* prompt user */ fputs( input, stderr ); /* get input */ interact->result = fgets( input, sizeof(input), stdin ); if( interact->result == NULL ) { interact->len = 0; return LDAP_UNAVAILABLE; } /* len of input */ interact->len = strlen(input); if( interact->len > 0 && input[interact->len - 1] == '\n' ) { /* input includes '\n', trim it */ interact->len--; input[interact->len] = '\0'; } } if( interact->len > 0 ) { /* duplicate */ char *p = (char *)interact->result; ldap_charray_add(&defaults->resps, interact->result); interact->result = defaults->resps[defaults->nresps++]; /* zap */ memset( p, '\0', interact->len ); } else { use_default: /* input must be empty */ interact->result = (dflt && *dflt) ? dflt : ""; interact->len = strlen( interact->result ); } return LDAP_SUCCESS; } int lutil_sasl_interact( LDAP *ld, unsigned flags, void *defaults, void *in ) { sasl_interact_t *interact = in; if( ld == NULL ) return LDAP_PARAM_ERROR; if( flags == LDAP_SASL_INTERACTIVE ) { fputs( _("SASL Interaction\n"), stderr ); } while( interact->id != SASL_CB_LIST_END ) { int rc = interaction( flags, interact, defaults ); if( rc ) return rc; interact++; } return LDAP_SUCCESS; } #endif openldap-2.4.42+dfsg/libraries/liblutil/testtavl.c0000644000175000017500000000776012563404150020650 0ustar ryanryan/* testavl.c - Test Tim Howes AVL code */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (c) 1993 Regents of the University of Michigan. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of Michigan at Ann Arbor. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. */ /* ACKNOWLEDGEMENTS: * This work was originally developed by the University of Michigan * (as part of U-MICH LDAP). Additional contributors include * Howard Chu */ #include "portable.h" #include #include #include #define AVL_INTERNAL #include "avl.h" static void ravl_print LDAP_P(( Avlnode *root, int depth, int thread )); static void myprint LDAP_P(( Avlnode *root )); static int avl_strcmp LDAP_P(( const void *s, const void *t )); int main( int argc, char **argv ) { Avlnode *tree = NULL, *n; char command[ 10 ]; char name[ 80 ]; char *p; printf( "> " ); while ( fgets( command, sizeof( command ), stdin ) != NULL ) { switch( *command ) { case 'n': /* new tree */ ( void ) tavl_free( tree, free ); tree = NULL; break; case 'p': /* print */ ( void ) myprint( tree ); break; case 't': /* traverse with first, next */ printf( "***\n" ); for ( n = tavl_end( tree, TAVL_DIR_LEFT ); n != NULL; n = tavl_next( n, TAVL_DIR_RIGHT )) printf( "%s\n", n->avl_data ); printf( "***\n" ); break; case 'f': /* find */ printf( "data? " ); if ( fgets( name, sizeof( name ), stdin ) == NULL ) exit( EXIT_SUCCESS ); name[ strlen( name ) - 1 ] = '\0'; if ( (p = (char *) tavl_find( tree, name, avl_strcmp )) == NULL ) printf( "Not found.\n\n" ); else printf( "%s\n\n", p ); break; case 'i': /* insert */ printf( "data? " ); if ( fgets( name, sizeof( name ), stdin ) == NULL ) exit( EXIT_SUCCESS ); name[ strlen( name ) - 1 ] = '\0'; if ( tavl_insert( &tree, strdup( name ), avl_strcmp, avl_dup_error ) != 0 ) printf( "\nNot inserted!\n" ); break; case 'd': /* delete */ printf( "data? " ); if ( fgets( name, sizeof( name ), stdin ) == NULL ) exit( EXIT_SUCCESS ); name[ strlen( name ) - 1 ] = '\0'; if ( tavl_delete( &tree, name, avl_strcmp ) == NULL ) printf( "\nNot found!\n" ); break; case 'q': /* quit */ exit( EXIT_SUCCESS ); break; case '\n': break; default: printf("Commands: insert, delete, print, new, quit\n"); } printf( "> " ); } return( 0 ); } static const char bfc_array[] = "\\-/"; static const char *bfcs = bfc_array+1; static void ravl_print( Avlnode *root, int depth, int thread ) { int i; if ( root && !thread ) ravl_print( root->avl_link[1], depth+1, root->avl_bits[1] == AVL_THREAD ); for ( i = 0; i < depth; i++ ) printf( " " ); if ( thread ) printf( "~" ); else if ( root ) printf( "%c", bfcs[root->avl_bf] ); else printf( " " ); if ( !root) { printf( ".\n" ); return; } printf( "%s\n", (char *) root->avl_data ); if ( !thread ) ravl_print( root->avl_link[0], depth+1, root->avl_bits[0] == AVL_THREAD ); } static void myprint( Avlnode *root ) { printf( "********\n" ); if ( root == 0 ) printf( "\tNULL\n" ); else ravl_print( root, 0, 0 ); printf( "********\n" ); } static int avl_strcmp( const void *s, const void *t ) { return strcmp( s, t ); } openldap-2.4.42+dfsg/libraries/liblutil/slapdmsg.rc0000644000175000017500000000004312563404150020761 0ustar ryanryanLANGUAGE 0x9,0x1 1 11 slapdmsg.bin openldap-2.4.42+dfsg/libraries/liblutil/ptest.c0000644000175000017500000000432212563404150020130 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #include "portable.h" #include #include #include #include #include #include #include #include #include "lutil.h" /* * Password Test Program */ static char *hash[] = { #ifdef SLAP_AUTHPASSWD "SHA1", "MD5", #else #ifdef SLAPD_CRYPT "{CRYPT}", #endif "{SSHA}", "{SMD5}", "{SHA}", "{MD5}", "{BOGUS}", #endif NULL }; static struct berval pw[] = { { sizeof("secret")-1, "secret" }, { sizeof("binary\0secret")-1, "binary\0secret" }, { 0, NULL } }; int main( int argc, char *argv[] ) { int i, j, rc; struct berval *passwd; #ifdef SLAP_AUTHPASSWD struct berval *salt; #endif struct berval bad; bad.bv_val = "bad password"; bad.bv_len = sizeof("bad password")-1; for( i= 0; hash[i]; i++ ) { for( j = 0; pw[j].bv_len; j++ ) { #ifdef SLAP_AUTHPASSWD rc = lutil_authpasswd_hash( &pw[j], &passwd, &salt, hash[i] ); if( rc ) #else passwd = lutil_passwd_hash( &pw[j], hash[i] ); if( passwd == NULL ) #endif { printf("%s generate fail: %s (%d)\n", hash[i], pw[j].bv_val, pw[j].bv_len ); continue; } #ifdef SLAP_AUTHPASSWD rc = lutil_authpasswd( &pw[j], passwd, salt, NULL ); #else rc = lutil_passwd( passwd, &pw[j], NULL ); #endif printf("%s (%d): %s (%d)\t(%d) %s\n", pw[j].bv_val, pw[j].bv_len, passwd->bv_val, passwd->bv_len, rc, rc == 0 ? "OKAY" : "BAD" ); #ifdef SLAP_AUTHPASSWD rc = lutil_authpasswd( passwd, salt, &bad, NULL ); #else rc = lutil_passwd( passwd, &bad, NULL ); #endif printf("%s (%d): %s (%d)\t(%d) %s\n", bad.bv_val, bad.bv_len, passwd->bv_val, passwd->bv_len, rc, rc != 0 ? "OKAY" : "BAD" ); } printf("\n"); } return EXIT_SUCCESS; } openldap-2.4.42+dfsg/libraries/liblutil/memcmp.c0000644000175000017500000000145512563404150020253 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #include "portable.h" #include /* * Memory Compare */ int (lutil_memcmp)(const void *v1, const void *v2, size_t n) { if (n != 0) { const unsigned char *s1=v1, *s2=v2; do { if (*s1++ != *s2++) return *--s1 - *--s2; } while (--n != 0); } return 0; } openldap-2.4.42+dfsg/libraries/liblutil/sha1.c0000644000175000017500000002005412563404150017625 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* This work was derived from code developed by Steve Reid and * adapted for use in OpenLDAP by Kurt D. Zeilenga. */ /* Acquired from: * $OpenBSD: sha1.c,v 1.9 1997/07/23 21:12:32 kstailey Exp $ */ /* * SHA-1 in C * By Steve Reid * 100% Public Domain * * Test Vectors (from FIPS PUB 180-1) * "abc" * A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" * 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 * A million repetitions of "a" * 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F */ /* * This code assumes uint32 is 32 bits and char is 8 bits */ #include "portable.h" #include #include #include #include #include "lutil_sha1.h" #ifdef LUTIL_SHA1_BYTES /* undefining this will cause pointer alignment errors */ #define SHA1HANDSOFF /* Copies data before messing with it. */ #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) /* * blk0() and blk() perform the initial expand. * I got the idea of expanding during the round function from SSLeay */ #if BYTE_ORDER == LITTLE_ENDIAN # define blk0(i) (block[i] = (rol(block[i],24)&0xFF00FF00) \ |(rol(block[i],8)&0x00FF00FF)) #else # define blk0(i) block[i] #endif #define blk(i) (block[i&15] = rol(block[(i+13)&15]^block[(i+8)&15] \ ^block[(i+2)&15]^block[i&15],1)) /* * (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1 */ #define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); #define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); #define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); #define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); #define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); /* * Hash a single 512-bit block. This is the core of the algorithm. */ void lutil_SHA1Transform( uint32 *state, const unsigned char *buffer ) { uint32 a, b, c, d, e; #ifdef SHA1HANDSOFF uint32 block[16]; (void)AC_MEMCPY(block, buffer, 64); #else uint32 *block = (u_int32 *) buffer; #endif /* Copy context->state[] to working vars */ a = state[0]; b = state[1]; c = state[2]; d = state[3]; e = state[4]; /* 4 rounds of 20 operations each. Loop unrolled. */ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); /* Add the working vars back into context.state[] */ state[0] += a; state[1] += b; state[2] += c; state[3] += d; state[4] += e; /* Wipe variables */ a = b = c = d = e = 0; } /* * lutil_SHA1Init - Initialize new context */ void lutil_SHA1Init( lutil_SHA1_CTX *context ) { /* SHA1 initialization constants */ context->state[0] = 0x67452301; context->state[1] = 0xEFCDAB89; context->state[2] = 0x98BADCFE; context->state[3] = 0x10325476; context->state[4] = 0xC3D2E1F0; context->count[0] = context->count[1] = 0; } /* * Run your data through this. */ void lutil_SHA1Update( lutil_SHA1_CTX *context, const unsigned char *data, uint32 len ) { u_int i, j; j = context->count[0]; if ((context->count[0] += len << 3) < j) context->count[1] += (len>>29)+1; j = (j >> 3) & 63; if ((j + len) > 63) { (void)AC_MEMCPY(&context->buffer[j], data, (i = 64-j)); lutil_SHA1Transform(context->state, context->buffer); for ( ; i + 63 < len; i += 64) lutil_SHA1Transform(context->state, &data[i]); j = 0; } else { i = 0; } (void)AC_MEMCPY(&context->buffer[j], &data[i], len - i); } /* * Add padding and return the message digest. */ void lutil_SHA1Final( unsigned char *digest, lutil_SHA1_CTX *context ) { u_int i; unsigned char finalcount[8]; for (i = 0; i < 8; i++) { finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ } lutil_SHA1Update(context, (unsigned char *)"\200", 1); while ((context->count[0] & 504) != 448) lutil_SHA1Update(context, (unsigned char *)"\0", 1); lutil_SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ if (digest) { for (i = 0; i < 20; i++) digest[i] = (unsigned char) ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); } } /* sha1hl.c * ---------------------------------------------------------------------------- * "THE BEER-WARE LICENSE" (Revision 42): * wrote this file. As long as you retain this notice you * can do whatever you want with this stuff. If we meet some day, and you think * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp * ---------------------------------------------------------------------------- */ #if defined(LIBC_SCCS) && !defined(lint) static char rcsid[] = "$OpenBSD: sha1hl.c,v 1.1 1997/07/12 20:06:03 millert Exp $"; #endif /* LIBC_SCCS and not lint */ #include #include #include #include #ifdef HAVE_SYS_FILE_H #include #endif #ifdef HAVE_IO_H #include #endif #ifdef HAVE_FCNTL_H #include #endif /* ARGSUSED */ char * lutil_SHA1End( lutil_SHA1_CTX *ctx, char *buf ) { int i; char *p = buf; unsigned char digest[20]; static const char hex[]="0123456789abcdef"; if (p == NULL && (p = malloc(41)) == NULL) return 0; lutil_SHA1Final(digest,ctx); for (i = 0; i < 20; i++) { p[i + i] = hex[digest[i] >> 4]; p[i + i + 1] = hex[digest[i] & 0x0f]; } p[i + i] = '\0'; return(p); } char * lutil_SHA1File( char *filename, char *buf ) { unsigned char buffer[BUFSIZ]; lutil_SHA1_CTX ctx; int fd, num, oerrno; lutil_SHA1Init(&ctx); if ((fd = open(filename,O_RDONLY)) < 0) return(0); while ((num = read(fd, buffer, sizeof(buffer))) > 0) lutil_SHA1Update(&ctx, buffer, num); oerrno = errno; close(fd); errno = oerrno; return(num < 0 ? 0 : lutil_SHA1End(&ctx, buf)); } char * lutil_SHA1Data( const unsigned char *data, size_t len, char *buf ) { lutil_SHA1_CTX ctx; lutil_SHA1Init(&ctx); lutil_SHA1Update(&ctx, data, len); return(lutil_SHA1End(&ctx, buf)); } #endif openldap-2.4.42+dfsg/libraries/liblutil/getpass.c0000644000175000017500000000614212563404150020441 0ustar ryanryan/* getpass.c -- get password from user */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * Portions Copyright 1998-2003 Kurt D. Zeilenga. * Portions Copyright 2009 Howard Chu. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (c) 1992, 1993 Regents of the University of Michigan. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of Michigan at Ann Arbor. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. */ /* This work was originally developed by the University of Michigan * and distributed as part of U-MICH LDAP. It was adapted for use in * -llutil by Kurt D. Zeilenga and subsequently rewritten by Howard Chu. */ #include "portable.h" #include #include #include #include #include #include #include #include #ifndef HAVE_GETPASSPHRASE #ifdef HAVE_FCNTL_H #include #endif #ifdef HAVE_CONIO_H #include #endif #include #include #include "ldap_defaults.h" #define PBUF 512 #ifdef HAVE_WINSOCK #define TTY "con:" #else #define TTY "/dev/tty" #endif char * lutil_getpass( const char *prompt ) { static char pbuf[PBUF]; FILE *fi; int c; unsigned i; #if defined(HAVE_TERMIOS_H) || defined(HAVE_SGTTY_H) TERMIO_TYPE ttyb; TERMFLAG_TYPE flags; RETSIGTYPE (*sig)( int sig ); #endif if( prompt == NULL ) prompt = _("Password: "); #ifdef DEBUG if (debug & D_TRACE) printf("->getpass(%s)\n", prompt); #endif #if defined(HAVE_TERMIOS_H) || defined(HAVE_SGTTY_H) if ((fi = fopen(TTY, "r")) == NULL) fi = stdin; else setbuf(fi, (char *)NULL); if (fi != stdin) { if (GETATTR(fileno(fi), &ttyb) < 0) perror("GETATTR"); sig = SIGNAL (SIGINT, SIG_IGN); flags = GETFLAGS( ttyb ); SETFLAGS( ttyb, flags & ~ECHO ); if (SETATTR(fileno(fi), &ttyb) < 0) perror("SETATTR"); } #else fi = stdin; #endif fprintf(stderr, "%s", prompt); fflush(stderr); i = 0; while ( (c = getc(fi)) != EOF && c != '\n' && c != '\r' ) if ( i < (sizeof(pbuf)-1) ) pbuf[i++] = c; #if defined(HAVE_TERMIOS_H) || defined(HAVE_SGTTY_H) /* tidy up */ if (fi != stdin) { fprintf(stderr, "\n"); fflush(stderr); SETFLAGS( ttyb, flags ); if (SETATTR(fileno(fi), &ttyb) < 0) perror("SETATTR"); (void) SIGNAL (SIGINT, sig); (void) fclose(fi); } #endif if ( c == EOF ) return( NULL ); pbuf[i] = '\0'; return (pbuf); } #endif /* !NEED_GETPASSPHRASE */ openldap-2.4.42+dfsg/libraries/liblutil/passwd.c0000644000175000017500000007153212563404150020301 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* * int lutil_passwd( * const struct berval *passwd, * const struct berval *cred, * const char **schemes ) * * Returns true if user supplied credentials (cred) matches * the stored password (passwd). * * Due to the use of the crypt(3) function * this routine is NOT thread-safe. */ #include "portable.h" #include #include #include #include #if defined(SLAPD_LMHASH) #if defined(HAVE_OPENSSL) # include typedef des_cblock des_key; typedef des_cblock des_data_block; typedef des_key_schedule des_context; #define des_failed(encrypted) 0 #define des_finish(key, schedule) #elif defined(HAVE_MOZNSS) /* hack hack hack We need to define this here so that nspr/obsolete/protypes.h will not be included if that file is included, it will create a uint32 typedef that will cause the one in lutil_sha1.h to blow up */ #define PROTYPES_H 1 # include typedef PK11SymKey *des_key; typedef unsigned char des_data_block[8]; typedef PK11Context *des_context[1]; #define DES_ENCRYPT CKA_ENCRYPT #endif #endif /* SLAPD_LMHASH */ #include #ifdef SLAPD_CRYPT # include # if defined( HAVE_GETPWNAM ) && defined( HAVE_STRUCT_PASSWD_PW_PASSWD ) # ifdef HAVE_SHADOW_H # include # endif # ifdef HAVE_PWD_H # include # endif # ifdef HAVE_AIX_SECURITY # include # endif # endif #endif #include #include "ldap_pvt.h" #include "lber_pvt.h" #include "lutil_md5.h" #include "lutil_sha1.h" #include "lutil.h" static const unsigned char crypt64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890./"; #ifdef SLAPD_CRYPT static char *salt_format = NULL; static lutil_cryptfunc lutil_crypt; lutil_cryptfunc *lutil_cryptptr = lutil_crypt; #endif /* KLUDGE: * chk_fn is NULL iff name is {CLEARTEXT} * otherwise, things will break */ struct pw_scheme { struct berval name; LUTIL_PASSWD_CHK_FUNC *chk_fn; LUTIL_PASSWD_HASH_FUNC *hash_fn; }; struct pw_slist { struct pw_slist *next; struct pw_scheme s; }; /* password check routines */ #define SALT_SIZE 4 static LUTIL_PASSWD_CHK_FUNC chk_md5; static LUTIL_PASSWD_CHK_FUNC chk_smd5; static LUTIL_PASSWD_HASH_FUNC hash_smd5; static LUTIL_PASSWD_HASH_FUNC hash_md5; #ifdef LUTIL_SHA1_BYTES static LUTIL_PASSWD_CHK_FUNC chk_ssha1; static LUTIL_PASSWD_CHK_FUNC chk_sha1; static LUTIL_PASSWD_HASH_FUNC hash_sha1; static LUTIL_PASSWD_HASH_FUNC hash_ssha1; #endif #ifdef SLAPD_LMHASH static LUTIL_PASSWD_CHK_FUNC chk_lanman; static LUTIL_PASSWD_HASH_FUNC hash_lanman; #endif #ifdef SLAPD_CRYPT static LUTIL_PASSWD_CHK_FUNC chk_crypt; static LUTIL_PASSWD_HASH_FUNC hash_crypt; #if defined( HAVE_GETPWNAM ) && defined( HAVE_STRUCT_PASSWD_PW_PASSWD ) static LUTIL_PASSWD_CHK_FUNC chk_unix; #endif #endif /* password hash routines */ #ifdef SLAPD_CLEARTEXT static LUTIL_PASSWD_HASH_FUNC hash_clear; #endif static struct pw_slist *pw_schemes; static int pw_inited; static const struct pw_scheme pw_schemes_default[] = { #ifdef LUTIL_SHA1_BYTES { BER_BVC("{SSHA}"), chk_ssha1, hash_ssha1 }, { BER_BVC("{SHA}"), chk_sha1, hash_sha1 }, #endif { BER_BVC("{SMD5}"), chk_smd5, hash_smd5 }, { BER_BVC("{MD5}"), chk_md5, hash_md5 }, #ifdef SLAPD_LMHASH { BER_BVC("{LANMAN}"), chk_lanman, hash_lanman }, #endif /* SLAPD_LMHASH */ #ifdef SLAPD_CRYPT { BER_BVC("{CRYPT}"), chk_crypt, hash_crypt }, # if defined( HAVE_GETPWNAM ) && defined( HAVE_STRUCT_PASSWD_PW_PASSWD ) { BER_BVC("{UNIX}"), chk_unix, NULL }, # endif #endif #ifdef SLAPD_CLEARTEXT /* pseudo scheme */ { BER_BVC("{CLEARTEXT}"), NULL, hash_clear }, #endif { BER_BVNULL, NULL, NULL } }; int lutil_passwd_add( struct berval *scheme, LUTIL_PASSWD_CHK_FUNC *chk, LUTIL_PASSWD_HASH_FUNC *hash ) { struct pw_slist *ptr; if (!pw_inited) lutil_passwd_init(); ptr = ber_memalloc( sizeof( struct pw_slist )); if (!ptr) return -1; ptr->next = pw_schemes; ptr->s.name = *scheme; ptr->s.chk_fn = chk; ptr->s.hash_fn = hash; pw_schemes = ptr; return 0; } void lutil_passwd_init() { struct pw_scheme *s; pw_inited = 1; for( s=(struct pw_scheme *)pw_schemes_default; s->name.bv_val; s++) { if ( lutil_passwd_add( &s->name, s->chk_fn, s->hash_fn ) ) break; } } void lutil_passwd_destroy() { struct pw_slist *ptr, *next; for( ptr=pw_schemes; ptr; ptr=next ) { next = ptr->next; ber_memfree( ptr ); } } static const struct pw_scheme *get_scheme( const char* scheme ) { struct pw_slist *pws; struct berval bv; if (!pw_inited) lutil_passwd_init(); bv.bv_val = strchr( scheme, '}' ); if ( !bv.bv_val ) return NULL; bv.bv_len = bv.bv_val - scheme + 1; bv.bv_val = (char *) scheme; for( pws=pw_schemes; pws; pws=pws->next ) { if ( ber_bvstrcasecmp(&bv, &pws->s.name ) == 0 ) { return &(pws->s); } } return NULL; } int lutil_passwd_scheme( const char* scheme ) { if( scheme == NULL ) { return 0; } return get_scheme(scheme) != NULL; } static int is_allowed_scheme( const char* scheme, const char** schemes ) { int i; if( schemes == NULL ) return 1; for( i=0; schemes[i] != NULL; i++ ) { if( strcasecmp( scheme, schemes[i] ) == 0 ) { return 1; } } return 0; } static struct berval *passwd_scheme( const struct pw_scheme *scheme, const struct berval * passwd, struct berval *bv, const char** allowed ) { if( !is_allowed_scheme( scheme->name.bv_val, allowed ) ) { return NULL; } if( passwd->bv_len >= scheme->name.bv_len ) { if( strncasecmp( passwd->bv_val, scheme->name.bv_val, scheme->name.bv_len ) == 0 ) { bv->bv_val = &passwd->bv_val[scheme->name.bv_len]; bv->bv_len = passwd->bv_len - scheme->name.bv_len; return bv; } } return NULL; } /* * Return 0 if creds are good. */ int lutil_passwd( const struct berval *passwd, /* stored passwd */ const struct berval *cred, /* user cred */ const char **schemes, const char **text ) { struct pw_slist *pws; if ( text ) *text = NULL; if (cred == NULL || cred->bv_len == 0 || passwd == NULL || passwd->bv_len == 0 ) { return -1; } if (!pw_inited) lutil_passwd_init(); for( pws=pw_schemes; pws; pws=pws->next ) { if( pws->s.chk_fn ) { struct berval x; struct berval *p = passwd_scheme( &(pws->s), passwd, &x, schemes ); if( p != NULL ) { return (pws->s.chk_fn)( &(pws->s.name), p, cred, text ); } } } #ifdef SLAPD_CLEARTEXT /* Do we think there is a scheme specifier here that we * didn't recognize? Assume a scheme name is at least 1 character. */ if (( passwd->bv_val[0] == '{' ) && ( ber_bvchr( passwd, '}' ) > passwd->bv_val+1 )) { return 1; } if( is_allowed_scheme("{CLEARTEXT}", schemes ) ) { return ( passwd->bv_len == cred->bv_len ) ? memcmp( passwd->bv_val, cred->bv_val, passwd->bv_len ) : 1; } #endif return 1; } int lutil_passwd_generate( struct berval *pw, ber_len_t len ) { if( len < 1 ) return -1; pw->bv_len = len; pw->bv_val = ber_memalloc( len + 1 ); if( pw->bv_val == NULL ) { return -1; } if( lutil_entropy( (unsigned char *) pw->bv_val, pw->bv_len) < 0 ) { return -1; } for( len = 0; len < pw->bv_len; len++ ) { pw->bv_val[len] = crypt64[ pw->bv_val[len] % (sizeof(crypt64)-1) ]; } pw->bv_val[len] = '\0'; return 0; } int lutil_passwd_hash( const struct berval * passwd, const char * method, struct berval *hash, const char **text ) { const struct pw_scheme *sc = get_scheme( method ); hash->bv_val = NULL; hash->bv_len = 0; if( sc == NULL ) { if( text ) *text = "scheme not recognized"; return -1; } if( ! sc->hash_fn ) { if( text ) *text = "scheme provided no hash function"; return -1; } if( text ) *text = NULL; return (sc->hash_fn)( &sc->name, passwd, hash, text ); } /* pw_string is only called when SLAPD_LMHASH or SLAPD_CRYPT is defined */ #if defined(SLAPD_LMHASH) || defined(SLAPD_CRYPT) static int pw_string( const struct berval *sc, struct berval *passwd ) { struct berval pw; pw.bv_len = sc->bv_len + passwd->bv_len; pw.bv_val = ber_memalloc( pw.bv_len + 1 ); if( pw.bv_val == NULL ) { return LUTIL_PASSWD_ERR; } AC_MEMCPY( pw.bv_val, sc->bv_val, sc->bv_len ); AC_MEMCPY( &pw.bv_val[sc->bv_len], passwd->bv_val, passwd->bv_len ); pw.bv_val[pw.bv_len] = '\0'; *passwd = pw; return LUTIL_PASSWD_OK; } #endif /* SLAPD_LMHASH || SLAPD_CRYPT */ int lutil_passwd_string64( const struct berval *sc, const struct berval *hash, struct berval *b64, const struct berval *salt ) { int rc; struct berval string; size_t b64len; if( salt ) { /* need to base64 combined string */ string.bv_len = hash->bv_len + salt->bv_len; string.bv_val = ber_memalloc( string.bv_len + 1 ); if( string.bv_val == NULL ) { return LUTIL_PASSWD_ERR; } AC_MEMCPY( string.bv_val, hash->bv_val, hash->bv_len ); AC_MEMCPY( &string.bv_val[hash->bv_len], salt->bv_val, salt->bv_len ); string.bv_val[string.bv_len] = '\0'; } else { string = *hash; } b64len = LUTIL_BASE64_ENCODE_LEN( string.bv_len ) + 1; b64->bv_len = b64len + sc->bv_len; b64->bv_val = ber_memalloc( b64->bv_len + 1 ); if( b64->bv_val == NULL ) { if( salt ) ber_memfree( string.bv_val ); return LUTIL_PASSWD_ERR; } AC_MEMCPY(b64->bv_val, sc->bv_val, sc->bv_len); rc = lutil_b64_ntop( (unsigned char *) string.bv_val, string.bv_len, &b64->bv_val[sc->bv_len], b64len ); if( salt ) ber_memfree( string.bv_val ); if( rc < 0 ) { return LUTIL_PASSWD_ERR; } /* recompute length */ b64->bv_len = sc->bv_len + rc; assert( strlen(b64->bv_val) == b64->bv_len ); return LUTIL_PASSWD_OK; } /* PASSWORD CHECK ROUTINES */ #ifdef LUTIL_SHA1_BYTES static int chk_ssha1( const struct berval *sc, const struct berval * passwd, const struct berval * cred, const char **text ) { lutil_SHA1_CTX SHA1context; unsigned char SHA1digest[LUTIL_SHA1_BYTES]; int rc; unsigned char *orig_pass = NULL; size_t decode_len = LUTIL_BASE64_DECODE_LEN(passwd->bv_len); /* safety check -- must have some salt */ if (decode_len <= sizeof(SHA1digest)) { return LUTIL_PASSWD_ERR; } /* decode base64 password */ orig_pass = (unsigned char *) ber_memalloc(decode_len + 1); if( orig_pass == NULL ) return LUTIL_PASSWD_ERR; rc = lutil_b64_pton(passwd->bv_val, orig_pass, decode_len); /* safety check -- must have some salt */ if (rc <= (int)(sizeof(SHA1digest))) { ber_memfree(orig_pass); return LUTIL_PASSWD_ERR; } /* hash credentials with salt */ lutil_SHA1Init(&SHA1context); lutil_SHA1Update(&SHA1context, (const unsigned char *) cred->bv_val, cred->bv_len); lutil_SHA1Update(&SHA1context, (const unsigned char *) &orig_pass[sizeof(SHA1digest)], rc - sizeof(SHA1digest)); lutil_SHA1Final(SHA1digest, &SHA1context); /* compare */ rc = memcmp((char *)orig_pass, (char *)SHA1digest, sizeof(SHA1digest)); ber_memfree(orig_pass); return rc ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK; } static int chk_sha1( const struct berval *sc, const struct berval * passwd, const struct berval * cred, const char **text ) { lutil_SHA1_CTX SHA1context; unsigned char SHA1digest[LUTIL_SHA1_BYTES]; int rc; unsigned char *orig_pass = NULL; size_t decode_len = LUTIL_BASE64_DECODE_LEN(passwd->bv_len); /* safety check */ if (decode_len < sizeof(SHA1digest)) { return LUTIL_PASSWD_ERR; } /* base64 un-encode password */ orig_pass = (unsigned char *) ber_memalloc(decode_len + 1); if( orig_pass == NULL ) return LUTIL_PASSWD_ERR; rc = lutil_b64_pton(passwd->bv_val, orig_pass, decode_len); if( rc != sizeof(SHA1digest) ) { ber_memfree(orig_pass); return LUTIL_PASSWD_ERR; } /* hash credentials with salt */ lutil_SHA1Init(&SHA1context); lutil_SHA1Update(&SHA1context, (const unsigned char *) cred->bv_val, cred->bv_len); lutil_SHA1Final(SHA1digest, &SHA1context); /* compare */ rc = memcmp((char *)orig_pass, (char *)SHA1digest, sizeof(SHA1digest)); ber_memfree(orig_pass); return rc ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK; } #endif static int chk_smd5( const struct berval *sc, const struct berval * passwd, const struct berval * cred, const char **text ) { lutil_MD5_CTX MD5context; unsigned char MD5digest[LUTIL_MD5_BYTES]; int rc; unsigned char *orig_pass = NULL; size_t decode_len = LUTIL_BASE64_DECODE_LEN(passwd->bv_len); /* safety check */ if (decode_len <= sizeof(MD5digest)) { return LUTIL_PASSWD_ERR; } /* base64 un-encode password */ orig_pass = (unsigned char *) ber_memalloc(decode_len + 1); if( orig_pass == NULL ) return LUTIL_PASSWD_ERR; rc = lutil_b64_pton(passwd->bv_val, orig_pass, decode_len); if (rc <= (int)(sizeof(MD5digest))) { ber_memfree(orig_pass); return LUTIL_PASSWD_ERR; } /* hash credentials with salt */ lutil_MD5Init(&MD5context); lutil_MD5Update(&MD5context, (const unsigned char *) cred->bv_val, cred->bv_len ); lutil_MD5Update(&MD5context, &orig_pass[sizeof(MD5digest)], rc - sizeof(MD5digest)); lutil_MD5Final(MD5digest, &MD5context); /* compare */ rc = memcmp((char *)orig_pass, (char *)MD5digest, sizeof(MD5digest)); ber_memfree(orig_pass); return rc ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK; } static int chk_md5( const struct berval *sc, const struct berval * passwd, const struct berval * cred, const char **text ) { lutil_MD5_CTX MD5context; unsigned char MD5digest[LUTIL_MD5_BYTES]; int rc; unsigned char *orig_pass = NULL; size_t decode_len = LUTIL_BASE64_DECODE_LEN(passwd->bv_len); /* safety check */ if (decode_len < sizeof(MD5digest)) { return LUTIL_PASSWD_ERR; } /* base64 un-encode password */ orig_pass = (unsigned char *) ber_memalloc(decode_len + 1); if( orig_pass == NULL ) return LUTIL_PASSWD_ERR; rc = lutil_b64_pton(passwd->bv_val, orig_pass, decode_len); if ( rc != sizeof(MD5digest) ) { ber_memfree(orig_pass); return LUTIL_PASSWD_ERR; } /* hash credentials with salt */ lutil_MD5Init(&MD5context); lutil_MD5Update(&MD5context, (const unsigned char *) cred->bv_val, cred->bv_len ); lutil_MD5Final(MD5digest, &MD5context); /* compare */ rc = memcmp((char *)orig_pass, (char *)MD5digest, sizeof(MD5digest)); ber_memfree(orig_pass); return rc ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK; } #ifdef SLAPD_LMHASH #if defined(HAVE_OPENSSL) /* * abstract away setting the parity. */ static void des_set_key_and_parity( des_key *key, unsigned char *keyData) { memcpy(key, keyData, 8); des_set_odd_parity( key ); } #elif defined(HAVE_MOZNSS) /* * implement MozNSS wrappers for the openSSL calls */ static void des_set_key_and_parity( des_key *key, unsigned char *keyData) { SECItem keyDataItem; PK11SlotInfo *slot; *key = NULL; keyDataItem.data = keyData; keyDataItem.len = 8; slot = PK11_GetBestSlot(CKM_DES_ECB, NULL); if (slot == NULL) { return; } /* NOTE: this will not work in FIPS mode. In order to make lmhash * work in fips mode we need to define a LMHASH pbe mechanism and * do the fulll key derivation inside the token */ *key = PK11_ImportSymKey(slot, CKM_DES_ECB, PK11_OriginGenerated, CKA_ENCRYPT, &keyDataItem, NULL); } static void des_set_key_unchecked( des_key *key, des_context ctxt ) { ctxt[0] = NULL; /* handle error conditions from previous call */ if (!*key) { return; } ctxt[0] = PK11_CreateContextBySymKey(CKM_DES_ECB, CKA_ENCRYPT, *key, NULL); } static void des_ecb_encrypt( des_data_block *plain, des_data_block *encrypted, des_context ctxt, int op) { SECStatus rv; int size; if (ctxt[0] == NULL) { /* need to fail here... */ memset(encrypted, 0, sizeof(des_data_block)); return; } rv = PK11_CipherOp(ctxt[0], (unsigned char *)&encrypted[0], &size, sizeof(des_data_block), (unsigned char *)&plain[0], sizeof(des_data_block)); if (rv != SECSuccess) { /* signal failure */ memset(encrypted, 0, sizeof(des_data_block)); return; } return; } static int des_failed(des_data_block *encrypted) { static const des_data_block zero = { 0 }; return memcmp(encrypted, zero, sizeof(zero)) == 0; } static void des_finish(des_key *key, des_context ctxt) { if (*key) { PK11_FreeSymKey(*key); *key = NULL; } if (ctxt[0]) { PK11_Finalize(ctxt[0]); PK11_DestroyContext(ctxt[0], PR_TRUE); ctxt[0] = NULL; } } #endif /* pseudocode from RFC2433 * A.2 LmPasswordHash() * * LmPasswordHash( * IN 0-to-14-oem-char Password, * OUT 16-octet PasswordHash ) * { * Set UcasePassword to the uppercased Password * Zero pad UcasePassword to 14 characters * * DesHash( 1st 7-octets of UcasePassword, * giving 1st 8-octets of PasswordHash ) * * DesHash( 2nd 7-octets of UcasePassword, * giving 2nd 8-octets of PasswordHash ) * } * * * A.3 DesHash() * * DesHash( * IN 7-octet Clear, * OUT 8-octet Cypher ) * { * * * * Make Cypher an irreversibly encrypted form of Clear by * * encrypting known text using Clear as the secret key. * * The known text consists of the string * * * * KGS!@#$% * * * * Set StdText to "KGS!@#$%" * DesEncrypt( StdText, Clear, giving Cypher ) * } * * * A.4 DesEncrypt() * * DesEncrypt( * IN 8-octet Clear, * IN 7-octet Key, * OUT 8-octet Cypher ) * { * * * * Use the DES encryption algorithm [4] in ECB mode [9] * * to encrypt Clear into Cypher such that Cypher can * * only be decrypted back to Clear by providing Key. * * Note that the DES algorithm takes as input a 64-bit * * stream where the 8th, 16th, 24th, etc. bits are * * parity bits ignored by the encrypting algorithm. * * Unless you write your own DES to accept 56-bit input * * without parity, you will need to insert the parity bits * * yourself. * * * } */ static void lmPasswd_to_key( const char *lmPasswd, des_key *key) { const unsigned char *lpw = (const unsigned char *) lmPasswd; unsigned char k[8]; /* make room for parity bits */ k[0] = lpw[0]; k[1] = ((lpw[0] & 0x01) << 7) | (lpw[1] >> 1); k[2] = ((lpw[1] & 0x03) << 6) | (lpw[2] >> 2); k[3] = ((lpw[2] & 0x07) << 5) | (lpw[3] >> 3); k[4] = ((lpw[3] & 0x0F) << 4) | (lpw[4] >> 4); k[5] = ((lpw[4] & 0x1F) << 3) | (lpw[5] >> 5); k[6] = ((lpw[5] & 0x3F) << 2) | (lpw[6] >> 6); k[7] = ((lpw[6] & 0x7F) << 1); des_set_key_and_parity( key, k ); } static int chk_lanman( const struct berval *scheme, const struct berval *passwd, const struct berval *cred, const char **text ) { ber_len_t i; char UcasePassword[15]; des_key key; des_context schedule; des_data_block StdText = "KGS!@#$%"; des_data_block PasswordHash1, PasswordHash2; char PasswordHash[33], storedPasswordHash[33]; for( i=0; ibv_len; i++) { if(cred->bv_val[i] == '\0') { return LUTIL_PASSWD_ERR; /* NUL character in password */ } } if( cred->bv_val[i] != '\0' ) { return LUTIL_PASSWD_ERR; /* passwd must behave like a string */ } strncpy( UcasePassword, cred->bv_val, 14 ); UcasePassword[14] = '\0'; ldap_pvt_str2upper( UcasePassword ); lmPasswd_to_key( UcasePassword, &key ); des_set_key_unchecked( &key, schedule ); des_ecb_encrypt( &StdText, &PasswordHash1, schedule , DES_ENCRYPT ); if (des_failed(&PasswordHash1)) { return LUTIL_PASSWD_ERR; } lmPasswd_to_key( &UcasePassword[7], &key ); des_set_key_unchecked( &key, schedule ); des_ecb_encrypt( &StdText, &PasswordHash2, schedule , DES_ENCRYPT ); if (des_failed(&PasswordHash2)) { return LUTIL_PASSWD_ERR; } des_finish( &key, schedule ); sprintf( PasswordHash, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", PasswordHash1[0],PasswordHash1[1],PasswordHash1[2],PasswordHash1[3], PasswordHash1[4],PasswordHash1[5],PasswordHash1[6],PasswordHash1[7], PasswordHash2[0],PasswordHash2[1],PasswordHash2[2],PasswordHash2[3], PasswordHash2[4],PasswordHash2[5],PasswordHash2[6],PasswordHash2[7] ); /* as a precaution convert stored password hash to lower case */ strncpy( storedPasswordHash, passwd->bv_val, 32 ); storedPasswordHash[32] = '\0'; ldap_pvt_str2lower( storedPasswordHash ); return memcmp( PasswordHash, storedPasswordHash, 32) ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK; } #endif /* SLAPD_LMHASH */ #ifdef SLAPD_CRYPT static int lutil_crypt( const char *key, const char *salt, char **hash ) { char *cr = crypt( key, salt ); int rc; if( cr == NULL || cr[0] == '\0' ) { /* salt must have been invalid */ rc = LUTIL_PASSWD_ERR; } else { if ( hash ) { *hash = ber_strdup( cr ); rc = LUTIL_PASSWD_OK; } else { rc = strcmp( salt, cr ) ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK; } } return rc; } static int chk_crypt( const struct berval *sc, const struct berval * passwd, const struct berval * cred, const char **text ) { unsigned int i; for( i=0; ibv_len; i++) { if(cred->bv_val[i] == '\0') { return LUTIL_PASSWD_ERR; /* NUL character in password */ } } if( cred->bv_val[i] != '\0' ) { return LUTIL_PASSWD_ERR; /* cred must behave like a string */ } if( passwd->bv_len < 2 ) { return LUTIL_PASSWD_ERR; /* passwd must be at least two characters long */ } for( i=0; ibv_len; i++) { if(passwd->bv_val[i] == '\0') { return LUTIL_PASSWD_ERR; /* NUL character in password */ } } if( passwd->bv_val[i] != '\0' ) { return LUTIL_PASSWD_ERR; /* passwd must behave like a string */ } return lutil_cryptptr( cred->bv_val, passwd->bv_val, NULL ); } # if defined( HAVE_GETPWNAM ) && defined( HAVE_STRUCT_PASSWD_PW_PASSWD ) static int chk_unix( const struct berval *sc, const struct berval * passwd, const struct berval * cred, const char **text ) { unsigned int i; char *pw; for( i=0; ibv_len; i++) { if(cred->bv_val[i] == '\0') { return LUTIL_PASSWD_ERR; /* NUL character in password */ } } if( cred->bv_val[i] != '\0' ) { return LUTIL_PASSWD_ERR; /* cred must behave like a string */ } for( i=0; ibv_len; i++) { if(passwd->bv_val[i] == '\0') { return LUTIL_PASSWD_ERR; /* NUL character in password */ } } if( passwd->bv_val[i] != '\0' ) { return LUTIL_PASSWD_ERR; /* passwd must behave like a string */ } { struct passwd *pwd = getpwnam(passwd->bv_val); if(pwd == NULL) { return LUTIL_PASSWD_ERR; /* not found */ } pw = pwd->pw_passwd; } # ifdef HAVE_GETSPNAM { struct spwd *spwd = getspnam(passwd->bv_val); if(spwd != NULL) { pw = spwd->sp_pwdp; } } # endif # ifdef HAVE_AIX_SECURITY { struct userpw *upw = getuserpw(passwd->bv_val); if (upw != NULL) { pw = upw->upw_passwd; } } # endif if( pw == NULL || pw[0] == '\0' || pw[1] == '\0' ) { /* password must must be at least two characters long */ return LUTIL_PASSWD_ERR; } return lutil_cryptptr( cred->bv_val, pw, NULL ); } # endif #endif /* PASSWORD GENERATION ROUTINES */ #ifdef LUTIL_SHA1_BYTES static int hash_ssha1( const struct berval *scheme, const struct berval *passwd, struct berval *hash, const char **text ) { lutil_SHA1_CTX SHA1context; unsigned char SHA1digest[LUTIL_SHA1_BYTES]; char saltdata[SALT_SIZE]; struct berval digest; struct berval salt; digest.bv_val = (char *) SHA1digest; digest.bv_len = sizeof(SHA1digest); salt.bv_val = saltdata; salt.bv_len = sizeof(saltdata); if( lutil_entropy( (unsigned char *) salt.bv_val, salt.bv_len) < 0 ) { return LUTIL_PASSWD_ERR; } lutil_SHA1Init( &SHA1context ); lutil_SHA1Update( &SHA1context, (const unsigned char *)passwd->bv_val, passwd->bv_len ); lutil_SHA1Update( &SHA1context, (const unsigned char *)salt.bv_val, salt.bv_len ); lutil_SHA1Final( SHA1digest, &SHA1context ); return lutil_passwd_string64( scheme, &digest, hash, &salt); } static int hash_sha1( const struct berval *scheme, const struct berval *passwd, struct berval *hash, const char **text ) { lutil_SHA1_CTX SHA1context; unsigned char SHA1digest[LUTIL_SHA1_BYTES]; struct berval digest; digest.bv_val = (char *) SHA1digest; digest.bv_len = sizeof(SHA1digest); lutil_SHA1Init( &SHA1context ); lutil_SHA1Update( &SHA1context, (const unsigned char *)passwd->bv_val, passwd->bv_len ); lutil_SHA1Final( SHA1digest, &SHA1context ); return lutil_passwd_string64( scheme, &digest, hash, NULL); } #endif static int hash_smd5( const struct berval *scheme, const struct berval *passwd, struct berval *hash, const char **text ) { lutil_MD5_CTX MD5context; unsigned char MD5digest[LUTIL_MD5_BYTES]; char saltdata[SALT_SIZE]; struct berval digest; struct berval salt; digest.bv_val = (char *) MD5digest; digest.bv_len = sizeof(MD5digest); salt.bv_val = saltdata; salt.bv_len = sizeof(saltdata); if( lutil_entropy( (unsigned char *) salt.bv_val, salt.bv_len) < 0 ) { return LUTIL_PASSWD_ERR; } lutil_MD5Init( &MD5context ); lutil_MD5Update( &MD5context, (const unsigned char *) passwd->bv_val, passwd->bv_len ); lutil_MD5Update( &MD5context, (const unsigned char *) salt.bv_val, salt.bv_len ); lutil_MD5Final( MD5digest, &MD5context ); return lutil_passwd_string64( scheme, &digest, hash, &salt ); } static int hash_md5( const struct berval *scheme, const struct berval *passwd, struct berval *hash, const char **text ) { lutil_MD5_CTX MD5context; unsigned char MD5digest[LUTIL_MD5_BYTES]; struct berval digest; digest.bv_val = (char *) MD5digest; digest.bv_len = sizeof(MD5digest); lutil_MD5Init( &MD5context ); lutil_MD5Update( &MD5context, (const unsigned char *) passwd->bv_val, passwd->bv_len ); lutil_MD5Final( MD5digest, &MD5context ); return lutil_passwd_string64( scheme, &digest, hash, NULL ); ; } #ifdef SLAPD_LMHASH static int hash_lanman( const struct berval *scheme, const struct berval *passwd, struct berval *hash, const char **text ) { ber_len_t i; char UcasePassword[15]; des_key key; des_context schedule; des_data_block StdText = "KGS!@#$%"; des_data_block PasswordHash1, PasswordHash2; char PasswordHash[33]; for( i=0; ibv_len; i++) { if(passwd->bv_val[i] == '\0') { return LUTIL_PASSWD_ERR; /* NUL character in password */ } } if( passwd->bv_val[i] != '\0' ) { return LUTIL_PASSWD_ERR; /* passwd must behave like a string */ } strncpy( UcasePassword, passwd->bv_val, 14 ); UcasePassword[14] = '\0'; ldap_pvt_str2upper( UcasePassword ); lmPasswd_to_key( UcasePassword, &key ); des_set_key_unchecked( &key, schedule ); des_ecb_encrypt( &StdText, &PasswordHash1, schedule , DES_ENCRYPT ); lmPasswd_to_key( &UcasePassword[7], &key ); des_set_key_unchecked( &key, schedule ); des_ecb_encrypt( &StdText, &PasswordHash2, schedule , DES_ENCRYPT ); sprintf( PasswordHash, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", PasswordHash1[0],PasswordHash1[1],PasswordHash1[2],PasswordHash1[3], PasswordHash1[4],PasswordHash1[5],PasswordHash1[6],PasswordHash1[7], PasswordHash2[0],PasswordHash2[1],PasswordHash2[2],PasswordHash2[3], PasswordHash2[4],PasswordHash2[5],PasswordHash2[6],PasswordHash2[7] ); hash->bv_val = PasswordHash; hash->bv_len = 32; return pw_string( scheme, hash ); } #endif /* SLAPD_LMHASH */ #ifdef SLAPD_CRYPT static int hash_crypt( const struct berval *scheme, const struct berval *passwd, struct berval *hash, const char **text ) { unsigned char salt[32]; /* salt suitable for most anything */ unsigned int i; char *save; int rc; for( i=0; ibv_len; i++) { if(passwd->bv_val[i] == '\0') { return LUTIL_PASSWD_ERR; /* NUL character in password */ } } if( passwd->bv_val[i] != '\0' ) { return LUTIL_PASSWD_ERR; /* passwd must behave like a string */ } if( lutil_entropy( salt, sizeof( salt ) ) < 0 ) { return LUTIL_PASSWD_ERR; } for( i=0; i< ( sizeof(salt) - 1 ); i++ ) { salt[i] = crypt64[ salt[i] % (sizeof(crypt64)-1) ]; } salt[sizeof( salt ) - 1 ] = '\0'; if( salt_format != NULL ) { /* copy the salt we made into entropy before snprintfing it back into the salt */ char entropy[sizeof(salt)]; strcpy( entropy, (char *) salt ); snprintf( (char *) salt, sizeof(entropy), salt_format, entropy ); } rc = lutil_cryptptr( passwd->bv_val, (char *) salt, &hash->bv_val ); if ( rc != LUTIL_PASSWD_OK ) return rc; if( hash->bv_val == NULL ) return -1; hash->bv_len = strlen( hash->bv_val ); save = hash->bv_val; if( hash->bv_len == 0 ) { rc = LUTIL_PASSWD_ERR; } else { rc = pw_string( scheme, hash ); } ber_memfree( save ); return rc; } #endif int lutil_salt_format(const char *format) { #ifdef SLAPD_CRYPT ber_memfree( salt_format ); salt_format = format != NULL ? ber_strdup( format ) : NULL; #endif return 0; } #ifdef SLAPD_CLEARTEXT static int hash_clear( const struct berval *scheme, const struct berval *passwd, struct berval *hash, const char **text ) { ber_dupbv( hash, (struct berval *)passwd ); return LUTIL_PASSWD_OK; } #endif openldap-2.4.42+dfsg/libraries/liblutil/entropy.c0000644000175000017500000000761212563404150020476 0ustar ryanryan/* entropy.c -- routines for providing pseudo-random data */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1999-2015 The OpenLDAP Foundation. * Portions Copyright 1999-2003 Kurt D. Zeilenga. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* This work was initially developed by Kurt D. Zeilenga for * inclusion in OpenLDAP Software based, in part, on publically * available works (as noted below). */ #include "portable.h" #include #include #include #ifdef HAVE_PROCESS_H #include #endif #include #include #include /* * lutil_entropy() provides nbytes of entropy in buf. * Quality offerred is suitable for one-time uses, such as "once" keys. * Values may not be suitable for multi-time uses. * * Note: Callers are encouraged to provide additional bytes of * of entropy in the buf argument. This information is used in * fallback mode to improve the quality of bytes returned. * * This routinue should be extended to support additional sources * of entropy. */ int lutil_entropy( unsigned char *buf, ber_len_t nbytes ) { if( nbytes == 0 ) return 0; #ifdef URANDOM_DEVICE #define URANDOM_NREADS 4 /* Linux and *BSD offer a urandom device */ { int rc, fd, n=0; fd = open( URANDOM_DEVICE, O_RDONLY ); if( fd < 0 ) return -1; do { rc = read( fd, buf, nbytes ); if( rc <= 0 ) break; buf+=rc; nbytes-=rc; if( ++n >= URANDOM_NREADS ) break; } while( nbytes > 0 ); close(fd); return nbytes > 0 ? -1 : 0; } #elif defined(PROV_RSA_FULL) { /* Not used since _WIN32_WINNT not set... */ HCRYPTPROV hProv = 0; /* Get handle to user default provider */ if(!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, 0)) { return -1; } /* Generate random initialization vector */ if(!CryptGenRandom(hProv, (DWORD) nbytes, (BYTE *) buf)) { return -1; } /* Release provider handle */ if(hProv != 0) CryptReleaseContext(hProv, 0); return 0; } #else { /* based upon Phil Karn's "practical randomness" idea * but implementation 100% OpenLDAP. So don't blame Phil. * * Worse case is that this is a MD5 hash of a counter, if * MD5 is a strong cryptographic hash, this should be fairly * resistant to attack */ /* * the caller may need to provide external synchronization OR * provide entropy (in buf) to ensure quality results as * access to this counter may not be atomic. */ static int counter = 0; ber_len_t n; struct rdata_s { int counter; unsigned char *buf; struct rdata_s *stack; pid_t pid; #ifdef HAVE_GETTIMEOFDAY struct timeval tv; #else time_t time; #endif unsigned long junk; /* purposely not initialized */ } rdata; /* make sure rdata differs for each process */ rdata.pid = getpid(); /* make sure rdata differs for each program */ rdata.buf = buf; rdata.stack = &rdata; for( n = 0; n < nbytes; n += 16 ) { struct lutil_MD5Context ctx; unsigned char digest[16]; /* poor resolution */ #ifdef HAVE_GETTIMEOFDAY (void) gettimeofday( &rdata.tv, NULL ); #else (void) time( &rdata.time ); #endif /* make sure rdata differs */ rdata.counter = ++counter; rdata.pid++; rdata.junk++; lutil_MD5Init( &ctx ); lutil_MD5Update( &ctx, (unsigned char *) &rdata, sizeof( rdata ) ); /* allow caller to provided additional entropy */ lutil_MD5Update( &ctx, buf, nbytes ); lutil_MD5Final( digest, &ctx ); AC_MEMCPY( &buf[n], digest, nbytes - n >= 16 ? 16 : nbytes - n ); } return 0; } #endif return -1; } openldap-2.4.42+dfsg/libraries/liblutil/meter.c0000644000175000017500000001755212563404150020116 0ustar ryanryan/* meter.c - lutil_meter meters */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright (c) 2009 by Emily Backes, Symas Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* ACKNOWLEDGEMENTS: * This work was initially developed by Emily Backes for inclusion * in OpenLDAP software. */ #include "portable.h" #include "lutil_meter.h" #include #include int lutil_time_string ( char *dest, int duration, int max_terms) { static const int time_div[] = {31556952, 604800, 86400, 3600, 60, 1, 0}; const int * time_divp = time_div; static const char * time_name_ch = "ywdhms"; const char * time_name_chp = time_name_ch; int term_count = 0; char *buf = dest; int time_quot; assert ( max_terms >= 2 ); /* room for "none" message */ if ( duration < 0 ) { *dest = '\0'; return 1; } if ( duration == 0 ) { strcpy( dest, "none" ); return 0; } while ( term_count < max_terms && duration > 0 ) { if (duration > *time_divp) { time_quot = duration / *time_divp; duration %= *time_divp; if (time_quot > 99) { return 1; } else { *(buf++) = time_quot / 10 + '0'; *(buf++) = time_quot % 10 + '0'; *(buf++) = *time_name_chp; ++term_count; } } if ( *(++time_divp) == 0) duration = 0; ++time_name_chp; } *buf = '\0'; return 0; } int lutil_get_now (double *now) { #ifdef HAVE_GETTIMEOFDAY struct timeval tv; assert( now ); gettimeofday( &tv, NULL ); *now = ((double) tv.tv_sec) + (((double) tv.tv_usec) / 1000000.0); return 0; #else time_t tm; assert( now ); time( &tm ); *now = (double) tm; return 0; #endif } int lutil_meter_open ( lutil_meter_t *meter, const lutil_meter_display_t *display, const lutil_meter_estimator_t *estimator, size_t goal_value) { int rc; assert( meter != NULL ); assert( display != NULL ); assert( estimator != NULL ); if (goal_value < 1) return -1; memset( (void*) meter, 0, sizeof( lutil_meter_t )); meter->display = display; meter->estimator = estimator; lutil_get_now( &meter->start_time ); meter->last_update = meter->start_time; meter->goal_value = goal_value; meter->last_position = 0; rc = meter->display->display_open( &meter->display_data ); if( rc != 0 ) return rc; rc = meter->estimator->estimator_open( &meter->estimator_data ); if( rc != 0 ) { meter->display->display_close( &meter->display_data ); return rc; } return 0; } int lutil_meter_update ( lutil_meter_t *meter, size_t position, int force) { static const double display_rate = 0.5; double frac, cycle_length, speed, now; time_t remaining_time, elapsed; int rc; assert( meter != NULL ); lutil_get_now( &now ); if ( !force && now - meter->last_update < display_rate ) return 0; frac = ((double)position) / ((double) meter->goal_value); elapsed = now - meter->start_time; if (frac <= 0.0) return 0; if (frac >= 1.0) { rc = meter->display->display_update( &meter->display_data, 1.0, 0, (time_t) elapsed, ((double)position) / elapsed); } else { rc = meter->estimator->estimator_update( &meter->estimator_data, meter->start_time, frac, &remaining_time ); if ( rc == 0 ) { cycle_length = now - meter->last_update; speed = cycle_length > 0.0 ? ((double)(position - meter->last_position)) / cycle_length : 0.0; rc = meter->display->display_update( &meter->display_data, frac, remaining_time, (time_t) elapsed, speed); if ( rc == 0 ) { meter->last_update = now; meter->last_position = position; } } } return rc; } int lutil_meter_close (lutil_meter_t *meter) { meter->estimator->estimator_close( &meter->estimator_data ); meter->display->display_close( &meter->display_data ); return 0; } /* Default display and estimator */ typedef struct { int buffer_length; char * buffer; int need_eol; int phase; FILE *output; } text_display_state_t; static int text_open (void ** display_datap) { static const int default_buffer_length = 81; text_display_state_t *data; assert( display_datap != NULL ); data = calloc( 1, sizeof( text_display_state_t )); assert( data != NULL ); data->buffer_length = default_buffer_length; data->buffer = calloc( 1, default_buffer_length ); assert( data->buffer != NULL ); data->output = stderr; *display_datap = data; return 0; } static int text_update ( void **display_datap, double frac, time_t remaining_time, time_t elapsed, double byte_rate) { text_display_state_t *data; char *buf, *buf_end; assert( display_datap != NULL ); assert( *display_datap != NULL ); data = (text_display_state_t*) *display_datap; if ( data->output == NULL ) return 1; buf = data->buffer; buf_end = buf + data->buffer_length - 1; /* |#################### 100.00% eta 1d19h elapsed 23w 7d23h15m12s spd nnnn.n M/s */ { /* spinner */ static const int phase_mod = 8; static const char phase_char[] = "_.-*\"*-."; *buf++ = phase_char[data->phase % phase_mod]; data->phase++; } { /* bar */ static const int bar_length = 20; static const double bar_lengthd = 20.0; static const char fill_char = '#'; static const char blank_char = ' '; char *bar_end = buf + bar_length; char *bar_pos = frac < 0.0 ? buf : frac < 1.0 ? buf + (int) (bar_lengthd * frac) : bar_end; assert( (buf_end - buf) > bar_length ); while ( buf < bar_end ) { *buf = buf < bar_pos ? fill_char : blank_char; ++buf; } } { /* percent */ (void) snprintf( buf, buf_end-buf, "%7.2f%%", 100.0*frac ); buf += 8; } { /* eta and elapsed */ char time_buffer[19]; int rc; rc = lutil_time_string( time_buffer, remaining_time, 2); if (rc == 0) snprintf( buf, buf_end-buf, " eta %6s", time_buffer ); buf += 5+6; rc = lutil_time_string( time_buffer, elapsed, 5); if (rc == 0) snprintf( buf, buf_end-buf, " elapsed %15s", time_buffer ); buf += 9+15; } { /* speed */ static const char prefixes[] = " kMGTPEZY"; const char *prefix_chp = prefixes; while (*prefix_chp && byte_rate >= 1024.0) { byte_rate /= 1024.0; ++prefix_chp; } if ( byte_rate >= 1024.0 ) { snprintf( buf, buf_end-buf, " fast!" ); buf += 6; } else { snprintf( buf, buf_end-buf, " spd %5.1f %c/s", byte_rate, *prefix_chp); buf += 5+6+4; } } (void) fprintf( data->output, "\r%-79s", data->buffer ); data->need_eol = 1; return 0; } static int text_close (void ** display_datap) { text_display_state_t *data; if (display_datap) { if (*display_datap) { data = (text_display_state_t*) *display_datap; if (data->output && data->need_eol) fputs ("\n", data->output); if (data->buffer) free( data->buffer ); free( data ); } *display_datap = NULL; } return 0; } static int null_open_close (void **datap) { assert( datap ); *datap = NULL; return 0; } static int linear_update ( void **estimator_datap, double start, double frac, time_t *remaining) { double now; double elapsed; assert( estimator_datap != NULL ); assert( *estimator_datap == NULL ); assert( start > 0.0 ); assert( frac >= 0.0 ); assert( frac <= 1.0 ); assert( remaining != NULL ); lutil_get_now( &now ); elapsed = now-start; assert( elapsed >= 0.0 ); if ( frac == 0.0 ) { return 1; } else if ( frac >= 1.0 ) { *remaining = 0; return 0; } else { *remaining = (time_t) (elapsed/frac-elapsed+0.5); return 0; } } const lutil_meter_display_t lutil_meter_text_display = { text_open, text_update, text_close }; const lutil_meter_estimator_t lutil_meter_linear_estimator = { null_open_close, linear_update, null_open_close }; openldap-2.4.42+dfsg/libraries/liblutil/utils.c0000644000175000017500000004547712563404150020151 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #include "portable.h" #include #include #include #include #include #include #include #include #include #ifdef HAVE_IO_H #include #endif #ifdef HAVE_FCNTL_H #include #endif #ifdef _WIN32 #include #endif #include "lutil.h" #include "ldap_defaults.h" #include "ldap_pvt.h" #include "lber_pvt.h" #ifdef HAVE_EBCDIC int _trans_argv = 1; #endif #ifdef _WIN32 /* Some Windows versions accept both forward and backslashes in * directory paths, but we always use backslashes when generating * and parsing... */ void lutil_slashpath( char *path ) { char *c, *p; p = path; while (( c=strchr( p, '/' ))) { *c++ = '\\'; p = c; } } #endif char* lutil_progname( const char* name, int argc, char *argv[] ) { char *progname; if(argc == 0) { return (char *)name; } #ifdef HAVE_EBCDIC if (_trans_argv) { int i; for (i=0; i 4 && strcasecmp( &progname[len - 4], ".exe" ) == 0 ) progname[len - 4] = '\0'; } #endif return progname; } #if 0 size_t lutil_gentime( char *s, size_t smax, const struct tm *tm ) { size_t ret; #ifdef HAVE_EBCDIC /* We've been compiling in ASCII so far, but we want EBCDIC now since * strftime only understands EBCDIC input. */ #pragma convlit(suspend) #endif ret = strftime( s, smax, "%Y%m%d%H%M%SZ", tm ); #ifdef HAVE_EBCDIC #pragma convlit(resume) __etoa( s ); #endif return ret; } #endif size_t lutil_localtime( char *s, size_t smax, const struct tm *tm, long delta ) { size_t ret; char *p; if ( smax < 16 ) { /* YYYYmmddHHMMSSZ */ return 0; } #ifdef HAVE_EBCDIC /* We've been compiling in ASCII so far, but we want EBCDIC now since * strftime only understands EBCDIC input. */ #pragma convlit(suspend) #endif ret = strftime( s, smax, "%Y%m%d%H%M%SZ", tm ); #ifdef HAVE_EBCDIC #pragma convlit(resume) __etoa( s ); #endif if ( delta == 0 || ret == 0 ) { return ret; } if ( smax < 20 ) { /* YYYYmmddHHMMSS+HHMM */ return 0; } p = s + 14; if ( delta < 0 ) { p[ 0 ] = '-'; delta = -delta; } else { p[ 0 ] = '+'; } p++; snprintf( p, smax - 15, "%02ld%02ld", delta / 3600, ( delta % 3600 ) / 60 ); return ret + 4; } int lutil_tm2time( struct lutil_tm *tm, struct lutil_timet *tt ) { static int moffset[12] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; int sec; tt->tt_usec = tm->tm_usec; /* special case 0000/01/01+00:00:00 is returned as zero */ if ( tm->tm_year == -1900 && tm->tm_mon == 0 && tm->tm_mday == 1 && tm->tm_hour == 0 && tm->tm_min == 0 && tm->tm_sec == 0 ) { tt->tt_sec = 0; tt->tt_gsec = 0; return 0; } /* tm->tm_year is years since 1900 */ /* calculate days from years since 1970 (epoch) */ tt->tt_sec = tm->tm_year - 70; tt->tt_sec *= 365L; /* count leap days in preceding years */ tt->tt_sec += ((tm->tm_year -69) >> 2); /* calculate days from months */ tt->tt_sec += moffset[tm->tm_mon]; /* add in this year's leap day, if any */ if (((tm->tm_year & 3) == 0) && (tm->tm_mon > 1)) { tt->tt_sec ++; } /* add in days in this month */ tt->tt_sec += (tm->tm_mday - 1); /* this function can handle a range of about 17408 years... */ /* 86400 seconds in a day, divided by 128 = 675 */ tt->tt_sec *= 675; /* move high 7 bits into tt_gsec */ tt->tt_gsec = tt->tt_sec >> 25; tt->tt_sec -= tt->tt_gsec << 25; /* get hours */ sec = tm->tm_hour; /* convert to minutes */ sec *= 60L; sec += tm->tm_min; /* convert to seconds */ sec *= 60L; sec += tm->tm_sec; /* add remaining seconds */ tt->tt_sec <<= 7; tt->tt_sec += sec; /* return success */ return 0; } int lutil_parsetime( char *atm, struct lutil_tm *tm ) { while (atm && tm) { char *ptr = atm; unsigned i, fracs; /* Is the stamp reasonably long? */ for (i=0; isdigit((unsigned char) atm[i]); i++); if (i < sizeof("00000101000000")-1) break; /* * parse the time into a struct tm */ /* 4 digit year to year - 1900 */ tm->tm_year = *ptr++ - '0'; tm->tm_year *= 10; tm->tm_year += *ptr++ - '0'; tm->tm_year *= 10; tm->tm_year += *ptr++ - '0'; tm->tm_year *= 10; tm->tm_year += *ptr++ - '0'; tm->tm_year -= 1900; /* month 01-12 to 0-11 */ tm->tm_mon = *ptr++ - '0'; tm->tm_mon *=10; tm->tm_mon += *ptr++ - '0'; if (tm->tm_mon < 1 || tm->tm_mon > 12) break; tm->tm_mon--; /* day of month 01-31 */ tm->tm_mday = *ptr++ - '0'; tm->tm_mday *=10; tm->tm_mday += *ptr++ - '0'; if (tm->tm_mday < 1 || tm->tm_mday > 31) break; /* Hour 00-23 */ tm->tm_hour = *ptr++ - '0'; tm->tm_hour *=10; tm->tm_hour += *ptr++ - '0'; if (tm->tm_hour < 0 || tm->tm_hour > 23) break; /* Minute 00-59 */ tm->tm_min = *ptr++ - '0'; tm->tm_min *=10; tm->tm_min += *ptr++ - '0'; if (tm->tm_min < 0 || tm->tm_min > 59) break; /* Second 00-61 */ tm->tm_sec = *ptr++ - '0'; tm->tm_sec *=10; tm->tm_sec += *ptr++ - '0'; if (tm->tm_sec < 0 || tm->tm_sec > 61) break; /* Fractions of seconds */ if ( *ptr == '.' ) { ptr++; for (i = 0, fracs = 0; isdigit((unsigned char) *ptr); ) { i*=10; i+= *ptr++ - '0'; fracs++; } tm->tm_usec = i; if (i) { for (i = fracs; i<6; i++) tm->tm_usec *= 10; } } /* Must be UTC */ if (*ptr != 'Z') break; return 0; } return -1; } /* strcopy is like strcpy except it returns a pointer to the trailing NUL of * the result string. This allows fast construction of catenated strings * without the overhead of strlen/strcat. */ char * lutil_strcopy( char *a, const char *b ) { if (!a || !b) return a; while ((*a++ = *b++)) ; return a-1; } /* strncopy is like strcpy except it returns a pointer to the trailing NUL of * the result string. This allows fast construction of catenated strings * without the overhead of strlen/strcat. */ char * lutil_strncopy( char *a, const char *b, size_t n ) { if (!a || !b || n == 0) return a; while ((*a++ = *b++) && n-- > 0) ; return a-1; } /* memcopy is like memcpy except it returns a pointer to the byte past * the end of the result buffer, set to NULL. This allows fast construction * of catenated buffers. Provided for API consistency with lutil_str*copy(). */ char * lutil_memcopy( char *a, const char *b, size_t n ) { AC_MEMCPY(a, b, n); return a + n; } #ifndef HAVE_MKSTEMP int mkstemp( char * template ) { #ifdef HAVE_MKTEMP return open ( mktemp ( template ), O_RDWR|O_CREAT|O_EXCL, 0600 ); #else return -1; #endif } #endif #ifdef _MSC_VER /* Equivalent of MS CRT's _dosmaperr(). * @param lastError[in] Result of GetLastError(). */ static errno_t win2errno(DWORD lastError) { const struct { DWORD windows_code; errno_t errno_code; } WIN2ERRNO_TABLE[] = { { ERROR_SUCCESS, 0 }, { ERROR_FILE_NOT_FOUND, ENOENT }, { ERROR_PATH_NOT_FOUND, ENOENT }, { ERROR_TOO_MANY_OPEN_FILES, EMFILE }, { ERROR_ACCESS_DENIED, EACCES }, { ERROR_INVALID_HANDLE, EBADF }, { ERROR_NOT_ENOUGH_MEMORY, ENOMEM }, { ERROR_LOCK_VIOLATION, EACCES }, { ERROR_FILE_EXISTS, EEXIST }, { ERROR_INVALID_PARAMETER, EINVAL }, { ERROR_FILENAME_EXCED_RANGE, ENAMETOOLONG }, }; const unsigned int WIN2ERRNO_TABLE_SIZE = sizeof(WIN2ERRNO_TABLE) / sizeof(WIN2ERRNO_TABLE[0]); const errno_t DEFAULT_ERRNO_ERROR = -1; unsigned int i; for (i = 0; i < WIN2ERRNO_TABLE_SIZE; ++i) { if (WIN2ERRNO_TABLE[i].windows_code == lastError) { return WIN2ERRNO_TABLE[i].errno_code; } } return DEFAULT_ERRNO_ERROR; } struct dirent { char *d_name; }; typedef struct DIR { HANDLE dir; struct dirent data; int first; char buf[MAX_PATH+1]; } DIR; DIR *opendir( char *path ) { char tmp[32768]; int len = strlen(path); DIR *d; HANDLE h; WIN32_FIND_DATA data; if (len+3 >= sizeof(tmp)) { errno = ENAMETOOLONG; return NULL; } strcpy(tmp, path); tmp[len++] = '\\'; tmp[len++] = '*'; tmp[len] = '\0'; h = FindFirstFile( tmp, &data ); if ( h == INVALID_HANDLE_VALUE ) { errno = win2errno( GetLastError()); return NULL; } d = ber_memalloc( sizeof(DIR) ); if ( !d ) return NULL; d->dir = h; d->data.d_name = d->buf; d->first = 1; strcpy(d->data.d_name, data.cFileName); return d; } struct dirent *readdir(DIR *dir) { WIN32_FIND_DATA data; if (dir->first) { dir->first = 0; } else { if (!FindNextFile(dir->dir, &data)) return NULL; strcpy(dir->data.d_name, data.cFileName); } return &dir->data; } int closedir(DIR *dir) { (void) FindClose(dir->dir); ber_memfree(dir); return 0; } #endif /* * Memory Reverse Search */ void * (lutil_memrchr)(const void *b, int c, size_t n) { if (n != 0) { const unsigned char *s, *bb = b, cc = c; for ( s = bb + n; s > bb; ) { if ( *--s == cc ) { return (void *) s; } } } return NULL; } int lutil_atoix( int *v, const char *s, int x ) { char *next; long i; assert( s != NULL ); assert( v != NULL ); i = strtol( s, &next, x ); if ( next == s || next[ 0 ] != '\0' ) { return -1; } if ( (long)(int)i != i ) { return 1; } *v = (int)i; return 0; } int lutil_atoux( unsigned *v, const char *s, int x ) { char *next; unsigned long u; assert( s != NULL ); assert( v != NULL ); /* strtoul() has an odd interface */ if ( s[ 0 ] == '-' ) { return -1; } u = strtoul( s, &next, x ); if ( next == s || next[ 0 ] != '\0' ) { return -1; } if ( (unsigned long)(unsigned)u != u ) { return 1; } *v = u; return 0; } int lutil_atolx( long *v, const char *s, int x ) { char *next; long l; int save_errno; assert( s != NULL ); assert( v != NULL ); if ( isspace( s[ 0 ] ) ) { return -1; } errno = 0; l = strtol( s, &next, x ); save_errno = errno; if ( next == s || next[ 0 ] != '\0' ) { return -1; } if ( ( l == LONG_MIN || l == LONG_MAX ) && save_errno != 0 ) { return -1; } *v = l; return 0; } int lutil_atoulx( unsigned long *v, const char *s, int x ) { char *next; unsigned long ul; int save_errno; assert( s != NULL ); assert( v != NULL ); /* strtoul() has an odd interface */ if ( s[ 0 ] == '-' || isspace( s[ 0 ] ) ) { return -1; } errno = 0; ul = strtoul( s, &next, x ); save_errno = errno; if ( next == s || next[ 0 ] != '\0' ) { return -1; } if ( ( ul == 0 || ul == ULONG_MAX ) && save_errno != 0 ) { return -1; } *v = ul; return 0; } #ifdef HAVE_LONG_LONG #if defined(HAVE_STRTOLL) || defined(HAVE_STRTOQ) int lutil_atollx( long long *v, const char *s, int x ) { char *next; long long ll; int save_errno; assert( s != NULL ); assert( v != NULL ); if ( isspace( s[ 0 ] ) ) { return -1; } errno = 0; #ifdef HAVE_STRTOLL ll = strtoll( s, &next, x ); #else /* HAVE_STRTOQ */ ll = (unsigned long long)strtoq( s, &next, x ); #endif /* HAVE_STRTOQ */ save_errno = errno; if ( next == s || next[ 0 ] != '\0' ) { return -1; } /* LLONG_MIN, LLONG_MAX are C99 only */ #if defined (LLONG_MIN) && defined(LLONG_MAX) if ( ( ll == LLONG_MIN || ll == LLONG_MAX ) && save_errno != 0 ) { return -1; } #endif /* LLONG_MIN && LLONG_MAX */ *v = ll; return 0; } #endif /* HAVE_STRTOLL || HAVE_STRTOQ */ #if defined(HAVE_STRTOULL) || defined(HAVE_STRTOUQ) int lutil_atoullx( unsigned long long *v, const char *s, int x ) { char *next; unsigned long long ull; int save_errno; assert( s != NULL ); assert( v != NULL ); /* strtoull() has an odd interface */ if ( s[ 0 ] == '-' || isspace( s[ 0 ] ) ) { return -1; } errno = 0; #ifdef HAVE_STRTOULL ull = strtoull( s, &next, x ); #else /* HAVE_STRTOUQ */ ull = (unsigned long long)strtouq( s, &next, x ); #endif /* HAVE_STRTOUQ */ save_errno = errno; if ( next == s || next[ 0 ] != '\0' ) { return -1; } /* ULLONG_MAX is C99 only */ #if defined(ULLONG_MAX) if ( ( ull == 0 || ull == ULLONG_MAX ) && save_errno != 0 ) { return -1; } #endif /* ULLONG_MAX */ *v = ull; return 0; } #endif /* HAVE_STRTOULL || HAVE_STRTOUQ */ #endif /* HAVE_LONG_LONG */ /* Multiply an integer by 100000000 and add new */ typedef struct lutil_int_decnum { unsigned char *buf; int bufsiz; int beg; int len; } lutil_int_decnum; #define FACTOR1 (100000000&0xffff) #define FACTOR2 (100000000>>16) static void scale( int new, lutil_int_decnum *prev, unsigned char *tmp ) { int i, j; unsigned char *in = prev->buf+prev->beg; unsigned int part; unsigned char *out = tmp + prev->bufsiz - prev->len; memset( tmp, 0, prev->bufsiz ); if ( prev->len ) { for ( i = prev->len-1; i>=0; i-- ) { part = in[i] * FACTOR1; for ( j = i; part; j-- ) { part += out[j]; out[j] = part & 0xff; part >>= 8; } part = in[i] * FACTOR2; for ( j = i-2; part; j-- ) { part += out[j]; out[j] = part & 0xff; part >>= 8; } } j++; prev->beg += j; prev->len -= j; } out = tmp + prev->bufsiz; i = 0; do { i--; new += out[i]; out[i] = new & 0xff; new >>= 8; } while ( new ); i = -i; if ( prev->len < i ) { prev->beg = prev->bufsiz - i; prev->len = i; } AC_MEMCPY( prev->buf+prev->beg, tmp+prev->beg, prev->len ); } /* Convert unlimited length decimal or hex string to binary. * Output buffer must be provided, bv_len must indicate buffer size * Hex input can be "0x1234" or "'1234'H" * * Note: High bit of binary form is always the sign bit. If the number * is supposed to be positive but has the high bit set, a zero byte * is prepended. It is assumed that this has already been handled on * any hex input. */ int lutil_str2bin( struct berval *in, struct berval *out, void *ctx ) { char *pin, *pout; char *end; int i, chunk, len, rc = 0, hex = 0; if ( !out || !out->bv_val || out->bv_len < in->bv_len ) return -1; pout = out->bv_val; /* Leading "0x" for hex input */ if ( in->bv_len > 2 && in->bv_val[0] == '0' && ( in->bv_val[1] == 'x' || in->bv_val[1] == 'X' ) ) { len = in->bv_len - 2; pin = in->bv_val + 2; hex = 1; } else if ( in->bv_len > 3 && in->bv_val[0] == '\'' && in->bv_val[in->bv_len-2] == '\'' && in->bv_val[in->bv_len-1] == 'H' ) { len = in->bv_len - 3; pin = in->bv_val + 1; hex = 1; } if ( hex ) { #define HEXMAX (2 * sizeof(long)) unsigned long l; char tbuf[HEXMAX+1]; /* Convert a longword at a time, but handle leading * odd bytes first */ chunk = len % HEXMAX; if ( !chunk ) chunk = HEXMAX; while ( len ) { int ochunk; memcpy( tbuf, pin, chunk ); tbuf[chunk] = '\0'; errno = 0; l = strtoul( tbuf, &end, 16 ); if ( errno ) return -1; ochunk = (chunk + 1)/2; for ( i = ochunk - 1; i >= 0; i-- ) { pout[i] = l & 0xff; l >>= 8; } pin += chunk; pout += ochunk; len -= chunk; chunk = HEXMAX; } out->bv_len = pout - out->bv_val; } else { /* Decimal */ #define DECMAX 8 /* 8 digits at a time */ char tmpbuf[64], *tmp; lutil_int_decnum num; int neg = 0; long l; char tbuf[DECMAX+1]; len = in->bv_len; pin = in->bv_val; num.buf = (unsigned char *)out->bv_val; num.bufsiz = out->bv_len; num.beg = num.bufsiz-1; num.len = 0; if ( pin[0] == '-' ) { neg = 0xff; len--; pin++; } /* tmp must be at least as large as outbuf */ if ( out->bv_len > sizeof(tmpbuf)) { tmp = ber_memalloc_x( out->bv_len, ctx ); } else { tmp = tmpbuf; } chunk = len & (DECMAX-1); if ( !chunk ) chunk = DECMAX; while ( len ) { memcpy( tbuf, pin, chunk ); tbuf[chunk] = '\0'; errno = 0; l = strtol( tbuf, &end, 10 ); if ( errno ) { rc = -1; goto decfail; } scale( l, &num, (unsigned char *)tmp ); pin += chunk; len -= chunk; chunk = DECMAX; } /* Negate the result */ if ( neg ) { unsigned char *ptr; ptr = num.buf+num.beg; /* flip all bits */ for ( i=0; ibv_len = num.len; decfail: if ( tmp != tmpbuf ) { ber_memfree_x( tmp, ctx ); } } return rc; } static char time_unit[] = "dhms"; /* Used to parse and unparse time intervals, not timestamps */ int lutil_parse_time( const char *in, unsigned long *tp ) { unsigned long t = 0; char *s, *next; int sofar = -1, scale[] = { 86400, 3600, 60, 1 }; *tp = 0; for ( s = (char *)in; s[ 0 ] != '\0'; ) { unsigned long u; char *what; /* strtoul() has an odd interface */ if ( s[ 0 ] == '-' ) { return -1; } u = strtoul( s, &next, 10 ); if ( next == s ) { return -1; } if ( next[ 0 ] == '\0' ) { /* assume seconds */ t += u; break; } what = strchr( time_unit, next[ 0 ] ); if ( what == NULL ) { return -1; } if ( what - time_unit <= sofar ) { return -1; } sofar = what - time_unit; t += u * scale[ sofar ]; s = &next[ 1 ]; } *tp = t; return 0; } int lutil_unparse_time( char *buf, size_t buflen, unsigned long t ) { int len, i; unsigned long v[ 4 ]; char *ptr = buf; v[ 0 ] = t/86400; v[ 1 ] = (t%86400)/3600; v[ 2 ] = (t%3600)/60; v[ 3 ] = t%60; for ( i = 0; i < 4; i++ ) { if ( v[i] > 0 || ( i == 3 && ptr == buf ) ) { len = snprintf( ptr, buflen, "%lu%c", v[ i ], time_unit[ i ] ); if ( len < 0 || (unsigned)len >= buflen ) { return -1; } buflen -= len; ptr += len; } } return 0; } /* * formatted print to string * * - if return code < 0, the error code returned by vsnprintf(3) is returned * * - if return code > 0, the buffer was not long enough; * - if next is not NULL, *next will be set to buf + bufsize - 1 * - if len is not NULL, *len will contain the required buffer length * * - if return code == 0, the buffer was long enough; * - if next is not NULL, *next will point to the end of the string printed so far * - if len is not NULL, *len will contain the length of the string printed so far */ int lutil_snprintf( char *buf, ber_len_t bufsize, char **next, ber_len_t *len, LDAP_CONST char *fmt, ... ) { va_list ap; int ret; assert( buf != NULL ); assert( bufsize > 0 ); assert( fmt != NULL ); va_start( ap, fmt ); ret = vsnprintf( buf, bufsize, fmt, ap ); va_end( ap ); if ( ret < 0 ) { return ret; } if ( len ) { *len = ret; } if ( (unsigned) ret >= bufsize ) { if ( next ) { *next = &buf[ bufsize - 1 ]; } return 1; } if ( next ) { *next = &buf[ ret ]; } return 0; } openldap-2.4.42+dfsg/libraries/liblutil/passfile.c0000644000175000017500000000427112563404150020602 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #include "portable.h" #include #include #include #include #ifdef HAVE_FSTAT #include #include #endif /* HAVE_FSTAT */ #include #include /* Get a password from a file. */ int lutil_get_filed_password( const char *filename, struct berval *passwd ) { size_t nread, nleft, nr; FILE *f = fopen( filename, "r" ); if( f == NULL ) { perror( filename ); return -1; } passwd->bv_val = NULL; passwd->bv_len = 4096; #ifdef HAVE_FSTAT { struct stat sb; if ( fstat( fileno( f ), &sb ) == 0 ) { if( sb.st_mode & 006 ) { fprintf( stderr, _("Warning: Password file %s" " is publicly readable/writeable\n"), filename ); } if ( sb.st_size ) passwd->bv_len = sb.st_size; } } #endif /* HAVE_FSTAT */ passwd->bv_val = (char *) ber_memalloc( passwd->bv_len + 1 ); if( passwd->bv_val == NULL ) { perror( filename ); fclose( f ); return -1; } nread = 0; nleft = passwd->bv_len; do { if( nleft == 0 ) { /* double the buffer size */ char *p = (char *) ber_memrealloc( passwd->bv_val, 2 * passwd->bv_len + 1 ); if( p == NULL ) { ber_memfree( passwd->bv_val ); passwd->bv_val = NULL; passwd->bv_len = 0; fclose( f ); return -1; } nleft = passwd->bv_len; passwd->bv_len *= 2; passwd->bv_val = p; } nr = fread( &passwd->bv_val[nread], 1, nleft, f ); if( nr < nleft && ferror( f ) ) { ber_memfree( passwd->bv_val ); passwd->bv_val = NULL; passwd->bv_len = 0; fclose( f ); return -1; } nread += nr; nleft -= nr; } while ( !feof(f) ); passwd->bv_len = nread; passwd->bv_val[nread] = '\0'; fclose( f ); return 0; } openldap-2.4.42+dfsg/libraries/liblutil/detach.c0000644000175000017500000000601512563404150020222 0ustar ryanryan/* detach.c -- routines to daemonize a process */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* * Copyright (c) 1990, 1994 Regents of the University of Michigan. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of Michigan at Ann Arbor. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. */ /* This work was originally developed by the University of Michigan * and distributed as part of U-MICH LDAP. */ #include "portable.h" #include #include #include #include #include #include #include #ifdef HAVE_SYS_FILE_H #include #endif #ifdef HAVE_SYS_IOCTL_H #include #endif #include "lutil.h" int lutil_detach( int debug, int do_close ) { int i, sd, nbits, pid; #ifdef HAVE_SYSCONF nbits = sysconf( _SC_OPEN_MAX ); #elif defined(HAVE_GETDTABLESIZE) nbits = getdtablesize(); #else nbits = FD_SETSIZE; #endif #ifdef FD_SETSIZE if ( nbits > FD_SETSIZE ) { nbits = FD_SETSIZE; } #endif /* FD_SETSIZE */ if ( debug == 0 ) { for ( i = 0; i < 5; i++ ) { #ifdef HAVE_THR pid = fork1(); #else pid = fork(); #endif switch ( pid ) { case -1: sleep( 5 ); continue; case 0: break; default: return pid; } break; } if ( (sd = open( "/dev/null", O_RDWR )) == -1 && (sd = open( "/dev/null", O_RDONLY )) == -1 && /* Panic -- open *something* */ (sd = open( "/", O_RDONLY )) == -1 ) { perror("/dev/null"); } else { /* redirect stdin, stdout, stderr to /dev/null */ dup2( sd, STDIN_FILENO ); dup2( sd, STDOUT_FILENO ); dup2( sd, STDERR_FILENO ); switch( sd ) { default: close( sd ); case STDIN_FILENO: case STDOUT_FILENO: case STDERR_FILENO: break; } } if ( do_close ) { /* close everything else */ for ( i = 0; i < nbits; i++ ) { if( i != STDIN_FILENO && i != STDOUT_FILENO && i != STDERR_FILENO ) { close( i ); } } } #ifdef CHDIR_TO_ROOT (void) chdir( "/" ); #endif #ifdef HAVE_SETSID (void) setsid(); #elif defined(TIOCNOTTY) if ( (sd = open( "/dev/tty", O_RDWR )) != -1 ) { (void) ioctl( sd, TIOCNOTTY, NULL ); (void) close( sd ); } #endif } #ifdef SIGPIPE (void) SIGNAL( SIGPIPE, SIG_IGN ); #endif return 0; } openldap-2.4.42+dfsg/libraries/liblutil/sockpair.c0000644000175000017500000000371412563404150020610 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #include "portable.h" #include #include #include /* Return a pair of socket descriptors that are connected to each other. * The returned descriptors are suitable for use with select(). The two * descriptors may or may not be identical; the function may return * the same descriptor number in both slots. It is guaranteed that * data written on sds[1] will be readable on sds[0]. The returned * descriptors may be datagram oriented, so data should be written * in reasonably small pieces and read all at once. On Unix systems * this function is best implemented using a single pipe() call. */ int lutil_pair( ber_socket_t sds[2] ) { #ifdef USE_PIPE return pipe( sds ); #else struct sockaddr_in si; int rc; ber_socklen_t len = sizeof(si); ber_socket_t sd; sd = socket( AF_INET, SOCK_DGRAM, 0 ); if ( sd == AC_SOCKET_INVALID ) { return sd; } (void) memset( (void*) &si, '\0', len ); si.sin_family = AF_INET; si.sin_port = 0; si.sin_addr.s_addr = htonl( INADDR_LOOPBACK ); rc = bind( sd, (struct sockaddr *)&si, len ); if ( rc == AC_SOCKET_ERROR ) { tcp_close(sd); return rc; } rc = getsockname( sd, (struct sockaddr *)&si, &len ); if ( rc == AC_SOCKET_ERROR ) { tcp_close(sd); return rc; } rc = connect( sd, (struct sockaddr *)&si, len ); if ( rc == AC_SOCKET_ERROR ) { tcp_close(sd); return rc; } sds[0] = sd; #if !HAVE_WINSOCK sds[1] = dup( sds[0] ); #else sds[1] = sds[0]; #endif return 0; #endif } openldap-2.4.42+dfsg/libraries/liblutil/slapdmsg.bin0000644000175000017500000000016412563404150021131 0ustar ryanryan@@DOpenLDAP service started. debuglevel=%1, conffile=%2, urls=%3 OpenLDAP service stopped. openldap-2.4.42+dfsg/libraries/liblutil/getopt.c0000644000175000017500000000537112563404150020300 0ustar ryanryan/* getopt.c -- replacement getopt(3) routines */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * Portions Copyright 1998-2003 Kurt D. Zeilenga. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* This work is based upon the public-domain getopt(3) routines * developed by AT&T. Modified by Kurt D. Zeilenga for inclusion * into OpenLDAP Software. Significant contributors include: * Howard Chu */ #include "portable.h" #ifndef HAVE_GETOPT #include #include #include #ifdef HAVE_IO_H #include #endif #include "lutil.h" #ifndef STDERR_FILENO #define STDERR_FILENO 2 #endif int opterr = 1; int optind = 1; int optopt; char * optarg; #ifdef HAVE_EBCDIC extern int _trans_argv; #endif static void ERR (char * const argv[], const char * s, char c) { #ifdef DF_TRACE_DEBUG printf("DF_TRACE_DEBUG: static void ERR () in getopt.c\n"); #endif if (opterr) { char *ptr, outbuf[4096]; ptr = lutil_strncopy(outbuf, argv[0], sizeof(outbuf) - 2); ptr = lutil_strncopy(ptr, s, sizeof(outbuf)-2 -(ptr-outbuf)); *ptr++ = c; *ptr++ = '\n'; #ifdef HAVE_EBCDIC __atoe_l(outbuf, ptr - outbuf); #endif (void) write(STDERR_FILENO,outbuf,ptr - outbuf); } } int getopt (int argc, char * const argv [], const char * opts) { static int sp = 1, error = (int) '?'; static char sw = '-', eos = '\0', arg = ':'; register char c, * cp; #ifdef DF_TRACE_DEBUG printf("DF_TRACE_DEBUG: int getopt () in getopt.c\n"); #endif #ifdef HAVE_EBCDIC if (_trans_argv) { int i; for (i=0; i= argc || argv[optind][0] != sw || argv[optind][1] == eos) return EOF; else if (strcmp(argv[optind],"--") == 0) { optind++; return EOF; } } c = argv[optind][sp]; optopt = (int) c; if (c == arg || (cp = strchr(opts,c)) == NULL) { ERR(argv,_(": illegal option--"),c); if (argv[optind][++sp] == eos) { optind++; sp = 1; } return error; } else if (*++cp == arg) { if (argv[optind][sp + 1] != eos) optarg = &argv[optind++][sp + 1]; else if (++optind >= argc) { ERR(argv,_(": option requires an argument--"),c); sp = 1; return error; } else optarg = argv[optind++]; sp = 1; } else { if (argv[optind][++sp] == eos) { sp = 1; optind++; } optarg = NULL; } return (int) c; } #endif /* HAVE_GETOPT */ openldap-2.4.42+dfsg/libraries/liblutil/md5.c0000644000175000017500000002340212563404150017456 0ustar ryanryan/* md5.c -- MD5 message-digest algorithm */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* This work was adapted for inclusion in OpenLDAP Software by * Kurt D. Zeilenga based upon code developed by Colin Plumb * and subsequently modified by Jim Kingdon. */ /* * This code implements the MD5 message-digest algorithm. * The algorithm is due to Ron Rivest. This code was * written by Colin Plumb in 1993, no copyright is claimed. * This code is in the public domain; do with it what you wish. * * Equivalent code is available from RSA Data Security, Inc. * This code has been tested against that, and is equivalent, * except that you don't need to include two pages of legalese * with every copy. * * To compute the message digest of a chunk of bytes, declare an * MD5Context structure, pass it to MD5Init, call MD5Update as * needed on buffers full of bytes, and then call MD5Final, which * will fill a supplied 16-byte array with the digest. */ /* This code was modified in 1997 by Jim Kingdon of Cyclic Software to not require an integer type which is exactly 32 bits. This work draws on the changes for the same purpose by Tatu Ylonen as part of SSH, but since I didn't actually use that code, there is no copyright issue. I hereby disclaim copyright in any changes I have made; this code remains in the public domain. */ #include "portable.h" #include /* include socket.h to get sys/types.h and/or winsock2.h */ #include #include /* Little-endian byte-swapping routines. Note that these do not depend on the size of datatypes such as ber_uint_t, nor do they require us to detect the endianness of the machine we are running on. It is possible they should be macros for speed, but I would be surprised if they were a performance bottleneck for MD5. */ static ber_uint_t getu32( const unsigned char *addr ) { return (((((unsigned long)addr[3] << 8) | addr[2]) << 8) | addr[1]) << 8 | addr[0]; } static void putu32( ber_uint_t data, unsigned char *addr ) { addr[0] = (unsigned char)data; addr[1] = (unsigned char)(data >> 8); addr[2] = (unsigned char)(data >> 16); addr[3] = (unsigned char)(data >> 24); } /* * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious * initialization constants. */ void lutil_MD5Init( struct lutil_MD5Context *ctx ) { ctx->buf[0] = 0x67452301; ctx->buf[1] = 0xefcdab89; ctx->buf[2] = 0x98badcfe; ctx->buf[3] = 0x10325476; ctx->bits[0] = 0; ctx->bits[1] = 0; } /* * Update context to reflect the concatenation of another buffer full * of bytes. */ void lutil_MD5Update( struct lutil_MD5Context *ctx, const unsigned char *buf, ber_len_t len ) { ber_uint_t t; /* Update bitcount */ t = ctx->bits[0]; if ((ctx->bits[0] = (t + ((ber_uint_t)len << 3)) & 0xffffffff) < t) ctx->bits[1]++; /* Carry from low to high */ ctx->bits[1] += len >> 29; t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ /* Handle any leading odd-sized chunks */ if ( t ) { unsigned char *p = ctx->in + t; t = 64-t; if (len < t) { AC_MEMCPY(p, buf, len); return; } AC_MEMCPY(p, buf, t); lutil_MD5Transform(ctx->buf, ctx->in); buf += t; len -= t; } /* Process data in 64-byte chunks */ while (len >= 64) { AC_MEMCPY(ctx->in, buf, 64); lutil_MD5Transform(ctx->buf, ctx->in); buf += 64; len -= 64; } /* Handle any remaining bytes of data. */ AC_MEMCPY(ctx->in, buf, len); } /* * Final wrapup - pad to 64-byte boundary with the bit pattern * 1 0* (64-bit count of bits processed, MSB-first) */ void lutil_MD5Final( unsigned char *digest, struct lutil_MD5Context *ctx ) { unsigned count; unsigned char *p; /* Compute number of bytes mod 64 */ count = (ctx->bits[0] >> 3) & 0x3F; /* Set the first char of padding to 0x80. This is safe since there is always at least one byte free */ p = ctx->in + count; *p++ = 0x80; /* Bytes of padding needed to make 64 bytes */ count = 64 - 1 - count; /* Pad out to 56 mod 64 */ if (count < 8) { /* Two lots of padding: Pad the first block to 64 bytes */ memset(p, '\0', count); lutil_MD5Transform(ctx->buf, ctx->in); /* Now fill the next block with 56 bytes */ memset(ctx->in, '\0', 56); } else { /* Pad block to 56 bytes */ memset(p, '\0', count-8); } /* Append length in bits and transform */ putu32(ctx->bits[0], ctx->in + 56); putu32(ctx->bits[1], ctx->in + 60); lutil_MD5Transform(ctx->buf, ctx->in); putu32(ctx->buf[0], digest); putu32(ctx->buf[1], digest + 4); putu32(ctx->buf[2], digest + 8); putu32(ctx->buf[3], digest + 12); memset(ctx, '\0', sizeof(*ctx)); /* In case it's sensitive */ } #ifndef ASM_MD5 /* The four core functions - F1 is optimized somewhat */ /* #define F1(x, y, z) (x & y | ~x & z) */ #define F1(x, y, z) (z ^ (x & (y ^ z))) #define F2(x, y, z) F1(z, x, y) #define F3(x, y, z) (x ^ y ^ z) #define F4(x, y, z) (y ^ (x | ~z)) /* This is the central step in the MD5 algorithm. */ #define MD5STEP(f, w, x, y, z, data, s) \ ( w += f(x, y, z) + data, w &= 0xffffffff, w = w<>(32-s), w += x ) /* * The core of the MD5 algorithm, this alters an existing MD5 hash to * reflect the addition of 16 longwords of new data. MD5Update blocks * the data and converts bytes into longwords for this routine. */ void lutil_MD5Transform( ber_uint_t *buf, const unsigned char *inraw ) { register ber_uint_t a, b, c, d; ber_uint_t in[16]; int i; for (i = 0; i < 16; ++i) in[i] = getu32 (inraw + 4 * i); a = buf[0]; b = buf[1]; c = buf[2]; d = buf[3]; MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478, 7); MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12); MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17); MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22); MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf, 7); MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12); MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17); MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22); MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8, 7); MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12); MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17); MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22); MD5STEP(F1, a, b, c, d, in[12]+0x6b901122, 7); MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12); MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17); MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22); MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562, 5); MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340, 9); MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14); MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20); MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d, 5); MD5STEP(F2, d, a, b, c, in[10]+0x02441453, 9); MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14); MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20); MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6, 5); MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6, 9); MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14); MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20); MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905, 5); MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8, 9); MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14); MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20); MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942, 4); MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11); MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16); MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23); MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44, 4); MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11); MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16); MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23); MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6, 4); MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11); MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16); MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23); MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039, 4); MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11); MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16); MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23); MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244, 6); MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10); MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15); MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21); MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3, 6); MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10); MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15); MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21); MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f, 6); MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10); MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15); MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21); MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82, 6); MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10); MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15); MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21); buf[0] += a; buf[1] += b; buf[2] += c; buf[3] += d; } #endif #ifdef TEST /* Simple test program. Can use it to manually run the tests from RFC1321 for example. */ #include int main (int argc, char **argv ) { struct lutil_MD5Context context; unsigned char checksum[LUTIL_MD5_BYTES]; int i; int j; if (argc < 2) { fprintf (stderr, "usage: %s string-to-hash\n", argv[0]); return EXIT_FAILURE; } for (j = 1; j < argc; ++j) { printf ("MD5 (\"%s\") = ", argv[j]); lutil_MD5Init (&context); lutil_MD5Update (&context, argv[j], strlen (argv[j])); lutil_MD5Final (checksum, &context); for (i = 0; i < LUTIL_MD5_BYTES; i++) { printf ("%02x", (unsigned int) checksum[i]); } printf ("\n"); } return EXIT_SUCCESS; } #endif /* TEST */ openldap-2.4.42+dfsg/libraries/liblutil/slapdmsg.h0000644000175000017500000000315712563404150020615 0ustar ryanryan// // This file contains message strings for the OpenLDAP slapd service. // // This file should be compiled as follows // mc -v slapdmsg.mc -r $(IntDir) // rc /v /r $(IntDir)\slapdmsg.rc // The mc (message compiler) command generates the .rc and .h files from this file. The // rc (resource compiler) takes the .rc file and produces a .res file that can be linked // with the final executable application. The application is then registered as a message // source with by creating the appropriate entries in the system registry. // // // Values are 32 bit values layed out as follows: // // 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 // +---+-+-+-----------------------+-------------------------------+ // |Sev|C|R| Facility | Code | // +---+-+-+-----------------------+-------------------------------+ // // where // // Sev - is the severity code // // 00 - Success // 01 - Informational // 10 - Warning // 11 - Error // // C - is the Customer code flag // // R - is a reserved bit // // Facility - is the facility code // // Code - is the facility's status code // // // Define the facility codes // // // Define the severity codes // // // MessageId: MSG_SVC_STARTED // // MessageText: // // OpenLDAP service started. debuglevel=%1, conffile=%2, urls=%3 // #define MSG_SVC_STARTED 0x40000500L // // MessageId: MSG_SVC_STOPPED // // MessageText: // // OpenLDAP service stopped. // #define MSG_SVC_STOPPED 0x40000501L openldap-2.4.42+dfsg/libraries/liblutil/signal.c0000644000175000017500000000167312563404150020254 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #include "portable.h" #ifdef HAVE_SIGACTION #include #include lutil_sig_t lutil_sigaction(int sig, lutil_sig_t func) { struct sigaction action, oaction; memset( &action, '\0', sizeof(action) ); action.sa_handler = func; sigemptyset( &action.sa_mask ); #ifdef SA_RESTART action.sa_flags |= SA_RESTART; #endif if( sigaction( sig, &action, &oaction ) != 0 ) { return NULL; } return oaction.sa_handler; } #endif openldap-2.4.42+dfsg/libraries/liblutil/tavl.c0000644000175000017500000002762212563404150017747 0ustar ryanryan/* avl.c - routines to implement an avl tree */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 2005-2015 The OpenLDAP Foundation. * Portions Copyright (c) 2005 by Howard Chu, Symas Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* ACKNOWLEDGEMENTS: * This work was initially developed by Howard Chu for inclusion * in OpenLDAP software. */ #include "portable.h" #include #include #include #ifdef CSRIMALLOC #define ber_memalloc malloc #define ber_memrealloc realloc #define ber_memfree free #else #include "lber.h" #endif #define AVL_INTERNAL #include "avl.h" /* Maximum tree depth this host's address space could support */ #define MAX_TREE_DEPTH (sizeof(void *) * CHAR_BIT) static const int avl_bfs[] = {LH, RH}; /* * Threaded AVL trees - for fast in-order traversal of nodes. */ /* * tavl_insert -- insert a node containing data data into the avl tree * with root root. fcmp is a function to call to compare the data portion * of two nodes. it should take two arguments and return <, >, or == 0, * depending on whether its first argument is <, >, or == its second * argument (like strcmp, e.g.). fdup is a function to call when a duplicate * node is inserted. it should return 0, or -1 and its return value * will be the return value from avl_insert in the case of a duplicate node. * the function will be called with the original node's data as its first * argument and with the incoming duplicate node's data as its second * argument. this could be used, for example, to keep a count with each * node. * * NOTE: this routine may malloc memory */ int tavl_insert( Avlnode ** root, void *data, AVL_CMP fcmp, AVL_DUP fdup ) { Avlnode *t, *p, *s, *q, *r; int a, cmp, ncmp; if ( *root == NULL ) { if (( r = (Avlnode *) ber_memalloc( sizeof( Avlnode ))) == NULL ) { return( -1 ); } r->avl_link[0] = r->avl_link[1] = NULL; r->avl_data = data; r->avl_bf = EH; r->avl_bits[0] = r->avl_bits[1] = AVL_THREAD; *root = r; return( 0 ); } t = NULL; s = p = *root; /* find insertion point */ while (1) { cmp = fcmp( data, p->avl_data ); if ( cmp == 0 ) return (*fdup)( p->avl_data, data ); cmp = (cmp > 0); q = avl_child( p, cmp ); if (q == NULL) { /* insert */ if (( q = (Avlnode *) ber_memalloc( sizeof( Avlnode ))) == NULL ) { return( -1 ); } q->avl_link[cmp] = p->avl_link[cmp]; q->avl_link[!cmp] = p; q->avl_data = data; q->avl_bf = EH; q->avl_bits[0] = q->avl_bits[1] = AVL_THREAD; p->avl_link[cmp] = q; p->avl_bits[cmp] = AVL_CHILD; break; } else if ( q->avl_bf ) { t = p; s = q; } p = q; } /* adjust balance factors */ cmp = fcmp( data, s->avl_data ) > 0; r = p = s->avl_link[cmp]; a = avl_bfs[cmp]; while ( p != q ) { cmp = fcmp( data, p->avl_data ) > 0; p->avl_bf = avl_bfs[cmp]; p = p->avl_link[cmp]; } /* checks and balances */ if ( s->avl_bf == EH ) { s->avl_bf = a; return 0; } else if ( s->avl_bf == -a ) { s->avl_bf = EH; return 0; } else if ( s->avl_bf == a ) { cmp = (a > 0); ncmp = !cmp; if ( r->avl_bf == a ) { /* single rotation */ p = r; if ( r->avl_bits[ncmp] == AVL_THREAD ) { r->avl_bits[ncmp] = AVL_CHILD; s->avl_bits[cmp] = AVL_THREAD; } else { s->avl_link[cmp] = r->avl_link[ncmp]; r->avl_link[ncmp] = s; } s->avl_bf = 0; r->avl_bf = 0; } else if ( r->avl_bf == -a ) { /* double rotation */ p = r->avl_link[ncmp]; if ( p->avl_bits[cmp] == AVL_THREAD ) { p->avl_bits[cmp] = AVL_CHILD; r->avl_bits[ncmp] = AVL_THREAD; } else { r->avl_link[ncmp] = p->avl_link[cmp]; p->avl_link[cmp] = r; } if ( p->avl_bits[ncmp] == AVL_THREAD ) { p->avl_bits[ncmp] = AVL_CHILD; s->avl_link[cmp] = p; s->avl_bits[cmp] = AVL_THREAD; } else { s->avl_link[cmp] = p->avl_link[ncmp]; p->avl_link[ncmp] = s; } if ( p->avl_bf == a ) { s->avl_bf = -a; r->avl_bf = 0; } else if ( p->avl_bf == -a ) { s->avl_bf = 0; r->avl_bf = a; } else { s->avl_bf = 0; r->avl_bf = 0; } p->avl_bf = 0; } /* Update parent */ if ( t == NULL ) *root = p; else if ( s == t->avl_right ) t->avl_right = p; else t->avl_left = p; } return 0; } void* tavl_delete( Avlnode **root, void* data, AVL_CMP fcmp ) { Avlnode *p, *q, *r, *top; int side, side_bf, shorter, nside = -1; /* parent stack */ Avlnode *pptr[MAX_TREE_DEPTH]; unsigned char pdir[MAX_TREE_DEPTH]; int depth = 0; if ( *root == NULL ) return NULL; p = *root; while (1) { side = fcmp( data, p->avl_data ); if ( !side ) break; side = ( side > 0 ); pdir[depth] = side; pptr[depth++] = p; if ( p->avl_bits[side] == AVL_THREAD ) return NULL; p = p->avl_link[side]; } data = p->avl_data; /* If this node has two children, swap so we are deleting a node with * at most one child. */ if ( p->avl_bits[0] == AVL_CHILD && p->avl_bits[1] == AVL_CHILD && p->avl_link[0] && p->avl_link[1] ) { /* find the immediate predecessor */ q = p->avl_link[0]; side = depth; pdir[depth++] = 0; while (q->avl_bits[1] == AVL_CHILD && q->avl_link[1]) { pdir[depth] = 1; pptr[depth++] = q; q = q->avl_link[1]; } /* swap links */ r = p->avl_link[0]; p->avl_link[0] = q->avl_link[0]; q->avl_link[0] = r; q->avl_link[1] = p->avl_link[1]; p->avl_link[1] = q; p->avl_bits[0] = q->avl_bits[0]; p->avl_bits[1] = q->avl_bits[1]; q->avl_bits[0] = q->avl_bits[1] = AVL_CHILD; q->avl_bf = p->avl_bf; /* fix stack positions: old parent of p points to q */ pptr[side] = q; if ( side ) { r = pptr[side-1]; r->avl_link[pdir[side-1]] = q; } else { *root = q; } /* new parent of p points to p */ if ( depth-side > 1 ) { r = pptr[depth-1]; r->avl_link[1] = p; } else { q->avl_link[0] = p; } /* fix right subtree: successor of p points to q */ r = q->avl_link[1]; while ( r->avl_bits[0] == AVL_CHILD && r->avl_link[0] ) r = r->avl_link[0]; r->avl_link[0] = q; } /* now

has at most one child, get it */ if ( p->avl_link[0] && p->avl_bits[0] == AVL_CHILD ) { q = p->avl_link[0]; /* Preserve thread continuity */ r = p->avl_link[1]; nside = 1; } else if ( p->avl_link[1] && p->avl_bits[1] == AVL_CHILD ) { q = p->avl_link[1]; r = p->avl_link[0]; nside = 0; } else { q = NULL; if ( depth > 0 ) r = p->avl_link[pdir[depth-1]]; else r = NULL; } ber_memfree( p ); /* Update child thread */ if ( q ) { for ( ; q->avl_bits[nside] == AVL_CHILD && q->avl_link[nside]; q = q->avl_link[nside] ) ; q->avl_link[nside] = r; } if ( !depth ) { *root = q; return data; } /* set the child into p's parent */ depth--; p = pptr[depth]; side = pdir[depth]; p->avl_link[side] = q; if ( !q ) { p->avl_bits[side] = AVL_THREAD; p->avl_link[side] = r; } top = NULL; shorter = 1; while ( shorter ) { p = pptr[depth]; side = pdir[depth]; nside = !side; side_bf = avl_bfs[side]; /* case 1: height unchanged */ if ( p->avl_bf == EH ) { /* Tree is now heavier on opposite side */ p->avl_bf = avl_bfs[nside]; shorter = 0; } else if ( p->avl_bf == side_bf ) { /* case 2: taller subtree shortened, height reduced */ p->avl_bf = EH; } else { /* case 3: shorter subtree shortened */ if ( depth ) top = pptr[depth-1]; /* p->parent; */ else top = NULL; /* set to the taller of the two subtrees of

*/ q = p->avl_link[nside]; if ( q->avl_bf == EH ) { /* case 3a: height unchanged, single rotate */ if ( q->avl_bits[side] == AVL_THREAD ) { q->avl_bits[side] = AVL_CHILD; p->avl_bits[nside] = AVL_THREAD; } else { p->avl_link[nside] = q->avl_link[side]; q->avl_link[side] = p; } shorter = 0; q->avl_bf = side_bf; p->avl_bf = (- side_bf); } else if ( q->avl_bf == p->avl_bf ) { /* case 3b: height reduced, single rotate */ if ( q->avl_bits[side] == AVL_THREAD ) { q->avl_bits[side] = AVL_CHILD; p->avl_bits[nside] = AVL_THREAD; } else { p->avl_link[nside] = q->avl_link[side]; q->avl_link[side] = p; } shorter = 1; q->avl_bf = EH; p->avl_bf = EH; } else { /* case 3c: height reduced, balance factors opposite */ r = q->avl_link[side]; if ( r->avl_bits[nside] == AVL_THREAD ) { r->avl_bits[nside] = AVL_CHILD; q->avl_bits[side] = AVL_THREAD; } else { q->avl_link[side] = r->avl_link[nside]; r->avl_link[nside] = q; } if ( r->avl_bits[side] == AVL_THREAD ) { r->avl_bits[side] = AVL_CHILD; p->avl_bits[nside] = AVL_THREAD; p->avl_link[nside] = r; } else { p->avl_link[nside] = r->avl_link[side]; r->avl_link[side] = p; } if ( r->avl_bf == side_bf ) { q->avl_bf = (- side_bf); p->avl_bf = EH; } else if ( r->avl_bf == (- side_bf)) { q->avl_bf = EH; p->avl_bf = side_bf; } else { q->avl_bf = EH; p->avl_bf = EH; } r->avl_bf = EH; q = r; } /* a rotation has caused (or in case 3c) to become * the root. let

's former parent know this. */ if ( top == NULL ) { *root = q; } else if (top->avl_link[0] == p) { top->avl_link[0] = q; } else { top->avl_link[1] = q; } /* end case 3 */ p = q; } if ( !depth ) break; depth--; } /* end while(shorter) */ return data; } /* * tavl_free -- traverse avltree root, freeing the memory it is using. * the dfree() is called to free the data portion of each node. The * number of items actually freed is returned. */ int tavl_free( Avlnode *root, AVL_FREE dfree ) { int nleft, nright; if ( root == 0 ) return( 0 ); nleft = tavl_free( avl_lchild( root ), dfree ); nright = tavl_free( avl_rchild( root ), dfree ); if ( dfree ) (*dfree)( root->avl_data ); ber_memfree( root ); return( nleft + nright + 1 ); } /* * tavl_find -- search avltree root for a node with data data. the function * cmp is used to compare things. it is called with data as its first arg * and the current node data as its second. it should return 0 if they match, * < 0 if arg1 is less than arg2 and > 0 if arg1 is greater than arg2. */ /* * tavl_find2 - returns Avlnode instead of data pointer. * tavl_find3 - as above, but returns Avlnode even if no match is found. * also set *ret = last comparison result, or -1 if root == NULL. */ Avlnode * tavl_find3( Avlnode *root, const void *data, AVL_CMP fcmp, int *ret ) { int cmp = -1, dir; Avlnode *prev = root; while ( root != 0 && (cmp = (*fcmp)( data, root->avl_data )) != 0 ) { prev = root; dir = cmp > 0; root = avl_child( root, dir ); } *ret = cmp; return root ? root : prev; } Avlnode * tavl_find2( Avlnode *root, const void *data, AVL_CMP fcmp ) { int cmp; while ( root != 0 && (cmp = (*fcmp)( data, root->avl_data )) != 0 ) { cmp = cmp > 0; root = avl_child( root, cmp ); } return root; } void* tavl_find( Avlnode *root, const void* data, AVL_CMP fcmp ) { int cmp; while ( root != 0 && (cmp = (*fcmp)( data, root->avl_data )) != 0 ) { cmp = cmp > 0; root = avl_child( root, cmp ); } return( root ? root->avl_data : 0 ); } /* Return the leftmost or rightmost node in the tree */ Avlnode * tavl_end( Avlnode *root, int dir ) { if ( root ) { while ( root->avl_bits[dir] == AVL_CHILD ) root = root->avl_link[dir]; } return root; } /* Return the next node in the given direction */ Avlnode * tavl_next( Avlnode *root, int dir ) { if ( root ) { int c = root->avl_bits[dir]; root = root->avl_link[dir]; if ( c == AVL_CHILD ) { dir ^= 1; while ( root->avl_bits[dir] == AVL_CHILD ) root = root->avl_link[dir]; } } return root; } openldap-2.4.42+dfsg/libraries/liblutil/hash.c0000644000175000017500000000277112563404150017722 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 2000-2015 The OpenLDAP Foundation. * Portions Copyright 2000-2003 Kurt D. Zeilenga. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* This implements the Fowler / Noll / Vo (FNV-1) hash algorithm. * A summary of the algorithm can be found at: * http://www.isthe.com/chongo/tech/comp/fnv/index.html */ #include "portable.h" #include /* offset and prime for 32-bit FNV-1 */ #define HASH_OFFSET 0x811c9dc5U #define HASH_PRIME 16777619 /* * Initialize context */ void lutil_HASHInit( struct lutil_HASHContext *ctx ) { ctx->hash = HASH_OFFSET; } /* * Update hash */ void lutil_HASHUpdate( struct lutil_HASHContext *ctx, const unsigned char *buf, ber_len_t len ) { const unsigned char *p, *e; ber_uint_t h; p = buf; e = &buf[len]; h = ctx->hash; while( p < e ) { h *= HASH_PRIME; h ^= *p++; } ctx->hash = h; } /* * Save hash */ void lutil_HASHFinal( unsigned char *digest, struct lutil_HASHContext *ctx ) { ber_uint_t h = ctx->hash; digest[0] = h & 0xffU; digest[1] = (h>>8) & 0xffU; digest[2] = (h>>16) & 0xffU; digest[3] = (h>>24) & 0xffU; } openldap-2.4.42+dfsg/libraries/librewrite/0000755000175000017500000000000012563404150017154 5ustar ryanryanopenldap-2.4.42+dfsg/libraries/librewrite/session.c0000644000175000017500000002317412563404150021012 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 2000-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* ACKNOWLEDGEMENT: * This work was initially developed by Pierangelo Masarati for * inclusion in OpenLDAP Software. */ #include #include "rewrite-int.h" /* * Compares two cookies */ static int rewrite_cookie_cmp( const void *c1, const void *c2 ) { const struct rewrite_session *s1, *s2; s1 = ( const struct rewrite_session * )c1; s2 = ( const struct rewrite_session * )c2; assert( s1 != NULL ); assert( s2 != NULL ); assert( s1->ls_cookie != NULL ); assert( s2->ls_cookie != NULL ); return ( ( s1->ls_cookie < s2->ls_cookie ) ? -1 : ( ( s1->ls_cookie > s2->ls_cookie ) ? 1 : 0 ) ); } /* * Duplicate cookies? */ static int rewrite_cookie_dup( void *c1, void *c2 ) { struct rewrite_session *s1, *s2; s1 = ( struct rewrite_session * )c1; s2 = ( struct rewrite_session * )c2; assert( s1 != NULL ); assert( s2 != NULL ); assert( s1->ls_cookie != NULL ); assert( s2->ls_cookie != NULL ); assert( s1->ls_cookie != s2->ls_cookie ); return ( ( s1->ls_cookie == s2->ls_cookie ) ? -1 : 0 ); } /* * Inits a session */ struct rewrite_session * rewrite_session_init( struct rewrite_info *info, const void *cookie ) { struct rewrite_session *session, tmp; int rc; assert( info != NULL ); assert( cookie != NULL ); #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_rdwr_wlock( &info->li_cookies_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ tmp.ls_cookie = ( void * )cookie; session = ( struct rewrite_session * )avl_find( info->li_cookies, ( caddr_t )&tmp, rewrite_cookie_cmp ); if ( session ) { session->ls_count++; #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_rdwr_wunlock( &info->li_cookies_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ return session; } session = calloc( sizeof( struct rewrite_session ), 1 ); if ( session == NULL ) { #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_rdwr_wunlock( &info->li_cookies_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ return NULL; } session->ls_cookie = ( void * )cookie; session->ls_count = 1; #ifdef USE_REWRITE_LDAP_PVT_THREADS if ( ldap_pvt_thread_mutex_init( &session->ls_mutex ) ) { free( session ); ldap_pvt_thread_rdwr_wunlock( &info->li_cookies_mutex ); return NULL; } if ( ldap_pvt_thread_rdwr_init( &session->ls_vars_mutex ) ) { ldap_pvt_thread_mutex_destroy( &session->ls_mutex ); free( session ); ldap_pvt_thread_rdwr_wunlock( &info->li_cookies_mutex ); return NULL; } #endif /* USE_REWRITE_LDAP_PVT_THREADS */ rc = avl_insert( &info->li_cookies, ( caddr_t )session, rewrite_cookie_cmp, rewrite_cookie_dup ); info->li_num_cookies++; #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_rdwr_wunlock( &info->li_cookies_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ if ( rc != 0 ) { #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_rdwr_destroy( &session->ls_vars_mutex ); ldap_pvt_thread_mutex_destroy( &session->ls_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ free( session ); return NULL; } return session; } /* * Fetches a session */ struct rewrite_session * rewrite_session_find( struct rewrite_info *info, const void *cookie ) { struct rewrite_session *session, tmp; assert( info != NULL ); assert( cookie != NULL ); tmp.ls_cookie = ( void * )cookie; #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_rdwr_rlock( &info->li_cookies_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ session = ( struct rewrite_session * )avl_find( info->li_cookies, ( caddr_t )&tmp, rewrite_cookie_cmp ); #ifdef USE_REWRITE_LDAP_PVT_THREADS if ( session ) { ldap_pvt_thread_mutex_lock( &session->ls_mutex ); session->ls_count++; } ldap_pvt_thread_rdwr_runlock( &info->li_cookies_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ return session; } /* * Returns a session */ void rewrite_session_return( struct rewrite_info *info, struct rewrite_session *session ) { assert( session != NULL ); session->ls_count--; ldap_pvt_thread_mutex_unlock( &session->ls_mutex ); } /* * Defines and inits a var with session scope */ int rewrite_session_var_set_f( struct rewrite_info *info, const void *cookie, const char *name, const char *value, int flags ) { struct rewrite_session *session; struct rewrite_var *var; assert( info != NULL ); assert( cookie != NULL ); assert( name != NULL ); assert( value != NULL ); session = rewrite_session_find( info, cookie ); if ( session == NULL ) { session = rewrite_session_init( info, cookie ); if ( session == NULL ) { return REWRITE_ERR; } #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_mutex_lock( &session->ls_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ } #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_rdwr_wlock( &session->ls_vars_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ var = rewrite_var_find( session->ls_vars, name ); if ( var != NULL ) { assert( var->lv_value.bv_val != NULL ); (void)rewrite_var_replace( var, value, flags ); } else { var = rewrite_var_insert_f( &session->ls_vars, name, value, flags ); if ( var == NULL ) { #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_rdwr_wunlock( &session->ls_vars_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ rewrite_session_return( info, session ); return REWRITE_ERR; } } #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_rdwr_wunlock( &session->ls_vars_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ rewrite_session_return( info, session ); return REWRITE_SUCCESS; } /* * Gets a var with session scope */ int rewrite_session_var_get( struct rewrite_info *info, const void *cookie, const char *name, struct berval *value ) { struct rewrite_session *session; struct rewrite_var *var; int rc = REWRITE_SUCCESS; assert( info != NULL ); assert( cookie != NULL ); assert( name != NULL ); assert( value != NULL ); value->bv_val = NULL; value->bv_len = 0; if ( cookie == NULL ) { return REWRITE_ERR; } session = rewrite_session_find( info, cookie ); if ( session == NULL ) { return REWRITE_ERR; } #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_rdwr_rlock( &session->ls_vars_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ var = rewrite_var_find( session->ls_vars, name ); if ( var != NULL ) { value->bv_val = strdup( var->lv_value.bv_val ); value->bv_len = var->lv_value.bv_len; } if ( var == NULL || value->bv_val == NULL ) { rc = REWRITE_ERR; } #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_rdwr_runlock( &session->ls_vars_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ rewrite_session_return( info, session ); return rc; } static void rewrite_session_clean( void *v_session ) { struct rewrite_session *session = (struct rewrite_session *)v_session; #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_rdwr_wlock( &session->ls_vars_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ rewrite_var_delete( session->ls_vars ); #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_rdwr_wunlock( &session->ls_vars_mutex ); ldap_pvt_thread_rdwr_destroy( &session->ls_vars_mutex ); ldap_pvt_thread_mutex_unlock( &session->ls_mutex ); ldap_pvt_thread_mutex_destroy( &session->ls_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ } static void rewrite_session_free( void *v_session ) { struct rewrite_session *session = (struct rewrite_session *)v_session; ldap_pvt_thread_mutex_lock( &session->ls_mutex ); rewrite_session_clean( v_session ); free( v_session ); } /* * Deletes a session */ int rewrite_session_delete( struct rewrite_info *info, const void *cookie ) { struct rewrite_session *session, tmp = { 0 }; assert( info != NULL ); assert( cookie != NULL ); session = rewrite_session_find( info, cookie ); if ( session == NULL ) { return REWRITE_SUCCESS; } if ( --session->ls_count > 0 ) { rewrite_session_return( info, session ); return REWRITE_SUCCESS; } rewrite_session_clean( session ); #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_rdwr_wlock( &info->li_cookies_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ assert( info->li_num_cookies > 0 ); info->li_num_cookies--; /* * There is nothing to delete in the return value */ tmp.ls_cookie = ( void * )cookie; avl_delete( &info->li_cookies, ( caddr_t )&tmp, rewrite_cookie_cmp ); free( session ); #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_rdwr_wunlock( &info->li_cookies_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ return REWRITE_SUCCESS; } /* * Destroys the cookie tree */ int rewrite_session_destroy( struct rewrite_info *info ) { int count; assert( info != NULL ); #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_rdwr_wlock( &info->li_cookies_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ /* * Should call per-session destruction routine ... */ count = avl_free( info->li_cookies, rewrite_session_free ); info->li_cookies = NULL; #if 0 fprintf( stderr, "count = %d; num_cookies = %d\n", count, info->li_num_cookies ); #endif assert( count == info->li_num_cookies ); info->li_num_cookies = 0; #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_rdwr_wunlock( &info->li_cookies_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ return REWRITE_SUCCESS; } openldap-2.4.42+dfsg/libraries/librewrite/info.c0000644000175000017500000001377612563404150020271 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 2000-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* ACKNOWLEDGEMENT: * This work was initially developed by Pierangelo Masarati for * inclusion in OpenLDAP Software. */ #include #include "rewrite-int.h" /* * Global data */ /* * This becomes the running context for subsequent calls to * rewrite_parse; it can be altered only by a * rewriteContext config line or by a change in info. */ struct rewrite_context *rewrite_int_curr_context = NULL; /* * Inits the info */ struct rewrite_info * rewrite_info_init( int mode ) { struct rewrite_info *info; struct rewrite_context *context; switch ( mode ) { case REWRITE_MODE_ERR: case REWRITE_MODE_OK: case REWRITE_MODE_COPY_INPUT: case REWRITE_MODE_USE_DEFAULT: break; default: mode = REWRITE_MODE_USE_DEFAULT; break; /* return NULL */ } /* * Resets the running context for parsing ... */ rewrite_int_curr_context = NULL; info = calloc( sizeof( struct rewrite_info ), 1 ); if ( info == NULL ) { return NULL; } info->li_state = REWRITE_DEFAULT; info->li_max_passes = REWRITE_MAX_PASSES; info->li_max_passes_per_rule = REWRITE_MAX_PASSES; info->li_rewrite_mode = mode; /* * Add the default (empty) rule */ context = rewrite_context_create( info, REWRITE_DEFAULT_CONTEXT ); if ( context == NULL ) { free( info ); return NULL; } #ifdef USE_REWRITE_LDAP_PVT_THREADS if ( ldap_pvt_thread_rdwr_init( &info->li_cookies_mutex ) ) { avl_free( info->li_context, rewrite_context_free ); free( info ); return NULL; } if ( ldap_pvt_thread_rdwr_init( &info->li_params_mutex ) ) { ldap_pvt_thread_rdwr_destroy( &info->li_cookies_mutex ); avl_free( info->li_context, rewrite_context_free ); free( info ); return NULL; } #endif /* USE_REWRITE_LDAP_PVT_THREADS */ return info; } /* * Cleans up the info structure */ int rewrite_info_delete( struct rewrite_info **pinfo ) { struct rewrite_info *info; assert( pinfo != NULL ); assert( *pinfo != NULL ); info = *pinfo; if ( info->li_context ) { avl_free( info->li_context, rewrite_context_free ); } info->li_context = NULL; if ( info->li_maps ) { avl_free( info->li_maps, rewrite_builtin_map_free ); } info->li_maps = NULL; rewrite_session_destroy( info ); #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_rdwr_destroy( &info->li_cookies_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ rewrite_param_destroy( info ); #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_rdwr_destroy( &info->li_params_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ free( info ); *pinfo = NULL; return REWRITE_SUCCESS; } /* * Rewrites a string according to context. * If the engine is off, OK is returned, but the return string will be NULL. * In case of 'unwilling to perform', UNWILLING is returned, and the * return string will also be null. The same in case of error. * Otherwise, OK is returned, and result will hold a newly allocated string * with the rewriting. * * What to do in case of non-existing rewrite context is still an issue. * Four possibilities: * - error, * - ok with NULL result, * - ok with copy of string as result, * - use the default rewrite context. */ int rewrite( struct rewrite_info *info, const char *rewriteContext, const char *string, char **result ) { return rewrite_session( info, rewriteContext, string, NULL, result ); } int rewrite_session( struct rewrite_info *info, const char *rewriteContext, const char *string, const void *cookie, char **result ) { struct rewrite_context *context; struct rewrite_op op = { 0, 0, NULL, NULL, NULL }; int rc; assert( info != NULL ); assert( rewriteContext != NULL ); assert( string != NULL ); assert( result != NULL ); /* * cookie can be null; means: don't care about session stuff */ *result = NULL; op.lo_cookie = cookie; /* * Engine not on means no failure, but explicit no rewriting */ if ( info->li_state != REWRITE_ON ) { rc = REWRITE_REGEXEC_OK; goto rc_return; } /* * Undefined context means no rewriting also * (conservative, are we sure it's what we want?) */ context = rewrite_context_find( info, rewriteContext ); if ( context == NULL ) { switch ( info->li_rewrite_mode ) { case REWRITE_MODE_ERR: rc = REWRITE_REGEXEC_ERR; goto rc_return; case REWRITE_MODE_OK: rc = REWRITE_REGEXEC_OK; goto rc_return; case REWRITE_MODE_COPY_INPUT: *result = strdup( string ); rc = ( *result != NULL ) ? REWRITE_REGEXEC_OK : REWRITE_REGEXEC_ERR; goto rc_return; case REWRITE_MODE_USE_DEFAULT: context = rewrite_context_find( info, REWRITE_DEFAULT_CONTEXT ); break; } } #if 0 /* FIXME: not used anywhere! (debug? then, why strdup?) */ op.lo_string = strdup( string ); if ( op.lo_string == NULL ) { rc = REWRITE_REGEXEC_ERR; goto rc_return; } #endif /* * Applies rewrite context */ rc = rewrite_context_apply( info, &op, context, string, result ); assert( op.lo_depth == 0 ); #if 0 /* FIXME: not used anywhere! (debug? then, why strdup?) */ free( op.lo_string ); #endif switch ( rc ) { /* * Success */ case REWRITE_REGEXEC_OK: case REWRITE_REGEXEC_STOP: /* * If rewrite succeeded return OK regardless of how * the successful rewriting was obtained! */ rc = REWRITE_REGEXEC_OK; break; /* * Internal or forced error, return = NULL; rc already OK. */ case REWRITE_REGEXEC_UNWILLING: case REWRITE_REGEXEC_ERR: if ( *result != NULL ) { if ( *result != string ) { free( *result ); } *result = NULL; } default: break; } rc_return:; if ( op.lo_vars ) { rewrite_var_delete( op.lo_vars ); } return rc; } openldap-2.4.42+dfsg/libraries/librewrite/Makefile.in0000644000175000017500000000217212563404150021223 0ustar ryanryan# LIBREWRITE # $OpenLDAP$ ## This work is part of OpenLDAP Software . ## ## Copyright 1998-2015 The OpenLDAP Foundation. ## All rights reserved. ## ## Redistribution and use in source and binary forms, with or without ## modification, are permitted only as authorized by the OpenLDAP ## Public License. ## ## A copy of this license is available in the file LICENSE in the ## top-level directory of the distribution or, alternatively, at ## . ## ## Copyright 2000-2001 Pierangelo Masarati ## SRCS = config.c context.c info.c ldapmap.c map.c params.c rule.c \ session.c subst.c var.c xmap.c \ parse.c rewrite.c XSRCS = version.c OBJS = config.o context.o info.o ldapmap.o map.o params.o rule.o \ session.o subst.o var.o xmap.o LDAP_INCDIR= ../../include LDAP_LIBDIR= ../../libraries LIBRARY = librewrite.a PROGRAMS = rewrite XLIBS = $(LIBRARY) $(LDAP_LIBLUTIL_A) \ $(LDAP_LIBLDAP_R_LA) $(LDAP_LIBLBER_LA) XXLIBS = $(SECURITY_LIBS) $(LUTIL_LIBS) XXXLIBS = $(LTHREAD_LIBS) rewrite: $(XLIBS) rewrite.o parse.o $(LTLINK) -o $@ rewrite.o parse.o $(LIBS) openldap-2.4.42+dfsg/libraries/librewrite/context.c0000644000175000017500000002326712563404150021016 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 2000-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* ACKNOWLEDGEMENT: * This work was initially developed by Pierangelo Masarati for * inclusion in OpenLDAP Software. */ #include #include "rewrite-int.h" /* * Compares two struct rewrite_context based on the name; * used by avl stuff */ static int rewrite_context_cmp( const void *c1, const void *c2 ) { const struct rewrite_context *lc1, *lc2; lc1 = (const struct rewrite_context *)c1; lc2 = (const struct rewrite_context *)c2; assert( c1 != NULL ); assert( c2 != NULL ); assert( lc1->lc_name != NULL ); assert( lc2->lc_name != NULL ); return strcasecmp( lc1->lc_name, lc2->lc_name ); } /* * Returns -1 in case a duplicate struct rewrite_context * has been inserted; used by avl stuff */ static int rewrite_context_dup( void *c1, void *c2 ) { struct rewrite_context *lc1, *lc2; lc1 = (struct rewrite_context *)c1; lc2 = (struct rewrite_context *)c2; assert( c1 != NULL ); assert( c2 != NULL ); assert( lc1->lc_name != NULL ); assert( lc2->lc_name != NULL ); return( strcasecmp( lc1->lc_name, lc2->lc_name) == 0 ? -1 : 0 ); } /* * Finds the context named rewriteContext in the context tree */ struct rewrite_context * rewrite_context_find( struct rewrite_info *info, const char *rewriteContext ) { struct rewrite_context *context, c; assert( info != NULL ); assert( rewriteContext != NULL ); /* * Fetches the required rewrite context */ c.lc_name = (char *)rewriteContext; context = (struct rewrite_context *)avl_find( info->li_context, (caddr_t)&c, rewrite_context_cmp ); if ( context == NULL ) { return NULL; } /* * De-aliases the context if required */ if ( context->lc_alias ) { return context->lc_alias; } return context; } /* * Creates a new context called rewriteContext and stores in into the tree */ struct rewrite_context * rewrite_context_create( struct rewrite_info *info, const char *rewriteContext ) { struct rewrite_context *context; int rc; assert( info != NULL ); assert( rewriteContext != NULL ); context = calloc( sizeof( struct rewrite_context ), 1 ); if ( context == NULL ) { return NULL; } /* * Context name */ context->lc_name = strdup( rewriteContext ); if ( context->lc_name == NULL ) { free( context ); return NULL; } /* * The first, empty rule */ context->lc_rule = calloc( sizeof( struct rewrite_rule ), 1 ); if ( context->lc_rule == NULL ) { free( context->lc_name ); free( context ); return NULL; } memset( context->lc_rule, 0, sizeof( struct rewrite_rule ) ); /* * Add context to tree */ rc = avl_insert( &info->li_context, (caddr_t)context, rewrite_context_cmp, rewrite_context_dup ); if ( rc == -1 ) { free( context->lc_rule ); free( context->lc_name ); free( context ); return NULL; } return context; } /* * Finds the next rule according to a goto action statement, * or null in case of error. * Helper for rewrite_context_apply. */ static struct rewrite_rule * rewrite_action_goto( struct rewrite_action *action, struct rewrite_rule *rule ) { int n; assert( action != NULL ); assert( action->la_args != NULL ); assert( rule != NULL ); n = ((int *)action->la_args)[ 0 ]; if ( n > 0 ) { for ( ; n > 1 && rule != NULL ; n-- ) { rule = rule->lr_next; } } else if ( n <= 0 ) { for ( ; n < 1 && rule != NULL ; n++ ) { rule = rule->lr_prev; } } return rule; } /* * Rewrites string according to context; may return: * OK: fine; if *result != NULL rule matched and rewrite succeeded. * STOP: fine, rule matched; stop processing following rules * UNWILL: rule matched; force 'unwilling to perform' */ int rewrite_context_apply( struct rewrite_info *info, struct rewrite_op *op, struct rewrite_context *context, const char *string, char **result ) { struct rewrite_rule *rule; char *s, *res = NULL; int return_code = REWRITE_REGEXEC_OK; assert( info != NULL ); assert( op != NULL ); assert( context != NULL ); assert( context->lc_rule != NULL ); assert( string != NULL ); assert( result != NULL ); op->lo_depth++; Debug( LDAP_DEBUG_TRACE, "==> rewrite_context_apply" " [depth=%d] string='%s'\n", op->lo_depth, string, 0 ); assert( op->lo_depth > 0 ); s = (char *)string; for ( rule = context->lc_rule->lr_next; rule != NULL && op->lo_num_passes < info->li_max_passes; rule = rule->lr_next, op->lo_num_passes++ ) { int rc; /* * Apply a single rule */ rc = rewrite_rule_apply( info, op, rule, s, &res ); /* * A rule may return: * OK with result != NULL if matched * ERR if anything was wrong * UNWILLING if the server should drop the request * the latter case in honored immediately; * the other two may require some special actions to take * place. */ switch ( rc ) { case REWRITE_REGEXEC_ERR: Debug( LDAP_DEBUG_ANY, "==> rewrite_context_apply" " error ...\n", 0, 0, 0); /* * Checks for special actions to be taken * in case of error ... */ if ( rule->lr_action != NULL ) { struct rewrite_action *action; int do_continue = 0; for ( action = rule->lr_action; action != NULL; action = action->la_next ) { switch ( action->la_type ) { /* * This action takes precedence * over the others in case of failure */ case REWRITE_ACTION_IGNORE_ERR: Debug( LDAP_DEBUG_ANY, "==> rewrite_context_apply" " ignoring error ...\n", 0, 0, 0 ); do_continue = 1; break; /* * Goto is honored only if it comes * after ignore error */ case REWRITE_ACTION_GOTO: if ( do_continue ) { rule = rewrite_action_goto( action, rule ); if ( rule == NULL ) { return_code = REWRITE_REGEXEC_ERR; goto rc_end_of_context; } } break; /* * Other actions are ignored */ default: break; } } if ( do_continue ) { if ( rule->lr_next == NULL ) { res = s; } goto rc_continue; } } /* * Default behavior is to bail out ... */ return_code = REWRITE_REGEXEC_ERR; goto rc_end_of_context; /* * OK means there were no errors or special return codes; * if res is defined, it means the rule matched and we * got a sucessful rewriting */ case REWRITE_REGEXEC_OK: /* * It matched! Check for actions ... */ if ( res != NULL ) { struct rewrite_action *action; if ( s != string && s != res ) { free( s ); } s = res; for ( action = rule->lr_action; action != NULL; action = action->la_next ) { switch ( action->la_type ) { /* * This ends the rewrite context * successfully */ case REWRITE_ACTION_STOP: goto rc_end_of_context; /* * This instructs the server to return * an `unwilling to perform' error * message */ case REWRITE_ACTION_UNWILLING: return_code = REWRITE_REGEXEC_UNWILLING; goto rc_end_of_context; /* * This causes the processing to * jump n rules back and forth */ case REWRITE_ACTION_GOTO: rule = rewrite_action_goto( action, rule ); if ( rule == NULL ) { return_code = REWRITE_REGEXEC_ERR; goto rc_end_of_context; } break; /* * This ends the rewrite context * and returns a user-defined * error code */ case REWRITE_ACTION_USER: return_code = ((int *)action->la_args)[ 0 ]; goto rc_end_of_context; default: /* ... */ break; } } /* * If result was OK and string didn't match, * in case of last rule we need to set the * result back to the string */ } else if ( rule->lr_next == NULL ) { res = s; } break; /* * A STOP has propagated ... */ case REWRITE_REGEXEC_STOP: goto rc_end_of_context; /* * This will instruct the server to return * an `unwilling to perform' error message */ case REWRITE_REGEXEC_UNWILLING: return_code = REWRITE_REGEXEC_UNWILLING; goto rc_end_of_context; /* * A user-defined error code has propagated ... */ default: assert( rc >= REWRITE_REGEXEC_USER ); goto rc_end_of_context; } rc_continue:; /* sent here by actions that require to continue */ } rc_end_of_context:; *result = res; Debug( LDAP_DEBUG_TRACE, "==> rewrite_context_apply" " [depth=%d] res={%d,'%s'}\n", op->lo_depth, return_code, ( res ? res : "NULL" ) ); assert( op->lo_depth > 0 ); op->lo_depth--; return return_code; } void rewrite_context_free( void *tmp ) { struct rewrite_context *context = (struct rewrite_context *)tmp; assert( tmp != NULL ); rewrite_context_destroy( &context ); } int rewrite_context_destroy( struct rewrite_context **pcontext ) { struct rewrite_context *context; struct rewrite_rule *r; assert( pcontext != NULL ); assert( *pcontext != NULL ); context = *pcontext; assert( context->lc_rule != NULL ); for ( r = context->lc_rule->lr_next; r; ) { struct rewrite_rule *cr = r; r = r->lr_next; rewrite_rule_destroy( &cr ); } free( context->lc_rule ); context->lc_rule = NULL; assert( context->lc_name != NULL ); free( context->lc_name ); context->lc_name = NULL; free( context ); *pcontext = NULL; return 0; } openldap-2.4.42+dfsg/libraries/librewrite/parse.c0000644000175000017500000000466212563404150020442 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 2000-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* ACKNOWLEDGEMENT: * This work was initially developed by Pierangelo Masarati for * inclusion in OpenLDAP Software. */ #include #include #include "rewrite-int.h" static int parse_line( char **argv, int *argc, int maxargs, char *buf ) { char *p, *begin; int in_quoted_field = 0, cnt = 0; char quote = '\0'; for ( p = buf; isspace( (unsigned char) p[ 0 ] ); p++ ); if ( p[ 0 ] == '#' ) { return 0; } for ( begin = p; p[ 0 ] != '\0'; p++ ) { if ( p[ 0 ] == '\\' && p[ 1 ] != '\0' ) { p++; } else if ( p[ 0 ] == '\'' || p[ 0 ] == '\"') { if ( in_quoted_field && p[ 0 ] == quote ) { in_quoted_field = 1 - in_quoted_field; quote = '\0'; p[ 0 ] = '\0'; argv[ cnt ] = begin; if ( ++cnt == maxargs ) { *argc = cnt; return 1; } for ( p++; isspace( (unsigned char) p[ 0 ] ); p++ ); begin = p; p--; } else if ( !in_quoted_field ) { if ( p != begin ) { return -1; } begin++; in_quoted_field = 1 - in_quoted_field; quote = p[ 0 ]; } } else if ( isspace( (unsigned char) p[ 0 ] ) && !in_quoted_field ) { p[ 0 ] = '\0'; argv[ cnt ] = begin; if ( ++cnt == maxargs ) { *argc = cnt; return 1; } for ( p++; isspace( (unsigned char) p[ 0 ] ); p++ ); begin = p; p--; } } *argc = cnt; return 1; } int rewrite_read( FILE *fin, struct rewrite_info *info ) { char buf[ 1024 ]; char *argv[11]; int argc, lineno; /* * Empty rule at the beginning of the context */ for ( lineno = 0; fgets( buf, sizeof( buf ), fin ); lineno++ ) { switch ( parse_line( argv, &argc, sizeof( argv ) - 1, buf ) ) { case -1: return REWRITE_ERR; case 0: break; case 1: if ( strncasecmp( argv[ 0 ], "rewrite", 7 ) == 0 ) { int rc; rc = rewrite_parse( info, "file", lineno, argc, argv ); if ( rc != REWRITE_SUCCESS ) { return rc; } } break; } } return REWRITE_SUCCESS; } openldap-2.4.42+dfsg/libraries/librewrite/RATIONALE0000644000175000017500000000015512563404150020416 0ustar ryanryanThe workings of the rewrite library are described in the REWRITING section of the slapd-meta(5) manual page. openldap-2.4.42+dfsg/libraries/librewrite/xmap.c0000644000175000017500000002434212563404150020272 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 2000-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* ACKNOWLEDGEMENT: * This work was initially developed by Pierangelo Masarati for * inclusion in OpenLDAP Software. */ #include #include #ifdef HAVE_PWD_H #include #endif #define LDAP_DEPRECATED 1 #include "rewrite-int.h" #include "rewrite-map.h" /* * Global data */ #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_mutex_t xpasswd_mutex; static int xpasswd_mutex_init = 0; #endif /* USE_REWRITE_LDAP_PVT_THREADS */ /* * Map parsing * NOTE: these are old-fashion maps; new maps will be parsed on separate * config lines, and referred by name. */ struct rewrite_map * rewrite_xmap_parse( struct rewrite_info *info, const char *s, const char **currpos ) { struct rewrite_map *map; assert( info != NULL ); assert( s != NULL ); assert( currpos != NULL ); Debug( LDAP_DEBUG_ARGS, "rewrite_xmap_parse: %s\n%s%s", s, "", "" ); *currpos = NULL; map = calloc( sizeof( struct rewrite_map ), 1 ); if ( map == NULL ) { Debug( LDAP_DEBUG_ANY, "rewrite_xmap_parse:" " calloc failed\n%s%s%s", "", "", "" ); return NULL; } /* * Experimental passwd map: * replaces the uid with the matching gecos from /etc/passwd file */ if ( strncasecmp(s, "xpasswd", 7 ) == 0 ) { map->lm_type = REWRITE_MAP_XPWDMAP; map->lm_name = strdup( "xpasswd" ); if ( map->lm_name == NULL ) { free( map ); return NULL; } assert( s[7] == '}' ); *currpos = s + 8; #ifdef USE_REWRITE_LDAP_PVT_THREADS if ( !xpasswd_mutex_init ) { if ( ldap_pvt_thread_mutex_init( &xpasswd_mutex ) ) { free( map ); return NULL; } } ++xpasswd_mutex_init; #endif /* USE_REWRITE_LDAP_PVT_THREADS */ /* Don't really care if fails */ return map; /* * Experimental file map: * looks up key in a `key value' ascii file */ } else if ( strncasecmp( s, "xfile", 5 ) == 0 ) { char *filename; const char *p; int l; int c = 5; map->lm_type = REWRITE_MAP_XFILEMAP; if ( s[ c ] != '(' ) { free( map ); return NULL; } /* Must start with '/' for security concerns */ c++; if ( s[ c ] != '/' ) { free( map ); return NULL; } for ( p = s + c; p[ 0 ] != '\0' && p[ 0 ] != ')'; p++ ); if ( p[ 0 ] != ')' ) { free( map ); return NULL; } l = p - s - c; filename = calloc( sizeof( char ), l + 1 ); if ( filename == NULL ) { free( map ); return NULL; } AC_MEMCPY( filename, s + c, l ); filename[ l ] = '\0'; map->lm_args = ( void * )fopen( filename, "r" ); free( filename ); if ( map->lm_args == NULL ) { free( map ); return NULL; } *currpos = p + 1; #ifdef USE_REWRITE_LDAP_PVT_THREADS if ( ldap_pvt_thread_mutex_init( &map->lm_mutex ) ) { fclose( ( FILE * )map->lm_args ); free( map ); return NULL; } #endif /* USE_REWRITE_LDAP_PVT_THREADS */ return map; /* * Experimental ldap map: * looks up key on the fly (not implemented!) */ } else if ( strncasecmp(s, "xldap", 5 ) == 0 ) { char *p; char *url; int l, rc; int c = 5; LDAPURLDesc *lud; if ( s[ c ] != '(' ) { free( map ); return NULL; } c++; p = strchr( s, '}' ); if ( p == NULL ) { free( map ); return NULL; } p--; *currpos = p + 2; /* * Add two bytes for urlencoding of '%s' */ l = p - s - c; url = calloc( sizeof( char ), l + 3 ); if ( url == NULL ) { free( map ); return NULL; } AC_MEMCPY( url, s + c, l ); url[ l ] = '\0'; /* * Urlencodes the '%s' for ldap_url_parse */ p = strchr( url, '%' ); if ( p != NULL ) { AC_MEMCPY( p + 3, p + 1, strlen( p + 1 ) + 1 ); p[ 1 ] = '2'; p[ 2 ] = '5'; } rc = ldap_url_parse( url, &lud ); free( url ); if ( rc != LDAP_SUCCESS ) { free( map ); return NULL; } assert( lud != NULL ); map->lm_args = ( void * )lud; map->lm_type = REWRITE_MAP_XLDAPMAP; #ifdef USE_REWRITE_LDAP_PVT_THREADS if ( ldap_pvt_thread_mutex_init( &map->lm_mutex ) ) { ldap_free_urldesc( lud ); free( map ); return NULL; } #endif /* USE_REWRITE_LDAP_PVT_THREADS */ return map; /* Unhandled map */ } free( map ); return NULL; } /* * Map key -> value resolution * NOTE: these are old-fashion maps; new maps will be parsed on separate * config lines, and referred by name. */ int rewrite_xmap_apply( struct rewrite_info *info, struct rewrite_op *op, struct rewrite_map *map, struct berval *key, struct berval *val ) { int rc = REWRITE_SUCCESS; assert( info != NULL ); assert( op != NULL ); assert( map != NULL ); assert( key != NULL ); assert( val != NULL ); val->bv_val = NULL; val->bv_len = 0; switch ( map->lm_type ) { #ifdef HAVE_GETPWNAM case REWRITE_MAP_XPWDMAP: { struct passwd *pwd; #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_mutex_lock( &xpasswd_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ pwd = getpwnam( key->bv_val ); if ( pwd == NULL ) { #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_mutex_unlock( &xpasswd_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ rc = LDAP_NO_SUCH_OBJECT; break; } #ifdef HAVE_STRUCT_PASSWD_PW_GECOS if ( pwd->pw_gecos != NULL && pwd->pw_gecos[0] != '\0' ) { int l = strlen( pwd->pw_gecos ); val->bv_val = strdup( pwd->pw_gecos ); val->bv_len = l; } else #endif /* HAVE_STRUCT_PASSWD_PW_GECOS */ { val->bv_val = strdup( key->bv_val ); val->bv_len = key->bv_len; } #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_mutex_unlock( &xpasswd_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ if ( val->bv_val == NULL ) { rc = REWRITE_ERR; } break; } #endif /* HAVE_GETPWNAM*/ case REWRITE_MAP_XFILEMAP: { char buf[1024]; if ( map->lm_args == NULL ) { rc = REWRITE_ERR; break; } #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_mutex_lock( &map->lm_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ rewind( ( FILE * )map->lm_args ); while ( fgets( buf, sizeof( buf ), ( FILE * )map->lm_args ) ) { char *p; int blen; blen = strlen( buf ); if ( buf[ blen - 1 ] == '\n' ) { buf[ blen - 1 ] = '\0'; } p = strtok( buf, " " ); if ( p == NULL ) { #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_mutex_unlock( &map->lm_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ rc = REWRITE_ERR; goto rc_return; } if ( strcasecmp( p, key->bv_val ) == 0 && ( p = strtok( NULL, "" ) ) ) { val->bv_val = strdup( p ); if ( val->bv_val == NULL ) { #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_mutex_unlock( &map->lm_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ rc = REWRITE_ERR; goto rc_return; } val->bv_len = strlen( p ); #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_mutex_unlock( &map->lm_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ goto rc_return; } } #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_mutex_unlock( &map->lm_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ rc = REWRITE_ERR; break; } case REWRITE_MAP_XLDAPMAP: { LDAP *ld; char filter[1024]; LDAPMessage *res = NULL, *entry; LDAPURLDesc *lud = ( LDAPURLDesc * )map->lm_args; int attrsonly = 0; char **values; assert( lud != NULL ); /* * No mutex because there is no write on the map data */ ld = ldap_init( lud->lud_host, lud->lud_port ); if ( ld == NULL ) { rc = REWRITE_ERR; goto rc_return; } snprintf( filter, sizeof( filter ), lud->lud_filter, key->bv_val ); if ( strcasecmp( lud->lud_attrs[ 0 ], "dn" ) == 0 ) { attrsonly = 1; } rc = ldap_search_s( ld, lud->lud_dn, lud->lud_scope, filter, lud->lud_attrs, attrsonly, &res ); if ( rc != LDAP_SUCCESS ) { ldap_unbind( ld ); rc = REWRITE_ERR; goto rc_return; } if ( ldap_count_entries( ld, res ) != 1 ) { ldap_unbind( ld ); rc = REWRITE_ERR; goto rc_return; } entry = ldap_first_entry( ld, res ); if ( entry == NULL ) { ldap_msgfree( res ); ldap_unbind( ld ); rc = REWRITE_ERR; goto rc_return; } if ( attrsonly == 1 ) { val->bv_val = ldap_get_dn( ld, entry ); } else { values = ldap_get_values( ld, entry, lud->lud_attrs[0] ); if ( values != NULL ) { val->bv_val = strdup( values[ 0 ] ); ldap_value_free( values ); } } ldap_msgfree( res ); ldap_unbind( ld ); if ( val->bv_val == NULL ) { rc = REWRITE_ERR; goto rc_return; } val->bv_len = strlen( val->bv_val ); rc = REWRITE_SUCCESS; } break; } rc_return:; return rc; } int rewrite_xmap_destroy( struct rewrite_map **pmap ) { struct rewrite_map *map; assert( pmap != NULL ); assert( *pmap != NULL ); map = *pmap; switch ( map->lm_type ) { case REWRITE_MAP_XPWDMAP: #ifdef USE_REWRITE_LDAP_PVT_THREADS --xpasswd_mutex_init; if ( !xpasswd_mutex_init ) { ldap_pvt_thread_mutex_destroy( &xpasswd_mutex ); } #endif /* USE_REWRITE_LDAP_PVT_THREADS */ break; case REWRITE_MAP_XFILEMAP: #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_mutex_lock( &map->lm_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ if ( map->lm_args ) { fclose( ( FILE * )map->lm_args ); map->lm_args = NULL; } #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_mutex_unlock( &map->lm_mutex ); ldap_pvt_thread_mutex_destroy( &map->lm_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ break; case REWRITE_MAP_XLDAPMAP: #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_mutex_lock( &map->lm_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ if ( map->lm_args ) { ldap_free_urldesc( ( LDAPURLDesc * )map->lm_args ); map->lm_args = NULL; } #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_mutex_unlock( &map->lm_mutex ); ldap_pvt_thread_mutex_destroy( &map->lm_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ break; default: break; } free( map->lm_name ); free( map ); *pmap = NULL; return 0; } openldap-2.4.42+dfsg/libraries/librewrite/rewrite.c0000644000175000017500000000737312563404150021013 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 2000-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* ACKNOWLEDGEMENT: * This work was initially developed by Pierangelo Masarati for * inclusion in OpenLDAP Software. */ #include #include #include #include #include #include #include #include #include #include #include #include #include int ldap_debug; int ldap_syslog; int ldap_syslog_level; static void apply( FILE *fin, const char *rewriteContext, const char *arg ) { struct rewrite_info *info; char *string, *sep, *result = NULL; int rc; void *cookie = &info; info = rewrite_info_init( REWRITE_MODE_ERR ); if ( rewrite_read( fin, info ) != 0 ) { exit( EXIT_FAILURE ); } rewrite_param_set( info, "prog", "rewrite" ); rewrite_session_init( info, cookie ); string = (char *)arg; for ( sep = strchr( rewriteContext, ',' ); rewriteContext != NULL; rewriteContext = sep, sep ? sep = strchr( rewriteContext, ',' ) : NULL ) { char *errmsg = ""; if ( sep != NULL ) { sep[ 0 ] = '\0'; sep++; } /* rc = rewrite( info, rewriteContext, string, &result ); */ rc = rewrite_session( info, rewriteContext, string, cookie, &result ); switch ( rc ) { case REWRITE_REGEXEC_OK: errmsg = "ok"; break; case REWRITE_REGEXEC_ERR: errmsg = "error"; break; case REWRITE_REGEXEC_STOP: errmsg = "stop"; break; case REWRITE_REGEXEC_UNWILLING: errmsg = "unwilling to perform"; break; default: if (rc >= REWRITE_REGEXEC_USER) { errmsg = "user-defined"; } else { errmsg = "unknown"; } break; } fprintf( stdout, "%s -> %s [%d:%s]\n", string, ( result ? result : "(null)" ), rc, errmsg ); if ( result == NULL ) { break; } if ( string != arg && string != result ) { free( string ); } string = result; } if ( result && result != arg ) { free( result ); } rewrite_session_delete( info, cookie ); rewrite_info_delete( &info ); } int main( int argc, char *argv[] ) { FILE *fin = NULL; char *rewriteContext = REWRITE_DEFAULT_CONTEXT; int debug = 0; while ( 1 ) { int opt = getopt( argc, argv, "d:f:hr:" ); if ( opt == EOF ) { break; } switch ( opt ) { case 'd': if ( lutil_atoi( &debug, optarg ) != 0 ) { fprintf( stderr, "illegal log level '%s'\n", optarg ); exit( EXIT_FAILURE ); } break; case 'f': fin = fopen( optarg, "r" ); if ( fin == NULL ) { fprintf( stderr, "unable to open file '%s'\n", optarg ); exit( EXIT_FAILURE ); } break; case 'h': fprintf( stderr, "usage: rewrite [options] string\n" "\n" "\t\t-f file\t\tconfiguration file\n" "\t\t-r rule[s]\tlist of comma-separated rules\n" "\n" "\tsyntax:\n" "\t\trewriteEngine\t{on|off}\n" "\t\trewriteContext\tcontextName [alias aliasedContextName]\n" "\t\trewriteRule\tpattern subst [flags]\n" "\n" ); exit( EXIT_SUCCESS ); case 'r': rewriteContext = optarg; break; } } if ( debug != 0 ) { ber_set_option(NULL, LBER_OPT_DEBUG_LEVEL, &debug); ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &debug); } if ( optind >= argc ) { return -1; } apply( ( fin ? fin : stdin ), rewriteContext, argv[ optind ] ); if ( fin ) { fclose( fin ); } return 0; } openldap-2.4.42+dfsg/libraries/librewrite/rule.c0000644000175000017500000002270312563404150020273 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 2000-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* ACKNOWLEDGEMENT: * This work was initially developed by Pierangelo Masarati for * inclusion in OpenLDAP Software. */ #include #include "rewrite-int.h" /* * Appends a rule to the double linked list of rules * Helper for rewrite_rule_compile */ static int append_rule( struct rewrite_context *context, struct rewrite_rule *rule ) { struct rewrite_rule *r; assert( context != NULL ); assert( context->lc_rule != NULL ); assert( rule != NULL ); for ( r = context->lc_rule; r->lr_next != NULL; r = r->lr_next ); r->lr_next = rule; rule->lr_prev = r; return REWRITE_SUCCESS; } /* * Appends an action to the linked list of actions * Helper for rewrite_rule_compile */ static int append_action( struct rewrite_action **pbase, struct rewrite_action *action ) { struct rewrite_action **pa; assert( pbase != NULL ); assert( action != NULL ); for ( pa = pbase; *pa != NULL; pa = &(*pa)->la_next ); *pa = action; return REWRITE_SUCCESS; } static int destroy_action( struct rewrite_action **paction ) { struct rewrite_action *action; assert( paction != NULL ); assert( *paction != NULL ); action = *paction; /* do something */ switch ( action->la_type ) { case REWRITE_FLAG_GOTO: case REWRITE_FLAG_USER: { int *pi = (int *)action->la_args; if ( pi ) { free( pi ); } break; } default: break; } free( action ); *paction = NULL; return 0; } static void destroy_actions( struct rewrite_action *paction ) { struct rewrite_action *next; for (; paction; paction = next) { next = paction->la_next; destroy_action( &paction ); } } /* */ int rewrite_rule_compile( struct rewrite_info *info, struct rewrite_context *context, const char *pattern, const char *result, const char *flagstring ) { int flags = REWRITE_REGEX_EXTENDED | REWRITE_REGEX_ICASE; int mode = REWRITE_RECURSE; int max_passes; struct rewrite_rule *rule = NULL; struct rewrite_subst *subst = NULL; struct rewrite_action *action = NULL, *first_action = NULL; const char *p; assert( info != NULL ); assert( context != NULL ); assert( pattern != NULL ); assert( result != NULL ); /* * A null flagstring should be allowed */ max_passes = info->li_max_passes_per_rule; /* * Take care of substitution string */ subst = rewrite_subst_compile( info, result ); if ( subst == NULL ) { return REWRITE_ERR; } /* * Take care of flags */ for ( p = flagstring; p[ 0 ] != '\0'; p++ ) { switch( p[ 0 ] ) { /* * REGEX flags */ case REWRITE_FLAG_HONORCASE: /* 'C' */ /* * Honor case (default is case insensitive) */ flags &= ~REWRITE_REGEX_ICASE; break; case REWRITE_FLAG_BASICREGEX: /* 'R' */ /* * Use POSIX Basic Regular Expression syntax * instead of POSIX Extended Regular Expression * syntax (default) */ flags &= ~REWRITE_REGEX_EXTENDED; break; /* * Execution mode flags */ case REWRITE_FLAG_EXECONCE: /* ':' */ /* * Apply rule once only */ mode &= ~REWRITE_RECURSE; mode |= REWRITE_EXEC_ONCE; break; /* * Special action flags */ case REWRITE_FLAG_STOP: /* '@' */ /* * Bail out after applying rule */ action = calloc( sizeof( struct rewrite_action ), 1 ); if ( action == NULL ) { goto fail; } action->la_type = REWRITE_ACTION_STOP; break; case REWRITE_FLAG_UNWILLING: /* '#' */ /* * Matching objs will be marked as gone! */ action = calloc( sizeof( struct rewrite_action ), 1 ); if ( action == NULL ) { goto fail; } mode &= ~REWRITE_RECURSE; mode |= REWRITE_EXEC_ONCE; action->la_type = REWRITE_ACTION_UNWILLING; break; case REWRITE_FLAG_GOTO: /* 'G' */ /* * After applying rule, jump N rules */ case REWRITE_FLAG_USER: { /* 'U' */ /* * After applying rule, return user-defined * error code */ char *next = NULL; int *d; if ( p[ 1 ] != '{' ) { goto fail; } d = malloc( sizeof( int ) ); if ( d == NULL ) { goto fail; } d[ 0 ] = strtol( &p[ 2 ], &next, 0 ); if ( next == &p[ 2 ] || next[0] != '}' ) { free( d ); goto fail; } action = calloc( sizeof( struct rewrite_action ), 1 ); if ( action == NULL ) { free( d ); goto fail; } switch ( p[ 0 ] ) { case REWRITE_FLAG_GOTO: action->la_type = REWRITE_ACTION_GOTO; break; case REWRITE_FLAG_USER: action->la_type = REWRITE_ACTION_USER; break; default: assert(0); } action->la_args = (void *)d; p = next; /* p is incremented by the for ... */ break; } case REWRITE_FLAG_MAX_PASSES: { /* 'U' */ /* * Set the number of max passes per rule */ char *next = NULL; if ( p[ 1 ] != '{' ) { goto fail; } max_passes = strtol( &p[ 2 ], &next, 0 ); if ( next == &p[ 2 ] || next[0] != '}' ) { goto fail; } if ( max_passes < 1 ) { /* FIXME: nonsense ... */ max_passes = 1; } p = next; /* p is incremented by the for ... */ break; } case REWRITE_FLAG_IGNORE_ERR: /* 'I' */ /* * Ignore errors! */ action = calloc( sizeof( struct rewrite_action ), 1 ); if ( action == NULL ) { goto fail; } action->la_type = REWRITE_ACTION_IGNORE_ERR; break; /* * Other flags ... */ default: /* * Unimplemented feature (complain only) */ break; } /* * Stupid way to append to a list ... */ if ( action != NULL ) { append_action( &first_action, action ); action = NULL; } } /* * Finally, rule allocation */ rule = calloc( sizeof( struct rewrite_rule ), 1 ); if ( rule == NULL ) { goto fail; } /* * REGEX compilation (luckily I don't need to take care of this ...) */ if ( regcomp( &rule->lr_regex, ( char * )pattern, flags ) != 0 ) { goto fail; } /* * Just to remember them ... */ rule->lr_pattern = strdup( pattern ); rule->lr_subststring = strdup( result ); rule->lr_flagstring = strdup( flagstring ); if ( rule->lr_pattern == NULL || rule->lr_subststring == NULL || rule->lr_flagstring == NULL ) { goto fail; } /* * Load compiled data into rule */ rule->lr_subst = subst; /* * Set various parameters */ rule->lr_flags = flags; /* don't really need any longer ... */ rule->lr_mode = mode; rule->lr_max_passes = max_passes; rule->lr_action = first_action; /* * Append rule at the end of the rewrite context */ append_rule( context, rule ); return REWRITE_SUCCESS; fail: if ( rule ) { if ( rule->lr_pattern ) free( rule->lr_pattern ); if ( rule->lr_subststring ) free( rule->lr_subststring ); if ( rule->lr_flagstring ) free( rule->lr_flagstring ); free( rule ); } destroy_actions( first_action ); free( subst ); return REWRITE_ERR; } /* * Rewrites string according to rule; may return: * OK: fine; if *result != NULL rule matched and rewrite succeeded. * STOP: fine, rule matched; stop processing following rules * UNWILL: rule matched; force 'unwilling to perform' */ int rewrite_rule_apply( struct rewrite_info *info, struct rewrite_op *op, struct rewrite_rule *rule, const char *arg, char **result ) { size_t nmatch = REWRITE_MAX_MATCH; regmatch_t match[ REWRITE_MAX_MATCH ]; int rc = REWRITE_SUCCESS; char *string; int strcnt = 0; struct berval val = { 0, NULL }; assert( info != NULL ); assert( op != NULL ); assert( rule != NULL ); assert( arg != NULL ); assert( result != NULL ); *result = NULL; string = (char *)arg; /* * In case recursive match is required (default) */ recurse:; Debug( LDAP_DEBUG_TRACE, "==> rewrite_rule_apply" " rule='%s' string='%s' [%d pass(es)]\n", rule->lr_pattern, string, strcnt + 1 ); op->lo_num_passes++; rc = regexec( &rule->lr_regex, string, nmatch, match, 0 ); if ( rc != 0 ) { if ( *result == NULL && string != arg ) { free( string ); } /* * No match is OK; *result = NULL means no match */ return REWRITE_REGEXEC_OK; } rc = rewrite_subst_apply( info, op, rule->lr_subst, string, match, &val ); *result = val.bv_val; val.bv_val = NULL; if ( string != arg ) { free( string ); string = NULL; } if ( rc != REWRITE_REGEXEC_OK ) { return rc; } if ( ( rule->lr_mode & REWRITE_RECURSE ) == REWRITE_RECURSE && op->lo_num_passes < info->li_max_passes && ++strcnt < rule->lr_max_passes ) { string = *result; goto recurse; } return REWRITE_REGEXEC_OK; } int rewrite_rule_destroy( struct rewrite_rule **prule ) { struct rewrite_rule *rule; assert( prule != NULL ); assert( *prule != NULL ); rule = *prule; if ( rule->lr_pattern ) { free( rule->lr_pattern ); rule->lr_pattern = NULL; } if ( rule->lr_subststring ) { free( rule->lr_subststring ); rule->lr_subststring = NULL; } if ( rule->lr_flagstring ) { free( rule->lr_flagstring ); rule->lr_flagstring = NULL; } if ( rule->lr_subst ) { rewrite_subst_destroy( &rule->lr_subst ); } regfree( &rule->lr_regex ); destroy_actions( rule->lr_action ); free( rule ); *prule = NULL; return 0; } openldap-2.4.42+dfsg/libraries/librewrite/subst.c0000644000175000017500000002476312563404150020474 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 2000-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* ACKNOWLEDGEMENT: * This work was initially developed by Pierangelo Masarati for * inclusion in OpenLDAP Software. */ #include #include "rewrite-int.h" /* * Compiles a substitution pattern */ struct rewrite_subst * rewrite_subst_compile( struct rewrite_info *info, const char *str ) { size_t subs_len; struct berval *subs = NULL, *tmps; struct rewrite_submatch *submatch = NULL; struct rewrite_subst *s = NULL; char *result, *begin, *p; int nsub = 0, l; assert( info != NULL ); assert( str != NULL ); result = strdup( str ); if ( result == NULL ) { return NULL; } /* * Take care of substitution string */ for ( p = begin = result, subs_len = 0; p[ 0 ] != '\0'; p++ ) { /* * Keep only single escapes '%' */ if ( !IS_REWRITE_SUBMATCH_ESCAPE( p[ 0 ] ) ) { continue; } if ( IS_REWRITE_SUBMATCH_ESCAPE( p[ 1 ] ) ) { /* Pull &p[1] over p, including the trailing '\0' */ AC_MEMCPY((char *)p, &p[ 1 ], strlen( p ) ); continue; } tmps = ( struct berval * )realloc( subs, sizeof( struct berval )*( nsub + 1 ) ); if ( tmps == NULL ) { goto cleanup; } subs = tmps; /* * I think an `if l > 0' at runtime is better outside than * inside a function call ... */ l = p - begin; if ( l > 0 ) { subs_len += l; subs[ nsub ].bv_len = l; subs[ nsub ].bv_val = malloc( l + 1 ); if ( subs[ nsub ].bv_val == NULL ) { goto cleanup; } AC_MEMCPY( subs[ nsub ].bv_val, begin, l ); subs[ nsub ].bv_val[ l ] = '\0'; } else { subs[ nsub ].bv_val = NULL; subs[ nsub ].bv_len = 0; } /* * Substitution pattern */ if ( isdigit( (unsigned char) p[ 1 ] ) ) { struct rewrite_submatch *tmpsm; int d = p[ 1 ] - '0'; /* * Add a new value substitution scheme */ tmpsm = ( struct rewrite_submatch * )realloc( submatch, sizeof( struct rewrite_submatch )*( nsub + 1 ) ); if ( tmpsm == NULL ) { goto cleanup; } submatch = tmpsm; submatch[ nsub ].ls_submatch = d; /* * If there is no argument, use default * (substitute substring as is) */ if ( p[ 2 ] != '{' ) { submatch[ nsub ].ls_type = REWRITE_SUBMATCH_ASIS; submatch[ nsub ].ls_map = NULL; begin = ++p + 1; } else { struct rewrite_map *map; submatch[ nsub ].ls_type = REWRITE_SUBMATCH_XMAP; map = rewrite_xmap_parse( info, p + 3, (const char **)&begin ); if ( map == NULL ) { goto cleanup; } submatch[ nsub ].ls_map = map; p = begin - 1; } /* * Map with args ... */ } else if ( p[ 1 ] == '{' ) { struct rewrite_map *map; struct rewrite_submatch *tmpsm; map = rewrite_map_parse( info, p + 2, (const char **)&begin ); if ( map == NULL ) { goto cleanup; } p = begin - 1; /* * Add a new value substitution scheme */ tmpsm = ( struct rewrite_submatch * )realloc( submatch, sizeof( struct rewrite_submatch )*( nsub + 1 ) ); if ( tmpsm == NULL ) { rewrite_map_destroy( &map ); goto cleanup; } submatch = tmpsm; submatch[ nsub ].ls_type = REWRITE_SUBMATCH_MAP_W_ARG; submatch[ nsub ].ls_map = map; /* * Escape '%' ... */ } else if ( p[ 1 ] == '%' ) { AC_MEMCPY( &p[ 1 ], &p[ 2 ], strlen( &p[ 1 ] ) ); continue; } else { goto cleanup; } nsub++; } /* * Last part of string */ tmps = (struct berval * )realloc( subs, sizeof( struct berval )*( nsub + 1 ) ); if ( tmps == NULL ) { /* * XXX need to free the value subst stuff! */ free( subs ); goto cleanup; } subs = tmps; l = p - begin; if ( l > 0 ) { subs_len += l; subs[ nsub ].bv_len = l; subs[ nsub ].bv_val = malloc( l + 1 ); if ( subs[ nsub ].bv_val == NULL ) { goto cleanup; } AC_MEMCPY( subs[ nsub ].bv_val, begin, l ); subs[ nsub ].bv_val[ l ] = '\0'; } else { subs[ nsub ].bv_val = NULL; subs[ nsub ].bv_len = 0; } s = calloc( sizeof( struct rewrite_subst ), 1 ); if ( s == NULL ) { goto cleanup; } s->lt_subs_len = subs_len; s->lt_subs = subs; s->lt_num_submatch = nsub; s->lt_submatch = submatch; subs = NULL; submatch = NULL; cleanup:; if ( subs ) { for ( l=0; lls_type == REWRITE_SUBMATCH_ASIS || submatch->ls_type == REWRITE_SUBMATCH_XMAP ); assert( string != NULL ); assert( match != NULL ); assert( val != NULL ); assert( val->bv_val == NULL ); c = submatch->ls_submatch; s = string + match[ c ].rm_so; l = match[ c ].rm_eo - match[ c ].rm_so; val->bv_len = l; val->bv_val = malloc( l + 1 ); if ( val->bv_val == NULL ) { return REWRITE_ERR; } AC_MEMCPY( val->bv_val, s, l ); val->bv_val[ l ] = '\0'; return REWRITE_SUCCESS; } /* * Substitutes a portion of rewritten string according to substitution * pattern using submatches */ int rewrite_subst_apply( struct rewrite_info *info, struct rewrite_op *op, struct rewrite_subst *subst, const char *string, const regmatch_t *match, struct berval *val ) { struct berval *submatch = NULL; char *res = NULL; int n = 0, l, cl; int rc = REWRITE_REGEXEC_OK; assert( info != NULL ); assert( op != NULL ); assert( subst != NULL ); assert( string != NULL ); assert( match != NULL ); assert( val != NULL ); assert( val->bv_val == NULL ); val->bv_val = NULL; val->bv_len = 0; /* * Prepare room for submatch expansion */ if ( subst->lt_num_submatch > 0 ) { submatch = calloc( sizeof( struct berval ), subst->lt_num_submatch ); if ( submatch == NULL ) { return REWRITE_REGEXEC_ERR; } } /* * Resolve submatches (simple subst, map expansion and so). */ for ( n = 0, l = 0; n < subst->lt_num_submatch; n++ ) { struct berval key = { 0, NULL }; submatch[ n ].bv_val = NULL; /* * Get key */ switch ( subst->lt_submatch[ n ].ls_type ) { case REWRITE_SUBMATCH_ASIS: case REWRITE_SUBMATCH_XMAP: rc = submatch_copy( &subst->lt_submatch[ n ], string, match, &key ); if ( rc != REWRITE_SUCCESS ) { rc = REWRITE_REGEXEC_ERR; goto cleanup; } break; case REWRITE_SUBMATCH_MAP_W_ARG: switch ( subst->lt_submatch[ n ].ls_map->lm_type ) { case REWRITE_MAP_GET_OP_VAR: case REWRITE_MAP_GET_SESN_VAR: case REWRITE_MAP_GET_PARAM: rc = REWRITE_SUCCESS; break; default: rc = rewrite_subst_apply( info, op, subst->lt_submatch[ n ].ls_map->lm_subst, string, match, &key); } if ( rc != REWRITE_SUCCESS ) { goto cleanup; } break; default: Debug( LDAP_DEBUG_ANY, "Not Implemented\n", 0, 0, 0 ); rc = REWRITE_ERR; break; } if ( rc != REWRITE_SUCCESS ) { rc = REWRITE_REGEXEC_ERR; goto cleanup; } /* * Resolve key */ switch ( subst->lt_submatch[ n ].ls_type ) { case REWRITE_SUBMATCH_ASIS: submatch[ n ] = key; rc = REWRITE_SUCCESS; break; case REWRITE_SUBMATCH_XMAP: rc = rewrite_xmap_apply( info, op, subst->lt_submatch[ n ].ls_map, &key, &submatch[ n ] ); free( key.bv_val ); key.bv_val = NULL; break; case REWRITE_SUBMATCH_MAP_W_ARG: rc = rewrite_map_apply( info, op, subst->lt_submatch[ n ].ls_map, &key, &submatch[ n ] ); free( key.bv_val ); key.bv_val = NULL; break; default: /* * When implemented, this might return the * exit status of a rewrite context, * which may include a stop, or an * unwilling to perform */ rc = REWRITE_ERR; break; } if ( rc != REWRITE_SUCCESS ) { rc = REWRITE_REGEXEC_ERR; goto cleanup; } /* * Increment the length of the resulting string */ l += submatch[ n ].bv_len; } /* * Alloc result buffer */ l += subst->lt_subs_len; res = malloc( l + 1 ); if ( res == NULL ) { rc = REWRITE_REGEXEC_ERR; goto cleanup; } /* * Apply submatches (possibly resolved thru maps) */ for ( n = 0, cl = 0; n < subst->lt_num_submatch; n++ ) { if ( subst->lt_subs[ n ].bv_val != NULL ) { AC_MEMCPY( res + cl, subst->lt_subs[ n ].bv_val, subst->lt_subs[ n ].bv_len ); cl += subst->lt_subs[ n ].bv_len; } AC_MEMCPY( res + cl, submatch[ n ].bv_val, submatch[ n ].bv_len ); cl += submatch[ n ].bv_len; } if ( subst->lt_subs[ n ].bv_val != NULL ) { AC_MEMCPY( res + cl, subst->lt_subs[ n ].bv_val, subst->lt_subs[ n ].bv_len ); cl += subst->lt_subs[ n ].bv_len; } res[ cl ] = '\0'; val->bv_val = res; val->bv_len = l; cleanup:; if ( submatch ) { for ( ; --n >= 0; ) { if ( submatch[ n ].bv_val ) { free( submatch[ n ].bv_val ); } } free( submatch ); } return rc; } /* * frees data */ int rewrite_subst_destroy( struct rewrite_subst **psubst ) { int n; struct rewrite_subst *subst; assert( psubst != NULL ); assert( *psubst != NULL ); subst = *psubst; for ( n = 0; n < subst->lt_num_submatch; n++ ) { if ( subst->lt_subs[ n ].bv_val ) { free( subst->lt_subs[ n ].bv_val ); subst->lt_subs[ n ].bv_val = NULL; } switch ( subst->lt_submatch[ n ].ls_type ) { case REWRITE_SUBMATCH_ASIS: break; case REWRITE_SUBMATCH_XMAP: rewrite_xmap_destroy( &subst->lt_submatch[ n ].ls_map ); break; case REWRITE_SUBMATCH_MAP_W_ARG: rewrite_map_destroy( &subst->lt_submatch[ n ].ls_map ); break; default: break; } } free( subst->lt_submatch ); subst->lt_submatch = NULL; /* last one */ if ( subst->lt_subs[ n ].bv_val ) { free( subst->lt_subs[ n ].bv_val ); subst->lt_subs[ n ].bv_val = NULL; } free( subst->lt_subs ); subst->lt_subs = NULL; free( subst ); *psubst = NULL; return 0; } openldap-2.4.42+dfsg/libraries/librewrite/var.c0000644000175000017500000001161512563404150020114 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 2000-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* ACKNOWLEDGEMENT: * This work was initially developed by Pierangelo Masarati for * inclusion in OpenLDAP Software. */ #include #include "rewrite-int.h" /* * Compares two vars */ static int rewrite_var_cmp( const void *c1, const void *c2 ) { const struct rewrite_var *v1, *v2; v1 = ( const struct rewrite_var * )c1; v2 = ( const struct rewrite_var * )c2; assert( v1 != NULL ); assert( v2 != NULL ); assert( v1->lv_name != NULL ); assert( v2->lv_name != NULL ); return strcasecmp( v1->lv_name, v2->lv_name ); } /* * Duplicate var ? */ static int rewrite_var_dup( void *c1, void *c2 ) { struct rewrite_var *v1, *v2; v1 = ( struct rewrite_var * )c1; v2 = ( struct rewrite_var * )c2; assert( v1 != NULL ); assert( v2 != NULL ); assert( v1->lv_name != NULL ); assert( v2->lv_name != NULL ); return ( strcasecmp( v1->lv_name, v2->lv_name ) == 0 ? -1 : 0 ); } /* * Frees a var */ static void rewrite_var_free( void *v_var ) { struct rewrite_var *var = v_var; assert( var != NULL ); assert( var->lv_name != NULL ); assert( var->lv_value.bv_val != NULL ); if ( var->lv_flags & REWRITE_VAR_COPY_NAME ) free( var->lv_name ); if ( var->lv_flags & REWRITE_VAR_COPY_VALUE ) free( var->lv_value.bv_val ); free( var ); } /* * Deletes a var tree */ int rewrite_var_delete( Avlnode *tree ) { avl_free( tree, rewrite_var_free ); return REWRITE_SUCCESS; } /* * Finds a var */ struct rewrite_var * rewrite_var_find( Avlnode *tree, const char *name ) { struct rewrite_var var; assert( name != NULL ); var.lv_name = ( char * )name; return ( struct rewrite_var * )avl_find( tree, ( caddr_t )&var, rewrite_var_cmp ); } int rewrite_var_replace( struct rewrite_var *var, const char *value, int flags ) { ber_len_t len; assert( value != NULL ); len = strlen( value ); if ( var->lv_flags & REWRITE_VAR_COPY_VALUE ) { if ( flags & REWRITE_VAR_COPY_VALUE ) { if ( len <= var->lv_value.bv_len ) { AC_MEMCPY(var->lv_value.bv_val, value, len + 1); } else { free( var->lv_value.bv_val ); var->lv_value.bv_val = strdup( value ); } } else { free( var->lv_value.bv_val ); var->lv_value.bv_val = (char *)value; var->lv_flags &= ~REWRITE_VAR_COPY_VALUE; } } else { if ( flags & REWRITE_VAR_COPY_VALUE ) { var->lv_value.bv_val = strdup( value ); var->lv_flags |= REWRITE_VAR_COPY_VALUE; } else { var->lv_value.bv_val = (char *)value; } } if ( var->lv_value.bv_val == NULL ) { return -1; } var->lv_value.bv_len = len; return 0; } /* * Inserts a newly created var */ struct rewrite_var * rewrite_var_insert_f( Avlnode **tree, const char *name, const char *value, int flags ) { struct rewrite_var *var; int rc = 0; assert( tree != NULL ); assert( name != NULL ); assert( value != NULL ); var = rewrite_var_find( *tree, name ); if ( var != NULL ) { if ( flags & REWRITE_VAR_UPDATE ) { (void)rewrite_var_replace( var, value, flags ); goto cleanup; } rc = -1; goto cleanup; } var = calloc( sizeof( struct rewrite_var ), 1 ); if ( var == NULL ) { return NULL; } memset( var, 0, sizeof( struct rewrite_var ) ); if ( flags & REWRITE_VAR_COPY_NAME ) { var->lv_name = strdup( name ); if ( var->lv_name == NULL ) { rc = -1; goto cleanup; } var->lv_flags |= REWRITE_VAR_COPY_NAME; } else { var->lv_name = (char *)name; } if ( flags & REWRITE_VAR_COPY_VALUE ) { var->lv_value.bv_val = strdup( value ); if ( var->lv_value.bv_val == NULL ) { rc = -1; goto cleanup; } var->lv_flags |= REWRITE_VAR_COPY_VALUE; } else { var->lv_value.bv_val = (char *)value; } var->lv_value.bv_len = strlen( value ); rc = avl_insert( tree, ( caddr_t )var, rewrite_var_cmp, rewrite_var_dup ); cleanup:; if ( rc != 0 && var ) { avl_delete( tree, ( caddr_t )var, rewrite_var_cmp ); rewrite_var_free( var ); var = NULL; } return var; } /* * Sets/inserts a var */ struct rewrite_var * rewrite_var_set_f( Avlnode **tree, const char *name, const char *value, int flags ) { struct rewrite_var *var; assert( tree != NULL ); assert( name != NULL ); assert( value != NULL ); var = rewrite_var_find( *tree, name ); if ( var == NULL ) { if ( flags & REWRITE_VAR_INSERT ) { return rewrite_var_insert_f( tree, name, value, flags ); } else { return NULL; } } else { assert( var->lv_value.bv_val != NULL ); (void)rewrite_var_replace( var, value, flags ); } return var; } openldap-2.4.42+dfsg/libraries/librewrite/Copyright0000644000175000017500000000200712563404150021046 0ustar ryanryan/****************************************************************************** * * Copyright (C) 2000 Pierangelo Masarati, * All rights reserved. * * Permission is granted to anyone to use this software for any purpose * on any computer system, and to alter it and redistribute it, subject * to the following restrictions: * * 1. The author is not responsible for the consequences of use of this * software, no matter how awful, even if they arise from flaws in it. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Since few users ever read sources, * credits should appear in the documentation. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. Since few users * ever read sources, credits should appear in the documentation. * * 4. This notice may not be removed or altered. * ******************************************************************************/ openldap-2.4.42+dfsg/libraries/librewrite/config.c0000644000175000017500000002355012563404150020572 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 2000-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* ACKNOWLEDGEMENT: * This work was initially developed by Pierangelo Masarati for * inclusion in OpenLDAP Software. */ #include #include "rewrite-int.h" #include "rewrite-map.h" /* * Parses a plugin map */ static int rewrite_parse_builtin_map( struct rewrite_info *info, const char *fname, int lineno, int argc, char **argv ); /* * Parses a config line and takes actions to fit content in rewrite structure; * lines handled are of the form: * * rewriteEngine {on|off} * rewriteMaxPasses numPasses [numPassesPerRule] * rewriteContext contextName [alias aliasedContextName] * rewriteRule pattern substPattern [ruleFlags] * rewriteMap mapType mapName [mapArgs] * rewriteParam paramName paramValue */ int rewrite_parse( struct rewrite_info *info, const char *fname, int lineno, int argc, char **argv ) { int rc = -1; assert( info != NULL ); assert( fname != NULL ); assert( argv != NULL ); assert( argc > 0 ); /* * Switch on the rewrite engine */ if ( strcasecmp( argv[ 0 ], "rewriteEngine" ) == 0 ) { if ( argc < 2 ) { Debug( LDAP_DEBUG_ANY, "[%s:%d] rewriteEngine needs 'state'\n%s", fname, lineno, "" ); return -1; } else if ( argc > 2 ) { Debug( LDAP_DEBUG_ANY, "[%s:%d] extra fields in rewriteEngine" " will be discarded\n%s", fname, lineno, "" ); } if ( strcasecmp( argv[ 1 ], "on" ) == 0 ) { info->li_state = REWRITE_ON; } else if ( strcasecmp( argv[ 1 ], "off" ) == 0 ) { info->li_state = REWRITE_OFF; } else { Debug( LDAP_DEBUG_ANY, "[%s:%d] unknown 'state' in rewriteEngine;" " assuming 'on'\n%s", fname, lineno, "" ); info->li_state = REWRITE_ON; } rc = REWRITE_SUCCESS; /* * Alter max passes */ } else if ( strcasecmp( argv[ 0 ], "rewriteMaxPasses" ) == 0 ) { if ( argc < 2 ) { Debug( LDAP_DEBUG_ANY, "[%s:%d] rewriteMaxPasses needs 'value'\n%s", fname, lineno, "" ); return -1; } if ( lutil_atoi( &info->li_max_passes, argv[ 1 ] ) != 0 ) { Debug( LDAP_DEBUG_ANY, "[%s:%d] unable to parse rewriteMaxPasses=\"%s\"\n", fname, lineno, argv[ 1 ] ); return -1; } if ( info->li_max_passes <= 0 ) { Debug( LDAP_DEBUG_ANY, "[%s:%d] negative or null rewriteMaxPasses\n", fname, lineno, 0 ); return -1; } if ( argc > 2 ) { if ( lutil_atoi( &info->li_max_passes_per_rule, argv[ 2 ] ) != 0 ) { Debug( LDAP_DEBUG_ANY, "[%s:%d] unable to parse rewriteMaxPassesPerRule=\"%s\"\n", fname, lineno, argv[ 2 ] ); return -1; } if ( info->li_max_passes_per_rule <= 0 ) { Debug( LDAP_DEBUG_ANY, "[%s:%d] negative or null rewriteMaxPassesPerRule\n", fname, lineno, 0 ); return -1; } } else { info->li_max_passes_per_rule = info->li_max_passes; } rc = REWRITE_SUCCESS; /* * Start a new rewrite context and set current context */ } else if ( strcasecmp( argv[ 0 ], "rewriteContext" ) == 0 ) { if ( argc < 2 ) { Debug( LDAP_DEBUG_ANY, "[%s:%d] rewriteContext needs 'name'\n%s", fname, lineno, "" ); return -1; } /* * Checks for existence (lots of contexts should be * available by default ...) */ rewrite_int_curr_context = rewrite_context_find( info, argv[ 1 ] ); if ( rewrite_int_curr_context == NULL ) { rewrite_int_curr_context = rewrite_context_create( info, argv[ 1 ] ); } if ( rewrite_int_curr_context == NULL ) { return -1; } if ( argc > 2 ) { /* * A context can alias another (e.g., the `builtin' * contexts for backend operations, if not defined, * alias the `default' rewrite context (with the * notable exception of the searchResult context, * which can be undefined) */ if ( strcasecmp( argv[ 2 ], "alias" ) == 0 ) { struct rewrite_context *aliased; if ( argc == 3 ) { Debug( LDAP_DEBUG_ANY, "[%s:%d] rewriteContext" " needs 'name' after" " 'alias'\n%s", fname, lineno, "" ); return -1; } else if ( argc > 4 ) { Debug( LDAP_DEBUG_ANY, "[%s:%d] extra fields in" " rewriteContext" " after aliased name" " will be" " discarded\n%s", fname, lineno, "" ); } aliased = rewrite_context_find( info, argv[ 3 ] ); if ( aliased == NULL ) { Debug( LDAP_DEBUG_ANY, "[%s:%d] aliased" " rewriteContext '%s'" " does not exists\n", fname, lineno, argv[ 3 ] ); return -1; } rewrite_int_curr_context->lc_alias = aliased; rewrite_int_curr_context = aliased; } else { Debug( LDAP_DEBUG_ANY, "[%s:%d] extra fields" " in rewriteContext" " will be discarded\n%s", fname, lineno, "" ); } } rc = REWRITE_SUCCESS; /* * Compile a rule in current context */ } else if ( strcasecmp( argv[ 0 ], "rewriteRule" ) == 0 ) { if ( argc < 3 ) { Debug( LDAP_DEBUG_ANY, "[%s:%d] rewriteRule needs 'pattern'" " 'subst' ['flags']\n%s", fname, lineno, "" ); return -1; } else if ( argc > 4 ) { Debug( LDAP_DEBUG_ANY, "[%s:%d] extra fields in rewriteRule" " will be discarded\n%s", fname, lineno, "" ); } if ( rewrite_int_curr_context == NULL ) { Debug( LDAP_DEBUG_ANY, "[%s:%d] rewriteRule outside a" " context; will add to default\n%s", fname, lineno, "" ); rewrite_int_curr_context = rewrite_context_find( info, REWRITE_DEFAULT_CONTEXT ); /* * Default context MUST exist in a properly initialized * struct rewrite_info */ assert( rewrite_int_curr_context != NULL ); } rc = rewrite_rule_compile( info, rewrite_int_curr_context, argv[ 1 ], argv[ 2 ], ( argc == 4 ? argv[ 3 ] : "" ) ); /* * Add a plugin map to the map tree */ } else if ( strcasecmp( argv[ 0 ], "rewriteMap" ) == 0 ) { if ( argc < 3 ) { Debug( LDAP_DEBUG_ANY, "[%s:%d] rewriteMap needs at least 'type'" " and 'name' ['args']\n%s", fname, lineno, "" ); return -1; } rc = rewrite_parse_builtin_map( info, fname, lineno, argc, argv ); /* * Set the value of a global scope parameter */ } else if ( strcasecmp( argv[ 0 ], "rewriteParam" ) == 0 ) { if ( argc < 3 ) { Debug( LDAP_DEBUG_ANY, "[%s:%d] rewriteParam needs 'name'" " and 'value'\n%s", fname, lineno, "" ); return -1; } rc = rewrite_param_set( info, argv[ 1 ], argv[ 2 ] ); /* * Error */ } else { Debug( LDAP_DEBUG_ANY, "[%s:%d] unknown command '%s'\n", fname, lineno, "" ); return -1; } return rc; } /* * Compares two maps */ static int rewrite_builtin_map_cmp( const void *c1, const void *c2 ) { const struct rewrite_builtin_map *m1, *m2; m1 = ( const struct rewrite_builtin_map * )c1; m2 = ( const struct rewrite_builtin_map * )c2; assert( m1 != NULL ); assert( m2 != NULL ); assert( m1->lb_name != NULL ); assert( m2->lb_name != NULL ); return strcasecmp( m1->lb_name, m2->lb_name ); } /* * Duplicate map ? */ static int rewrite_builtin_map_dup( void *c1, void *c2 ) { struct rewrite_builtin_map *m1, *m2; m1 = ( struct rewrite_builtin_map * )c1; m2 = ( struct rewrite_builtin_map * )c2; assert( m1 != NULL ); assert( m2 != NULL ); assert( m1->lb_name != NULL ); assert( m2->lb_name != NULL ); return ( strcasecmp( m1->lb_name, m2->lb_name ) == 0 ? -1 : 0 ); } /* * Adds a map to the info map tree */ static int rewrite_builtin_map_insert( struct rewrite_info *info, struct rewrite_builtin_map *map ) { /* * May need a mutex? */ return avl_insert( &info->li_maps, ( caddr_t )map, rewrite_builtin_map_cmp, rewrite_builtin_map_dup ); } /* * Retrieves a map */ struct rewrite_builtin_map * rewrite_builtin_map_find( struct rewrite_info *info, const char *name ) { struct rewrite_builtin_map tmp; assert( info != NULL ); assert( name != NULL ); tmp.lb_name = ( char * )name; return ( struct rewrite_builtin_map * )avl_find( info->li_maps, ( caddr_t )&tmp, rewrite_builtin_map_cmp ); } /* * Parses a plugin map */ static int rewrite_parse_builtin_map( struct rewrite_info *info, const char *fname, int lineno, int argc, char **argv ) { struct rewrite_builtin_map *map; #define MAP_TYPE 1 #define MAP_NAME 2 assert( info != NULL ); assert( fname != NULL ); assert( argc > 2 ); assert( argv != NULL ); assert( strcasecmp( argv[ 0 ], "rewriteMap" ) == 0 ); map = calloc( sizeof( struct rewrite_builtin_map ), 1 ); if ( map == NULL ) { return REWRITE_ERR; } map->lb_name = strdup( argv[ MAP_NAME ] ); if ( map->lb_name == NULL ) { free( map ); return REWRITE_ERR; } /* * Built-in ldap map */ if (( map->lb_mapper = rewrite_mapper_find( argv[ MAP_TYPE ] ))) { map->lb_type = REWRITE_BUILTIN_MAP; #ifdef USE_REWRITE_LDAP_PVT_THREADS if ( ldap_pvt_thread_mutex_init( & map->lb_mutex ) ) { free( map->lb_name ); free( map ); return REWRITE_ERR; } #endif /* USE_REWRITE_LDAP_PVT_THREADS */ map->lb_private = map->lb_mapper->rm_config( fname, lineno, argc - 3, argv + 3 ); /* * Error */ } else { free( map ); Debug( LDAP_DEBUG_ANY, "[%s:%d] unknown map type\n%s", fname, lineno, "" ); return -1; } return rewrite_builtin_map_insert( info, map ); } openldap-2.4.42+dfsg/libraries/librewrite/params.c0000644000175000017500000000631212563404150020605 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 2000-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* ACKNOWLEDGEMENT: * This work was initially developed by Pierangelo Masarati for * inclusion in OpenLDAP Software. */ #include #include "rewrite-int.h" /* * Defines and inits a variable with global scope */ int rewrite_param_set( struct rewrite_info *info, const char *name, const char *value ) { struct rewrite_var *var; int rc = REWRITE_SUCCESS; assert( info != NULL ); assert( name != NULL ); assert( value != NULL ); #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_rdwr_wlock( &info->li_params_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ var = rewrite_var_find( info->li_params, name ); if ( var != NULL ) { assert( var->lv_value.bv_val != NULL ); free( var->lv_value.bv_val ); var->lv_value.bv_val = strdup( value ); var->lv_value.bv_len = strlen( value ); } else { var = rewrite_var_insert( &info->li_params, name, value ); } if ( var == NULL || var->lv_value.bv_val == NULL ) { rc = REWRITE_ERR; } #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_rdwr_wunlock( &info->li_params_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ return rc; } /* * Gets a var with global scope */ int rewrite_param_get( struct rewrite_info *info, const char *name, struct berval *value ) { struct rewrite_var *var; int rc = REWRITE_SUCCESS; assert( info != NULL ); assert( name != NULL ); assert( value != NULL ); value->bv_val = NULL; value->bv_len = 0; #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_rdwr_rlock( &info->li_params_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ var = rewrite_var_find( info->li_params, name ); if ( var != NULL ) { value->bv_val = strdup( var->lv_value.bv_val ); value->bv_len = var->lv_value.bv_len; } if ( var == NULL || value->bv_val == NULL ) { rc = REWRITE_ERR; } #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_rdwr_runlock( &info->li_params_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ return REWRITE_SUCCESS; } static void rewrite_param_free( void *tmp ) { struct rewrite_var *var = ( struct rewrite_var * )tmp; assert( var != NULL ); assert( var->lv_name != NULL ); assert( var->lv_value.bv_val != NULL ); free( var->lv_name ); free( var->lv_value.bv_val ); free( var ); } /* * Destroys the parameter tree */ int rewrite_param_destroy( struct rewrite_info *info ) { int count; assert( info != NULL ); #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_rdwr_wlock( &info->li_params_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ count = avl_free( info->li_params, rewrite_param_free ); info->li_params = NULL; #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_rdwr_wunlock( &info->li_params_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ return REWRITE_SUCCESS; } openldap-2.4.42+dfsg/libraries/librewrite/map.c0000644000175000017500000002575512563404150020113 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 2000-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* ACKNOWLEDGEMENT: * This work was initially developed by Pierangelo Masarati for * inclusion in OpenLDAP Software. */ #include #include #ifdef HAVE_PWD_H #include #endif #include "rewrite-int.h" #include "rewrite-map.h" static int num_mappers; static const rewrite_mapper **mappers; #define MAPPER_ALLOC 8 struct rewrite_map * rewrite_map_parse( struct rewrite_info *info, const char *string, const char **currpos ) { struct rewrite_map *map = NULL; struct rewrite_subst *subst = NULL; char *s, *begin = NULL, *end; const char *p; int l, cnt, mtx = 0, rc = 0; assert( info != NULL ); assert( string != NULL ); assert( currpos != NULL ); *currpos = NULL; /* * Go to the end of the map invocation (the right closing brace) */ for ( p = string, cnt = 1; p[ 0 ] != '\0' && cnt > 0; p++ ) { if ( IS_REWRITE_SUBMATCH_ESCAPE( p[ 0 ] ) ) { /* * '%' marks the beginning of a new map */ if ( p[ 1 ] == '{' ) { cnt++; /* * '%' followed by a digit may mark the beginning * of an old map */ } else if ( isdigit( (unsigned char) p[ 1 ] ) && p[ 2 ] == '{' ) { cnt++; p++; } if ( p[ 1 ] != '\0' ) { p++; } } else if ( p[ 0 ] == '}' ) { cnt--; } } if ( cnt != 0 ) { return NULL; } *currpos = p; /* * Copy the map invocation */ l = p - string - 1; s = calloc( sizeof( char ), l + 1 ); if ( s == NULL ) { return NULL; } AC_MEMCPY( s, string, l ); s[ l ] = 0; /* * Isolate the map name (except for variable deref) */ switch ( s[ 0 ] ) { case REWRITE_OPERATOR_VARIABLE_GET: case REWRITE_OPERATOR_PARAM_GET: break; default: begin = strchr( s, '(' ); if ( begin == NULL ) { rc = -1; goto cleanup; } begin[ 0 ] = '\0'; begin++; break; } /* * Check for special map types */ p = s; switch ( p[ 0 ] ) { case REWRITE_OPERATOR_SUBCONTEXT: case REWRITE_OPERATOR_COMMAND: case REWRITE_OPERATOR_VARIABLE_SET: case REWRITE_OPERATOR_VARIABLE_GET: case REWRITE_OPERATOR_PARAM_GET: p++; break; } /* * Variable set and get may be repeated to indicate session-wide * instead of operation-wide variables */ switch ( p[ 0 ] ) { case REWRITE_OPERATOR_VARIABLE_SET: case REWRITE_OPERATOR_VARIABLE_GET: p++; break; } /* * Variable get token can be appended to variable set to mean store * AND rewrite */ if ( p[ 0 ] == REWRITE_OPERATOR_VARIABLE_GET ) { p++; } /* * Check the syntax of the variable name */ if ( !isalpha( (unsigned char) p[ 0 ] ) ) { rc = -1; goto cleanup; } for ( p++; p[ 0 ] != '\0'; p++ ) { if ( !isalnum( (unsigned char) p[ 0 ] ) ) { rc = -1; goto cleanup; } } /* * Isolate the argument of the map (except for variable deref) */ switch ( s[ 0 ] ) { case REWRITE_OPERATOR_VARIABLE_GET: case REWRITE_OPERATOR_PARAM_GET: break; default: end = strrchr( begin, ')' ); if ( end == NULL ) { rc = -1; goto cleanup; } end[ 0 ] = '\0'; /* * Compile the substitution pattern of the map argument */ subst = rewrite_subst_compile( info, begin ); if ( subst == NULL ) { rc = -1; goto cleanup; } break; } /* * Create the map */ map = calloc( sizeof( struct rewrite_map ), 1 ); if ( map == NULL ) { rc = -1; goto cleanup; } memset( map, 0, sizeof( struct rewrite_map ) ); #ifdef USE_REWRITE_LDAP_PVT_THREADS if ( ldap_pvt_thread_mutex_init( &map->lm_mutex ) ) { rc = -1; goto cleanup; } ++mtx; #endif /* USE_REWRITE_LDAP_PVT_THREADS */ /* * No subst for variable deref */ switch ( s[ 0 ] ) { case REWRITE_OPERATOR_VARIABLE_GET: case REWRITE_OPERATOR_PARAM_GET: break; default: map->lm_subst = subst; break; } /* * Parses special map types */ switch ( s[ 0 ] ) { /* * Subcontext */ case REWRITE_OPERATOR_SUBCONTEXT: /* '>' */ /* * Fetch the rewrite context * it MUST have been defined previously */ map->lm_type = REWRITE_MAP_SUBCONTEXT; map->lm_name = strdup( s + 1 ); if ( map->lm_name == NULL ) { rc = -1; goto cleanup; } map->lm_data = rewrite_context_find( info, s + 1 ); if ( map->lm_data == NULL ) { rc = -1; goto cleanup; } break; /* * External command (not implemented yet) */ case REWRITE_OPERATOR_COMMAND: /* '|' */ rc = -1; goto cleanup; /* * Variable set */ case REWRITE_OPERATOR_VARIABLE_SET: /* '&' */ if ( s[ 1 ] == REWRITE_OPERATOR_VARIABLE_SET ) { if ( s[ 2 ] == REWRITE_OPERATOR_VARIABLE_GET ) { map->lm_type = REWRITE_MAP_SETW_SESN_VAR; map->lm_name = strdup( s + 3 ); } else { map->lm_type = REWRITE_MAP_SET_SESN_VAR; map->lm_name = strdup( s + 2 ); } } else { if ( s[ 1 ] == REWRITE_OPERATOR_VARIABLE_GET ) { map->lm_type = REWRITE_MAP_SETW_OP_VAR; map->lm_name = strdup( s + 2 ); } else { map->lm_type = REWRITE_MAP_SET_OP_VAR; map->lm_name = strdup( s + 1 ); } } if ( map->lm_name == NULL ) { rc = -1; goto cleanup; } break; /* * Variable dereference */ case REWRITE_OPERATOR_VARIABLE_GET: /* '*' */ if ( s[ 1 ] == REWRITE_OPERATOR_VARIABLE_GET ) { map->lm_type = REWRITE_MAP_GET_SESN_VAR; map->lm_name = strdup( s + 2 ); } else { map->lm_type = REWRITE_MAP_GET_OP_VAR; map->lm_name = strdup( s + 1 ); } if ( map->lm_name == NULL ) { rc = -1; goto cleanup; } break; /* * Parameter */ case REWRITE_OPERATOR_PARAM_GET: /* '$' */ map->lm_type = REWRITE_MAP_GET_PARAM; map->lm_name = strdup( s + 1 ); if ( map->lm_name == NULL ) { rc = -1; goto cleanup; } break; /* * Built-in map */ default: map->lm_type = REWRITE_MAP_BUILTIN; map->lm_name = strdup( s ); if ( map->lm_name == NULL ) { rc = -1; goto cleanup; } map->lm_data = rewrite_builtin_map_find( info, s ); if ( map->lm_data == NULL ) { rc = -1; goto cleanup; } break; } cleanup: free( s ); if ( rc ) { if ( subst != NULL ) { free( subst ); } if ( map ) { #ifdef USE_REWRITE_LDAP_PVT_THREADS if ( mtx ) { ldap_pvt_thread_mutex_destroy( &map->lm_mutex ); } #endif /* USE_REWRITE_LDAP_PVT_THREADS */ if ( map->lm_name ) { free( map->lm_name ); map->lm_name = NULL; } free( map ); map = NULL; } } return map; } /* * Applies the new map type */ int rewrite_map_apply( struct rewrite_info *info, struct rewrite_op *op, struct rewrite_map *map, struct berval *key, struct berval *val ) { int rc = REWRITE_SUCCESS; assert( info != NULL ); assert( op != NULL ); assert( map != NULL ); assert( key != NULL ); assert( val != NULL ); val->bv_val = NULL; val->bv_len = 0; switch ( map->lm_type ) { case REWRITE_MAP_SUBCONTEXT: rc = rewrite_context_apply( info, op, ( struct rewrite_context * )map->lm_data, key->bv_val, &val->bv_val ); if ( val->bv_val != NULL ) { if ( val->bv_val == key->bv_val ) { val->bv_len = key->bv_len; key->bv_val = NULL; } else { val->bv_len = strlen( val->bv_val ); } } break; case REWRITE_MAP_SET_OP_VAR: case REWRITE_MAP_SETW_OP_VAR: rc = rewrite_var_set( &op->lo_vars, map->lm_name, key->bv_val, 1 ) ? REWRITE_SUCCESS : REWRITE_ERR; if ( rc == REWRITE_SUCCESS ) { if ( map->lm_type == REWRITE_MAP_SET_OP_VAR ) { val->bv_val = strdup( "" ); } else { val->bv_val = strdup( key->bv_val ); val->bv_len = key->bv_len; } if ( val->bv_val == NULL ) { rc = REWRITE_ERR; } } break; case REWRITE_MAP_GET_OP_VAR: { struct rewrite_var *var; var = rewrite_var_find( op->lo_vars, map->lm_name ); if ( var == NULL ) { rc = REWRITE_ERR; } else { val->bv_val = strdup( var->lv_value.bv_val ); val->bv_len = var->lv_value.bv_len; if ( val->bv_val == NULL ) { rc = REWRITE_ERR; } } break; } case REWRITE_MAP_SET_SESN_VAR: case REWRITE_MAP_SETW_SESN_VAR: if ( op->lo_cookie == NULL ) { rc = REWRITE_ERR; break; } rc = rewrite_session_var_set( info, op->lo_cookie, map->lm_name, key->bv_val ); if ( rc == REWRITE_SUCCESS ) { if ( map->lm_type == REWRITE_MAP_SET_SESN_VAR ) { val->bv_val = strdup( "" ); } else { val->bv_val = strdup( key->bv_val ); val->bv_len = key->bv_len; } if ( val->bv_val == NULL ) { rc = REWRITE_ERR; } } break; case REWRITE_MAP_GET_SESN_VAR: rc = rewrite_session_var_get( info, op->lo_cookie, map->lm_name, val ); break; case REWRITE_MAP_GET_PARAM: rc = rewrite_param_get( info, map->lm_name, val ); break; case REWRITE_MAP_BUILTIN: { struct rewrite_builtin_map *bmap = map->lm_data; if ( bmap->lb_mapper && bmap->lb_mapper->rm_apply ) rc = bmap->lb_mapper->rm_apply( bmap->lb_private, key->bv_val, val ); else rc = REWRITE_ERR; break; break; } default: rc = REWRITE_ERR; break; } return rc; } void rewrite_builtin_map_free( void *tmp ) { struct rewrite_builtin_map *map = ( struct rewrite_builtin_map * )tmp; assert( map != NULL ); if ( map->lb_mapper && map->lb_mapper->rm_destroy ) map->lb_mapper->rm_destroy( map->lb_private ); free( map->lb_name ); free( map ); } int rewrite_map_destroy( struct rewrite_map **pmap ) { struct rewrite_map *map; assert( pmap != NULL ); assert( *pmap != NULL ); map = *pmap; #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_mutex_lock( &map->lm_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ if ( map->lm_name ) { free( map->lm_name ); map->lm_name = NULL; } if ( map->lm_subst ) { rewrite_subst_destroy( &map->lm_subst ); } #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_mutex_unlock( &map->lm_mutex ); ldap_pvt_thread_mutex_destroy( &map->lm_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ free( map ); *pmap = NULL; return 0; } /* ldapmap.c */ extern const rewrite_mapper rewrite_ldap_mapper; const rewrite_mapper * rewrite_mapper_find( const char *name ) { int i; if ( !strcasecmp( name, "ldap" )) return &rewrite_ldap_mapper; for (i=0; irm_name )) return mappers[i]; return NULL; } int rewrite_mapper_register( const rewrite_mapper *map ) { if ( num_mappers % MAPPER_ALLOC == 0 ) { const rewrite_mapper **mnew; mnew = realloc( mappers, (num_mappers + MAPPER_ALLOC) * sizeof( rewrite_mapper * )); if ( mnew ) mappers = mnew; else return -1; } mappers[num_mappers++] = map; return 0; } int rewrite_mapper_unregister( const rewrite_mapper *map ) { int i; for (i = 0; i. * * Copyright 2000-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* ACKNOWLEDGEMENT: * This work was initially developed by Pierangelo Masarati for * inclusion in OpenLDAP Software. */ #include #define LDAP_DEPRECATED 1 #include "rewrite-int.h" #include "rewrite-map.h" typedef enum { MAP_LDAP_UNKNOWN, MAP_LDAP_EVERYTIME, MAP_LDAP_NOW, MAP_LDAP_LATER } bindwhen_t; /* * LDAP map data structure */ struct ldap_map_data { char *lm_url; LDAPURLDesc *lm_lud; int lm_version; char *lm_binddn; struct berval lm_cred; bindwhen_t lm_when; LDAP *lm_ld; int lm_wantdn; char *lm_attrs[ 2 ]; #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_mutex_t lm_mutex; #endif /* USE_REWRITE_LDAP_PVT_THREADS */ }; static void map_ldap_free( struct ldap_map_data *data ) { assert( data != NULL ); if ( data->lm_url != NULL ) { free( data->lm_url ); } if ( data->lm_lud != NULL ) { ldap_free_urldesc( data->lm_lud ); } if ( data->lm_binddn != NULL ) { free( data->lm_binddn ); } if ( data->lm_cred.bv_val != NULL ) { memset( data->lm_cred.bv_val, 0, data->lm_cred.bv_len ); free( data->lm_cred.bv_val ); data->lm_cred.bv_val = NULL; data->lm_cred.bv_len = 0; } if ( data->lm_when != MAP_LDAP_EVERYTIME && data->lm_ld != NULL ) { ldap_unbind_ext( data->lm_ld, NULL, NULL ); } free( data ); } static void * map_ldap_parse( const char *fname, int lineno, int argc, char **argv ) { struct ldap_map_data *data; char *p, *uri; assert( fname != NULL ); assert( argv != NULL ); data = calloc( sizeof( struct ldap_map_data ), 1 ); if ( data == NULL ) { return NULL; } if ( argc < 1 ) { Debug( LDAP_DEBUG_ANY, "[%s:%d] ldap map needs URI\n%s", fname, lineno, "" ); free( data ); return NULL; } uri = argv[ 0 ]; if ( strncasecmp( uri, "uri=", STRLENOF( "uri=" ) ) == 0 ) { uri += STRLENOF( "uri=" ); } data->lm_url = strdup( uri ); if ( data->lm_url == NULL ) { map_ldap_free( data ); return NULL; } if ( ldap_url_parse( uri, &data->lm_lud ) != REWRITE_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "[%s:%d] illegal URI '%s'\n", fname, lineno, argv[ 0 ] ); map_ldap_free( data ); return NULL; } /* trim everything after [host][:port] */ p = strchr( data->lm_url, '/' ); assert( p[ 1 ] == '/' ); if ( ( p = strchr( p + 2, '/' ) ) != NULL ) { p[ 0 ] = '\0'; } if ( data->lm_lud->lud_attrs == NULL ) { data->lm_attrs[ 0 ] = LDAP_NO_ATTRS; data->lm_wantdn = 1; } else { if ( data->lm_lud->lud_attrs[ 1 ] != NULL ) { Debug( LDAP_DEBUG_ANY, "[%s:%d] only one attribute allowed in URI\n", fname, lineno, 0 ); map_ldap_free( data ); return NULL; } if ( strcasecmp( data->lm_lud->lud_attrs[ 0 ], "dn" ) == 0 || strcasecmp( data->lm_lud->lud_attrs[ 0 ], "entryDN" ) == 0 ) { ldap_memfree( data->lm_lud->lud_attrs[ 0 ] ); ldap_memfree( data->lm_lud->lud_attrs ); data->lm_lud->lud_attrs = NULL; data->lm_attrs[ 0 ] = LDAP_NO_ATTRS; data->lm_wantdn = 1; } else { data->lm_attrs[ 0 ] = data->lm_lud->lud_attrs[ 0 ]; } } data->lm_attrs[ 1 ] = NULL; /* safe defaults */ data->lm_version = LDAP_VERSION3; for ( argc--, argv++; argc > 0; argc--, argv++ ) { if ( strncasecmp( argv[ 0 ], "binddn=", STRLENOF( "binddn=" ) ) == 0 ) { char *p = argv[ 0 ] + STRLENOF( "binddn=" ); int l; if ( p[ 0 ] == '\"' || p [ 0 ] == '\'' ) { l = strlen( p ) - 2; p++; if ( p[ l ] != p[ 0 ] ) { map_ldap_free( data ); return NULL; } } else { l = strlen( p ); } data->lm_binddn = strdup( p ); if ( data->lm_binddn == NULL ) { map_ldap_free( data ); return NULL; } if ( data->lm_binddn[ l ] == '\"' || data->lm_binddn[ l ] == '\'' ) { data->lm_binddn[ l ] = '\0'; } /* deprecated */ } else if ( strncasecmp( argv[ 0 ], "bindpw=", STRLENOF( "bindpw=" ) ) == 0 ) { ber_str2bv( argv[ 0 ] + STRLENOF( "bindpw=" ), 0, 1, &data->lm_cred ); if ( data->lm_cred.bv_val == NULL ) { map_ldap_free( data ); return NULL; } } else if ( strncasecmp( argv[ 0 ], "credentials=", STRLENOF( "credentials=" ) ) == 0 ) { ber_str2bv( argv[ 0 ] + STRLENOF( "credentials=" ), 0, 1, &data->lm_cred ); if ( data->lm_cred.bv_val == NULL ) { map_ldap_free( data ); return NULL; } } else if ( strncasecmp( argv[ 0 ], "bindwhen=", STRLENOF( "bindwhen=" ) ) == 0 ) { char *p = argv[ 0 ] + STRLENOF( "bindwhen=" ); if ( strcasecmp( p, "now" ) == 0 ) { int rc; data->lm_when = MAP_LDAP_NOW; /* * Init LDAP handler ... */ rc = ldap_initialize( &data->lm_ld, data->lm_url ); if ( rc != LDAP_SUCCESS ) { map_ldap_free( data ); return NULL; } ldap_set_option( data->lm_ld, LDAP_OPT_PROTOCOL_VERSION, (void *)&data->lm_version ); #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_mutex_init( &data->lm_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ } else if ( strcasecmp( p, "later" ) == 0 ) { data->lm_when = MAP_LDAP_LATER; #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_mutex_init( &data->lm_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ } else if ( strcasecmp( p, "everytime" ) == 0 ) { data->lm_when = MAP_LDAP_EVERYTIME; } else { /* ignore ... */ } } else if ( strncasecmp( argv[ 0 ], "version=", STRLENOF( "version=" ) ) == 0 ) { if ( lutil_atoi( &data->lm_version, argv[ 0 ] + STRLENOF( "version=" ) ) ) { map_ldap_free( data ); return NULL; } switch ( data->lm_version ) { case LDAP_VERSION2: case LDAP_VERSION3: break; default: Debug( LDAP_DEBUG_ANY, "[%s:%d] unknown version %s\n", fname, lineno, p ); map_ldap_free( data ); return NULL; } } else { Debug( LDAP_DEBUG_ANY, "[%s:%d] unknown option %s (ignored)\n", fname, lineno, argv[0] ); } } if ( data->lm_when == MAP_LDAP_UNKNOWN ) { data->lm_when = MAP_LDAP_EVERYTIME; } return ( void * )data; } static int map_ldap_apply( void *private, const char *filter, struct berval *val ) { LDAP *ld; LDAPMessage *res = NULL, *entry; int rc; struct ldap_map_data *data = private; LDAPURLDesc *lud = data->lm_lud; int first_try = 1, set_version = 0; assert( private != NULL ); assert( filter != NULL ); assert( val != NULL ); val->bv_val = NULL; val->bv_len = 0; if ( data->lm_when == MAP_LDAP_EVERYTIME ) { rc = ldap_initialize( &ld, data->lm_url ); set_version = 1; } else { #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_mutex_lock( &data->lm_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ rc = LDAP_SUCCESS; if ( data->lm_when == MAP_LDAP_LATER && data->lm_ld == NULL ) { rc = ldap_initialize( &data->lm_ld, data->lm_url ); set_version = 1; } ld = data->lm_ld; } if ( rc != LDAP_SUCCESS ) { rc = REWRITE_ERR; goto rc_return; } do_bind:; if ( set_version ) { ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, (void *)&data->lm_version ); set_version = 0; } if ( data->lm_binddn != NULL ) { rc = ldap_sasl_bind_s( ld, data->lm_binddn, LDAP_SASL_SIMPLE, &data->lm_cred, NULL, NULL, NULL ); if ( rc == LDAP_SERVER_DOWN && first_try ) { first_try = 0; if ( ldap_initialize( &ld, data->lm_url ) != LDAP_SUCCESS ) { rc = REWRITE_ERR; goto rc_return; } set_version = 1; goto do_bind; } else if ( rc != REWRITE_SUCCESS ) { rc = REWRITE_ERR; goto rc_return; } } rc = ldap_search_ext_s( ld, lud->lud_dn, lud->lud_scope, ( char * )filter, data->lm_attrs, 0, NULL, NULL, NULL, 1, &res ); if ( rc == LDAP_SERVER_DOWN && first_try ) { first_try = 0; if ( ldap_initialize( &ld, data->lm_url ) != LDAP_SUCCESS ) { rc = REWRITE_ERR; goto rc_return; } set_version = 1; goto do_bind; } else if ( rc != LDAP_SUCCESS ) { rc = REWRITE_ERR; goto rc_return; } if ( ldap_count_entries( ld, res ) != 1 ) { ldap_msgfree( res ); rc = REWRITE_ERR; goto rc_return; } entry = ldap_first_entry( ld, res ); assert( entry != NULL ); if ( data->lm_wantdn == 1 ) { /* * dn is newly allocated, so there's no need to strdup it */ val->bv_val = ldap_get_dn( ld, entry ); val->bv_len = strlen( val->bv_val ); } else { struct berval **values; values = ldap_get_values_len( ld, entry, data->lm_attrs[ 0 ] ); if ( values != NULL ) { if ( values[ 0 ] != NULL && values[ 0 ]->bv_val != NULL ) { #if 0 /* NOTE: in principle, multiple values * should not be acceptable according * to the current API; ignore by now */ if ( values[ 1 ] != NULL ) { /* error */ } #endif ber_dupbv( val, values[ 0 ] ); } ldap_value_free_len( values ); } } ldap_msgfree( res ); if ( val->bv_val == NULL ) { rc = REWRITE_ERR; goto rc_return; } rc_return:; if ( data->lm_when == MAP_LDAP_EVERYTIME ) { if ( ld != NULL ) { ldap_unbind_ext( ld, NULL, NULL ); } } else { data->lm_ld = ld; #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_mutex_unlock( &data->lm_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ } return rc; } static int map_ldap_destroy( void *private ) { struct ldap_map_data *data = private; assert( private != NULL ); map_ldap_free( data ); return 0; } const rewrite_mapper rewrite_ldap_mapper = { "ldap", map_ldap_parse, map_ldap_apply, map_ldap_destroy }; openldap-2.4.42+dfsg/libraries/librewrite/rewrite-map.h0000644000175000017500000000153312563404150021563 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 2000-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* ACKNOWLEDGEMENT: * This work was initially developed by Pierangelo Masarati for * inclusion in OpenLDAP Software. */ #ifndef MAP_H #define MAP_H /* * Retrieves a builtin map */ LDAP_REWRITE_F (struct rewrite_builtin_map *) rewrite_builtin_map_find( struct rewrite_info *info, const char *name ); #endif /* MAP_H */ openldap-2.4.42+dfsg/libraries/librewrite/rewrite-int.h0000644000175000017500000003310212563404150021575 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 2000-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* ACKNOWLEDGEMENT: * This work was initially developed by Pierangelo Masarati for * inclusion in OpenLDAP Software. */ #ifndef REWRITE_INT_H #define REWRITE_INT_H /* * These are required by every file of the library, so they're included here */ #include #include #include #include #include #include #include #include #include #define LDAP_DEFINE_LDAP_DEBUG #include #include #include #include #define malloc(x) ber_memalloc(x) #define calloc(x,y) ber_memcalloc(x,y) #define realloc(x,y) ber_memrealloc(x,y) #define free(x) ber_memfree(x) #undef strdup #define strdup(x) ber_strdup(x) /* Uncomment to use ldap pvt threads */ #define USE_REWRITE_LDAP_PVT_THREADS #include /* * For details, see RATIONALE. */ #define REWRITE_MAX_MATCH 11 /* 0: overall string; 1-9: submatches */ #define REWRITE_MAX_PASSES 100 /* * Submatch escape char */ /* the '\' conflicts with slapd.conf parsing */ /* #define REWRITE_SUBMATCH_ESCAPE '\\' */ #define REWRITE_SUBMATCH_ESCAPE_ORIG '%' #define REWRITE_SUBMATCH_ESCAPE '$' #define IS_REWRITE_SUBMATCH_ESCAPE(c) \ ((c) == REWRITE_SUBMATCH_ESCAPE || (c) == REWRITE_SUBMATCH_ESCAPE_ORIG) /* * REGEX flags */ #define REWRITE_FLAG_HONORCASE 'C' #define REWRITE_FLAG_BASICREGEX 'R' /* * Action flags */ #define REWRITE_FLAG_EXECONCE ':' #define REWRITE_FLAG_STOP '@' #define REWRITE_FLAG_UNWILLING '#' #define REWRITE_FLAG_GOTO 'G' /* requires an arg */ #define REWRITE_FLAG_USER 'U' /* requires an arg */ #define REWRITE_FLAG_MAX_PASSES 'M' /* requires an arg */ #define REWRITE_FLAG_IGNORE_ERR 'I' /* * Map operators */ #define REWRITE_OPERATOR_SUBCONTEXT '>' #define REWRITE_OPERATOR_COMMAND '|' #define REWRITE_OPERATOR_VARIABLE_SET '&' #define REWRITE_OPERATOR_VARIABLE_GET '*' #define REWRITE_OPERATOR_PARAM_GET '$' /*********** * PRIVATE * ***********/ /* * Action */ struct rewrite_action { struct rewrite_action *la_next; #define REWRITE_ACTION_STOP 0x0001 #define REWRITE_ACTION_UNWILLING 0x0002 #define REWRITE_ACTION_GOTO 0x0003 #define REWRITE_ACTION_IGNORE_ERR 0x0004 #define REWRITE_ACTION_USER 0x0005 int la_type; void *la_args; }; /* * Map */ struct rewrite_map { /* * Legacy stuff */ #define REWRITE_MAP_XFILEMAP 0x0001 /* Rough implementation! */ #define REWRITE_MAP_XPWDMAP 0x0002 /* uid -> gecos */ #define REWRITE_MAP_XLDAPMAP 0x0003 /* Not implemented yet! */ /* * Maps with args */ #define REWRITE_MAP_SUBCONTEXT 0x0101 #define REWRITE_MAP_SET_OP_VAR 0x0102 #define REWRITE_MAP_SETW_OP_VAR 0x0103 #define REWRITE_MAP_GET_OP_VAR 0x0104 #define REWRITE_MAP_SET_SESN_VAR 0x0105 #define REWRITE_MAP_SETW_SESN_VAR 0x0106 #define REWRITE_MAP_GET_SESN_VAR 0x0107 #define REWRITE_MAP_GET_PARAM 0x0108 #define REWRITE_MAP_BUILTIN 0x0109 int lm_type; char *lm_name; void *lm_data; /* * Old maps store private data in _lm_args; * new maps store the substitution pattern in _lm_subst */ union { void *_lm_args; struct rewrite_subst *_lm_subst; } lm_union; #define lm_args lm_union._lm_args #define lm_subst lm_union._lm_subst #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_mutex_t lm_mutex; #endif /* USE_REWRITE_LDAP_PVT_THREADS */ }; /* * Builtin maps */ struct rewrite_builtin_map { #define REWRITE_BUILTIN_MAP 0x0200 int lb_type; char *lb_name; void *lb_private; const rewrite_mapper *lb_mapper; #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_mutex_t lb_mutex; #endif /* USE_REWRITE_LDAP_PVT_THREADS */ }; /* * Submatch substitution */ struct rewrite_submatch { #define REWRITE_SUBMATCH_ASIS 0x0000 #define REWRITE_SUBMATCH_XMAP 0x0001 #define REWRITE_SUBMATCH_MAP_W_ARG 0x0002 int ls_type; struct rewrite_map *ls_map; int ls_submatch; /* * The first one represents the index of the submatch in case * the map has single submatch as argument; * the latter represents the map argument scheme in case * the map has substitution string argument form */ }; /* * Pattern substitution */ struct rewrite_subst { size_t lt_subs_len; struct berval *lt_subs; int lt_num_submatch; struct rewrite_submatch *lt_submatch; }; /* * Rule */ struct rewrite_rule { struct rewrite_rule *lr_next; struct rewrite_rule *lr_prev; char *lr_pattern; char *lr_subststring; char *lr_flagstring; regex_t lr_regex; /* * I was thinking about some kind of per-rule mutex, but there's * probably no need, because rules after compilation are only read; * however, I need to check whether regexec is reentrant ... */ struct rewrite_subst *lr_subst; #define REWRITE_REGEX_ICASE REG_ICASE #define REWRITE_REGEX_EXTENDED REG_EXTENDED int lr_flags; #define REWRITE_RECURSE 0x0001 #define REWRITE_EXEC_ONCE 0x0002 int lr_mode; int lr_max_passes; struct rewrite_action *lr_action; }; /* * Rewrite Context (set of rules) */ struct rewrite_context { char *lc_name; struct rewrite_context *lc_alias; struct rewrite_rule *lc_rule; }; /* * Session */ struct rewrite_session { void *ls_cookie; Avlnode *ls_vars; #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_rdwr_t ls_vars_mutex; ldap_pvt_thread_mutex_t ls_mutex; #endif /* USE_REWRITE_LDAP_PVT_THREADS */ int ls_count; }; /* * Variable */ struct rewrite_var { char *lv_name; int lv_flags; struct berval lv_value; }; /* * Operation */ struct rewrite_op { int lo_num_passes; int lo_depth; #if 0 /* FIXME: not used anywhere! (debug? then, why strdup?) */ char *lo_string; #endif char *lo_result; Avlnode *lo_vars; const void *lo_cookie; }; /********** * PUBLIC * **********/ /* * Rewrite info */ struct rewrite_info { Avlnode *li_context; Avlnode *li_maps; /* * No global mutex because maps are read only at * config time */ Avlnode *li_params; Avlnode *li_cookies; int li_num_cookies; #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_rdwr_t li_params_mutex; ldap_pvt_thread_rdwr_t li_cookies_mutex; #endif /* USE_REWRITE_LDAP_PVT_THREADS */ /* * Default to `off'; * use `rewriteEngine {on|off}' directive to alter */ int li_state; /* * Defaults to REWRITE_MAXPASSES; * use `rewriteMaxPasses numPasses' directive to alter */ #define REWRITE_MAXPASSES 100 int li_max_passes; int li_max_passes_per_rule; /* * Behavior in case a NULL or non-existent context is required */ int li_rewrite_mode; }; /*********** * PRIVATE * ***********/ LDAP_REWRITE_V (struct rewrite_context*) rewrite_int_curr_context; /* * Maps */ /* * Parses a map (also in legacy 'x' version) */ LDAP_REWRITE_F (struct rewrite_map *) rewrite_map_parse( struct rewrite_info *info, const char *s, const char **end ); LDAP_REWRITE_F (struct rewrite_map *) rewrite_xmap_parse( struct rewrite_info *info, const char *s, const char **end ); /* * Resolves key in val by means of map (also in legacy 'x' version) */ LDAP_REWRITE_F (int) rewrite_map_apply( struct rewrite_info *info, struct rewrite_op *op, struct rewrite_map *map, struct berval *key, struct berval *val ); LDAP_REWRITE_F (int) rewrite_xmap_apply( struct rewrite_info *info, struct rewrite_op *op, struct rewrite_map *map, struct berval *key, struct berval *val ); LDAP_REWRITE_F (int) rewrite_map_destroy( struct rewrite_map **map ); LDAP_REWRITE_F (int) rewrite_xmap_destroy( struct rewrite_map **map ); LDAP_REWRITE_F (void) rewrite_builtin_map_free( void *map ); /* * Submatch substitution */ /* * Compiles a substitution pattern */ LDAP_REWRITE_F (struct rewrite_subst *) rewrite_subst_compile( struct rewrite_info *info, const char *result ); /* * Substitutes a portion of rewritten string according to substitution * pattern using submatches */ LDAP_REWRITE_F (int) rewrite_subst_apply( struct rewrite_info *info, struct rewrite_op *op, struct rewrite_subst *subst, const char *string, const regmatch_t *match, struct berval *val ); LDAP_REWRITE_F (int) rewrite_subst_destroy( struct rewrite_subst **subst ); /* * Rules */ /* * Compiles the rule and appends it at the running context */ LDAP_REWRITE_F (int) rewrite_rule_compile( struct rewrite_info *info, struct rewrite_context *context, const char *pattern, const char *result, const char *flagstring ); /* * Rewrites string according to rule; may return: * REWRITE_REGEXEC_OK: fine; if *result != NULL rule matched * and rewrite succeeded. * REWRITE_REGEXEC_STOP: fine, rule matched; stop processing * following rules * REWRITE_REGEXEC_UNWILL: rule matched; force 'unwilling to perform' * REWRITE_REGEXEC_ERR: an error occurred */ LDAP_REWRITE_F (int) rewrite_rule_apply( struct rewrite_info *info, struct rewrite_op *op, struct rewrite_rule *rule, const char *string, char **result ); LDAP_REWRITE_F (int) rewrite_rule_destroy( struct rewrite_rule **rule ); /* * Sessions */ /* * Fetches a struct rewrite_session */ LDAP_REWRITE_F (struct rewrite_session *) rewrite_session_find( struct rewrite_info *info, const void *cookie ); /* * Defines and inits a variable with session scope */ LDAP_REWRITE_F (int) rewrite_session_var_set_f( struct rewrite_info *info, const void *cookie, const char *name, const char *value, int flags ); /* * Gets a var with session scope */ LDAP_REWRITE_F (int) rewrite_session_var_get( struct rewrite_info *info, const void *cookie, const char *name, struct berval *val ); /* * Deletes a session */ LDAP_REWRITE_F (int) rewrite_session_delete( struct rewrite_info *info, const void *cookie ); /* * Destroys the cookie tree */ LDAP_REWRITE_F (int) rewrite_session_destroy( struct rewrite_info *info ); /* * Vars */ /* * Finds a var */ LDAP_REWRITE_F (struct rewrite_var *) rewrite_var_find( Avlnode *tree, const char *name ); /* * Replaces the value of a variable */ LDAP_REWRITE_F (int) rewrite_var_replace( struct rewrite_var *var, const char *value, int flags ); /* * Inserts a newly created var */ LDAP_REWRITE_F (struct rewrite_var *) rewrite_var_insert_f( Avlnode **tree, const char *name, const char *value, int flags ); #define rewrite_var_insert(tree, name, value) \ rewrite_var_insert_f((tree), (name), (value), \ REWRITE_VAR_UPDATE|REWRITE_VAR_COPY_NAME|REWRITE_VAR_COPY_VALUE) /* * Sets/inserts a var */ LDAP_REWRITE_F (struct rewrite_var *) rewrite_var_set_f( Avlnode **tree, const char *name, const char *value, int flags ); #define rewrite_var_set(tree, name, value, insert) \ rewrite_var_set_f((tree), (name), (value), \ REWRITE_VAR_UPDATE|REWRITE_VAR_COPY_NAME|REWRITE_VAR_COPY_VALUE|((insert)? REWRITE_VAR_INSERT : 0)) /* * Deletes a var tree */ LDAP_REWRITE_F (int) rewrite_var_delete( Avlnode *tree ); /* * Contexts */ /* * Finds the context named rewriteContext in the context tree */ LDAP_REWRITE_F (struct rewrite_context *) rewrite_context_find( struct rewrite_info *info, const char *rewriteContext ); /* * Creates a new context called rewriteContext and stores in into the tree */ LDAP_REWRITE_F (struct rewrite_context *) rewrite_context_create( struct rewrite_info *info, const char *rewriteContext ); /* * Rewrites string according to context; may return: * OK: fine; if *result != NULL rule matched and rewrite succeeded. * STOP: fine, rule matched; stop processing following rules * UNWILL: rule matched; force 'unwilling to perform' */ LDAP_REWRITE_F (int) rewrite_context_apply( struct rewrite_info *info, struct rewrite_op *op, struct rewrite_context *context, const char *string, char **result ); LDAP_REWRITE_F (int) rewrite_context_destroy( struct rewrite_context **context ); LDAP_REWRITE_F (void) rewrite_context_free( void *tmp ); #endif /* REWRITE_INT_H */ openldap-2.4.42+dfsg/include/0000755000175000017500000000000012563404150014453 5ustar ryanryanopenldap-2.4.42+dfsg/include/slapi-plugin.h0000644000175000017500000011271712563404150017241 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * Portions Copyright 1997,2002,2003 IBM Corporation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* * This header is used in development of SLAPI plugins for * OpenLDAP slapd(8) and other directory servers supporting * this interface. Your portability mileage may vary. */ #ifndef _SLAPI_PLUGIN_H #define _SLAPI_PLUGIN_H #include typedef struct slapi_pblock Slapi_PBlock; typedef struct slapi_entry Slapi_Entry; typedef struct slapi_attr Slapi_Attr; typedef struct slapi_value Slapi_Value; typedef struct slapi_valueset Slapi_ValueSet; typedef struct slapi_filter Slapi_Filter; typedef struct BackendDB Slapi_Backend; typedef struct Operation Slapi_Operation; typedef struct Connection Slapi_Connection; typedef struct slapi_dn Slapi_DN; typedef struct slapi_rdn Slapi_RDN; typedef struct slapi_mod Slapi_Mod; typedef struct slapi_mods Slapi_Mods; typedef struct slapi_componentid Slapi_ComponentId; #define SLAPI_ATTR_UNIQUEID "entryUUID" #define SLAPI_ATTR_OBJECTCLASS "objectClass" /* pblock routines */ int slapi_pblock_get( Slapi_PBlock *pb, int arg, void *value ); int slapi_pblock_set( Slapi_PBlock *pb, int arg, void *value ); Slapi_PBlock *slapi_pblock_new( void ); void slapi_pblock_destroy( Slapi_PBlock *pb ); /* entry/attr/dn routines */ Slapi_Entry *slapi_str2entry( char *s, int flags ); #define SLAPI_STR2ENTRY_REMOVEDUPVALS 1 #define SLAPI_STR2ENTRY_ADDRDNVALS 2 #define SLAPI_STR2ENTRY_BIGENTRY 4 #define SLAPI_STR2ENTRY_TOMBSTONE_CHECK 8 #define SLAPI_STR2ENTRY_IGNORE_STATE 16 #define SLAPI_STR2ENTRY_INCLUDE_VERSION_STR 32 #define SLAPI_STR2ENTRY_EXPAND_OBJECTCLASSES 64 #define SLAPI_STR2ENTRY_NOT_WELL_FORMED_LDIF 128 char *slapi_entry2str( Slapi_Entry *e, int *len ); char *slapi_entry_get_dn( Slapi_Entry *e ); int slapi_x_entry_get_id( Slapi_Entry *e ); void slapi_entry_set_dn( Slapi_Entry *e, char *dn ); Slapi_Entry *slapi_entry_dup( Slapi_Entry *e ); int slapi_entry_attr_delete( Slapi_Entry *e, char *type ); Slapi_Entry *slapi_entry_alloc(); void slapi_entry_free( Slapi_Entry *e ); int slapi_entry_attr_merge( Slapi_Entry *e, char *type, struct berval **vals ); int slapi_entry_attr_find( Slapi_Entry *e, char *type, Slapi_Attr **attr ); char *slapi_entry_attr_get_charptr( const Slapi_Entry *e, const char *type ); int slapi_entry_attr_get_int( const Slapi_Entry *e, const char *type ); long slapi_entry_attr_get_long( const Slapi_Entry *e, const char *type ); unsigned int slapi_entry_attr_get_uint( const Slapi_Entry *e, const char *type ); unsigned long slapi_entry_attr_get_ulong( const Slapi_Entry *e, const char *type ); int slapi_attr_get_values( Slapi_Attr *attr, struct berval ***vals ); char *slapi_dn_normalize( char *dn ); char *slapi_dn_normalize_case( char *dn ); int slapi_dn_issuffix( char *dn, char *suffix ); char *slapi_dn_beparent( Slapi_PBlock *pb, const char *dn ); int slapi_dn_isbesuffix( Slapi_PBlock *pb, char *dn ); char *slapi_dn_parent( const char *dn ); int slapi_dn_isparent( const char *parentdn, const char *childdn ); char *slapi_dn_ignore_case( char *dn ); int slapi_rdn2typeval( char *rdn, char **type, struct berval *bv ); char *slapi_dn_plus_rdn(const char *dn, const char *rdn); /* DS 5.x SLAPI */ int slapi_access_allowed( Slapi_PBlock *pb, Slapi_Entry *e, char *attr, struct berval *val, int access ); int slapi_acl_check_mods( Slapi_PBlock *pb, Slapi_Entry *e, LDAPMod **mods, char **errbuf ); Slapi_Attr *slapi_attr_new( void ); Slapi_Attr *slapi_attr_init( Slapi_Attr *a, const char *type ); void slapi_attr_free( Slapi_Attr **a ); Slapi_Attr *slapi_attr_dup( const Slapi_Attr *attr ); int slapi_attr_add_value( Slapi_Attr *a, const Slapi_Value *v ); int slapi_attr_type2plugin( const char *type, void **pi ); int slapi_attr_get_type( const Slapi_Attr *attr, char **type ); int slapi_attr_get_oid_copy( const Slapi_Attr *attr, char **oidp ); int slapi_attr_get_flags( const Slapi_Attr *attr, unsigned long *flags ); int slapi_attr_flag_is_set( const Slapi_Attr *attr, unsigned long flag ); int slapi_attr_value_cmp( const Slapi_Attr *attr, const struct berval *v1, const struct berval *v2 ); int slapi_attr_value_find( const Slapi_Attr *a, struct berval *v ); #define SLAPI_TYPE_CMP_EXACT 0 #define SLAPI_TYPE_CMP_BASE 1 #define SLAPI_TYPE_CMP_SUBTYPE 2 int slapi_attr_type_cmp( const char *t1, const char *t2, int opt ); int slapi_attr_types_equivalent( const char *t1, const char *t2 ); int slapi_attr_first_value( Slapi_Attr *a, Slapi_Value **v ); int slapi_attr_next_value( Slapi_Attr *a, int hint, Slapi_Value **v ); int slapi_attr_get_numvalues( const Slapi_Attr *a, int *numValues ); int slapi_attr_get_valueset( const Slapi_Attr *a, Slapi_ValueSet **vs ); int slapi_attr_get_bervals_copy( Slapi_Attr *a, struct berval ***vals ); int slapi_entry_attr_hasvalue( Slapi_Entry *e, const char *type, const char *value ); int slapi_entry_attr_merge_sv( Slapi_Entry *e, const char *type, Slapi_Value **vals ); void slapi_entry_attr_set_charptr(Slapi_Entry* e, const char *type, const char *value); void slapi_entry_attr_set_int( Slapi_Entry* e, const char *type, int l); void slapi_entry_attr_set_uint( Slapi_Entry* e, const char *type, unsigned int l); void slapi_entry_attr_set_long(Slapi_Entry* e, const char *type, long l); void slapi_entry_attr_set_ulong(Slapi_Entry* e, const char *type, unsigned long l); int slapi_entry_has_children(const Slapi_Entry *e); size_t slapi_entry_size(Slapi_Entry *e); int slapi_is_rootdse( const char *dn ); int slapi_entry_attr_merge_sv( Slapi_Entry *e, const char *type, Slapi_Value **vals ); int slapi_entry_add_values_sv( Slapi_Entry *e, const char *type, Slapi_Value **vals ); int slapi_entry_add_valueset(Slapi_Entry *e, const char *type, Slapi_ValueSet *vs); int slapi_entry_delete_values_sv( Slapi_Entry *e, const char *type, Slapi_Value **vals ); int slapi_entry_merge_values_sv( Slapi_Entry *e, const char *type, Slapi_Value **vals ); int slapi_entry_attr_replace_sv( Slapi_Entry *e, const char *type, Slapi_Value **vals ); int slapi_entry_add_value(Slapi_Entry *e, const char *type, const Slapi_Value *value); int slapi_entry_add_string(Slapi_Entry *e, const char *type, const char *value); int slapi_entry_delete_string(Slapi_Entry *e, const char *type, const char *value); int slapi_entry_first_attr( const Slapi_Entry *e, Slapi_Attr **attr ); int slapi_entry_next_attr( const Slapi_Entry *e, Slapi_Attr *prevattr, Slapi_Attr **attr ); const char *slapi_entry_get_uniqueid( const Slapi_Entry *e ); void slapi_entry_set_uniqueid( Slapi_Entry *e, char *uniqueid ); int slapi_entry_schema_check( Slapi_PBlock *pb, Slapi_Entry *e ); int slapi_entry_rdn_values_present( const Slapi_Entry *e ); int slapi_entry_add_rdn_values( Slapi_Entry *e ); char *slapi_attr_syntax_normalize( const char *s ); Slapi_Value *slapi_value_new( void ); Slapi_Value *slapi_value_new_berval(const struct berval *bval); Slapi_Value *slapi_value_new_value(const Slapi_Value *v); Slapi_Value *slapi_value_new_string(const char *s); Slapi_Value *slapi_value_init(Slapi_Value *v); Slapi_Value *slapi_value_init_berval(Slapi_Value *v, struct berval *bval); Slapi_Value *slapi_value_init_string(Slapi_Value *v, const char *s); Slapi_Value *slapi_value_dup(const Slapi_Value *v); void slapi_value_free(Slapi_Value **value); const struct berval *slapi_value_get_berval( const Slapi_Value *value ); Slapi_Value *slapi_value_set_berval( Slapi_Value *value, const struct berval *bval ); Slapi_Value *slapi_value_set_value( Slapi_Value *value, const Slapi_Value *vfrom); Slapi_Value *slapi_value_set( Slapi_Value *value, void *val, unsigned long len); int slapi_value_set_string(Slapi_Value *value, const char *strVal); int slapi_value_set_int(Slapi_Value *value, int intVal); const char*slapi_value_get_string(const Slapi_Value *value); int slapi_value_get_int(const Slapi_Value *value); unsigned int slapi_value_get_uint(const Slapi_Value *value); long slapi_value_get_long(const Slapi_Value *value); unsigned long slapi_value_get_ulong(const Slapi_Value *value); size_t slapi_value_get_length(const Slapi_Value *value); int slapi_value_compare(const Slapi_Attr *a, const Slapi_Value *v1, const Slapi_Value *v2); Slapi_ValueSet *slapi_valueset_new( void ); void slapi_valueset_free(Slapi_ValueSet *vs); void slapi_valueset_init(Slapi_ValueSet *vs); void slapi_valueset_done(Slapi_ValueSet *vs); void slapi_valueset_add_value(Slapi_ValueSet *vs, const Slapi_Value *addval); int slapi_valueset_first_value( Slapi_ValueSet *vs, Slapi_Value **v ); int slapi_valueset_next_value( Slapi_ValueSet *vs, int index, Slapi_Value **v); int slapi_valueset_count( const Slapi_ValueSet *vs); void slapi_valueset_set_valueset(Slapi_ValueSet *vs1, const Slapi_ValueSet *vs2); /* DNs */ Slapi_DN *slapi_sdn_new( void ); Slapi_DN *slapi_sdn_new_dn_byval( const char *dn ); Slapi_DN *slapi_sdn_new_ndn_byval( const char *ndn ); Slapi_DN *slapi_sdn_new_dn_byref( const char *dn ); Slapi_DN *slapi_sdn_new_ndn_byref( const char *ndn ); Slapi_DN *slapi_sdn_new_dn_passin( const char *dn ); Slapi_DN *slapi_sdn_set_dn_byval( Slapi_DN *sdn, const char *dn ); Slapi_DN *slapi_sdn_set_dn_byref( Slapi_DN *sdn, const char *dn ); Slapi_DN *slapi_sdn_set_dn_passin( Slapi_DN *sdn, const char *dn ); Slapi_DN *slapi_sdn_set_ndn_byval( Slapi_DN *sdn, const char *ndn ); Slapi_DN *slapi_sdn_set_ndn_byref( Slapi_DN *sdn, const char *ndn ); void slapi_sdn_done( Slapi_DN *sdn ); void slapi_sdn_free( Slapi_DN **sdn ); const char * slapi_sdn_get_dn( const Slapi_DN *sdn ); const char * slapi_sdn_get_ndn( const Slapi_DN *sdn ); void slapi_sdn_get_parent( const Slapi_DN *sdn,Slapi_DN *sdn_parent ); void slapi_sdn_get_backend_parent( const Slapi_DN *sdn, Slapi_DN *sdn_parent, const Slapi_Backend *backend ); Slapi_DN * slapi_sdn_dup( const Slapi_DN *sdn ); void slapi_sdn_copy( const Slapi_DN *from, Slapi_DN *to ); int slapi_sdn_compare( const Slapi_DN *sdn1, const Slapi_DN *sdn2 ); int slapi_sdn_isempty( const Slapi_DN *sdn ); int slapi_sdn_issuffix(const Slapi_DN *sdn, const Slapi_DN *suffixsdn ); int slapi_sdn_isparent( const Slapi_DN *parent, const Slapi_DN *child ); int slapi_sdn_isgrandparent( const Slapi_DN *parent, const Slapi_DN *child ); int slapi_sdn_get_ndn_len( const Slapi_DN *sdn ); int slapi_sdn_scope_test( const Slapi_DN *dn, const Slapi_DN *base, int scope ); void slapi_sdn_get_rdn( const Slapi_DN *sdn,Slapi_RDN *rdn ); Slapi_DN *slapi_sdn_set_rdn( Slapi_DN *sdn, const Slapi_RDN *rdn ); Slapi_DN *slapi_sdn_set_parent( Slapi_DN *sdn, const Slapi_DN *parentdn ); int slapi_sdn_is_rdn_component( const Slapi_DN *rdn, const Slapi_Attr *a, const Slapi_Value *v ); char * slapi_moddn_get_newdn( Slapi_DN *dn_olddn, char *newrdn, char *newsuperiordn ); /* RDNs */ Slapi_RDN *slapi_rdn_new( void ); Slapi_RDN *slapi_rdn_new_dn( const char *dn ); Slapi_RDN *slapi_rdn_new_sdn( const Slapi_DN *sdn ); Slapi_RDN *slapi_rdn_new_rdn( const Slapi_RDN *fromrdn ); void slapi_rdn_init( Slapi_RDN *rdn ); void slapi_rdn_init_dn( Slapi_RDN *rdn, const char *dn ); void slapi_rdn_init_sdn( Slapi_RDN *rdn, const Slapi_DN *sdn ); void slapi_rdn_init_rdn( Slapi_RDN *rdn, const Slapi_RDN *fromrdn ); void slapi_rdn_set_dn( Slapi_RDN *rdn, const char *dn ); void slapi_rdn_set_sdn( Slapi_RDN *rdn, const Slapi_DN *sdn ); void slapi_rdn_set_rdn( Slapi_RDN *rdn, const Slapi_RDN *fromrdn ); void slapi_rdn_free( Slapi_RDN **rdn ); void slapi_rdn_done( Slapi_RDN *rdn ); int slapi_rdn_get_first( Slapi_RDN *rdn, char **type, char **value ); int slapi_rdn_get_next( Slapi_RDN *rdn, int index, char **type, char **value ); int slapi_rdn_get_index( Slapi_RDN *rdn, const char *type, const char *value, size_t length ); int slapi_rdn_get_index_attr( Slapi_RDN *rdn, const char *type, char **value ); int slapi_rdn_contains( Slapi_RDN *rdn, const char *type, const char *value,size_t length ); int slapi_rdn_contains_attr( Slapi_RDN *rdn, const char *type, char **value ); int slapi_rdn_add( Slapi_RDN *rdn, const char *type, const char *value ); int slapi_rdn_remove_index( Slapi_RDN *rdn, int atindex ); int slapi_rdn_remove( Slapi_RDN *rdn, const char *type, const char *value, size_t length ); int slapi_rdn_remove_attr( Slapi_RDN *rdn, const char *type ); int slapi_rdn_isempty( const Slapi_RDN *rdn ); int slapi_rdn_get_num_components( Slapi_RDN *rdn ); int slapi_rdn_compare( Slapi_RDN *rdn1, Slapi_RDN *rdn2 ); const char *slapi_rdn_get_rdn( const Slapi_RDN *rdn ); const char *slapi_rdn_get_nrdn( const Slapi_RDN *rdn ); Slapi_DN *slapi_sdn_add_rdn( Slapi_DN *sdn, const Slapi_RDN *rdn ); /* locks and synchronization */ typedef struct slapi_mutex Slapi_Mutex; typedef struct slapi_condvar Slapi_CondVar; Slapi_Mutex *slapi_new_mutex( void ); void slapi_destroy_mutex( Slapi_Mutex *mutex ); void slapi_lock_mutex( Slapi_Mutex *mutex ); int slapi_unlock_mutex( Slapi_Mutex *mutex ); Slapi_CondVar *slapi_new_condvar( Slapi_Mutex *mutex ); void slapi_destroy_condvar( Slapi_CondVar *cvar ); int slapi_wait_condvar( Slapi_CondVar *cvar, struct timeval *timeout ); int slapi_notify_condvar( Slapi_CondVar *cvar, int notify_all ); /* thread-safe LDAP connections */ LDAP *slapi_ldap_init( char *ldaphost, int ldapport, int secure, int shared ); void slapi_ldap_unbind( LDAP *ld ); char *slapi_ch_malloc( unsigned long size ); void slapi_ch_free( void **ptr ); void slapi_ch_free_string( char **ptr ); char *slapi_ch_calloc( unsigned long nelem, unsigned long size ); char *slapi_ch_realloc( char *block, unsigned long size ); char *slapi_ch_strdup( const char *s ); void slapi_ch_array_free( char **arrayp ); struct berval *slapi_ch_bvdup(const struct berval *v); struct berval **slapi_ch_bvecdup(const struct berval **v); /* LDAP V3 routines */ int slapi_control_present( LDAPControl **controls, char *oid, struct berval **val, int *iscritical); void slapi_register_supported_control(char *controloid, unsigned long controlops); #define SLAPI_OPERATION_BIND 0x00000001L #define SLAPI_OPERATION_UNBIND 0x00000002L #define SLAPI_OPERATION_SEARCH 0x00000004L #define SLAPI_OPERATION_MODIFY 0x00000008L #define SLAPI_OPERATION_ADD 0x00000010L #define SLAPI_OPERATION_DELETE 0x00000020L #define SLAPI_OPERATION_MODDN 0x00000040L #define SLAPI_OPERATION_MODRDN SLAPI_OPERATION_MODDN #define SLAPI_OPERATION_COMPARE 0x00000080L #define SLAPI_OPERATION_ABANDON 0x00000100L #define SLAPI_OPERATION_EXTENDED 0x00000200L #define SLAPI_OPERATION_ANY 0xFFFFFFFFL #define SLAPI_OPERATION_NONE 0x00000000L int slapi_get_supported_controls(char ***ctrloidsp, unsigned long **ctrlopsp); LDAPControl *slapi_dup_control(LDAPControl *ctrl); void slapi_register_supported_saslmechanism(char *mechanism); char **slapi_get_supported_saslmechanisms(); char **slapi_get_supported_extended_ops(void); /* operation */ int slapi_op_abandoned( Slapi_PBlock *pb ); unsigned long slapi_op_get_type(Slapi_Operation * op); void slapi_operation_set_flag(Slapi_Operation *op, unsigned long flag); void slapi_operation_clear_flag(Slapi_Operation *op, unsigned long flag); int slapi_operation_is_flag_set(Slapi_Operation *op, unsigned long flag); char *slapi_op_type_to_string(unsigned long type); /* send ldap result back */ void slapi_send_ldap_result( Slapi_PBlock *pb, int err, char *matched, char *text, int nentries, struct berval **urls ); int slapi_send_ldap_search_entry( Slapi_PBlock *pb, Slapi_Entry *e, LDAPControl **ectrls, char **attrs, int attrsonly ); int slapi_send_ldap_search_reference( Slapi_PBlock *pb, Slapi_Entry *e, struct berval **urls, LDAPControl **ectrls, struct berval **v2refs ); /* filter routines */ Slapi_Filter *slapi_str2filter( char *str ); Slapi_Filter *slapi_filter_dup( Slapi_Filter *f ); void slapi_filter_free( Slapi_Filter *f, int recurse ); int slapi_filter_get_choice( Slapi_Filter *f); int slapi_filter_get_ava( Slapi_Filter *f, char **type, struct berval **bval ); Slapi_Filter *slapi_filter_list_first( Slapi_Filter *f ); Slapi_Filter *slapi_filter_list_next( Slapi_Filter *f, Slapi_Filter *fprev ); int slapi_filter_get_attribute_type( Slapi_Filter *f, char **type ); int slapi_x_filter_set_attribute_type( Slapi_Filter *f, const char *type ); int slapi_filter_get_subfilt( Slapi_Filter *f, char **type, char **initial, char ***any, char **final ); Slapi_Filter *slapi_filter_join( int ftype, Slapi_Filter *f1, Slapi_Filter *f2); int slapi_x_filter_append( int choice, Slapi_Filter **pContainingFilter, Slapi_Filter **pNextFilter, Slapi_Filter *filterToAppend ); int slapi_filter_test( Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Filter *f, int verify_access ); int slapi_filter_test_simple( Slapi_Entry *e, Slapi_Filter *f ); typedef int (*FILTER_APPLY_FN)( Slapi_Filter *f, void *arg ); int slapi_filter_apply( Slapi_Filter *f, FILTER_APPLY_FN fn, void *arg, int *error_code ); #define SLAPI_FILTER_SCAN_STOP -1 /* set by callback */ #define SLAPI_FILTER_SCAN_ERROR -2 /* set by callback */ #define SLAPI_FILTER_SCAN_NOMORE 0 /* set by callback */ #define SLAPI_FILTER_SCAN_CONTINUE 1 /* set by callback */ #define SLAPI_FILTER_UNKNOWN_FILTER_TYPE 2 /* set by slapi_filter_apply() */ /* internal add/delete/search/modify routines */ Slapi_PBlock *slapi_search_internal( char *base, int scope, char *filter, LDAPControl **controls, char **attrs, int attrsonly ); Slapi_PBlock *slapi_modify_internal( char *dn, LDAPMod **mods, LDAPControl **controls, int log_change ); Slapi_PBlock *slapi_add_internal( char * dn, LDAPMod **attrs, LDAPControl **controls, int log_changes ); Slapi_PBlock *slapi_add_entry_internal( Slapi_Entry * e, LDAPControl **controls, int log_change ); Slapi_PBlock *slapi_delete_internal( char * dn, LDAPControl **controls, int log_change ); Slapi_PBlock *slapi_modrdn_internal( char * olddn, char * newrdn, int deloldrdn, LDAPControl **controls, int log_change ); Slapi_PBlock *slapi_rename_internal( const char * olddn, const char *newrdn, const char *newsuperior, int delolrdn, LDAPControl **controls, int log_change ); void slapi_free_search_results_internal(Slapi_PBlock *pb); /* new internal add/delete/search/modify routines */ typedef void (*plugin_result_callback)( int rc, void *callback_data ); typedef int (*plugin_referral_entry_callback)( char * referral, void *callback_data ); typedef int (*plugin_search_entry_callback)( Slapi_Entry *e, void *callback_data ); void slapi_free_search_results_internal( Slapi_PBlock *pb ); #define SLAPI_OP_FLAG_NEVER_CHAIN 0x0800 int slapi_search_internal_pb( Slapi_PBlock *pb ); int slapi_search_internal_callback_pb( Slapi_PBlock *pb, void *callback_data, plugin_result_callback prc, plugin_search_entry_callback psec, plugin_referral_entry_callback prec ); int slapi_add_internal_pb( Slapi_PBlock *pb ); int slapi_modify_internal_pb( Slapi_PBlock *pb ); int slapi_modrdn_internal_pb( Slapi_PBlock *pb ); int slapi_delete_internal_pb( Slapi_PBlock *pb ); int slapi_seq_internal_callback_pb(Slapi_PBlock *pb, void *callback_data, plugin_result_callback res_callback, plugin_search_entry_callback srch_callback, plugin_referral_entry_callback ref_callback); void slapi_search_internal_set_pb( Slapi_PBlock *pb, const char *base, int scope, const char *filter, char **attrs, int attrsonly, LDAPControl **controls, const char *uniqueid, Slapi_ComponentId *plugin_identity, int operation_flags ); void slapi_add_entry_internal_set_pb( Slapi_PBlock *pb, Slapi_Entry *e, LDAPControl **controls, Slapi_ComponentId *plugin_identity, int operation_flags ); int slapi_add_internal_set_pb( Slapi_PBlock *pb, const char *dn, LDAPMod **attrs, LDAPControl **controls, Slapi_ComponentId *plugin_identity, int operation_flags ); void slapi_modify_internal_set_pb( Slapi_PBlock *pb, const char *dn, LDAPMod **mods, LDAPControl **controls, const char *uniqueid, Slapi_ComponentId *plugin_identity, int operation_flags ); void slapi_rename_internal_set_pb( Slapi_PBlock *pb, const char *olddn, const char *newrdn, const char *newsuperior, int deloldrdn, LDAPControl **controls, const char *uniqueid, Slapi_ComponentId *plugin_identity, int operation_flags ); void slapi_delete_internal_set_pb( Slapi_PBlock *pb, const char *dn, LDAPControl **controls, const char *uniqueid, Slapi_ComponentId *plugin_identity, int operation_flags ); void slapi_seq_internal_set_pb( Slapi_PBlock *pb, char *ibase, int type, char *attrname, char *val, char **attrs, int attrsonly, LDAPControl **controls, Slapi_ComponentId *plugin_identity, int operation_flags ); /* connection related routines */ int slapi_is_connection_ssl(Slapi_PBlock *pPB, int *isSSL); int slapi_get_client_port(Slapi_PBlock *pPB, int *fromPort); int slapi_get_client_ip(Slapi_PBlock *pb, char **clientIP); void slapi_free_client_ip(char **clientIP); /* computed attributes */ typedef struct _computed_attr_context computed_attr_context; typedef int (*slapi_compute_output_t)(computed_attr_context *c, Slapi_Attr *a, Slapi_Entry *e); typedef int (*slapi_compute_callback_t)(computed_attr_context *c, char *type, Slapi_Entry *e, slapi_compute_output_t outputfn); typedef int (*slapi_search_rewrite_callback_t)(Slapi_PBlock *pb); int slapi_compute_add_evaluator(slapi_compute_callback_t function); int slapi_compute_add_search_rewriter(slapi_search_rewrite_callback_t function); int compute_rewrite_search_filter(Slapi_PBlock *pb); int compute_evaluator(computed_attr_context *c, char *type, Slapi_Entry *e, slapi_compute_output_t outputfn); int slapi_x_compute_get_pblock(computed_attr_context *c, Slapi_PBlock **pb); /* backend routines */ void slapi_be_set_readonly( Slapi_Backend *be, int readonly ); int slapi_be_get_readonly( Slapi_Backend *be ); const char *slapi_x_be_get_updatedn( Slapi_Backend *be ); Slapi_Backend *slapi_be_select( const Slapi_DN *sdn ); /* ACL plugins; only SLAPI_PLUGIN_ACL_ALLOW_ACCESS supported now */ typedef int (*slapi_acl_callback_t)(Slapi_PBlock *pb, Slapi_Entry *e, const char *attr, struct berval *berval, int access, void *state); /* object extensions */ typedef void *(*slapi_extension_constructor_fnptr)(void *object, void *parent); typedef void (*slapi_extension_destructor_fnptr)(void *extension, void *object, void *parent); int slapi_register_object_extension( const char *pluginname, const char *objectname, slapi_extension_constructor_fnptr constructor, slapi_extension_destructor_fnptr destructor, int *objecttype, int *extensionhandle); #define SLAPI_EXT_CONNECTION "Connection" #define SLAPI_EXT_OPERATION "Operation" #define SLAPI_EXT_ENTRY "Entry" #define SLAPI_EXT_MTNODE "Mapping Tree Node" void *slapi_get_object_extension(int objecttype, void *object, int extensionhandle); void slapi_set_object_extension(int objecttype, void *object, int extensionhandle, void *extension); int slapi_x_backend_get_flags( const Slapi_Backend *be, unsigned long *flags ); /* parameters currently supported */ /* * Attribute flags returned by slapi_attr_get_flags() */ #define SLAPI_ATTR_FLAG_SINGLE 0x0001 #define SLAPI_ATTR_FLAG_OPATTR 0x0002 #define SLAPI_ATTR_FLAG_READONLY 0x0004 #define SLAPI_ATTR_FLAG_STD_ATTR SLAPI_ATTR_FLAG_READONLY #define SLAPI_ATTR_FLAG_OBSOLETE 0x0040 #define SLAPI_ATTR_FLAG_COLLECTIVE 0x0080 #define SLAPI_ATTR_FLAG_NOUSERMOD 0x0100 /* * Backend flags returned by slapi_x_backend_get_flags() */ #define SLAPI_BACKEND_FLAG_NOLASTMOD 0x0001U #define SLAPI_BACKEND_FLAG_NO_SCHEMA_CHECK 0x0002U #define SLAPI_BACKEND_FLAG_GLUE_INSTANCE 0x0010U /* a glue backend */ #define SLAPI_BACKEND_FLAG_GLUE_SUBORDINATE 0x0020U /* child of a glue hierarchy */ #define SLAPI_BACKEND_FLAG_GLUE_LINKED 0x0040U /* child is connected to parent */ #define SLAPI_BACKEND_FLAG_OVERLAY 0x0080U /* this db struct is an overlay */ #define SLAPI_BACKEND_FLAG_GLOBAL_OVERLAY 0x0100U /* this db struct is a global overlay */ #define SLAPI_BACKEND_FLAG_SHADOW 0x8000U /* a shadow */ #define SLAPI_BACKEND_FLAG_SYNC_SHADOW 0x1000U /* a sync shadow */ #define SLAPI_BACKEND_FLAG_SLURP_SHADOW 0x2000U /* a slurp shadow */ /* * ACL levels */ #define SLAPI_ACL_COMPARE 0x01 #define SLAPI_ACL_SEARCH 0x02 #define SLAPI_ACL_READ 0x04 #define SLAPI_ACL_WRITE 0x08 #define SLAPI_ACL_DELETE 0x10 #define SLAPI_ACL_ADD 0x20 #define SLAPI_ACL_SELF 0x40 #define SLAPI_ACL_PROXY 0x80 #define SLAPI_ACL_ALL 0x7f /* plugin types supported */ #define SLAPI_PLUGIN_DATABASE 1 #define SLAPI_PLUGIN_EXTENDEDOP 2 #define SLAPI_PLUGIN_PREOPERATION 3 #define SLAPI_PLUGIN_POSTOPERATION 4 #define SLAPI_PLUGIN_MATCHINGRULE 5 #define SLAPI_PLUGIN_SYNTAX 6 #define SLAPI_PLUGIN_AUDIT 7 /* misc params */ #define SLAPI_BACKEND 130 #define SLAPI_CONNECTION 131 #define SLAPI_OPERATION 132 #define SLAPI_REQUESTOR_ISROOT 133 #define SLAPI_BE_MONITORDN 134 #define SLAPI_BE_TYPE 135 #define SLAPI_BE_READONLY 136 #define SLAPI_BE_LASTMOD 137 #define SLAPI_CONN_ID 139 /* operation params */ #define SLAPI_OPINITIATED_TIME 140 #define SLAPI_REQUESTOR_DN 141 #define SLAPI_IS_REPLICATED_OPERATION 142 #define SLAPI_REQUESTOR_ISUPDATEDN SLAPI_IS_REPLICATED_OPERATION /* connection structure params*/ #define SLAPI_CONN_DN 143 #define SLAPI_CONN_AUTHTYPE 144 #define SLAPI_CONN_CLIENTIP 145 #define SLAPI_CONN_SERVERIP 146 /* OpenLDAP extensions */ #define SLAPI_X_CONN_CLIENTPATH 1300 #define SLAPI_X_CONN_SERVERPATH 1301 #define SLAPI_X_CONN_IS_UDP 1302 #define SLAPI_X_CONN_SSF 1303 #define SLAPI_X_CONN_SASL_CONTEXT 1304 #define SLAPI_X_OPERATION_DELETE_GLUE_PARENT 1305 #define SLAPI_X_RELAX 1306 #define SLAPI_X_MANAGEDIT SLAPI_X_RELAX #define SLAPI_X_OPERATION_NO_SCHEMA_CHECK 1307 #define SLAPI_X_ADD_STRUCTURAL_CLASS 1308 #define SLAPI_X_OPERATION_NO_SUBORDINATE_GLUE 1309 /* Authentication types */ #define SLAPD_AUTH_NONE "none" #define SLAPD_AUTH_SIMPLE "simple" #define SLAPD_AUTH_SSL "SSL" #define SLAPD_AUTH_SASL "SASL " /* plugin configuration parmams */ #define SLAPI_PLUGIN 3 #define SLAPI_PLUGIN_PRIVATE 4 #define SLAPI_PLUGIN_TYPE 5 #define SLAPI_PLUGIN_ARGV 6 #define SLAPI_PLUGIN_ARGC 7 #define SLAPI_PLUGIN_VERSION 8 #define SLAPI_PLUGIN_OPRETURN 9 #define SLAPI_PLUGIN_OBJECT 10 #define SLAPI_PLUGIN_DESTROY_FN 11 #define SLAPI_PLUGIN_DESCRIPTION 12 #define SLAPI_PLUGIN_IDENTITY 13 /* internal opreations params */ #define SLAPI_PLUGIN_INTOP_RESULT 15 #define SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES 16 #define SLAPI_PLUGIN_INTOP_SEARCH_REFERRALS 17 /* transaction arguments */ #define SLAPI_PARENT_TXN 190 #define SLAPI_TXN 191 /* function pointer params for backends */ #define SLAPI_PLUGIN_DB_BIND_FN 200 #define SLAPI_PLUGIN_DB_UNBIND_FN 201 #define SLAPI_PLUGIN_DB_SEARCH_FN 202 #define SLAPI_PLUGIN_DB_COMPARE_FN 203 #define SLAPI_PLUGIN_DB_MODIFY_FN 204 #define SLAPI_PLUGIN_DB_MODRDN_FN 205 #define SLAPI_PLUGIN_DB_ADD_FN 206 #define SLAPI_PLUGIN_DB_DELETE_FN 207 #define SLAPI_PLUGIN_DB_ABANDON_FN 208 #define SLAPI_PLUGIN_DB_CONFIG_FN 209 #define SLAPI_PLUGIN_CLOSE_FN 210 #define SLAPI_PLUGIN_DB_FLUSH_FN 211 #define SLAPI_PLUGIN_START_FN 212 #define SLAPI_PLUGIN_DB_SEQ_FN 213 #define SLAPI_PLUGIN_DB_ENTRY_FN 214 #define SLAPI_PLUGIN_DB_REFERRAL_FN 215 #define SLAPI_PLUGIN_DB_RESULT_FN 216 #define SLAPI_PLUGIN_DB_LDIF2DB_FN 217 #define SLAPI_PLUGIN_DB_DB2LDIF_FN 218 #define SLAPI_PLUGIN_DB_BEGIN_FN 219 #define SLAPI_PLUGIN_DB_COMMIT_FN 220 #define SLAPI_PLUGIN_DB_ABORT_FN 221 #define SLAPI_PLUGIN_DB_ARCHIVE2DB_FN 222 #define SLAPI_PLUGIN_DB_DB2ARCHIVE_FN 223 #define SLAPI_PLUGIN_DB_NEXT_SEARCH_ENTRY_FN 224 #define SLAPI_PLUGIN_DB_FREE_RESULT_SET_FN 225 #define SLAPI_PLUGIN_DB_SIZE_FN 226 #define SLAPI_PLUGIN_DB_TEST_FN 227 /* functions pointers for LDAP V3 extended ops */ #define SLAPI_PLUGIN_EXT_OP_FN 300 #define SLAPI_PLUGIN_EXT_OP_OIDLIST 301 /* preoperation */ #define SLAPI_PLUGIN_PRE_BIND_FN 401 #define SLAPI_PLUGIN_PRE_UNBIND_FN 402 #define SLAPI_PLUGIN_PRE_SEARCH_FN 403 #define SLAPI_PLUGIN_PRE_COMPARE_FN 404 #define SLAPI_PLUGIN_PRE_MODIFY_FN 405 #define SLAPI_PLUGIN_PRE_MODRDN_FN 406 #define SLAPI_PLUGIN_PRE_ADD_FN 407 #define SLAPI_PLUGIN_PRE_DELETE_FN 408 #define SLAPI_PLUGIN_PRE_ABANDON_FN 409 #define SLAPI_PLUGIN_PRE_ENTRY_FN 410 #define SLAPI_PLUGIN_PRE_REFERRAL_FN 411 #define SLAPI_PLUGIN_PRE_RESULT_FN 412 /* internal preoperation */ #define SLAPI_PLUGIN_INTERNAL_PRE_ADD_FN 420 #define SLAPI_PLUGIN_INTERNAL_PRE_MODIFY_FN 421 #define SLAPI_PLUGIN_INTERNAL_PRE_MODRDN_FN 422 #define SLAPI_PLUGIN_INTERNAL_PRE_DELETE_FN 423 /* backend preoperation */ #define SLAPI_PLUGIN_BE_PRE_ADD_FN 450 #define SLAPI_PLUGIN_BE_PRE_MODIFY_FN 451 #define SLAPI_PLUGIN_BE_PRE_MODRDN_FN 452 #define SLAPI_PLUGIN_BE_PRE_DELETE_FN 453 /* postoperation */ #define SLAPI_PLUGIN_POST_BIND_FN 501 #define SLAPI_PLUGIN_POST_UNBIND_FN 502 #define SLAPI_PLUGIN_POST_SEARCH_FN 503 #define SLAPI_PLUGIN_POST_COMPARE_FN 504 #define SLAPI_PLUGIN_POST_MODIFY_FN 505 #define SLAPI_PLUGIN_POST_MODRDN_FN 506 #define SLAPI_PLUGIN_POST_ADD_FN 507 #define SLAPI_PLUGIN_POST_DELETE_FN 508 #define SLAPI_PLUGIN_POST_ABANDON_FN 509 #define SLAPI_PLUGIN_POST_ENTRY_FN 510 #define SLAPI_PLUGIN_POST_REFERRAL_FN 511 #define SLAPI_PLUGIN_POST_RESULT_FN 512 /* internal postoperation */ #define SLAPI_PLUGIN_INTERNAL_POST_ADD_FN 520 #define SLAPI_PLUGIN_INTERNAL_POST_MODIFY_FN 521 #define SLAPI_PLUGIN_INTERNAL_POST_MODRDN_FN 522 #define SLAPI_PLUGIN_INTERNAL_POST_DELETE_FN 523 /* backend postoperation */ #define SLAPI_PLUGIN_BE_POST_ADD_FN 550 #define SLAPI_PLUGIN_BE_POST_MODIFY_FN 551 #define SLAPI_PLUGIN_BE_POST_MODRDN_FN 552 #define SLAPI_PLUGIN_BE_POST_DELETE_FN 553 #define SLAPI_OPERATION_TYPE 590 #define SLAPI_OPERATION_MSGID 591 #define SLAPI_PLUGIN_MR_FILTER_CREATE_FN 600 #define SLAPI_PLUGIN_MR_INDEXER_CREATE_FN 601 #define SLAPI_PLUGIN_MR_FILTER_MATCH_FN 602 #define SLAPI_PLUGIN_MR_FILTER_INDEX_FN 603 #define SLAPI_PLUGIN_MR_FILTER_RESET_FN 604 #define SLAPI_PLUGIN_MR_INDEX_FN 605 #define SLAPI_PLUGIN_MR_OID 610 #define SLAPI_PLUGIN_MR_TYPE 611 #define SLAPI_PLUGIN_MR_VALUE 612 #define SLAPI_PLUGIN_MR_VALUES 613 #define SLAPI_PLUGIN_MR_KEYS 614 #define SLAPI_PLUGIN_MR_FILTER_REUSABLE 615 #define SLAPI_PLUGIN_MR_QUERY_OPERATOR 616 #define SLAPI_PLUGIN_MR_USAGE 617 #define SLAPI_MATCHINGRULE_NAME 1 #define SLAPI_MATCHINGRULE_OID 2 #define SLAPI_MATCHINGRULE_DESC 3 #define SLAPI_MATCHINGRULE_SYNTAX 4 #define SLAPI_MATCHINGRULE_OBSOLETE 5 #define SLAPI_OP_LESS 1 #define SLAPI_OP_LESS_OR_EQUAL 2 #define SLAPI_OP_EQUAL 3 #define SLAPI_OP_GREATER_OR_EQUAL 4 #define SLAPI_OP_GREATER 5 #define SLAPI_OP_SUBSTRING 6 #define SLAPI_PLUGIN_MR_USAGE_INDEX 0 #define SLAPI_PLUGIN_MR_USAGE_SORT 1 #define SLAPI_PLUGIN_SYNTAX_FILTER_AVA 700 #define SLAPI_PLUGIN_SYNTAX_FILTER_SUB 701 #define SLAPI_PLUGIN_SYNTAX_VALUES2KEYS 702 #define SLAPI_PLUGIN_SYNTAX_ASSERTION2KEYS_AVA 703 #define SLAPI_PLUGIN_SYNTAX_ASSERTION2KEYS_SUB 704 #define SLAPI_PLUGIN_SYNTAX_NAMES 705 #define SLAPI_PLUGIN_SYNTAX_OID 706 #define SLAPI_PLUGIN_SYNTAX_FLAGS 707 #define SLAPI_PLUGIN_SYNTAX_COMPARE 708 #define SLAPI_PLUGIN_SYNTAX_FLAG_ORKEYS 1 #define SLAPI_PLUGIN_SYNTAX_FLAG_ORDERING 2 #define SLAPI_PLUGIN_ACL_INIT 730 #define SLAPI_PLUGIN_ACL_SYNTAX_CHECK 731 #define SLAPI_PLUGIN_ACL_ALLOW_ACCESS 732 #define SLAPI_PLUGIN_ACL_MODS_ALLOWED 733 #define SLAPI_PLUGIN_ACL_MODS_UPDATE 734 #define SLAPI_OPERATION_AUTHTYPE 741 #define SLAPI_OPERATION_ID 742 #define SLAPI_CONN_CERT 743 #define SLAPI_CONN_AUTHMETHOD 746 #define SLAPI_IS_INTERNAL_OPERATION 748 #define SLAPI_RESULT_CODE 881 #define SLAPI_RESULT_TEXT 882 #define SLAPI_RESULT_MATCHED 883 /* managedsait control */ #define SLAPI_MANAGEDSAIT 1000 /* audit plugin defines */ #define SLAPI_PLUGIN_AUDIT_DATA 1100 #define SLAPI_PLUGIN_AUDIT_FN 1101 /* backend_group extension */ #define SLAPI_X_PLUGIN_PRE_GROUP_FN 1202 #define SLAPI_X_PLUGIN_POST_GROUP_FN 1203 #define SLAPI_X_GROUP_ENTRY 1250 /* group entry */ #define SLAPI_X_GROUP_ATTRIBUTE 1251 /* member attribute */ #define SLAPI_X_GROUP_OPERATION_DN 1252 /* asserted value */ #define SLAPI_X_GROUP_TARGET_ENTRY 1253 /* target entry */ /* internal preoperation extensions */ #define SLAPI_PLUGIN_INTERNAL_PRE_BIND_FN 1260 #define SLAPI_PLUGIN_INTERNAL_PRE_UNBIND_FN 1261 #define SLAPI_PLUGIN_INTERNAL_PRE_SEARCH_FN 1262 #define SLAPI_PLUGIN_INTERNAL_PRE_COMPARE_FN 1263 #define SLAPI_PLUGIN_INTERNAL_PRE_ABANDON_FN 1264 /* internal postoperation extensions */ #define SLAPI_PLUGIN_INTERNAL_POST_BIND_FN 1270 #define SLAPI_PLUGIN_INTERNAL_POST_UNBIND_FN 1271 #define SLAPI_PLUGIN_INTERNAL_POST_SEARCH_FN 1272 #define SLAPI_PLUGIN_INTERNAL_POST_COMPARE_FN 1273 #define SLAPI_PLUGIN_INTERNAL_POST_ABANDON_FN 1274 /* config stuff */ #define SLAPI_CONFIG_FILENAME 40 #define SLAPI_CONFIG_LINENO 41 #define SLAPI_CONFIG_ARGC 42 #define SLAPI_CONFIG_ARGV 43 /* operational params */ #define SLAPI_TARGET_ADDRESS 48 #define SLAPI_TARGET_UNIQUEID 49 #define SLAPI_TARGET_DN 50 /* server LDAPv3 controls */ #define SLAPI_REQCONTROLS 51 #define SLAPI_RESCONTROLS 55 #define SLAPI_ADD_RESCONTROL 56 #define SLAPI_CONTROLS_ARG 58 /* add params */ #define SLAPI_ADD_TARGET SLAPI_TARGET_DN #define SLAPI_ADD_ENTRY 60 #define SLAPI_ADD_EXISTING_DN_ENTRY 61 #define SLAPI_ADD_PARENT_ENTRY 62 #define SLAPI_ADD_PARENT_UNIQUEID 63 #define SLAPI_ADD_EXISTING_UNIQUEID_ENTRY 64 /* bind params */ #define SLAPI_BIND_TARGET SLAPI_TARGET_DN #define SLAPI_BIND_METHOD 70 #define SLAPI_BIND_CREDENTIALS 71 #define SLAPI_BIND_SASLMECHANISM 72 #define SLAPI_BIND_RET_SASLCREDS 73 /* compare params */ #define SLAPI_COMPARE_TARGET SLAPI_TARGET_DN #define SLAPI_COMPARE_TYPE 80 #define SLAPI_COMPARE_VALUE 81 /* delete params */ #define SLAPI_DELETE_TARGET SLAPI_TARGET_DN #define SLAPI_DELETE_EXISTING_ENTRY SLAPI_ADD_EXISTING_DN_ENTRY /* modify params */ #define SLAPI_MODIFY_TARGET SLAPI_TARGET_DN #define SLAPI_MODIFY_MODS 90 #define SLAPI_MODIFY_EXISTING_ENTRY SLAPI_ADD_EXISTING_DN_ENTRY /* modrdn params */ #define SLAPI_MODRDN_TARGET SLAPI_TARGET_DN #define SLAPI_MODRDN_NEWRDN 100 #define SLAPI_MODRDN_DELOLDRDN 101 #define SLAPI_MODRDN_NEWSUPERIOR 102 /* v3 only */ #define SLAPI_MODRDN_EXISTING_ENTRY SLAPI_ADD_EXISTING_DN_ENTRY #define SLAPI_MODRDN_PARENT_ENTRY 104 #define SLAPI_MODRDN_NEWPARENT_ENTRY 105 #define SLAPI_MODRDN_TARGET_ENTRY 106 #define SLAPI_MODRDN_NEWSUPERIOR_ADDRESS 107 /* search params */ #define SLAPI_SEARCH_TARGET SLAPI_TARGET_DN #define SLAPI_SEARCH_SCOPE 110 #define SLAPI_SEARCH_DEREF 111 #define SLAPI_SEARCH_SIZELIMIT 112 #define SLAPI_SEARCH_TIMELIMIT 113 #define SLAPI_SEARCH_FILTER 114 #define SLAPI_SEARCH_STRFILTER 115 #define SLAPI_SEARCH_ATTRS 116 #define SLAPI_SEARCH_ATTRSONLY 117 /* abandon params */ #define SLAPI_ABANDON_MSGID 120 /* extended operation params */ #define SLAPI_EXT_OP_REQ_OID 160 #define SLAPI_EXT_OP_REQ_VALUE 161 /* extended operation return codes */ #define SLAPI_EXT_OP_RET_OID 162 #define SLAPI_EXT_OP_RET_VALUE 163 #define SLAPI_PLUGIN_EXTENDED_SENT_RESULT -1 #define SLAPI_FAIL_DISKFULL -2 #define SLAPI_FAIL_GENERAL -1 #define SLAPI_PLUGIN_EXTENDED_NOT_HANDLED -2 #define SLAPI_BIND_SUCCESS 0 #define SLAPI_BIND_FAIL 2 #define SLAPI_BIND_ANONYMOUS 3 /* Search result params */ #define SLAPI_SEARCH_RESULT_SET 193 #define SLAPI_SEARCH_RESULT_ENTRY 194 #define SLAPI_NENTRIES 195 #define SLAPI_SEARCH_REFERRALS 196 /* filter types */ #ifndef LDAP_FILTER_AND #define LDAP_FILTER_AND 0xa0L #endif #ifndef LDAP_FILTER_OR #define LDAP_FILTER_OR 0xa1L #endif #ifndef LDAP_FILTER_NOT #define LDAP_FILTER_NOT 0xa2L #endif #ifndef LDAP_FILTER_EQUALITY #define LDAP_FILTER_EQUALITY 0xa3L #endif #ifndef LDAP_FILTER_SUBSTRINGS #define LDAP_FILTER_SUBSTRINGS 0xa4L #endif #ifndef LDAP_FILTER_GE #define LDAP_FILTER_GE 0xa5L #endif #ifndef LDAP_FILTER_LE #define LDAP_FILTER_LE 0xa6L #endif #ifndef LDAP_FILTER_PRESENT #define LDAP_FILTER_PRESENT 0x87L #endif #ifndef LDAP_FILTER_APPROX #define LDAP_FILTER_APPROX 0xa8L #endif #ifndef LDAP_FILTER_EXT_MATCH #define LDAP_FILTER_EXT_MATCH 0xa9L #endif int slapi_log_error( int severity, char *subsystem, char *fmt, ... ); #define SLAPI_LOG_FATAL 0 #define SLAPI_LOG_TRACE 1 #define SLAPI_LOG_PACKETS 2 #define SLAPI_LOG_ARGS 3 #define SLAPI_LOG_CONNS 4 #define SLAPI_LOG_BER 5 #define SLAPI_LOG_FILTER 6 #define SLAPI_LOG_CONFIG 7 #define SLAPI_LOG_ACL 8 #define SLAPI_LOG_SHELL 9 #define SLAPI_LOG_PARSE 10 #define SLAPI_LOG_HOUSE 11 #define SLAPI_LOG_REPL 12 #define SLAPI_LOG_CACHE 13 #define SLAPI_LOG_PLUGIN 14 #define SLAPI_LOG_TIMING 15 #define SLAPI_PLUGIN_DESCRIPTION 12 typedef struct slapi_plugindesc { char *spd_id; char *spd_vendor; char *spd_version; char *spd_description; } Slapi_PluginDesc; #define SLAPI_PLUGIN_VERSION_01 "01" #define SLAPI_PLUGIN_VERSION_02 "02" #define SLAPI_PLUGIN_VERSION_03 "03" #define SLAPI_PLUGIN_CURRENT_VERSION SLAPI_PLUGIN_VERSION_03 #endif /* _SLAPI_PLUGIN_H */ openldap-2.4.42+dfsg/include/ldap.h0000644000175000017500000017641712563404150015564 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (c) 1990 Regents of the University of Michigan. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of Michigan at Ann Arbor. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. */ #ifndef _LDAP_H #define _LDAP_H /* pull in lber */ #include /* include version and API feature defines */ #include LDAP_BEGIN_DECL #define LDAP_VERSION1 1 #define LDAP_VERSION2 2 #define LDAP_VERSION3 3 #define LDAP_VERSION_MIN LDAP_VERSION2 #define LDAP_VERSION LDAP_VERSION2 #define LDAP_VERSION_MAX LDAP_VERSION3 /* * We use 3000+n here because it is above 1823 (for RFC 1823), * above 2000+rev of IETF LDAPEXT draft (now quite dated), * yet below allocations for new RFCs (just in case there is * someday an RFC produced). */ #define LDAP_API_VERSION 3001 #define LDAP_VENDOR_NAME "OpenLDAP" /* OpenLDAP API Features */ #define LDAP_API_FEATURE_X_OPENLDAP LDAP_VENDOR_VERSION #if defined( LDAP_API_FEATURE_X_OPENLDAP_REENTRANT ) || \ ( defined( LDAP_THREAD_SAFE ) && \ defined( LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE ) ) /* -lldap may or may not be thread safe */ /* -lldap_r, if available, is always thread safe */ # define LDAP_API_FEATURE_THREAD_SAFE 1 # define LDAP_API_FEATURE_SESSION_THREAD_SAFE 1 # define LDAP_API_FEATURE_OPERATION_THREAD_SAFE 1 #endif #if defined( LDAP_THREAD_SAFE ) && \ defined( LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE ) /* #define LDAP_API_FEATURE_SESSION_SAFE 1 */ /* #define LDAP_API_OPERATION_SESSION_SAFE 1 */ #endif #define LDAP_PORT 389 /* ldap:/// default LDAP port */ #define LDAPS_PORT 636 /* ldaps:/// default LDAP over TLS port */ #define LDAP_ROOT_DSE "" #define LDAP_NO_ATTRS "1.1" #define LDAP_ALL_USER_ATTRIBUTES "*" #define LDAP_ALL_OPERATIONAL_ATTRIBUTES "+" /* RFC 3673 */ /* RFC 4511: maxInt INTEGER ::= 2147483647 -- (2^^31 - 1) -- */ #define LDAP_MAXINT (2147483647) /* * LDAP_OPTions * 0x0000 - 0x0fff reserved for api options * 0x1000 - 0x3fff reserved for api extended options * 0x4000 - 0x7fff reserved for private and experimental options */ #define LDAP_OPT_API_INFO 0x0000 #define LDAP_OPT_DESC 0x0001 /* historic */ #define LDAP_OPT_DEREF 0x0002 #define LDAP_OPT_SIZELIMIT 0x0003 #define LDAP_OPT_TIMELIMIT 0x0004 /* 0x05 - 0x07 not defined */ #define LDAP_OPT_REFERRALS 0x0008 #define LDAP_OPT_RESTART 0x0009 /* 0x0a - 0x10 not defined */ #define LDAP_OPT_PROTOCOL_VERSION 0x0011 #define LDAP_OPT_SERVER_CONTROLS 0x0012 #define LDAP_OPT_CLIENT_CONTROLS 0x0013 /* 0x14 not defined */ #define LDAP_OPT_API_FEATURE_INFO 0x0015 /* 0x16 - 0x2f not defined */ #define LDAP_OPT_HOST_NAME 0x0030 #define LDAP_OPT_RESULT_CODE 0x0031 #define LDAP_OPT_ERROR_NUMBER LDAP_OPT_RESULT_CODE #define LDAP_OPT_DIAGNOSTIC_MESSAGE 0x0032 #define LDAP_OPT_ERROR_STRING LDAP_OPT_DIAGNOSTIC_MESSAGE #define LDAP_OPT_MATCHED_DN 0x0033 /* 0x0034 - 0x3fff not defined */ /* 0x0091 used by Microsoft for LDAP_OPT_AUTO_RECONNECT */ #define LDAP_OPT_SSPI_FLAGS 0x0092 /* 0x0093 used by Microsoft for LDAP_OPT_SSL_INFO */ /* 0x0094 used by Microsoft for LDAP_OPT_REF_DEREF_CONN_PER_MSG */ #define LDAP_OPT_SIGN 0x0095 #define LDAP_OPT_ENCRYPT 0x0096 #define LDAP_OPT_SASL_METHOD 0x0097 /* 0x0098 used by Microsoft for LDAP_OPT_AREC_EXCLUSIVE */ #define LDAP_OPT_SECURITY_CONTEXT 0x0099 /* 0x009A used by Microsoft for LDAP_OPT_ROOTDSE_CACHE */ /* 0x009B - 0x3fff not defined */ /* API Extensions */ #define LDAP_OPT_API_EXTENSION_BASE 0x4000 /* API extensions */ /* private and experimental options */ /* OpenLDAP specific options */ #define LDAP_OPT_DEBUG_LEVEL 0x5001 /* debug level */ #define LDAP_OPT_TIMEOUT 0x5002 /* default timeout */ #define LDAP_OPT_REFHOPLIMIT 0x5003 /* ref hop limit */ #define LDAP_OPT_NETWORK_TIMEOUT 0x5005 /* socket level timeout */ #define LDAP_OPT_URI 0x5006 #define LDAP_OPT_REFERRAL_URLS 0x5007 /* Referral URLs */ #define LDAP_OPT_SOCKBUF 0x5008 /* sockbuf */ #define LDAP_OPT_DEFBASE 0x5009 /* searchbase */ #define LDAP_OPT_CONNECT_ASYNC 0x5010 /* create connections asynchronously */ #define LDAP_OPT_CONNECT_CB 0x5011 /* connection callbacks */ #define LDAP_OPT_SESSION_REFCNT 0x5012 /* session reference count */ /* OpenLDAP TLS options */ #define LDAP_OPT_X_TLS 0x6000 #define LDAP_OPT_X_TLS_CTX 0x6001 /* OpenSSL CTX* */ #define LDAP_OPT_X_TLS_CACERTFILE 0x6002 #define LDAP_OPT_X_TLS_CACERTDIR 0x6003 #define LDAP_OPT_X_TLS_CERTFILE 0x6004 #define LDAP_OPT_X_TLS_KEYFILE 0x6005 #define LDAP_OPT_X_TLS_REQUIRE_CERT 0x6006 #define LDAP_OPT_X_TLS_PROTOCOL_MIN 0x6007 #define LDAP_OPT_X_TLS_CIPHER_SUITE 0x6008 #define LDAP_OPT_X_TLS_RANDOM_FILE 0x6009 #define LDAP_OPT_X_TLS_SSL_CTX 0x600a /* OpenSSL SSL* */ #define LDAP_OPT_X_TLS_CRLCHECK 0x600b #define LDAP_OPT_X_TLS_CONNECT_CB 0x600c #define LDAP_OPT_X_TLS_CONNECT_ARG 0x600d #define LDAP_OPT_X_TLS_DHFILE 0x600e #define LDAP_OPT_X_TLS_NEWCTX 0x600f #define LDAP_OPT_X_TLS_CRLFILE 0x6010 /* GNUtls only */ #define LDAP_OPT_X_TLS_PACKAGE 0x6011 #define LDAP_OPT_X_TLS_NEVER 0 #define LDAP_OPT_X_TLS_HARD 1 #define LDAP_OPT_X_TLS_DEMAND 2 #define LDAP_OPT_X_TLS_ALLOW 3 #define LDAP_OPT_X_TLS_TRY 4 #define LDAP_OPT_X_TLS_CRL_NONE 0 #define LDAP_OPT_X_TLS_CRL_PEER 1 #define LDAP_OPT_X_TLS_CRL_ALL 2 /* for LDAP_OPT_X_TLS_PROTOCOL_MIN */ #define LDAP_OPT_X_TLS_PROTOCOL(maj,min) (((maj) << 8) + (min)) #define LDAP_OPT_X_TLS_PROTOCOL_SSL2 (2 << 8) #define LDAP_OPT_X_TLS_PROTOCOL_SSL3 (3 << 8) #define LDAP_OPT_X_TLS_PROTOCOL_TLS1_0 ((3 << 8) + 1) #define LDAP_OPT_X_TLS_PROTOCOL_TLS1_1 ((3 << 8) + 2) #define LDAP_OPT_X_TLS_PROTOCOL_TLS1_2 ((3 << 8) + 3) /* OpenLDAP SASL options */ #define LDAP_OPT_X_SASL_MECH 0x6100 #define LDAP_OPT_X_SASL_REALM 0x6101 #define LDAP_OPT_X_SASL_AUTHCID 0x6102 #define LDAP_OPT_X_SASL_AUTHZID 0x6103 #define LDAP_OPT_X_SASL_SSF 0x6104 /* read-only */ #define LDAP_OPT_X_SASL_SSF_EXTERNAL 0x6105 /* write-only */ #define LDAP_OPT_X_SASL_SECPROPS 0x6106 /* write-only */ #define LDAP_OPT_X_SASL_SSF_MIN 0x6107 #define LDAP_OPT_X_SASL_SSF_MAX 0x6108 #define LDAP_OPT_X_SASL_MAXBUFSIZE 0x6109 #define LDAP_OPT_X_SASL_MECHLIST 0x610a /* read-only */ #define LDAP_OPT_X_SASL_NOCANON 0x610b #define LDAP_OPT_X_SASL_USERNAME 0x610c /* read-only */ #define LDAP_OPT_X_SASL_GSS_CREDS 0x610d /* OpenLDAP GSSAPI options */ #define LDAP_OPT_X_GSSAPI_DO_NOT_FREE_CONTEXT 0x6200 #define LDAP_OPT_X_GSSAPI_ALLOW_REMOTE_PRINCIPAL 0x6201 /* * OpenLDAP per connection tcp-keepalive settings * (Linux only, ignored where unsupported) */ #define LDAP_OPT_X_KEEPALIVE_IDLE 0x6300 #define LDAP_OPT_X_KEEPALIVE_PROBES 0x6301 #define LDAP_OPT_X_KEEPALIVE_INTERVAL 0x6302 /* Private API Extensions -- reserved for application use */ #define LDAP_OPT_PRIVATE_EXTENSION_BASE 0x7000 /* Private API inclusive */ /* * ldap_get_option() and ldap_set_option() return values. * As later versions may return other values indicating * failure, current applications should only compare returned * value against LDAP_OPT_SUCCESS. */ #define LDAP_OPT_SUCCESS 0 #define LDAP_OPT_ERROR (-1) /* option on/off values */ #define LDAP_OPT_ON ((void *) &ber_pvt_opt_on) #define LDAP_OPT_OFF ((void *) 0) typedef struct ldapapiinfo { int ldapai_info_version; /* version of LDAPAPIInfo */ #define LDAP_API_INFO_VERSION (1) int ldapai_api_version; /* revision of API supported */ int ldapai_protocol_version; /* highest LDAP version supported */ char **ldapai_extensions; /* names of API extensions */ char *ldapai_vendor_name; /* name of supplier */ int ldapai_vendor_version; /* supplier-specific version * 100 */ } LDAPAPIInfo; typedef struct ldap_apifeature_info { int ldapaif_info_version; /* version of LDAPAPIFeatureInfo */ #define LDAP_FEATURE_INFO_VERSION (1) /* apifeature_info struct version */ char* ldapaif_name; /* LDAP_API_FEATURE_* (less prefix) */ int ldapaif_version; /* value of LDAP_API_FEATURE_... */ } LDAPAPIFeatureInfo; /* * LDAP Control structure */ typedef struct ldapcontrol { char * ldctl_oid; /* numericoid of control */ struct berval ldctl_value; /* encoded value of control */ char ldctl_iscritical; /* criticality */ } LDAPControl; /* LDAP Controls */ /* standard track controls */ #define LDAP_CONTROL_MANAGEDSAIT "2.16.840.1.113730.3.4.2" /* RFC 3296 */ #define LDAP_CONTROL_PROXY_AUTHZ "2.16.840.1.113730.3.4.18" /* RFC 4370 */ #define LDAP_CONTROL_SUBENTRIES "1.3.6.1.4.1.4203.1.10.1" /* RFC 3672 */ #define LDAP_CONTROL_VALUESRETURNFILTER "1.2.826.0.1.3344810.2.3"/* RFC 3876 */ #define LDAP_CONTROL_ASSERT "1.3.6.1.1.12" /* RFC 4528 */ #define LDAP_CONTROL_PRE_READ "1.3.6.1.1.13.1" /* RFC 4527 */ #define LDAP_CONTROL_POST_READ "1.3.6.1.1.13.2" /* RFC 4527 */ #define LDAP_CONTROL_SORTREQUEST "1.2.840.113556.1.4.473" /* RFC 2891 */ #define LDAP_CONTROL_SORTRESPONSE "1.2.840.113556.1.4.474" /* RFC 2891 */ /* non-standard track controls */ #define LDAP_CONTROL_PAGEDRESULTS "1.2.840.113556.1.4.319" /* RFC 2696 */ /* LDAP Content Synchronization Operation -- RFC 4533 */ #define LDAP_SYNC_OID "1.3.6.1.4.1.4203.1.9.1" #define LDAP_CONTROL_SYNC LDAP_SYNC_OID ".1" #define LDAP_CONTROL_SYNC_STATE LDAP_SYNC_OID ".2" #define LDAP_CONTROL_SYNC_DONE LDAP_SYNC_OID ".3" #define LDAP_SYNC_INFO LDAP_SYNC_OID ".4" #define LDAP_SYNC_NONE 0x00 #define LDAP_SYNC_REFRESH_ONLY 0x01 #define LDAP_SYNC_RESERVED 0x02 #define LDAP_SYNC_REFRESH_AND_PERSIST 0x03 #define LDAP_SYNC_REFRESH_PRESENTS 0 #define LDAP_SYNC_REFRESH_DELETES 1 #define LDAP_TAG_SYNC_NEW_COOKIE ((ber_tag_t) 0x80U) #define LDAP_TAG_SYNC_REFRESH_DELETE ((ber_tag_t) 0xa1U) #define LDAP_TAG_SYNC_REFRESH_PRESENT ((ber_tag_t) 0xa2U) #define LDAP_TAG_SYNC_ID_SET ((ber_tag_t) 0xa3U) #define LDAP_TAG_SYNC_COOKIE ((ber_tag_t) 0x04U) #define LDAP_TAG_REFRESHDELETES ((ber_tag_t) 0x01U) #define LDAP_TAG_REFRESHDONE ((ber_tag_t) 0x01U) #define LDAP_TAG_RELOAD_HINT ((ber_tag_t) 0x01U) #define LDAP_SYNC_PRESENT 0 #define LDAP_SYNC_ADD 1 #define LDAP_SYNC_MODIFY 2 #define LDAP_SYNC_DELETE 3 #define LDAP_SYNC_NEW_COOKIE 4 /* LDAP Don't Use Copy Control (RFC 6171) */ #define LDAP_CONTROL_DONTUSECOPY "1.3.6.1.1.22" /* Password policy Controls *//* work in progress */ /* ITS#3458: released; disabled by default */ #define LDAP_CONTROL_PASSWORDPOLICYREQUEST "1.3.6.1.4.1.42.2.27.8.5.1" #define LDAP_CONTROL_PASSWORDPOLICYRESPONSE "1.3.6.1.4.1.42.2.27.8.5.1" /* various works in progress */ #define LDAP_CONTROL_NOOP "1.3.6.1.4.1.4203.666.5.2" #define LDAP_CONTROL_NO_SUBORDINATES "1.3.6.1.4.1.4203.666.5.11" #define LDAP_CONTROL_RELAX "1.3.6.1.4.1.4203.666.5.12" #define LDAP_CONTROL_MANAGEDIT LDAP_CONTROL_RELAX #define LDAP_CONTROL_SLURP "1.3.6.1.4.1.4203.666.5.13" #define LDAP_CONTROL_VALSORT "1.3.6.1.4.1.4203.666.5.14" #define LDAP_CONTROL_X_DEREF "1.3.6.1.4.1.4203.666.5.16" #define LDAP_CONTROL_X_WHATFAILED "1.3.6.1.4.1.4203.666.5.17" /* LDAP Chaining Behavior Control *//* work in progress */ /* ; * see also LDAP_NO_REFERRALS_FOUND, LDAP_CANNOT_CHAIN */ #define LDAP_CONTROL_X_CHAINING_BEHAVIOR "1.3.6.1.4.1.4203.666.11.3" #define LDAP_CHAINING_PREFERRED 0 #define LDAP_CHAINING_REQUIRED 1 #define LDAP_REFERRALS_PREFERRED 2 #define LDAP_REFERRALS_REQUIRED 3 /* MS Active Directory controls (for compatibility) */ #define LDAP_CONTROL_X_INCREMENTAL_VALUES "1.2.840.113556.1.4.802" #define LDAP_CONTROL_X_DOMAIN_SCOPE "1.2.840.113556.1.4.1339" #define LDAP_CONTROL_X_PERMISSIVE_MODIFY "1.2.840.113556.1.4.1413" #define LDAP_CONTROL_X_SEARCH_OPTIONS "1.2.840.113556.1.4.1340" #define LDAP_SEARCH_FLAG_DOMAIN_SCOPE 1 /* do not generate referrals */ #define LDAP_SEARCH_FLAG_PHANTOM_ROOT 2 /* search all subordinate NCs */ #define LDAP_CONTROL_X_TREE_DELETE "1.2.840.113556.1.4.805" /* MS Active Directory controls - not implemented in slapd(8) */ #define LDAP_CONTROL_X_EXTENDED_DN "1.2.840.113556.1.4.529" /* */ #define LDAP_CONTROL_X_SESSION_TRACKING "1.3.6.1.4.1.21008.108.63.1" #define LDAP_CONTROL_X_SESSION_TRACKING_RADIUS_ACCT_SESSION_ID \ LDAP_CONTROL_X_SESSION_TRACKING ".1" #define LDAP_CONTROL_X_SESSION_TRACKING_RADIUS_ACCT_MULTI_SESSION_ID \ LDAP_CONTROL_X_SESSION_TRACKING ".2" #define LDAP_CONTROL_X_SESSION_TRACKING_USERNAME \ LDAP_CONTROL_X_SESSION_TRACKING ".3" /* various expired works */ /* LDAP Duplicated Entry Control Extension *//* not implemented in slapd(8) */ #define LDAP_CONTROL_DUPENT_REQUEST "2.16.840.1.113719.1.27.101.1" #define LDAP_CONTROL_DUPENT_RESPONSE "2.16.840.1.113719.1.27.101.2" #define LDAP_CONTROL_DUPENT_ENTRY "2.16.840.1.113719.1.27.101.3" #define LDAP_CONTROL_DUPENT LDAP_CONTROL_DUPENT_REQUEST /* LDAP Persistent Search Control *//* not implemented in slapd(8) */ #define LDAP_CONTROL_PERSIST_REQUEST "2.16.840.1.113730.3.4.3" #define LDAP_CONTROL_PERSIST_ENTRY_CHANGE_NOTICE "2.16.840.1.113730.3.4.7" #define LDAP_CONTROL_PERSIST_ENTRY_CHANGE_ADD 0x1 #define LDAP_CONTROL_PERSIST_ENTRY_CHANGE_DELETE 0x2 #define LDAP_CONTROL_PERSIST_ENTRY_CHANGE_MODIFY 0x4 #define LDAP_CONTROL_PERSIST_ENTRY_CHANGE_RENAME 0x8 /* LDAP VLV */ #define LDAP_CONTROL_VLVREQUEST "2.16.840.1.113730.3.4.9" #define LDAP_CONTROL_VLVRESPONSE "2.16.840.1.113730.3.4.10" /* LDAP Unsolicited Notifications */ #define LDAP_NOTICE_OF_DISCONNECTION "1.3.6.1.4.1.1466.20036" /* RFC 4511 */ #define LDAP_NOTICE_DISCONNECT LDAP_NOTICE_OF_DISCONNECTION /* LDAP Extended Operations */ #define LDAP_EXOP_START_TLS "1.3.6.1.4.1.1466.20037" /* RFC 4511 */ #define LDAP_EXOP_MODIFY_PASSWD "1.3.6.1.4.1.4203.1.11.1" /* RFC 3062 */ #define LDAP_TAG_EXOP_MODIFY_PASSWD_ID ((ber_tag_t) 0x80U) #define LDAP_TAG_EXOP_MODIFY_PASSWD_OLD ((ber_tag_t) 0x81U) #define LDAP_TAG_EXOP_MODIFY_PASSWD_NEW ((ber_tag_t) 0x82U) #define LDAP_TAG_EXOP_MODIFY_PASSWD_GEN ((ber_tag_t) 0x80U) #define LDAP_EXOP_CANCEL "1.3.6.1.1.8" /* RFC 3909 */ #define LDAP_EXOP_X_CANCEL LDAP_EXOP_CANCEL #define LDAP_EXOP_REFRESH "1.3.6.1.4.1.1466.101.119.1" /* RFC 2589 */ #define LDAP_TAG_EXOP_REFRESH_REQ_DN ((ber_tag_t) 0x80U) #define LDAP_TAG_EXOP_REFRESH_REQ_TTL ((ber_tag_t) 0x81U) #define LDAP_TAG_EXOP_REFRESH_RES_TTL ((ber_tag_t) 0x81U) #define LDAP_EXOP_WHO_AM_I "1.3.6.1.4.1.4203.1.11.3" /* RFC 4532 */ #define LDAP_EXOP_X_WHO_AM_I LDAP_EXOP_WHO_AM_I /* various works in progress */ #define LDAP_EXOP_TURN "1.3.6.1.1.19" /* RFC 4531 */ #define LDAP_EXOP_X_TURN LDAP_EXOP_TURN /* LDAP Distributed Procedures */ /* a work in progress */ #define LDAP_X_DISTPROC_BASE "1.3.6.1.4.1.4203.666.11.6" #define LDAP_EXOP_X_CHAINEDREQUEST LDAP_X_DISTPROC_BASE ".1" #define LDAP_FEATURE_X_CANCHAINOPS LDAP_X_DISTPROC_BASE ".2" #define LDAP_CONTROL_X_RETURNCONTREF LDAP_X_DISTPROC_BASE ".3" #define LDAP_URLEXT_X_LOCALREFOID LDAP_X_DISTPROC_BASE ".4" #define LDAP_URLEXT_X_REFTYPEOID LDAP_X_DISTPROC_BASE ".5" #define LDAP_URLEXT_X_SEARCHEDSUBTREEOID \ LDAP_X_DISTPROC_BASE ".6" #define LDAP_URLEXT_X_FAILEDNAMEOID LDAP_X_DISTPROC_BASE ".7" #define LDAP_URLEXT_X_LOCALREF "x-localReference" #define LDAP_URLEXT_X_REFTYPE "x-referenceType" #define LDAP_URLEXT_X_SEARCHEDSUBTREE "x-searchedSubtree" #define LDAP_URLEXT_X_FAILEDNAME "x-failedName" #ifdef LDAP_DEVEL #define LDAP_X_TXN "1.3.6.1.4.1.4203.666.11.7" /* tmp */ #define LDAP_EXOP_X_TXN_START LDAP_X_TXN ".1" #define LDAP_CONTROL_X_TXN_SPEC LDAP_X_TXN ".2" #define LDAP_EXOP_X_TXN_END LDAP_X_TXN ".3" #define LDAP_EXOP_X_TXN_ABORTED_NOTICE LDAP_X_TXN ".4" #endif /* LDAP Features */ #define LDAP_FEATURE_ALL_OP_ATTRS "1.3.6.1.4.1.4203.1.5.1" /* RFC 3673 */ #define LDAP_FEATURE_OBJECTCLASS_ATTRS \ "1.3.6.1.4.1.4203.1.5.2" /* @objectClass - new number to be assigned */ #define LDAP_FEATURE_ABSOLUTE_FILTERS "1.3.6.1.4.1.4203.1.5.3" /* (&) (|) */ #define LDAP_FEATURE_LANGUAGE_TAG_OPTIONS "1.3.6.1.4.1.4203.1.5.4" #define LDAP_FEATURE_LANGUAGE_RANGE_OPTIONS "1.3.6.1.4.1.4203.1.5.5" #define LDAP_FEATURE_MODIFY_INCREMENT "1.3.6.1.1.14" /* LDAP Experimental (works in progress) Features */ #define LDAP_FEATURE_SUBORDINATE_SCOPE \ "1.3.6.1.4.1.4203.666.8.1" /* "children" */ #define LDAP_FEATURE_CHILDREN_SCOPE LDAP_FEATURE_SUBORDINATE_SCOPE /* * specific LDAP instantiations of BER types we know about */ /* Overview of LBER tag construction * * Bits * ______ * 8 7 | CLASS * 0 0 = UNIVERSAL * 0 1 = APPLICATION * 1 0 = CONTEXT-SPECIFIC * 1 1 = PRIVATE * _____ * | 6 | DATA-TYPE * 0 = PRIMITIVE * 1 = CONSTRUCTED * ___________ * | 5 ... 1 | TAG-NUMBER */ /* general stuff */ #define LDAP_TAG_MESSAGE ((ber_tag_t) 0x30U) /* constructed + 16 */ #define LDAP_TAG_MSGID ((ber_tag_t) 0x02U) /* integer */ #define LDAP_TAG_LDAPDN ((ber_tag_t) 0x04U) /* octet string */ #define LDAP_TAG_LDAPCRED ((ber_tag_t) 0x04U) /* octet string */ #define LDAP_TAG_CONTROLS ((ber_tag_t) 0xa0U) /* context specific + constructed + 0 */ #define LDAP_TAG_REFERRAL ((ber_tag_t) 0xa3U) /* context specific + constructed + 3 */ #define LDAP_TAG_NEWSUPERIOR ((ber_tag_t) 0x80U) /* context-specific + primitive + 0 */ #define LDAP_TAG_EXOP_REQ_OID ((ber_tag_t) 0x80U) /* context specific + primitive */ #define LDAP_TAG_EXOP_REQ_VALUE ((ber_tag_t) 0x81U) /* context specific + primitive */ #define LDAP_TAG_EXOP_RES_OID ((ber_tag_t) 0x8aU) /* context specific + primitive */ #define LDAP_TAG_EXOP_RES_VALUE ((ber_tag_t) 0x8bU) /* context specific + primitive */ #define LDAP_TAG_IM_RES_OID ((ber_tag_t) 0x80U) /* context specific + primitive */ #define LDAP_TAG_IM_RES_VALUE ((ber_tag_t) 0x81U) /* context specific + primitive */ #define LDAP_TAG_SASL_RES_CREDS ((ber_tag_t) 0x87U) /* context specific + primitive */ /* LDAP Request Messages */ #define LDAP_REQ_BIND ((ber_tag_t) 0x60U) /* application + constructed */ #define LDAP_REQ_UNBIND ((ber_tag_t) 0x42U) /* application + primitive */ #define LDAP_REQ_SEARCH ((ber_tag_t) 0x63U) /* application + constructed */ #define LDAP_REQ_MODIFY ((ber_tag_t) 0x66U) /* application + constructed */ #define LDAP_REQ_ADD ((ber_tag_t) 0x68U) /* application + constructed */ #define LDAP_REQ_DELETE ((ber_tag_t) 0x4aU) /* application + primitive */ #define LDAP_REQ_MODDN ((ber_tag_t) 0x6cU) /* application + constructed */ #define LDAP_REQ_MODRDN LDAP_REQ_MODDN #define LDAP_REQ_RENAME LDAP_REQ_MODDN #define LDAP_REQ_COMPARE ((ber_tag_t) 0x6eU) /* application + constructed */ #define LDAP_REQ_ABANDON ((ber_tag_t) 0x50U) /* application + primitive */ #define LDAP_REQ_EXTENDED ((ber_tag_t) 0x77U) /* application + constructed */ /* LDAP Response Messages */ #define LDAP_RES_BIND ((ber_tag_t) 0x61U) /* application + constructed */ #define LDAP_RES_SEARCH_ENTRY ((ber_tag_t) 0x64U) /* application + constructed */ #define LDAP_RES_SEARCH_REFERENCE ((ber_tag_t) 0x73U) /* V3: application + constructed */ #define LDAP_RES_SEARCH_RESULT ((ber_tag_t) 0x65U) /* application + constructed */ #define LDAP_RES_MODIFY ((ber_tag_t) 0x67U) /* application + constructed */ #define LDAP_RES_ADD ((ber_tag_t) 0x69U) /* application + constructed */ #define LDAP_RES_DELETE ((ber_tag_t) 0x6bU) /* application + constructed */ #define LDAP_RES_MODDN ((ber_tag_t) 0x6dU) /* application + constructed */ #define LDAP_RES_MODRDN LDAP_RES_MODDN /* application + constructed */ #define LDAP_RES_RENAME LDAP_RES_MODDN /* application + constructed */ #define LDAP_RES_COMPARE ((ber_tag_t) 0x6fU) /* application + constructed */ #define LDAP_RES_EXTENDED ((ber_tag_t) 0x78U) /* V3: application + constructed */ #define LDAP_RES_INTERMEDIATE ((ber_tag_t) 0x79U) /* V3+: application + constructed */ #define LDAP_RES_ANY (-1) #define LDAP_RES_UNSOLICITED (0) /* sasl methods */ #define LDAP_SASL_SIMPLE ((char*)0) #define LDAP_SASL_NULL ("") /* authentication methods available */ #define LDAP_AUTH_NONE ((ber_tag_t) 0x00U) /* no authentication */ #define LDAP_AUTH_SIMPLE ((ber_tag_t) 0x80U) /* context specific + primitive */ #define LDAP_AUTH_SASL ((ber_tag_t) 0xa3U) /* context specific + constructed */ #define LDAP_AUTH_KRBV4 ((ber_tag_t) 0xffU) /* means do both of the following */ #define LDAP_AUTH_KRBV41 ((ber_tag_t) 0x81U) /* context specific + primitive */ #define LDAP_AUTH_KRBV42 ((ber_tag_t) 0x82U) /* context specific + primitive */ /* used by the Windows API but not used on the wire */ #define LDAP_AUTH_NEGOTIATE ((ber_tag_t) 0x04FFU) /* filter types */ #define LDAP_FILTER_AND ((ber_tag_t) 0xa0U) /* context specific + constructed */ #define LDAP_FILTER_OR ((ber_tag_t) 0xa1U) /* context specific + constructed */ #define LDAP_FILTER_NOT ((ber_tag_t) 0xa2U) /* context specific + constructed */ #define LDAP_FILTER_EQUALITY ((ber_tag_t) 0xa3U) /* context specific + constructed */ #define LDAP_FILTER_SUBSTRINGS ((ber_tag_t) 0xa4U) /* context specific + constructed */ #define LDAP_FILTER_GE ((ber_tag_t) 0xa5U) /* context specific + constructed */ #define LDAP_FILTER_LE ((ber_tag_t) 0xa6U) /* context specific + constructed */ #define LDAP_FILTER_PRESENT ((ber_tag_t) 0x87U) /* context specific + primitive */ #define LDAP_FILTER_APPROX ((ber_tag_t) 0xa8U) /* context specific + constructed */ #define LDAP_FILTER_EXT ((ber_tag_t) 0xa9U) /* context specific + constructed */ /* extended filter component types */ #define LDAP_FILTER_EXT_OID ((ber_tag_t) 0x81U) /* context specific */ #define LDAP_FILTER_EXT_TYPE ((ber_tag_t) 0x82U) /* context specific */ #define LDAP_FILTER_EXT_VALUE ((ber_tag_t) 0x83U) /* context specific */ #define LDAP_FILTER_EXT_DNATTRS ((ber_tag_t) 0x84U) /* context specific */ /* substring filter component types */ #define LDAP_SUBSTRING_INITIAL ((ber_tag_t) 0x80U) /* context specific */ #define LDAP_SUBSTRING_ANY ((ber_tag_t) 0x81U) /* context specific */ #define LDAP_SUBSTRING_FINAL ((ber_tag_t) 0x82U) /* context specific */ /* search scopes */ #define LDAP_SCOPE_BASE ((ber_int_t) 0x0000) #define LDAP_SCOPE_BASEOBJECT LDAP_SCOPE_BASE #define LDAP_SCOPE_ONELEVEL ((ber_int_t) 0x0001) #define LDAP_SCOPE_ONE LDAP_SCOPE_ONELEVEL #define LDAP_SCOPE_SUBTREE ((ber_int_t) 0x0002) #define LDAP_SCOPE_SUB LDAP_SCOPE_SUBTREE #define LDAP_SCOPE_SUBORDINATE ((ber_int_t) 0x0003) /* OpenLDAP extension */ #define LDAP_SCOPE_CHILDREN LDAP_SCOPE_SUBORDINATE #define LDAP_SCOPE_DEFAULT ((ber_int_t) -1) /* OpenLDAP extension */ /* substring filter component types */ #define LDAP_SUBSTRING_INITIAL ((ber_tag_t) 0x80U) /* context specific */ #define LDAP_SUBSTRING_ANY ((ber_tag_t) 0x81U) /* context specific */ #define LDAP_SUBSTRING_FINAL ((ber_tag_t) 0x82U) /* context specific */ /* * LDAP Result Codes */ #define LDAP_SUCCESS 0x00 #define LDAP_RANGE(n,x,y) (((x) <= (n)) && ((n) <= (y))) #define LDAP_OPERATIONS_ERROR 0x01 #define LDAP_PROTOCOL_ERROR 0x02 #define LDAP_TIMELIMIT_EXCEEDED 0x03 #define LDAP_SIZELIMIT_EXCEEDED 0x04 #define LDAP_COMPARE_FALSE 0x05 #define LDAP_COMPARE_TRUE 0x06 #define LDAP_AUTH_METHOD_NOT_SUPPORTED 0x07 #define LDAP_STRONG_AUTH_NOT_SUPPORTED LDAP_AUTH_METHOD_NOT_SUPPORTED #define LDAP_STRONG_AUTH_REQUIRED 0x08 #define LDAP_STRONGER_AUTH_REQUIRED LDAP_STRONG_AUTH_REQUIRED #define LDAP_PARTIAL_RESULTS 0x09 /* LDAPv2+ (not LDAPv3) */ #define LDAP_REFERRAL 0x0a /* LDAPv3 */ #define LDAP_ADMINLIMIT_EXCEEDED 0x0b /* LDAPv3 */ #define LDAP_UNAVAILABLE_CRITICAL_EXTENSION 0x0c /* LDAPv3 */ #define LDAP_CONFIDENTIALITY_REQUIRED 0x0d /* LDAPv3 */ #define LDAP_SASL_BIND_IN_PROGRESS 0x0e /* LDAPv3 */ #define LDAP_ATTR_ERROR(n) LDAP_RANGE((n),0x10,0x15) /* 16-21 */ #define LDAP_NO_SUCH_ATTRIBUTE 0x10 #define LDAP_UNDEFINED_TYPE 0x11 #define LDAP_INAPPROPRIATE_MATCHING 0x12 #define LDAP_CONSTRAINT_VIOLATION 0x13 #define LDAP_TYPE_OR_VALUE_EXISTS 0x14 #define LDAP_INVALID_SYNTAX 0x15 #define LDAP_NAME_ERROR(n) LDAP_RANGE((n),0x20,0x24) /* 32-34,36 */ #define LDAP_NO_SUCH_OBJECT 0x20 #define LDAP_ALIAS_PROBLEM 0x21 #define LDAP_INVALID_DN_SYNTAX 0x22 #define LDAP_IS_LEAF 0x23 /* not LDAPv3 */ #define LDAP_ALIAS_DEREF_PROBLEM 0x24 #define LDAP_SECURITY_ERROR(n) LDAP_RANGE((n),0x2F,0x32) /* 47-50 */ #define LDAP_X_PROXY_AUTHZ_FAILURE 0x2F /* LDAPv3 proxy authorization */ #define LDAP_INAPPROPRIATE_AUTH 0x30 #define LDAP_INVALID_CREDENTIALS 0x31 #define LDAP_INSUFFICIENT_ACCESS 0x32 #define LDAP_SERVICE_ERROR(n) LDAP_RANGE((n),0x33,0x36) /* 51-54 */ #define LDAP_BUSY 0x33 #define LDAP_UNAVAILABLE 0x34 #define LDAP_UNWILLING_TO_PERFORM 0x35 #define LDAP_LOOP_DETECT 0x36 #define LDAP_UPDATE_ERROR(n) LDAP_RANGE((n),0x40,0x47) /* 64-69,71 */ #define LDAP_NAMING_VIOLATION 0x40 #define LDAP_OBJECT_CLASS_VIOLATION 0x41 #define LDAP_NOT_ALLOWED_ON_NONLEAF 0x42 #define LDAP_NOT_ALLOWED_ON_RDN 0x43 #define LDAP_ALREADY_EXISTS 0x44 #define LDAP_NO_OBJECT_CLASS_MODS 0x45 #define LDAP_RESULTS_TOO_LARGE 0x46 /* CLDAP */ #define LDAP_AFFECTS_MULTIPLE_DSAS 0x47 #define LDAP_VLV_ERROR 0x4C #define LDAP_OTHER 0x50 /* LCUP operation codes (113-117) - not implemented */ #define LDAP_CUP_RESOURCES_EXHAUSTED 0x71 #define LDAP_CUP_SECURITY_VIOLATION 0x72 #define LDAP_CUP_INVALID_DATA 0x73 #define LDAP_CUP_UNSUPPORTED_SCHEME 0x74 #define LDAP_CUP_RELOAD_REQUIRED 0x75 /* Cancel operation codes (118-121) */ #define LDAP_CANCELLED 0x76 #define LDAP_NO_SUCH_OPERATION 0x77 #define LDAP_TOO_LATE 0x78 #define LDAP_CANNOT_CANCEL 0x79 /* Assertion control (122) */ #define LDAP_ASSERTION_FAILED 0x7A /* Proxied Authorization Denied (123) */ #define LDAP_PROXIED_AUTHORIZATION_DENIED 0x7B /* Experimental result codes */ #define LDAP_E_ERROR(n) LDAP_RANGE((n),0x1000,0x3FFF) /* LDAP Sync (4096) */ #define LDAP_SYNC_REFRESH_REQUIRED 0x1000 /* Private Use result codes */ #define LDAP_X_ERROR(n) LDAP_RANGE((n),0x4000,0xFFFF) #define LDAP_X_SYNC_REFRESH_REQUIRED 0x4100 /* defunct */ #define LDAP_X_ASSERTION_FAILED 0x410f /* defunct */ /* for the LDAP No-Op control */ #define LDAP_X_NO_OPERATION 0x410e /* for the Chaining Behavior control (consecutive result codes requested; * see ) */ #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR #define LDAP_X_NO_REFERRALS_FOUND 0x4110 #define LDAP_X_CANNOT_CHAIN 0x4111 #endif /* for Distributed Procedures (see ) */ #ifdef LDAP_X_DISTPROC_BASE #define LDAP_X_INVALIDREFERENCE 0x4112 #endif #ifdef LDAP_X_TXN #define LDAP_X_TXN_SPECIFY_OKAY 0x4120 #define LDAP_X_TXN_ID_INVALID 0x4121 #endif /* API Error Codes * * Based on draft-ietf-ldap-c-api-xx * but with new negative code values */ #define LDAP_API_ERROR(n) ((n)<0) #define LDAP_API_RESULT(n) ((n)<=0) #define LDAP_SERVER_DOWN (-1) #define LDAP_LOCAL_ERROR (-2) #define LDAP_ENCODING_ERROR (-3) #define LDAP_DECODING_ERROR (-4) #define LDAP_TIMEOUT (-5) #define LDAP_AUTH_UNKNOWN (-6) #define LDAP_FILTER_ERROR (-7) #define LDAP_USER_CANCELLED (-8) #define LDAP_PARAM_ERROR (-9) #define LDAP_NO_MEMORY (-10) #define LDAP_CONNECT_ERROR (-11) #define LDAP_NOT_SUPPORTED (-12) #define LDAP_CONTROL_NOT_FOUND (-13) #define LDAP_NO_RESULTS_RETURNED (-14) #define LDAP_MORE_RESULTS_TO_RETURN (-15) /* Obsolete */ #define LDAP_CLIENT_LOOP (-16) #define LDAP_REFERRAL_LIMIT_EXCEEDED (-17) #define LDAP_X_CONNECTING (-18) /* * This structure represents both ldap messages and ldap responses. * These are really the same, except in the case of search responses, * where a response has multiple messages. */ typedef struct ldapmsg LDAPMessage; /* for modifications */ typedef struct ldapmod { int mod_op; #define LDAP_MOD_OP (0x0007) #define LDAP_MOD_ADD (0x0000) #define LDAP_MOD_DELETE (0x0001) #define LDAP_MOD_REPLACE (0x0002) #define LDAP_MOD_INCREMENT (0x0003) /* OpenLDAP extension */ #define LDAP_MOD_BVALUES (0x0080) /* IMPORTANT: do not use code 0x1000 (or above), * it is used internally by the backends! * (see ldap/servers/slapd/slap.h) */ char *mod_type; union mod_vals_u { char **modv_strvals; struct berval **modv_bvals; } mod_vals; #define mod_values mod_vals.modv_strvals #define mod_bvalues mod_vals.modv_bvals } LDAPMod; /* * structure representing an ldap session which can * encompass connections to multiple servers (in the * face of referrals). */ typedef struct ldap LDAP; #define LDAP_DEREF_NEVER 0x00 #define LDAP_DEREF_SEARCHING 0x01 #define LDAP_DEREF_FINDING 0x02 #define LDAP_DEREF_ALWAYS 0x03 #define LDAP_NO_LIMIT 0 /* how many messages to retrieve results for */ #define LDAP_MSG_ONE 0x00 #define LDAP_MSG_ALL 0x01 #define LDAP_MSG_RECEIVED 0x02 /* * types for ldap URL handling */ typedef struct ldap_url_desc { struct ldap_url_desc *lud_next; char *lud_scheme; char *lud_host; int lud_port; char *lud_dn; char **lud_attrs; int lud_scope; char *lud_filter; char **lud_exts; int lud_crit_exts; } LDAPURLDesc; #define LDAP_URL_SUCCESS 0x00 /* Success */ #define LDAP_URL_ERR_MEM 0x01 /* can't allocate memory space */ #define LDAP_URL_ERR_PARAM 0x02 /* parameter is bad */ #define LDAP_URL_ERR_BADSCHEME 0x03 /* URL doesn't begin with "ldap[si]://" */ #define LDAP_URL_ERR_BADENCLOSURE 0x04 /* URL is missing trailing ">" */ #define LDAP_URL_ERR_BADURL 0x05 /* URL is bad */ #define LDAP_URL_ERR_BADHOST 0x06 /* host port is bad */ #define LDAP_URL_ERR_BADATTRS 0x07 /* bad (or missing) attributes */ #define LDAP_URL_ERR_BADSCOPE 0x08 /* scope string is invalid (or missing) */ #define LDAP_URL_ERR_BADFILTER 0x09 /* bad or missing filter */ #define LDAP_URL_ERR_BADEXTS 0x0a /* bad or missing extensions */ /* * LDAP sync (RFC4533) API */ typedef struct ldap_sync_t ldap_sync_t; typedef enum { /* these are private - the client should never see them */ LDAP_SYNC_CAPI_NONE = -1, LDAP_SYNC_CAPI_PHASE_FLAG = 0x10U, LDAP_SYNC_CAPI_IDSET_FLAG = 0x20U, LDAP_SYNC_CAPI_DONE_FLAG = 0x40U, /* these are passed to ls_search_entry() */ LDAP_SYNC_CAPI_PRESENT = LDAP_SYNC_PRESENT, LDAP_SYNC_CAPI_ADD = LDAP_SYNC_ADD, LDAP_SYNC_CAPI_MODIFY = LDAP_SYNC_MODIFY, LDAP_SYNC_CAPI_DELETE = LDAP_SYNC_DELETE, /* these are passed to ls_intermediate() */ LDAP_SYNC_CAPI_PRESENTS = ( LDAP_SYNC_CAPI_PHASE_FLAG | LDAP_SYNC_CAPI_PRESENT ), LDAP_SYNC_CAPI_DELETES = ( LDAP_SYNC_CAPI_PHASE_FLAG | LDAP_SYNC_CAPI_DELETE ), LDAP_SYNC_CAPI_PRESENTS_IDSET = ( LDAP_SYNC_CAPI_PRESENTS | LDAP_SYNC_CAPI_IDSET_FLAG ), LDAP_SYNC_CAPI_DELETES_IDSET = ( LDAP_SYNC_CAPI_DELETES | LDAP_SYNC_CAPI_IDSET_FLAG ), LDAP_SYNC_CAPI_DONE = ( LDAP_SYNC_CAPI_DONE_FLAG | LDAP_SYNC_CAPI_PRESENTS ) } ldap_sync_refresh_t; /* * Called when an entry is returned by ldap_result(). * If phase is LDAP_SYNC_CAPI_ADD or LDAP_SYNC_CAPI_MODIFY, * the entry has been either added or modified, and thus * the complete view of the entry should be in the LDAPMessage. * If phase is LDAP_SYNC_CAPI_PRESENT or LDAP_SYNC_CAPI_DELETE, * only the DN should be in the LDAPMessage. */ typedef int (*ldap_sync_search_entry_f) LDAP_P(( ldap_sync_t *ls, LDAPMessage *msg, struct berval *entryUUID, ldap_sync_refresh_t phase )); /* * Called when a reference is returned; the client should know * what to do with it. */ typedef int (*ldap_sync_search_reference_f) LDAP_P(( ldap_sync_t *ls, LDAPMessage *msg )); /* * Called when specific intermediate/final messages are returned. * If phase is LDAP_SYNC_CAPI_PRESENTS or LDAP_SYNC_CAPI_DELETES, * a "presents" or "deletes" phase begins. * If phase is LDAP_SYNC_CAPI_DONE, a special "presents" phase * with refreshDone set to "TRUE" has been returned, to indicate * that the refresh phase of a refreshAndPersist is complete. * In the above cases, syncUUIDs is NULL. * * If phase is LDAP_SYNC_CAPI_PRESENTS_IDSET or * LDAP_SYNC_CAPI_DELETES_IDSET, syncUUIDs is an array of UUIDs * that are either present or have been deleted. */ typedef int (*ldap_sync_intermediate_f) LDAP_P(( ldap_sync_t *ls, LDAPMessage *msg, BerVarray syncUUIDs, ldap_sync_refresh_t phase )); /* * Called when a searchResultDone is returned. In refreshAndPersist, * this can only occur if the search for any reason is being terminated * by the server. */ typedef int (*ldap_sync_search_result_f) LDAP_P(( ldap_sync_t *ls, LDAPMessage *msg, int refreshDeletes )); /* * This structure contains all information about the persistent search; * the caller is responsible for connecting, setting version, binding, tls... */ struct ldap_sync_t { /* conf search params */ char *ls_base; int ls_scope; char *ls_filter; char **ls_attrs; int ls_timelimit; int ls_sizelimit; /* poll timeout */ int ls_timeout; /* helpers - add as appropriate */ ldap_sync_search_entry_f ls_search_entry; ldap_sync_search_reference_f ls_search_reference; ldap_sync_intermediate_f ls_intermediate; ldap_sync_search_result_f ls_search_result; /* set by the caller as appropriate */ void *ls_private; /* conn stuff */ LDAP *ls_ld; /* --- the parameters below are private - do not modify --- */ /* FIXME: make the structure opaque, and provide an interface * to modify the public values? */ /* result stuff */ int ls_msgid; /* sync stuff */ /* needed by refreshOnly */ int ls_reloadHint; /* opaque - need to pass between sessions, updated by the API */ struct berval ls_cookie; /* state variable - do not modify */ ldap_sync_refresh_t ls_refreshPhase; }; /* * End of LDAP sync (RFC4533) API */ /* * Connection callbacks... */ struct ldap_conncb; struct sockaddr; /* Called after a connection is established */ typedef int (ldap_conn_add_f) LDAP_P(( LDAP *ld, Sockbuf *sb, LDAPURLDesc *srv, struct sockaddr *addr, struct ldap_conncb *ctx )); /* Called before a connection is closed */ typedef void (ldap_conn_del_f) LDAP_P(( LDAP *ld, Sockbuf *sb, struct ldap_conncb *ctx )); /* Callbacks are pushed on a stack. Last one pushed is first one executed. The * delete callback is called with a NULL Sockbuf just before freeing the LDAP handle. */ typedef struct ldap_conncb { ldap_conn_add_f *lc_add; ldap_conn_del_f *lc_del; void *lc_arg; } ldap_conncb; /* * The API draft spec says we should declare (or cause to be declared) * 'struct timeval'. We don't. See IETF LDAPext discussions. */ struct timeval; /* * in options.c: */ LDAP_F( int ) ldap_get_option LDAP_P(( LDAP *ld, int option, void *outvalue)); LDAP_F( int ) ldap_set_option LDAP_P(( LDAP *ld, int option, LDAP_CONST void *invalue)); /* V3 REBIND Function Callback Prototype */ typedef int (LDAP_REBIND_PROC) LDAP_P(( LDAP *ld, LDAP_CONST char *url, ber_tag_t request, ber_int_t msgid, void *params )); LDAP_F( int ) ldap_set_rebind_proc LDAP_P(( LDAP *ld, LDAP_REBIND_PROC *rebind_proc, void *params )); /* V3 referral selection Function Callback Prototype */ typedef int (LDAP_NEXTREF_PROC) LDAP_P(( LDAP *ld, char ***refsp, int *cntp, void *params )); LDAP_F( int ) ldap_set_nextref_proc LDAP_P(( LDAP *ld, LDAP_NEXTREF_PROC *nextref_proc, void *params )); /* V3 URLLIST Function Callback Prototype */ typedef int (LDAP_URLLIST_PROC) LDAP_P(( LDAP *ld, LDAPURLDesc **urllist, LDAPURLDesc **url, void *params )); LDAP_F( int ) ldap_set_urllist_proc LDAP_P(( LDAP *ld, LDAP_URLLIST_PROC *urllist_proc, void *params )); /* * in controls.c: */ #if LDAP_DEPRECATED LDAP_F( int ) ldap_create_control LDAP_P(( /* deprecated, use ldap_control_create */ LDAP_CONST char *requestOID, BerElement *ber, int iscritical, LDAPControl **ctrlp )); LDAP_F( LDAPControl * ) ldap_find_control LDAP_P(( /* deprecated, use ldap_control_find */ LDAP_CONST char *oid, LDAPControl **ctrls )); #endif LDAP_F( int ) ldap_control_create LDAP_P(( LDAP_CONST char *requestOID, int iscritical, struct berval *value, int dupval, LDAPControl **ctrlp )); LDAP_F( LDAPControl * ) ldap_control_find LDAP_P(( LDAP_CONST char *oid, LDAPControl **ctrls, LDAPControl ***nextctrlp )); LDAP_F( void ) ldap_control_free LDAP_P(( LDAPControl *ctrl )); LDAP_F( void ) ldap_controls_free LDAP_P(( LDAPControl **ctrls )); LDAP_F( LDAPControl ** ) ldap_controls_dup LDAP_P(( LDAPControl *LDAP_CONST *controls )); LDAP_F( LDAPControl * ) ldap_control_dup LDAP_P(( LDAP_CONST LDAPControl *c )); /* * in dnssrv.c: */ LDAP_F( int ) ldap_domain2dn LDAP_P(( LDAP_CONST char* domain, char** dn )); LDAP_F( int ) ldap_dn2domain LDAP_P(( LDAP_CONST char* dn, char** domain )); LDAP_F( int ) ldap_domain2hostlist LDAP_P(( LDAP_CONST char *domain, char** hostlist )); /* * in extended.c: */ LDAP_F( int ) ldap_extended_operation LDAP_P(( LDAP *ld, LDAP_CONST char *reqoid, struct berval *reqdata, LDAPControl **serverctrls, LDAPControl **clientctrls, int *msgidp )); LDAP_F( int ) ldap_extended_operation_s LDAP_P(( LDAP *ld, LDAP_CONST char *reqoid, struct berval *reqdata, LDAPControl **serverctrls, LDAPControl **clientctrls, char **retoidp, struct berval **retdatap )); LDAP_F( int ) ldap_parse_extended_result LDAP_P(( LDAP *ld, LDAPMessage *res, char **retoidp, struct berval **retdatap, int freeit )); LDAP_F( int ) ldap_parse_intermediate LDAP_P(( LDAP *ld, LDAPMessage *res, char **retoidp, struct berval **retdatap, LDAPControl ***serverctrls, int freeit )); /* * in abandon.c: */ LDAP_F( int ) ldap_abandon_ext LDAP_P(( LDAP *ld, int msgid, LDAPControl **serverctrls, LDAPControl **clientctrls )); #if LDAP_DEPRECATED LDAP_F( int ) ldap_abandon LDAP_P(( /* deprecated, use ldap_abandon_ext */ LDAP *ld, int msgid )); #endif /* * in add.c: */ LDAP_F( int ) ldap_add_ext LDAP_P(( LDAP *ld, LDAP_CONST char *dn, LDAPMod **attrs, LDAPControl **serverctrls, LDAPControl **clientctrls, int *msgidp )); LDAP_F( int ) ldap_add_ext_s LDAP_P(( LDAP *ld, LDAP_CONST char *dn, LDAPMod **attrs, LDAPControl **serverctrls, LDAPControl **clientctrls )); #if LDAP_DEPRECATED LDAP_F( int ) ldap_add LDAP_P(( /* deprecated, use ldap_add_ext */ LDAP *ld, LDAP_CONST char *dn, LDAPMod **attrs )); LDAP_F( int ) ldap_add_s LDAP_P(( /* deprecated, use ldap_add_ext_s */ LDAP *ld, LDAP_CONST char *dn, LDAPMod **attrs )); #endif /* * in sasl.c: */ LDAP_F( int ) ldap_sasl_bind LDAP_P(( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *mechanism, struct berval *cred, LDAPControl **serverctrls, LDAPControl **clientctrls, int *msgidp )); /* Interaction flags (should be passed about in a control) * Automatic (default): use defaults, prompt otherwise * Interactive: prompt always * Quiet: never prompt */ #define LDAP_SASL_AUTOMATIC 0U #define LDAP_SASL_INTERACTIVE 1U #define LDAP_SASL_QUIET 2U /* * V3 SASL Interaction Function Callback Prototype * when using Cyrus SASL, interact is pointer to sasl_interact_t * should likely passed in a control (and provided controls) */ typedef int (LDAP_SASL_INTERACT_PROC) LDAP_P(( LDAP *ld, unsigned flags, void* defaults, void *interact )); LDAP_F( int ) ldap_sasl_interactive_bind LDAP_P(( LDAP *ld, LDAP_CONST char *dn, /* usually NULL */ LDAP_CONST char *saslMechanism, LDAPControl **serverControls, LDAPControl **clientControls, /* should be client controls */ unsigned flags, LDAP_SASL_INTERACT_PROC *proc, void *defaults, /* as obtained from ldap_result() */ LDAPMessage *result, /* returned during bind processing */ const char **rmech, int *msgid )); LDAP_F( int ) ldap_sasl_interactive_bind_s LDAP_P(( LDAP *ld, LDAP_CONST char *dn, /* usually NULL */ LDAP_CONST char *saslMechanism, LDAPControl **serverControls, LDAPControl **clientControls, /* should be client controls */ unsigned flags, LDAP_SASL_INTERACT_PROC *proc, void *defaults )); LDAP_F( int ) ldap_sasl_bind_s LDAP_P(( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *mechanism, struct berval *cred, LDAPControl **serverctrls, LDAPControl **clientctrls, struct berval **servercredp )); LDAP_F( int ) ldap_parse_sasl_bind_result LDAP_P(( LDAP *ld, LDAPMessage *res, struct berval **servercredp, int freeit )); #if LDAP_DEPRECATED /* * in bind.c: * (deprecated) */ LDAP_F( int ) ldap_bind LDAP_P(( /* deprecated, use ldap_sasl_bind */ LDAP *ld, LDAP_CONST char *who, LDAP_CONST char *passwd, int authmethod )); LDAP_F( int ) ldap_bind_s LDAP_P(( /* deprecated, use ldap_sasl_bind_s */ LDAP *ld, LDAP_CONST char *who, LDAP_CONST char *cred, int authmethod )); /* * in sbind.c: */ LDAP_F( int ) ldap_simple_bind LDAP_P(( /* deprecated, use ldap_sasl_bind */ LDAP *ld, LDAP_CONST char *who, LDAP_CONST char *passwd )); LDAP_F( int ) ldap_simple_bind_s LDAP_P(( /* deprecated, use ldap_sasl_bind_s */ LDAP *ld, LDAP_CONST char *who, LDAP_CONST char *passwd )); #endif /* * in compare.c: */ LDAP_F( int ) ldap_compare_ext LDAP_P(( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *attr, struct berval *bvalue, LDAPControl **serverctrls, LDAPControl **clientctrls, int *msgidp )); LDAP_F( int ) ldap_compare_ext_s LDAP_P(( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *attr, struct berval *bvalue, LDAPControl **serverctrls, LDAPControl **clientctrls )); #if LDAP_DEPRECATED LDAP_F( int ) ldap_compare LDAP_P(( /* deprecated, use ldap_compare_ext */ LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *attr, LDAP_CONST char *value )); LDAP_F( int ) ldap_compare_s LDAP_P(( /* deprecated, use ldap_compare_ext_s */ LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *attr, LDAP_CONST char *value )); #endif /* * in delete.c: */ LDAP_F( int ) ldap_delete_ext LDAP_P(( LDAP *ld, LDAP_CONST char *dn, LDAPControl **serverctrls, LDAPControl **clientctrls, int *msgidp )); LDAP_F( int ) ldap_delete_ext_s LDAP_P(( LDAP *ld, LDAP_CONST char *dn, LDAPControl **serverctrls, LDAPControl **clientctrls )); #if LDAP_DEPRECATED LDAP_F( int ) ldap_delete LDAP_P(( /* deprecated, use ldap_delete_ext */ LDAP *ld, LDAP_CONST char *dn )); LDAP_F( int ) ldap_delete_s LDAP_P(( /* deprecated, use ldap_delete_ext_s */ LDAP *ld, LDAP_CONST char *dn )); #endif /* * in error.c: */ LDAP_F( int ) ldap_parse_result LDAP_P(( LDAP *ld, LDAPMessage *res, int *errcodep, char **matcheddnp, char **errmsgp, char ***referralsp, LDAPControl ***serverctrls, int freeit )); LDAP_F( char * ) ldap_err2string LDAP_P(( int err )); #if LDAP_DEPRECATED LDAP_F( int ) ldap_result2error LDAP_P(( /* deprecated, use ldap_parse_result */ LDAP *ld, LDAPMessage *r, int freeit )); LDAP_F( void ) ldap_perror LDAP_P(( /* deprecated, use ldap_err2string */ LDAP *ld, LDAP_CONST char *s )); #endif /* * gssapi.c: */ LDAP_F( int ) ldap_gssapi_bind LDAP_P(( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *creds )); LDAP_F( int ) ldap_gssapi_bind_s LDAP_P(( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *creds )); /* * in modify.c: */ LDAP_F( int ) ldap_modify_ext LDAP_P(( LDAP *ld, LDAP_CONST char *dn, LDAPMod **mods, LDAPControl **serverctrls, LDAPControl **clientctrls, int *msgidp )); LDAP_F( int ) ldap_modify_ext_s LDAP_P(( LDAP *ld, LDAP_CONST char *dn, LDAPMod **mods, LDAPControl **serverctrls, LDAPControl **clientctrls )); #if LDAP_DEPRECATED LDAP_F( int ) ldap_modify LDAP_P(( /* deprecated, use ldap_modify_ext */ LDAP *ld, LDAP_CONST char *dn, LDAPMod **mods )); LDAP_F( int ) ldap_modify_s LDAP_P(( /* deprecated, use ldap_modify_ext_s */ LDAP *ld, LDAP_CONST char *dn, LDAPMod **mods )); #endif /* * in modrdn.c: */ LDAP_F( int ) ldap_rename LDAP_P(( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *newrdn, LDAP_CONST char *newSuperior, int deleteoldrdn, LDAPControl **sctrls, LDAPControl **cctrls, int *msgidp )); LDAP_F( int ) ldap_rename_s LDAP_P(( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *newrdn, LDAP_CONST char *newSuperior, int deleteoldrdn, LDAPControl **sctrls, LDAPControl **cctrls )); #if LDAP_DEPRECATED LDAP_F( int ) ldap_rename2 LDAP_P(( /* deprecated, use ldap_rename */ LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *newrdn, LDAP_CONST char *newSuperior, int deleteoldrdn )); LDAP_F( int ) ldap_rename2_s LDAP_P(( /* deprecated, use ldap_rename_s */ LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *newrdn, LDAP_CONST char *newSuperior, int deleteoldrdn )); LDAP_F( int ) ldap_modrdn LDAP_P(( /* deprecated, use ldap_rename */ LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *newrdn )); LDAP_F( int ) ldap_modrdn_s LDAP_P(( /* deprecated, use ldap_rename_s */ LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *newrdn )); LDAP_F( int ) ldap_modrdn2 LDAP_P(( /* deprecated, use ldap_rename */ LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *newrdn, int deleteoldrdn )); LDAP_F( int ) ldap_modrdn2_s LDAP_P(( /* deprecated, use ldap_rename_s */ LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *newrdn, int deleteoldrdn)); #endif /* * in open.c: */ #if LDAP_DEPRECATED LDAP_F( LDAP * ) ldap_init LDAP_P(( /* deprecated, use ldap_create or ldap_initialize */ LDAP_CONST char *host, int port )); LDAP_F( LDAP * ) ldap_open LDAP_P(( /* deprecated, use ldap_create or ldap_initialize */ LDAP_CONST char *host, int port )); #endif LDAP_F( int ) ldap_create LDAP_P(( LDAP **ldp )); LDAP_F( int ) ldap_initialize LDAP_P(( LDAP **ldp, LDAP_CONST char *url )); LDAP_F( LDAP * ) ldap_dup LDAP_P(( LDAP *old )); /* * in tls.c */ LDAP_F( int ) ldap_tls_inplace LDAP_P(( LDAP *ld )); LDAP_F( int ) ldap_start_tls LDAP_P(( LDAP *ld, LDAPControl **serverctrls, LDAPControl **clientctrls, int *msgidp )); LDAP_F( int ) ldap_install_tls LDAP_P(( LDAP *ld )); LDAP_F( int ) ldap_start_tls_s LDAP_P(( LDAP *ld, LDAPControl **serverctrls, LDAPControl **clientctrls )); /* * in messages.c: */ LDAP_F( LDAPMessage * ) ldap_first_message LDAP_P(( LDAP *ld, LDAPMessage *chain )); LDAP_F( LDAPMessage * ) ldap_next_message LDAP_P(( LDAP *ld, LDAPMessage *msg )); LDAP_F( int ) ldap_count_messages LDAP_P(( LDAP *ld, LDAPMessage *chain )); /* * in references.c: */ LDAP_F( LDAPMessage * ) ldap_first_reference LDAP_P(( LDAP *ld, LDAPMessage *chain )); LDAP_F( LDAPMessage * ) ldap_next_reference LDAP_P(( LDAP *ld, LDAPMessage *ref )); LDAP_F( int ) ldap_count_references LDAP_P(( LDAP *ld, LDAPMessage *chain )); LDAP_F( int ) ldap_parse_reference LDAP_P(( LDAP *ld, LDAPMessage *ref, char ***referralsp, LDAPControl ***serverctrls, int freeit)); /* * in getentry.c: */ LDAP_F( LDAPMessage * ) ldap_first_entry LDAP_P(( LDAP *ld, LDAPMessage *chain )); LDAP_F( LDAPMessage * ) ldap_next_entry LDAP_P(( LDAP *ld, LDAPMessage *entry )); LDAP_F( int ) ldap_count_entries LDAP_P(( LDAP *ld, LDAPMessage *chain )); LDAP_F( int ) ldap_get_entry_controls LDAP_P(( LDAP *ld, LDAPMessage *entry, LDAPControl ***serverctrls)); /* * in addentry.c */ LDAP_F( LDAPMessage * ) ldap_delete_result_entry LDAP_P(( LDAPMessage **list, LDAPMessage *e )); LDAP_F( void ) ldap_add_result_entry LDAP_P(( LDAPMessage **list, LDAPMessage *e )); /* * in getdn.c */ LDAP_F( char * ) ldap_get_dn LDAP_P(( LDAP *ld, LDAPMessage *entry )); typedef struct ldap_ava { struct berval la_attr; struct berval la_value; unsigned la_flags; #define LDAP_AVA_NULL 0x0000U #define LDAP_AVA_STRING 0x0001U #define LDAP_AVA_BINARY 0x0002U #define LDAP_AVA_NONPRINTABLE 0x0004U #define LDAP_AVA_FREE_ATTR 0x0010U #define LDAP_AVA_FREE_VALUE 0x0020U void *la_private; } LDAPAVA; typedef LDAPAVA** LDAPRDN; typedef LDAPRDN* LDAPDN; /* DN formats */ #define LDAP_DN_FORMAT_LDAP 0x0000U #define LDAP_DN_FORMAT_LDAPV3 0x0010U #define LDAP_DN_FORMAT_LDAPV2 0x0020U #define LDAP_DN_FORMAT_DCE 0x0030U #define LDAP_DN_FORMAT_UFN 0x0040U /* dn2str only */ #define LDAP_DN_FORMAT_AD_CANONICAL 0x0050U /* dn2str only */ #define LDAP_DN_FORMAT_LBER 0x00F0U /* for testing only */ #define LDAP_DN_FORMAT_MASK 0x00F0U /* DN flags */ #define LDAP_DN_PRETTY 0x0100U #define LDAP_DN_SKIP 0x0200U #define LDAP_DN_P_NOLEADTRAILSPACES 0x1000U #define LDAP_DN_P_NOSPACEAFTERRDN 0x2000U #define LDAP_DN_PEDANTIC 0xF000U LDAP_F( void ) ldap_rdnfree LDAP_P(( LDAPRDN rdn )); LDAP_F( void ) ldap_dnfree LDAP_P(( LDAPDN dn )); LDAP_F( int ) ldap_bv2dn LDAP_P(( struct berval *bv, LDAPDN *dn, unsigned flags )); LDAP_F( int ) ldap_str2dn LDAP_P(( LDAP_CONST char *str, LDAPDN *dn, unsigned flags )); LDAP_F( int ) ldap_dn2bv LDAP_P(( LDAPDN dn, struct berval *bv, unsigned flags )); LDAP_F( int ) ldap_dn2str LDAP_P(( LDAPDN dn, char **str, unsigned flags )); LDAP_F( int ) ldap_bv2rdn LDAP_P(( struct berval *bv, LDAPRDN *rdn, char **next, unsigned flags )); LDAP_F( int ) ldap_str2rdn LDAP_P(( LDAP_CONST char *str, LDAPRDN *rdn, char **next, unsigned flags )); LDAP_F( int ) ldap_rdn2bv LDAP_P(( LDAPRDN rdn, struct berval *bv, unsigned flags )); LDAP_F( int ) ldap_rdn2str LDAP_P(( LDAPRDN rdn, char **str, unsigned flags )); LDAP_F( int ) ldap_dn_normalize LDAP_P(( LDAP_CONST char *in, unsigned iflags, char **out, unsigned oflags )); LDAP_F( char * ) ldap_dn2ufn LDAP_P(( /* deprecated, use ldap_str2dn/dn2str */ LDAP_CONST char *dn )); LDAP_F( char ** ) ldap_explode_dn LDAP_P(( /* deprecated, ldap_str2dn */ LDAP_CONST char *dn, int notypes )); LDAP_F( char ** ) ldap_explode_rdn LDAP_P(( /* deprecated, ldap_str2rdn */ LDAP_CONST char *rdn, int notypes )); typedef int LDAPDN_rewrite_func LDAP_P(( LDAPDN dn, unsigned flags, void *ctx )); LDAP_F( int ) ldap_X509dn2bv LDAP_P(( void *x509_name, struct berval *dn, LDAPDN_rewrite_func *func, unsigned flags )); LDAP_F( char * ) ldap_dn2dcedn LDAP_P(( /* deprecated, ldap_str2dn/dn2str */ LDAP_CONST char *dn )); LDAP_F( char * ) ldap_dcedn2dn LDAP_P(( /* deprecated, ldap_str2dn/dn2str */ LDAP_CONST char *dce )); LDAP_F( char * ) ldap_dn2ad_canonical LDAP_P(( /* deprecated, ldap_str2dn/dn2str */ LDAP_CONST char *dn )); LDAP_F( int ) ldap_get_dn_ber LDAP_P(( LDAP *ld, LDAPMessage *e, BerElement **berout, struct berval *dn )); LDAP_F( int ) ldap_get_attribute_ber LDAP_P(( LDAP *ld, LDAPMessage *e, BerElement *ber, struct berval *attr, struct berval **vals )); /* * in getattr.c */ LDAP_F( char * ) ldap_first_attribute LDAP_P(( LDAP *ld, LDAPMessage *entry, BerElement **ber )); LDAP_F( char * ) ldap_next_attribute LDAP_P(( LDAP *ld, LDAPMessage *entry, BerElement *ber )); /* * in getvalues.c */ LDAP_F( struct berval ** ) ldap_get_values_len LDAP_P(( LDAP *ld, LDAPMessage *entry, LDAP_CONST char *target )); LDAP_F( int ) ldap_count_values_len LDAP_P(( struct berval **vals )); LDAP_F( void ) ldap_value_free_len LDAP_P(( struct berval **vals )); #if LDAP_DEPRECATED LDAP_F( char ** ) ldap_get_values LDAP_P(( /* deprecated, use ldap_get_values_len */ LDAP *ld, LDAPMessage *entry, LDAP_CONST char *target )); LDAP_F( int ) ldap_count_values LDAP_P(( /* deprecated, use ldap_count_values_len */ char **vals )); LDAP_F( void ) ldap_value_free LDAP_P(( /* deprecated, use ldap_value_free_len */ char **vals )); #endif /* * in result.c: */ LDAP_F( int ) ldap_result LDAP_P(( LDAP *ld, int msgid, int all, struct timeval *timeout, LDAPMessage **result )); LDAP_F( int ) ldap_msgtype LDAP_P(( LDAPMessage *lm )); LDAP_F( int ) ldap_msgid LDAP_P(( LDAPMessage *lm )); LDAP_F( int ) ldap_msgfree LDAP_P(( LDAPMessage *lm )); LDAP_F( int ) ldap_msgdelete LDAP_P(( LDAP *ld, int msgid )); /* * in search.c: */ LDAP_F( int ) ldap_bv2escaped_filter_value LDAP_P(( struct berval *in, struct berval *out )); LDAP_F( int ) ldap_search_ext LDAP_P(( LDAP *ld, LDAP_CONST char *base, int scope, LDAP_CONST char *filter, char **attrs, int attrsonly, LDAPControl **serverctrls, LDAPControl **clientctrls, struct timeval *timeout, int sizelimit, int *msgidp )); LDAP_F( int ) ldap_search_ext_s LDAP_P(( LDAP *ld, LDAP_CONST char *base, int scope, LDAP_CONST char *filter, char **attrs, int attrsonly, LDAPControl **serverctrls, LDAPControl **clientctrls, struct timeval *timeout, int sizelimit, LDAPMessage **res )); #if LDAP_DEPRECATED LDAP_F( int ) ldap_search LDAP_P(( /* deprecated, use ldap_search_ext */ LDAP *ld, LDAP_CONST char *base, int scope, LDAP_CONST char *filter, char **attrs, int attrsonly )); LDAP_F( int ) ldap_search_s LDAP_P(( /* deprecated, use ldap_search_ext_s */ LDAP *ld, LDAP_CONST char *base, int scope, LDAP_CONST char *filter, char **attrs, int attrsonly, LDAPMessage **res )); LDAP_F( int ) ldap_search_st LDAP_P(( /* deprecated, use ldap_search_ext_s */ LDAP *ld, LDAP_CONST char *base, int scope, LDAP_CONST char *filter, char **attrs, int attrsonly, struct timeval *timeout, LDAPMessage **res )); #endif /* * in unbind.c */ LDAP_F( int ) ldap_unbind_ext LDAP_P(( LDAP *ld, LDAPControl **serverctrls, LDAPControl **clientctrls)); LDAP_F( int ) ldap_unbind_ext_s LDAP_P(( LDAP *ld, LDAPControl **serverctrls, LDAPControl **clientctrls)); LDAP_F( int ) ldap_destroy LDAP_P(( LDAP *ld)); #if LDAP_DEPRECATED LDAP_F( int ) ldap_unbind LDAP_P(( /* deprecated, use ldap_unbind_ext */ LDAP *ld )); LDAP_F( int ) ldap_unbind_s LDAP_P(( /* deprecated, use ldap_unbind_ext_s */ LDAP *ld )); #endif /* * in filter.c */ LDAP_F( int ) ldap_put_vrFilter LDAP_P(( BerElement *ber, const char *vrf )); /* * in free.c */ LDAP_F( void * ) ldap_memalloc LDAP_P(( ber_len_t s )); LDAP_F( void * ) ldap_memrealloc LDAP_P(( void* p, ber_len_t s )); LDAP_F( void * ) ldap_memcalloc LDAP_P(( ber_len_t n, ber_len_t s )); LDAP_F( void ) ldap_memfree LDAP_P(( void* p )); LDAP_F( void ) ldap_memvfree LDAP_P(( void** v )); LDAP_F( char * ) ldap_strdup LDAP_P(( LDAP_CONST char * )); LDAP_F( void ) ldap_mods_free LDAP_P(( LDAPMod **mods, int freemods )); #if LDAP_DEPRECATED /* * in sort.c (deprecated, use custom code instead) */ typedef int (LDAP_SORT_AD_CMP_PROC) LDAP_P(( /* deprecated */ LDAP_CONST char *left, LDAP_CONST char *right )); typedef int (LDAP_SORT_AV_CMP_PROC) LDAP_P(( /* deprecated */ LDAP_CONST void *left, LDAP_CONST void *right )); LDAP_F( int ) /* deprecated */ ldap_sort_entries LDAP_P(( LDAP *ld, LDAPMessage **chain, LDAP_CONST char *attr, LDAP_SORT_AD_CMP_PROC *cmp )); LDAP_F( int ) /* deprecated */ ldap_sort_values LDAP_P(( LDAP *ld, char **vals, LDAP_SORT_AV_CMP_PROC *cmp )); LDAP_F( int ) /* deprecated */ ldap_sort_strcasecmp LDAP_P(( LDAP_CONST void *a, LDAP_CONST void *b )); #endif /* * in url.c */ LDAP_F( int ) ldap_is_ldap_url LDAP_P(( LDAP_CONST char *url )); LDAP_F( int ) ldap_is_ldaps_url LDAP_P(( LDAP_CONST char *url )); LDAP_F( int ) ldap_is_ldapi_url LDAP_P(( LDAP_CONST char *url )); LDAP_F( int ) ldap_url_parse LDAP_P(( LDAP_CONST char *url, LDAPURLDesc **ludpp )); LDAP_F( char * ) ldap_url_desc2str LDAP_P(( LDAPURLDesc *ludp )); LDAP_F( void ) ldap_free_urldesc LDAP_P(( LDAPURLDesc *ludp )); /* * LDAP Cancel Extended Operation * in cancel.c */ #define LDAP_API_FEATURE_CANCEL 1000 LDAP_F( int ) ldap_cancel LDAP_P(( LDAP *ld, int cancelid, LDAPControl **sctrls, LDAPControl **cctrls, int *msgidp )); LDAP_F( int ) ldap_cancel_s LDAP_P(( LDAP *ld, int cancelid, LDAPControl **sctrl, LDAPControl **cctrl )); /* * LDAP Turn Extended Operation * in turn.c */ #define LDAP_API_FEATURE_TURN 1000 LDAP_F( int ) ldap_turn LDAP_P(( LDAP *ld, int mutual, LDAP_CONST char* identifier, LDAPControl **sctrls, LDAPControl **cctrls, int *msgidp )); LDAP_F( int ) ldap_turn_s LDAP_P(( LDAP *ld, int mutual, LDAP_CONST char* identifier, LDAPControl **sctrl, LDAPControl **cctrl )); /* * LDAP Paged Results * in pagectrl.c */ #define LDAP_API_FEATURE_PAGED_RESULTS 2000 LDAP_F( int ) ldap_create_page_control_value LDAP_P(( LDAP *ld, ber_int_t pagesize, struct berval *cookie, struct berval *value )); LDAP_F( int ) ldap_create_page_control LDAP_P(( LDAP *ld, ber_int_t pagesize, struct berval *cookie, int iscritical, LDAPControl **ctrlp )); #if LDAP_DEPRECATED LDAP_F( int ) ldap_parse_page_control LDAP_P(( /* deprecated, use ldap_parse_pageresponse_control */ LDAP *ld, LDAPControl **ctrls, ber_int_t *count, struct berval **cookie )); #endif LDAP_F( int ) ldap_parse_pageresponse_control LDAP_P(( LDAP *ld, LDAPControl *ctrl, ber_int_t *count, struct berval *cookie )); /* * LDAP Server Side Sort * in sortctrl.c */ #define LDAP_API_FEATURE_SERVER_SIDE_SORT 2000 /* structure for a sort-key */ typedef struct ldapsortkey { char *attributeType; char *orderingRule; int reverseOrder; } LDAPSortKey; LDAP_F( int ) ldap_create_sort_keylist LDAP_P(( LDAPSortKey ***sortKeyList, char *keyString )); LDAP_F( void ) ldap_free_sort_keylist LDAP_P(( LDAPSortKey **sortkeylist )); LDAP_F( int ) ldap_create_sort_control_value LDAP_P(( LDAP *ld, LDAPSortKey **keyList, struct berval *value )); LDAP_F( int ) ldap_create_sort_control LDAP_P(( LDAP *ld, LDAPSortKey **keyList, int iscritical, LDAPControl **ctrlp )); LDAP_F( int ) ldap_parse_sortresponse_control LDAP_P(( LDAP *ld, LDAPControl *ctrl, ber_int_t *result, char **attribute )); /* * LDAP Virtual List View * in vlvctrl.c */ #define LDAP_API_FEATURE_VIRTUAL_LIST_VIEW 2000 /* structure for virtual list */ typedef struct ldapvlvinfo { ber_int_t ldvlv_version; ber_int_t ldvlv_before_count; ber_int_t ldvlv_after_count; ber_int_t ldvlv_offset; ber_int_t ldvlv_count; struct berval * ldvlv_attrvalue; struct berval * ldvlv_context; void * ldvlv_extradata; } LDAPVLVInfo; LDAP_F( int ) ldap_create_vlv_control_value LDAP_P(( LDAP *ld, LDAPVLVInfo *ldvlistp, struct berval *value)); LDAP_F( int ) ldap_create_vlv_control LDAP_P(( LDAP *ld, LDAPVLVInfo *ldvlistp, LDAPControl **ctrlp )); LDAP_F( int ) ldap_parse_vlvresponse_control LDAP_P(( LDAP *ld, LDAPControl *ctrls, ber_int_t *target_posp, ber_int_t *list_countp, struct berval **contextp, int *errcodep )); /* * LDAP Who Am I? * in whoami.c */ #define LDAP_API_FEATURE_WHOAMI 1000 LDAP_F( int ) ldap_parse_whoami LDAP_P(( LDAP *ld, LDAPMessage *res, struct berval **authzid )); LDAP_F( int ) ldap_whoami LDAP_P(( LDAP *ld, LDAPControl **sctrls, LDAPControl **cctrls, int *msgidp )); LDAP_F( int ) ldap_whoami_s LDAP_P(( LDAP *ld, struct berval **authzid, LDAPControl **sctrls, LDAPControl **cctrls )); /* * LDAP Password Modify * in passwd.c */ #define LDAP_API_FEATURE_PASSWD_MODIFY 1000 LDAP_F( int ) ldap_parse_passwd LDAP_P(( LDAP *ld, LDAPMessage *res, struct berval *newpasswd )); LDAP_F( int ) ldap_passwd LDAP_P(( LDAP *ld, struct berval *user, struct berval *oldpw, struct berval *newpw, LDAPControl **sctrls, LDAPControl **cctrls, int *msgidp )); LDAP_F( int ) ldap_passwd_s LDAP_P(( LDAP *ld, struct berval *user, struct berval *oldpw, struct berval *newpw, struct berval *newpasswd, LDAPControl **sctrls, LDAPControl **cctrls )); #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST /* * LDAP Password Policy controls * in ppolicy.c */ #define LDAP_API_FEATURE_PASSWORD_POLICY 1000 typedef enum passpolicyerror_enum { PP_passwordExpired = 0, PP_accountLocked = 1, PP_changeAfterReset = 2, PP_passwordModNotAllowed = 3, PP_mustSupplyOldPassword = 4, PP_insufficientPasswordQuality = 5, PP_passwordTooShort = 6, PP_passwordTooYoung = 7, PP_passwordInHistory = 8, PP_noError = 65535 } LDAPPasswordPolicyError; LDAP_F( int ) ldap_create_passwordpolicy_control LDAP_P(( LDAP *ld, LDAPControl **ctrlp )); LDAP_F( int ) ldap_parse_passwordpolicy_control LDAP_P(( LDAP *ld, LDAPControl *ctrl, ber_int_t *expirep, ber_int_t *gracep, LDAPPasswordPolicyError *errorp )); LDAP_F( const char * ) ldap_passwordpolicy_err2txt LDAP_P(( LDAPPasswordPolicyError )); #endif /* LDAP_CONTROL_PASSWORDPOLICYREQUEST */ /* * LDAP Dynamic Directory Services Refresh -- RFC 2589 * in dds.c */ #define LDAP_API_FEATURE_REFRESH 1000 LDAP_F( int ) ldap_parse_refresh LDAP_P(( LDAP *ld, LDAPMessage *res, ber_int_t *newttl )); LDAP_F( int ) ldap_refresh LDAP_P(( LDAP *ld, struct berval *dn, ber_int_t ttl, LDAPControl **sctrls, LDAPControl **cctrls, int *msgidp )); LDAP_F( int ) ldap_refresh_s LDAP_P(( LDAP *ld, struct berval *dn, ber_int_t ttl, ber_int_t *newttl, LDAPControl **sctrls, LDAPControl **cctrls )); /* * LDAP Transactions */ #ifdef LDAP_X_TXN LDAP_F( int ) ldap_txn_start LDAP_P(( LDAP *ld, LDAPControl **sctrls, LDAPControl **cctrls, int *msgidp )); LDAP_F( int ) ldap_txn_start_s LDAP_P(( LDAP *ld, LDAPControl **sctrl, LDAPControl **cctrl, struct berval **rettxnid )); LDAP_F( int ) ldap_txn_end LDAP_P(( LDAP *ld, int commit, struct berval *txnid, LDAPControl **sctrls, LDAPControl **cctrls, int *msgidp )); LDAP_F( int ) ldap_txn_end_s LDAP_P(( LDAP *ld, int commit, struct berval *txnid, LDAPControl **sctrl, LDAPControl **cctrl, int *retidp )); #endif /* * in ldap_sync.c */ /* * initialize the persistent search structure */ LDAP_F( ldap_sync_t * ) ldap_sync_initialize LDAP_P(( ldap_sync_t *ls )); /* * destroy the persistent search structure */ LDAP_F( void ) ldap_sync_destroy LDAP_P(( ldap_sync_t *ls, int freeit )); /* * initialize a refreshOnly sync */ LDAP_F( int ) ldap_sync_init LDAP_P(( ldap_sync_t *ls, int mode )); /* * initialize a refreshOnly sync */ LDAP_F( int ) ldap_sync_init_refresh_only LDAP_P(( ldap_sync_t *ls )); /* * initialize a refreshAndPersist sync */ LDAP_F( int ) ldap_sync_init_refresh_and_persist LDAP_P(( ldap_sync_t *ls )); /* * poll for new responses */ LDAP_F( int ) ldap_sync_poll LDAP_P(( ldap_sync_t *ls )); #ifdef LDAP_CONTROL_X_SESSION_TRACKING /* * in stctrl.c */ LDAP_F( int ) ldap_create_session_tracking_value LDAP_P(( LDAP *ld, char *sessionSourceIp, char *sessionSourceName, char *formatOID, struct berval *sessionTrackingIdentifier, struct berval *value )); LDAP_F( int ) ldap_create_session_tracking_control LDAP_P(( LDAP *ld, char *sessionSourceIp, char *sessionSourceName, char *formatOID, struct berval *sessionTrackingIdentifier, LDAPControl **ctrlp )); LDAP_F( int ) ldap_parse_session_tracking_control LDAP_P(( LDAP *ld, LDAPControl *ctrl, struct berval *ip, struct berval *name, struct berval *oid, struct berval *id )); #endif /* LDAP_CONTROL_X_SESSION_TRACKING */ /* * in assertion.c */ LDAP_F (int) ldap_create_assertion_control_value LDAP_P(( LDAP *ld, char *assertion, struct berval *value )); LDAP_F( int ) ldap_create_assertion_control LDAP_P(( LDAP *ld, char *filter, int iscritical, LDAPControl **ctrlp )); /* * in deref.c */ typedef struct LDAPDerefSpec { char *derefAttr; char **attributes; } LDAPDerefSpec; typedef struct LDAPDerefVal { char *type; BerVarray vals; struct LDAPDerefVal *next; } LDAPDerefVal; typedef struct LDAPDerefRes { char *derefAttr; struct berval derefVal; LDAPDerefVal *attrVals; struct LDAPDerefRes *next; } LDAPDerefRes; LDAP_F( int ) ldap_create_deref_control_value LDAP_P(( LDAP *ld, LDAPDerefSpec *ds, struct berval *value )); LDAP_F( int ) ldap_create_deref_control LDAP_P(( LDAP *ld, LDAPDerefSpec *ds, int iscritical, LDAPControl **ctrlp )); LDAP_F( void ) ldap_derefresponse_free LDAP_P(( LDAPDerefRes *dr )); LDAP_F( int ) ldap_parse_derefresponse_control LDAP_P(( LDAP *ld, LDAPControl *ctrl, LDAPDerefRes **drp )); LDAP_F( int ) ldap_parse_deref_control LDAP_P(( LDAP *ld, LDAPControl **ctrls, LDAPDerefRes **drp )); LDAP_END_DECL #endif /* _LDAP_H */ openldap-2.4.42+dfsg/include/Makefile.in0000644000175000017500000000513012563404150016517 0ustar ryanryan# include Makefile.in for OpenLDAP # $OpenLDAP$ ## This work is part of OpenLDAP Software . ## ## Copyright 1998-2015 The OpenLDAP Foundation. ## All rights reserved. ## ## Redistribution and use in source and binary forms, with or without ## modification, are permitted only as authorized by the OpenLDAP ## Public License. ## ## A copy of this license is available in the file LICENSE in the ## top-level directory of the distribution or, alternatively, at ## . all-local: ldap_config.h FORCE install-local: FORCE -$(MKDIR) $(DESTDIR)$(includedir) for header in $(srcdir)/lber.h lber_types.h \ $(srcdir)/ldap.h $(srcdir)/ldap_cdefs.h \ $(srcdir)/ldap_schema.h $(srcdir)/ldap_utf8.h \ $(srcdir)/slapi-plugin.h ldap_features.h \ $(srcdir)/ldif.h ; \ do \ $(INSTALL) $(INSTALLFLAGS) -m 644 $$header $(DESTDIR)$(includedir); \ done clean-local: FORCE $(RM) ldap_config.h veryclean-local: clean-local FORCE $(RM) portable.h lber_types.h ldap_features.h depend-local: ldap_config.h FORCE LDAP_CONFIG=$(srcdir)/ldap_config.hin ldap_config.h: $(LDAP_CONFIG) Makefile @$(RM) $@ @echo "Making $@" @echo "/* Generated from $(LDAP_CONFIG) on `date` */" > $@; \ if test $(PLAT) = NT; then \ sysconfdir=`cygpath -w $(sysconfdir) | \ $(SED) -e 's/\\\\/\\\\\\\\\\\\\\\\/g'`; \ datadir=`cygpath -w $(datadir) | \ $(SED) -e 's/\\\\/\\\\\\\\\\\\\\\\/g'`; \ bindir=`cygpath -w $(bindir) | \ $(SED) -e 's/\\\\/\\\\\\\\\\\\\\\\/g'`; \ sbindir=`cygpath -w $(sbindir) | \ $(SED) -e 's/\\\\/\\\\\\\\\\\\\\\\/g'`; \ libexecdir=`cygpath -w $(libexecdir) | \ $(SED) -e 's/\\\\/\\\\\\\\\\\\\\\\/g'`; \ moduledir=`cygpath -w $(moduledir) | \ $(SED) -e 's/\\\\/\\\\\\\\\\\\\\\\/g'`; \ localstatedir=`cygpath -w $(localstatedir) | \ $(SED) -e 's/\\\\/\\\\\\\\\\\\\\\\/g'`; \ else \ sysconfdir=$(sysconfdir); \ datadir=$(datadir); \ bindir=$(bindir); \ sbindir=$(sbindir); \ libexecdir=$(libexecdir); \ moduledir=$(moduledir); \ localstatedir=$(localstatedir); \ localedir=$(localedir); \ fi; \ $(SED) \ -e "s;%SYSCONFDIR%;$$sysconfdir;" \ -e "s;%DATADIR%;$$datadir;" \ -e "s;%BINDIR%;$$bindir;" \ -e "s;%SBINDIR%;$$sbindir;" \ -e "s;%LIBEXECDIR%;$$libexecdir;" \ -e "s;%MODULEDIR%;$$moduledir;" \ -e "s;%RUNDIR%;$$localstatedir;" \ -e "s;%LOCALEDIR%;$$localedir;" \ $(LDAP_CONFIG) >> $@; \ $(CHMOD) 444 $@ all-common: all-local install-common: all-common install-local clean-common: clean-local veryclean-common: veryclean-local depend-common: depend-local openldap-2.4.42+dfsg/include/ldap_queue.h0000644000175000017500000004540712563404150016762 0ustar ryanryan/* ldap_queue.h -- queue macros */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 2001-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Copyright (c) 1991, 1993 * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. * * @(#)queue.h 8.5 (Berkeley) 8/20/94 * $FreeBSD: src/sys/sys/queue.h,v 1.32.2.5 2001/09/30 21:12:54 luigi Exp $ * * See also: ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change */ /* ACKNOWLEDGEMENTS: * This work is derived from FreeBSD queue.h work. Adapted for use in * OpenLDAP Software by Kurt D. Zeilenga. */ #ifndef _LDAP_QUEUE_H_ #define _LDAP_QUEUE_H_ /* * This file defines five types of data structures: singly-linked lists, * singly-linked tail queues, lists, tail queues, and circular queues. * * A singly-linked list is headed by a single forward pointer. The elements * are singly linked for minimum space and pointer manipulation overhead at * the expense of O(n) removal for arbitrary elements. New elements can be * added to the list after an existing element or at the head of the list. * Elements being removed from the head of the list should use the explicit * macro for this purpose for optimum efficiency. A singly-linked list may * only be traversed in the forward direction. Singly-linked lists are ideal * for applications with large datasets and few or no removals or for * implementing a LIFO queue. * * A singly-linked tail queue is headed by a pair of pointers, one to the * head of the list and the other to the tail of the list. The elements are * singly linked for minimum space and pointer manipulation overhead at the * expense of O(n) removal for arbitrary elements. New elements can be added * to the list after an existing element, at the head of the list, or at the * end of the list. Elements being removed from the head of the tail queue * should use the explicit macro for this purpose for optimum efficiency. * A singly-linked tail queue may only be traversed in the forward direction. * Singly-linked tail queues are ideal for applications with large datasets * and few or no removals or for implementing a FIFO queue. * * A list is headed by a single forward pointer (or an array of forward * pointers for a hash table header). The elements are doubly linked * so that an arbitrary element can be removed without a need to * traverse the list. New elements can be added to the list before * or after an existing element or at the head of the list. A list * may only be traversed in the forward direction. * * A tail queue is headed by a pair of pointers, one to the head of the * list and the other to the tail of the list. The elements are doubly * linked so that an arbitrary element can be removed without a need to * traverse the list. New elements can be added to the list before or * after an existing element, at the head of the list, or at the end of * the list. A tail queue may be traversed in either direction. * * A circle queue is headed by a pair of pointers, one to the head of the * list and the other to the tail of the list. The elements are doubly * linked so that an arbitrary element can be removed without a need to * traverse the list. New elements can be added to the list before or after * an existing element, at the head of the list, or at the end of the list. * A circle queue may be traversed in either direction, but has a more * complex end of list detection. * * For details on the use of these macros, see the queue(3) manual page. * All macros are prefixed with LDAP_. * * SLIST_ LIST_ STAILQ_ TAILQ_ CIRCLEQ_ * _HEAD + + + + + * _ENTRY + + + + + * _INIT + + + + + * _ENTRY_INIT + + + + + * _EMPTY + + + + + * _FIRST + + + + + * _NEXT + + + + + * _PREV - - - + + * _LAST - - + + + * _FOREACH + + + + + * _FOREACH_REVERSE - - - + + * _INSERT_HEAD + + + + + * _INSERT_BEFORE - + - + + * _INSERT_AFTER + + + + + * _INSERT_TAIL - - + + + * _REMOVE_HEAD + - + - - * _REMOVE + + + + + * */ /* * Singly-linked List definitions. */ #define LDAP_SLIST_HEAD(name, type) \ struct name { \ struct type *slh_first; /* first element */ \ } #define LDAP_SLIST_HEAD_INITIALIZER(head) \ { NULL } #define LDAP_SLIST_ENTRY(type) \ struct { \ struct type *sle_next; /* next element */ \ } #define LDAP_SLIST_ENTRY_INITIALIZER(entry) \ { NULL } /* * Singly-linked List functions. */ #define LDAP_SLIST_EMPTY(head) ((head)->slh_first == NULL) #define LDAP_SLIST_FIRST(head) ((head)->slh_first) #define LDAP_SLIST_FOREACH(var, head, field) \ for((var) = (head)->slh_first; (var); (var) = (var)->field.sle_next) #define LDAP_SLIST_INIT(head) { \ (head)->slh_first = NULL; \ } #define LDAP_SLIST_ENTRY_INIT(var, field) { \ (var)->field.sle_next = NULL; \ } #define LDAP_SLIST_INSERT_AFTER(slistelm, elm, field) do { \ (elm)->field.sle_next = (slistelm)->field.sle_next; \ (slistelm)->field.sle_next = (elm); \ } while (0) #define LDAP_SLIST_INSERT_HEAD(head, elm, field) do { \ (elm)->field.sle_next = (head)->slh_first; \ (head)->slh_first = (elm); \ } while (0) #define LDAP_SLIST_NEXT(elm, field) ((elm)->field.sle_next) #define LDAP_SLIST_REMOVE_HEAD(head, field) do { \ (head)->slh_first = (head)->slh_first->field.sle_next; \ } while (0) #define LDAP_SLIST_REMOVE(head, elm, type, field) do { \ if ((head)->slh_first == (elm)) { \ LDAP_SLIST_REMOVE_HEAD((head), field); \ } \ else { \ struct type *curelm = (head)->slh_first; \ while( curelm->field.sle_next != (elm) ) \ curelm = curelm->field.sle_next; \ curelm->field.sle_next = \ curelm->field.sle_next->field.sle_next; \ } \ } while (0) /* * Singly-linked Tail queue definitions. */ #define LDAP_STAILQ_HEAD(name, type) \ struct name { \ struct type *stqh_first;/* first element */ \ struct type **stqh_last;/* addr of last next element */ \ } #define LDAP_STAILQ_HEAD_INITIALIZER(head) \ { NULL, &(head).stqh_first } #define LDAP_STAILQ_ENTRY(type) \ struct { \ struct type *stqe_next; /* next element */ \ } #define LDAP_STAILQ_ENTRY_INITIALIZER(entry) \ { NULL } /* * Singly-linked Tail queue functions. */ #define LDAP_STAILQ_EMPTY(head) ((head)->stqh_first == NULL) #define LDAP_STAILQ_INIT(head) do { \ (head)->stqh_first = NULL; \ (head)->stqh_last = &(head)->stqh_first; \ } while (0) #define LDAP_STAILQ_ENTRY_INIT(var, field) { \ (entry)->field.stqe_next = NULL; \ } #define LDAP_STAILQ_FIRST(head) ((head)->stqh_first) #define LDAP_STAILQ_LAST(head, type, field) \ (LDAP_STAILQ_EMPTY(head) ? \ NULL : \ ((struct type *) \ ((char *)((head)->stqh_last) - offsetof(struct type, field)))) #define LDAP_STAILQ_FOREACH(var, head, field) \ for((var) = (head)->stqh_first; (var); (var) = (var)->field.stqe_next) #define LDAP_STAILQ_INSERT_HEAD(head, elm, field) do { \ if (((elm)->field.stqe_next = (head)->stqh_first) == NULL) \ (head)->stqh_last = &(elm)->field.stqe_next; \ (head)->stqh_first = (elm); \ } while (0) #define LDAP_STAILQ_INSERT_TAIL(head, elm, field) do { \ (elm)->field.stqe_next = NULL; \ *(head)->stqh_last = (elm); \ (head)->stqh_last = &(elm)->field.stqe_next; \ } while (0) #define LDAP_STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \ if (((elm)->field.stqe_next = (tqelm)->field.stqe_next) == NULL)\ (head)->stqh_last = &(elm)->field.stqe_next; \ (tqelm)->field.stqe_next = (elm); \ } while (0) #define LDAP_STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) #define LDAP_STAILQ_REMOVE_HEAD(head, field) do { \ if (((head)->stqh_first = \ (head)->stqh_first->field.stqe_next) == NULL) \ (head)->stqh_last = &(head)->stqh_first; \ } while (0) #define LDAP_STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do { \ if (((head)->stqh_first = (elm)->field.stqe_next) == NULL) \ (head)->stqh_last = &(head)->stqh_first; \ } while (0) #define LDAP_STAILQ_REMOVE(head, elm, type, field) do { \ if ((head)->stqh_first == (elm)) { \ LDAP_STAILQ_REMOVE_HEAD(head, field); \ } \ else { \ struct type *curelm = (head)->stqh_first; \ while( curelm->field.stqe_next != (elm) ) \ curelm = curelm->field.stqe_next; \ if((curelm->field.stqe_next = \ curelm->field.stqe_next->field.stqe_next) == NULL) \ (head)->stqh_last = &(curelm)->field.stqe_next; \ } \ } while (0) /* * List definitions. */ #define LDAP_LIST_HEAD(name, type) \ struct name { \ struct type *lh_first; /* first element */ \ } #define LDAP_LIST_HEAD_INITIALIZER(head) \ { NULL } #define LDAP_LIST_ENTRY(type) \ struct { \ struct type *le_next; /* next element */ \ struct type **le_prev; /* address of previous next element */ \ } #define LDAP_LIST_ENTRY_INITIALIZER(entry) \ { NULL, NULL } /* * List functions. */ #define LDAP_LIST_EMPTY(head) ((head)->lh_first == NULL) #define LDAP_LIST_FIRST(head) ((head)->lh_first) #define LDAP_LIST_FOREACH(var, head, field) \ for((var) = (head)->lh_first; (var); (var) = (var)->field.le_next) #define LDAP_LIST_INIT(head) do { \ (head)->lh_first = NULL; \ } while (0) #define LDAP_LIST_ENTRY_INIT(var, field) do { \ (var)->field.le_next = NULL; \ (var)->field.le_prev = NULL; \ } while (0) #define LDAP_LIST_INSERT_AFTER(listelm, elm, field) do { \ if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ (listelm)->field.le_next->field.le_prev = \ &(elm)->field.le_next; \ (listelm)->field.le_next = (elm); \ (elm)->field.le_prev = &(listelm)->field.le_next; \ } while (0) #define LDAP_LIST_INSERT_BEFORE(listelm, elm, field) do { \ (elm)->field.le_prev = (listelm)->field.le_prev; \ (elm)->field.le_next = (listelm); \ *(listelm)->field.le_prev = (elm); \ (listelm)->field.le_prev = &(elm)->field.le_next; \ } while (0) #define LDAP_LIST_INSERT_HEAD(head, elm, field) do { \ if (((elm)->field.le_next = (head)->lh_first) != NULL) \ (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ (head)->lh_first = (elm); \ (elm)->field.le_prev = &(head)->lh_first; \ } while (0) #define LDAP_LIST_NEXT(elm, field) ((elm)->field.le_next) #define LDAP_LIST_REMOVE(elm, field) do { \ if ((elm)->field.le_next != NULL) \ (elm)->field.le_next->field.le_prev = \ (elm)->field.le_prev; \ *(elm)->field.le_prev = (elm)->field.le_next; \ } while (0) /* * Tail queue definitions. */ #define LDAP_TAILQ_HEAD(name, type) \ struct name { \ struct type *tqh_first; /* first element */ \ struct type **tqh_last; /* addr of last next element */ \ } #define LDAP_TAILQ_HEAD_INITIALIZER(head) \ { NULL, &(head).tqh_first } #define LDAP_TAILQ_ENTRY(type) \ struct { \ struct type *tqe_next; /* next element */ \ struct type **tqe_prev; /* address of previous next element */ \ } #define LDAP_TAILQ_ENTRY_INITIALIZER(entry) \ { NULL, NULL } /* * Tail queue functions. */ #define LDAP_TAILQ_EMPTY(head) ((head)->tqh_first == NULL) #define LDAP_TAILQ_FOREACH(var, head, field) \ for (var = LDAP_TAILQ_FIRST(head); var; var = LDAP_TAILQ_NEXT(var, field)) #define LDAP_TAILQ_FOREACH_REVERSE(var, head, type, field) \ for ((var) = LDAP_TAILQ_LAST((head), type, field); \ (var); \ (var) = LDAP_TAILQ_PREV((var), head, type, field)) #define LDAP_TAILQ_FIRST(head) ((head)->tqh_first) #define LDAP_TAILQ_LAST(head, type, field) \ (LDAP_TAILQ_EMPTY(head) ? \ NULL : \ ((struct type *) \ ((char *)((head)->tqh_last) - offsetof(struct type, field)))) #define LDAP_TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) #define LDAP_TAILQ_PREV(elm, head, type, field) \ ((struct type *)((elm)->field.tqe_prev) == LDAP_TAILQ_FIRST(head) ? \ NULL : \ ((struct type *) \ ((char *)((elm)->field.tqe_prev) - offsetof(struct type, field)))) #define LDAP_TAILQ_INIT(head) do { \ (head)->tqh_first = NULL; \ (head)->tqh_last = &(head)->tqh_first; \ } while (0) #define LDAP_TAILQ_ENTRY_INIT(var, field) do { \ (var)->field.tqe_next = NULL; \ (var)->field.tqe_prev = NULL; \ } while (0) #define LDAP_TAILQ_INSERT_HEAD(head, elm, field) do { \ if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ (head)->tqh_first->field.tqe_prev = \ &(elm)->field.tqe_next; \ else \ (head)->tqh_last = &(elm)->field.tqe_next; \ (head)->tqh_first = (elm); \ (elm)->field.tqe_prev = &(head)->tqh_first; \ } while (0) #define LDAP_TAILQ_INSERT_TAIL(head, elm, field) do { \ (elm)->field.tqe_next = NULL; \ (elm)->field.tqe_prev = (head)->tqh_last; \ *(head)->tqh_last = (elm); \ (head)->tqh_last = &(elm)->field.tqe_next; \ } while (0) #define LDAP_TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ (elm)->field.tqe_next->field.tqe_prev = \ &(elm)->field.tqe_next; \ else \ (head)->tqh_last = &(elm)->field.tqe_next; \ (listelm)->field.tqe_next = (elm); \ (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ } while (0) #define LDAP_TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ (elm)->field.tqe_next = (listelm); \ *(listelm)->field.tqe_prev = (elm); \ (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ } while (0) #define LDAP_TAILQ_REMOVE(head, elm, field) do { \ if (((elm)->field.tqe_next) != NULL) \ (elm)->field.tqe_next->field.tqe_prev = \ (elm)->field.tqe_prev; \ else \ (head)->tqh_last = (elm)->field.tqe_prev; \ *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ } while (0) /* * Circular queue definitions. */ #define LDAP_CIRCLEQ_HEAD(name, type) \ struct name { \ struct type *cqh_first; /* first element */ \ struct type *cqh_last; /* last element */ \ } #define LDAP_CIRCLEQ_ENTRY(type) \ struct { \ struct type *cqe_next; /* next element */ \ struct type *cqe_prev; /* previous element */ \ } /* * Circular queue functions. */ #define LDAP_CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head)) #define LDAP_CIRCLEQ_FIRST(head) ((head)->cqh_first) #define LDAP_CIRCLEQ_FOREACH(var, head, field) \ for((var) = (head)->cqh_first; \ (var) != (void *)(head); \ (var) = (var)->field.cqe_next) #define LDAP_CIRCLEQ_FOREACH_REVERSE(var, head, field) \ for((var) = (head)->cqh_last; \ (var) != (void *)(head); \ (var) = (var)->field.cqe_prev) #define LDAP_CIRCLEQ_INIT(head) do { \ (head)->cqh_first = (void *)(head); \ (head)->cqh_last = (void *)(head); \ } while (0) #define LDAP_CIRCLEQ_ENTRY_INIT(var, field) do { \ (var)->field.cqe_next = NULL; \ (var)->field.cqe_prev = NULL; \ } while (0) #define LDAP_CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ (elm)->field.cqe_next = (listelm)->field.cqe_next; \ (elm)->field.cqe_prev = (listelm); \ if ((listelm)->field.cqe_next == (void *)(head)) \ (head)->cqh_last = (elm); \ else \ (listelm)->field.cqe_next->field.cqe_prev = (elm); \ (listelm)->field.cqe_next = (elm); \ } while (0) #define LDAP_CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ (elm)->field.cqe_next = (listelm); \ (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \ if ((listelm)->field.cqe_prev == (void *)(head)) \ (head)->cqh_first = (elm); \ else \ (listelm)->field.cqe_prev->field.cqe_next = (elm); \ (listelm)->field.cqe_prev = (elm); \ } while (0) #define LDAP_CIRCLEQ_INSERT_HEAD(head, elm, field) do { \ (elm)->field.cqe_next = (head)->cqh_first; \ (elm)->field.cqe_prev = (void *)(head); \ if ((head)->cqh_last == (void *)(head)) \ (head)->cqh_last = (elm); \ else \ (head)->cqh_first->field.cqe_prev = (elm); \ (head)->cqh_first = (elm); \ } while (0) #define LDAP_CIRCLEQ_INSERT_TAIL(head, elm, field) do { \ (elm)->field.cqe_next = (void *)(head); \ (elm)->field.cqe_prev = (head)->cqh_last; \ if ((head)->cqh_first == (void *)(head)) \ (head)->cqh_first = (elm); \ else \ (head)->cqh_last->field.cqe_next = (elm); \ (head)->cqh_last = (elm); \ } while (0) #define LDAP_CIRCLEQ_LAST(head) ((head)->cqh_last) #define LDAP_CIRCLEQ_NEXT(elm,field) ((elm)->field.cqe_next) #define LDAP_CIRCLEQ_PREV(elm,field) ((elm)->field.cqe_prev) #define LDAP_CIRCLEQ_REMOVE(head, elm, field) do { \ if ((elm)->field.cqe_next == (void *)(head)) \ (head)->cqh_last = (elm)->field.cqe_prev; \ else \ (elm)->field.cqe_next->field.cqe_prev = \ (elm)->field.cqe_prev; \ if ((elm)->field.cqe_prev == (void *)(head)) \ (head)->cqh_first = (elm)->field.cqe_next; \ else \ (elm)->field.cqe_prev->field.cqe_next = \ (elm)->field.cqe_next; \ } while (0) #endif /* !_LDAP_QUEUE_H_ */ openldap-2.4.42+dfsg/include/lutil_lockf.h0000644000175000017500000000145512563404150017140 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* File locking methods * * lutil_lockf() will block until an exclusive lock is acquired. */ #ifndef _LUTIL_LOCKF_H_ #define _LUTIL_LOCKF_H_ LDAP_BEGIN_DECL LDAP_LUTIL_F( int ) lutil_lockf LDAP_P(( int fd )); LDAP_LUTIL_F( int ) lutil_unlockf LDAP_P(( int fd )); LDAP_END_DECL #endif /* _LUTIL_LOCKF_H_ */ openldap-2.4.42+dfsg/include/portable.hin0000644000175000017500000007056112563404150016774 0ustar ryanryan/* include/portable.hin. Generated from configure.in by autoheader. */ /* begin of portable.h.pre */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #ifndef _LDAP_PORTABLE_H #define _LDAP_PORTABLE_H /* define this if needed to get reentrant functions */ #ifndef REENTRANT #undef REENTRANT #endif #ifndef _REENTRANT #undef _REENTRANT #endif /* define this if needed to get threadsafe functions */ #ifndef THREADSAFE #undef THREADSAFE #endif #ifndef _THREADSAFE #undef _THREADSAFE #endif #ifndef THREAD_SAFE #undef THREAD_SAFE #endif #ifndef _THREAD_SAFE #undef _THREAD_SAFE #endif #ifndef _SGI_MP_SOURCE #undef _SGI_MP_SOURCE #endif /* end of portable.h.pre */ /* define to use both and */ #undef BOTH_STRINGS_H /* define if cross compiling */ #undef CROSS_COMPILING /* set to the number of arguments ctime_r() expects */ #undef CTIME_R_NARGS /* define if toupper() requires islower() */ #undef C_UPPER_LOWER /* define if sys_errlist is not declared in stdio.h or errno.h */ #undef DECL_SYS_ERRLIST /* define to enable rewriting in back-ldap and back-meta */ #undef ENABLE_REWRITE /* define to enable slapi library */ #undef ENABLE_SLAPI /* defined to be the EXE extension */ #undef EXEEXT /* set to the number of arguments gethostbyaddr_r() expects */ #undef GETHOSTBYADDR_R_NARGS /* set to the number of arguments gethostbyname_r() expects */ #undef GETHOSTBYNAME_R_NARGS /* Define to 1 if `TIOCGWINSZ' requires . */ #undef GWINSZ_IN_SYS_IOCTL /* define if you have AIX security lib */ #undef HAVE_AIX_SECURITY /* Define to 1 if you have the header file. */ #undef HAVE_ARPA_INET_H /* Define to 1 if you have the header file. */ #undef HAVE_ARPA_NAMESER_H /* Define to 1 if you have the header file. */ #undef HAVE_ASSERT_H /* Define to 1 if you have the `bcopy' function. */ #undef HAVE_BCOPY /* define this if Berkeley DB is available */ #undef HAVE_BERKELEY_DB /* define if Berkeley DB has DB_THREAD support */ #undef HAVE_BERKELEY_DB_THREAD /* Define to 1 if you have the header file. */ #undef HAVE_BITS_TYPES_H /* Define to 1 if you have the `chroot' function. */ #undef HAVE_CHROOT /* Define to 1 if you have the `closesocket' function. */ #undef HAVE_CLOSESOCKET /* Define to 1 if you have the header file. */ #undef HAVE_CONIO_H /* define if crypt(3) is available */ #undef HAVE_CRYPT /* Define to 1 if you have the header file. */ #undef HAVE_CRYPT_H /* Define to 1 if you have the header file. */ #undef HAVE_CTHREADS_H /* Define to 1 if you have the `ctime_r' function. */ #undef HAVE_CTIME_R /* define if you have Cyrus SASL */ #undef HAVE_CYRUS_SASL /* Define to 1 if you have the header file. */ #undef HAVE_DB_H /* define if your system supports /dev/poll */ #undef HAVE_DEVPOLL /* Define to 1 if you have the header file. */ #undef HAVE_DIRECT_H /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_DIRENT_H /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H /* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ #undef HAVE_DOPRNT /* define if system uses EBCDIC instead of ASCII */ #undef HAVE_EBCDIC /* Define to 1 if you have the `endgrent' function. */ #undef HAVE_ENDGRENT /* Define to 1 if you have the `endpwent' function. */ #undef HAVE_ENDPWENT /* define if your system supports epoll */ #undef HAVE_EPOLL /* Define to 1 if you have the header file. */ #undef HAVE_ERRNO_H /* Define to 1 if you have the `fcntl' function. */ #undef HAVE_FCNTL /* Define to 1 if you have the header file. */ #undef HAVE_FCNTL_H /* define if you actually have FreeBSD fetch(3) */ #undef HAVE_FETCH /* Define to 1 if you have the header file. */ #undef HAVE_FILIO_H /* Define to 1 if you have the `flock' function. */ #undef HAVE_FLOCK /* Define to 1 if you have the `fstat' function. */ #undef HAVE_FSTAT /* Define to 1 if you have the `gai_strerror' function. */ #undef HAVE_GAI_STRERROR /* Define to 1 if you have the `getaddrinfo' function. */ #undef HAVE_GETADDRINFO /* Define to 1 if you have the `getdtablesize' function. */ #undef HAVE_GETDTABLESIZE /* Define to 1 if you have the `geteuid' function. */ #undef HAVE_GETEUID /* Define to 1 if you have the `getgrgid' function. */ #undef HAVE_GETGRGID /* Define to 1 if you have the `gethostbyaddr_r' function. */ #undef HAVE_GETHOSTBYADDR_R /* Define to 1 if you have the `gethostbyname_r' function. */ #undef HAVE_GETHOSTBYNAME_R /* Define to 1 if you have the `gethostname' function. */ #undef HAVE_GETHOSTNAME /* Define to 1 if you have the `getnameinfo' function. */ #undef HAVE_GETNAMEINFO /* Define to 1 if you have the `getopt' function. */ #undef HAVE_GETOPT /* Define to 1 if you have the header file. */ #undef HAVE_GETOPT_H /* Define to 1 if you have the `getpassphrase' function. */ #undef HAVE_GETPASSPHRASE /* Define to 1 if you have the `getpeereid' function. */ #undef HAVE_GETPEEREID /* Define to 1 if you have the `getpeerucred' function. */ #undef HAVE_GETPEERUCRED /* Define to 1 if you have the `getpwnam' function. */ #undef HAVE_GETPWNAM /* Define to 1 if you have the `getpwuid' function. */ #undef HAVE_GETPWUID /* Define to 1 if you have the `getspnam' function. */ #undef HAVE_GETSPNAM /* Define to 1 if you have the `gettimeofday' function. */ #undef HAVE_GETTIMEOFDAY /* Define to 1 if you have the header file. */ #undef HAVE_GMP_H /* Define to 1 if you have the `gmtime_r' function. */ #undef HAVE_GMTIME_R /* define if you have GNUtls */ #undef HAVE_GNUTLS /* Define to 1 if you have the header file. */ #undef HAVE_GNUTLS_GNUTLS_H /* if you have GNU Pth */ #undef HAVE_GNU_PTH /* Define to 1 if you have the header file. */ #undef HAVE_GRP_H /* Define to 1 if you have the `hstrerror' function. */ #undef HAVE_HSTRERROR /* define if you actually have ICU */ #undef HAVE_ICU /* define to you inet_aton(3) is available */ #undef HAVE_INET_ATON /* Define to 1 if you have the `inet_ntoa_b' function. */ #undef HAVE_INET_NTOA_B /* Define to 1 if you have the `inet_ntop' function. */ #undef HAVE_INET_NTOP /* Define to 1 if you have the `initgroups' function. */ #undef HAVE_INITGROUPS /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the `ioctl' function. */ #undef HAVE_IOCTL /* Define to 1 if you have the header file. */ #undef HAVE_IO_H /* Define to 1 if you have the `gen' library (-lgen). */ #undef HAVE_LIBGEN /* Define to 1 if you have the `gmp' library (-lgmp). */ #undef HAVE_LIBGMP /* Define to 1 if you have the `inet' library (-linet). */ #undef HAVE_LIBINET /* define if you have libtool -ltdl */ #undef HAVE_LIBLTDL /* Define to 1 if you have the `net' library (-lnet). */ #undef HAVE_LIBNET /* Define to 1 if you have the `nsl' library (-lnsl). */ #undef HAVE_LIBNSL /* Define to 1 if you have the `nsl_s' library (-lnsl_s). */ #undef HAVE_LIBNSL_S /* Define to 1 if you have the `socket' library (-lsocket). */ #undef HAVE_LIBSOCKET /* Define to 1 if you have the header file. */ #undef HAVE_LIBUTIL_H /* Define to 1 if you have the `V3' library (-lV3). */ #undef HAVE_LIBV3 /* Define to 1 if you have the header file. */ #undef HAVE_LIMITS_H /* if you have LinuxThreads */ #undef HAVE_LINUX_THREADS /* Define to 1 if you have the header file. */ #undef HAVE_LOCALE_H /* Define to 1 if you have the `localtime_r' function. */ #undef HAVE_LOCALTIME_R /* Define to 1 if you have the `lockf' function. */ #undef HAVE_LOCKF /* Define to 1 if the system has the type `long long'. */ #undef HAVE_LONG_LONG /* Define to 1 if you have the header file. */ #undef HAVE_LTDL_H /* define if you have Mach Cthreads */ #undef HAVE_MACH_CTHREADS /* Define to 1 if you have the header file. */ #undef HAVE_MACH_CTHREADS_H /* Define to 1 if you have the header file. */ #undef HAVE_MALLOC_H /* Define to 1 if you have the `memcpy' function. */ #undef HAVE_MEMCPY /* Define to 1 if you have the `memmove' function. */ #undef HAVE_MEMMOVE /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the `memrchr' function. */ #undef HAVE_MEMRCHR /* Define to 1 if you have the `mkstemp' function. */ #undef HAVE_MKSTEMP /* Define to 1 if you have the `mktemp' function. */ #undef HAVE_MKTEMP /* define this if you have mkversion */ #undef HAVE_MKVERSION /* define if you have MozNSS */ #undef HAVE_MOZNSS /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_NDIR_H /* Define to 1 if you have the header file. */ #undef HAVE_NETINET_TCP_H /* define if strerror_r returns char* instead of int */ #undef HAVE_NONPOSIX_STRERROR_R /* Define to 1 if you have the header file. */ #undef HAVE_NSSUTIL_H /* if you have NT Event Log */ #undef HAVE_NT_EVENT_LOG /* if you have NT Service Manager */ #undef HAVE_NT_SERVICE_MANAGER /* if you have NT Threads */ #undef HAVE_NT_THREADS /* define if you have OpenSSL */ #undef HAVE_OPENSSL /* Define to 1 if you have the header file. */ #undef HAVE_OPENSSL_BN_H /* define if you have OpenSSL with CRL checking capability */ #undef HAVE_OPENSSL_CRL /* Define to 1 if you have the header file. */ #undef HAVE_OPENSSL_CRYPTO_H /* Define to 1 if you have the header file. */ #undef HAVE_OPENSSL_SSL_H /* Define to 1 if you have the `pipe' function. */ #undef HAVE_PIPE /* Define to 1 if you have the `poll' function. */ #undef HAVE_POLL /* Define to 1 if you have the header file. */ #undef HAVE_POLL_H /* Define to 1 if you have the header file. */ #undef HAVE_PROCESS_H /* Define to 1 if you have the header file. */ #undef HAVE_PSAP_H /* define to pthreads API spec revision */ #undef HAVE_PTHREADS /* define if you have pthread_detach function */ #undef HAVE_PTHREAD_DETACH /* Define to 1 if you have the `pthread_getconcurrency' function. */ #undef HAVE_PTHREAD_GETCONCURRENCY /* Define to 1 if you have the header file. */ #undef HAVE_PTHREAD_H /* Define to 1 if you have the `pthread_kill' function. */ #undef HAVE_PTHREAD_KILL /* Define to 1 if you have the `pthread_kill_other_threads_np' function. */ #undef HAVE_PTHREAD_KILL_OTHER_THREADS_NP /* define if you have pthread_rwlock_destroy function */ #undef HAVE_PTHREAD_RWLOCK_DESTROY /* Define to 1 if you have the `pthread_setconcurrency' function. */ #undef HAVE_PTHREAD_SETCONCURRENCY /* Define to 1 if you have the `pthread_yield' function. */ #undef HAVE_PTHREAD_YIELD /* Define to 1 if you have the header file. */ #undef HAVE_PTH_H /* Define to 1 if the system has the type `ptrdiff_t'. */ #undef HAVE_PTRDIFF_T /* Define to 1 if you have the header file. */ #undef HAVE_PWD_H /* Define to 1 if you have the `read' function. */ #undef HAVE_READ /* Define to 1 if you have the `recv' function. */ #undef HAVE_RECV /* Define to 1 if you have the `recvfrom' function. */ #undef HAVE_RECVFROM /* Define to 1 if you have the header file. */ #undef HAVE_REGEX_H /* Define to 1 if you have the header file. */ #undef HAVE_RESOLV_H /* define if you have res_query() */ #undef HAVE_RES_QUERY /* define if OpenSSL needs RSAref */ #undef HAVE_RSAREF /* Define to 1 if you have the header file. */ #undef HAVE_SASL_H /* Define to 1 if you have the header file. */ #undef HAVE_SASL_SASL_H /* define if your SASL library has sasl_version() */ #undef HAVE_SASL_VERSION /* Define to 1 if you have the header file. */ #undef HAVE_SCHED_H /* Define to 1 if you have the `sched_yield' function. */ #undef HAVE_SCHED_YIELD /* Define to 1 if you have the `send' function. */ #undef HAVE_SEND /* Define to 1 if you have the `sendmsg' function. */ #undef HAVE_SENDMSG /* Define to 1 if you have the `sendto' function. */ #undef HAVE_SENDTO /* Define to 1 if you have the `setegid' function. */ #undef HAVE_SETEGID /* Define to 1 if you have the `seteuid' function. */ #undef HAVE_SETEUID /* Define to 1 if you have the `setgid' function. */ #undef HAVE_SETGID /* define if setproctitle(3) is available */ #undef HAVE_SETPROCTITLE /* Define to 1 if you have the `setpwfile' function. */ #undef HAVE_SETPWFILE /* Define to 1 if you have the `setsid' function. */ #undef HAVE_SETSID /* Define to 1 if you have the `setuid' function. */ #undef HAVE_SETUID /* Define to 1 if you have the header file. */ #undef HAVE_SGTTY_H /* Define to 1 if you have the header file. */ #undef HAVE_SHADOW_H /* Define to 1 if you have the `sigaction' function. */ #undef HAVE_SIGACTION /* Define to 1 if you have the `signal' function. */ #undef HAVE_SIGNAL /* Define to 1 if you have the `sigset' function. */ #undef HAVE_SIGSET /* define if you have -lslp */ #undef HAVE_SLP /* Define to 1 if you have the header file. */ #undef HAVE_SLP_H /* Define to 1 if you have the `snprintf' function. */ #undef HAVE_SNPRINTF /* if you have spawnlp() */ #undef HAVE_SPAWNLP /* Define to 1 if you have the header file. */ #undef HAVE_SQLEXT_H /* Define to 1 if you have the header file. */ #undef HAVE_SQL_H /* Define to 1 if you have the header file. */ #undef HAVE_STDDEF_H /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the `strdup' function. */ #undef HAVE_STRDUP /* Define to 1 if you have the `strerror' function. */ #undef HAVE_STRERROR /* Define to 1 if you have the `strerror_r' function. */ #undef HAVE_STRERROR_R /* Define to 1 if you have the `strftime' function. */ #undef HAVE_STRFTIME /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the `strpbrk' function. */ #undef HAVE_STRPBRK /* Define to 1 if you have the `strrchr' function. */ #undef HAVE_STRRCHR /* Define to 1 if you have the `strsep' function. */ #undef HAVE_STRSEP /* Define to 1 if you have the `strspn' function. */ #undef HAVE_STRSPN /* Define to 1 if you have the `strstr' function. */ #undef HAVE_STRSTR /* Define to 1 if you have the `strtol' function. */ #undef HAVE_STRTOL /* Define to 1 if you have the `strtoll' function. */ #undef HAVE_STRTOLL /* Define to 1 if you have the `strtoq' function. */ #undef HAVE_STRTOQ /* Define to 1 if you have the `strtoul' function. */ #undef HAVE_STRTOUL /* Define to 1 if you have the `strtoull' function. */ #undef HAVE_STRTOULL /* Define to 1 if you have the `strtouq' function. */ #undef HAVE_STRTOUQ /* Define to 1 if `msg_accrightslen' is member of `struct msghdr'. */ #undef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTSLEN /* Define to 1 if `msg_control' is member of `struct msghdr'. */ #undef HAVE_STRUCT_MSGHDR_MSG_CONTROL /* Define to 1 if `pw_gecos' is member of `struct passwd'. */ #undef HAVE_STRUCT_PASSWD_PW_GECOS /* Define to 1 if `pw_passwd' is member of `struct passwd'. */ #undef HAVE_STRUCT_PASSWD_PW_PASSWD /* Define to 1 if `st_blksize' is member of `struct stat'. */ #undef HAVE_STRUCT_STAT_ST_BLKSIZE /* Define to 1 if `st_fstype' is member of `struct stat'. */ #undef HAVE_STRUCT_STAT_ST_FSTYPE /* define to 1 if st_fstype is char * */ #undef HAVE_STRUCT_STAT_ST_FSTYPE_CHAR /* define to 1 if st_fstype is int */ #undef HAVE_STRUCT_STAT_ST_FSTYPE_INT /* Define to 1 if `st_vfstype' is member of `struct stat'. */ #undef HAVE_STRUCT_STAT_ST_VFSTYPE /* Define to 1 if you have the header file. */ #undef HAVE_SYNCH_H /* Define to 1 if you have the `sysconf' function. */ #undef HAVE_SYSCONF /* Define to 1 if you have the header file. */ #undef HAVE_SYSEXITS_H /* Define to 1 if you have the header file. */ #undef HAVE_SYSLOG_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_DEVPOLL_H /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_SYS_DIR_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_EPOLL_H /* define if you actually have sys_errlist in your libs */ #undef HAVE_SYS_ERRLIST /* Define to 1 if you have the header file. */ #undef HAVE_SYS_ERRNO_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_FILE_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_FILIO_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_FSTYP_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_IOCTL_H /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_SYS_NDIR_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_PARAM_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_POLL_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_PRIVGRP_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_RESOURCE_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SELECT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SOCKET_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SYSLOG_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TIME_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_UCRED_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_UIO_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_UN_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_UUID_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_VMOUNT_H /* Define to 1 if you have that is POSIX.1 compatible. */ #undef HAVE_SYS_WAIT_H /* define if you have -lwrap */ #undef HAVE_TCPD /* Define to 1 if you have the header file. */ #undef HAVE_TCPD_H /* Define to 1 if you have the header file. */ #undef HAVE_TERMIOS_H /* if you have Solaris LWP (thr) package */ #undef HAVE_THR /* Define to 1 if you have the header file. */ #undef HAVE_THREAD_H /* Define to 1 if you have the `thr_getconcurrency' function. */ #undef HAVE_THR_GETCONCURRENCY /* Define to 1 if you have the `thr_setconcurrency' function. */ #undef HAVE_THR_SETCONCURRENCY /* Define to 1 if you have the `thr_yield' function. */ #undef HAVE_THR_YIELD /* define if you have TLS */ #undef HAVE_TLS /* Define to 1 if you have the header file. */ #undef HAVE_UNICODE_UTYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define to 1 if you have the header file. */ #undef HAVE_UTIME_H /* define if you have uuid_generate() */ #undef HAVE_UUID_GENERATE /* define if you have uuid_to_str() */ #undef HAVE_UUID_TO_STR /* Define to 1 if you have the header file. */ #undef HAVE_UUID_UUID_H /* Define to 1 if you have the `vprintf' function. */ #undef HAVE_VPRINTF /* Define to 1 if you have the `vsnprintf' function. */ #undef HAVE_VSNPRINTF /* Define to 1 if you have the `wait4' function. */ #undef HAVE_WAIT4 /* Define to 1 if you have the `waitpid' function. */ #undef HAVE_WAITPID /* define if you have winsock */ #undef HAVE_WINSOCK /* define if you have winsock2 */ #undef HAVE_WINSOCK2 /* Define to 1 if you have the header file. */ #undef HAVE_WINSOCK2_H /* Define to 1 if you have the header file. */ #undef HAVE_WINSOCK_H /* Define to 1 if you have the `write' function. */ #undef HAVE_WRITE /* define if select implicitly yields */ #undef HAVE_YIELDING_SELECT /* Define to 1 if you have the `_vsnprintf' function. */ #undef HAVE__VSNPRINTF /* define to 32-bit or greater integer type */ #undef LBER_INT_T /* define to large integer type */ #undef LBER_LEN_T /* define to socket descriptor type */ #undef LBER_SOCKET_T /* define to large integer type */ #undef LBER_TAG_T /* define to 1 if library is thread safe */ #undef LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE /* define to LDAP VENDOR VERSION */ #undef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS /* define this to add debugging code */ #undef LDAP_DEBUG /* define if LDAP libs are dynamic */ #undef LDAP_LIBS_DYNAMIC /* define to support PF_INET6 */ #undef LDAP_PF_INET6 /* define to support PF_LOCAL */ #undef LDAP_PF_LOCAL /* define this for LDAP process title support */ #undef LDAP_PROCTITLE /* define this to add SLAPI code */ #undef LDAP_SLAPI /* define this to add syslog code */ #undef LDAP_SYSLOG /* Version */ #undef LDAP_VENDOR_VERSION /* Major */ #undef LDAP_VENDOR_VERSION_MAJOR /* Minor */ #undef LDAP_VENDOR_VERSION_MINOR /* Patch */ #undef LDAP_VENDOR_VERSION_PATCH /* define if memcmp is not 8-bit clean or is otherwise broken */ #undef NEED_MEMCMP_REPLACEMENT /* define if you have (or want) no threads */ #undef NO_THREADS /* define to use the original debug style */ #undef OLD_DEBUG /* Package */ #undef OPENLDAP_PACKAGE /* Version */ #undef OPENLDAP_VERSION /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the version of this package. */ #undef PACKAGE_VERSION /* define if sched_yield yields the entire process */ #undef REPLACE_BROKEN_YIELD /* Define as the return type of signal handlers (`int' or `void'). */ #undef RETSIGTYPE /* Define to the type of arg 1 for `select'. */ #undef SELECT_TYPE_ARG1 /* Define to the type of args 2, 3 and 4 for `select'. */ #undef SELECT_TYPE_ARG234 /* Define to the type of arg 5 for `select'. */ #undef SELECT_TYPE_ARG5 /* The size of `int', as computed by sizeof. */ #undef SIZEOF_INT /* The size of `long', as computed by sizeof. */ #undef SIZEOF_LONG /* The size of `long long', as computed by sizeof. */ #undef SIZEOF_LONG_LONG /* The size of `short', as computed by sizeof. */ #undef SIZEOF_SHORT /* The size of `wchar_t', as computed by sizeof. */ #undef SIZEOF_WCHAR_T /* define to support per-object ACIs */ #undef SLAPD_ACI_ENABLED /* define to support BDB backend */ #undef SLAPD_BDB /* define to support cleartext passwords */ #undef SLAPD_CLEARTEXT /* define to support crypt(3) passwords */ #undef SLAPD_CRYPT /* define to support DNS SRV backend */ #undef SLAPD_DNSSRV /* define to support HDB backend */ #undef SLAPD_HDB /* define to support LDAP backend */ #undef SLAPD_LDAP /* define to support LAN Manager passwords */ #undef SLAPD_LMHASH /* define to support MDB backend */ #undef SLAPD_MDB /* define to support LDAP Metadirectory backend */ #undef SLAPD_META /* define to support modules */ #undef SLAPD_MODULES /* dynamically linked module */ #undef SLAPD_MOD_DYNAMIC /* statically linked module */ #undef SLAPD_MOD_STATIC /* define to support cn=Monitor backend */ #undef SLAPD_MONITOR /* define to support NDB backend */ #undef SLAPD_NDB /* define to support NULL backend */ #undef SLAPD_NULL /* define for In-Directory Access Logging overlay */ #undef SLAPD_OVER_ACCESSLOG /* define for Audit Logging overlay */ #undef SLAPD_OVER_AUDITLOG /* define for Collect overlay */ #undef SLAPD_OVER_COLLECT /* define for Attribute Constraint overlay */ #undef SLAPD_OVER_CONSTRAINT /* define for Dynamic Directory Services overlay */ #undef SLAPD_OVER_DDS /* define for Dynamic Directory Services overlay */ #undef SLAPD_OVER_DEREF /* define for Dynamic Group overlay */ #undef SLAPD_OVER_DYNGROUP /* define for Dynamic List overlay */ #undef SLAPD_OVER_DYNLIST /* define for Reverse Group Membership overlay */ #undef SLAPD_OVER_MEMBEROF /* define for Password Policy overlay */ #undef SLAPD_OVER_PPOLICY /* define for Proxy Cache overlay */ #undef SLAPD_OVER_PROXYCACHE /* define for Referential Integrity overlay */ #undef SLAPD_OVER_REFINT /* define for Referential Integrity overlay */ #undef SLAPD_OVER_RETCODE /* define for Rewrite/Remap overlay */ #undef SLAPD_OVER_RWM /* define for Sequential Modify overlay */ #undef SLAPD_OVER_SEQMOD /* define for ServerSideSort/VLV overlay */ #undef SLAPD_OVER_SSSVLV /* define for Syncrepl Provider overlay */ #undef SLAPD_OVER_SYNCPROV /* define for Translucent Proxy overlay */ #undef SLAPD_OVER_TRANSLUCENT /* define for Attribute Uniqueness overlay */ #undef SLAPD_OVER_UNIQUE /* define for Value Sorting overlay */ #undef SLAPD_OVER_VALSORT /* define to support PASSWD backend */ #undef SLAPD_PASSWD /* define to support PERL backend */ #undef SLAPD_PERL /* define to support relay backend */ #undef SLAPD_RELAY /* define to support reverse lookups */ #undef SLAPD_RLOOKUPS /* define to support SHELL backend */ #undef SLAPD_SHELL /* define to support SOCK backend */ #undef SLAPD_SOCK /* define to support SASL passwords */ #undef SLAPD_SPASSWD /* define to support SQL backend */ #undef SLAPD_SQL /* define to support run-time loadable ACL */ #undef SLAP_DYNACL /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Define to 1 if you can safely include both and . */ #undef TIME_WITH_SYS_TIME /* Define to 1 if your declares `struct tm'. */ #undef TM_IN_SYS_TIME /* set to urandom device */ #undef URANDOM_DEVICE /* define to use OpenSSL BIGNUM for MP */ #undef USE_MP_BIGNUM /* define to use GMP for MP */ #undef USE_MP_GMP /* define to use 'long' for MP */ #undef USE_MP_LONG /* define to use 'long long' for MP */ #undef USE_MP_LONG_LONG /* Define to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel and VAX). */ #undef WORDS_BIGENDIAN /* Define to the type of arg 3 for `accept'. */ #undef ber_socklen_t /* Define to `char *' if does not define. */ #undef caddr_t /* Define to empty if `const' does not conform to ANSI C. */ #undef const /* Define to `int' if doesn't define. */ #undef gid_t /* Define to `int' if does not define. */ #undef mode_t /* Define to `long' if does not define. */ #undef off_t /* Define to `int' if does not define. */ #undef pid_t /* Define to `int' if does not define. */ #undef sig_atomic_t /* Define to `unsigned' if does not define. */ #undef size_t /* define to snprintf routine */ #undef snprintf /* Define like ber_socklen_t if does not define. */ #undef socklen_t /* Define to `signed int' if does not define. */ #undef ssize_t /* Define to `int' if doesn't define. */ #undef uid_t /* define as empty if volatile is not supported */ #undef volatile /* define to snprintf routine */ #undef vsnprintf /* begin of portable.h.post */ #ifdef _WIN32 /* don't suck in all of the win32 api */ # define WIN32_LEAN_AND_MEAN 1 #endif #ifndef LDAP_NEEDS_PROTOTYPES /* force LDAP_P to always include prototypes */ #define LDAP_NEEDS_PROTOTYPES 1 #endif #ifndef LDAP_REL_ENG #if (LDAP_VENDOR_VERSION == 000000) && !defined(LDAP_DEVEL) #define LDAP_DEVEL #endif #if defined(LDAP_DEVEL) && !defined(LDAP_TEST) #define LDAP_TEST #endif #endif #ifdef HAVE_STDDEF_H # include #endif #ifdef HAVE_EBCDIC /* ASCII/EBCDIC converting replacements for stdio funcs * vsnprintf and snprintf are used too, but they are already * checked by the configure script */ #define fputs ber_pvt_fputs #define fgets ber_pvt_fgets #define printf ber_pvt_printf #define fprintf ber_pvt_fprintf #define vfprintf ber_pvt_vfprintf #define vsprintf ber_pvt_vsprintf #endif #include "ac/fdset.h" #include "ldap_cdefs.h" #include "ldap_features.h" #include "ac/assert.h" #include "ac/localize.h" #endif /* _LDAP_PORTABLE_H */ /* end of portable.h.post */ openldap-2.4.42+dfsg/include/ldap_schema.h0000644000175000017500000002235212563404150017070 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* ldap-schema.h - Header for basic schema handling functions that can be * used by both clients and servers. * these routines should be renamed ldap_x_... */ #ifndef _LDAP_SCHEMA_H #define _LDAP_SCHEMA_H 1 #include LDAP_BEGIN_DECL /* Codes for parsing errors */ #define LDAP_SCHERR_OUTOFMEM 1 #define LDAP_SCHERR_UNEXPTOKEN 2 #define LDAP_SCHERR_NOLEFTPAREN 3 #define LDAP_SCHERR_NORIGHTPAREN 4 #define LDAP_SCHERR_NODIGIT 5 #define LDAP_SCHERR_BADNAME 6 #define LDAP_SCHERR_BADDESC 7 #define LDAP_SCHERR_BADSUP 8 #define LDAP_SCHERR_DUPOPT 9 #define LDAP_SCHERR_EMPTY 10 #define LDAP_SCHERR_MISSING 11 #define LDAP_SCHERR_OUT_OF_ORDER 12 typedef struct ldap_schema_extension_item { char *lsei_name; char **lsei_values; } LDAPSchemaExtensionItem; typedef struct ldap_syntax { char *syn_oid; /* REQUIRED */ char **syn_names; /* OPTIONAL */ char *syn_desc; /* OPTIONAL */ LDAPSchemaExtensionItem **syn_extensions; /* OPTIONAL */ } LDAPSyntax; typedef struct ldap_matchingrule { char *mr_oid; /* REQUIRED */ char **mr_names; /* OPTIONAL */ char *mr_desc; /* OPTIONAL */ int mr_obsolete; /* OPTIONAL */ char *mr_syntax_oid; /* REQUIRED */ LDAPSchemaExtensionItem **mr_extensions; /* OPTIONAL */ } LDAPMatchingRule; typedef struct ldap_matchingruleuse { char *mru_oid; /* REQUIRED */ char **mru_names; /* OPTIONAL */ char *mru_desc; /* OPTIONAL */ int mru_obsolete; /* OPTIONAL */ char **mru_applies_oids; /* REQUIRED */ LDAPSchemaExtensionItem **mru_extensions; /* OPTIONAL */ } LDAPMatchingRuleUse; typedef struct ldap_attributetype { char *at_oid; /* REQUIRED */ char **at_names; /* OPTIONAL */ char *at_desc; /* OPTIONAL */ int at_obsolete; /* 0=no, 1=yes */ char *at_sup_oid; /* OPTIONAL */ char *at_equality_oid; /* OPTIONAL */ char *at_ordering_oid; /* OPTIONAL */ char *at_substr_oid; /* OPTIONAL */ char *at_syntax_oid; /* OPTIONAL */ int at_syntax_len; /* OPTIONAL */ int at_single_value; /* 0=no, 1=yes */ int at_collective; /* 0=no, 1=yes */ int at_no_user_mod; /* 0=no, 1=yes */ int at_usage; /* 0=userApplications, 1=directoryOperation, 2=distributedOperation, 3=dSAOperation */ LDAPSchemaExtensionItem **at_extensions; /* OPTIONAL */ } LDAPAttributeType; typedef struct ldap_objectclass { char *oc_oid; /* REQUIRED */ char **oc_names; /* OPTIONAL */ char *oc_desc; /* OPTIONAL */ int oc_obsolete; /* 0=no, 1=yes */ char **oc_sup_oids; /* OPTIONAL */ int oc_kind; /* 0=ABSTRACT, 1=STRUCTURAL, 2=AUXILIARY */ char **oc_at_oids_must; /* OPTIONAL */ char **oc_at_oids_may; /* OPTIONAL */ LDAPSchemaExtensionItem **oc_extensions; /* OPTIONAL */ } LDAPObjectClass; typedef struct ldap_contentrule { char *cr_oid; /* REQUIRED */ char **cr_names; /* OPTIONAL */ char *cr_desc; /* OPTIONAL */ char **cr_sup_oids; /* OPTIONAL */ int cr_obsolete; /* 0=no, 1=yes */ char **cr_oc_oids_aux; /* OPTIONAL */ char **cr_at_oids_must; /* OPTIONAL */ char **cr_at_oids_may; /* OPTIONAL */ char **cr_at_oids_not; /* OPTIONAL */ LDAPSchemaExtensionItem **cr_extensions; /* OPTIONAL */ } LDAPContentRule; typedef struct ldap_nameform { char *nf_oid; /* REQUIRED */ char **nf_names; /* OPTIONAL */ char *nf_desc; /* OPTIONAL */ int nf_obsolete; /* 0=no, 1=yes */ char *nf_objectclass; /* REQUIRED */ char **nf_at_oids_must; /* REQUIRED */ char **nf_at_oids_may; /* OPTIONAL */ LDAPSchemaExtensionItem **nf_extensions; /* OPTIONAL */ } LDAPNameForm; typedef struct ldap_structurerule { int sr_ruleid; /* REQUIRED */ char **sr_names; /* OPTIONAL */ char *sr_desc; /* OPTIONAL */ int sr_obsolete; /* 0=no, 1=yes */ char *sr_nameform; /* REQUIRED */ int sr_nsup_ruleids;/* number of sr_sup_ruleids */ int *sr_sup_ruleids;/* OPTIONAL */ LDAPSchemaExtensionItem **sr_extensions; /* OPTIONAL */ } LDAPStructureRule; /* * Misc macros */ #define LDAP_SCHEMA_NO 0 #define LDAP_SCHEMA_YES 1 #define LDAP_SCHEMA_USER_APPLICATIONS 0 #define LDAP_SCHEMA_DIRECTORY_OPERATION 1 #define LDAP_SCHEMA_DISTRIBUTED_OPERATION 2 #define LDAP_SCHEMA_DSA_OPERATION 3 #define LDAP_SCHEMA_ABSTRACT 0 #define LDAP_SCHEMA_STRUCTURAL 1 #define LDAP_SCHEMA_AUXILIARY 2 /* * Flags that control how liberal the parsing routines are. */ #define LDAP_SCHEMA_ALLOW_NONE 0x00U /* Strict parsing */ #define LDAP_SCHEMA_ALLOW_NO_OID 0x01U /* Allow missing oid */ #define LDAP_SCHEMA_ALLOW_QUOTED 0x02U /* Allow bogus extra quotes */ #define LDAP_SCHEMA_ALLOW_DESCR 0x04U /* Allow descr instead of OID */ #define LDAP_SCHEMA_ALLOW_DESCR_PREFIX 0x08U /* Allow descr as OID prefix */ #define LDAP_SCHEMA_ALLOW_OID_MACRO 0x10U /* Allow OID macros in slapd */ #define LDAP_SCHEMA_ALLOW_OUT_OF_ORDER_FIELDS 0x20U /* Allow fields in most any order */ #define LDAP_SCHEMA_ALLOW_ALL 0x3fU /* Be very liberal in parsing */ #define LDAP_SCHEMA_SKIP 0x80U /* Don't malloc any result */ LDAP_F( LDAP_CONST char * ) ldap_syntax2name LDAP_P(( LDAPSyntax * syn )); LDAP_F( LDAP_CONST char * ) ldap_matchingrule2name LDAP_P(( LDAPMatchingRule * mr )); LDAP_F( LDAP_CONST char * ) ldap_matchingruleuse2name LDAP_P(( LDAPMatchingRuleUse * mru )); LDAP_F( LDAP_CONST char * ) ldap_attributetype2name LDAP_P(( LDAPAttributeType * at )); LDAP_F( LDAP_CONST char * ) ldap_objectclass2name LDAP_P(( LDAPObjectClass * oc )); LDAP_F( LDAP_CONST char * ) ldap_contentrule2name LDAP_P(( LDAPContentRule * cr )); LDAP_F( LDAP_CONST char * ) ldap_nameform2name LDAP_P(( LDAPNameForm * nf )); LDAP_F( LDAP_CONST char * ) ldap_structurerule2name LDAP_P(( LDAPStructureRule * sr )); LDAP_F( void ) ldap_syntax_free LDAP_P(( LDAPSyntax * syn )); LDAP_F( void ) ldap_matchingrule_free LDAP_P(( LDAPMatchingRule * mr )); LDAP_F( void ) ldap_matchingruleuse_free LDAP_P(( LDAPMatchingRuleUse * mr )); LDAP_F( void ) ldap_attributetype_free LDAP_P(( LDAPAttributeType * at )); LDAP_F( void ) ldap_objectclass_free LDAP_P(( LDAPObjectClass * oc )); LDAP_F( void ) ldap_contentrule_free LDAP_P(( LDAPContentRule * cr )); LDAP_F( void ) ldap_nameform_free LDAP_P(( LDAPNameForm * nf )); LDAP_F( void ) ldap_structurerule_free LDAP_P(( LDAPStructureRule * sr )); LDAP_F( LDAPStructureRule * ) ldap_str2structurerule LDAP_P(( LDAP_CONST char * s, int * code, LDAP_CONST char ** errp, LDAP_CONST unsigned flags )); LDAP_F( LDAPNameForm * ) ldap_str2nameform LDAP_P(( LDAP_CONST char * s, int * code, LDAP_CONST char ** errp, LDAP_CONST unsigned flags )); LDAP_F( LDAPContentRule * ) ldap_str2contentrule LDAP_P(( LDAP_CONST char * s, int * code, LDAP_CONST char ** errp, LDAP_CONST unsigned flags )); LDAP_F( LDAPObjectClass * ) ldap_str2objectclass LDAP_P(( LDAP_CONST char * s, int * code, LDAP_CONST char ** errp, LDAP_CONST unsigned flags )); LDAP_F( LDAPAttributeType * ) ldap_str2attributetype LDAP_P(( LDAP_CONST char * s, int * code, LDAP_CONST char ** errp, LDAP_CONST unsigned flags )); LDAP_F( LDAPSyntax * ) ldap_str2syntax LDAP_P(( LDAP_CONST char * s, int * code, LDAP_CONST char ** errp, LDAP_CONST unsigned flags )); LDAP_F( LDAPMatchingRule * ) ldap_str2matchingrule LDAP_P(( LDAP_CONST char * s, int * code, LDAP_CONST char ** errp, LDAP_CONST unsigned flags )); LDAP_F( LDAPMatchingRuleUse * ) ldap_str2matchingruleuse LDAP_P(( LDAP_CONST char * s, int * code, LDAP_CONST char ** errp, LDAP_CONST unsigned flags )); LDAP_F( char * ) ldap_structurerule2str LDAP_P(( LDAPStructureRule * sr )); LDAP_F( struct berval * ) ldap_structurerule2bv LDAP_P(( LDAPStructureRule * sr, struct berval *bv )); LDAP_F( char * ) ldap_nameform2str LDAP_P(( LDAPNameForm * nf )); LDAP_F( struct berval * ) ldap_nameform2bv LDAP_P(( LDAPNameForm * nf, struct berval *bv )); LDAP_F( char * ) ldap_contentrule2str LDAP_P(( LDAPContentRule * cr )); LDAP_F( struct berval * ) ldap_contentrule2bv LDAP_P(( LDAPContentRule * cr, struct berval *bv )); LDAP_F( char * ) ldap_objectclass2str LDAP_P(( LDAPObjectClass * oc )); LDAP_F( struct berval * ) ldap_objectclass2bv LDAP_P(( LDAPObjectClass * oc, struct berval *bv )); LDAP_F( char * ) ldap_attributetype2str LDAP_P(( LDAPAttributeType * at )); LDAP_F( struct berval * ) ldap_attributetype2bv LDAP_P(( LDAPAttributeType * at, struct berval *bv )); LDAP_F( char * ) ldap_syntax2str LDAP_P(( LDAPSyntax * syn )); LDAP_F( struct berval * ) ldap_syntax2bv LDAP_P(( LDAPSyntax * syn, struct berval *bv )); LDAP_F( char * ) ldap_matchingrule2str LDAP_P(( LDAPMatchingRule * mr )); LDAP_F( struct berval * ) ldap_matchingrule2bv LDAP_P(( LDAPMatchingRule * mr, struct berval *bv )); LDAP_F( char * ) ldap_matchingruleuse2str LDAP_P(( LDAPMatchingRuleUse * mru )); LDAP_F( struct berval * ) ldap_matchingruleuse2bv LDAP_P(( LDAPMatchingRuleUse * mru, struct berval *bv )); LDAP_F( char * ) ldap_scherr2str LDAP_P(( int code )) LDAP_GCCATTR((const)); LDAP_END_DECL #endif openldap-2.4.42+dfsg/include/lutil_hash.h0000644000175000017500000000211012563404150016752 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #ifndef _LUTIL_HASH_H_ #define _LUTIL_HASH_H_ #include LDAP_BEGIN_DECL #define LUTIL_HASH_BYTES 4 struct lutil_HASHContext { ber_uint_t hash; }; LDAP_LUTIL_F( void ) lutil_HASHInit LDAP_P(( struct lutil_HASHContext *context)); LDAP_LUTIL_F( void ) lutil_HASHUpdate LDAP_P(( struct lutil_HASHContext *context, unsigned char const *buf, ber_len_t len)); LDAP_LUTIL_F( void ) lutil_HASHFinal LDAP_P(( unsigned char digest[LUTIL_HASH_BYTES], struct lutil_HASHContext *context)); typedef struct lutil_HASHContext lutil_HASH_CTX; LDAP_END_DECL #endif /* _LUTIL_HASH_H_ */ openldap-2.4.42+dfsg/include/lutil_sha1.h0000644000175000017500000000324312563404150016673 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* This version is based on: * $OpenBSD: sha1.h,v 1.8 1997/07/15 01:54:23 millert Exp $ */ #ifndef _LUTIL_SHA1_H_ #define _LUTIL_SHA1_H_ #include #include #ifdef AC_INT4_TYPE LDAP_BEGIN_DECL /* * SHA-1 in C * By Steve Reid */ #define LUTIL_SHA1_BYTES 20 /* This code assumes char are 8-bits and uint32 are 32-bits */ typedef ac_uint4 uint32; typedef struct { uint32 state[5]; uint32 count[2]; unsigned char buffer[64]; } lutil_SHA1_CTX; LDAP_LUTIL_F( void ) lutil_SHA1Transform LDAP_P((uint32 state[5], const unsigned char buffer[64])); LDAP_LUTIL_F( void ) lutil_SHA1Init LDAP_P((lutil_SHA1_CTX *context)); LDAP_LUTIL_F( void ) lutil_SHA1Update LDAP_P((lutil_SHA1_CTX *context, const unsigned char *data, uint32 len)); LDAP_LUTIL_F( void ) lutil_SHA1Final LDAP_P((unsigned char digest[20], lutil_SHA1_CTX *context)); LDAP_LUTIL_F( char * ) lutil_SHA1End LDAP_P((lutil_SHA1_CTX *, char *)); LDAP_LUTIL_F( char * ) lutil_SHA1File LDAP_P((char *, char *)); LDAP_LUTIL_F( char * ) lutil_SHA1Data LDAP_P((const unsigned char *, size_t, char *)); LDAP_END_DECL #endif /* AC_INT4_TYPE */ #endif /* _LUTIL_SHA1_H_ */ openldap-2.4.42+dfsg/include/ac/0000755000175000017500000000000012563404150015036 5ustar ryanryanopenldap-2.4.42+dfsg/include/ac/signal.h0000644000175000017500000000365112563404150016471 0ustar ryanryan/* Generic signal.h */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #ifndef _AC_SIGNAL_H #define _AC_SIGNAL_H #include #undef SIGNAL #if defined( HAVE_SIGACTION ) #define SIGNAL lutil_sigaction typedef void (*lutil_sig_t)(int); LDAP_LUTIL_F(lutil_sig_t) lutil_sigaction( int sig, lutil_sig_t func ); #define SIGNAL_REINSTALL(sig,act) (void)0 #elif defined( HAVE_SIGSET ) #define SIGNAL sigset #define SIGNAL_REINSTALL sigset #else #define SIGNAL signal #define SIGNAL_REINSTALL signal #endif #if !defined( LDAP_SIGUSR1 ) || !defined( LDAP_SIGUSR2 ) #undef LDAP_SIGUSR1 #undef LDAP_SIGUSR2 # if defined(WINNT) || defined(_WINNT) || defined(_WIN32) # define LDAP_SIGUSR1 SIGILL # define LDAP_SIGUSR2 SIGTERM # elif !defined(HAVE_LINUX_THREADS) # define LDAP_SIGUSR1 SIGUSR1 # define LDAP_SIGUSR2 SIGUSR2 # else /* * Some versions of LinuxThreads unfortunately uses the only * two signals reserved for user applications. This forces * OpenLDAP to use other signals reserved for other uses. */ # if defined( SIGSTKFLT ) # define LDAP_SIGUSR1 SIGSTKFLT # elif defined ( SIGSYS ) # define LDAP_SIGUSR1 SIGSYS # endif # if defined( SIGUNUSED ) # define LDAP_SIGUSR2 SIGUNUSED # elif defined ( SIGINFO ) # define LDAP_SIGUSR2 SIGINFO # elif defined ( SIGEMT ) # define LDAP_SIGUSR2 SIGEMT # endif # endif #endif #ifndef LDAP_SIGCHLD #ifdef SIGCHLD #define LDAP_SIGCHLD SIGCHLD #elif SIGCLD #define LDAP_SIGCHLD SIGCLD #endif #endif #endif /* _AC_SIGNAL_H */ openldap-2.4.42+dfsg/include/ac/assert.h0000644000175000017500000000261312563404150016512 0ustar ryanryan/* Generic assert.h */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #ifndef _AC_ASSERT_H #define _AC_ASSERT_H #undef assert #ifdef LDAP_DEBUG #if defined( HAVE_ASSERT_H ) || defined( STDC_HEADERS ) #undef NDEBUG #include #else /* !(HAVE_ASSERT_H || STDC_HEADERS) */ #define LDAP_NEED_ASSERT 1 /* * no assert()... must be a very old compiler. * create a replacement and hope it works */ LBER_F (void) ber_pvt_assert LDAP_P(( const char *file, int line, const char *test )); /* Can't use LDAP_STRING(test), that'd expand to "test" */ #if defined(__STDC__) || defined(__cplusplus) #define assert(test) \ ((test) ? (void)0 : ber_pvt_assert( __FILE__, __LINE__, #test ) ) #else #define assert(test) \ ((test) ? (void)0 : ber_pvt_assert( __FILE__, __LINE__, "test" ) ) #endif #endif /* (HAVE_ASSERT_H || STDC_HEADERS) */ #else /* !LDAP_DEBUG */ /* no asserts */ #define assert(test) ((void)0) #endif /* LDAP_DEBUG */ #endif /* _AC_ASSERT_H */ openldap-2.4.42+dfsg/include/ac/stdlib.h0000644000175000017500000000206412563404150016472 0ustar ryanryan/* Generic stdlib.h */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #ifndef _AC_STDLIB_H #define _AC_STDLIB_H #if defined( HAVE_CSRIMALLOC ) #include #define MALLOC_TRACE #include #endif #include /* Ignore malloc.h if we have STDC_HEADERS */ #if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS) # include #endif #ifndef EXIT_SUCCESS # define EXIT_SUCCESS 0 # define EXIT_FAILURE 1 #endif #ifdef HAVE_LIMITS_H #include #endif #if defined(LINE_MAX) # define AC_LINE_MAX LINE_MAX #else # define AC_LINE_MAX 2048 /* POSIX MIN */ #endif #endif /* _AC_STDLIB_H */ openldap-2.4.42+dfsg/include/ac/param.h0000644000175000017500000000157212563404150016314 0ustar ryanryan/* Generic param.h */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #ifndef _AC_PARAM_H #define _AC_PARAM_H #ifdef HAVE_SYS_PARAM_H #include #endif /* MAXPATHLEN should come from */ #include #ifndef MAXPATHLEN # if defined(PATH_MAX) # define MAXPATHLEN PATH_MAX # elif defined(_MAX_PATH) # define MAXPATHLEN _MAX_PATH # else # define MAXPATHLEN 4096 # endif #endif #endif /* _AC_PARAM_H */ openldap-2.4.42+dfsg/include/ac/time.h0000644000175000017500000000143312563404150016146 0ustar ryanryan/* Generic time.h */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #ifndef _AC_TIME_H #define _AC_TIME_H #ifdef TIME_WITH_SYS_TIME # include # include #elif defined(HAVE_SYS_TIME_H) # include # ifdef HAVE_SYS_TIMEB_H # include # endif #else # include #endif #endif /* _AC_TIME_H */ openldap-2.4.42+dfsg/include/ac/stdarg.h0000644000175000017500000000130612563404150016473 0ustar ryanryan/* Generic stdarg.h */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #ifndef _AC_STDARG_H #define _AC_STDARG_H 1 /* require STDC variable argument support */ #include #ifndef HAVE_STDARG # define HAVE_STDARG 1 #endif #endif /* _AC_STDARG_H */ openldap-2.4.42+dfsg/include/ac/socket.h0000644000175000017500000001405112563404150016500 0ustar ryanryan/* Generic socket.h */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #ifndef _AC_SOCKET_H_ #define _AC_SOCKET_H_ #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_POLL_H #include #elif defined(HAVE_SYS_POLL_H) #include #endif #ifdef HAVE_SYS_SOCKET_H #include #ifdef HAVE_SYS_UN_H #include #endif #ifdef HAVE_SYS_SELECT_H #include #endif #include #ifdef HAVE_NETINET_TCP_H #include #endif #ifdef HAVE_ARPA_INET_H #include #endif #ifdef HAVE_ARPA_NAMESER_H #include #endif #include #ifdef HAVE_RESOLV_H #include #endif #endif /* HAVE_SYS_SOCKET_H */ #ifdef HAVE_WINSOCK2 #include #include #elif HAVE_WINSOCK #include #endif #ifdef HAVE_PCNFS #include #endif /* HAVE_PCNFS */ #ifndef INADDR_LOOPBACK #define INADDR_LOOPBACK (0x7f000001UL) #endif #ifndef MAXHOSTNAMELEN #define MAXHOSTNAMELEN 64 #endif #undef sock_errno #undef sock_errstr #define sock_errno() errno #define sock_errstr(e) STRERROR(e) #define sock_errset(e) ((void) (errno = (e))) #ifdef HAVE_WINSOCK # define tcp_read( s, buf, len ) recv( s, buf, len, 0 ) # define tcp_write( s, buf, len ) send( s, buf, len, 0 ) # define ioctl( s, c, a ) ioctlsocket( (s), (c), (a) ) # define ioctl_t u_long # define AC_SOCKET_INVALID ((unsigned int) -1) # ifdef SD_BOTH # define tcp_close( s ) (shutdown( s, SD_BOTH ), closesocket( s )) # else # define tcp_close( s ) closesocket( s ) # endif #define EWOULDBLOCK WSAEWOULDBLOCK #define EINPROGRESS WSAEINPROGRESS #define ETIMEDOUT WSAETIMEDOUT #undef sock_errno #undef sock_errstr #undef sock_errset #define sock_errno() WSAGetLastError() #define sock_errstr(e) ber_pvt_wsa_err2string(e) #define sock_errset(e) WSASetLastError(e) LBER_F( char * ) ber_pvt_wsa_err2string LDAP_P((int)); #elif MACOS # define tcp_close( s ) tcpclose( s ) # define tcp_read( s, buf, len ) tcpread( s, buf, len ) # define tcp_write( s, buf, len ) tcpwrite( s, buf, len ) #elif DOS # ifdef PCNFS # define tcp_close( s ) close( s ) # define tcp_read( s, buf, len ) recv( s, buf, len, 0 ) # define tcp_write( s, buf, len ) send( s, buf, len, 0 ) # endif /* PCNFS */ # ifdef NCSA # define tcp_close( s ) do { netclose( s ); netshut() } while(0) # define tcp_read( s, buf, len ) nread( s, buf, len ) # define tcp_write( s, buf, len ) netwrite( s, buf, len ) # endif /* NCSA */ #elif defined(HAVE_CLOSESOCKET) # define tcp_close( s ) closesocket( s ) # ifdef __BEOS__ # define tcp_read( s, buf, len ) recv( s, buf, len, 0 ) # define tcp_write( s, buf, len ) send( s, buf, len, 0 ) # endif #else # define tcp_read( s, buf, len) read( s, buf, len ) # define tcp_write( s, buf, len) write( s, buf, len ) # ifdef SHUT_RDWR # define tcp_close( s ) (shutdown( s, SHUT_RDWR ), close( s )) # else # define tcp_close( s ) close( s ) # endif #ifdef HAVE_PIPE /* * Only use pipe() on systems where file and socket descriptors * are interchangable */ # define USE_PIPE HAVE_PIPE #endif #endif /* MACOS */ #ifndef ioctl_t # define ioctl_t int #endif #ifndef AC_SOCKET_INVALID # define AC_SOCKET_INVALID (-1) #endif #ifndef AC_SOCKET_ERROR # define AC_SOCKET_ERROR (-1) #endif #if !defined( HAVE_INET_ATON ) && !defined( inet_aton ) # define inet_aton ldap_pvt_inet_aton struct in_addr; LDAP_F (int) ldap_pvt_inet_aton LDAP_P(( const char *, struct in_addr * )); #endif #if defined(__WIN32) && defined(_ALPHA) /* NT on Alpha is hosed. */ # define AC_HTONL( l ) \ ((((l)&0xffU)<<24) + (((l)&0xff00U)<<8) + \ (((l)&0xff0000U)>>8) + (((l)&0xff000000U)>>24)) # define AC_NTOHL(l) AC_HTONL(l) #else # define AC_HTONL( l ) htonl( l ) # define AC_NTOHL( l ) ntohl( l ) #endif /* htons()/ntohs() may be broken much like htonl()/ntohl() */ #define AC_HTONS( s ) htons( s ) #define AC_NTOHS( s ) ntohs( s ) #ifdef LDAP_PF_LOCAL # if !defined( AF_LOCAL ) && defined( AF_UNIX ) # define AF_LOCAL AF_UNIX # endif # if !defined( PF_LOCAL ) && defined( PF_UNIX ) # define PF_LOCAL PF_UNIX # endif #endif #ifndef INET_ADDRSTRLEN # define INET_ADDRSTRLEN 16 #endif #ifndef INET6_ADDRSTRLEN # define INET6_ADDRSTRLEN 46 #endif #if defined( HAVE_GETADDRINFO ) || defined( HAVE_GETNAMEINFO ) # ifdef HAVE_GAI_STRERROR # define AC_GAI_STRERROR(x) (gai_strerror((x))) # else # define AC_GAI_STRERROR(x) (ldap_pvt_gai_strerror((x))) LDAP_F (char *) ldap_pvt_gai_strerror( int ); # endif #endif #if defined(LDAP_PF_LOCAL) && \ !defined(HAVE_GETPEEREID) && \ !defined(HAVE_GETPEERUCRED) && \ !defined(SO_PEERCRED) && !defined(LOCAL_PEERCRED) && \ defined(HAVE_SENDMSG) && (defined(HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTSLEN) || \ defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL)) # define LDAP_PF_LOCAL_SENDMSG 1 #endif #ifdef HAVE_GETPEEREID #define LUTIL_GETPEEREID( s, uid, gid, bv ) getpeereid( s, uid, gid ) #elif defined(LDAP_PF_LOCAL_SENDMSG) struct berval; LDAP_LUTIL_F( int ) lutil_getpeereid( int s, uid_t *, gid_t *, struct berval *bv ); #define LUTIL_GETPEEREID( s, uid, gid, bv ) lutil_getpeereid( s, uid, gid, bv ) #else LDAP_LUTIL_F( int ) lutil_getpeereid( int s, uid_t *, gid_t * ); #define LUTIL_GETPEEREID( s, uid, gid, bv ) lutil_getpeereid( s, uid, gid ) #endif /* DNS RFC defines max host name as 255. New systems seem to use 1024 */ #ifndef NI_MAXHOST #define NI_MAXHOST 256 #endif #ifdef HAVE_POLL # ifndef INFTIM # define INFTIM (-1) # endif #undef POLL_OTHER #define POLL_OTHER (POLLERR|POLLHUP) #undef POLL_READ #define POLL_READ (POLLIN|POLLPRI|POLL_OTHER) #undef POLL_WRITE #define POLL_WRITE (POLLOUT|POLL_OTHER) #endif #endif /* _AC_SOCKET_H_ */ openldap-2.4.42+dfsg/include/ac/errno.h0000644000175000017500000000267512563404150016346 0ustar ryanryan/* Generic errno.h */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #ifndef _AC_ERRNO_H #define _AC_ERRNO_H #if defined( HAVE_ERRNO_H ) # include #elif defined( HAVE_SYS_ERRNO_H ) # include #endif #ifndef HAVE_SYS_ERRLIST /* no sys_errlist */ # define sys_nerr 0 # define sys_errlist ((char **)0) #elif defined( DECL_SYS_ERRLIST ) /* have sys_errlist but need declaration */ LDAP_LIBC_V(int) sys_nerr; LDAP_LIBC_V(char) *sys_errlist[]; #endif #undef _AC_ERRNO_UNKNOWN #define _AC_ERRNO_UNKNOWN "unknown error" #ifdef HAVE_SYS_ERRLIST /* this is thread safe */ # define STRERROR(e) ( (e) > -1 && (e) < sys_nerr \ ? sys_errlist[(e)] : _AC_ERRNO_UNKNOWN ) #elif defined( HAVE_STRERROR ) /* this may not be thread safe */ /* and, yes, some implementations of strerror may return NULL */ # define STRERROR(e) ( strerror(e) \ ? strerror(e) : _AC_ERRNO_UNKNOWN ) #else /* this is thread safe */ # define STRERROR(e) ( _AC_ERRNO_UNKNOWN ) #endif #endif /* _AC_ERRNO_H */ openldap-2.4.42+dfsg/include/ac/dirent.h0000644000175000017500000000231612563404150016476 0ustar ryanryan/* Generic dirent.h */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #ifndef _AC_DIRENT_H #define _AC_DIRENT_H #ifdef HAVE_DIRENT_H # include # define NAMLEN(dirent) strlen((dirent)->d_name) #elif defined(_MSC_VER) #include #ifndef MAX_PATH #define MAX_PATH 260 #endif struct dirent { char *d_name; }; typedef struct DIR { HANDLE dir; struct dirent data; int first; char buf[MAX_PATH+1]; } DIR; DIR *opendir(const char *name); struct dirent *readdir(DIR *dir); int closedir(DIR *dir); #else # define dirent direct # define NAMLEN(dirent) (dirent)->d_namlen # ifdef HAVE_SYS_NDIR_H # include # endif # ifdef HAVE_SYS_DIR_H # include # endif # ifdef HAVE_NDIR_H # include # endif #endif #endif /* _AC_DIRENT_H */ openldap-2.4.42+dfsg/include/ac/crypt.h0000644000175000017500000000135112563404150016350 0ustar ryanryan/* Generic crypt.h */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #ifndef _AC_CRYPT_H #define _AC_CRYPT_H #include /* crypt() may be defined in a separate include file */ #ifdef HAVE_CRYPT_H # include #else extern char *(crypt)(); #endif #endif /* _AC_CRYPT_H */ openldap-2.4.42+dfsg/include/ac/fdset.h0000644000175000017500000000214312563404150016314 0ustar ryanryan/* redefine FD_SET */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* * This header is to be included by portable.h to ensure * tweaking of FD_SETSIZE is done early enough to be effective. */ #ifndef _AC_FDSET_H #define _AC_FDSET_H #if !defined( OPENLDAP_FD_SETSIZE ) && !defined( FD_SETSIZE ) # define OPENLDAP_FD_SETSIZE 4096 #endif #ifdef OPENLDAP_FD_SETSIZE /* assume installer desires to enlarge fd_set */ # ifdef HAVE_BITS_TYPES_H # include # endif # ifdef __FD_SETSIZE # undef __FD_SETSIZE # define __FD_SETSIZE OPENLDAP_FD_SETSIZE # else # define FD_SETSIZE OPENLDAP_FD_SETSIZE # endif #endif #endif /* _AC_FDSET_H */ openldap-2.4.42+dfsg/include/ac/alloca.h0000644000175000017500000000177612563404150016455 0ustar ryanryan/* Generic alloca.h */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #ifndef _AC_ALLOCA_H #define _AC_ALLOCA_H /* * use of alloca is disallowed as it is machine dependent */ #error "alloca() not supported, use malloc()" /* AIX requires this to be the first thing in the file. */ #ifdef __GNUC__ # define alloca __builtin_alloca #else # ifdef HAVE_ALLOCA_H # include # else # ifdef _AIX #pragma alloca # else # ifndef alloca /* predefined by HP cc +Olibcalls */ extern char *(alloca)(); # endif # endif # endif #endif #endif /* _AC_ALLOCA_H */ openldap-2.4.42+dfsg/include/ac/bytes.h0000644000175000017500000000401512563404150016335 0ustar ryanryan/* Generic bytes.h */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #ifndef _AC_BYTES_H #define _AC_BYTES_H /* cross compilers should define both AC_INT{2,4}_TYPE in CPPFLAGS */ #if !defined( AC_INT4_TYPE ) /* use autoconf defines to provide sized typedefs */ # if SIZEOF_LONG == 4 # define AC_INT4_TYPE long # elif SIZEOF_INT == 4 # define AC_INT4_TYPE int # elif SIZEOF_SHORT == 4 # define AC_INT4_TYPE short # else # error "AC_INT4_TYPE?" # endif #endif typedef AC_INT4_TYPE ac_int4; typedef signed AC_INT4_TYPE ac_sint4; typedef unsigned AC_INT4_TYPE ac_uint4; #if !defined( AC_INT2_TYPE ) # if SIZEOF_SHORT == 2 # define AC_INT2_TYPE short # elif SIZEOF_INT == 2 # define AC_INT2_TYPE int # elif SIZEOF_LONG == 2 # define AC_INT2_TYPE long # else # error "AC_INT2_TYPE?" # endif #endif #if defined( AC_INT2_TYPE ) typedef AC_INT2_TYPE ac_int2; typedef signed AC_INT2_TYPE ac_sint2; typedef unsigned AC_INT2_TYPE ac_uint2; #endif #ifndef BYTE_ORDER /* cross compilers should define BYTE_ORDER in CPPFLAGS */ /* * Definitions for byte order, according to byte significance from low * address to high. */ #define LITTLE_ENDIAN 1234 /* LSB first: i386, vax */ #define BIG_ENDIAN 4321 /* MSB first: 68000, ibm, net */ #define PDP_ENDIAN 3412 /* LSB first in word, MSW first in long */ /* assume autoconf's AC_C_BIGENDIAN has been ran */ /* if it hasn't, we assume (maybe falsely) the order is LITTLE ENDIAN */ # ifdef WORDS_BIGENDIAN # define BYTE_ORDER BIG_ENDIAN # else # define BYTE_ORDER LITTLE_ENDIAN # endif #endif /* BYTE_ORDER */ #endif /* _AC_BYTES_H */ openldap-2.4.42+dfsg/include/ac/termios.h0000644000175000017500000000260612563404150016675 0ustar ryanryan/* Generic termios.h */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #ifndef _AC_TERMIOS_H #define _AC_TERMIOS_H #ifdef HAVE_TERMIOS_H #include #ifdef GCWINSZ_IN_SYS_IOCTL #include #endif #define TERMIO_TYPE struct termios #define TERMFLAG_TYPE tcflag_t #define GETATTR( fd, tiop ) tcgetattr((fd), (tiop)) #define SETATTR( fd, tiop ) tcsetattr((fd), TCSANOW /* 0 */, (tiop)) #define GETFLAGS( tio ) ((tio).c_lflag) #define SETFLAGS( tio, flags ) ((tio).c_lflag = (flags)) #elif defined( HAVE_SGTTY_H ) #include #ifdef HAVE_SYS_IOCTL_H #include #endif #define TERMIO_TYPE struct sgttyb #define TERMFLAG_TYPE int #define GETATTR( fd, tiop ) ioctl((fd), TIOCGETP, (caddr_t)(tiop)) #define SETATTR( fd, tiop ) ioctl((fd), TIOCSETP, (caddr_t)(tiop)) #define GETFLAGS( tio ) ((tio).sg_flags) #define SETFLAGS( tio, flags ) ((tio).sg_flags = (flags)) #endif /* HAVE_SGTTY_H */ #endif /* _AC_TERMIOS_H */ openldap-2.4.42+dfsg/include/ac/regex.h0000644000175000017500000000176012563404150016325 0ustar ryanryan/* Generic Regex */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #ifndef _AC_REGEX_H_ #define _AC_REGEX_H_ #ifdef HAVE_SYS_TYPES_H #include #endif #ifndef HAVE_REGEX_H /* NO POSIX REGEX!! * You'll need to install a POSIX compatible REGEX library. * Either Henry Spencer's or GNU regex will do. */ #error "No POSIX REGEX available." #elif HAVE_GNUREGEX_H /* system has GNU gnuregex.h */ # include #else /* have regex.h, assume it's POSIX compliant */ # include #endif /* regex.h */ #endif /* _AC_REGEX_H_ */ openldap-2.4.42+dfsg/include/ac/localize.h0000644000175000017500000000224212563404150017011 0ustar ryanryan/* localize.h (i18n/l10n) */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #ifndef _AC_LOCALIZE_H #define _AC_LOCALIZE_H #ifdef LDAP_LOCALIZE # include # include /* enable i18n/l10n */ # define gettext_noop(s) s # define _(s) gettext(s) # define N_(s) gettext_noop(s) # define ldap_pvt_setlocale(c,l) ((void) setlocale(c, l)) # define ldap_pvt_textdomain(d) ((void) textdomain(d)) # define ldap_pvt_bindtextdomain(p,d) ((void) bindtextdomain(p, d)) #else /* disable i18n/l10n */ # define _(s) s # define N_(s) s # define ldap_pvt_setlocale(c,l) ((void) 0) # define ldap_pvt_textdomain(d) ((void) 0) # define ldap_pvt_bindtextdomain(p,d) ((void) 0) #endif #endif /* _AC_LOCALIZE_H */ openldap-2.4.42+dfsg/include/ac/sysexits.h0000644000175000017500000000126112563404150017102 0ustar ryanryan/* Generic sysexits */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #ifndef _AC_SYSEXITS_H_ #define _AC_SYSEXITS_H_ #ifdef HAVE_SYSEXITS_H # include #else # include #endif #endif /* _AC_SYSEXITS_H_ */ openldap-2.4.42+dfsg/include/ac/wait.h0000644000175000017500000000256312563404150016161 0ustar ryanryan/* Generic wait.h */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #ifndef _AC_WAIT_H #define _AC_WAIT_H #include #ifdef HAVE_SYS_WAIT_H # include #endif #define LDAP_HI(s) (((s) >> 8) & 0377) #define LDAP_LO(s) ((s) & 0377) /* These should work on non-POSIX UNIX platforms, all bets on off on non-POSIX non-UNIX platforms... */ #ifndef WIFEXITED # define WIFEXITED(s) (LDAP_LO(s) == 0) #endif #ifndef WEXITSTATUS # define WEXITSTATUS(s) LDAP_HI(s) #endif #ifndef WIFSIGNALED # define WIFSIGNALED(s) (LDAP_LO(s) > 0 && LDAP_HI(s) == 0) #endif #ifndef WTERMSIG # define WTERMSIG(s) (LDAP_LO(s) & 0177) #endif #ifndef WIFSTOPPED # define WIFSTOPPED(s) (LDAP_LO(s) == 0177 && LDAP_HI(s) != 0) #endif #ifndef WSTOPSIG # define WSTOPSIG(s) LDAP_HI(s) #endif #ifdef WCONTINUED # define WAIT_FLAGS ( WNOHANG | WUNTRACED | WCONTINUED ) #else # define WAIT_FLAGS ( WNOHANG | WUNTRACED ) #endif #endif /* _AC_WAIT_H */ openldap-2.4.42+dfsg/include/ac/string.h0000644000175000017500000000630512563404150016521 0ustar ryanryan/* Generic string.h */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #ifndef _AC_STRING_H #define _AC_STRING_H #ifdef STDC_HEADERS # include #else # ifdef HAVE_STRING_H # include # endif # if defined(HAVE_STRINGS_H) && (!defined(HAVE_STRING_H) || defined(BOTH_STRINGS_H)) # include # endif # ifdef HAVE_MEMORY_H # include # endif # ifndef HAVE_STRRCHR # undef strchr # define strchr index # undef strrchr # define strrchr rindex # endif # ifndef HAVE_MEMCPY # undef memcpy # define memcpy(d, s, n) ((void) bcopy ((s), (d), (n))) # undef memmove # define memmove(d, s, n) ((void) bcopy ((s), (d), (n))) # endif #endif /* use ldap_pvt_strtok instead of strtok or strtok_r! */ LDAP_F(char *) ldap_pvt_strtok LDAP_P(( char *str, const char *delim, char **pos )); #ifndef HAVE_STRDUP /* strdup() is missing, declare our own version */ # undef strdup # define strdup(s) ber_strdup(s) #elif !defined(_WIN32) /* some systems fail to declare strdup */ /* Windows does not require this declaration */ LDAP_LIBC_F(char *) (strdup)(); #endif /* * some systems fail to declare strcasecmp() and strncasecmp() * we need them declared so we can obtain pointers to them */ /* we don't want these declared for Windows or Mingw */ #ifndef _WIN32 int (strcasecmp)(); int (strncasecmp)(); #endif #ifndef SAFEMEMCPY # if defined( HAVE_MEMMOVE ) # define SAFEMEMCPY( d, s, n ) memmove((d), (s), (n)) # elif defined( HAVE_BCOPY ) # define SAFEMEMCPY( d, s, n ) bcopy((s), (d), (n)) # else /* nothing left but memcpy() */ # define SAFEMEMCPY( d, s, n ) memcpy((d), (s), (n)) # endif #endif #define AC_MEMCPY( d, s, n ) (SAFEMEMCPY((d),(s),(n))) #define AC_FMEMCPY( d, s, n ) do { \ if((n) == 1) *((char*)(d)) = *((char*)(s)); \ else AC_MEMCPY( (d), (s), (n) ); \ } while(0) #ifdef NEED_MEMCMP_REPLACEMENT int (lutil_memcmp)(const void *b1, const void *b2, size_t len); #define memcmp lutil_memcmp #endif void *(lutil_memrchr)(const void *b, int c, size_t n); /* GNU extension (glibc >= 2.1.91), only declared when defined(_GNU_SOURCE) */ #if defined(HAVE_MEMRCHR) && defined(_GNU_SOURCE) #define lutil_memrchr(b, c, n) memrchr(b, c, n) #endif /* ! HAVE_MEMRCHR */ #define STRLENOF(s) (sizeof(s)-1) #if defined( HAVE_NONPOSIX_STRERROR_R ) # define AC_STRERROR_R(e,b,l) (strerror_r((e), (b), (l))) #elif defined( HAVE_STRERROR_R ) # define AC_STRERROR_R(e,b,l) (strerror_r((e), (b), (l)) == 0 ? (b) : "Unknown error") #elif defined( HAVE_SYS_ERRLIST ) # define AC_STRERROR_R(e,b,l) ((e) > -1 && (e) < sys_nerr \ ? sys_errlist[(e)] : "Unknown error" ) #elif defined( HAVE_STRERROR ) # define AC_STRERROR_R(e,b,l) (strerror(e)) /* NOTE: may be NULL */ #else # define AC_STRERROR_R(e,b,l) ("Unknown error") #endif #endif /* _AC_STRING_H */ openldap-2.4.42+dfsg/include/ac/syslog.h0000644000175000017500000000210112563404150016521 0ustar ryanryan/* Generic syslog.h */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #ifndef _AC_SYSLOG_H_ #define _AC_SYSLOG_H_ #if defined( HAVE_SYSLOG_H ) #include #elif defined ( HAVE_SYS_SYSLOG_H ) #include #endif #if defined( LOG_NDELAY ) && defined( LOG_NOWAIT ) # define OPENLOG_OPTIONS ( LOG_PID | LOG_NDELAY | LOG_NOWAIT ) #elif defined( LOG_NDELAY ) # define OPENLOG_OPTIONS ( LOG_PID | LOG_NDELAY ) #elif defined( LOG_NOWAIT ) # define OPENLOG_OPTIONS ( LOG_PID | LOG_NOWAIT ) #elif defined( LOG_PID ) # define OPENLOG_OPTIONS ( LOG_PID ) #else # define OPENLOG_OPTIONS ( 0 ) #endif #endif /* _AC_SYSLOG_H_ */ openldap-2.4.42+dfsg/include/ac/unistd.h0000644000175000017500000000334012563404150016515 0ustar ryanryan/* Generic unistd.h */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #ifndef _AC_UNISTD_H #define _AC_UNISTD_H #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_UNISTD_H # include #endif #ifdef HAVE_PROCESS_H # include #endif /* note: callers of crypt(3) should include */ #if defined(HAVE_GETPASSPHRASE) LDAP_LIBC_F(char*)(getpassphrase)(); #else #define getpassphrase(p) lutil_getpass(p) LDAP_LUTIL_F(char*)(lutil_getpass) LDAP_P((const char *getpass)); #endif /* getopt() defines may be in separate include file */ #ifdef HAVE_GETOPT_H # include #elif !defined(HAVE_GETOPT) /* no getopt, assume we need getopt-compat.h */ # include #else /* assume we need to declare these externs */ LDAP_LIBC_V (char *) optarg; LDAP_LIBC_V (int) optind, opterr, optopt; #endif /* use lutil file locking */ #define ldap_lockf(x) lutil_lockf(x) #define ldap_unlockf(x) lutil_unlockf(x) #include /* * Windows: although sleep() will be resolved by both MSVC and Mingw GCC * linkers, the function is not declared in header files. This is * because Windows' version of the function is called _sleep(), and it * is declared in stdlib.h */ #ifdef _WIN32 #define sleep _sleep #endif #endif /* _AC_UNISTD_H */ openldap-2.4.42+dfsg/include/ac/ctype.h0000644000175000017500000000150612563404150016335 0ustar ryanryan/* Generic ctype.h */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #ifndef _AC_CTYPE_H #define _AC_CTYPE_H #include #undef TOUPPER #undef TOLOWER #ifdef C_UPPER_LOWER # define TOUPPER(c) (islower(c) ? toupper(c) : (c)) # define TOLOWER(c) (isupper(c) ? tolower(c) : (c)) #else # define TOUPPER(c) toupper(c) # define TOLOWER(c) tolower(c) #endif #endif /* _AC_CTYPE_H */ openldap-2.4.42+dfsg/include/ac/setproctitle.h0000644000175000017500000000163012563404150017730 0ustar ryanryan/* Generic setproctitle.h */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #ifndef _AC_SETPROCTITLE_H #define _AC_SETPROCTITLE_H #ifdef LDAP_PROCTITLE #if defined( HAVE_LIBUTIL_H ) # include #else /* use lutil version */ LDAP_LUTIL_F (void) (setproctitle) LDAP_P((const char *fmt, ...)) \ LDAP_GCCATTR((format(printf, 1, 2))); LDAP_LUTIL_V (int) Argc; LDAP_LUTIL_V (char) **Argv; #endif #endif /* LDAP_PROCTITLE */ #endif /* _AC_SETPROCTITLE_H */ openldap-2.4.42+dfsg/include/ldap_pvt.h0000644000175000017500000003304412563404150016441 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* ldap-pvt.h - Header for ldap_pvt_ functions. * These are meant to be internal to OpenLDAP Software. */ #ifndef _LDAP_PVT_H #define _LDAP_PVT_H 1 #include /* get ber_slen_t */ #include /* get Sockbuf_Buf */ LDAP_BEGIN_DECL #define LDAP_PROTO_TCP 1 /* ldap:// */ #define LDAP_PROTO_UDP 2 /* reserved */ #define LDAP_PROTO_IPC 3 /* ldapi:// */ #define LDAP_PROTO_EXT 4 /* user-defined socket/sockbuf */ LDAP_F ( int ) ldap_pvt_url_scheme2proto LDAP_P(( const char * )); LDAP_F ( int ) ldap_pvt_url_scheme2tls LDAP_P(( const char * )); LDAP_F ( int ) ldap_pvt_url_scheme_port LDAP_P(( const char *, int )); struct ldap_url_desc; /* avoid pulling in */ #define LDAP_PVT_URL_PARSE_NONE (0x00U) #define LDAP_PVT_URL_PARSE_NOEMPTY_HOST (0x01U) #define LDAP_PVT_URL_PARSE_DEF_PORT (0x02U) #define LDAP_PVT_URL_PARSE_NOEMPTY_DN (0x04U) #define LDAP_PVT_URL_PARSE_NODEF_SCOPE (0x08U) #define LDAP_PVT_URL_PARSE_HISTORIC (LDAP_PVT_URL_PARSE_NODEF_SCOPE | \ LDAP_PVT_URL_PARSE_NOEMPTY_HOST | \ LDAP_PVT_URL_PARSE_DEF_PORT) LDAP_F( int ) ldap_url_parse_ext LDAP_P(( LDAP_CONST char *url, struct ldap_url_desc **ludpp, unsigned flags )); LDAP_F (int) ldap_url_parselist LDAP_P(( /* deprecated, use ldap_url_parselist_ext() */ struct ldap_url_desc **ludlist, const char *url )); LDAP_F (int) ldap_url_parselist_ext LDAP_P(( struct ldap_url_desc **ludlist, const char *url, const char *sep, unsigned flags )); LDAP_F (char *) ldap_url_list2urls LDAP_P(( struct ldap_url_desc *ludlist )); LDAP_F (void) ldap_free_urllist LDAP_P(( struct ldap_url_desc *ludlist )); LDAP_F (int) ldap_pvt_scope2bv LDAP_P (( int scope, struct berval *bv )); LDAP_F (LDAP_CONST char *) ldap_pvt_scope2str LDAP_P (( int scope )); LDAP_F (int) ldap_pvt_bv2scope LDAP_P (( struct berval *bv )); LDAP_F (int) ldap_pvt_str2scope LDAP_P (( LDAP_CONST char * )); LDAP_F( char * ) ldap_pvt_ctime LDAP_P(( const time_t *tp, char *buf )); # if defined( HAVE_GMTIME_R ) # define USE_GMTIME_R # define ldap_pvt_gmtime(timep, result) gmtime_r((timep), (result)) # else LDAP_F( struct tm * ) ldap_pvt_gmtime LDAP_P(( LDAP_CONST time_t *timep, struct tm *result )); #endif # if defined( HAVE_LOCALTIME_R ) # define USE_LOCALTIME_R # define ldap_pvt_localtime(timep, result) localtime_r((timep), (result)) # else LDAP_F( struct tm * ) ldap_pvt_localtime LDAP_P(( LDAP_CONST time_t *timep, struct tm *result )); # endif #if defined( USE_GMTIME_R ) && defined( USE_LOCALTIME_R ) # define ldap_pvt_gmtime_lock() (0) # define ldap_pvt_gmtime_unlock() (0) #else LDAP_F( int ) ldap_pvt_gmtime_lock LDAP_P(( void )); LDAP_F( int ) ldap_pvt_gmtime_unlock LDAP_P(( void )); #endif /* USE_GMTIME_R && USE_LOCALTIME_R */ /* Get current time as a structured time */ struct lutil_tm; LDAP_F( void ) ldap_pvt_gettime LDAP_P(( struct lutil_tm * )); /* use this macro to allocate buffer for ldap_pvt_csnstr */ #define LDAP_PVT_CSNSTR_BUFSIZE 64 LDAP_F( size_t ) ldap_pvt_csnstr( char *buf, size_t len, unsigned int replica, unsigned int mod ); LDAP_F( char *) ldap_pvt_get_fqdn LDAP_P(( char * )); struct hostent; /* avoid pulling in */ LDAP_F( int ) ldap_pvt_gethostbyname_a LDAP_P(( const char *name, struct hostent *resbuf, char **buf, struct hostent **result, int *herrno_ptr )); LDAP_F( int ) ldap_pvt_gethostbyaddr_a LDAP_P(( const char *addr, int len, int type, struct hostent *resbuf, char **buf, struct hostent **result, int *herrno_ptr )); struct sockaddr; LDAP_F( int ) ldap_pvt_get_hname LDAP_P(( const struct sockaddr * sa, int salen, char *name, int namelen, char **herr )); /* charray.c */ LDAP_F( int ) ldap_charray_add LDAP_P(( char ***a, const char *s )); LDAP_F( int ) ldap_charray_merge LDAP_P(( char ***a, char **s )); LDAP_F( void ) ldap_charray_free LDAP_P(( char **a )); LDAP_F( int ) ldap_charray_inlist LDAP_P(( char **a, const char *s )); LDAP_F( char ** ) ldap_charray_dup LDAP_P(( char **a )); LDAP_F( char ** ) ldap_str2charray LDAP_P(( const char *str, const char *brkstr )); LDAP_F( char * ) ldap_charray2str LDAP_P(( char **array, const char* sep )); /* getdn.c */ #ifdef LDAP_AVA_NULL /* in ldap.h */ LDAP_F( void ) ldap_rdnfree_x LDAP_P(( LDAPRDN rdn, void *ctx )); LDAP_F( void ) ldap_dnfree_x LDAP_P(( LDAPDN dn, void *ctx )); LDAP_F( int ) ldap_bv2dn_x LDAP_P(( struct berval *bv, LDAPDN *dn, unsigned flags, void *ctx )); LDAP_F( int ) ldap_dn2bv_x LDAP_P(( LDAPDN dn, struct berval *bv, unsigned flags, void *ctx )); LDAP_F( int ) ldap_bv2rdn_x LDAP_P(( struct berval *, LDAPRDN *, char **, unsigned flags, void *ctx )); LDAP_F( int ) ldap_rdn2bv_x LDAP_P(( LDAPRDN rdn, struct berval *bv, unsigned flags, void *ctx )); #endif /* LDAP_AVA_NULL */ /* url.c */ LDAP_F (void) ldap_pvt_hex_unescape LDAP_P(( char *s )); /* * these macros assume 'x' is an ASCII x * and assume the "C" locale */ #define LDAP_ASCII(c) (!((c) & 0x80)) #define LDAP_SPACE(c) ((c) == ' ' || (c) == '\t' || (c) == '\n') #define LDAP_DIGIT(c) ((c) >= '0' && (c) <= '9') #define LDAP_LOWER(c) ((c) >= 'a' && (c) <= 'z') #define LDAP_UPPER(c) ((c) >= 'A' && (c) <= 'Z') #define LDAP_ALPHA(c) (LDAP_LOWER(c) || LDAP_UPPER(c)) #define LDAP_ALNUM(c) (LDAP_ALPHA(c) || LDAP_DIGIT(c)) #define LDAP_LDH(c) (LDAP_ALNUM(c) || (c) == '-') #define LDAP_HEXLOWER(c) ((c) >= 'a' && (c) <= 'f') #define LDAP_HEXUPPER(c) ((c) >= 'A' && (c) <= 'F') #define LDAP_HEX(c) (LDAP_DIGIT(c) || \ LDAP_HEXLOWER(c) || LDAP_HEXUPPER(c)) /* controls.c */ struct ldapcontrol; LDAP_F (int) ldap_pvt_put_control LDAP_P(( const struct ldapcontrol *c, BerElement *ber )); LDAP_F (int) ldap_pvt_get_controls LDAP_P(( BerElement *be, struct ldapcontrol ***ctrlsp)); #ifdef HAVE_CYRUS_SASL /* cyrus.c */ struct sasl_security_properties; /* avoid pulling in */ LDAP_F (int) ldap_pvt_sasl_secprops LDAP_P(( const char *in, struct sasl_security_properties *secprops )); LDAP_F (void) ldap_pvt_sasl_secprops_unparse LDAP_P(( struct sasl_security_properties *secprops, struct berval *out )); LDAP_F (void *) ldap_pvt_sasl_mutex_new LDAP_P((void)); LDAP_F (int) ldap_pvt_sasl_mutex_lock LDAP_P((void *mutex)); LDAP_F (int) ldap_pvt_sasl_mutex_unlock LDAP_P((void *mutex)); LDAP_F (void) ldap_pvt_sasl_mutex_dispose LDAP_P((void *mutex)); #endif /* HAVE_CYRUS_SASL */ struct sockbuf; /* avoid pulling in */ LDAP_F (int) ldap_pvt_sasl_install LDAP_P(( struct sockbuf *, void * )); LDAP_F (void) ldap_pvt_sasl_remove LDAP_P(( struct sockbuf * )); /* * SASL encryption support for LBER Sockbufs */ struct sb_sasl_generic_data; struct sb_sasl_generic_ops { void (*init)(struct sb_sasl_generic_data *p, ber_len_t *min_send, ber_len_t *max_send, ber_len_t *max_recv); ber_int_t (*encode)(struct sb_sasl_generic_data *p, unsigned char *buf, ber_len_t len, Sockbuf_Buf *dst); ber_int_t (*decode)(struct sb_sasl_generic_data *p, const Sockbuf_Buf *src, Sockbuf_Buf *dst); void (*reset_buf)(struct sb_sasl_generic_data *p, Sockbuf_Buf *buf); void (*fini)(struct sb_sasl_generic_data *p); }; struct sb_sasl_generic_install { const struct sb_sasl_generic_ops *ops; void *ops_private; }; struct sb_sasl_generic_data { const struct sb_sasl_generic_ops *ops; void *ops_private; Sockbuf_IO_Desc *sbiod; ber_len_t min_send; ber_len_t max_send; ber_len_t max_recv; Sockbuf_Buf sec_buf_in; Sockbuf_Buf buf_in; Sockbuf_Buf buf_out; unsigned int flags; #define LDAP_PVT_SASL_PARTIAL_WRITE 1 }; #ifndef LDAP_PVT_SASL_LOCAL_SSF #define LDAP_PVT_SASL_LOCAL_SSF 71 /* SSF for Unix Domain Sockets */ #endif /* ! LDAP_PVT_SASL_LOCAL_SSF */ struct ldap; struct ldapmsg; /* abandon */ LDAP_F ( int ) ldap_pvt_discard LDAP_P(( struct ldap *ld, ber_int_t msgid )); /* messages.c */ LDAP_F( BerElement * ) ldap_get_message_ber LDAP_P(( struct ldapmsg * )); /* open */ LDAP_F (int) ldap_open_internal_connection LDAP_P(( struct ldap **ldp, ber_socket_t *fdp )); LDAP_F (int) ldap_init_fd LDAP_P(( ber_socket_t fd, int proto, LDAP_CONST char *url, struct ldap **ldp )); /* sasl.c */ LDAP_F (int) ldap_pvt_sasl_generic_install LDAP_P(( Sockbuf *sb, struct sb_sasl_generic_install *install_arg )); LDAP_F (void) ldap_pvt_sasl_generic_remove LDAP_P(( Sockbuf *sb )); /* search.c */ LDAP_F( int ) ldap_pvt_put_filter LDAP_P(( BerElement *ber, const char *str )); LDAP_F( char * ) ldap_pvt_find_wildcard LDAP_P(( const char *s )); LDAP_F( ber_slen_t ) ldap_pvt_filter_value_unescape LDAP_P(( char *filter )); LDAP_F( ber_len_t ) ldap_bv2escaped_filter_value_len LDAP_P(( struct berval *in )); LDAP_F( int ) ldap_bv2escaped_filter_value_x LDAP_P(( struct berval *in, struct berval *out, int inplace, void *ctx )); LDAP_F (int) ldap_pvt_search LDAP_P(( struct ldap *ld, LDAP_CONST char *base, int scope, LDAP_CONST char *filter, char **attrs, int attrsonly, struct ldapcontrol **sctrls, struct ldapcontrol **cctrls, struct timeval *timeout, int sizelimit, int deref, int *msgidp )); LDAP_F(int) ldap_pvt_search_s LDAP_P(( struct ldap *ld, LDAP_CONST char *base, int scope, LDAP_CONST char *filter, char **attrs, int attrsonly, struct ldapcontrol **sctrls, struct ldapcontrol **cctrls, struct timeval *timeout, int sizelimit, int deref, struct ldapmsg **res )); /* string.c */ LDAP_F( char * ) ldap_pvt_str2upper LDAP_P(( char *str )); LDAP_F( char * ) ldap_pvt_str2lower LDAP_P(( char *str )); LDAP_F( struct berval * ) ldap_pvt_str2upperbv LDAP_P(( char *str, struct berval *bv )); LDAP_F( struct berval * ) ldap_pvt_str2lowerbv LDAP_P(( char *str, struct berval *bv )); /* tls.c */ LDAP_F (int) ldap_int_tls_config LDAP_P(( struct ldap *ld, int option, const char *arg )); LDAP_F (int) ldap_pvt_tls_get_option LDAP_P(( struct ldap *ld, int option, void *arg )); LDAP_F (int) ldap_pvt_tls_set_option LDAP_P(( struct ldap *ld, int option, void *arg )); LDAP_F (void) ldap_pvt_tls_destroy LDAP_P(( void )); LDAP_F (int) ldap_pvt_tls_init LDAP_P(( void )); LDAP_F (int) ldap_pvt_tls_init_def_ctx LDAP_P(( int is_server )); LDAP_F (int) ldap_pvt_tls_accept LDAP_P(( Sockbuf *sb, void *ctx_arg )); LDAP_F (int) ldap_pvt_tls_inplace LDAP_P(( Sockbuf *sb )); LDAP_F (void *) ldap_pvt_tls_sb_ctx LDAP_P(( Sockbuf *sb )); LDAP_F (void) ldap_pvt_tls_ctx_free LDAP_P(( void * )); typedef int LDAPDN_rewrite_dummy LDAP_P (( void *dn, unsigned flags )); typedef int (LDAP_TLS_CONNECT_CB) LDAP_P (( struct ldap *ld, void *ssl, void *ctx, void *arg )); LDAP_F (int) ldap_pvt_tls_get_my_dn LDAP_P(( void *ctx, struct berval *dn, LDAPDN_rewrite_dummy *func, unsigned flags )); LDAP_F (int) ldap_pvt_tls_get_peer_dn LDAP_P(( void *ctx, struct berval *dn, LDAPDN_rewrite_dummy *func, unsigned flags )); LDAP_F (int) ldap_pvt_tls_get_strength LDAP_P(( void *ctx )); LDAP_END_DECL /* * Multiple precision stuff * * May use OpenSSL's BIGNUM if built with TLS, * or GNU's multiple precision library. But if * long long is available, that's big enough * and much more efficient. * * If none is available, unsigned long data is used. */ LDAP_BEGIN_DECL #ifdef USE_MP_BIGNUM /* * Use OpenSSL's BIGNUM */ #include #include typedef BIGNUM* ldap_pvt_mp_t; #define LDAP_PVT_MP_INIT (NULL) #define ldap_pvt_mp_init(mp) \ do { (mp) = BN_new(); } while (0) /* FIXME: we rely on mpr being initialized */ #define ldap_pvt_mp_init_set(mpr,mpv) \ do { ldap_pvt_mp_init((mpr)); BN_add((mpr), (mpr), (mpv)); } while (0) #define ldap_pvt_mp_add(mpr,mpv) \ BN_add((mpr), (mpr), (mpv)) #define ldap_pvt_mp_add_ulong(mp,v) \ BN_add_word((mp), (v)) #define ldap_pvt_mp_clear(mp) \ do { BN_free((mp)); (mp) = 0; } while (0) #elif defined(USE_MP_GMP) /* * Use GNU's multiple precision library */ #include typedef mpz_t ldap_pvt_mp_t; #define LDAP_PVT_MP_INIT { 0 } #define ldap_pvt_mp_init(mp) \ mpz_init((mp)) #define ldap_pvt_mp_init_set(mpr,mpv) \ mpz_init_set((mpr), (mpv)) #define ldap_pvt_mp_add(mpr,mpv) \ mpz_add((mpr), (mpr), (mpv)) #define ldap_pvt_mp_add_ulong(mp,v) \ mpz_add_ui((mp), (mp), (v)) #define ldap_pvt_mp_clear(mp) \ mpz_clear((mp)) #else /* * Use unsigned long long */ #ifdef USE_MP_LONG_LONG typedef unsigned long long ldap_pvt_mp_t; #define LDAP_PVT_MP_INIT (0LL) #elif defined(USE_MP_LONG) typedef unsigned long ldap_pvt_mp_t; #define LDAP_PVT_MP_INIT (0L) #elif defined(HAVE_LONG_LONG) typedef unsigned long long ldap_pvt_mp_t; #define LDAP_PVT_MP_INIT (0LL) #else typedef unsigned long ldap_pvt_mp_t; #define LDAP_PVT_MP_INIT (0L) #endif #define ldap_pvt_mp_init(mp) \ do { (mp) = 0; } while (0) #define ldap_pvt_mp_init_set(mpr,mpv) \ do { (mpr) = (mpv); } while (0) #define ldap_pvt_mp_add(mpr,mpv) \ do { (mpr) += (mpv); } while (0) #define ldap_pvt_mp_add_ulong(mp,v) \ do { (mp) += (v); } while (0) #define ldap_pvt_mp_clear(mp) \ do { (mp) = 0; } while (0) #endif /* MP */ #include "ldap_pvt_uc.h" LDAP_END_DECL LDAP_BEGIN_DECL #include /* get CHAR_BIT */ /* Buffer space for sign, decimal digits and \0. Note: log10(2) < 146/485. */ #define LDAP_PVT_INTTYPE_CHARS(type) (((sizeof(type)*CHAR_BIT-1)*146)/485 + 3) LDAP_END_DECL #endif /* _LDAP_PVT_H */ openldap-2.4.42+dfsg/include/lber_types.hin0000644000175000017500000000253412563404150017327 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* * LBER types */ #ifndef _LBER_TYPES_H #define _LBER_TYPES_H #include LDAP_BEGIN_DECL /* LBER boolean, enum, integers (32 bits or larger) */ #undef LBER_INT_T /* LBER tags (32 bits or larger) */ #undef LBER_TAG_T /* LBER socket descriptor */ #undef LBER_SOCKET_T /* LBER lengths (32 bits or larger) */ #undef LBER_LEN_T /* ------------------------------------------------------------ */ /* booleans, enumerations, and integers */ typedef LBER_INT_T ber_int_t; /* signed and unsigned versions */ typedef signed LBER_INT_T ber_sint_t; typedef unsigned LBER_INT_T ber_uint_t; /* tags */ typedef unsigned LBER_TAG_T ber_tag_t; /* "socket" descriptors */ typedef LBER_SOCKET_T ber_socket_t; /* lengths */ typedef unsigned LBER_LEN_T ber_len_t; /* signed lengths */ typedef signed LBER_LEN_T ber_slen_t; LDAP_END_DECL #endif /* _LBER_TYPES_H */ openldap-2.4.42+dfsg/include/ldap_pvt_thread.h0000644000175000017500000002134512563404150017771 0ustar ryanryan/* ldap_pvt_thread.h - ldap threads header file */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #ifndef _LDAP_PVT_THREAD_H #define _LDAP_PVT_THREAD_H /* libldap_r/ldap_thr_debug.h #undefines this */ #include "ldap_cdefs.h" #include "ldap_int_thread.h" LDAP_BEGIN_DECL #ifndef LDAP_PVT_THREAD_H_DONE typedef ldap_int_thread_t ldap_pvt_thread_t; #ifdef LDAP_THREAD_DEBUG_WRAP typedef ldap_debug_thread_mutex_t ldap_pvt_thread_mutex_t; typedef ldap_debug_thread_cond_t ldap_pvt_thread_cond_t; typedef ldap_debug_thread_rdwr_t ldap_pvt_thread_rdwr_t; #define LDAP_PVT_MUTEX_FIRSTCREATE LDAP_DEBUG_MUTEX_FIRSTCREATE #define LDAP_PVT_MUTEX_NULL LDAP_DEBUG_MUTEX_NULL #else typedef ldap_int_thread_mutex_t ldap_pvt_thread_mutex_t; typedef ldap_int_thread_cond_t ldap_pvt_thread_cond_t; typedef ldap_int_thread_rdwr_t ldap_pvt_thread_rdwr_t; #define LDAP_PVT_MUTEX_FIRSTCREATE LDAP_INT_MUTEX_FIRSTCREATE #define LDAP_PVT_MUTEX_NULL LDAP_INT_MUTEX_NULL #endif typedef ldap_int_thread_rmutex_t ldap_pvt_thread_rmutex_t; typedef ldap_int_thread_key_t ldap_pvt_thread_key_t; #endif /* !LDAP_PVT_THREAD_H_DONE */ #define ldap_pvt_thread_equal ldap_int_thread_equal LDAP_F( int ) ldap_pvt_thread_initialize LDAP_P(( void )); LDAP_F( int ) ldap_pvt_thread_destroy LDAP_P(( void )); LDAP_F( unsigned int ) ldap_pvt_thread_sleep LDAP_P(( unsigned int s )); LDAP_F( int ) ldap_pvt_thread_get_concurrency LDAP_P(( void )); LDAP_F( int ) ldap_pvt_thread_set_concurrency LDAP_P(( int )); #define LDAP_PVT_THREAD_CREATE_JOINABLE 0 #define LDAP_PVT_THREAD_CREATE_DETACHED 1 #ifndef LDAP_PVT_THREAD_H_DONE #define LDAP_PVT_THREAD_SET_STACK_SIZE /* The size may be explicitly #defined to zero to disable it. */ #if defined( LDAP_PVT_THREAD_STACK_SIZE ) && LDAP_PVT_THREAD_STACK_SIZE == 0 # undef LDAP_PVT_THREAD_SET_STACK_SIZE #elif !defined( LDAP_PVT_THREAD_STACK_SIZE ) /* LARGE stack. Will be twice as large on 64 bit machine. */ # define LDAP_PVT_THREAD_STACK_SIZE ( 1 * 1024 * 1024 * sizeof(void *) ) #endif #endif /* !LDAP_PVT_THREAD_H_DONE */ LDAP_F( int ) ldap_pvt_thread_create LDAP_P(( ldap_pvt_thread_t * thread, int detach, void *(*start_routine)( void * ), void *arg)); LDAP_F( void ) ldap_pvt_thread_exit LDAP_P(( void *retval )); LDAP_F( int ) ldap_pvt_thread_join LDAP_P(( ldap_pvt_thread_t thread, void **status )); LDAP_F( int ) ldap_pvt_thread_kill LDAP_P(( ldap_pvt_thread_t thread, int signo )); LDAP_F( int ) ldap_pvt_thread_yield LDAP_P(( void )); LDAP_F( int ) ldap_pvt_thread_cond_init LDAP_P(( ldap_pvt_thread_cond_t *cond )); LDAP_F( int ) ldap_pvt_thread_cond_destroy LDAP_P(( ldap_pvt_thread_cond_t *cond )); LDAP_F( int ) ldap_pvt_thread_cond_signal LDAP_P(( ldap_pvt_thread_cond_t *cond )); LDAP_F( int ) ldap_pvt_thread_cond_broadcast LDAP_P(( ldap_pvt_thread_cond_t *cond )); LDAP_F( int ) ldap_pvt_thread_cond_wait LDAP_P(( ldap_pvt_thread_cond_t *cond, ldap_pvt_thread_mutex_t *mutex )); LDAP_F( int ) ldap_pvt_thread_mutex_init LDAP_P(( ldap_pvt_thread_mutex_t *mutex )); LDAP_F( int ) ldap_pvt_thread_mutex_destroy LDAP_P(( ldap_pvt_thread_mutex_t *mutex )); LDAP_F( int ) ldap_pvt_thread_mutex_lock LDAP_P(( ldap_pvt_thread_mutex_t *mutex )); LDAP_F( int ) ldap_pvt_thread_mutex_trylock LDAP_P(( ldap_pvt_thread_mutex_t *mutex )); LDAP_F( int ) ldap_pvt_thread_mutex_unlock LDAP_P(( ldap_pvt_thread_mutex_t *mutex )); LDAP_F( int ) ldap_pvt_thread_rmutex_init LDAP_P(( ldap_pvt_thread_rmutex_t *rmutex )); LDAP_F( int ) ldap_pvt_thread_rmutex_destroy LDAP_P(( ldap_pvt_thread_rmutex_t *rmutex )); LDAP_F( int ) ldap_pvt_thread_rmutex_lock LDAP_P(( ldap_pvt_thread_rmutex_t *rmutex, ldap_pvt_thread_t owner)); LDAP_F( int ) ldap_pvt_thread_rmutex_trylock LDAP_P(( ldap_pvt_thread_rmutex_t *rmutex, ldap_pvt_thread_t owner)); LDAP_F( int ) ldap_pvt_thread_rmutex_unlock LDAP_P(( ldap_pvt_thread_rmutex_t *rmutex, ldap_pvt_thread_t owner)); LDAP_F( ldap_pvt_thread_t ) ldap_pvt_thread_self LDAP_P(( void )); #ifdef LDAP_INT_THREAD_ASSERT_MUTEX_OWNER #define LDAP_PVT_THREAD_ASSERT_MUTEX_OWNER LDAP_INT_THREAD_ASSERT_MUTEX_OWNER #else #define LDAP_PVT_THREAD_ASSERT_MUTEX_OWNER(mutex) ((void) 0) #endif LDAP_F( int ) ldap_pvt_thread_rdwr_init LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp)); LDAP_F( int ) ldap_pvt_thread_rdwr_destroy LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp)); LDAP_F( int ) ldap_pvt_thread_rdwr_rlock LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp)); LDAP_F( int ) ldap_pvt_thread_rdwr_rtrylock LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp)); LDAP_F( int ) ldap_pvt_thread_rdwr_runlock LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp)); LDAP_F( int ) ldap_pvt_thread_rdwr_wlock LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp)); LDAP_F( int ) ldap_pvt_thread_rdwr_wtrylock LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp)); LDAP_F( int ) ldap_pvt_thread_rdwr_wunlock LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp)); LDAP_F( int ) ldap_pvt_thread_key_create LDAP_P((ldap_pvt_thread_key_t *keyp)); LDAP_F( int ) ldap_pvt_thread_key_destroy LDAP_P((ldap_pvt_thread_key_t key)); LDAP_F( int ) ldap_pvt_thread_key_setdata LDAP_P((ldap_pvt_thread_key_t key, void *data)); LDAP_F( int ) ldap_pvt_thread_key_getdata LDAP_P((ldap_pvt_thread_key_t key, void **data)); #ifdef LDAP_DEBUG LDAP_F( int ) ldap_pvt_thread_rdwr_readers LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp)); LDAP_F( int ) ldap_pvt_thread_rdwr_writers LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp)); LDAP_F( int ) ldap_pvt_thread_rdwr_active LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp)); #endif /* LDAP_DEBUG */ #define LDAP_PVT_THREAD_EINVAL EINVAL #define LDAP_PVT_THREAD_EBUSY EINVAL #ifndef LDAP_PVT_THREAD_H_DONE typedef ldap_int_thread_pool_t ldap_pvt_thread_pool_t; typedef void * (ldap_pvt_thread_start_t) LDAP_P((void *ctx, void *arg)); typedef void (ldap_pvt_thread_pool_keyfree_t) LDAP_P((void *key, void *data)); #endif /* !LDAP_PVT_THREAD_H_DONE */ LDAP_F( int ) ldap_pvt_thread_pool_init LDAP_P(( ldap_pvt_thread_pool_t *pool_out, int max_threads, int max_pending )); LDAP_F( int ) ldap_pvt_thread_pool_submit LDAP_P(( ldap_pvt_thread_pool_t *pool, ldap_pvt_thread_start_t *start, void *arg )); LDAP_F( int ) ldap_pvt_thread_pool_retract LDAP_P(( ldap_pvt_thread_pool_t *pool, ldap_pvt_thread_start_t *start, void *arg )); LDAP_F( int ) ldap_pvt_thread_pool_maxthreads LDAP_P(( ldap_pvt_thread_pool_t *pool, int max_threads )); #ifndef LDAP_PVT_THREAD_H_DONE typedef enum { LDAP_PVT_THREAD_POOL_PARAM_UNKNOWN = -1, LDAP_PVT_THREAD_POOL_PARAM_MAX, LDAP_PVT_THREAD_POOL_PARAM_MAX_PENDING, LDAP_PVT_THREAD_POOL_PARAM_OPEN, LDAP_PVT_THREAD_POOL_PARAM_STARTING, LDAP_PVT_THREAD_POOL_PARAM_ACTIVE, LDAP_PVT_THREAD_POOL_PARAM_PAUSING, LDAP_PVT_THREAD_POOL_PARAM_PENDING, LDAP_PVT_THREAD_POOL_PARAM_BACKLOAD, LDAP_PVT_THREAD_POOL_PARAM_ACTIVE_MAX, LDAP_PVT_THREAD_POOL_PARAM_PENDING_MAX, LDAP_PVT_THREAD_POOL_PARAM_BACKLOAD_MAX, LDAP_PVT_THREAD_POOL_PARAM_STATE } ldap_pvt_thread_pool_param_t; #endif /* !LDAP_PVT_THREAD_H_DONE */ LDAP_F( int ) ldap_pvt_thread_pool_query LDAP_P(( ldap_pvt_thread_pool_t *pool, ldap_pvt_thread_pool_param_t param, void *value )); LDAP_F( int ) ldap_pvt_thread_pool_pausing LDAP_P(( ldap_pvt_thread_pool_t *pool )); LDAP_F( int ) ldap_pvt_thread_pool_backload LDAP_P(( ldap_pvt_thread_pool_t *pool )); LDAP_F( void ) ldap_pvt_thread_pool_idle LDAP_P(( ldap_pvt_thread_pool_t *pool )); LDAP_F( void ) ldap_pvt_thread_pool_unidle LDAP_P(( ldap_pvt_thread_pool_t *pool )); LDAP_F( int ) ldap_pvt_thread_pool_pausecheck LDAP_P(( ldap_pvt_thread_pool_t *pool )); LDAP_F( int ) ldap_pvt_thread_pool_pause LDAP_P(( ldap_pvt_thread_pool_t *pool )); LDAP_F( int ) ldap_pvt_thread_pool_resume LDAP_P(( ldap_pvt_thread_pool_t *pool )); LDAP_F( int ) ldap_pvt_thread_pool_destroy LDAP_P(( ldap_pvt_thread_pool_t *pool, int run_pending )); LDAP_F( int ) ldap_pvt_thread_pool_getkey LDAP_P(( void *ctx, void *key, void **data, ldap_pvt_thread_pool_keyfree_t **kfree )); LDAP_F( int ) ldap_pvt_thread_pool_setkey LDAP_P(( void *ctx, void *key, void *data, ldap_pvt_thread_pool_keyfree_t *kfree, void **olddatap, ldap_pvt_thread_pool_keyfree_t **oldkfreep )); LDAP_F( void ) ldap_pvt_thread_pool_purgekey LDAP_P(( void *key )); LDAP_F( void *) ldap_pvt_thread_pool_context LDAP_P(( void )); LDAP_F( void ) ldap_pvt_thread_pool_context_reset LDAP_P(( void *key )); LDAP_F( ldap_pvt_thread_t ) ldap_pvt_thread_pool_tid LDAP_P(( void *ctx )); LDAP_END_DECL #define LDAP_PVT_THREAD_H_DONE #endif /* _LDAP_PVT_THREAD_H */ openldap-2.4.42+dfsg/include/ldap_cdefs.h0000644000175000017500000002237212563404150016716 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* LDAP C Defines */ #ifndef _LDAP_CDEFS_H #define _LDAP_CDEFS_H #if defined(__cplusplus) || defined(c_plusplus) # define LDAP_BEGIN_DECL extern "C" { # define LDAP_END_DECL } #else # define LDAP_BEGIN_DECL /* begin declarations */ # define LDAP_END_DECL /* end declarations */ #endif #if !defined(LDAP_NO_PROTOTYPES) && ( defined(LDAP_NEEDS_PROTOTYPES) || \ defined(__STDC__) || defined(__cplusplus) || defined(c_plusplus) ) /* ANSI C or C++ */ # define LDAP_P(protos) protos # define LDAP_CONCAT1(x,y) x ## y # define LDAP_CONCAT(x,y) LDAP_CONCAT1(x,y) # define LDAP_STRING(x) #x /* stringify without expanding x */ # define LDAP_XSTRING(x) LDAP_STRING(x) /* expand x, then stringify */ #ifndef LDAP_CONST # define LDAP_CONST const #endif #else /* no prototypes */ /* traditional C */ # define LDAP_P(protos) () # define LDAP_CONCAT(x,y) x/**/y # define LDAP_STRING(x) "x" #ifndef LDAP_CONST # define LDAP_CONST /* no const */ #endif #endif /* no prototypes */ #if (__GNUC__) * 1000 + (__GNUC_MINOR__) >= 2006 # define LDAP_GCCATTR(attrs) __attribute__(attrs) #else # define LDAP_GCCATTR(attrs) #endif /* * Support for Windows DLLs. * * When external source code includes header files for dynamic libraries, * the external source code is "importing" DLL symbols into its resulting * object code. On Windows, symbols imported from DLLs must be explicitly * indicated in header files with the __declspec(dllimport) directive. * This is not totally necessary for functions because the compiler * (gcc or MSVC) will generate stubs when this directive is absent. * However, this is required for imported variables. * * The LDAP libraries, i.e. liblber and libldap, can be built as * static or shared, based on configuration. Just about all other source * code in OpenLDAP use these libraries. If the LDAP libraries * are configured as shared, 'configure' defines the LDAP_LIBS_DYNAMIC * macro. When other source files include LDAP library headers, the * LDAP library symbols will automatically be marked as imported. When * the actual LDAP libraries are being built, the symbols will not * be marked as imported because the LBER_LIBRARY or LDAP_LIBRARY macros * will be respectively defined. * * Any project outside of OpenLDAP with source code wanting to use * LDAP dynamic libraries should explicitly define LDAP_LIBS_DYNAMIC. * This will ensure that external source code appropriately marks symbols * that will be imported. * * The slapd executable, itself, can be used as a dynamic library. * For example, if a backend module is compiled as shared, it will * import symbols from slapd. When this happens, the slapd symbols * must be marked as imported in header files that the backend module * includes. Remember that slapd links with various static libraries. * If the LDAP libraries were configured as static, their object * code is also part of the monolithic slapd executable. Thus, when * a backend module imports symbols from slapd, it imports symbols from * all of the static libraries in slapd as well. Thus, the SLAP_IMPORT * macro, when defined, will appropriately mark symbols as imported. * This macro should be used by shared backend modules as well as any * other external source code that imports symbols from the slapd * executable as if it were a DLL. * * Note that we don't actually have to worry about using the * __declspec(dllexport) directive anywhere. This is because both * MSVC and Mingw provide alternate (more effective) methods for exporting * symbols out of binaries, i.e. the use of a DEF file. * * NOTE ABOUT BACKENDS: Backends can be configured as static or dynamic. * When a backend is configured as dynamic, slapd will load the backend * explicitly and populate function pointer structures by calling * the backend's well-known initialization function. Because of this * procedure, slapd never implicitly imports symbols from dynamic backends. * This makes it unnecessary to tag various backend functions with the * __declspec(dllimport) directive. This is because neither slapd nor * any other external binary should ever be implicitly loading a backend * dynamic module. * * Backends are supposed to be self-contained. However, it appears that * back-meta DOES implicitly import symbols from back-ldap. This means * that the __declspec(dllimport) directive should be marked on back-ldap * functions (in its header files) if and only if we're compiling for * windows AND back-ldap has been configured as dynamic AND back-meta * is the client of back-ldap. When client is slapd, there is no effect * since slapd does not implicitly import symbols. * * TODO(?): Currently, back-meta nor back-ldap is supported for Mingw32. * Thus, there's no need to worry about this right now. This is something that * may or may not have to be addressed in the future. */ /* LBER library */ #if defined(_WIN32) && \ ((defined(LDAP_LIBS_DYNAMIC) && !defined(LBER_LIBRARY)) || \ (!defined(LDAP_LIBS_DYNAMIC) && defined(SLAPD_IMPORT))) # define LBER_F(type) extern __declspec(dllimport) type # define LBER_V(type) extern __declspec(dllimport) type #else # define LBER_F(type) extern type # define LBER_V(type) extern type #endif /* LDAP library */ #if defined(_WIN32) && \ ((defined(LDAP_LIBS_DYNAMIC) && !defined(LDAP_LIBRARY)) || \ (!defined(LDAP_LIBS_DYNAMIC) && defined(SLAPD_IMPORT))) # define LDAP_F(type) extern __declspec(dllimport) type # define LDAP_V(type) extern __declspec(dllimport) type #else # define LDAP_F(type) extern type # define LDAP_V(type) extern type #endif /* AVL library */ #if defined(_WIN32) && defined(SLAPD_IMPORT) # define LDAP_AVL_F(type) extern __declspec(dllimport) type # define LDAP_AVL_V(type) extern __declspec(dllimport) type #else # define LDAP_AVL_F(type) extern type # define LDAP_AVL_V(type) extern type #endif /* LDIF library */ #if defined(_WIN32) && defined(SLAPD_IMPORT) # define LDAP_LDIF_F(type) extern __declspec(dllimport) type # define LDAP_LDIF_V(type) extern __declspec(dllimport) type #else # define LDAP_LDIF_F(type) extern type # define LDAP_LDIF_V(type) extern type #endif /* LUNICODE library */ #if defined(_WIN32) && defined(SLAPD_IMPORT) # define LDAP_LUNICODE_F(type) extern __declspec(dllimport) type # define LDAP_LUNICODE_V(type) extern __declspec(dllimport) type #else # define LDAP_LUNICODE_F(type) extern type # define LDAP_LUNICODE_V(type) extern type #endif /* LUTIL library */ #if defined(_WIN32) && defined(SLAPD_IMPORT) # define LDAP_LUTIL_F(type) extern __declspec(dllimport) type # define LDAP_LUTIL_V(type) extern __declspec(dllimport) type #else # define LDAP_LUTIL_F(type) extern type # define LDAP_LUTIL_V(type) extern type #endif /* REWRITE library */ #if defined(_WIN32) && defined(SLAPD_IMPORT) # define LDAP_REWRITE_F(type) extern __declspec(dllimport) type # define LDAP_REWRITE_V(type) extern __declspec(dllimport) type #else # define LDAP_REWRITE_F(type) extern type # define LDAP_REWRITE_V(type) extern type #endif /* SLAPD (as a dynamic library exporting symbols) */ #if defined(_WIN32) && defined(SLAPD_IMPORT) # define LDAP_SLAPD_F(type) extern __declspec(dllimport) type # define LDAP_SLAPD_V(type) extern __declspec(dllimport) type #else # define LDAP_SLAPD_F(type) extern type # define LDAP_SLAPD_V(type) extern type #endif /* SLAPD (as a dynamic library exporting symbols) */ #if defined(_WIN32) && defined(SLAPD_IMPORT) # define LDAP_SLAPI_F(type) extern __declspec(dllimport) type # define LDAP_SLAPI_V(type) extern __declspec(dllimport) type #else # define LDAP_SLAPI_F(type) extern type # define LDAP_SLAPI_V(type) extern type #endif /* SLAPD (as a dynamic library exporting symbols) */ #if defined(_WIN32) && defined(SLAPD_IMPORT) # define SLAPI_F(type) extern __declspec(dllimport) type # define SLAPI_V(type) extern __declspec(dllimport) type #else # define SLAPI_F(type) extern type # define SLAPI_V(type) extern type #endif /* * C library. Mingw32 links with the dynamic C run-time library by default, * so the explicit definition of CSTATIC will keep dllimport from * being defined, if desired. * * MSVC defines the _DLL macro when the compiler is invoked with /MD or /MDd, * which means the resulting object code will be linked with the dynamic * C run-time library. * * Technically, it shouldn't be necessary to redefine any functions that * the headers for the C library should already contain. Nevertheless, this * is here as a safe-guard. * * TODO: Determine if these macros ever get expanded for Windows. If not, * the declspec expansion can probably be removed. */ #if (defined(__MINGW32__) && !defined(CSTATIC)) || \ (defined(_MSC_VER) && defined(_DLL)) # define LDAP_LIBC_F(type) extern __declspec(dllimport) type # define LDAP_LIBC_V(type) extern __declspec(dllimport) type #else # define LDAP_LIBC_F(type) extern type # define LDAP_LIBC_V(type) extern type #endif #endif /* _LDAP_CDEFS_H */ openldap-2.4.42+dfsg/include/ldap_rq.h0000644000175000017500000000363112563404150016251 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #ifndef LDAP_RQ_H #define LDAP_RQ_H 1 #include LDAP_BEGIN_DECL typedef struct re_s { struct timeval next_sched; struct timeval interval; LDAP_STAILQ_ENTRY(re_s) tnext; /* it includes running */ LDAP_STAILQ_ENTRY(re_s) rnext; ldap_pvt_thread_start_t *routine; void *arg; char *tname; char *tspec; } re_t; typedef struct runqueue_s { LDAP_STAILQ_HEAD(l, re_s) task_list; LDAP_STAILQ_HEAD(rl, re_s) run_list; ldap_pvt_thread_mutex_t rq_mutex; } runqueue_t; LDAP_F( struct re_s* ) ldap_pvt_runqueue_insert( struct runqueue_s* rq, time_t interval, ldap_pvt_thread_start_t* routine, void *arg, char *tname, char *tspec ); LDAP_F( struct re_s* ) ldap_pvt_runqueue_find( struct runqueue_s* rq, ldap_pvt_thread_start_t* routine, void *arg ); LDAP_F( void ) ldap_pvt_runqueue_remove( struct runqueue_s* rq, struct re_s* entry ); LDAP_F( struct re_s* ) ldap_pvt_runqueue_next_sched( struct runqueue_s* rq, struct timeval* next_run ); LDAP_F( void ) ldap_pvt_runqueue_runtask( struct runqueue_s* rq, struct re_s* entry ); LDAP_F( void ) ldap_pvt_runqueue_stoptask( struct runqueue_s* rq, struct re_s* entry ); LDAP_F( int ) ldap_pvt_runqueue_isrunning( struct runqueue_s* rq, struct re_s* entry ); LDAP_F( void ) ldap_pvt_runqueue_resched( struct runqueue_s* rq, struct re_s* entry, int defer ); LDAP_F( int ) ldap_pvt_runqueue_persistent_backload( struct runqueue_s* rq ); LDAP_END_DECL #endif openldap-2.4.42+dfsg/include/ldap_features.hin0000644000175000017500000000325412563404150017775 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* * LDAP Features */ #ifndef _LDAP_FEATURES_H #define _LDAP_FEATURES_H 1 /* OpenLDAP API version macros */ #undef LDAP_VENDOR_VERSION #undef LDAP_VENDOR_VERSION_MAJOR #undef LDAP_VENDOR_VERSION_MINOR #undef LDAP_VENDOR_VERSION_PATCH /* ** WORK IN PROGRESS! ** ** OpenLDAP reentrancy/thread-safeness should be dynamically ** checked using ldap_get_option(). ** ** The -lldap implementation is not thread-safe. ** ** The -lldap_r implementation is: ** LDAP_API_FEATURE_THREAD_SAFE (basic thread safety) ** but also be: ** LDAP_API_FEATURE_SESSION_THREAD_SAFE ** LDAP_API_FEATURE_OPERATION_THREAD_SAFE ** ** The preprocessor flag LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE ** can be used to determine if -lldap_r is available at compile ** time. You must define LDAP_THREAD_SAFE if and only if you ** link with -lldap_r. ** ** If you fail to define LDAP_THREAD_SAFE when linking with ** -lldap_r or define LDAP_THREAD_SAFE when linking with -lldap, ** provided header definations and declarations may be incorrect. ** */ /* is -lldap_r available or not */ #undef LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE /* LDAP v2 Referrals */ #undef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS #endif /* LDAP_FEATURES */ openldap-2.4.42+dfsg/include/lutil_meter.h0000644000175000017500000000372012563404150017153 0ustar ryanryan/* lutil_meter.h - progress meters */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright (c) 2009 by Emily Backes, Symas Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* ACKNOWLEDGEMENTS: * This work was initially developed by Emily Backes for inclusion * in OpenLDAP software. */ #ifndef _LUTIL_METER_H #define _LUTIL_METER_H #include "portable.h" #include #include #include #include #include typedef struct { int (*display_open) (void **datap); int (*display_update) (void **datap, double frac, time_t remaining_time, time_t elapsed, double byte_rate); int (*display_close) (void **datap); } lutil_meter_display_t; typedef struct { int (*estimator_open) (void **datap); int (*estimator_update) (void **datap, double start, double frac, time_t *remaining_time); int (*estimator_close) (void **datap); } lutil_meter_estimator_t; typedef struct { const lutil_meter_display_t *display; void * display_data; const lutil_meter_estimator_t *estimator; void * estimator_data; double start_time; double last_update; size_t goal_value; size_t last_position; } lutil_meter_t; extern const lutil_meter_display_t lutil_meter_text_display; extern const lutil_meter_estimator_t lutil_meter_linear_estimator; extern int lutil_meter_open ( lutil_meter_t *lutil_meter, const lutil_meter_display_t *display, const lutil_meter_estimator_t *estimator, size_t goal_value); extern int lutil_meter_update ( lutil_meter_t *lutil_meter, size_t position, int force); extern int lutil_meter_close (lutil_meter_t *lutil_meter); #endif /* _LUTIL_METER_H */ openldap-2.4.42+dfsg/include/ldap_int_thread.h0000644000175000017500000001776112563404150017761 0ustar ryanryan/* ldap_int_thread.h - ldap internal thread wrappers header file */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ LDAP_BEGIN_DECL /* Can be done twice in libldap_r. See libldap_r/ldap_thr_debug.h. */ LDAP_F(int) ldap_int_thread_initialize LDAP_P(( void )); LDAP_F(int) ldap_int_thread_destroy LDAP_P(( void )); LDAP_END_DECL #ifndef _LDAP_INT_THREAD_H #define _LDAP_INT_THREAD_H #if defined( HAVE_PTHREADS ) /********************************** * * * definitions for POSIX Threads * * * **********************************/ #include #ifdef HAVE_SCHED_H #include #endif LDAP_BEGIN_DECL typedef pthread_t ldap_int_thread_t; typedef pthread_mutex_t ldap_int_thread_mutex_t; typedef pthread_cond_t ldap_int_thread_cond_t; typedef pthread_key_t ldap_int_thread_key_t; #define ldap_int_thread_equal(a, b) pthread_equal((a), (b)) #if defined( _POSIX_REENTRANT_FUNCTIONS ) || \ defined( _POSIX_THREAD_SAFE_FUNCTIONS ) || \ defined( _POSIX_THREADSAFE_FUNCTIONS ) #define HAVE_REENTRANT_FUNCTIONS 1 #endif #if defined( HAVE_PTHREAD_GETCONCURRENCY ) || \ defined( HAVE_THR_GETCONCURRENCY ) #define LDAP_THREAD_HAVE_GETCONCURRENCY 1 #endif #if defined( HAVE_PTHREAD_SETCONCURRENCY ) || \ defined( HAVE_THR_SETCONCURRENCY ) #define LDAP_THREAD_HAVE_SETCONCURRENCY 1 #endif #if defined( HAVE_PTHREAD_RWLOCK_DESTROY ) #define LDAP_THREAD_HAVE_RDWR 1 typedef pthread_rwlock_t ldap_int_thread_rdwr_t; #endif #ifndef LDAP_INT_MUTEX_NULL #define LDAP_INT_MUTEX_NULL PTHREAD_MUTEX_INITIALIZER #define LDAP_INT_MUTEX_FIRSTCREATE(m) ((void) 0) #endif LDAP_END_DECL #elif defined ( HAVE_MACH_CTHREADS ) /********************************** * * * definitions for Mach CThreads * * * **********************************/ #if defined( HAVE_MACH_CTHREADS_H ) # include #elif defined( HAVE_CTHREADS_H ) # include #endif LDAP_BEGIN_DECL typedef cthread_t ldap_int_thread_t; typedef struct mutex ldap_int_thread_mutex_t; typedef struct condition ldap_int_thread_cond_t; typedef cthread_key_t ldap_int_thread_key_t; #ifndef LDAP_INT_MUTEX_NULL #define LDAP_INT_MUTEX_NULL MUTEX_INITIALIZER #define LDAP_INT_MUTEX_FIRSTCREATE(m) ((void) 0) #endif LDAP_END_DECL #elif defined( HAVE_GNU_PTH ) /*********************************** * * * thread definitions for GNU Pth * * * ***********************************/ #define PTH_SYSCALL_SOFT 1 #include LDAP_BEGIN_DECL typedef pth_t ldap_int_thread_t; typedef pth_mutex_t ldap_int_thread_mutex_t; typedef pth_cond_t ldap_int_thread_cond_t; typedef pth_key_t ldap_int_thread_key_t; #if 0 #define LDAP_THREAD_HAVE_RDWR 1 typedef pth_rwlock_t ldap_int_thread_rdwr_t; #endif #ifndef LDAP_INT_MUTEX_NULL #define LDAP_INT_MUTEX_NULL PTH_MUTEX_INIT #define LDAP_INT_MUTEX_FIRSTCREATE(m) ((void) 0) #endif LDAP_END_DECL #elif defined( HAVE_THR ) /******************************************** * * * thread definitions for Solaris LWP (THR) * * * ********************************************/ #include #include LDAP_BEGIN_DECL typedef thread_t ldap_int_thread_t; typedef mutex_t ldap_int_thread_mutex_t; typedef cond_t ldap_int_thread_cond_t; typedef thread_key_t ldap_int_thread_key_t; #define HAVE_REENTRANT_FUNCTIONS 1 #ifdef HAVE_THR_GETCONCURRENCY #define LDAP_THREAD_HAVE_GETCONCURRENCY 1 #endif #ifdef HAVE_THR_SETCONCURRENCY #define LDAP_THREAD_HAVE_SETCONCURRENCY 1 #endif #ifndef LDAP_INT_MUTEX_NULL #define LDAP_INT_MUTEX_NULL DEFAULTMUTEX #define LDAP_INT_MUTEX_FIRSTCREATE(m) ((void) 0) #endif #elif defined(HAVE_NT_THREADS) /************************************* * * * thread definitions for NT threads * * * *************************************/ #include #include LDAP_BEGIN_DECL typedef unsigned long ldap_int_thread_t; typedef HANDLE ldap_int_thread_mutex_t; typedef HANDLE ldap_int_thread_cond_t; typedef DWORD ldap_int_thread_key_t; #ifndef LDAP_INT_MUTEX_NULL #define LDAP_INT_MUTEX_NULL ((HANDLE)0) #define LDAP_INT_MUTEX_FIRSTCREATE(m) \ ((void) ((m) || ldap_pvt_thread_mutex_init(&(m)))) #endif LDAP_END_DECL #else /*********************************** * * * thread definitions for no * * underlying library support * * * ***********************************/ #ifndef NO_THREADS #define NO_THREADS 1 #endif LDAP_BEGIN_DECL typedef int ldap_int_thread_t; typedef int ldap_int_thread_mutex_t; typedef int ldap_int_thread_cond_t; typedef int ldap_int_thread_key_t; #define LDAP_THREAD_HAVE_TPOOL 1 typedef int ldap_int_thread_pool_t; #ifndef LDAP_INT_MUTEX_NULL #define LDAP_INT_MUTEX_NULL 0 #define LDAP_INT_MUTEX_FIRSTCREATE(m) ((void) 0) #endif LDAP_END_DECL #endif /* no threads support */ LDAP_BEGIN_DECL #ifndef ldap_int_thread_equal #define ldap_int_thread_equal(a, b) ((a) == (b)) #endif #ifndef LDAP_THREAD_HAVE_RDWR typedef struct ldap_int_thread_rdwr_s * ldap_int_thread_rdwr_t; #endif LDAP_F(int) ldap_int_thread_pool_startup ( void ); LDAP_F(int) ldap_int_thread_pool_shutdown ( void ); #ifndef LDAP_THREAD_HAVE_TPOOL typedef struct ldap_int_thread_pool_s * ldap_int_thread_pool_t; #endif typedef struct ldap_int_thread_rmutex_s * ldap_int_thread_rmutex_t; LDAP_END_DECL #if defined(LDAP_THREAD_DEBUG) && !((LDAP_THREAD_DEBUG +0) & 2U) #define LDAP_THREAD_DEBUG_WRAP 1 #endif #ifdef LDAP_THREAD_DEBUG_WRAP /************************************** * * * definitions for type-wrapped debug * * * **************************************/ LDAP_BEGIN_DECL #ifndef LDAP_UINTPTR_T /* May be configured in CPPFLAGS */ #define LDAP_UINTPTR_T unsigned long #endif typedef enum { ldap_debug_magic = -(int) (((unsigned)-1)/19) } ldap_debug_magic_t; typedef enum { /* Could fill in "locked" etc here later */ ldap_debug_state_inited = (int) (((unsigned)-1)/11), ldap_debug_state_destroyed } ldap_debug_state_t; typedef struct { /* Enclosed in magic numbers in the hope of catching overwrites */ ldap_debug_magic_t magic; /* bit pattern to recognize usages */ LDAP_UINTPTR_T self; /* ~(LDAP_UINTPTR_T)&(this struct) */ union ldap_debug_mem_u { /* Dummy memory reference */ unsigned char *ptr; LDAP_UINTPTR_T num; } mem; ldap_debug_state_t state; /* doubles as another magic number */ } ldap_debug_usage_info_t; typedef struct { ldap_int_thread_mutex_t wrapped; ldap_debug_usage_info_t usage; ldap_int_thread_t owner; } ldap_debug_thread_mutex_t; #define LDAP_DEBUG_MUTEX_NULL {LDAP_INT_MUTEX_NULL, {0,0,{0},0} /*,owner*/} #define LDAP_DEBUG_MUTEX_FIRSTCREATE(m) \ ((void) ((m).usage.state || ldap_pvt_thread_mutex_init(&(m)))) typedef struct { ldap_int_thread_cond_t wrapped; ldap_debug_usage_info_t usage; } ldap_debug_thread_cond_t; typedef struct { ldap_int_thread_rdwr_t wrapped; ldap_debug_usage_info_t usage; } ldap_debug_thread_rdwr_t; #ifndef NDEBUG #define LDAP_INT_THREAD_ASSERT_MUTEX_OWNER(mutex) \ ldap_debug_thread_assert_mutex_owner( \ __FILE__, __LINE__, "owns(" #mutex ")", mutex ) LDAP_F(void) ldap_debug_thread_assert_mutex_owner LDAP_P(( LDAP_CONST char *file, int line, LDAP_CONST char *msg, ldap_debug_thread_mutex_t *mutex )); #endif /* NDEBUG */ LDAP_END_DECL #endif /* LDAP_THREAD_DEBUG_WRAP */ #endif /* _LDAP_INT_THREAD_H */ openldap-2.4.42+dfsg/include/lber_pvt.h0000644000175000017500000001243112563404150016442 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* * lber_pvt.h - Header for ber_pvt_ functions. * These are meant to be internal to OpenLDAP Software. */ #ifndef _LBER_PVT_H #define _LBER_PVT_H 1 #include LDAP_BEGIN_DECL /* for allocating aligned buffers (on the stack) */ #define LBER_ALIGNED_BUFFER(uname,size) \ union uname { \ char buffer[size]; \ /* force alignment */ \ int ialign; \ long lalign; \ float falign; \ double dalign; \ char* palign; \ } #define LBER_ELEMENT_SIZEOF (256) /* must be >= sizeof(BerElement) */ typedef LBER_ALIGNED_BUFFER(lber_berelement_u,LBER_ELEMENT_SIZEOF) BerElementBuffer; typedef struct sockbuf_buf { ber_len_t buf_size; ber_len_t buf_ptr; ber_len_t buf_end; char *buf_base; } Sockbuf_Buf; /* * bprint.c */ LBER_V( BER_LOG_PRINT_FN ) ber_pvt_log_print; LBER_F( int ) ber_pvt_log_printf LDAP_P(( int errlvl, int loglvl, const char *fmt, ... )) LDAP_GCCATTR((format(printf, 3, 4))); /* * sockbuf.c */ LBER_F( ber_slen_t ) ber_pvt_sb_do_write LDAP_P(( Sockbuf_IO_Desc *sbiod, Sockbuf_Buf *buf_out )); LBER_F( void ) ber_pvt_sb_buf_init LDAP_P(( Sockbuf_Buf *buf )); LBER_F( void ) ber_pvt_sb_buf_destroy LDAP_P(( Sockbuf_Buf *buf )); LBER_F( int ) ber_pvt_sb_grow_buffer LDAP_P(( Sockbuf_Buf *buf, ber_len_t minsize )); LBER_F( ber_len_t ) ber_pvt_sb_copy_out LDAP_P(( Sockbuf_Buf *sbb, char *buf, ber_len_t len )); LBER_F( int ) ber_pvt_socket_set_nonblock LDAP_P(( ber_socket_t sd, int nb )); /* * memory.c */ LBER_F( void * ) ber_memalloc_x LDAP_P(( ber_len_t s, void *ctx)); LBER_F( void * ) ber_memrealloc_x LDAP_P(( void* p, ber_len_t s, void *ctx )); LBER_F( void * ) ber_memcalloc_x LDAP_P(( ber_len_t n, ber_len_t s, void *ctx )); LBER_F( void ) ber_memfree_x LDAP_P(( void* p, void *ctx )); LBER_F( void ) ber_memvfree_x LDAP_P(( void** vector, void *ctx )); LBER_F( void ) ber_bvfree_x LDAP_P(( struct berval *bv, void *ctx )); LBER_F( void ) ber_bvecfree_x LDAP_P(( struct berval **bv, void *ctx )); LBER_F( int ) ber_bvecadd_x LDAP_P(( struct berval ***bvec, struct berval *bv, void *ctx )); LBER_F( struct berval * ) ber_dupbv_x LDAP_P(( struct berval *dst, struct berval *src, void *ctx )); LBER_F( struct berval * ) ber_str2bv_x LDAP_P(( LDAP_CONST char *, ber_len_t len, int dup, struct berval *bv, void *ctx)); LBER_F( struct berval * ) ber_mem2bv_x LDAP_P(( LDAP_CONST char *, ber_len_t len, int dup, struct berval *bv, void *ctx)); LBER_F( char * ) ber_strdup_x LDAP_P(( LDAP_CONST char *, void *ctx )); LBER_F( struct berval * ) ber_bvreplace_x LDAP_P(( struct berval *dst, LDAP_CONST struct berval *src, void *ctx )); LBER_F( void ) ber_bvarray_free_x LDAP_P(( BerVarray p, void *ctx )); LBER_F( int ) ber_bvarray_add_x LDAP_P(( BerVarray *p, BerValue *bv, void *ctx )); LBER_F( int ) ber_bvarray_dup_x LDAP_P(( BerVarray *dst, BerVarray src, void *ctx )); #if 0 #define ber_bvstrcmp(v1,v2) \ ((v1)->bv_len < (v2)->bv_len \ ? -1 : ((v1)->bv_len > (v2)->bv_len \ ? 1 : strncmp((v1)->bv_val, (v2)->bv_val, (v1)->bv_len) )) #else /* avoid strncmp() */ #define ber_bvstrcmp(v1,v2) ber_bvcmp((v1),(v2)) #endif #define ber_bvstrcasecmp(v1,v2) \ ((v1)->bv_len < (v2)->bv_len \ ? -1 : ((v1)->bv_len > (v2)->bv_len \ ? 1 : strncasecmp((v1)->bv_val, (v2)->bv_val, (v1)->bv_len) )) #define ber_bvccmp(v1,c) \ ( (v1)->bv_len == 1 && (v1)->bv_val[0] == (c) ) #define ber_strccmp(s,c) \ ( (s)[0] == (c) && (s)[1] == '\0' ) #define ber_bvchr(bv,c) \ ((char *) memchr( (bv)->bv_val, (c), (bv)->bv_len )) #define ber_bvrchr(bv,c) \ ((char *) lutil_memrchr( (bv)->bv_val, (c), (bv)->bv_len )) #define ber_bvchr_post(dst,bv,c) \ do { \ (dst)->bv_val = memchr( (bv)->bv_val, (c), (bv)->bv_len ); \ (dst)->bv_len = (dst)->bv_val ? (bv)->bv_len - ((dst)->bv_val - (bv)->bv_val) : 0; \ } while (0) #define ber_bvchr_pre(dst,bv,c) \ do { \ (dst)->bv_val = memchr( (bv)->bv_val, (c), (bv)->bv_len ); \ (dst)->bv_len = (dst)->bv_val ? ((dst)->bv_val - (bv)->bv_val) : (bv)->bv_len; \ (dst)->bv_val = (bv)->bv_val; \ } while (0) #define ber_bvrchr_post(dst,bv,c) \ do { \ (dst)->bv_val = lutil_memrchr( (bv)->bv_val, (c), (bv)->bv_len ); \ (dst)->bv_len = (dst)->bv_val ? (bv)->bv_len - ((dst)->bv_val - (bv)->bv_val) : 0; \ } while (0) #define ber_bvrchr_pre(dst,bv,c) \ do { \ (dst)->bv_val = lutil_memrchr( (bv)->bv_val, (c), (bv)->bv_len ); \ (dst)->bv_len = (dst)->bv_val ? ((dst)->bv_val - (bv)->bv_val) : (bv)->bv_len; \ (dst)->bv_val = (bv)->bv_val; \ } while (0) #define BER_BVC(s) { STRLENOF(s), (char *)(s) } #define BER_BVNULL { 0L, NULL } #define BER_BVZERO(bv) \ do { \ (bv)->bv_len = 0; \ (bv)->bv_val = NULL; \ } while (0) #define BER_BVSTR(bv,s) \ do { \ (bv)->bv_len = STRLENOF(s); \ (bv)->bv_val = (s); \ } while (0) #define BER_BVISNULL(bv) ((bv)->bv_val == NULL) #define BER_BVISEMPTY(bv) ((bv)->bv_len == 0) LDAP_END_DECL #endif openldap-2.4.42+dfsg/include/ldap_pvt_uc.h0000644000175000017500000001163412563404150017131 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* * ldap_pvt_uc.h - Header for Unicode functions. * These are meant to be used by the OpenLDAP distribution only. * These should be named ldap_pvt_....() */ #ifndef _LDAP_PVT_UC_H #define _LDAP_PVT_UC_H 1 #include /* get ber_slen_t */ #include #include "../libraries/liblunicode/ucdata/ucdata.h" LDAP_BEGIN_DECL /* * UTF-8 (in utf-8.c) */ /* UCDATA uses UCS-2 passed in a 4 byte unsigned int */ typedef ac_uint4 ldap_unicode_t; /* Convert a string with csize octets per character to UTF-8 */ LDAP_F( int ) ldap_ucs_to_utf8s LDAP_P(( struct berval *ucs, int csize, struct berval *utf8s )); /* returns the number of bytes in the UTF-8 string */ LDAP_F (ber_len_t) ldap_utf8_bytes( const char * ); /* returns the number of UTF-8 characters in the string */ LDAP_F (ber_len_t) ldap_utf8_chars( const char * ); /* returns the length (in bytes) of the UTF-8 character */ LDAP_F (int) ldap_utf8_offset( const char * ); /* returns the length (in bytes) indicated by the UTF-8 character */ LDAP_F (int) ldap_utf8_charlen( const char * ); /* returns the length (in bytes) indicated by the UTF-8 character * also checks that shortest possible encoding was used */ LDAP_F (int) ldap_utf8_charlen2( const char * ); /* copies a UTF-8 character and returning number of bytes copied */ LDAP_F (int) ldap_utf8_copy( char *, const char *); /* returns pointer of next UTF-8 character in string */ LDAP_F (char*) ldap_utf8_next( const char * ); /* returns pointer of previous UTF-8 character in string */ LDAP_F (char*) ldap_utf8_prev( const char * ); /* primitive ctype routines -- not aware of non-ascii characters */ LDAP_F (int) ldap_utf8_isascii( const char * ); LDAP_F (int) ldap_utf8_isalpha( const char * ); LDAP_F (int) ldap_utf8_isalnum( const char * ); LDAP_F (int) ldap_utf8_isdigit( const char * ); LDAP_F (int) ldap_utf8_isxdigit( const char * ); LDAP_F (int) ldap_utf8_isspace( const char * ); /* span characters not in set, return bytes spanned */ LDAP_F (ber_len_t) ldap_utf8_strcspn( const char* str, const char *set); /* span characters in set, return bytes spanned */ LDAP_F (ber_len_t) ldap_utf8_strspn( const char* str, const char *set); /* return first occurance of character in string */ LDAP_F (char *) ldap_utf8_strchr( const char* str, const char *chr); /* return first character of set in string */ LDAP_F (char *) ldap_utf8_strpbrk( const char* str, const char *set); /* reentrant tokenizer */ LDAP_F (char*) ldap_utf8_strtok( char* sp, const char* sep, char **last); /* Optimizations */ LDAP_V (const char) ldap_utf8_lentab[128]; LDAP_V (const char) ldap_utf8_mintab[32]; #define LDAP_UTF8_ISASCII(p) ( !(*(const unsigned char *)(p) & 0x80 ) ) #define LDAP_UTF8_CHARLEN(p) ( LDAP_UTF8_ISASCII(p) \ ? 1 : ldap_utf8_lentab[*(const unsigned char *)(p) ^ 0x80] ) /* This is like CHARLEN but additionally validates to make sure * the char used the shortest possible encoding. * 'l' is used to temporarily hold the result of CHARLEN. */ #define LDAP_UTF8_CHARLEN2(p, l) ( ( ( l = LDAP_UTF8_CHARLEN( p )) < 3 || \ ( ldap_utf8_mintab[*(const unsigned char *)(p) & 0x1f] & (p)[1] ) ) ? \ l : 0 ) #define LDAP_UTF8_OFFSET(p) ( LDAP_UTF8_ISASCII(p) \ ? 1 : ldap_utf8_offset((p)) ) #define LDAP_UTF8_COPY(d,s) ( LDAP_UTF8_ISASCII(s) \ ? (*(d) = *(s), 1) : ldap_utf8_copy((d),(s)) ) #define LDAP_UTF8_NEXT(p) ( LDAP_UTF8_ISASCII(p) \ ? (char *)(p)+1 : ldap_utf8_next((p)) ) #define LDAP_UTF8_INCR(p) ((p) = LDAP_UTF8_NEXT(p)) /* For symmetry */ #define LDAP_UTF8_PREV(p) (ldap_utf8_prev((p))) #define LDAP_UTF8_DECR(p) ((p)=LDAP_UTF8_PREV((p))) /* these probably should be renamed */ LDAP_LUNICODE_F(int) ucstrncmp( const ldap_unicode_t *, const ldap_unicode_t *, ber_len_t ); LDAP_LUNICODE_F(int) ucstrncasecmp( const ldap_unicode_t *, const ldap_unicode_t *, ber_len_t ); LDAP_LUNICODE_F(ldap_unicode_t *) ucstrnchr( const ldap_unicode_t *, ber_len_t, ldap_unicode_t ); LDAP_LUNICODE_F(ldap_unicode_t *) ucstrncasechr( const ldap_unicode_t *, ber_len_t, ldap_unicode_t ); LDAP_LUNICODE_F(void) ucstr2upper( ldap_unicode_t *, ber_len_t ); #define LDAP_UTF8_NOCASEFOLD 0x0U #define LDAP_UTF8_CASEFOLD 0x1U #define LDAP_UTF8_ARG1NFC 0x2U #define LDAP_UTF8_ARG2NFC 0x4U #define LDAP_UTF8_APPROX 0x8U LDAP_LUNICODE_F(struct berval *) UTF8bvnormalize( struct berval *, struct berval *, unsigned, void *memctx ); LDAP_LUNICODE_F(int) UTF8bvnormcmp( struct berval *, struct berval *, unsigned, void *memctx ); LDAP_END_DECL #endif openldap-2.4.42+dfsg/include/lber.h0000644000175000017500000003571712563404150015565 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (c) 1990 Regents of the University of Michigan. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of Michigan at Ann Arbor. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. */ #ifndef _LBER_H #define _LBER_H #include #include LDAP_BEGIN_DECL /* * ber_tag_t represents the identifier octets at the beginning of BER * elements. OpenLDAP treats them as mere big-endian unsigned integers. * * Actually the BER identifier octets look like this: * * Bits of 1st octet: * ______ * 8 7 | CLASS * 0 0 = UNIVERSAL * 0 1 = APPLICATION * 1 0 = CONTEXT-SPECIFIC * 1 1 = PRIVATE * _____ * | 6 | DATA-TYPE * 0 = PRIMITIVE * 1 = CONSTRUCTED * ___________ * | 5 ... 1 | TAG-NUMBER * * For ASN.1 tag numbers >= 0x1F, TAG-NUMBER above is 0x1F and the next * BER octets contain the actual ASN.1 tag number: Big-endian, base * 128, 8.bit = 1 in all but the last octet, minimum number of octets. */ /* BER classes and mask (in 1st identifier octet) */ #define LBER_CLASS_UNIVERSAL ((ber_tag_t) 0x00U) #define LBER_CLASS_APPLICATION ((ber_tag_t) 0x40U) #define LBER_CLASS_CONTEXT ((ber_tag_t) 0x80U) #define LBER_CLASS_PRIVATE ((ber_tag_t) 0xc0U) #define LBER_CLASS_MASK ((ber_tag_t) 0xc0U) /* BER encoding type and mask (in 1st identifier octet) */ #define LBER_PRIMITIVE ((ber_tag_t) 0x00U) #define LBER_CONSTRUCTED ((ber_tag_t) 0x20U) #define LBER_ENCODING_MASK ((ber_tag_t) 0x20U) #define LBER_BIG_TAG_MASK ((ber_tag_t) 0x1fU) #define LBER_MORE_TAG_MASK ((ber_tag_t) 0x80U) /* * LBER_ERROR and LBER_DEFAULT are values that can never appear * as valid BER tags, so it is safe to use them to report errors. * Valid tags have (tag & (ber_tag_t) 0xFF) != 0xFF. */ #define LBER_ERROR ((ber_tag_t) -1) #define LBER_DEFAULT ((ber_tag_t) -1) /* general BER types we know about */ #define LBER_BOOLEAN ((ber_tag_t) 0x01UL) #define LBER_INTEGER ((ber_tag_t) 0x02UL) #define LBER_BITSTRING ((ber_tag_t) 0x03UL) #define LBER_OCTETSTRING ((ber_tag_t) 0x04UL) #define LBER_NULL ((ber_tag_t) 0x05UL) #define LBER_ENUMERATED ((ber_tag_t) 0x0aUL) #define LBER_SEQUENCE ((ber_tag_t) 0x30UL) /* constructed */ #define LBER_SET ((ber_tag_t) 0x31UL) /* constructed */ /* LBER BerElement options */ #define LBER_USE_DER 0x01 /* get/set options for BerElement */ #define LBER_OPT_BER_OPTIONS 0x01 #define LBER_OPT_BER_DEBUG 0x02 #define LBER_OPT_BER_REMAINING_BYTES 0x03 #define LBER_OPT_BER_TOTAL_BYTES 0x04 #define LBER_OPT_BER_BYTES_TO_WRITE 0x05 #define LBER_OPT_BER_MEMCTX 0x06 #define LBER_OPT_DEBUG_LEVEL LBER_OPT_BER_DEBUG #define LBER_OPT_REMAINING_BYTES LBER_OPT_BER_REMAINING_BYTES #define LBER_OPT_TOTAL_BYTES LBER_OPT_BER_TOTAL_BYTES #define LBER_OPT_BYTES_TO_WRITE LBER_OPT_BER_BYTES_TO_WRITE #define LBER_OPT_LOG_PRINT_FN 0x8001 #define LBER_OPT_MEMORY_FNS 0x8002 #define LBER_OPT_ERROR_FN 0x8003 #define LBER_OPT_LOG_PRINT_FILE 0x8004 /* get/set Memory Debug options */ #define LBER_OPT_MEMORY_INUSE 0x8005 /* for memory debugging */ #define LBER_OPT_LOG_PROC 0x8006 /* for external logging function */ typedef int* (*BER_ERRNO_FN) LDAP_P(( void )); typedef void (*BER_LOG_PRINT_FN) LDAP_P(( LDAP_CONST char *buf )); typedef void* (BER_MEMALLOC_FN) LDAP_P(( ber_len_t size, void *ctx )); typedef void* (BER_MEMCALLOC_FN) LDAP_P(( ber_len_t n, ber_len_t size, void *ctx )); typedef void* (BER_MEMREALLOC_FN) LDAP_P(( void *p, ber_len_t size, void *ctx )); typedef void (BER_MEMFREE_FN) LDAP_P(( void *p, void *ctx )); typedef struct lber_memory_fns { BER_MEMALLOC_FN *bmf_malloc; BER_MEMCALLOC_FN *bmf_calloc; BER_MEMREALLOC_FN *bmf_realloc; BER_MEMFREE_FN *bmf_free; } BerMemoryFunctions; /* LBER Sockbuf_IO options */ #define LBER_SB_OPT_GET_FD 1 #define LBER_SB_OPT_SET_FD 2 #define LBER_SB_OPT_HAS_IO 3 #define LBER_SB_OPT_SET_NONBLOCK 4 #define LBER_SB_OPT_GET_SSL 7 #define LBER_SB_OPT_DATA_READY 8 #define LBER_SB_OPT_SET_READAHEAD 9 #define LBER_SB_OPT_DRAIN 10 #define LBER_SB_OPT_NEEDS_READ 11 #define LBER_SB_OPT_NEEDS_WRITE 12 #define LBER_SB_OPT_GET_MAX_INCOMING 13 #define LBER_SB_OPT_SET_MAX_INCOMING 14 /* Only meaningful ifdef LDAP_PF_LOCAL_SENDMSG */ #define LBER_SB_OPT_UNGET_BUF 15 /* Largest option used by the library */ #define LBER_SB_OPT_OPT_MAX 15 /* LBER IO operations stacking levels */ #define LBER_SBIOD_LEVEL_PROVIDER 10 #define LBER_SBIOD_LEVEL_TRANSPORT 20 #define LBER_SBIOD_LEVEL_APPLICATION 30 /* get/set options for Sockbuf */ #define LBER_OPT_SOCKBUF_DESC 0x1000 #define LBER_OPT_SOCKBUF_OPTIONS 0x1001 #define LBER_OPT_SOCKBUF_DEBUG 0x1002 /* on/off values */ LBER_V( char ) ber_pvt_opt_on; #define LBER_OPT_ON ((void *) &ber_pvt_opt_on) #define LBER_OPT_OFF ((void *) 0) #define LBER_OPT_SUCCESS (0) #define LBER_OPT_ERROR (-1) typedef struct berelement BerElement; typedef struct sockbuf Sockbuf; typedef struct sockbuf_io Sockbuf_IO; /* Structure for LBER IO operarion descriptor */ typedef struct sockbuf_io_desc { int sbiod_level; Sockbuf *sbiod_sb; Sockbuf_IO *sbiod_io; void *sbiod_pvt; struct sockbuf_io_desc *sbiod_next; } Sockbuf_IO_Desc; /* Structure for LBER IO operation functions */ struct sockbuf_io { int (*sbi_setup)( Sockbuf_IO_Desc *sbiod, void *arg ); int (*sbi_remove)( Sockbuf_IO_Desc *sbiod ); int (*sbi_ctrl)( Sockbuf_IO_Desc *sbiod, int opt, void *arg); ber_slen_t (*sbi_read)( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len ); ber_slen_t (*sbi_write)( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len ); int (*sbi_close)( Sockbuf_IO_Desc *sbiod ); }; /* Helper macros for LBER IO functions */ #define LBER_SBIOD_READ_NEXT( sbiod, buf, len ) \ ( (sbiod)->sbiod_next->sbiod_io->sbi_read( (sbiod)->sbiod_next, \ buf, len ) ) #define LBER_SBIOD_WRITE_NEXT( sbiod, buf, len ) \ ( (sbiod)->sbiod_next->sbiod_io->sbi_write( (sbiod)->sbiod_next, \ buf, len ) ) #define LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg ) \ ( (sbiod)->sbiod_next ? \ ( (sbiod)->sbiod_next->sbiod_io->sbi_ctrl( \ (sbiod)->sbiod_next, opt, arg ) ) : 0 ) /* structure for returning a sequence of octet strings + length */ typedef struct berval { ber_len_t bv_len; char *bv_val; } BerValue; typedef BerValue *BerVarray; /* To distinguish from a single bv */ /* this should be moved to lber-int.h */ /* * in bprint.c: */ LBER_F( void ) ber_error_print LDAP_P(( LDAP_CONST char *data )); LBER_F( void ) ber_bprint LDAP_P(( LDAP_CONST char *data, ber_len_t len )); LBER_F( void ) ber_dump LDAP_P(( BerElement *ber, int inout )); /* * in decode.c: */ typedef int (*BERDecodeCallback) LDAP_P(( BerElement *ber, void *data, int mode )); LBER_F( ber_tag_t ) ber_get_tag LDAP_P(( BerElement *ber )); LBER_F( ber_tag_t ) ber_skip_tag LDAP_P(( BerElement *ber, ber_len_t *len )); LBER_F( ber_tag_t ) ber_peek_tag LDAP_P(( BerElement *ber, ber_len_t *len )); LBER_F( ber_tag_t ) ber_skip_element LDAP_P(( BerElement *ber, struct berval *bv )); LBER_F( ber_tag_t ) ber_peek_element LDAP_P(( LDAP_CONST BerElement *ber, struct berval *bv )); LBER_F( ber_tag_t ) ber_get_int LDAP_P(( BerElement *ber, ber_int_t *num )); LBER_F( ber_tag_t ) ber_get_enum LDAP_P(( BerElement *ber, ber_int_t *num )); LBER_F( ber_tag_t ) ber_get_stringb LDAP_P(( BerElement *ber, char *buf, ber_len_t *len )); #define LBER_BV_ALLOC 0x01 /* allocate/copy result, otherwise in-place */ #define LBER_BV_NOTERM 0x02 /* omit NUL-terminator if parsing in-place */ #define LBER_BV_STRING 0x04 /* fail if berval contains embedded \0 */ /* LBER_BV_STRING currently accepts a terminating \0 in the berval, because * Active Directory sends that in at least the diagonsticMessage field. */ LBER_F( ber_tag_t ) ber_get_stringbv LDAP_P(( BerElement *ber, struct berval *bv, int options )); LBER_F( ber_tag_t ) ber_get_stringa LDAP_P(( BerElement *ber, char **buf )); LBER_F( ber_tag_t ) ber_get_stringal LDAP_P(( BerElement *ber, struct berval **bv )); LBER_F( ber_tag_t ) ber_get_bitstringa LDAP_P(( BerElement *ber, char **buf, ber_len_t *len )); LBER_F( ber_tag_t ) ber_get_null LDAP_P(( BerElement *ber )); LBER_F( ber_tag_t ) ber_get_boolean LDAP_P(( BerElement *ber, ber_int_t *boolval )); LBER_F( ber_tag_t ) ber_first_element LDAP_P(( BerElement *ber, ber_len_t *len, char **last )); LBER_F( ber_tag_t ) ber_next_element LDAP_P(( BerElement *ber, ber_len_t *len, LDAP_CONST char *last )); LBER_F( ber_tag_t ) ber_scanf LDAP_P(( BerElement *ber, LDAP_CONST char *fmt, ... )); LBER_F( int ) ber_decode_oid LDAP_P(( struct berval *in, struct berval *out )); /* * in encode.c */ LBER_F( int ) ber_encode_oid LDAP_P(( struct berval *in, struct berval *out )); typedef int (*BEREncodeCallback) LDAP_P(( BerElement *ber, void *data )); LBER_F( int ) ber_put_enum LDAP_P(( BerElement *ber, ber_int_t num, ber_tag_t tag )); LBER_F( int ) ber_put_int LDAP_P(( BerElement *ber, ber_int_t num, ber_tag_t tag )); LBER_F( int ) ber_put_ostring LDAP_P(( BerElement *ber, LDAP_CONST char *str, ber_len_t len, ber_tag_t tag )); LBER_F( int ) ber_put_berval LDAP_P(( BerElement *ber, struct berval *bv, ber_tag_t tag )); LBER_F( int ) ber_put_string LDAP_P(( BerElement *ber, LDAP_CONST char *str, ber_tag_t tag )); LBER_F( int ) ber_put_bitstring LDAP_P(( BerElement *ber, LDAP_CONST char *str, ber_len_t bitlen, ber_tag_t tag )); LBER_F( int ) ber_put_null LDAP_P(( BerElement *ber, ber_tag_t tag )); LBER_F( int ) ber_put_boolean LDAP_P(( BerElement *ber, ber_int_t boolval, ber_tag_t tag )); LBER_F( int ) ber_start_seq LDAP_P(( BerElement *ber, ber_tag_t tag )); LBER_F( int ) ber_start_set LDAP_P(( BerElement *ber, ber_tag_t tag )); LBER_F( int ) ber_put_seq LDAP_P(( BerElement *ber )); LBER_F( int ) ber_put_set LDAP_P(( BerElement *ber )); LBER_F( int ) ber_printf LDAP_P(( BerElement *ber, LDAP_CONST char *fmt, ... )); /* * in io.c: */ LBER_F( ber_slen_t ) ber_skip_data LDAP_P(( BerElement *ber, ber_len_t len )); LBER_F( ber_slen_t ) ber_read LDAP_P(( BerElement *ber, char *buf, ber_len_t len )); LBER_F( ber_slen_t ) ber_write LDAP_P(( BerElement *ber, LDAP_CONST char *buf, ber_len_t len, int zero )); /* nonzero is unsupported from OpenLDAP 2.4.18 */ LBER_F( void ) ber_free LDAP_P(( BerElement *ber, int freebuf )); LBER_F( void ) ber_free_buf LDAP_P(( BerElement *ber )); LBER_F( int ) ber_flush2 LDAP_P(( Sockbuf *sb, BerElement *ber, int freeit )); #define LBER_FLUSH_FREE_NEVER (0x0) /* traditional behavior */ #define LBER_FLUSH_FREE_ON_SUCCESS (0x1) /* traditional behavior */ #define LBER_FLUSH_FREE_ON_ERROR (0x2) #define LBER_FLUSH_FREE_ALWAYS (LBER_FLUSH_FREE_ON_SUCCESS|LBER_FLUSH_FREE_ON_ERROR) LBER_F( int ) ber_flush LDAP_P(( Sockbuf *sb, BerElement *ber, int freeit )); /* DEPRECATED */ LBER_F( BerElement * ) ber_alloc LDAP_P(( void )); /* DEPRECATED */ LBER_F( BerElement * ) der_alloc LDAP_P(( void )); /* DEPRECATED */ LBER_F( BerElement * ) ber_alloc_t LDAP_P(( int beroptions )); LBER_F( BerElement * ) ber_dup LDAP_P(( BerElement *ber )); LBER_F( ber_tag_t ) ber_get_next LDAP_P(( Sockbuf *sb, ber_len_t *len, BerElement *ber )); LBER_F( void ) ber_init2 LDAP_P(( BerElement *ber, struct berval *bv, int options )); LBER_F( void ) ber_init_w_nullc LDAP_P(( /* DEPRECATED */ BerElement *ber, int options )); LBER_F( void ) ber_reset LDAP_P(( BerElement *ber, int was_writing )); LBER_F( BerElement * ) ber_init LDAP_P(( struct berval *bv )); LBER_F( int ) ber_flatten LDAP_P(( BerElement *ber, struct berval **bvPtr )); LBER_F( int ) ber_flatten2 LDAP_P(( BerElement *ber, struct berval *bv, int alloc )); LBER_F( int ) ber_remaining LDAP_P(( BerElement *ber )); /* * LBER ber accessor functions */ LBER_F( int ) ber_get_option LDAP_P(( void *item, int option, void *outvalue)); LBER_F( int ) ber_set_option LDAP_P(( void *item, int option, LDAP_CONST void *invalue)); /* * LBER sockbuf.c */ LBER_F( Sockbuf * ) ber_sockbuf_alloc LDAP_P(( void )); LBER_F( void ) ber_sockbuf_free LDAP_P(( Sockbuf *sb )); LBER_F( int ) ber_sockbuf_add_io LDAP_P(( Sockbuf *sb, Sockbuf_IO *sbio, int layer, void *arg )); LBER_F( int ) ber_sockbuf_remove_io LDAP_P(( Sockbuf *sb, Sockbuf_IO *sbio, int layer )); LBER_F( int ) ber_sockbuf_ctrl LDAP_P(( Sockbuf *sb, int opt, void *arg )); LBER_V( Sockbuf_IO ) ber_sockbuf_io_tcp; LBER_V( Sockbuf_IO ) ber_sockbuf_io_readahead; LBER_V( Sockbuf_IO ) ber_sockbuf_io_fd; LBER_V( Sockbuf_IO ) ber_sockbuf_io_debug; LBER_V( Sockbuf_IO ) ber_sockbuf_io_udp; /* * LBER memory.c */ LBER_F( void * ) ber_memalloc LDAP_P(( ber_len_t s )); LBER_F( void * ) ber_memrealloc LDAP_P(( void* p, ber_len_t s )); LBER_F( void * ) ber_memcalloc LDAP_P(( ber_len_t n, ber_len_t s )); LBER_F( void ) ber_memfree LDAP_P(( void* p )); LBER_F( void ) ber_memvfree LDAP_P(( void** vector )); LBER_F( void ) ber_bvfree LDAP_P(( struct berval *bv )); LBER_F( void ) ber_bvecfree LDAP_P(( struct berval **bv )); LBER_F( int ) ber_bvecadd LDAP_P(( struct berval ***bvec, struct berval *bv )); LBER_F( struct berval * ) ber_dupbv LDAP_P(( struct berval *dst, struct berval *src )); LBER_F( struct berval * ) ber_bvdup LDAP_P(( struct berval *src )); LBER_F( struct berval * ) ber_mem2bv LDAP_P(( LDAP_CONST char *, ber_len_t len, int duplicate, struct berval *bv)); LBER_F( struct berval * ) ber_str2bv LDAP_P(( LDAP_CONST char *, ber_len_t len, int duplicate, struct berval *bv)); #define ber_bvstr(a) ((ber_str2bv)((a), 0, 0, NULL)) #define ber_bvstrdup(a) ((ber_str2bv)((a), 0, 1, NULL)) LBER_F( char * ) ber_strdup LDAP_P(( LDAP_CONST char * )); LBER_F( ber_len_t ) ber_strnlen LDAP_P(( LDAP_CONST char *s, ber_len_t len )); LBER_F( char * ) ber_strndup LDAP_P(( LDAP_CONST char *s, ber_len_t l )); LBER_F( struct berval * ) ber_bvreplace LDAP_P(( struct berval *dst, LDAP_CONST struct berval *src )); LBER_F( void ) ber_bvarray_free LDAP_P(( BerVarray p )); LBER_F( int ) ber_bvarray_add LDAP_P(( BerVarray *p, BerValue *bv )); #define ber_bvcmp(v1,v2) \ ((v1)->bv_len < (v2)->bv_len \ ? -1 : ((v1)->bv_len > (v2)->bv_len \ ? 1 : memcmp((v1)->bv_val, (v2)->bv_val, (v1)->bv_len) )) /* * error.c */ LBER_F( int * ) ber_errno_addr LDAP_P((void)); #define ber_errno (*(ber_errno_addr)()) #define LBER_ERROR_NONE 0 #define LBER_ERROR_PARAM 0x1 #define LBER_ERROR_MEMORY 0x2 LDAP_END_DECL #endif /* _LBER_H */ openldap-2.4.42+dfsg/include/lutil_ldap.h0000644000175000017500000000177212563404150016764 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #ifndef _LUTIL_LDAP_H #define _LUTIL_LDAP_H 1 #include #include /* * Include file for lutil LDAP routines */ LDAP_BEGIN_DECL LDAP_LUTIL_F( void ) lutil_sasl_freedefs LDAP_P(( void *defaults )); LDAP_LUTIL_F( void * ) lutil_sasl_defaults LDAP_P(( LDAP *ld, char *mech, char *realm, char *authcid, char *passwd, char *authzid )); LDAP_LUTIL_F( int ) lutil_sasl_interact LDAP_P(( LDAP *ld, unsigned flags, void *defaults, void *p )); LDAP_END_DECL #endif /* _LUTIL_LDAP_H */ openldap-2.4.42+dfsg/include/ldap_log.h0000644000175000017500000002137612563404150016416 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (c) 1990 Regents of the University of Michigan. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of Michigan at Ann Arbor. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. */ #ifndef LDAP_LOG_H #define LDAP_LOG_H #include #include LDAP_BEGIN_DECL /* * debug reporting levels. * * They start with the syslog levels, and * go down in importance. The normal * debugging levels begin with LDAP_LEVEL_ENTRY * */ /* * The "OLD_DEBUG" means that all logging occurs at LOG_DEBUG */ #ifdef OLD_DEBUG /* original behavior: all logging occurs at the same severity level */ #if defined(LDAP_DEBUG) && defined(LDAP_SYSLOG) #define LDAP_LEVEL_EMERG ldap_syslog_level #define LDAP_LEVEL_ALERT ldap_syslog_level #define LDAP_LEVEL_CRIT ldap_syslog_level #define LDAP_LEVEL_ERR ldap_syslog_level #define LDAP_LEVEL_WARNING ldap_syslog_level #define LDAP_LEVEL_NOTICE ldap_syslog_level #define LDAP_LEVEL_INFO ldap_syslog_level #define LDAP_LEVEL_DEBUG ldap_syslog_level #else /* !LDAP_DEBUG || !LDAP_SYSLOG */ #define LDAP_LEVEL_EMERG (7) #define LDAP_LEVEL_ALERT (7) #define LDAP_LEVEL_CRIT (7) #define LDAP_LEVEL_ERR (7) #define LDAP_LEVEL_WARNING (7) #define LDAP_LEVEL_NOTICE (7) #define LDAP_LEVEL_INFO (7) #define LDAP_LEVEL_DEBUG (7) #endif /* !LDAP_DEBUG || !LDAP_SYSLOG */ #else /* ! OLD_DEBUG */ /* map syslog onto LDAP severity levels */ #ifdef LOG_DEBUG #define LDAP_LEVEL_EMERG LOG_EMERG #define LDAP_LEVEL_ALERT LOG_ALERT #define LDAP_LEVEL_CRIT LOG_CRIT #define LDAP_LEVEL_ERR LOG_ERR #define LDAP_LEVEL_WARNING LOG_WARNING #define LDAP_LEVEL_NOTICE LOG_NOTICE #define LDAP_LEVEL_INFO LOG_INFO #define LDAP_LEVEL_DEBUG LOG_DEBUG #else /* ! LOG_DEBUG */ #define LDAP_LEVEL_EMERG (0) #define LDAP_LEVEL_ALERT (1) #define LDAP_LEVEL_CRIT (2) #define LDAP_LEVEL_ERR (3) #define LDAP_LEVEL_WARNING (4) #define LDAP_LEVEL_NOTICE (5) #define LDAP_LEVEL_INFO (6) #define LDAP_LEVEL_DEBUG (7) #endif /* ! LOG_DEBUG */ #endif /* ! OLD_DEBUG */ #if 0 /* in case we need to reuse the unused bits of severity */ #define LDAP_LEVEL_MASK(s) ((s) & 0x7) #else #define LDAP_LEVEL_MASK(s) (s) #endif /* (yet) unused */ #define LDAP_LEVEL_ENTRY (0x08) /* log function entry points */ #define LDAP_LEVEL_ARGS (0x10) /* log function call parameters */ #define LDAP_LEVEL_RESULTS (0x20) /* Log function results */ #define LDAP_LEVEL_DETAIL1 (0x40) /* log level 1 function operational details */ #define LDAP_LEVEL_DETAIL2 (0x80) /* Log level 2 function operational details */ /* end of (yet) unused */ /* original subsystem selection mechanism */ #define LDAP_DEBUG_TRACE 0x0001 #define LDAP_DEBUG_PACKETS 0x0002 #define LDAP_DEBUG_ARGS 0x0004 #define LDAP_DEBUG_CONNS 0x0008 #define LDAP_DEBUG_BER 0x0010 #define LDAP_DEBUG_FILTER 0x0020 #define LDAP_DEBUG_CONFIG 0x0040 #define LDAP_DEBUG_ACL 0x0080 #define LDAP_DEBUG_STATS 0x0100 #define LDAP_DEBUG_STATS2 0x0200 #define LDAP_DEBUG_SHELL 0x0400 #define LDAP_DEBUG_PARSE 0x0800 #if 0 /* no longer used (nor supported) */ #define LDAP_DEBUG_CACHE 0x1000 #define LDAP_DEBUG_INDEX 0x2000 #endif #define LDAP_DEBUG_SYNC 0x4000 #define LDAP_DEBUG_NONE 0x8000 #define LDAP_DEBUG_ANY (-1) /* debugging stuff */ #ifdef LDAP_DEBUG /* * This is a bogus extern declaration for the compiler. No need to ensure * a 'proper' dllimport. */ #ifndef ldap_debug extern int ldap_debug; #endif /* !ldap_debug */ #ifdef LDAP_SYSLOG extern int ldap_syslog; extern int ldap_syslog_level; #ifdef HAVE_EBCDIC #define syslog eb_syslog extern void eb_syslog(int pri, const char *fmt, ...); #endif /* HAVE_EBCDIC */ #endif /* LDAP_SYSLOG */ /* this doesn't below as part of ldap.h */ #ifdef LDAP_SYSLOG #define Log0( level, severity, fmt ) \ do { \ if ( ldap_debug & (level) ) \ lutil_debug( ldap_debug, (level), (fmt) ); \ if ( ldap_syslog & (level) ) \ syslog( LDAP_LEVEL_MASK((severity)), (fmt) ); \ } while ( 0 ) #define Log1( level, severity, fmt, arg1 ) \ do { \ if ( ldap_debug & (level) ) \ lutil_debug( ldap_debug, (level), (fmt), (arg1) ); \ if ( ldap_syslog & (level) ) \ syslog( LDAP_LEVEL_MASK((severity)), (fmt), (arg1) ); \ } while ( 0 ) #define Log2( level, severity, fmt, arg1, arg2 ) \ do { \ if ( ldap_debug & (level) ) \ lutil_debug( ldap_debug, (level), (fmt), (arg1), (arg2) ); \ if ( ldap_syslog & (level) ) \ syslog( LDAP_LEVEL_MASK((severity)), (fmt), (arg1), (arg2) ); \ } while ( 0 ) #define Log3( level, severity, fmt, arg1, arg2, arg3 ) \ do { \ if ( ldap_debug & (level) ) \ lutil_debug( ldap_debug, (level), (fmt), (arg1), (arg2), (arg3) ); \ if ( ldap_syslog & (level) ) \ syslog( LDAP_LEVEL_MASK((severity)), (fmt), (arg1), (arg2), (arg3) ); \ } while ( 0 ) #define Log4( level, severity, fmt, arg1, arg2, arg3, arg4 ) \ do { \ if ( ldap_debug & (level) ) \ lutil_debug( ldap_debug, (level), (fmt), (arg1), (arg2), (arg3), (arg4) ); \ if ( ldap_syslog & (level) ) \ syslog( LDAP_LEVEL_MASK((severity)), (fmt), (arg1), (arg2), (arg3), (arg4) ); \ } while ( 0 ) #define Log5( level, severity, fmt, arg1, arg2, arg3, arg4, arg5 ) \ do { \ if ( ldap_debug & (level) ) \ lutil_debug( ldap_debug, (level), (fmt), (arg1), (arg2), (arg3), (arg4), (arg5) ); \ if ( ldap_syslog & (level) ) \ syslog( LDAP_LEVEL_MASK((severity)), (fmt), (arg1), (arg2), (arg3), (arg4), (arg5) ); \ } while ( 0 ) #define Debug( level, fmt, arg1, arg2, arg3 ) \ Log3( (level), ldap_syslog_level, (fmt), (arg1), (arg2), (arg3) ) #define LogTest(level) ( ( ldap_debug | ldap_syslog ) & (level) ) #else /* ! LDAP_SYSLOG */ #define Log0( level, severity, fmt ) \ do { \ if ( ldap_debug & (level) ) \ lutil_debug( ldap_debug, (level), (fmt) ); \ } while ( 0 ) #define Log1( level, severity, fmt, arg1 ) \ do { \ if ( ldap_debug & (level) ) \ lutil_debug( ldap_debug, (level), (fmt), (arg1) ); \ } while ( 0 ) #define Log2( level, severity, fmt, arg1, arg2 ) \ do { \ if ( ldap_debug & (level) ) \ lutil_debug( ldap_debug, (level), (fmt), (arg1), (arg2) ); \ } while ( 0 ) #define Log3( level, severity, fmt, arg1, arg2, arg3 ) \ do { \ if ( ldap_debug & (level) ) \ lutil_debug( ldap_debug, (level), (fmt), (arg1), (arg2), (arg3) ); \ } while ( 0 ) #define Log4( level, severity, fmt, arg1, arg2, arg3, arg4 ) \ do { \ if ( ldap_debug & (level) ) \ lutil_debug( ldap_debug, (level), (fmt), (arg1), (arg2), (arg3), (arg4) ); \ } while ( 0 ) #define Log5( level, severity, fmt, arg1, arg2, arg3, arg4, arg5 ) \ do { \ if ( ldap_debug & (level) ) \ lutil_debug( ldap_debug, (level), (fmt), (arg1), (arg2), (arg3), (arg4), (arg5) ); \ } while ( 0 ) #define Debug( level, fmt, arg1, arg2, arg3 ) \ Log3( (level), 0, (fmt), (arg1), (arg2), (arg3) ) #define LogTest(level) ( ldap_debug & (level) ) #endif /* ! LDAP_SYSLOG */ #else /* ! LDAP_DEBUG */ /* TODO: in case LDAP_DEBUG is undefined, make sure logs with appropriate * severity gets thru anyway */ #define Log0( level, severity, fmt ) ((void)0) #define Log1( level, severity, fmt, arg1 ) ((void)0) #define Log2( level, severity, fmt, arg1, arg2 ) ((void)0) #define Log3( level, severity, fmt, arg1, arg2, arg3 ) ((void)0) #define Log4( level, severity, fmt, arg1, arg2, arg3, arg4 ) ((void)0) #define Log5( level, severity, fmt, arg1, arg2, arg3, arg4, arg5 ) ((void)0) #define Debug( level, fmt, arg1, arg2, arg3 ) ((void)0) #define LogTest(level) ( 0 ) #endif /* ! LDAP_DEBUG */ /* Actually now in liblber/debug.c */ LDAP_LUTIL_F(int) lutil_debug_file LDAP_P(( FILE *file )); LDAP_LUTIL_F(void) lutil_debug LDAP_P(( int debug, int level, const char* fmt, ... )) LDAP_GCCATTR((format(printf, 3, 4))); #ifdef LDAP_DEFINE_LDAP_DEBUG /* This struct matches the head of ldapoptions in */ struct ldapoptions_prefix { short ldo_valid; int ldo_debug; }; #define ldap_debug \ (*(int *) ((char *)&ldap_int_global_options \ + offsetof(struct ldapoptions_prefix, ldo_debug))) struct ldapoptions; LDAP_V ( struct ldapoptions ) ldap_int_global_options; #endif /* LDAP_DEFINE_LDAP_DEBUG */ LDAP_END_DECL #endif /* LDAP_LOG_H */ openldap-2.4.42+dfsg/include/ldap_utf8.h0000644000175000017500000000661412563404150016521 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* This notice applies to changes, created by or for Novell, Inc., * to preexisting works for which notices appear elsewhere in this file. * * Copyright (C) 2000 Novell, Inc. All Rights Reserved. * * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND TREATIES. * USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO VERSION * 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS AVAILABLE AT * HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE" IN THE * TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION OF THIS * WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP PUBLIC * LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT THE * PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY. */ /* Note: A verbatim copy of version 2.0.1 of the OpenLDAP Public License * can be found in the file "build/LICENSE-2.0.1" in this distribution * of OpenLDAP Software. */ #ifndef _LDAP_UTF8_H #define _LDAP_UTF8_H #include /* get ber_*_t */ /* * UTF-8 Utility Routines */ LDAP_BEGIN_DECL #define LDAP_UCS4_INVALID (0x80000000U) typedef ber_int_t ldap_ucs4_t; /* LDAP_MAX_UTF8_LEN is 3 or 6 depending on size of wchar_t */ #define LDAP_MAX_UTF8_LEN ( sizeof(wchar_t) * 3/2 ) /* Unicode conversion routines */ LDAP_F( ldap_ucs4_t ) ldap_x_utf8_to_ucs4( LDAP_CONST char * p ); LDAP_F( int ) ldap_x_ucs4_to_utf8( ldap_ucs4_t c, char *buf ); /* * Wide Char / UTF-8 Conversion Routines */ /* UTF-8 character to Wide Char */ LDAP_F(int) ldap_x_utf8_to_wc LDAP_P(( wchar_t *wchar, LDAP_CONST char *utf8char )); /* UTF-8 string to Wide Char string */ LDAP_F(int) ldap_x_utf8s_to_wcs LDAP_P(( wchar_t *wcstr, LDAP_CONST char *utf8str, size_t count )); /* Wide Char to UTF-8 character */ LDAP_F(int) ldap_x_wc_to_utf8 LDAP_P(( char *utf8char, wchar_t wchar, size_t count )); /* Wide Char string to UTF-8 string */ LDAP_F(int) ldap_x_wcs_to_utf8s LDAP_P(( char *utf8str, LDAP_CONST wchar_t *wcstr, size_t count )); /* * MultiByte Char / UTF-8 Conversion Routines */ /* UTF-8 character to MultiByte character */ LDAP_F(int) ldap_x_utf8_to_mb LDAP_P(( char *mbchar, LDAP_CONST char *utf8char, int (*ldap_f_wctomb)( char *mbchar, wchar_t wchar ))); /* UTF-8 string to MultiByte string */ LDAP_F(int) ldap_x_utf8s_to_mbs LDAP_P(( char *mbstr, LDAP_CONST char *utf8str, size_t count, size_t (*ldap_f_wcstombs)( char *mbstr, LDAP_CONST wchar_t *wcstr, size_t count) )); /* MultiByte character to UTF-8 character */ LDAP_F(int) ldap_x_mb_to_utf8 LDAP_P(( char *utf8char, LDAP_CONST char *mbchar, size_t mbsize, int (*ldap_f_mbtowc)( wchar_t *wchar, LDAP_CONST char *mbchar, size_t count) )); /* MultiByte string to UTF-8 string */ LDAP_F(int) ldap_x_mbs_to_utf8s LDAP_P(( char *utf8str, LDAP_CONST char *mbstr, size_t count, size_t (*ldap_f_mbstowcs)( wchar_t *wcstr, LDAP_CONST char *mbstr, size_t count) )); LDAP_END_DECL #endif /* _LDAP_UTF8_H */ openldap-2.4.42+dfsg/include/ldap_defaults.h0000644000175000017500000000445512563404150017443 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (c) 1994 Regents of the University of Michigan. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of Michigan at Ann Arbor. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. */ /* * This file controls defaults for OpenLDAP package. * You probably do not need to edit the defaults provided by this file. */ #ifndef _LDAP_DEFAULTS_H #define _LDAP_DEFAULTS_H #include #define LDAP_CONF_FILE LDAP_SYSCONFDIR LDAP_DIRSEP "ldap.conf" #define LDAP_USERRC_FILE "ldaprc" #define LDAP_ENV_PREFIX "LDAP" /* default ldapi:// socket */ #define LDAPI_SOCK LDAP_RUNDIR LDAP_DIRSEP "run" LDAP_DIRSEP "ldapi" /* * SLAPD DEFINITIONS */ /* location of the default slapd config file */ #define SLAPD_DEFAULT_CONFIGFILE LDAP_SYSCONFDIR LDAP_DIRSEP "slapd.conf" #define SLAPD_DEFAULT_CONFIGDIR LDAP_SYSCONFDIR LDAP_DIRSEP "slapd.d" #define SLAPD_DEFAULT_DB_DIR LDAP_RUNDIR LDAP_DIRSEP "openldap-data" #define SLAPD_DEFAULT_DB_MODE 0600 #define SLAPD_DEFAULT_UCDATA LDAP_DATADIR LDAP_DIRSEP "ucdata" /* default max deref depth for aliases */ #define SLAPD_DEFAULT_MAXDEREFDEPTH 15 /* default sizelimit on number of entries from a search */ #define SLAPD_DEFAULT_SIZELIMIT 500 /* default timelimit to spend on a search */ #define SLAPD_DEFAULT_TIMELIMIT 3600 /* the following DNs must be normalized! */ /* dn of the default subschema subentry */ #define SLAPD_SCHEMA_DN "cn=Subschema" /* dn of the default "monitor" subentry */ #define SLAPD_MONITOR_DN "cn=Monitor" #endif /* _LDAP_CONFIG_H */ openldap-2.4.42+dfsg/include/avl.h0000644000175000017500000000764012563404150015415 0ustar ryanryan/* avl.h - avl tree definitions */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (c) 1993 Regents of the University of Michigan. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of Michigan at Ann Arbor. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. */ #ifndef _AVL #define _AVL #include /* * this structure represents a generic avl tree node. */ LDAP_BEGIN_DECL typedef struct avlnode Avlnode; struct avlnode { void* avl_data; struct avlnode *avl_link[2]; char avl_bits[2]; signed char avl_bf; }; #define avl_left avl_link[0] #define avl_right avl_link[1] #define avl_lbit avl_bits[0] #define avl_rbit avl_bits[1] #ifdef AVL_INTERNAL #define NULLAVL ((Avlnode *) NULL) /* balance factor values */ #define LH (-1) #define EH 0 #define RH 1 #define avl_bf2str(bf) ((bf) == -1 ? "LH" : (bf) == 0 ? "EH" : (bf) == 1 ? "RH" : "(unknown)" ) /* thread bits */ #define AVL_THREAD 0 #define AVL_CHILD 1 /* avl routines */ #define avl_getone(x) ((x) == 0 ? 0 : (x)->avl_data) #define avl_onenode(x) ((x) == 0 || ((x)->avl_left == 0 && (x)->avl_right == 0)) #endif /* AVL_INTERNALS */ #define avl_child(x,dir) ((x)->avl_bits[dir]) == AVL_CHILD ? \ (x)->avl_link[dir] : NULL #define avl_lchild(x) avl_child(x,0) #define avl_rchild(x) avl_child(x,1) typedef int (*AVL_APPLY) LDAP_P((void *, void*)); typedef int (*AVL_CMP) LDAP_P((const void*, const void*)); typedef int (*AVL_DUP) LDAP_P((void*, void*)); typedef void (*AVL_FREE) LDAP_P((void*)); LDAP_AVL_F( int ) avl_free LDAP_P(( Avlnode *root, AVL_FREE dfree )); LDAP_AVL_F( int ) avl_insert LDAP_P((Avlnode **, void*, AVL_CMP, AVL_DUP)); LDAP_AVL_F( void* ) avl_delete LDAP_P((Avlnode **, void*, AVL_CMP)); LDAP_AVL_F( void* ) avl_find LDAP_P((Avlnode *, const void*, AVL_CMP)); LDAP_AVL_F( Avlnode* ) avl_find2 LDAP_P((Avlnode *, const void*, AVL_CMP)); LDAP_AVL_F( void* ) avl_find_lin LDAP_P((Avlnode *, const void*, AVL_CMP)); #ifdef AVL_NONREENTRANT LDAP_AVL_F( void* ) avl_getfirst LDAP_P((Avlnode *)); LDAP_AVL_F( void* ) avl_getnext LDAP_P((void)); #endif LDAP_AVL_F( int ) avl_dup_error LDAP_P((void*, void*)); LDAP_AVL_F( int ) avl_dup_ok LDAP_P((void*, void*)); LDAP_AVL_F( int ) avl_apply LDAP_P((Avlnode *, AVL_APPLY, void*, int, int)); LDAP_AVL_F( int ) avl_prefixapply LDAP_P((Avlnode *, void*, AVL_CMP, void*, AVL_CMP, void*, int)); LDAP_AVL_F( int ) tavl_free LDAP_P(( Avlnode *root, AVL_FREE dfree )); LDAP_AVL_F( int ) tavl_insert LDAP_P((Avlnode **, void*, AVL_CMP, AVL_DUP)); LDAP_AVL_F( void* ) tavl_delete LDAP_P((Avlnode **, void*, AVL_CMP)); LDAP_AVL_F( void* ) tavl_find LDAP_P((Avlnode *, const void*, AVL_CMP)); LDAP_AVL_F( Avlnode* ) tavl_find2 LDAP_P((Avlnode *, const void*, AVL_CMP)); LDAP_AVL_F( Avlnode* ) tavl_find3 LDAP_P((Avlnode *, const void*, AVL_CMP, int *ret)); #define TAVL_DIR_LEFT 0 #define TAVL_DIR_RIGHT 1 LDAP_AVL_F( Avlnode* ) tavl_end LDAP_P((Avlnode *, int direction )); LDAP_AVL_F( Avlnode* ) tavl_next LDAP_P((Avlnode *, int direction )); /* apply traversal types */ #define AVL_PREORDER 1 #define AVL_INORDER 2 #define AVL_POSTORDER 3 /* what apply returns if it ran out of nodes */ #define AVL_NOMORE (-6) LDAP_END_DECL #endif /* _AVL */ openldap-2.4.42+dfsg/include/lutil_md5.h0000644000175000017500000000313712563404150016526 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #ifndef _LUTIL_MD5_H_ #define _LUTIL_MD5_H_ #include LDAP_BEGIN_DECL /* Unlike previous versions of this code, ber_int_t need not be exactly 32 bits, merely 32 bits or more. Choosing a data type which is 32 bits instead of 64 is not important; speed is considerably more important. ANSI guarantees that "unsigned long" will be big enough, and always using it seems to have few disadvantages. */ #define LUTIL_MD5_BYTES 16 struct lutil_MD5Context { ber_uint_t buf[4]; ber_uint_t bits[2]; unsigned char in[64]; }; LDAP_LUTIL_F( void ) lutil_MD5Init LDAP_P(( struct lutil_MD5Context *context)); LDAP_LUTIL_F( void ) lutil_MD5Update LDAP_P(( struct lutil_MD5Context *context, unsigned char const *buf, ber_len_t len)); LDAP_LUTIL_F( void ) lutil_MD5Final LDAP_P(( unsigned char digest[16], struct lutil_MD5Context *context)); LDAP_LUTIL_F( void ) lutil_MD5Transform LDAP_P(( ber_uint_t buf[4], const unsigned char in[64])); /* * This is needed to make RSAREF happy on some MS-DOS compilers. */ typedef struct lutil_MD5Context lutil_MD5_CTX; LDAP_END_DECL #endif /* _LUTIL_MD5_H_ */ openldap-2.4.42+dfsg/include/getopt-compat.h0000644000175000017500000000203412563404150017406 0ustar ryanryan/* getopt-compat.h -- getopt(3) compatibility header */ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* * getopt(3) declarations */ #ifndef _GETOPT_COMPAT_H #define _GETOPT_COMPAT_H #include LDAP_BEGIN_DECL /* change symbols to avoid clashing */ #define optarg lutil_optarg #define optind lutil_optind #define opterr lutil_opterr #define optopt lutil_optopt #define getopt lutil_getopt LDAP_LUTIL_V (char *) optarg; LDAP_LUTIL_V (int) optind, opterr, optopt; LDAP_LUTIL_F (int) getopt LDAP_P(( int, char * const [], const char *)); LDAP_END_DECL #endif /* _GETOPT_COMPAT_H */ openldap-2.4.42+dfsg/include/ldap_config.hin0000644000175000017500000000331712563404150017424 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* * This file works in confunction with OpenLDAP configure system. * If you do no like the values below, adjust your configure options. */ #ifndef _LDAP_CONFIG_H #define _LDAP_CONFIG_H /* directory separator */ #ifndef LDAP_DIRSEP #ifndef _WIN32 #define LDAP_DIRSEP "/" #else #define LDAP_DIRSEP "\\" #endif #endif /* directory for temporary files */ #if defined(_WIN32) # define LDAP_TMPDIR "C:\\." /* we don't have much of a choice */ #elif defined( _P_tmpdir ) # define LDAP_TMPDIR _P_tmpdir #elif defined( P_tmpdir ) # define LDAP_TMPDIR P_tmpdir #elif defined( _PATH_TMPDIR ) # define LDAP_TMPDIR _PATH_TMPDIR #else # define LDAP_TMPDIR LDAP_DIRSEP "tmp" #endif /* directories */ #ifndef LDAP_BINDIR #define LDAP_BINDIR "%BINDIR%" #endif #ifndef LDAP_SBINDIR #define LDAP_SBINDIR "%SBINDIR%" #endif #ifndef LDAP_DATADIR #define LDAP_DATADIR "%DATADIR%" #endif #ifndef LDAP_SYSCONFDIR #define LDAP_SYSCONFDIR "%SYSCONFDIR%" #endif #ifndef LDAP_LIBEXECDIR #define LDAP_LIBEXECDIR "%LIBEXECDIR%" #endif #ifndef LDAP_MODULEDIR #define LDAP_MODULEDIR "%MODULEDIR%" #endif #ifndef LDAP_RUNDIR #define LDAP_RUNDIR "%RUNDIR%" #endif #ifndef LDAP_LOCALEDIR #define LDAP_LOCALEDIR "%LOCALEDIR%" #endif #endif /* _LDAP_CONFIG_H */ openldap-2.4.42+dfsg/include/rewrite.h0000644000175000017500000001600712563404150016311 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 2000-2015 The OpenLDAP Foundation. * Portions Copyright 2000-2003 Pierangelo Masarati. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* ACKNOWLEDGEMENT: * This work was initially developed by Pierangelo Masarati for * inclusion in OpenLDAP Software. */ #ifndef REWRITE_H #define REWRITE_H /* * Default rewrite context */ #define REWRITE_DEFAULT_CONTEXT "default" /* * Rewrite engine states */ #define REWRITE_OFF 0x0000 #define REWRITE_ON 0x0001 #define REWRITE_DEFAULT REWRITE_OFF /* * Rewrite internal status returns */ #define REWRITE_SUCCESS LDAP_SUCCESS #define REWRITE_ERR LDAP_OTHER /* * Rewrite modes (input values for rewrite_info_init); determine the * behavior in case a null or non existent context is required: * * REWRITE_MODE_ERR error * REWRITE_MODE_OK no error but no rewrite * REWRITE_MODE_COPY_INPUT a copy of the input is returned * REWRITE_MODE_USE_DEFAULT the default context is used. */ #define REWRITE_MODE_ERR 0x0010 #define REWRITE_MODE_OK 0x0011 #define REWRITE_MODE_COPY_INPUT 0x0012 #define REWRITE_MODE_USE_DEFAULT 0x0013 /* * Rewrite status returns * * REWRITE_REGEXEC_OK success (result may be empty in case * of no match) * REWRITE_REGEXEC_ERR error (internal error, * misconfiguration, map not working ...) * REWRITE_REGEXEC_STOP internal use; never returned * REWRITE_REGEXEC_UNWILLING the server should issue an 'unwilling * to perform' error */ #define REWRITE_REGEXEC_OK (0) #define REWRITE_REGEXEC_ERR (-1) #define REWRITE_REGEXEC_STOP (-2) #define REWRITE_REGEXEC_UNWILLING (-3) #define REWRITE_REGEXEC_USER (1) /* and above: LDAP errors */ /* * Rewrite variable flags * REWRITE_VAR_INSERT insert mode (default) when adding * a variable; if not set during value * update, the variable is not inserted * if not present * REWRITE_VAR_UPDATE update mode (default) when updating * a variable; if not set during insert, * the value is not updated if the * variable already exists * REWRITE_VAR_COPY_NAME copy the variable name; if not set, * the name is not copied; be sure the * referenced string is available for * the entire life scope of the variable. * REWRITE_VAR_COPY_VALUE copy the variable value; if not set, * the value is not copied; be sure the * referenced string is available for * the entire life scope of the variable. */ #define REWRITE_VAR_NONE 0x0000 #define REWRITE_VAR_INSERT 0x0001 #define REWRITE_VAR_UPDATE 0x0002 #define REWRITE_VAR_COPY_NAME 0x0004 #define REWRITE_VAR_COPY_VALUE 0x0008 /* * Rewrite info */ struct rewrite_info; struct berval; /* avoid include */ LDAP_BEGIN_DECL /* * Inits the info */ LDAP_REWRITE_F (struct rewrite_info *) rewrite_info_init( int mode ); /* * Cleans up the info structure */ LDAP_REWRITE_F (int) rewrite_info_delete( struct rewrite_info **info ); /* * Parses a config line and takes actions to fit content in rewrite structure; * lines handled are of the form: * * rewriteEngine {on|off} * rewriteMaxPasses numPasses * rewriteContext contextName [alias aliasedRewriteContex] * rewriteRule pattern substPattern [ruleFlags] * rewriteMap mapType mapName [mapArgs] * rewriteParam paramName paramValue */ LDAP_REWRITE_F (int) rewrite_parse( struct rewrite_info *info, const char *fname, int lineno, int argc, char **argv ); /* * process a config file that was already opened. Uses rewrite_parse. */ LDAP_REWRITE_F (int) rewrite_read( FILE *fin, struct rewrite_info *info ); /* * Rewrites a string according to context. * If the engine is off, OK is returned, but the return string will be NULL. * In case of 'unwilling to perform', UNWILLING is returned, and the * return string will also be null. The same in case of error. * Otherwise, OK is returned, and result will hold a newly allocated string * with the rewriting. * * What to do in case of non-existing rewrite context is still an issue. * Four possibilities: * - error, * - ok with NULL result, * - ok with copy of string as result, * - use the default rewrite context. */ LDAP_REWRITE_F (int) rewrite( struct rewrite_info *info, const char *rewriteContext, const char *string, char **result ); /* * Same as above; the cookie relates the rewrite to a session */ LDAP_REWRITE_F (int) rewrite_session( struct rewrite_info *info, const char *rewriteContext, const char *string, const void *cookie, char **result ); /* * Inits a session */ LDAP_REWRITE_F (struct rewrite_session *) rewrite_session_init( struct rewrite_info *info, const void *cookie ); /* * Defines and inits a variable with session scope */ LDAP_REWRITE_F (int) rewrite_session_var_set_f( struct rewrite_info *info, const void *cookie, const char *name, const char *value, int flags ); #define rewrite_session_var_set(info, cookie, name, value) \ rewrite_session_var_set_f((info), (cookie), (name), (value), \ REWRITE_VAR_INSERT|REWRITE_VAR_UPDATE|REWRITE_VAR_COPY_NAME|REWRITE_VAR_COPY_VALUE) /* * Deletes a session */ LDAP_REWRITE_F (int) rewrite_session_delete( struct rewrite_info *info, const void *cookie ); /* * Params */ /* * Defines and inits a variable with global scope */ LDAP_REWRITE_F (int) rewrite_param_set( struct rewrite_info *info, const char *name, const char *value ); /* * Gets a var with global scope */ LDAP_REWRITE_F (int) rewrite_param_get( struct rewrite_info *info, const char *name, struct berval *value ); /* * Destroys the parameter tree */ LDAP_REWRITE_F (int) rewrite_param_destroy( struct rewrite_info *info ); /* * Mapping implementations */ struct rewrite_mapper; typedef void * (rewrite_mapper_config)( const char *fname, int lineno, int argc, char **argv ); typedef int (rewrite_mapper_apply)( void *ctx, const char *arg, struct berval *retval ); typedef int (rewrite_mapper_destroy)( void *ctx ); typedef struct rewrite_mapper { char *rm_name; rewrite_mapper_config *rm_config; rewrite_mapper_apply *rm_apply; rewrite_mapper_destroy *rm_destroy; } rewrite_mapper; /* For dynamic loading and unloading of mappers */ LDAP_REWRITE_F (int) rewrite_mapper_register( const rewrite_mapper *map ); LDAP_REWRITE_F (int) rewrite_mapper_unregister( const rewrite_mapper *map ); LDAP_REWRITE_F (const rewrite_mapper *) rewrite_mapper_find( const char *name ); LDAP_END_DECL #endif /* REWRITE_H */ openldap-2.4.42+dfsg/include/lutil.h0000644000175000017500000002146012563404150015760 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #ifndef _LUTIL_H #define _LUTIL_H 1 #include #include /* * Include file for LDAP utility routine */ LDAP_BEGIN_DECL /* n octets encode into ceiling(n/3) * 4 bytes */ /* Avoid floating point math through extra padding */ #define LUTIL_BASE64_ENCODE_LEN(n) (((n)+2)/3 * 4) #define LUTIL_BASE64_DECODE_LEN(n) ((n)/4*3) /* ISC Base64 Routines */ /* base64.c */ LDAP_LUTIL_F( int ) lutil_b64_ntop LDAP_P(( unsigned char const *, size_t, char *, size_t)); LDAP_LUTIL_F( int ) lutil_b64_pton LDAP_P(( char const *, unsigned char *, size_t)); /* detach.c */ LDAP_LUTIL_F( int ) lutil_detach LDAP_P(( int debug, int do_close)); /* entropy.c */ LDAP_LUTIL_F( int ) lutil_entropy LDAP_P(( unsigned char *buf, ber_len_t nbytes )); /* passfile.c */ struct berval; /* avoid pulling in lber.h */ LDAP_LUTIL_F( int ) lutil_get_filed_password LDAP_P(( const char *filename, struct berval * )); /* passwd.c */ struct lutil_pw_scheme; #define LUTIL_PASSWD_OK (0) #define LUTIL_PASSWD_ERR (-1) typedef int (LUTIL_PASSWD_CHK_FUNC)( const struct berval *scheme, const struct berval *passwd, const struct berval *cred, const char **text ); typedef int (LUTIL_PASSWD_HASH_FUNC) ( const struct berval *scheme, const struct berval *passwd, struct berval *hash, const char **text ); LDAP_LUTIL_F( int ) lutil_passwd_add LDAP_P(( struct berval *scheme, LUTIL_PASSWD_CHK_FUNC *chk_fn, LUTIL_PASSWD_HASH_FUNC *hash_fn )); LDAP_LUTIL_F( void ) lutil_passwd_init LDAP_P(( void )); LDAP_LUTIL_F( void ) lutil_passwd_destroy LDAP_P(( void )); LDAP_LUTIL_F( int ) lutil_authpasswd LDAP_P(( const struct berval *passwd, /* stored password */ const struct berval *cred, /* user supplied value */ const char **methods )); LDAP_LUTIL_F( int ) lutil_authpasswd_hash LDAP_P(( const struct berval *cred, struct berval **passwd, /* password to store */ struct berval **salt, /* salt to store */ const char *method )); #ifdef SLAPD_CRYPT typedef int (lutil_cryptfunc) LDAP_P(( const char *key, const char *salt, char **hash )); LDAP_LUTIL_V (lutil_cryptfunc *) lutil_cryptptr; #endif LDAP_LUTIL_F( int ) lutil_passwd LDAP_P(( const struct berval *passwd, /* stored password */ const struct berval *cred, /* user supplied value */ const char **methods, const char **text )); /* error message */ LDAP_LUTIL_F( int ) lutil_passwd_generate LDAP_P(( struct berval *pw, ber_len_t )); LDAP_LUTIL_F( int ) lutil_passwd_hash LDAP_P(( const struct berval *passwd, const char *method, struct berval *hash, const char **text )); LDAP_LUTIL_F( int ) lutil_passwd_scheme LDAP_P(( const char *scheme )); LDAP_LUTIL_F( int ) lutil_salt_format LDAP_P(( const char *format )); LDAP_LUTIL_F( int ) lutil_passwd_string64 LDAP_P(( const struct berval *sc, const struct berval *hash, struct berval *b64, const struct berval *salt )); /* utils.c */ LDAP_LUTIL_F( char* ) lutil_progname LDAP_P(( const char* name, int argc, char *argv[] )); typedef struct lutil_tm { int tm_sec; /* seconds 0-60 (1 leap second) */ int tm_min; /* minutes 0-59 */ int tm_hour; /* hours 0-23 */ int tm_mday; /* day 1-31 */ int tm_mon; /* month 0-11 */ int tm_year; /* year - 1900 */ int tm_usec; /* microseconds */ int tm_usub; /* submicro */ } lutil_tm; typedef struct lutil_timet { unsigned int tt_sec; /* seconds since 1900 */ int tt_gsec; /* seconds since 1900, high 7 bits */ unsigned int tt_usec; /* microseconds */ } lutil_timet; /* Parse a timestamp string into a structure */ LDAP_LUTIL_F( int ) lutil_parsetime LDAP_P(( char *atm, struct lutil_tm * )); /* Convert structured time to time in seconds since 1900 */ LDAP_LUTIL_F( int ) lutil_tm2time LDAP_P(( struct lutil_tm *, struct lutil_timet * )); #ifdef _WIN32 LDAP_LUTIL_F( void ) lutil_slashpath LDAP_P(( char* path )); #define LUTIL_SLASHPATH(p) lutil_slashpath(p) #else #define LUTIL_SLASHPATH(p) #endif LDAP_LUTIL_F( char* ) lutil_strcopy LDAP_P(( char *dst, const char *src )); LDAP_LUTIL_F( char* ) lutil_strncopy LDAP_P(( char *dst, const char *src, size_t n )); LDAP_LUTIL_F( char* ) lutil_memcopy LDAP_P(( char *dst, const char *src, size_t n )); #define lutil_strbvcopy(a, bv) lutil_memcopy((a),(bv)->bv_val,(bv)->bv_len) struct tm; /* use this macro to statically allocate buffer for lutil_gentime */ #define LDAP_LUTIL_GENTIME_BUFSIZE 22 #define lutil_gentime(s,m,t) lutil_localtime((s),(m),(t),0) LDAP_LUTIL_F( size_t ) lutil_localtime LDAP_P(( char *s, size_t smax, const struct tm *tm, long delta )); #ifndef HAVE_MKSTEMP LDAP_LUTIL_F( int ) mkstemp LDAP_P (( char * template )); #endif /* sockpair.c */ LDAP_LUTIL_F( int ) lutil_pair( ber_socket_t sd[2] ); /* uuid.c */ /* use this macro to allocate buffer for lutil_uuidstr */ #define LDAP_LUTIL_UUIDSTR_BUFSIZE 40 LDAP_LUTIL_F( size_t ) lutil_uuidstr( char *buf, size_t len ); LDAP_LUTIL_F( int ) lutil_uuidstr_from_normalized( char *uuid, size_t uuidlen, char *buf, size_t buflen ); /* * Sometimes not all declarations in a header file are needed. * An indicator to this is whether or not the symbol's type has * been defined. Thus, we don't need to include a symbol if * its type has not been defined through another header file. */ #ifdef HAVE_NT_SERVICE_MANAGER LDAP_LUTIL_V (int) is_NT_Service; #ifdef _LDAP_PVT_THREAD_H LDAP_LUTIL_V (ldap_pvt_thread_cond_t) started_event; #endif /* _LDAP_PVT_THREAD_H */ /* macros are different between Windows and Mingw */ #if defined(_WINSVC_H) || defined(_WINSVC_) LDAP_LUTIL_V (SERVICE_STATUS) lutil_ServiceStatus; LDAP_LUTIL_V (SERVICE_STATUS_HANDLE) hlutil_ServiceStatus; #endif /* _WINSVC_H */ LDAP_LUTIL_F (void) lutil_CommenceStartupProcessing( char *serverName, void (*stopper)(int)) ; LDAP_LUTIL_F (void) lutil_ReportShutdownComplete( void ); LDAP_LUTIL_F (void *) lutil_getRegParam( char *svc, char *value ); LDAP_LUTIL_F (int) lutil_srv_install( char* service, char * displayName, char* filename, int auto_start ); LDAP_LUTIL_F (int) lutil_srv_remove ( char* service, char* filename ); #endif /* HAVE_NT_SERVICE_MANAGER */ #ifdef HAVE_NT_EVENT_LOG LDAP_LUTIL_F (void) lutil_LogStartedEvent( char *svc, int slap_debug, char *configfile, char *urls ); LDAP_LUTIL_F (void) lutil_LogStoppedEvent( char *svc ); #endif #ifdef HAVE_EBCDIC /* Generally this has only been used to put '\n' to stdout. We need to * make sure it is output in EBCDIC. */ #undef putchar #undef putc #define putchar(c) putc((c), stdout) #define putc(c,fp) do { char x=(c); __atoe_l(&x,1); putc(x,fp); } while(0) #endif LDAP_LUTIL_F (int) lutil_atoix( int *v, const char *s, int x ); LDAP_LUTIL_F (int) lutil_atoux( unsigned *v, const char *s, int x ); LDAP_LUTIL_F (int) lutil_atolx( long *v, const char *s, int x ); LDAP_LUTIL_F (int) lutil_atoulx( unsigned long *v, const char *s, int x ); #define lutil_atoi(v, s) lutil_atoix((v), (s), 10) #define lutil_atou(v, s) lutil_atoux((v), (s), 10) #define lutil_atol(v, s) lutil_atolx((v), (s), 10) #define lutil_atoul(v, s) lutil_atoulx((v), (s), 10) #ifdef HAVE_LONG_LONG #if defined(HAVE_STRTOLL) || defined(HAVE_STRTOQ) LDAP_LUTIL_F (int) lutil_atollx( long long *v, const char *s, int x ); #define lutil_atoll(v, s) lutil_atollx((v), (s), 10) #endif /* HAVE_STRTOLL || HAVE_STRTOQ */ #if defined(HAVE_STRTOULL) || defined(HAVE_STRTOUQ) LDAP_LUTIL_F (int) lutil_atoullx( unsigned long long *v, const char *s, int x ); #define lutil_atoull(v, s) lutil_atoullx((v), (s), 10) #endif /* HAVE_STRTOULL || HAVE_STRTOUQ */ #endif /* HAVE_LONG_LONG */ LDAP_LUTIL_F (int) lutil_str2bin( struct berval *in, struct berval *out, void *ctx ); /* Parse and unparse time intervals */ LDAP_LUTIL_F (int) lutil_parse_time( const char *in, unsigned long *tp ); LDAP_LUTIL_F (int) lutil_unparse_time( char *buf, size_t buflen, unsigned long t ); #ifdef timerdiv #define lutil_timerdiv timerdiv #else /* ! timerdiv */ /* works inplace (x == t) */ #define lutil_timerdiv(t,d,x) \ do { \ time_t s = (t)->tv_sec; \ assert( d > 0 ); \ (x)->tv_sec = s / d; \ (x)->tv_usec = ( (t)->tv_usec + 1000000 * ( s % d ) ) / d; \ } while ( 0 ) #endif /* ! timerdiv */ #ifdef timermul #define lutil_timermul timermul #else /* ! timermul */ /* works inplace (x == t) */ #define lutil_timermul(t,m,x) \ do { \ time_t u = (t)->tv_usec * m; \ assert( m > 0 ); \ (x)->tv_sec = (t)->tv_sec * m + u / 1000000; \ (x)->tv_usec = u % 1000000; \ } while ( 0 ); #endif /* ! timermul */ LDAP_END_DECL #endif /* _LUTIL_H */ openldap-2.4.42+dfsg/include/ldif.h0000644000175000017500000001112412563404150015541 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (c) 1996 Regents of the University of Michigan. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of Michigan at Ann Arbor. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. */ #ifndef _LDIF_H #define _LDIF_H #include LDAP_BEGIN_DECL /* This is NOT a bogus extern declaration (unlike ldap_debug) */ LDAP_LDIF_V (int) ldif_debug; #define LDIF_LINE_WIDTH 76 /* default maximum length of LDIF lines */ #define LDIF_LINE_WIDTH_MAX ((ber_len_t)-1) /* maximum length of LDIF lines */ #define LDIF_LINE_WIDTH_WRAP(wrap) ((wrap) == 0 ? LDIF_LINE_WIDTH : (wrap)) /* * Macro to calculate maximum number of bytes that the base64 equivalent * of an item that is "len" bytes long will take up. Base64 encoding * uses one byte for every six bits in the value plus up to two pad bytes. */ #define LDIF_BASE64_LEN(len) (((len) * 4 / 3 ) + 3) /* * Macro to calculate maximum size that an LDIF-encoded type (length * tlen) and value (length vlen) will take up: room for type + ":: " + * first newline + base64 value + continued lines. Each continued line * needs room for a newline and a leading space character. */ #define LDIF_SIZE_NEEDED(nlen,vlen) \ ((nlen) + 4 + LDIF_BASE64_LEN(vlen) \ + ((LDIF_BASE64_LEN(vlen) + (nlen) + 3) / (LDIF_LINE_WIDTH-1) * 2 )) #define LDIF_SIZE_NEEDED_WRAP(nlen,vlen,wrap) \ ((nlen) + 4 + LDIF_BASE64_LEN(vlen) \ + ((wrap) == 0 ? ((LDIF_BASE64_LEN(vlen) + (nlen) + 3) / ( LDIF_LINE_WIDTH-1 ) * 2 ) : \ ((wrap) == LDIF_LINE_WIDTH_MAX ? 0 : ((LDIF_BASE64_LEN(vlen) + (nlen) + 3) / (wrap-1) * 2 )))) LDAP_LDIF_F( int ) ldif_parse_line LDAP_P(( LDAP_CONST char *line, char **name, char **value, ber_len_t *vlen )); LDAP_LDIF_F( int ) ldif_parse_line2 LDAP_P(( char *line, struct berval *type, struct berval *value, int *freeval )); LDAP_LDIF_F( FILE * ) ldif_open_url LDAP_P(( LDAP_CONST char *urlstr )); LDAP_LDIF_F( int ) ldif_fetch_url LDAP_P(( LDAP_CONST char *line, char **value, ber_len_t *vlen )); LDAP_LDIF_F( char * ) ldif_getline LDAP_P(( char **next )); LDAP_LDIF_F( int ) ldif_countlines LDAP_P(( LDAP_CONST char *line )); /* ldif_ropen, rclose, read_record - just for reading LDIF files, * no special open/close needed to write LDIF files. */ typedef struct LDIFFP { FILE *fp; struct LDIFFP *prev; } LDIFFP; LDAP_LDIF_F( LDIFFP * ) ldif_open LDAP_P(( LDAP_CONST char *file, LDAP_CONST char *mode )); LDAP_LDIF_F( void ) ldif_close LDAP_P(( LDIFFP * )); LDAP_LDIF_F( int ) ldif_read_record LDAP_P(( LDIFFP *fp, unsigned long *lineno, char **bufp, int *buflen )); LDAP_LDIF_F( int ) ldif_must_b64_encode_register LDAP_P(( LDAP_CONST char *name, LDAP_CONST char *oid )); LDAP_LDIF_F( void ) ldif_must_b64_encode_release LDAP_P(( void )); #define LDIF_PUT_NOVALUE 0x0000 /* no value */ #define LDIF_PUT_VALUE 0x0001 /* value w/ auto detection */ #define LDIF_PUT_TEXT 0x0002 /* assume text */ #define LDIF_PUT_BINARY 0x0004 /* assume binary (convert to base64) */ #define LDIF_PUT_B64 0x0008 /* pre-converted base64 value */ #define LDIF_PUT_COMMENT 0x0010 /* comment */ #define LDIF_PUT_URL 0x0020 /* url */ #define LDIF_PUT_SEP 0x0040 /* separator */ LDAP_LDIF_F( void ) ldif_sput LDAP_P(( char **out, int type, LDAP_CONST char *name, LDAP_CONST char *val, ber_len_t vlen )); LDAP_LDIF_F( void ) ldif_sput_wrap LDAP_P(( char **out, int type, LDAP_CONST char *name, LDAP_CONST char *val, ber_len_t vlen, ber_len_t wrap )); LDAP_LDIF_F( char * ) ldif_put LDAP_P(( int type, LDAP_CONST char *name, LDAP_CONST char *val, ber_len_t vlen )); LDAP_LDIF_F( char * ) ldif_put_wrap LDAP_P(( int type, LDAP_CONST char *name, LDAP_CONST char *val, ber_len_t vlen, ber_len_t wrap )); LDAP_LDIF_F( int ) ldif_is_not_printable LDAP_P(( LDAP_CONST char *val, ber_len_t vlen )); LDAP_END_DECL #endif /* _LDIF_H */ openldap-2.4.42+dfsg/include/sysexits-compat.h0000644000175000017500000001171712563404150020007 0ustar ryanryan/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* Portions Copyright (c) 1987 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley. The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * @(#)sysexits.h 4.5 (Berkeley) 7/6/88 */ /* ** SYSEXITS.H -- Exit status codes for system programs. ** ** This include file attempts to categorize possible error ** exit statuses for system programs, notably delivermail ** and the Berkeley network. ** ** Error numbers begin at EX__BASE to reduce the possibility of ** clashing with other exit statuses that random programs may ** already return. The meaning of the codes is approximately ** as follows: ** ** EX_USAGE -- The command was used incorrectly, e.g., with ** the wrong number of arguments, a bad flag, a bad ** syntax in a parameter, or whatever. ** EX_DATAERR -- The input data was incorrect in some way. ** This should only be used for user's data & not ** system files. ** EX_NOINPUT -- An input file (not a system file) did not ** exist or was not readable. This could also include ** errors like "No message" to a mailer (if it cared ** to catch it). ** EX_NOUSER -- The user specified did not exist. This might ** be used for mail addresses or remote logins. ** EX_NOHOST -- The host specified did not exist. This is used ** in mail addresses or network requests. ** EX_UNAVAILABLE -- A service is unavailable. This can occur ** if a support program or file does not exist. This ** can also be used as a catchall message when something ** you wanted to do doesn't work, but you don't know ** why. ** EX_SOFTWARE -- An internal software error has been detected. ** This should be limited to non-operating system related ** errors as possible. ** EX_OSERR -- An operating system error has been detected. ** This is intended to be used for such things as "cannot ** fork", "cannot create pipe", or the like. It includes ** things like getuid returning a user that does not ** exist in the passwd file. ** EX_OSFILE -- Some system file (e.g., /etc/passwd, /etc/utmp, ** etc.) does not exist, cannot be opened, or has some ** sort of error (e.g., syntax error). ** EX_CANTCREAT -- A (user specified) output file cannot be ** created. ** EX_IOERR -- An error occurred while doing I/O on some file. ** EX_TEMPFAIL -- temporary failure, indicating something that ** is not really an error. In sendmail, this means ** that a mailer (e.g.) could not create a connection, ** and the request should be reattempted later. ** EX_PROTOCOL -- the remote system returned something that ** was "not possible" during a protocol exchange. ** EX_NOPERM -- You did not have sufficient permission to ** perform the operation. This is not intended for ** file system problems, which should use NOINPUT or ** CANTCREAT, but rather for higher level permissions. ** For example, kre uses this to restrict who students ** can send mail to. ** ** Maintained by Eric Allman (eric@berkeley, ucbvax!eric) -- ** please mail changes to me. ** ** @(#)sysexits.h 4.5 7/6/88 */ # define EX_OK 0 /* successful termination */ # define EX__BASE 64 /* base value for error messages */ # define EX_USAGE 64 /* command line usage error */ # define EX_DATAERR 65 /* data format error */ # define EX_NOINPUT 66 /* cannot open input */ # define EX_NOUSER 67 /* addressee unknown */ # define EX_NOHOST 68 /* host name unknown */ # define EX_UNAVAILABLE 69 /* service unavailable */ # define EX_SOFTWARE 70 /* internal software error */ # define EX_OSERR 71 /* system error (e.g., can't fork) */ # define EX_OSFILE 72 /* critical OS file missing */ # define EX_CANTCREAT 73 /* can't create (user) output file */ # define EX_IOERR 74 /* input/output error */ # define EX_TEMPFAIL 75 /* temp failure; user is invited to retry */ # define EX_PROTOCOL 76 /* remote error in protocol */ # define EX_NOPERM 77 /* permission denied */ # define EX_CONFIG 78 /* configuration error */ openldap-2.4.42+dfsg/configure.in0000644000175000017500000027335512563404150015360 0ustar ryanryandnl $OpenLDAP$ dnl This work is part of OpenLDAP Software . dnl dnl Copyright 1998-2015 The OpenLDAP Foundation. dnl All rights reserved. dnl dnl Redistribution and use in source and binary forms, with or without dnl modification, are permitted only as authorized by the OpenLDAP dnl Public License. dnl dnl A copy of this license is available in the file LICENSE in the dnl top-level directory of the distribution or, alternatively, at dnl . dnl dnl ---------------------------------------------------------------- dnl Disable config.cache! define([AC_CACHE_LOAD], )dnl define([AC_CACHE_SAVE], )dnl dnl ---------------------------------------------------------------- dnl Disable libtool 1.5 support for languages we don't use define([AC_LIBTOOL_LANG_CXX_CONFIG], [:])dnl define([AC_LIBTOOL_LANG_F77_CONFIG], [:])dnl define([AC_LIBTOOL_LANG_GCJ_CONFIG], [:])dnl dnl ================================================================ dnl Configure.in for OpenLDAP AC_COPYRIGHT([[Copyright 1998-2015 The OpenLDAP Foundation. All rights reserved. Restrictions apply, see COPYRIGHT and LICENSE files.]]) AC_REVISION([$Id: 47c7929401c409f8d9308cfee042e7bef5a3b4bb $]) AC_INIT([OpenLDAP],,[http://www.openldap.org/its/]) m4_define([AC_PACKAGE_BUGREPORT],[]) AC_CONFIG_SRCDIR(build/version.sh)dnl dnl ---------------------------------------------------------------- dnl OpenLDAP Autoconf Macros builtin(include, build/openldap.m4)dnl dnl ================================================================ AC_CONFIG_AUX_DIR(build)dnl eval `$ac_aux_dir/version.sh` if test -z "$OL_STRING"; then AC_MSG_ERROR([could not determine version]) fi if test -f "$ac_aux_dir/shtool" && test ! -d $ac_aux_dir/shtool; then ac_cv_shtool="$ac_aux_dir/shtool" else AC_MSG_ERROR([no shtool found in $ac_aux_dir]) fi SHTOOL="$ac_cv_shtool" dnl AC_SUBST(SHTOOL)dnl TB="" TN="" if test -t 1; then TB="`$SHTOOL echo -e '%B' 2>/dev/null`" TN="`$SHTOOL echo -e '%b' 2>/dev/null`" fi OPENLDAP_REPO="" if test -d $ac_aux_dir/../.git; then OPENLDAP_REPO="(from Git clone) " elif test -d $ac_aux_dir/CVS; then OPENLDAP_REPO="(from CVS checkout) " fi echo "Configuring ${TB}${OL_STRING}${TN} ${OPENLDAP_REPO}..." dnl Determine host platform dnl we try not to use this for much AC_CANONICAL_TARGET([]) AM_INIT_AUTOMAKE([$OL_PACKAGE],[$OL_VERSION], [no defines])dnl AC_SUBST(PACKAGE)dnl AC_SUBST(VERSION)dnl AC_DEFINE_UNQUOTED(OPENLDAP_PACKAGE,"$PACKAGE",Package) AC_DEFINE_UNQUOTED(OPENLDAP_VERSION,"$VERSION",Version) AC_DEFINE_UNQUOTED(LDAP_VENDOR_VERSION,$OL_API_INC,Version) AC_DEFINE_UNQUOTED(LDAP_VENDOR_VERSION_MAJOR,$OL_MAJOR,Major) AC_DEFINE_UNQUOTED(LDAP_VENDOR_VERSION_MINOR,$OL_MINOR,Minor) AC_DEFINE_UNQUOTED(LDAP_VENDOR_VERSION_PATCH,$OL_PATCH,Patch) OPENLDAP_LIBRELEASE=$OL_API_LIB_RELEASE AC_SUBST(OPENLDAP_LIBRELEASE)dnl OPENLDAP_LIBVERSION=$OL_API_LIB_VERSION AC_SUBST(OPENLDAP_LIBVERSION)dnl OPENLDAP_RELEASE_DATE="$OL_RELEASE_DATE" AC_SUBST(OPENLDAP_RELEASE_DATE)dnl dnl We use autoconf features new to 2.59. Later versions like won't work. dnl aclocal.m4 should be built using aclocal from automake 1.5 dnl libtool 1.5 should be installed. AC_PREREQ(2.59)dnl Required Autoconf version AH_TOP([ /* begin of portable.h.pre */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ #ifndef _LDAP_PORTABLE_H #define _LDAP_PORTABLE_H /* define this if needed to get reentrant functions */ #ifndef REENTRANT #undef REENTRANT #endif #ifndef _REENTRANT #undef _REENTRANT #endif /* define this if needed to get threadsafe functions */ #ifndef THREADSAFE #undef THREADSAFE #endif #ifndef _THREADSAFE #undef _THREADSAFE #endif #ifndef THREAD_SAFE #undef THREAD_SAFE #endif #ifndef _THREAD_SAFE #undef _THREAD_SAFE #endif #ifndef _SGI_MP_SOURCE #undef _SGI_MP_SOURCE #endif /* end of portable.h.pre */ ]) AH_BOTTOM([ /* begin of portable.h.post */ #ifdef _WIN32 /* don't suck in all of the win32 api */ # define WIN32_LEAN_AND_MEAN 1 #endif #ifndef LDAP_NEEDS_PROTOTYPES /* force LDAP_P to always include prototypes */ #define LDAP_NEEDS_PROTOTYPES 1 #endif #ifndef LDAP_REL_ENG #if (LDAP_VENDOR_VERSION == 000000) && !defined(LDAP_DEVEL) #define LDAP_DEVEL #endif #if defined(LDAP_DEVEL) && !defined(LDAP_TEST) #define LDAP_TEST #endif #endif #ifdef HAVE_STDDEF_H # include #endif #ifdef HAVE_EBCDIC /* ASCII/EBCDIC converting replacements for stdio funcs * vsnprintf and snprintf are used too, but they are already * checked by the configure script */ #define fputs ber_pvt_fputs #define fgets ber_pvt_fgets #define printf ber_pvt_printf #define fprintf ber_pvt_fprintf #define vfprintf ber_pvt_vfprintf #define vsprintf ber_pvt_vsprintf #endif #include "ac/fdset.h" #include "ldap_cdefs.h" #include "ldap_features.h" #include "ac/assert.h" #include "ac/localize.h" #endif /* _LDAP_PORTABLE_H */ /* end of portable.h.post */ ]) AC_CONFIG_HEADERS([include/portable.h:include/portable.hin]) AC_CONFIG_HEADERS([include/ldap_features.h:include/ldap_features.hin]) AC_CONFIG_HEADERS([include/lber_types.h:include/lber_types.hin]) dnl ================================================================ dnl Start Args AC_MSG_CHECKING(configure arguments) AC_PREFIX_DEFAULT(/usr/local) top_builddir=`pwd` AC_SUBST(top_builddir)dnl dnl ---------------------------------------------------------------- dnl --with-subdir ldap_subdir="/openldap" AC_ARG_WITH(subdir, [ --with-subdir=DIR change default subdirectory used for installs], [case "$withval" in no) ldap_subdir="" ;; yes) ;; /*|\\*) ldap_subdir="$withval" ;; *) ldap_subdir="/$withval" ;; esac ])dnl AC_SUBST(ldap_subdir)dnl dnl ---------------------------------------------------------------- dnl General "enable" options dnl set default to traditional to enable the original debug style OL_ARG_ENABLE(debug,[ --enable-debug enable debugging], yes, [no yes traditional])dnl OL_ARG_ENABLE(dynamic,[ --enable-dynamic enable linking built binaries with dynamic libs], no)dnl OL_ARG_ENABLE(syslog,[ --enable-syslog enable syslog support], auto)dnl OL_ARG_ENABLE(proctitle,[ --enable-proctitle enable proctitle support], yes)dnl dnl OL_ARG_ENABLE(referrals,[ --enable-referrals enable LDAPv2+ Referrals (experimental)], no)dnl ol_enable_referrals=${ol_enable_referrals-no} OL_ARG_ENABLE(ipv6,[ --enable-ipv6 enable IPv6 support], auto)dnl OL_ARG_ENABLE(local,[ --enable-local enable AF_LOCAL (AF_UNIX) socket support], auto)dnl dnl ---------------------------------------------------------------- dnl General "with" options OL_ARG_WITH(cyrus_sasl,[ --with-cyrus-sasl with Cyrus SASL support], auto, [auto yes no] ) OL_ARG_WITH(fetch,[ --with-fetch with fetch(3) URL support], auto, [auto yes no] ) OL_ARG_WITH(threads,[ --with-threads with threads], auto, [auto nt posix mach pth lwp yes no manual] ) OL_ARG_WITH(tls,[ --with-tls with TLS/SSL support auto|openssl|gnutls|moznss], auto, [auto openssl gnutls moznss yes no] ) OL_ARG_WITH(yielding_select, [ --with-yielding-select with implicitly yielding select], auto, [auto yes no manual] ) OL_ARG_WITH(mp, [ --with-mp with multiple precision statistics auto|longlong|long|bignum|gmp], auto, [auto longlong long bignum gmp yes no]) OL_ARG_WITH(odbc, [ --with-odbc with specific ODBC support iodbc|unixodbc|odbc32|auto], auto, [auto iodbc unixodbc odbc32] ) dnl ---------------------------------------------------------------- dnl Server options dnl ---------------------------------------------------------------- dnl ---------------------------------------------------------------- dnl SLAPD OPTIONS AC_ARG_ENABLE(xxslapdoptions,[ SLAPD (Standalone LDAP Daemon) Options:]) OL_ARG_ENABLE(slapd,[ --enable-slapd enable building slapd], yes)dnl OL_ARG_ENABLE(dynacl,[ --enable-dynacl enable run-time loadable ACL support (experimental)], no)dnl OL_ARG_ENABLE(aci,[ --enable-aci enable per-object ACIs (experimental)], no, [no yes mod])dnl OL_ARG_ENABLE(cleartext,[ --enable-cleartext enable cleartext passwords], yes)dnl OL_ARG_ENABLE(crypt,[ --enable-crypt enable crypt(3) passwords], no)dnl OL_ARG_ENABLE(lmpasswd,[ --enable-lmpasswd enable LAN Manager passwords], no)dnl OL_ARG_ENABLE(spasswd,[ --enable-spasswd enable (Cyrus) SASL password verification], no)dnl OL_ARG_ENABLE(modules,[ --enable-modules enable dynamic module support], no)dnl OL_ARG_ENABLE(rewrite,[ --enable-rewrite enable DN rewriting in back-ldap and rwm overlay], auto)dnl OL_ARG_ENABLE(rlookups,[ --enable-rlookups enable reverse lookups of client hostnames], no)dnl OL_ARG_ENABLE(slapi,[ --enable-slapi enable SLAPI support (experimental)], no)dnl OL_ARG_ENABLE(slp,[ --enable-slp enable SLPv2 support], no)dnl OL_ARG_ENABLE(wrappers,[ --enable-wrappers enable tcp wrapper support], no)dnl dnl ---------------------------------------------------------------- dnl SLAPD Backend Options Backends="bdb \ dnssrv \ hdb \ ldap \ mdb \ meta \ monitor \ ndb \ null \ passwd \ perl \ relay \ shell \ sock \ sql" AC_ARG_ENABLE(xxslapbackends,[ SLAPD Backend Options:]) OL_ARG_ENABLE(backends,[ --enable-backends enable all available backends], --, [no yes mod])dnl OL_ARG_ENABLE(bdb,[ --enable-bdb enable Berkeley DB backend], yes, [no yes mod], ol_enable_backends)dnl OL_ARG_ENABLE(dnssrv,[ --enable-dnssrv enable dnssrv backend], no, [no yes mod], ol_enable_backends)dnl OL_ARG_ENABLE(hdb,[ --enable-hdb enable Hierarchical DB backend], yes, [no yes mod], ol_enable_backends)dnl OL_ARG_ENABLE(ldap,[ --enable-ldap enable ldap backend], no, [no yes mod], ol_enable_backends)dnl OL_ARG_ENABLE(mdb,[ --enable-mdb enable mdb database backend], yes, [no yes mod], ol_enable_backends)dnl OL_ARG_ENABLE(meta,[ --enable-meta enable metadirectory backend], no, [no yes mod], ol_enable_backends)dnl OL_ARG_ENABLE(monitor,[ --enable-monitor enable monitor backend], yes, [no yes mod], ol_enable_backends)dnl OL_ARG_ENABLE(ndb,[ --enable-ndb enable MySQL NDB Cluster backend], no, [no yes mod], ol_enable_backends)dnl OL_ARG_ENABLE(null,[ --enable-null enable null backend], no, [no yes mod], ol_enable_backends)dnl OL_ARG_ENABLE(passwd,[ --enable-passwd enable passwd backend], no, [no yes mod], ol_enable_backends)dnl OL_ARG_ENABLE(perl,[ --enable-perl enable perl backend], no, [no yes mod], ol_enable_backends)dnl OL_ARG_ENABLE(relay,[ --enable-relay enable relay backend], yes, [no yes mod], ol_enable_backends)dnl OL_ARG_ENABLE(shell,[ --enable-shell enable shell backend], no, [no yes mod], ol_enable_backends)dnl OL_ARG_ENABLE(sock,[ --enable-sock enable sock backend], no, [no yes mod], ol_enable_backends)dnl OL_ARG_ENABLE(sql,[ --enable-sql enable sql backend], no, [no yes mod], ol_enable_backends)dnl dnl ---------------------------------------------------------------- dnl SLAPD Overlay Options Overlays="accesslog \ auditlog \ collect \ constraint \ dds \ deref \ dyngroup \ dynlist \ memberof \ ppolicy \ proxycache \ refint \ retcode \ rwm \ seqmod \ sssvlv \ syncprov \ translucent \ unique \ valsort" AC_ARG_ENABLE(xxslapoverlays,[ SLAPD Overlay Options:]) OL_ARG_ENABLE(overlays,[ --enable-overlays enable all available overlays], --, [no yes mod])dnl OL_ARG_ENABLE(accesslog,[ --enable-accesslog In-Directory Access Logging overlay], no, [no yes mod], ol_enable_overlays) OL_ARG_ENABLE(auditlog,[ --enable-auditlog Audit Logging overlay], no, [no yes mod], ol_enable_overlays) OL_ARG_ENABLE(collect,[ --enable-collect Collect overlay], no, [no yes mod], ol_enable_overlays) OL_ARG_ENABLE(constraint,[ --enable-constraint Attribute Constraint overlay], no, [no yes mod], ol_enable_overlays) OL_ARG_ENABLE(dds,[ --enable-dds Dynamic Directory Services overlay], no, [no yes mod], ol_enable_overlays) OL_ARG_ENABLE(deref,[ --enable-deref Dereference overlay], no, [no yes mod], ol_enable_overlays) OL_ARG_ENABLE(dyngroup,[ --enable-dyngroup Dynamic Group overlay], no, [no yes mod], ol_enable_overlays) OL_ARG_ENABLE(dynlist,[ --enable-dynlist Dynamic List overlay], no, [no yes mod], ol_enable_overlays) OL_ARG_ENABLE(memberof,[ --enable-memberof Reverse Group Membership overlay], no, [no yes mod], ol_enable_overlays) OL_ARG_ENABLE(ppolicy,[ --enable-ppolicy Password Policy overlay], no, [no yes mod], ol_enable_overlays) OL_ARG_ENABLE(proxycache,[ --enable-proxycache Proxy Cache overlay], no, [no yes mod], ol_enable_overlays) OL_ARG_ENABLE(refint,[ --enable-refint Referential Integrity overlay], no, [no yes mod], ol_enable_overlays) OL_ARG_ENABLE(retcode,[ --enable-retcode Return Code testing overlay], no, [no yes mod], ol_enable_overlays) OL_ARG_ENABLE(rwm,[ --enable-rwm Rewrite/Remap overlay], no, [no yes mod], ol_enable_overlays) OL_ARG_ENABLE(seqmod,[ --enable-seqmod Sequential Modify overlay], no, [no yes mod], ol_enable_overlays) OL_ARG_ENABLE(sssvlv,[ --enable-sssvlv ServerSideSort/VLV overlay], no, [no yes mod], ol_enable_overlays) OL_ARG_ENABLE(syncprov,[ --enable-syncprov Syncrepl Provider overlay], yes, [no yes mod], ol_enable_overlays) OL_ARG_ENABLE(translucent,[ --enable-translucent Translucent Proxy overlay], no, [no yes mod], ol_enable_overlays) OL_ARG_ENABLE(unique,[ --enable-unique Attribute Uniqueness overlay], no, [no yes mod], ol_enable_overlays) OL_ARG_ENABLE(valsort,[ --enable-valsort Value Sorting overlay], no, [no yes mod], ol_enable_overlays) dnl ---------------------------------------------------------------- AC_ARG_ENABLE(xxliboptions,[ Library Generation & Linking Options]) AC_ENABLE_STATIC AC_ENABLE_SHARED dnl ---------------------------------------------------------------- # validate options if test $ol_enable_slapd = no ; then dnl SLAPD was specificallly disabled if test $ol_enable_slapi = yes ; then AC_MSG_WARN([slapd disabled, ignoring --enable-slapi argument]) fi case "$ol_enable_backends" in yes | mod) AC_MSG_WARN([slapd disabled, ignoring --enable-backends argument]) esac for i in $Backends; do eval "ol_tmp=\$ol_enable_$i" if test $ol_tmp != no ; then AC_MSG_WARN([slapd disabled, ignoring --enable-$i argument]) eval "ol_enable_$i=no" fi done if test $ol_enable_modules = yes ; then AC_MSG_WARN([slapd disabled, ignoring --enable-modules argument]) fi if test $ol_enable_wrappers = yes ; then AC_MSG_WARN([slapd disabled, ignoring --enable-wrappers argument]) fi if test $ol_enable_rlookups = yes ; then AC_MSG_WARN([slapd disabled, ignoring --enable-rlookups argument]) fi if test $ol_enable_dynacl = yes ; then AC_MSG_WARN([slapd disabled, ignoring --enable-dynacl argument]) fi if test $ol_enable_aci != no ; then AC_MSG_WARN([slapd disabled, ignoring --enable-aci argument]) fi if test $ol_enable_rewrite = yes ; then AC_MSG_WARN([slapd disabled, ignoring --enable-rewrite argument]) fi dnl overlays case "$ol_enable_overlays" in yes | mod) AC_MSG_WARN([slapd disabled, ignoring --enable-overlays argument]) esac for i in $Overlays; do eval "ol_tmp=\$ol_enable_$i" if test $ol_tmp != no ; then AC_MSG_WARN([slapd disabled, ignoring --enable-$i argument]) eval "ol_enable_$i=no" fi done # force settings to no ol_enable_slapi=no ol_enable_backends= ol_enable_overlays= ol_enable_modules=no ol_enable_rlookups=no ol_enable_dynacl=no ol_enable_aci=no ol_enable_wrappers=no ol_enable_rewrite=no elif test $ol_enable_modules != yes && test $ol_enable_bdb = no && test $ol_enable_dnssrv = no && test $ol_enable_hdb = no && test $ol_enable_ldap = no && test $ol_enable_mdb = no && test $ol_enable_meta = no && test $ol_enable_monitor = no && test $ol_enable_ndb = no && test $ol_enable_null = no && test $ol_enable_passwd = no && test $ol_enable_perl = no && test $ol_enable_relay = no && test $ol_enable_shell = no && test $ol_enable_sock = no && test $ol_enable_sql = no ; then dnl no slapd backend if test $ol_enable_slapd = yes ; then AC_MSG_ERROR([slapd requires a backend]) else AC_MSG_WARN([skipping slapd, no backend specified]) ol_enable_slapd=no fi fi if test $ol_enable_meta/$ol_enable_ldap = yes/no ; then AC_MSG_ERROR([--enable-meta requires --enable-ldap]) fi if test $ol_enable_lmpasswd = yes ; then if test $ol_with_tls = no ; then AC_MSG_ERROR([LAN Manager passwords require OpenSSL]) fi fi if test $ol_enable_spasswd = yes ; then if test $ol_with_cyrus_sasl = no ; then AC_MSG_ERROR([options require --with-cyrus-sasl]) fi ol_with_cyrus_sasl=yes fi AC_MSG_RESULT(done) dnl ---------------------------------------------------------------- dnl Initialize vars LDAP_LIBS= BDB_LIBS= SLAPD_NDB_LIBS= SLAPD_NDB_INCS= LTHREAD_LIBS= LUTIL_LIBS= SLAPD_LIBS= BUILD_SLAPD=no BUILD_THREAD=no BUILD_SLAPI=no SLAPD_SLAPI_DEPEND= BUILD_BDB=no BUILD_DNSSRV=no BUILD_HDB=no BUILD_LDAP=no BUILD_MDB=no BUILD_META=no BUILD_MONITOR=no BUILD_NDB=no BUILD_NULL=no BUILD_PASSWD=no BUILD_PERL=no BUILD_RELAY=no BUILD_SHELL=no BUILD_SOCK=no BUILD_SQL=no BUILD_ACCESSLOG=no BUILD_AUDITLOG=no BUILD_CONSTRAINT=no BUILD_DDS=no BUILD_DENYOP=no BUILD_DEREF=no BUILD_DYNGROUP=no BUILD_DYNLIST=no BUILD_LASTMOD=no BUILD_MEMBEROF=no BUILD_PPOLICY=no BUILD_PROXYCACHE=no BUILD_REFINT=no BUILD_RETCODE=no BUILD_RWM=no BUILD_SEQMOD=no BUILD_SSSVLV=no BUILD_SYNCPROV=no BUILD_TRANSLUCENT=no BUILD_UNIQUE=no BUILD_VALSORT=no SLAPD_STATIC_OVERLAYS= SLAPD_DYNAMIC_OVERLAYS= SLAPD_MODULES_LDFLAGS= SLAPD_MODULES_CPPFLAGS= SLAPD_STATIC_BACKENDS=back-ldif SLAPD_DYNAMIC_BACKENDS= SLAPD_PERL_LDFLAGS= MOD_PERL_LDFLAGS= PERL_CPPFLAGS= SLAPD_SQL_LDFLAGS= SLAPD_SQL_LIBS= SLAPD_SQL_INCLUDES= KRB4_LIBS= KRB5_LIBS= SASL_LIBS= TLS_LIBS= MODULES_LIBS= SLAPI_LIBS= LIBSLAPI= AUTH_LIBS= ICU_LIBS= SLAPD_SLP_LIBS= SLAPD_GMP_LIBS= dnl ================================================================ dnl Checks for programs AC_DEFINE(HAVE_MKVERSION, 1, [define this if you have mkversion]) dnl ---------------------------------------------------------------- dnl dnl Determine which C translator to use dnl dnl AIX Thread requires we use cc_r or xlc_r. dnl But only do this IF AIX and CC is not set dnl and threads are auto|yes|posix. dnl dnl If we find cc_r|xlc_r, force pthreads and assume dnl pthread_create is in $LIBS (ie: don't bring in dnl any additional thread libraries) dnl If we do not find cc_r|xlc_r, disable threads ol_aix_threads=no case "$target" in *-*-aix*) dnl all AIX is not a good idea. if test -z "$CC" ; then case "$ol_with_threads" in auto | yes | posix) ol_aix_threads=yes ;; esac fi ;; esac if test $ol_aix_threads = yes ; then if test -z "${CC}" ; then AC_CHECK_PROGS(CC,cc_r xlc_r cc) if test "$CC" = cc ; then dnl no CC! don't allow --with-threads if test $ol_with_threads != auto ; then AC_MSG_ERROR([--with-threads requires cc_r (or other suitable compiler) on AIX]) else AC_MSG_WARN([disabling threads, no cc_r on AIX]) fi ol_with_threads=no fi fi case ${CC} in cc_r | xlc_r) ol_with_threads=posix ol_cv_pthread_create=yes ;; esac fi if test -z "${CC}"; then AC_CHECK_PROGS(CC,cc gcc,missing) if test "${CC}" = "missing" ; then AC_MSG_ERROR([Unable to locate cc(1) or suitable replacement. Check PATH or set CC.]) fi fi if test -z "${AR}"; then AC_CHECK_PROGS(AR,ar gar,missing) if test "${AR}" = "missing" ; then AC_MSG_ERROR([Unable to locate ar(1) or suitable replacement. Check PATH or set AR.]) fi fi AC_LIBTOOL_WIN32_DLL AC_LIBTOOL_DLOPEN AC_PROG_LIBTOOL dnl ---------------------------------------------------------------- dnl Perl ol_link_perl=no if test $ol_enable_perl != no ; then AC_PATH_PROG(PERLBIN, perl, /usr/bin/perl) if test "no$PERLBIN" = "no" ; then if test $ol_enable_perl = yes ; then AC_MSG_ERROR([could not locate perl]) fi else PERL_CPPFLAGS="`$PERLBIN -MExtUtils::Embed -e ccopts`" PERL_LDFLAGS="`$PERLBIN -MExtUtils::Embed -e ldopts|sed -e 's/ -lc / /' -e 's/ -lc$//'`" if test x"$ol_enable_perl" = "xyes" ; then SLAPD_PERL_LDFLAGS="$PERL_LDFLAGS" else MOD_PERL_LDFLAGS="$PERL_LDFLAGS" fi dnl should check perl version ol_link_perl=yes fi fi AC_PROG_CPP OL_MSVC dnl ---------------------------------------------------------------- dnl Checks for Windows NT case $host_os in *mingw32* ) ac_cv_mingw32=yes ;; *cygwin* ) ac_cv_cygwin=yes ;; *interix* ) ac_cv_interix=yes ;; esac dnl ---------------------------------------------------------------- dnl Checks for file extensions AC_EXEEXT AC_OBJEXT AC_DEFINE_UNQUOTED(EXEEXT, "${EXEEXT}", [defined to be the EXE extension]) dnl ---------------------------------------------------------------- dnl BeOS requires -lbe -lroot -lnet AC_CHECK_LIB(be, be_app, [LIBS="$LIBS -lbe -lroot -lnet"], :, [-lroot -lnet]) dnl ---------------------------------------------------------------- dnl OpenLDAP requires STDC features AC_PROG_CC if test "X${ac_cv_prog_cc_stdc}" = "Xno" ; then AC_MSG_ERROR([OpenLDAP requires compiler to support STDC constructs.]) fi dnl ---------------------------------------------------------------- dnl Check cc depend flags OL_MKDEPEND if test "${ol_cv_mkdep}" = no ; then # this will soon become an error AC_MSG_WARN([do not know how to generate dependencies]) fi dnl ---------------------------------------------------------------- dnl Check for AIX security library AC_CHECK_LIB(s, afopen, [ AUTH_LIBS=-ls AC_DEFINE(HAVE_AIX_SECURITY,1,[define if you have AIX security lib]) ]) dnl ---------------------------------------------------------------- dnl Check for IBM OS/390 case "$target" in *-ibm-openedition) ac_cv_func_getopt=no AC_DEFINE(BOTH_STRINGS_H,1,[define to use both and ]) ;; esac dnl ---------------------------------------------------------------- dnl Check for module support ol_link_modules=no WITH_MODULES_ENABLED=no if test $ol_enable_modules != no ; then AC_CHECK_HEADERS(ltdl.h) if test $ac_cv_header_ltdl_h = no ; then AC_MSG_ERROR([could not locate libtool ltdl.h]) fi AC_CHECK_LIB(ltdl, lt_dlinit, [ MODULES_LIBS=-lltdl AC_DEFINE(HAVE_LIBLTDL,1,[define if you have libtool -ltdl]) ]) if test "$ac_cv_lib_ltdl_lt_dlinit" = no ; then AC_MSG_ERROR([could not locate libtool -lltdl]) fi ol_link_modules=yes WITH_MODULES_ENABLED=yes else for i in $Backends; do eval "ol_tmp=\$ol_enable_$i" if test $ol_tmp = mod ; then AC_MSG_WARN([building static $i backend]) eval "ol_enable_$i=yes" fi done for i in $Overlays; do eval "ol_tmp=\$ol_enable_$i" if test $ol_tmp = mod ; then AC_MSG_WARN([building static $i overlay]) eval "ol_enable_$i=yes" fi done fi dnl ---------------------------------------------------------------- dnl Checks for header files. OL_HEADER_STDC if test $ol_cv_header_stdc != yes; then AC_MSG_WARN([could not locate Standard C compliant headers]) fi AC_HEADER_DIRENT AC_HEADER_SYS_WAIT AC_HEADER_TIOCGWINSZ AC_CHECK_HEADERS( \ arpa/inet.h \ arpa/nameser.h \ assert.h \ bits/types.h \ conio.h \ crypt.h \ direct.h \ errno.h \ fcntl.h \ filio.h \ getopt.h \ grp.h \ io.h \ libutil.h \ limits.h \ locale.h \ malloc.h \ memory.h \ psap.h \ pwd.h \ process.h \ sgtty.h \ shadow.h \ stddef.h \ string.h \ strings.h \ sysexits.h \ sys/file.h \ sys/filio.h \ sys/fstyp.h \ sys/errno.h \ sys/ioctl.h \ sys/param.h \ sys/privgrp.h \ sys/resource.h \ sys/select.h \ sys/socket.h \ sys/stat.h \ sys/syslog.h \ sys/time.h \ sys/types.h \ sys/uio.h \ sys/vmount.h \ syslog.h \ termios.h \ unistd.h \ utime.h \ ) dnl Only check Winsock on MinGW if test "$ac_cv_mingw32" = yes \ -o "$ac_cv_interix" = yes \ -o "$ol_cv_msvc" = yes then AC_CHECK_HEADERS( winsock.h winsock2.h ) fi AC_CHECK_HEADERS( resolv.h, [], [], [$ac_includes_default #include ]) AC_CHECK_HEADERS( netinet/tcp.h, [], [], [$ac_includes_default #include ]) AC_CHECK_HEADERS( sys/ucred.h, [], [], [$ac_includes_default #ifdef HAVE_SYS_PARAM_H #include #endif ]) dnl ---------------------------------------------------------------- dnl Checks for libraries AC_CHECK_FUNCS( sigaction sigset ) dnl HP-UX requires -lV3 dnl this is not needed on newer versions of HP-UX if test $ac_cv_func_sigaction = no && test $ac_cv_func_sigaction = no ; then AC_CHECK_LIB(V3, sigset) fi if test $ol_cv_msvc = yes ; then ol_cv_winsock=yes fi dnl The following is INTENTIONALLY scripted out because shell does not dnl support variable names with the '@' character, which is what dnl autoconf would try to generate if one merely used AC_SEARCH_LIBS if test "$ac_cv_header_winsock_h" = yes; then AC_CACHE_CHECK([for winsock], [ol_cv_winsock],[ save_LIBS="$LIBS" for curlib in none ws2_32 wsock32; do if test $curlib != none ; then LIBS="$save_LIBS -l$curlib" fi AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ socket(0,0,0); select(0,NULL,NULL,NULL,NULL); closesocket(0); gethostname(NULL,0); ]])],[ol_cv_winsock=$curlib],[ol_cv_winsock=no]) test "$ol_cv_winsock" != no && break done LIBS="$save_LIBS" ]) if test $ol_cv_winsock != no ; then AC_DEFINE(HAVE_WINSOCK, 1, [define if you have winsock]) ac_cv_func_socket=yes ac_cv_func_select=yes ac_cv_func_closesocket=yes ac_cv_func_gethostname=yes if test $ol_cv_winsock != none -a $ol_cv_winsock != yes ; then LIBS="$LIBS -l$ol_cv_winsock" fi if test $ol_cv_winsock = ws2_32 -o $ol_cv_winsock = yes ; then AC_DEFINE(HAVE_WINSOCK2, 1, [define if you have winsock2]) fi fi fi dnl Find socket() dnl Likely combinations: dnl -lsocket [ -lnsl_s | -lnsl ] dnl -linet AC_CHECK_FUNC(socket, :, [ dnl hopefully we won't include too many libraries AC_CHECK_LIB(socket, main) AC_CHECK_LIB(net, socket) AC_CHECK_LIB(nsl_s, main) AC_CHECK_LIB(nsl, main) AC_CHECK_LIB(inet, socket) AC_CHECK_LIB(gen, main) ]) dnl require select AC_CHECK_FUNC(select, :, AC_MSG_ERROR([select() required.])) if test "${ac_cv_header_winsock_h}" != yes; then dnl Select arg types dnl (if this detection becomes permenent, it and the select() detection dnl should be done before the yielding select test) AC_FUNC_SELECT_ARGTYPES fi dnl check to see if system call automatically restart dnl AC_SYS_RESTARTABLE_SYSCALLS dnl ---------------------------------------------------------------- AC_CHECK_FUNCS( poll ) if test $ac_cv_func_poll = yes; then AC_CHECK_HEADERS( poll.h sys/poll.h ) fi dnl ---------------------------------------------------------------- AC_CHECK_HEADERS( sys/epoll.h ) if test "${ac_cv_header_sys_epoll_h}" = yes; then AC_MSG_CHECKING(for epoll system call) AC_RUN_IFELSE([AC_LANG_SOURCE([[int main(int argc, char **argv) { int epfd = epoll_create(256); exit (epfd == -1 ? 1 : 0); }]])],[AC_MSG_RESULT(yes) AC_DEFINE(HAVE_EPOLL,1, [define if your system supports epoll])],[AC_MSG_RESULT(no)],[AC_MSG_RESULT(no)]) fi dnl ---------------------------------------------------------------- AC_CHECK_HEADERS( sys/devpoll.h ) dnl "/dev/poll" needs as well... if test "${ac_cv_header_sys_devpoll_h}" = yes \ -a "${ac_cv_header_poll_h}" = yes ; \ then AC_MSG_CHECKING(for /dev/poll) AC_RUN_IFELSE([AC_LANG_SOURCE([[int main(int argc, char **argv) { int devpollfd = open("/dev/poll", /* O_RDWR */ 2); exit (devpollfd == -1 ? 1 : 0); }]])],[AC_MSG_RESULT(yes) AC_DEFINE(HAVE_DEVPOLL,1, [define if your system supports /dev/poll])],[AC_MSG_RESULT(no)],[AC_MSG_RESULT(no)]) fi dnl ---------------------------------------------------------------- OL_STRERROR dnl ---------------------------------------------------------------- dnl require POSIX regex AC_CHECK_HEADERS( regex.h, [], [], [$ac_includes_default #ifdef HAVE_SYS_TYPES_H #include #endif ]) if test "$ac_cv_header_regex_h" != yes ; then AC_MSG_ERROR([POSIX regex.h required.]) fi AC_SEARCH_LIBS(regfree, [regex gnuregex], :, AC_MSG_ERROR([POSIX regex required.])) OL_POSIX_REGEX if test "$ol_cv_c_posix_regex" = no ; then AC_MSG_ERROR([broken POSIX regex!]) fi dnl ---------------------------------------------------------------- dnl UUID Support have_uuid=no AC_CHECK_HEADERS(sys/uuid.h) dnl The HAVE_UUID_TO_STR code path also needs uuid_create if test $ac_cv_header_sys_uuid_h = yes ; then save_LIBS="$LIBS" AC_SEARCH_LIBS([uuid_to_str], [uuid], [have_uuid=yes], :) AC_SEARCH_LIBS([uuid_create], [uuid], :, [have_uuid=no]) LIBS="$save_LIBS" if test $have_uuid = yes ; then AC_DEFINE(HAVE_UUID_TO_STR,1, [define if you have uuid_to_str()]) test "$ac_cv_search_uuid_to_str" = "none required" || \ SLAPD_LIBS="$SLAPD_LIBS $ac_cv_search_uuid_to_str" fi fi dnl Look for uuid_generate dnl The HAVE_UUID_GENERATE code path also needs uuid_unparse_lower if test $have_uuid = no ; then AC_CHECK_HEADERS(uuid/uuid.h) if test $ac_cv_header_uuid_uuid_h = yes ; then save_LIBS="$LIBS" AC_SEARCH_LIBS([uuid_generate], [uuid], [have_uuid=yes], :) AC_SEARCH_LIBS([uuid_unparse_lower], [uuid], :, [have_uuid=no]) LIBS="$save_LIBS" if test $have_uuid = yes ; then AC_DEFINE(HAVE_UUID_GENERATE,1, [define if you have uuid_generate()]) test "$ac_cv_search_uuid_generate" = "none required" || \ SLAPD_LIBS="$SLAPD_LIBS $ac_cv_search_uuid_generate" fi fi fi dnl For windows, check for the need of RPCRT for UUID function support if test $have_uuid = no ; then AC_MSG_CHECKING(to see if -lrpcrt4 is needed for win32 UUID support) save_LIBS="$LIBS" LIBS="$LIBS -lrpcrt4" AC_LINK_IFELSE([AC_LANG_PROGRAM([[ int __stdcall UuidCreate(void *); int __stdcall UuidToStringA(void *,void **); ]], [[ UuidCreate(0); UuidToStringA(0,0); ]])],[need_rpcrt=yes],[need_rpcrt=no]) if test $need_rpcrt = yes; then SLAPD_LIBS="$SLAPD_LIBS -lrpcrt4" fi LIBS="$save_LIBS" AC_MSG_RESULT($need_rpcrt) fi dnl ---------------------------------------------------------------- dnl Check for resolver routines OL_RESOLVER_LINK ol_link_dnssrv=no if test "$ol_cv_lib_resolver" != no ; then AC_DEFINE(HAVE_RES_QUERY,1, [define if you have res_query()]) if test "$ol_enable_dnssrv" != no ; then ol_link_dnssrv=yes fi if test "$ol_cv_lib_resolver" != yes ; then LIBS="$ol_cv_lib_resolver $LIBS" fi fi if test "$ol_enable_dnssrv" = yes || test "$ol_enable_dnssrv" = mod ; then if test "$ol_link_dnssrv" = no ; then AC_MSG_ERROR([DNSSRV requires res_query()]) fi else ol_enable_dnssrv=no fi AC_CHECK_FUNCS( hstrerror ) dnl ---------------------------------------------------------------- dnl PF_INET6 support requires getaddrinfo and INET6_ADDRSTRLEN dnl PF_LOCAL may use getaddrinfo in available AC_CHECK_FUNCS( getaddrinfo getnameinfo gai_strerror inet_ntop ) ol_link_ipv6=no if test $ac_cv_func_getaddrinfo = no || test $ac_cv_func_inet_ntop = no ; then if test $ol_enable_ipv6 = yes ; then AC_MSG_ERROR([IPv6 support requires getaddrinfo() and inet_ntop()]) fi elif test $ol_enable_ipv6 != no ; then AC_CACHE_CHECK([INET6_ADDRSTRLEN],[ol_cv_inet6_addrstrlen],[ AC_EGREP_CPP(__has_inet6_addrstrlen__,[ # include # ifdef INET6_ADDRSTRLEN __has_inet6_addrstrlen__; # endif ], [ol_cv_inet6_addrstrlen=yes], [ol_cv_inet6_addrstrlen=no])]) AC_CACHE_CHECK([struct sockaddr_storage],ol_cv_struct_sockaddr_storage,[ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include ]], [[ struct sockaddr_storage ss; ]])],[ol_cv_struct_sockaddr_storage=yes],[ol_cv_struct_sockaddr_storage=no])]) if test $ol_cv_inet6_addrstrlen = yes && test $ol_cv_struct_sockaddr_storage = yes ; then ol_link_ipv6=yes elif test $ol_enable_ipv6 = yes && test $ol_cv_inet6_addrstrlen = no ; then AC_MSG_ERROR([IPv6 support requires INET6_ADDRSTRLEN]) elif test $ol_enable_ipv6 = yes && test $ol_cv_struct_sockaddr_storage = no ; then AC_MSG_ERROR([IPv6 support requires struct sockaddr_storage]) fi fi if test $ol_enable_local != no ; then AC_CHECK_HEADERS( sys/un.h ) if test $ol_enable_local = auto ; then ol_enable_local=$ac_cv_header_sys_un_h elif test $ac_cv_header_sys_un_h = no ; then AC_MSG_ERROR([AF_LOCAL domain support requires sys/un.h]) fi fi dnl ---------------------------------------------------------------- dnl TLS/SSL if test $ol_with_tls = yes ; then ol_with_tls=auto fi ol_link_tls=no if test $ol_with_tls = openssl || test $ol_with_tls = auto ; then AC_CHECK_HEADERS(openssl/ssl.h) if test $ac_cv_header_openssl_ssl_h = yes ; then AC_CHECK_LIB(ssl, SSL_library_init, [have_openssl=yes need_rsaref=no], [have_openssl=no], [-lcrypto]) if test $have_openssl = no ; then AC_CHECK_LIB(ssl, ssl3_accept, [have_openssl=yes need_rsaref=yes], [have_openssl=no], [-lcrypto -lRSAglue -lrsaref]) fi if test $have_openssl = yes ; then ol_with_tls=openssl ol_link_tls=yes AC_DEFINE(HAVE_OPENSSL, 1, [define if you have OpenSSL]) if test $need_rsaref = yes; then AC_DEFINE(HAVE_RSAREF, 1, [define if OpenSSL needs RSAref]) TLS_LIBS="-lssl -lcrypto -lRSAglue -lrsaref" else TLS_LIBS="-lssl -lcrypto" fi OL_SSL_COMPAT if test $ol_cv_ssl_crl_compat = yes ; then AC_DEFINE(HAVE_OPENSSL_CRL, 1, [define if you have OpenSSL with CRL checking capability]) fi fi fi fi if test $ol_link_tls = no ; then if test $ol_with_tls = gnutls || test $ol_with_tls = auto ; then AC_CHECK_HEADERS(gnutls/gnutls.h) if test $ac_cv_header_gnutls_gnutls_h = yes ; then AC_PREPROC_IFELSE( [[#include ] [#if GNUTLS_VERSION_NUMBER < 0x020c00] [#error "GnuTLS 2.12.0 or newer required"] [#endif]], , [AC_MSG_FAILURE([GnuTLS is too old])]) AC_CHECK_LIB(gnutls, gnutls_init, [have_gnutls=yes], [have_gnutls=no]) if test $have_gnutls = yes ; then ol_with_tls=gnutls ol_link_tls=yes TLS_LIBS="-lgnutls" AC_DEFINE(HAVE_GNUTLS, 1, [define if you have GNUtls]) fi fi fi fi dnl NOTE: caller must specify -I/path/to/nspr4 and -I/path/to/nss3 dnl and -L/path/to/nspr4 libs and -L/path/to/nss3 libs if those libs dnl are not in the default system location if test $ol_link_tls = no ; then if test $ol_with_tls = moznss || test $ol_with_tls = auto ; then have_moznss=no AC_CHECK_HEADERS([nssutil.h]) if test "$ac_cv_header_nssutil_h" = yes ; then AC_CHECK_LIB([nss3], [NSS_Initialize], [ have_moznss=yes ], [ have_moznss=no ]) fi if test "$have_moznss" = yes ; then ol_with_tls=moznss ol_link_tls=yes AC_DEFINE(HAVE_MOZNSS, 1, [define if you have MozNSS]) TLS_LIBS="-lssl3 -lsmime3 -lnss3 -lnssutil3 -lplds4 -lplc4 -lnspr4" else if test $ol_with_tls = moznss ; then AC_MSG_ERROR([MozNSS not found - please specify the location to the NSPR and NSS header files in CPPFLAGS and the location to the NSPR and NSS libraries in LDFLAGS (if not in the system location)]) fi fi fi fi WITH_TLS=no if test $ol_link_tls = yes ; then AC_DEFINE(HAVE_TLS, 1, [define if you have TLS]) WITH_TLS=yes elif test $ol_with_tls = auto ; then AC_MSG_WARN([Could not locate TLS/SSL package]) AC_MSG_WARN([TLS data protection not supported!]) elif test $ol_with_tls != no ; then AC_MSG_ERROR([Could not locate TLS/SSL package]) else AC_MSG_WARN([TLS data protection not supported!]) fi dnl ---------------------------------------------------------------- dnl LAN Manger password checking requires DES from OpenSSL if test $ol_enable_lmpasswd != no; then if test $ol_link_tls != yes ; then AC_MSG_ERROR([LAN Manager passwords require OpenSSL]) fi AC_DEFINE(SLAPD_LMHASH, 1, [define to support LAN Manager passwords]) fi dnl ---------------------------------------------------------------- dnl Threads? ol_link_threads=no case $ol_with_threads in auto | yes | nt) OL_NT_THREADS if test "$ol_cv_nt_threads" = yes ; then ol_link_threads=nt ol_with_threads=found ol_with_yielding_select=yes AC_DEFINE(HAVE_NT_SERVICE_MANAGER,1,[if you have NT Service Manager]) AC_DEFINE(HAVE_NT_EVENT_LOG,1,[if you have NT Event Log]) fi if test $ol_with_threads = nt ; then AC_MSG_ERROR([could not locate NT Threads]) fi ;; esac case $ol_with_threads in auto | yes | posix) AC_CHECK_HEADERS(pthread.h) if test $ac_cv_header_pthread_h = yes ; then OL_POSIX_THREAD_VERSION if test $ol_cv_pthread_version != 0 ; then AC_DEFINE_UNQUOTED(HAVE_PTHREADS,$ol_cv_pthread_version, [define to pthreads API spec revision]) else AC_MSG_ERROR([unknown pthread version]) fi # consider threads found ol_with_threads=found OL_HEADER_LINUX_THREADS OL_HEADER_GNU_PTH_PTHREAD_H if test $ol_cv_header_gnu_pth_pthread_h = no ; then AC_CHECK_HEADERS(sched.h) fi dnl Now the hard part, how to link? dnl dnl currently supported checks: dnl dnl Check for no flags dnl pthread_create() in $LIBS dnl dnl Check special pthread (final) flags dnl [skipped] pthread_create() with -mt (Solaris) [disabled] dnl pthread_create() with -kthread (FreeBSD) dnl pthread_create() with -pthread (FreeBSD/Digital Unix) dnl pthread_create() with -pthreads (?) dnl pthread_create() with -mthreads (AIX) dnl pthread_create() with -thread (?) dnl dnl Check pthread (final) libraries dnl pthread_mutex_unlock() in -lpthread -lmach -lexc -lc_r (OSF/1) dnl pthread_mutex_lock() in -lpthread -lmach -lexc (OSF/1) dnl [skipped] pthread_mutex_trylock() in -lpthread -lexc (OSF/1) dnl pthread_join() -Wl,-woff,85 -lpthread (IRIX) dnl pthread_create() in -lpthread (many) dnl pthread_create() in -lc_r (FreeBSD) dnl dnl Check pthread (draft4) flags (depreciated) dnl pthread_create() with -threads (OSF/1) dnl dnl Check pthread (draft4) libraries (depreciated) dnl pthread_mutex_unlock() in -lpthreads -lmach -lexc -lc_r (OSF/1) dnl pthread_mutex_lock() in -lpthreads -lmach -lexc (OSF/1) dnl pthread_mutex_trylock() in -lpthreads -lexc (OSF/1) dnl pthread_create() in -lpthreads (many) dnl dnl pthread_create in $LIBS AC_CACHE_CHECK([for pthread_create in default libraries], ol_cv_pthread_create,[ AC_RUN_IFELSE([OL_PTHREAD_TEST_PROGRAM], [ol_cv_pthread_create=yes], [ol_cv_pthread_create=no], [AC_TRY_LINK(OL_PTHREAD_TEST_INCLUDES,OL_PTHREAD_TEST_FUNCTION, [ol_cv_pthread_create=yes], [ol_cv_pthread_create=no])])]) if test $ol_cv_pthread_create != no ; then ol_link_threads=posix ol_link_pthreads="" fi dnl OL_PTHREAD_TRY([-mt], [ol_cv_pthread_mt]) OL_PTHREAD_TRY([-kthread], [ol_cv_pthread_kthread]) OL_PTHREAD_TRY([-pthread], [ol_cv_pthread_pthread]) OL_PTHREAD_TRY([-pthreads], [ol_cv_pthread_pthreads]) OL_PTHREAD_TRY([-mthreads], [ol_cv_pthread_mthreads]) OL_PTHREAD_TRY([-thread], [ol_cv_pthread_thread]) OL_PTHREAD_TRY([-lpthread -lmach -lexc -lc_r], [ol_cv_pthread_lpthread_lmach_lexc_lc_r]) OL_PTHREAD_TRY([-lpthread -lmach -lexc], [ol_cv_pthread_lpthread_lmach_lexc]) dnl OL_PTHREAD_TRY([-lpthread -lexc], dnl [ol_cv_pthread_lpthread_lexc]) OL_PTHREAD_TRY([-lpthread -Wl,-woff,85], [ol_cv_pthread_lib_lpthread_woff]) OL_PTHREAD_TRY([-lpthread], [ol_cv_pthread_lpthread]) OL_PTHREAD_TRY([-lc_r], [ol_cv_pthread_lc_r]) OL_PTHREAD_TRY([-threads], [ol_cv_pthread_threads]) OL_PTHREAD_TRY([-lpthreads -lmach -lexc -lc_r], [ol_cv_pthread_lpthreads_lmach_lexc_lc_r]) OL_PTHREAD_TRY([-lpthreads -lmach -lexc], [ol_cv_pthread_lpthreads_lmach_lexc]) OL_PTHREAD_TRY([-lpthreads -lexc], [ol_cv_pthread_lpthreads_lexc]) OL_PTHREAD_TRY([-lpthreads],[ol_cv_pthread_lib_lpthreads]) if test $ol_link_threads != no ; then LTHREAD_LIBS="$LTHREAD_LIBS $ol_link_pthreads" dnl save flags save_CPPFLAGS="$CPPFLAGS" save_LIBS="$LIBS" LIBS="$LTHREAD_LIBS $LIBS" dnl All POSIX Thread (final) implementations should have dnl sched_yield instead of pthread yield. dnl check for both, and thr_yield for Solaris AC_CHECK_FUNCS(sched_yield pthread_yield thr_yield) if test $ac_cv_func_sched_yield = no && test $ac_cv_func_pthread_yield = no && test $ac_cv_func_thr_yield = no ; then dnl Digital UNIX has sched_yield() in -lrt AC_CHECK_LIB(rt, sched_yield, [LTHREAD_LIBS="$LTHREAD_LIBS -lrt" AC_DEFINE(HAVE_SCHED_YIELD,1, [Define if you have the sched_yield function.]) ac_cv_func_sched_yield=yes], [ac_cv_func_sched_yield=no]) fi if test $ac_cv_func_sched_yield = no && test $ac_cv_func_pthread_yield = no && test "$ac_cv_func_thr_yield" = no ; then AC_MSG_WARN([could not locate sched_yield() or pthread_yield()]) fi dnl Check functions for compatibility AC_CHECK_FUNCS(pthread_kill) dnl Check for pthread_rwlock_destroy with dnl as pthread_rwlock_t may not be defined. AC_CACHE_CHECK([for pthread_rwlock_destroy with ], [ol_cv_func_pthread_rwlock_destroy], [ dnl save the flags AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include pthread_rwlock_t rwlock; ]], [[pthread_rwlock_destroy(&rwlock);]])],[ol_cv_func_pthread_rwlock_destroy=yes],[ol_cv_func_pthread_rwlock_destroy=no]) ]) if test $ol_cv_func_pthread_rwlock_destroy = yes ; then AC_DEFINE(HAVE_PTHREAD_RWLOCK_DESTROY,1, [define if you have pthread_rwlock_destroy function]) fi dnl Check for pthread_detach with inclusion dnl as it's symbol may have been mangled. AC_CACHE_CHECK([for pthread_detach with ], [ol_cv_func_pthread_detach], [ dnl save the flags AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include #ifndef NULL #define NULL (void*)0 #endif ]], [[pthread_detach(NULL);]])],[ol_cv_func_pthread_detach=yes],[ol_cv_func_pthread_detach=no]) ]) if test $ol_cv_func_pthread_detach = no ; then AC_MSG_ERROR([could not locate pthread_detach()]) fi AC_DEFINE(HAVE_PTHREAD_DETACH,1, [define if you have pthread_detach function]) dnl Check for setconcurreny functions AC_CHECK_FUNCS( \ pthread_setconcurrency \ pthread_getconcurrency \ thr_setconcurrency \ thr_getconcurrency \ ) OL_SYS_LINUX_THREADS OL_LINUX_THREADS if test $ol_cv_linux_threads = error; then AC_MSG_ERROR([LinuxThreads header/library mismatch]); fi AC_CACHE_CHECK([if pthread_create() works], ol_cv_pthread_create_works,[ AC_RUN_IFELSE([OL_PTHREAD_TEST_PROGRAM], [ol_cv_pthread_create_works=yes], [ol_cv_pthread_create_works=no], [dnl assume yes ol_cv_pthread_create_works=yes])]) if test $ol_cv_pthread_create_works = no ; then AC_MSG_ERROR([pthread_create is not usable, check environment settings]) fi ol_replace_broken_yield=no dnl case "$target" in dnl *-*-linux*) dnl AC_CHECK_FUNCS(nanosleep) dnl ol_replace_broken_yield=yes dnl ;; dnl esac if test $ol_replace_broken_yield = yes ; then AC_DEFINE([REPLACE_BROKEN_YIELD],1, [define if sched_yield yields the entire process]) fi dnl Check if select causes an yield if test $ol_with_yielding_select = auto ; then AC_CACHE_CHECK([if select yields when using pthreads], ol_cv_pthread_select_yields,[ AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include #include #include #include #ifndef NULL #define NULL (void*) 0 #endif static int fildes[2]; static void *task(p) void *p; { int i; struct timeval tv; fd_set rfds; tv.tv_sec=10; tv.tv_usec=0; FD_ZERO(&rfds); FD_SET(fildes[0], &rfds); /* we're not interested in any fds */ i = select(FD_SETSIZE, &rfds, NULL, NULL, &tv); if(i < 0) { perror("select"); exit(10); } exit(0); /* if we exit here, the select blocked the whole process */ } int main(argc, argv) int argc; char **argv; { pthread_t t; /* create a pipe to select */ if(pipe(&fildes[0])) { perror("select"); exit(1); } #ifdef HAVE_PTHREAD_SETCONCURRENCY (void) pthread_setconcurrency(2); #else #ifdef HAVE_THR_SETCONCURRENCY /* Set Solaris LWP concurrency to 2 */ thr_setconcurrency(2); #endif #endif #if HAVE_PTHREADS < 6 pthread_create(&t, pthread_attr_default, task, NULL); #else pthread_create(&t, NULL, task, NULL); #endif /* make sure task runs first */ #ifdef HAVE_THR_YIELD thr_yield(); #elif defined( HAVE_SCHED_YIELD ) sched_yield(); #elif defined( HAVE_PTHREAD_YIELD ) pthread_yield(); #endif exit(2); }]])],[ol_cv_pthread_select_yields=no],[ol_cv_pthread_select_yields=yes],[ol_cv_pthread_select_yields=cross])]) if test $ol_cv_pthread_select_yields = cross ; then AC_MSG_ERROR([crossing compiling: use --with-yielding_select=yes|no|manual]) fi if test $ol_cv_pthread_select_yields = yes ; then ol_with_yielding_select=yes fi fi dnl restore flags CPPFLAGS="$save_CPPFLAGS" LIBS="$save_LIBS" else AC_MSG_ERROR([could not locate usable POSIX Threads]) fi fi if test $ol_with_threads = posix ; then AC_MSG_ERROR([could not locate POSIX Threads]) fi ;; esac case $ol_with_threads in auto | yes | mach) dnl check for Mach CThreads AC_CHECK_HEADERS(mach/cthreads.h cthreads.h) if test $ac_cv_header_mach_cthreads_h = yes ; then ol_with_threads=found dnl check for cthreads support in current $LIBS AC_CHECK_FUNC(cthread_fork,[ol_link_threads=yes]) if test $ol_link_threads = no ; then dnl try -all_load dnl this test needs work AC_CACHE_CHECK([for cthread_fork with -all_load], [ol_cv_cthread_all_load], [ dnl save the flags save_LIBS="$LIBS" LIBS="-all_load $LIBS" AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ cthread_fork((void *)0, (void *)0); ]])],[ol_cv_cthread_all_load=yes],[ol_cv_cthread_all_load=no]) dnl restore the LIBS LIBS="$save_LIBS" ]) if test $ol_cv_cthread_all_load = yes ; then LTHREAD_LIBS="$LTHREAD_LIBS -all_load" ol_link_threads=mach ol_with_threads=found fi fi elif test $ac_cv_header_cthreads_h = yes ; then dnl Hurd variant of Mach Cthreads dnl uses and -lthreads ol_with_threads=found dnl save the flags save_LIBS="$LIBS" LIBS="$LIBS -lthreads" AC_CHECK_FUNC(cthread_fork,[ol_link_threads=yes]) LIBS="$save_LIBS" if test $ol_link_threads = yes ; then LTHREAD_LIBS="-lthreads" ol_link_threads=mach ol_with_threads=found else AC_MSG_ERROR([could not link with Mach CThreads]) fi elif test $ol_with_threads = mach ; then AC_MSG_ERROR([could not locate Mach CThreads]) fi if test $ol_link_threads = mach ; then AC_DEFINE(HAVE_MACH_CTHREADS,1, [define if you have Mach Cthreads]) elif test $ol_with_threads = found ; then AC_MSG_ERROR([could not link with Mach CThreads]) fi ;; esac case $ol_with_threads in auto | yes | pth) AC_CHECK_HEADERS(pth.h) if test $ac_cv_header_pth_h = yes ; then AC_CHECK_LIB(pth, pth_version, [have_pth=yes], [have_pth=no]) if test $have_pth = yes ; then AC_DEFINE(HAVE_GNU_PTH,1,[if you have GNU Pth]) LTHREAD_LIBS="$LTHREAD_LIBS -lpth" ol_link_threads=pth ol_with_threads=found if test $ol_with_yielding_select = auto ; then ol_with_yielding_select=yes fi fi fi ;; esac case $ol_with_threads in auto | yes | lwp) dnl check for SunOS5 LWP AC_CHECK_HEADERS(thread.h synch.h) if test $ac_cv_header_thread_h = yes && test $ac_cv_header_synch_h = yes ; then AC_CHECK_LIB(thread, thr_create, [have_thr=yes], [have_thr=no]) if test $have_thr = yes ; then AC_DEFINE(HAVE_THR,1, [if you have Solaris LWP (thr) package]) LTHREAD_LIBS="$LTHREAD_LIBS -lthread" ol_link_threads=thr if test $ol_with_yielding_select = auto ; then ol_with_yielding_select=yes fi dnl Check for setconcurreny functions AC_CHECK_FUNCS( \ thr_setconcurrency \ thr_getconcurrency \ ) fi fi ;; esac if test $ol_with_yielding_select = yes ; then AC_DEFINE(HAVE_YIELDING_SELECT,1, [define if select implicitly yields]) fi if test $ol_with_threads = manual ; then dnl User thinks he can manually configure threads. ol_link_threads=yes AC_MSG_WARN([thread defines and link options must be set manually]) AC_CHECK_HEADERS(pthread.h sched.h) AC_CHECK_FUNCS(sched_yield pthread_yield) OL_HEADER_LINUX_THREADS AC_CHECK_HEADERS(mach/cthreads.h) AC_CHECK_HEADERS(thread.h synch.h) fi if test $ol_link_threads != no && test $ol_link_threads != nt ; then dnl needed to get reentrant/threadsafe versions dnl AC_DEFINE(REENTRANT,1) AC_DEFINE(_REENTRANT,1) AC_DEFINE(THREAD_SAFE,1) AC_DEFINE(_THREAD_SAFE,1) AC_DEFINE(THREADSAFE,1) AC_DEFINE(_THREADSAFE,1) AC_DEFINE(_SGI_MP_SOURCE,1) dnl The errno declaration may dependent upon _REENTRANT. dnl If it does, we must link with thread support. AC_CACHE_CHECK([for thread specific errno], [ol_cv_errno_thread_specific], [ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[errno = 0;]])],[ol_cv_errno_thread_specific=yes],[ol_cv_errno_thread_specific=no]) ]) dnl The h_errno declaration may dependent upon _REENTRANT. dnl If it does, we must link with thread support. AC_CACHE_CHECK([for thread specific h_errno], [ol_cv_h_errno_thread_specific], [ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[h_errno = 0;]])],[ol_cv_h_errno_thread_specific=yes],[ol_cv_h_errno_thread_specific=no]) ]) if test $ol_cv_errno_thread_specific != yes || test $ol_cv_h_errno_thread_specific != yes ; then LIBS="$LTHREAD_LIBS $LIBS" LTHREAD_LIBS="" fi dnl When in thread environment, use dnl #if defined( HAVE_REENTRANT_FUNCTIONS ) || defined( HAVE_FUNC_R ) dnl func_r(...); dnl #else dnl # if defined( HAVE_THREADS ) dnl /* lock */ dnl # endif dnl func(...); dnl # if defined( HAVE_THREADS ) dnl /* unlock */ dnl # endif dnl #endif dnl dnl HAVE_REENTRANT_FUNCTIONS is derived from: dnl _POSIX_REENTRANT_FUNCTIONS dnl _POSIX_THREAD_SAFE_FUNCTIONS dnl _POSIX_THREADSAFE_FUNCTIONS dnl dnl and is currently defined in dnl dnl HAVE_THREADS is defined by iff -UNO_THREADS dnl dnl libldap/*.c should only include iff dnl LDAP_R_COMPILE is defined. ie: dnl #ifdef LDAP_R_COMPILE dnl # include dnl #endif dnl dnl LDAP_R_COMPILE is defined by libldap_r/Makefile.in dnl specifically for compiling the threadsafe version of dnl the ldap library (-lldap_r). dnl dnl dnl check for reentrant/threadsafe functions dnl dnl dnl dnl note: these should only be used when linking dnl dnl with $LTHREAD_LIBS dnl dnl dnl save_CPPFLAGS="$CPPFLAGS" dnl save_LIBS="$LIBS" dnl LIBS="$LTHREAD_LIBS $LIBS" dnl AC_CHECK_FUNCS( \ dnl gmtime_r \ dnl gethostbyaddr_r gethostbyname_r \ dnl feof_unlocked unlocked_feof \ dnl putc_unlocked unlocked_putc \ dnl flockfile ftrylockfile \ dnl ) dnl CPPFLAGS="$save_CPPFLAGS" dnl LIBS="$save_LIBS" fi if test $ol_link_threads = no ; then if test $ol_with_threads = yes ; then AC_MSG_ERROR([no suitable thread support]) fi if test $ol_with_threads = auto ; then AC_MSG_WARN([no suitable thread support, disabling threads]) ol_with_threads=no fi AC_DEFINE(NO_THREADS,1, [define if you have (or want) no threads]) LTHREAD_LIBS="" BUILD_THREAD=no else BUILD_THREAD=yes fi if test $ol_link_threads != no ; then AC_DEFINE(LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE,1, [define to 1 if library is thread safe]) fi dnl ---------------------------------------------------------------- dnl Tests for reentrant functions necessary to build -lldap_r AC_CHECK_FUNCS( \ ctime_r \ gmtime_r localtime_r \ gethostbyname_r gethostbyaddr_r \ ) if test "$ac_cv_func_ctime_r" = no ; then ol_cv_func_ctime_r_nargs=0 else OL_FUNC_CTIME_R_NARGS dnl OL_FUNC_CTIME_R_TYPE fi if test "$ac_cv_func_gethostbyname_r" = yes ; then OL_FUNC_GETHOSTBYNAME_R_NARGS else ol_cv_func_gethostbyname_r_nargs=0 fi if test "$ac_cv_func_gethostbyaddr_r" = yes ; then OL_FUNC_GETHOSTBYADDR_R_NARGS else ol_cv_func_gethostbyaddr_r_nargs=0 fi dnl ---------------------------------------------------------------- ol_link_bdb=no if test $ol_enable_bdb/$ol_enable_hdb != no/no; then OL_BERKELEY_DB if test $ol_cv_berkeley_db = no ; then AC_MSG_ERROR(BDB/HDB: BerkeleyDB not available) fi AC_DEFINE(HAVE_BERKELEY_DB,1, [define this if Berkeley DB is available]) dnl $ol_cv_lib_db should be yes or -ldb dnl (it could be no, but that would be an error if test $ol_cv_lib_db != yes ; then BDB_LIBS="$BDB_LIBS $ol_cv_lib_db" fi SLAPD_LIBS="$SLAPD_LIBS \$(BDB_LIBS)" ol_link_bdb=yes fi dnl ---------------------------------------------------------------- if test $ol_enable_dynamic = yes && test $enable_shared = yes ; then BUILD_LIBS_DYNAMIC=shared AC_DEFINE(LDAP_LIBS_DYNAMIC, 1, [define if LDAP libs are dynamic]) LTSTATIC="" else BUILD_LIBS_DYNAMIC=static LTSTATIC="-static" fi AC_SUBST(LTSTATIC)dnl dnl ---------------------------------------------------------------- if test $ol_enable_wrappers != no ; then AC_CHECK_HEADERS(tcpd.h,[ AC_MSG_CHECKING([for TCP wrappers library]) save_LIBS="$LIBS" LIBS="$LIBS -lwrap" AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include int allow_severity = 0; int deny_severity = 0; struct request_info *req; ]], [[ hosts_access(req) ]])],[AC_MSG_RESULT([-lwrap]) have_wrappers=yes LIBS="$save_LIBS"],[ dnl try with -lnsl LIBS="$LIBS -lnsl" AC_TRY_LINK([ #include int allow_severity = 0; int deny_severity = 0; struct request_info *req; ],[ hosts_access(req) ],[AC_MSG_RESULT([-lwrap -lnsl]) have_wrappers=yes LIBS="$save_LIBS -lnsl"],[ AC_MSG_RESULT(no) have_wrappers=no LIBS=$save_LIBS])])],[have_wrappers=no]) if test $have_wrappers = yes ; then AC_DEFINE(HAVE_TCPD,1, [define if you have -lwrap]) WRAP_LIBS="-lwrap" elif test $ol_enable_wrappers = yes ; then AC_MSG_ERROR([could not find TCP wrappers, select apppropriate options or disable]) else AC_MSG_WARN([could not find TCP wrappers, support disabled]) WRAP_LIBS="" fi fi dnl ---------------------------------------------------------------- if test $ol_enable_syslog != no ; then AC_CHECK_FUNC(openlog) if test $ac_cv_func_openlog = no && test $ol_enable_syslog = yes; then AC_MSG_ERROR(could not find syslog, select appropriate options or disable) fi ol_enable_syslog=$ac_cv_func_openlog fi dnl ---------------------------------------------------------------- dnl SQL ol_link_sql=no if test $ol_enable_sql != no ; then AC_CHECK_HEADERS(sql.h sqlext.h,[],[ AC_MSG_ERROR([could not locate SQL headers]) ]) sql_LIBS="$LIBS" LIBS="$LTHREAD_LIBS $LIBS" if test $ol_with_odbc = auto ; then ol_with_odbc="iodbc unixodbc odbc32" fi for odbc in $ol_with_odbc ; do if test $ol_link_sql = no ; then case $odbc in iodbc) AC_CHECK_LIB(iodbc, SQLDriverConnect, [have_iodbc=yes], [have_iodbc=no]) if test $have_iodbc = yes ; then ol_link_sql="-liodbc" fi ;; unixodbc) AC_CHECK_LIB(odbc, SQLDriverConnect, [have_odbc=yes], [have_odbc=no]) if test $have_odbc = yes ; then ol_link_sql="-lodbc" fi ;; odbc32) AC_CHECK_LIB(odbc32, SQLDriverConnect, [have_odbc32=yes], [have_odbc32=no]) dnl The windows API uses __stdcall which cannot be detected by AC_CHECK_LIB if test $have_odbc32 = no ; then AC_MSG_CHECKING([for SQLDriverConnect in -lodbc32 with windows.h]) save_LIBS="$LIBS" LIBS="$LIBS -lodbc32" AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include #include ]], [[ SQLDriverConnect(NULL,NULL,NULL,0,NULL,0,NULL,0); ]])],[have_odbc32=yes], [have_odbc32=no]) LIBS="$save_LIBS" AC_MSG_RESULT($have_odbc32) fi if test $have_odbc32 = yes ; then ol_link_sql="-lodbc32" fi ;; *) AC_MSG_ERROR([unknown ODBC library]) ;; esac fi done LIBS="$sql_LIBS" if test $ol_link_sql != no ; then SLAPD_SQL_LIBS="$ol_link_sql" elif test $ol_enable_sql != auto ; then AC_MSG_ERROR([could not locate suitable ODBC library]) fi fi dnl ---------------------------------------------------------------- dnl MySQL NDBapi dnl Note: uses C++, but we don't want to add C++ test overhead to dnl the rest of the libtool machinery. ol_link_ndb=no if test $ol_enable_ndb != no ; then AC_CHECK_PROG(MYSQL,mysql_config,yes) if test "$MYSQL" != yes ; then AC_MSG_ERROR([could not locate mysql_config]) fi SQL_INC=`mysql_config --include` SLAPD_NDB_INCS="$SQL_INC $SQL_INC/storage/ndb $SQL_INC/storage/ndb/ndbapi" save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$SLAPD_NDB_INCS" AC_MSG_CHECKING(for NdbApi.hpp) AC_PREPROC_IFELSE( [AC_LANG_SOURCE([[#include ]])], AC_MSG_RESULT(yes), AC_MSG_ERROR([could not locate NdbApi headers]) ) CPPFLAGS="$save_CPPFLAGS" SQL_LIB=`mysql_config --libs_r` SLAPD_NDB_LIBS="$SQL_LIB -lndbclient -lstdc++" save_LDFLAGS="$LDFLAGS" save_LIBS="$LIBS" LDFLAGS="$SQL_LIB" AC_CHECK_LIB(ndbclient,ndb_init,[: ok],[ AC_MSG_ERROR([could not locate ndbclient library]) ],[-lstdc++]) LIBS="$save_LIBS" LDFLAGS="$save_LDFLAGS" if test "$ol_enable_ndb" = yes ; then SLAPD_LIBS="$SLAPD_LIBS \$(SLAPD_NDB_LIBS)" fi fi dnl ---------------------------------------------------------------- dnl International Components for Unicode OL_ICU if test "$ol_icu" = no ; then AC_MSG_WARN([ICU not available]) else ICU_LIBS="$ol_icu" fi dnl ---------------------------------------------------------------- dnl dnl Check for Cyrus SASL dnl WITH_SASL=no ol_link_sasl=no ol_link_spasswd=no if test $ol_with_cyrus_sasl != no ; then AC_CHECK_HEADERS(sasl/sasl.h sasl.h) if test $ac_cv_header_sasl_sasl_h = yes || test $ac_cv_header_sasl_h = yes; then AC_CHECK_LIB(sasl2, sasl_client_init, [ol_link_sasl="-lsasl2"], [AC_CHECK_LIB(sasl, sasl_client_init, [ol_link_sasl="-lsasl"])]) fi if test $ol_link_sasl = no ; then if test $ol_with_cyrus_sasl != auto ; then AC_MSG_ERROR([Could not locate Cyrus SASL]) else AC_MSG_WARN([Could not locate Cyrus SASL]) AC_MSG_WARN([SASL authentication not supported!]) if test $ol_link_tls = no ; then AC_MSG_WARN([Strong authentication not supported!]) fi fi else OL_SASL_COMPAT if test $ol_cv_sasl_compat = no ; then ol_link_sasl=no AC_MSG_ERROR([Cyrus SASL library located but is incompatible]) fi AC_DEFINE(HAVE_CYRUS_SASL,1,[define if you have Cyrus SASL]) SASL_LIBS="$ol_link_sasl" if test $ol_enable_spasswd != no ; then ol_link_spasswd=yes fi ac_save_LIBS="$LIBS" LIBS="$LIBS $ol_link_sasl" AC_CHECK_FUNC(sasl_version, [AC_DEFINE(HAVE_SASL_VERSION,1, [define if your SASL library has sasl_version()])]) LIBS="$ac_save_LIBS" WITH_SASL=yes fi else AC_MSG_WARN([SASL authentication not supported!]) if test $ol_link_tls = no ; then AC_MSG_WARN([Strong authentication not supported!]) fi fi dnl ---------------------------------------------------------------- dnl Check for entropy sources if test $cross_compiling != yes && test "$ac_cv_mingw32" != yes ; then dev=no if test -r /dev/urandom ; then dev="/dev/urandom"; elif test -r /idev/urandom ; then dev="/idev/urandom"; elif test -r /dev/srandom ; then dev="/dev/srandom"; elif test -r /dev/random ; then dev="/dev/random"; elif test -r /idev/random ; then dev="/idev/random"; fi if test $dev != no ; then AC_DEFINE_UNQUOTED(URANDOM_DEVICE,"$dev",[set to urandom device]) fi fi dnl ---------------------------------------------------------------- dnl dnl Check for fetch URL support dnl should be extended to support other fetch URL APIs dnl ol_link_fetch=no if test $ol_with_fetch != no ; then OL_LIB_FETCH if test $ol_cv_lib_fetch != no ; then LIBS="$LIBS $ol_link_fetch" ol_link_fetch=freebsd elif test $ol_with_fetch != auto ; then AC_MSG_ERROR(no suitable API for --with-fetch=$ol_with_fetch) fi fi dnl ---------------------------------------------------------------- dnl FreeBSD (and others) have crypt(3) in -lcrypt if test $ol_enable_crypt != no ; then save_LIBS="$LIBS" LIBS="$TLS_LIBS $LIBS" AC_CHECK_FUNC(crypt, [have_crypt=yes], [ LIBS="$save_LIBS" AC_CHECK_LIB(crypt, crypt, [LUTIL_LIBS="$LUTIL_LIBS -lcrypt" have_crypt=yes], [have_crypt=no])]) LIBS="$save_LIBS" if test $have_crypt = yes ; then AC_DEFINE(HAVE_CRYPT,1, [define if crypt(3) is available]) else AC_MSG_WARN([could not find crypt]) if test $ol_enable_crypt = yes ; then AC_MSG_ERROR([could not find crypt, select appropriate options or disable]) fi AC_MSG_WARN([disabling crypt support]) ol_enable_crypt=no fi fi dnl ---------------------------------------------------------------- dnl FreeBSD (and others) have setproctitle(3) in -lutil if test $ol_enable_proctitle != no ; then AC_CHECK_FUNC(setproctitle, [have_setproctitle=yes], [ AC_CHECK_LIB(util, setproctitle, [have_setproctitle=yes LUTIL_LIBS="$LUTIL_LIBS -lutil"], [have_setproctitle=no AC_LIBOBJ(setproctitle) LIBSRCS="$LIBSRCS setproctitle.c"])]) if test $have_setproctitle = yes ; then AC_DEFINE(HAVE_SETPROCTITLE,1, [define if setproctitle(3) is available]) fi fi dnl ---------------------------------------------------------------- if test $ol_enable_slp != no ; then AC_CHECK_HEADERS( slp.h ) if test $ac_cv_header_slp_h = yes ; then AC_CHECK_LIB(slp, SLPOpen, [have_slp=yes], [have_slp=no]) if test $have_slp = yes ; then AC_DEFINE(HAVE_SLP, 1, [define if you have -lslp]) SLAPD_SLP_LIBS=-lslp fi elif test $ol_enable_slp = yes ; then AC_MSG_ERROR([SLP not found]) fi fi dnl ---------------------------------------------------------------- dnl Checks for typedefs, structures, and compiler characteristics. AC_CHECK_TYPE(mode_t, int) AC_CHECK_TYPE(off_t, long) AC_CHECK_TYPE(pid_t, int) AC_CHECK_TYPE(ssize_t, [signed int]) AC_CHECK_TYPE(caddr_t, [char *]) AC_CHECK_TYPE(size_t, unsigned) AC_CHECK_TYPES([long long]) AC_CHECK_TYPES([ptrdiff_t]) AC_CHECK_TYPE([socklen_t],,, [$ac_includes_default #ifdef HAVE_SYS_SOCKET_H #include #endif]) dnl socklen_t-like type in accept(), default socklen_t or int: dnl - The OS might define socklen_t without using it. POSIX moved from dnl int to size_t to socklen_t, hoping to stay at a 32-bit type, and dnl HP-UX now has selectors for what to use. dnl - On Solaris 2.8 the prototype has void *len, but the default is OK. AC_MSG_CHECKING([the type of arg 3 to accept()]) AC_CACHE_VAL(ol_cv_type_ber_socklen_t, [ set socklen_t int unsigned "unsigned long" long size_t test "$ac_cv_type_socklen_t" = yes || shift ol_cv_type_ber_socklen_t=$1 guessing="guessing " for lentype in "$@" ; do for addrtype in "struct sockaddr" void ; do AC_COMPILE_IFELSE([AC_LANG_PROGRAM([$ac_includes_default #ifdef HAVE_SYS_SOCKET_H #include #endif extern int accept(int s, $addrtype *ap, $lentype *lp); ], [ accept(0, (struct sockaddr *) 0, ($lentype *) 0); ])], [ol_cv_type_ber_socklen_t=$lentype guessing= ; break 2]) done ; done]) AC_MSG_RESULT([$guessing$ol_cv_type_ber_socklen_t *]) AC_DEFINE_UNQUOTED(ber_socklen_t, $ol_cv_type_ber_socklen_t, [Define to the type of arg 3 for `accept'.]) dnl Modules should use ber_socklen_t, not socklen_t. Define socklen_t dnl for the time being anyway, for backwards compatibility. if test "$ac_cv_type_socklen_t" != yes; then AC_DEFINE_UNQUOTED([socklen_t], [$ol_cv_type_ber_socklen_t], [Define like ber_socklen_t if does not define.]) fi AC_TYPE_SIGNAL AC_CHECK_TYPE([sig_atomic_t],, [AC_DEFINE_UNQUOTED([sig_atomic_t], [int], [Define to `int' if does not define.])], [$ac_includes_default #include ]) AC_TYPE_UID_T AC_HEADER_TIME AC_STRUCT_TM AC_CHECK_MEMBERS([struct stat.st_blksize]) AC_CHECK_MEMBERS([struct passwd.pw_gecos],,,[$ac_includes_default #include ]) AC_CHECK_MEMBERS([struct passwd.pw_passwd],,,[$ac_includes_default #include ]) OL_C_UPPER_LOWER AC_C_CONST OL_C_VOLATILE if test $cross_compiling = yes ; then AC_MSG_WARN([Crossing compiling... all bets are off!]) AC_DEFINE(CROSS_COMPILING, 1, [define if cross compiling]) else AC_C_BIGENDIAN fi AC_CHECK_SIZEOF(short) AC_CHECK_SIZEOF(int) AC_CHECK_SIZEOF(long) AC_CHECK_SIZEOF(long long) AC_CHECK_SIZEOF(wchar_t) if test "$ac_cv_sizeof_int" -lt 4 ; then AC_MSG_WARN([OpenLDAP requires 'int' to be 32 bits or greater.]) AC_DEFINE(LBER_INT_T,long,[define to 32-bit or greater integer type]) else AC_DEFINE(LBER_INT_T,int,[define to 32-bit or greater integer type]) fi AC_DEFINE(LBER_LEN_T,long,[define to large integer type]) AC_DEFINE(LBER_SOCKET_T,int,[define to socket descriptor type]) AC_DEFINE(LBER_TAG_T,long,[define to large integer type]) dnl ---------------------------------------------------------------- dnl Check for multiple precision support if test $ol_with_mp = longlong || test $ol_with_mp = auto ; then if test $ac_cv_sizeof_long_long -gt 4 ; then ol_with_mp=longlong AC_DEFINE(USE_MP_LONG_LONG,1,[define to use 'long long' for MP]) elif test $ol_with_mp = longlong ; then AC_MSG_ERROR([long long unusable for multiple precision]) fi fi if test $ol_with_mp = long || test $ol_with_mp = auto ; then if test $ac_cv_sizeof_long -gt 4 ; then ol_with_mp=long AC_DEFINE(USE_MP_LONG,1,[define to use 'long' for MP]) elif test $ol_with_mp = long ; then AC_MSG_ERROR([long unusable for multiple precision]) fi fi if test $ol_with_mp = bignum || test $ol_with_mp = auto ; then AC_CHECK_HEADERS(openssl/bn.h) AC_CHECK_HEADERS(openssl/crypto.h) if test "$ac_cv_header_openssl_bn_h" = "yes" && test "$ac_cv_header_openssl_crypto_h" = "yes" && test "$ol_with_tls" = "found" ; then ol_with_mp=bignum AC_DEFINE(USE_MP_BIGNUM,1,[define to use OpenSSL BIGNUM for MP]) elif test $ol_with_mp = bignum ; then AC_MSG_ERROR([bignum not available]) fi fi if test $ol_with_mp = gmp || test $ol_with_mp = auto ; then AC_CHECK_HEADERS(gmp.h) AC_CHECK_LIB(gmp, __gmpz_add_ui) if test $ac_cv_header_gmp_h = yes && test $ac_cv_lib_gmp___gmpz_add_ui = yes ; then AC_DEFINE(USE_MP_GMP,1,[define to use GMP for MP]) ol_with_mp=gmp elif test $ol_with_mp = gmp ; then AC_MSG_ERROR([gmp not available]) fi fi if test $ol_with_mp = auto ; then ol_with_mp=no fi dnl ---------------------------------------------------------------- dnl Checks for library functions. AC_FUNC_MEMCMP if test $ac_cv_func_memcmp_working = no ; then AC_DEFINE(NEED_MEMCMP_REPLACEMENT,1, [define if memcmp is not 8-bit clean or is otherwise broken]) fi AC_FUNC_STRFTIME OL_FUNC_INET_ATON dnl Check for NT specific routines AC_CHECK_FUNC(_spawnlp, AC_DEFINE(HAVE_SPAWNLP,1,[if you have spawnlp()])) AC_CHECK_FUNC(_snprintf, [ac_cv_func_snprintf=yes AC_DEFINE(snprintf, _snprintf, [define to snprintf routine]) ]) AC_CHECK_FUNCS(vsnprintf _vsnprintf) if test $ac_cv_func_vsnprintf = no -a $ac_cv_func__vsnprintf = yes ; then ac_cv_func_vsnprintf=yes AC_DEFINE(vsnprintf, _vsnprintf, [define to vsnprintf routine]) fi AC_FUNC_VPRINTF if test $ac_cv_func_vprintf = yes ; then dnl check for vsnprintf AC_CHECK_FUNCS(snprintf vsnprintf) fi AC_CHECK_FUNCS( \ bcopy \ closesocket \ chroot \ endgrent \ endpwent \ fcntl \ flock \ fstat \ getdtablesize \ geteuid \ getgrgid \ gethostname \ getpassphrase \ getpwuid \ getpwnam \ getspnam \ gettimeofday \ initgroups \ inet_ntoa_b \ ioctl \ lockf \ memcpy \ memmove \ memrchr \ mkstemp \ mktemp \ pipe \ read \ recv \ recvfrom \ setpwfile \ setgid \ setegid \ setsid \ setuid \ seteuid \ signal \ strdup \ strpbrk \ strrchr \ strsep \ strstr \ strtol \ strtoul \ strtoq \ strtouq \ strtoll \ strtoull \ strspn \ sysconf \ waitpid \ wait4 \ write \ send \ sendmsg \ sendto \ ) dnl We actually may need to replace more than this. AC_REPLACE_FUNCS(getopt getpeereid) if test "$ac_cv_func_getopt" != yes; then LIBSRCS="$LIBSRCS getopt.c" fi if test "$ac_cv_func_getpeereid" != yes; then AC_CHECK_FUNCS( getpeerucred ) if test "$ac_cv_func_getpeerucred" != yes ; then AC_CHECK_MEMBERS([struct msghdr.msg_accrightslen],,, [$ac_includes_default #ifdef HAVE_SYS_SOCKET_H #include #endif]) if test "$ac_cv_member_struct_msghdr_msg_accrightslen" != yes; then AC_CHECK_MEMBERS([struct msghdr.msg_control],,, [$ac_includes_default #ifdef HAVE_SYS_SOCKET_H #include #endif]) fi AC_CHECK_MEMBERS([struct stat.st_fstype, struct stat.st_vfstype]) if test "$ac_cv_member_struct_stat_st_fstype" = yes; then AC_COMPILE_IFELSE([struct stat st; char *ptr=st.st_fstype;], AC_DEFINE([HAVE_STRUCT_STAT_ST_FSTYPE_CHAR],1,[define to 1 if st_fstype is char *]), AC_DEFINE([HAVE_STRUCT_STAT_ST_FSTYPE_INT],1,[define to 1 if st_fstype is int])) fi fi LIBSRCS="$LIBSRCS getpeereid.c" fi if test "$ac_cv_func_snprintf" != yes || test "$ac_cv_func_vsnprintf" != yes; then if test "$ac_cv_func_snprintf" != yes; then AC_DEFINE(snprintf, ber_pvt_snprintf, [define to snprintf routine]) fi if test "$ac_cv_func_vsnprintf" != yes; then AC_DEFINE(vsnprintf, ber_pvt_vsnprintf, [define to snprintf routine]) fi fi dnl ---------------------------------------------------------------- dnl Sort out defines if test "$ol_enable_slapi" != no ; then dnl This check is done also if --enable-modules is used; dnl it is duplicated here, 'cause it'd be cached anyway AC_CHECK_HEADERS(ltdl.h) if test $ac_cv_header_ltdl_h != yes ; then AC_MSG_ERROR([could not locate ]) fi AC_CHECK_LIB(ltdl, lt_dlinit, [ SLAPI_LIBS=-lltdl LIBSLAPI=slapi/libslapi.la AC_DEFINE(HAVE_LIBLTDL,1,[define if you have libtool -ltdl]) ],[AC_MSG_ERROR([could not locate libtool -lltdl])]) AC_DEFINE(LDAP_SLAPI,1, [define this to add SLAPI code]) fi if test "$ol_enable_debug" != no ; then if test "$ol_enable_debug" = traditional; then AC_DEFINE(OLD_DEBUG,1, [define to use the original debug style]) fi AC_DEFINE(LDAP_DEBUG,1, [define this to add debugging code]) fi if test "$ol_enable_syslog" = yes ; then AC_DEFINE(LDAP_SYSLOG,1, [define this to add syslog code]) fi if test "$ol_enable_proctitle" != no ; then AC_DEFINE(LDAP_PROCTITLE,1, [define this for LDAP process title support]) fi if test "$ol_enable_referrals" != no ; then AC_DEFINE(LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS,LDAP_VENDOR_VERSION, [define to LDAP VENDOR VERSION]) fi if test "$ol_enable_local" != no; then AC_DEFINE(LDAP_PF_LOCAL,1,[define to support PF_LOCAL]) fi if test "$ol_link_ipv6" != no; then AC_DEFINE(LDAP_PF_INET6,1,[define to support PF_INET6]) fi if test "$ol_enable_cleartext" != no ; then AC_DEFINE(SLAPD_CLEARTEXT,1,[define to support cleartext passwords]) fi if test "$ol_enable_crypt" != no ; then AC_DEFINE(SLAPD_CRYPT,1,[define to support crypt(3) passwords]) fi if test "$ol_link_spasswd" != no ; then AC_DEFINE(SLAPD_SPASSWD,1,[define to support SASL passwords]) fi if test "$ol_enable_rlookups" != no ; then AC_DEFINE(SLAPD_RLOOKUPS,1,[define to support reverse lookups]) fi if test "$ol_enable_aci" != no ; then if test $ol_enable_dynacl = no ; then ol_enable_dynacl=yes AC_MSG_WARN([ACIs need dynacl]) fi if test "$ol_enable_aci" = mod ; then MFLAG=SLAPD_MOD_DYNAMIC dnl remove this after moving servers/slapd/aci.c in contrib/slapd-modules/acl AC_MSG_ERROR([ACI build as dynamic module not supported (yet)]) else MFLAG=SLAPD_MOD_STATIC fi WITH_ACI_ENABLED=$ol_enable_aci AC_DEFINE_UNQUOTED(SLAPD_ACI_ENABLED,$MFLAG,[define to support per-object ACIs]) else WITH_ACI_ENABLED=no fi if test "$ol_enable_dynacl" != no ; then AC_DEFINE(SLAP_DYNACL,1,[define to support run-time loadable ACL]) fi if test "$ol_link_modules" != no ; then AC_DEFINE(SLAPD_MODULES,1,[define to support modules]) BUILD_SLAPD=yes SLAPD_MODULES_LDFLAGS="-dlopen self" fi AC_DEFINE(SLAPD_MOD_STATIC,1,[statically linked module]) AC_DEFINE(SLAPD_MOD_DYNAMIC,2,[dynamically linked module]) dnl back-monitor goes first (well, after back-config) if test "$ol_enable_monitor" != no ; then BUILD_SLAPD=yes BUILD_MONITOR=$ol_enable_monitor if test "$ol_enable_monitor" = mod ; then SLAPD_DYNAMIC_BACKENDS="$SLAPD_DYNAMIC_BACKENDS back-monitor" MFLAG=SLAPD_MOD_DYNAMIC else SLAPD_STATIC_BACKENDS="$SLAPD_STATIC_BACKENDS back-monitor" MFLAG=SLAPD_MOD_STATIC fi AC_DEFINE_UNQUOTED(SLAPD_MONITOR,$MFLAG,[define to support cn=Monitor backend]) fi if test "$ol_enable_bdb" != no ; then BUILD_SLAPD=yes BUILD_BDB=$ol_enable_bdb if test "$ol_enable_bdb" = mod ; then SLAPD_DYNAMIC_BACKENDS="$SLAPD_DYNAMIC_BACKENDS back-bdb" MFLAG=SLAPD_MOD_DYNAMIC else SLAPD_STATIC_BACKENDS="$SLAPD_STATIC_BACKENDS back-bdb" MFLAG=SLAPD_MOD_STATIC fi AC_DEFINE_UNQUOTED(SLAPD_BDB,$MFLAG,[define to support BDB backend]) fi if test "$ol_enable_dnssrv" != no ; then BUILD_SLAPD=yes BUILD_DNSSRV=$ol_enable_dnssrv if test "$ol_enable_dnssrv" = mod ; then SLAPD_DYNAMIC_BACKENDS="$SLAPD_DYNAMIC_BACKENDS back-dnssrv" MFLAG=SLAPD_MOD_DYNAMIC else SLAPD_STATIC_BACKENDS="$SLAPD_STATIC_BACKENDS back-dnssrv" MFLAG=SLAPD_MOD_STATIC fi AC_DEFINE_UNQUOTED(SLAPD_DNSSRV,$MFLAG,[define to support DNS SRV backend]) fi if test "$ol_enable_hdb" != no ; then BUILD_SLAPD=yes BUILD_HDB=$ol_enable_hdb if test "$ol_enable_hdb" = mod ; then SLAPD_DYNAMIC_BACKENDS="$SLAPD_DYNAMIC_BACKENDS back-hdb" MFLAG=SLAPD_MOD_DYNAMIC else SLAPD_STATIC_BACKENDS="$SLAPD_STATIC_BACKENDS back-hdb" MFLAG=SLAPD_MOD_STATIC fi AC_DEFINE_UNQUOTED(SLAPD_HDB,$MFLAG,[define to support HDB backend]) fi if test "$ol_enable_ldap" != no ; then BUILD_SLAPD=yes BUILD_LDAP=$ol_enable_ldap if test "$ol_enable_ldap" = mod ; then SLAPD_DYNAMIC_BACKENDS="$SLAPD_DYNAMIC_BACKENDS back-ldap" MFLAG=SLAPD_MOD_DYNAMIC else SLAPD_STATIC_BACKENDS="$SLAPD_STATIC_BACKENDS back-ldap" MFLAG=SLAPD_MOD_STATIC fi AC_DEFINE_UNQUOTED(SLAPD_LDAP,$MFLAG,[define to support LDAP backend]) fi if test "$ol_enable_mdb" != no ; then BUILD_SLAPD=yes BUILD_MDB=$ol_enable_mdb if test "$ol_enable_mdb" = mod ; then SLAPD_DYNAMIC_BACKENDS="$SLAPD_DYNAMIC_BACKENDS back-mdb" MFLAG=SLAPD_MOD_DYNAMIC else SLAPD_STATIC_BACKENDS="$SLAPD_STATIC_BACKENDS back-mdb" MFLAG=SLAPD_MOD_STATIC fi AC_DEFINE_UNQUOTED(SLAPD_MDB,$MFLAG,[define to support MDB backend]) fi if test "$ol_enable_meta" != no ; then BUILD_SLAPD=yes BUILD_META=$ol_enable_meta BUILD_REWRITE=yes if test "$ol_enable_meta" = mod ; then SLAPD_DYNAMIC_BACKENDS="$SLAPD_DYNAMIC_BACKENDS back-meta" MFLAG=SLAPD_MOD_DYNAMIC else SLAPD_STATIC_BACKENDS="$SLAPD_STATIC_BACKENDS back-meta" MFLAG=SLAPD_MOD_STATIC fi AC_DEFINE_UNQUOTED(SLAPD_META,$MFLAG,[define to support LDAP Metadirectory backend]) fi if test "$ol_enable_ndb" != no ; then BUILD_SLAPD=yes BUILD_NDB=$ol_enable_ndb if test "$ol_enable_ndb" = mod ; then SLAPD_DYNAMIC_BACKENDS="$SLAPD_DYNAMIC_BACKENDS back-ndb" MFLAG=SLAPD_MOD_DYNAMIC else SLAPD_STATIC_BACKENDS="$SLAPD_STATIC_BACKENDS back-ndb" MFLAG=SLAPD_MOD_STATIC fi AC_DEFINE_UNQUOTED(SLAPD_NDB,$MFLAG,[define to support NDB backend]) fi if test "$ol_enable_null" != no ; then BUILD_SLAPD=yes BUILD_NULL=$ol_enable_null if test "$ol_enable_null" = mod ; then SLAPD_DYNAMIC_BACKENDS="$SLAPD_DYNAMIC_BACKENDS back-null" MFLAG=SLAPD_MOD_DYNAMIC else SLAPD_STATIC_BACKENDS="$SLAPD_STATIC_BACKENDS back-null" MFLAG=SLAPD_MOD_STATIC fi AC_DEFINE_UNQUOTED(SLAPD_NULL,$MFLAG,[define to support NULL backend]) fi if test "$ol_enable_passwd" != no ; then BUILD_SLAPD=yes BUILD_PASSWD=$ol_enable_passwd if test "$ol_enable_passwd" = mod ; then SLAPD_DYNAMIC_BACKENDS="$SLAPD_DYNAMIC_BACKENDS back-passwd" MFLAG=SLAPD_MOD_DYNAMIC else SLAPD_STATIC_BACKENDS="$SLAPD_STATIC_BACKENDS back-passwd" MFLAG=SLAPD_MOD_STATIC fi AC_DEFINE_UNQUOTED(SLAPD_PASSWD,$MFLAG,[define to support PASSWD backend]) fi if test "$ol_link_perl" != no ; then BUILD_SLAPD=yes BUILD_PERL=$ol_enable_perl if test "$ol_enable_perl" = mod ; then SLAPD_DYNAMIC_BACKENDS="$SLAPD_DYNAMIC_BACKENDS back-perl" MFLAG=SLAPD_MOD_DYNAMIC else SLAPD_STATIC_BACKENDS="$SLAPD_STATIC_BACKENDS back-perl" MFLAG=SLAPD_MOD_STATIC fi AC_DEFINE_UNQUOTED(SLAPD_PERL,$MFLAG,[define to support PERL backend]) fi if test "$ol_enable_relay" != no ; then BUILD_SLAPD=yes BUILD_RELAY=$ol_enable_relay if test "$ol_enable_relay" = mod ; then SLAPD_DYNAMIC_BACKENDS="$SLAPD_DYNAMIC_BACKENDS back-relay" MFLAG=SLAPD_MOD_DYNAMIC else SLAPD_STATIC_BACKENDS="$SLAPD_STATIC_BACKENDS back-relay" MFLAG=SLAPD_MOD_STATIC fi AC_DEFINE_UNQUOTED(SLAPD_RELAY,$MFLAG,[define to support relay backend]) fi if test "$ol_enable_shell" != no ; then if test "$ol_link_threads" != no ; then AC_MSG_WARN([Use of --without-threads is recommended with back-shell]) fi BUILD_SLAPD=yes BUILD_SHELL=$ol_enable_shell if test "$ol_enable_shell" = mod ; then SLAPD_DYNAMIC_BACKENDS="$SLAPD_DYNAMIC_BACKENDS back-shell" MFLAG=SLAPD_MOD_DYNAMIC else SLAPD_STATIC_BACKENDS="$SLAPD_STATIC_BACKENDS back-shell" MFLAG=SLAPD_MOD_STATIC fi AC_DEFINE_UNQUOTED(SLAPD_SHELL,$MFLAG,[define to support SHELL backend]) fi if test "$ol_enable_sock" != no ; then BUILD_SLAPD=yes BUILD_SOCK=$ol_enable_sock if test "$ol_enable_sock" = mod ; then SLAPD_DYNAMIC_BACKENDS="$SLAPD_DYNAMIC_BACKENDS back-sock" MFLAG=SLAPD_MOD_DYNAMIC else SLAPD_STATIC_BACKENDS="$SLAPD_STATIC_BACKENDS back-sock" MFLAG=SLAPD_MOD_STATIC fi AC_DEFINE_UNQUOTED(SLAPD_SOCK,$MFLAG,[define to support SOCK backend]) fi if test "$ol_link_sql" != no ; then BUILD_SLAPD=yes BUILD_SQL=$ol_enable_sql if test "$ol_enable_sql" = mod; then SLAPD_DYNAMIC_BACKENDS="$SLAPD_DYNAMIC_BACKENDS back-sql" MFLAG=SLAPD_MOD_DYNAMIC else SLAPD_STATIC_BACKENDS="$SLAPD_STATIC_BACKENDS back-sql" MFLAG=SLAPD_MOD_STATIC fi AC_DEFINE_UNQUOTED(SLAPD_SQL,$MFLAG,[define to support SQL backend]) fi if test "$ol_enable_accesslog" != no ; then BUILD_ACCESSLOG=$ol_enable_accesslog if test "$ol_enable_accesslog" = mod ; then MFLAG=SLAPD_MOD_DYNAMIC SLAPD_DYNAMIC_OVERLAYS="$SLAPD_DYNAMIC_OVERLAYS accesslog.la" else MFLAG=SLAPD_MOD_STATIC SLAPD_STATIC_OVERLAYS="$SLAPD_STATIC_OVERLAYS accesslog.o" fi AC_DEFINE_UNQUOTED(SLAPD_OVER_ACCESSLOG,$MFLAG,[define for In-Directory Access Logging overlay]) fi if test "$ol_enable_auditlog" != no ; then BUILD_AUDITLOG=$ol_enable_auditlog if test "$ol_enable_auditlog" = mod ; then MFLAG=SLAPD_MOD_DYNAMIC SLAPD_DYNAMIC_OVERLAYS="$SLAPD_DYNAMIC_OVERLAYS auditlog.la" else MFLAG=SLAPD_MOD_STATIC SLAPD_STATIC_OVERLAYS="$SLAPD_STATIC_OVERLAYS auditlog.o" fi AC_DEFINE_UNQUOTED(SLAPD_OVER_AUDITLOG,$MFLAG,[define for Audit Logging overlay]) fi if test "$ol_enable_collect" != no ; then BUILD_COLLECT=$ol_enable_collect if test "$ol_enable_collect" = mod ; then MFLAG=SLAPD_MOD_DYNAMIC SLAPD_DYNAMIC_OVERLAYS="$SLAPD_DYNAMIC_OVERLAYS collect.la" else MFLAG=SLAPD_MOD_STATIC SLAPD_STATIC_OVERLAYS="$SLAPD_STATIC_OVERLAYS collect.o" fi AC_DEFINE_UNQUOTED(SLAPD_OVER_COLLECT,$MFLAG,[define for Collect overlay]) fi if test "$ol_enable_constraint" != no ; then BUILD_CONSTRAINT=$ol_enable_constraint if test "$ol_enable_constraint" = mod ; then MFLAG=SLAPD_MOD_DYNAMIC SLAPD_DYNAMIC_OVERLAYS="$SLAPD_DYNAMIC_OVERLAYS constraint.la" else MFLAG=SLAPD_MOD_STATIC SLAPD_STATIC_OVERLAYS="$SLAPD_STATIC_OVERLAYS constraint.o" fi AC_DEFINE_UNQUOTED(SLAPD_OVER_CONSTRAINT,$MFLAG,[define for Attribute Constraint overlay]) fi if test "$ol_enable_dds" != no ; then BUILD_DDS=$ol_enable_dds if test "$ol_enable_dds" = mod ; then MFLAG=SLAPD_MOD_DYNAMIC SLAPD_DYNAMIC_OVERLAYS="$SLAPD_DYNAMIC_OVERLAYS dds.la" else MFLAG=SLAPD_MOD_STATIC SLAPD_STATIC_OVERLAYS="$SLAPD_STATIC_OVERLAYS dds.o" fi AC_DEFINE_UNQUOTED(SLAPD_OVER_DDS,$MFLAG,[define for Dynamic Directory Services overlay]) fi if test "$ol_enable_deref" != no ; then BUILD_DEREF=$ol_enable_deref if test "$ol_enable_deref" = mod ; then MFLAG=SLAPD_MOD_DYNAMIC SLAPD_DYNAMIC_OVERLAYS="$SLAPD_DYNAMIC_OVERLAYS deref.la" else MFLAG=SLAPD_MOD_STATIC SLAPD_STATIC_OVERLAYS="$SLAPD_STATIC_OVERLAYS deref.o" fi AC_DEFINE_UNQUOTED(SLAPD_OVER_DEREF,$MFLAG,[define for Dynamic Directory Services overlay]) fi if test "$ol_enable_dyngroup" != no ; then BUILD_DYNGROUP=$ol_enable_dyngroup if test "$ol_enable_dyngroup" = mod ; then MFLAG=SLAPD_MOD_DYNAMIC SLAPD_DYNAMIC_OVERLAYS="$SLAPD_DYNAMIC_OVERLAYS dyngroup.la" else MFLAG=SLAPD_MOD_STATIC SLAPD_STATIC_OVERLAYS="$SLAPD_STATIC_OVERLAYS dyngroup.o" fi AC_DEFINE_UNQUOTED(SLAPD_OVER_DYNGROUP,$MFLAG,[define for Dynamic Group overlay]) fi if test "$ol_enable_dynlist" != no ; then BUILD_DYNLIST=$ol_enable_dynlist if test "$ol_enable_dynlist" = mod ; then MFLAG=SLAPD_MOD_DYNAMIC SLAPD_DYNAMIC_OVERLAYS="$SLAPD_DYNAMIC_OVERLAYS dynlist.la" else MFLAG=SLAPD_MOD_STATIC SLAPD_STATIC_OVERLAYS="$SLAPD_STATIC_OVERLAYS dynlist.o" fi AC_DEFINE_UNQUOTED(SLAPD_OVER_DYNLIST,$MFLAG,[define for Dynamic List overlay]) fi if test "$ol_enable_memberof" != no ; then BUILD_MEMBEROF=$ol_enable_memberof if test "$ol_enable_memberof" = mod ; then MFLAG=SLAPD_MOD_DYNAMIC SLAPD_DYNAMIC_OVERLAYS="$SLAPD_DYNAMIC_OVERLAYS memberof.la" else MFLAG=SLAPD_MOD_STATIC SLAPD_STATIC_OVERLAYS="$SLAPD_STATIC_OVERLAYS memberof.o" fi AC_DEFINE_UNQUOTED(SLAPD_OVER_MEMBEROF,$MFLAG,[define for Reverse Group Membership overlay]) fi if test "$ol_enable_ppolicy" != no ; then BUILD_PPOLICY=$ol_enable_ppolicy if test "$ol_enable_ppolicy" = mod ; then MFLAG=SLAPD_MOD_DYNAMIC SLAPD_DYNAMIC_OVERLAYS="$SLAPD_DYNAMIC_OVERLAYS ppolicy.la" else MFLAG=SLAPD_MOD_STATIC SLAPD_STATIC_OVERLAYS="$SLAPD_STATIC_OVERLAYS ppolicy.o" fi AC_DEFINE_UNQUOTED(SLAPD_OVER_PPOLICY,$MFLAG,[define for Password Policy overlay]) fi if test "$ol_enable_proxycache" != no ; then BUILD_PROXYCACHE=$ol_enable_proxycache if test "$ol_enable_proxycache" = mod ; then MFLAG=SLAPD_MOD_DYNAMIC SLAPD_DYNAMIC_OVERLAYS="$SLAPD_DYNAMIC_OVERLAYS pcache.la" else MFLAG=SLAPD_MOD_STATIC SLAPD_STATIC_OVERLAYS="$SLAPD_STATIC_OVERLAYS pcache.o" fi AC_DEFINE_UNQUOTED(SLAPD_OVER_PROXYCACHE,$MFLAG,[define for Proxy Cache overlay]) fi if test "$ol_enable_refint" != no ; then BUILD_REFINT=$ol_enable_refint if test "$ol_enable_refint" = mod ; then MFLAG=SLAPD_MOD_DYNAMIC SLAPD_DYNAMIC_OVERLAYS="$SLAPD_DYNAMIC_OVERLAYS refint.la" else MFLAG=SLAPD_MOD_STATIC SLAPD_STATIC_OVERLAYS="$SLAPD_STATIC_OVERLAYS refint.o" fi AC_DEFINE_UNQUOTED(SLAPD_OVER_REFINT,$MFLAG,[define for Referential Integrity overlay]) fi if test "$ol_enable_retcode" != no ; then BUILD_RETCODE=$ol_enable_retcode if test "$ol_enable_retcode" = mod ; then MFLAG=SLAPD_MOD_DYNAMIC SLAPD_DYNAMIC_OVERLAYS="$SLAPD_DYNAMIC_OVERLAYS retcode.la" else MFLAG=SLAPD_MOD_STATIC SLAPD_STATIC_OVERLAYS="$SLAPD_STATIC_OVERLAYS retcode.o" fi AC_DEFINE_UNQUOTED(SLAPD_OVER_RETCODE,$MFLAG,[define for Referential Integrity overlay]) fi if test "$ol_enable_rwm" != no ; then BUILD_REWRITE=yes BUILD_RWM=$ol_enable_rwm if test "$ol_enable_rwm" = mod ; then MFLAG=SLAPD_MOD_DYNAMIC SLAPD_DYNAMIC_OVERLAYS="$SLAPD_DYNAMIC_OVERLAYS rwm.la" else MFLAG=SLAPD_MOD_STATIC SLAPD_STATIC_OVERLAYS="$SLAPD_STATIC_OVERLAYS rwm_x.o" fi AC_DEFINE_UNQUOTED(SLAPD_OVER_RWM,$MFLAG,[define for Rewrite/Remap overlay]) fi if test "$ol_enable_seqmod" != no ; then BUILD_SEQMOD=$ol_enable_seqmod if test "$ol_enable_seqmod" = mod ; then MFLAG=SLAPD_MOD_DYNAMIC SLAPD_DYNAMIC_OVERLAYS="$SLAPD_DYNAMIC_OVERLAYS seqmod.la" else MFLAG=SLAPD_MOD_STATIC SLAPD_STATIC_OVERLAYS="$SLAPD_STATIC_OVERLAYS seqmod.o" fi AC_DEFINE_UNQUOTED(SLAPD_OVER_SEQMOD,$MFLAG,[define for Sequential Modify overlay]) fi if test "$ol_enable_sssvlv" != no ; then BUILD_SSSVLV=$ol_enable_sssvlv if test "$ol_enable_sssvlv" = mod ; then MFLAG=SLAPD_MOD_DYNAMIC SLAPD_DYNAMIC_OVERLAYS="$SLAPD_DYNAMIC_OVERLAYS sssvlv.la" else MFLAG=SLAPD_MOD_STATIC SLAPD_STATIC_OVERLAYS="$SLAPD_STATIC_OVERLAYS sssvlv.o" fi AC_DEFINE_UNQUOTED(SLAPD_OVER_SSSVLV,$MFLAG,[define for ServerSideSort/VLV overlay]) fi if test "$ol_enable_syncprov" != no ; then BUILD_SYNCPROV=$ol_enable_syncprov if test "$ol_enable_syncprov" = mod ; then MFLAG=SLAPD_MOD_DYNAMIC SLAPD_DYNAMIC_OVERLAYS="$SLAPD_DYNAMIC_OVERLAYS syncprov.la" else MFLAG=SLAPD_MOD_STATIC SLAPD_STATIC_OVERLAYS="$SLAPD_STATIC_OVERLAYS syncprov.o" fi AC_DEFINE_UNQUOTED(SLAPD_OVER_SYNCPROV,$MFLAG,[define for Syncrepl Provider overlay]) fi if test "$ol_enable_translucent" != no ; then BUILD_TRANSLUCENT=$ol_enable_translucent if test "$ol_enable_translucent" = mod ; then MFLAG=SLAPD_MOD_DYNAMIC SLAPD_DYNAMIC_OVERLAYS="$SLAPD_DYNAMIC_OVERLAYS translucent.la" else MFLAG=SLAPD_MOD_STATIC SLAPD_STATIC_OVERLAYS="$SLAPD_STATIC_OVERLAYS translucent.o" fi AC_DEFINE_UNQUOTED(SLAPD_OVER_TRANSLUCENT,$MFLAG,[define for Translucent Proxy overlay]) fi if test "$ol_enable_unique" != no ; then BUILD_UNIQUE=$ol_enable_unique if test "$ol_enable_unique" = mod ; then MFLAG=SLAPD_MOD_DYNAMIC SLAPD_DYNAMIC_OVERLAYS="$SLAPD_DYNAMIC_OVERLAYS unique.la" else MFLAG=SLAPD_MOD_STATIC SLAPD_STATIC_OVERLAYS="$SLAPD_STATIC_OVERLAYS unique.o" fi AC_DEFINE_UNQUOTED(SLAPD_OVER_UNIQUE,$MFLAG,[define for Attribute Uniqueness overlay]) fi if test "$ol_enable_valsort" != no ; then BUILD_VALSORT=$ol_enable_valsort if test "$ol_enable_valsort" = mod ; then MFLAG=SLAPD_MOD_DYNAMIC SLAPD_DYNAMIC_OVERLAYS="$SLAPD_DYNAMIC_OVERLAYS valsort.la" else MFLAG=SLAPD_MOD_STATIC SLAPD_STATIC_OVERLAYS="$SLAPD_STATIC_OVERLAYS valsort.o" fi AC_DEFINE_UNQUOTED(SLAPD_OVER_VALSORT,$MFLAG,[define for Value Sorting overlay]) fi if test "$ol_enable_rewrite" != no ; then AC_DEFINE(ENABLE_REWRITE,1,[define to enable rewriting in back-ldap and back-meta]) BUILD_REWRITE=yes fi if test "$ol_enable_slapi" != no ; then AC_DEFINE(ENABLE_SLAPI,1,[define to enable slapi library]) BUILD_SLAPI=yes SLAPD_SLAPI_DEPEND=libslapi.a fi dnl ---------------------------------------------------------------- dnl dnl For Windows build, we don't want to include -dlopen flags. dnl They hurt more than they help. dnl if test "$ac_cv_mingw32" = yes -o $ol_cv_msvc = yes ; then PLAT=NT SLAPD_MODULES_LDFLAGS= else PLAT=UNIX fi AC_SUBST(LIBSRCS) AC_SUBST(PLAT) AC_SUBST(WITH_SASL) AC_SUBST(WITH_TLS) AC_SUBST(WITH_MODULES_ENABLED) AC_SUBST(WITH_ACI_ENABLED) AC_SUBST(BUILD_THREAD) AC_SUBST(BUILD_LIBS_DYNAMIC) AC_SUBST(BUILD_SLAPD) dnl slapi AC_SUBST(BUILD_SLAPI) AC_SUBST(SLAPD_SLAPI_DEPEND) dnl backends AC_SUBST(BUILD_BDB) AC_SUBST(BUILD_DNSSRV) AC_SUBST(BUILD_HDB) AC_SUBST(BUILD_LDAP) AC_SUBST(BUILD_MDB) AC_SUBST(BUILD_META) AC_SUBST(BUILD_MONITOR) AC_SUBST(BUILD_NDB) AC_SUBST(BUILD_NULL) AC_SUBST(BUILD_PASSWD) AC_SUBST(BUILD_RELAY) AC_SUBST(BUILD_PERL) AC_SUBST(BUILD_SHELL) AC_SUBST(BUILD_SOCK) AC_SUBST(BUILD_SQL) dnl overlays AC_SUBST(BUILD_ACCESSLOG) AC_SUBST(BUILD_AUDITLOG) AC_SUBST(BUILD_COLLECT) AC_SUBST(BUILD_CONSTRAINT) AC_SUBST(BUILD_DDS) AC_SUBST(BUILD_DENYOP) AC_SUBST(BUILD_DEREF) AC_SUBST(BUILD_DYNGROUP) AC_SUBST(BUILD_DYNLIST) AC_SUBST(BUILD_LASTMOD) AC_SUBST(BUILD_MEMBEROF) AC_SUBST(BUILD_PPOLICY) AC_SUBST(BUILD_PROXYCACHE) AC_SUBST(BUILD_REFINT) AC_SUBST(BUILD_RETCODE) AC_SUBST(BUILD_RWM) AC_SUBST(BUILD_SEQMOD) AC_SUBST(BUILD_SSSVLV) AC_SUBST(BUILD_SYNCPROV) AC_SUBST(BUILD_TRANSLUCENT) AC_SUBST(BUILD_UNIQUE) AC_SUBST(BUILD_VALSORT) AC_SUBST(LDAP_LIBS) AC_SUBST(SLAPD_LIBS) AC_SUBST(BDB_LIBS) AC_SUBST(SLAPD_NDB_LIBS) AC_SUBST(SLAPD_NDB_INCS) AC_SUBST(LTHREAD_LIBS) AC_SUBST(LUTIL_LIBS) AC_SUBST(WRAP_LIBS) AC_SUBST(SLAPD_MODULES_CPPFLAGS) AC_SUBST(SLAPD_MODULES_LDFLAGS) AC_SUBST(SLAPD_NO_STATIC) AC_SUBST(SLAPD_STATIC_BACKENDS) AC_SUBST(SLAPD_DYNAMIC_BACKENDS) AC_SUBST(SLAPD_STATIC_OVERLAYS) AC_SUBST(SLAPD_DYNAMIC_OVERLAYS) AC_SUBST(PERL_CPPFLAGS) AC_SUBST(SLAPD_PERL_LDFLAGS) AC_SUBST(MOD_PERL_LDFLAGS) AC_SUBST(KRB4_LIBS) AC_SUBST(KRB5_LIBS) AC_SUBST(SASL_LIBS) AC_SUBST(TLS_LIBS) AC_SUBST(MODULES_LIBS) AC_SUBST(SLAPI_LIBS) AC_SUBST(LIBSLAPI) AC_SUBST(AUTH_LIBS) AC_SUBST(ICU_LIBS) AC_SUBST(SLAPD_SLP_LIBS) AC_SUBST(SLAPD_GMP_LIBS) AC_SUBST(SLAPD_SQL_LDFLAGS) AC_SUBST(SLAPD_SQL_LIBS) AC_SUBST(SLAPD_SQL_INCLUDES) dnl ---------------------------------------------------------------- dnl final help output AC_ARG_WITH(xxinstall,[ See INSTALL file for further details.]) dnl ---------------------------------------------------------------- dnl final output dnl AC_CONFIG_FILES([Makefile:build/top.mk:Makefile.in:build/dir.mk] [doc/Makefile:build/top.mk:doc/Makefile.in:build/dir.mk] [doc/man/Makefile:build/top.mk:doc/man/Makefile.in:build/dir.mk] [doc/man/man1/Makefile:build/top.mk:doc/man/man1/Makefile.in:build/man.mk] [doc/man/man3/Makefile:build/top.mk:doc/man/man3/Makefile.in:build/man.mk] [doc/man/man5/Makefile:build/top.mk:doc/man/man5/Makefile.in:build/man.mk] [doc/man/man8/Makefile:build/top.mk:doc/man/man8/Makefile.in:build/man.mk] [clients/Makefile:build/top.mk:clients/Makefile.in:build/dir.mk] [clients/tools/Makefile:build/top.mk:clients/tools/Makefile.in:build/rules.mk] [include/Makefile:build/top.mk:include/Makefile.in] [libraries/Makefile:build/top.mk:libraries/Makefile.in:build/dir.mk] [libraries/liblber/Makefile:build/top.mk:libraries/liblber/Makefile.in:build/lib.mk:build/lib-shared.mk] [libraries/libldap/Makefile:build/top.mk:libraries/libldap/Makefile.in:build/lib.mk:build/lib-shared.mk] [libraries/libldap_r/Makefile:build/top.mk:libraries/libldap_r/Makefile.in:build/lib.mk:build/lib-shared.mk] [libraries/liblunicode/Makefile:build/top.mk:libraries/liblunicode/Makefile.in:build/lib.mk:build/lib-static.mk] [libraries/liblutil/Makefile:build/top.mk:libraries/liblutil/Makefile.in:build/lib.mk:build/lib-static.mk] [libraries/librewrite/Makefile:build/top.mk:libraries/librewrite/Makefile.in:build/lib.mk:build/lib-static.mk] [servers/Makefile:build/top.mk:servers/Makefile.in:build/dir.mk] [servers/slapd/Makefile:build/top.mk:servers/slapd/Makefile.in:build/srv.mk] [servers/slapd/back-bdb/Makefile:build/top.mk:servers/slapd/back-bdb/Makefile.in:build/mod.mk] [servers/slapd/back-dnssrv/Makefile:build/top.mk:servers/slapd/back-dnssrv/Makefile.in:build/mod.mk] [servers/slapd/back-hdb/Makefile:build/top.mk:servers/slapd/back-hdb/Makefile.in:build/mod.mk] [servers/slapd/back-ldap/Makefile:build/top.mk:servers/slapd/back-ldap/Makefile.in:build/mod.mk] [servers/slapd/back-ldif/Makefile:build/top.mk:servers/slapd/back-ldif/Makefile.in:build/mod.mk] [servers/slapd/back-mdb/Makefile:build/top.mk:servers/slapd/back-mdb/Makefile.in:build/mod.mk] [servers/slapd/back-meta/Makefile:build/top.mk:servers/slapd/back-meta/Makefile.in:build/mod.mk] [servers/slapd/back-monitor/Makefile:build/top.mk:servers/slapd/back-monitor/Makefile.in:build/mod.mk] [servers/slapd/back-ndb/Makefile:build/top.mk:servers/slapd/back-ndb/Makefile.in:build/mod.mk] [servers/slapd/back-null/Makefile:build/top.mk:servers/slapd/back-null/Makefile.in:build/mod.mk] [servers/slapd/back-passwd/Makefile:build/top.mk:servers/slapd/back-passwd/Makefile.in:build/mod.mk] [servers/slapd/back-perl/Makefile:build/top.mk:servers/slapd/back-perl/Makefile.in:build/mod.mk] [servers/slapd/back-relay/Makefile:build/top.mk:servers/slapd/back-relay/Makefile.in:build/mod.mk] [servers/slapd/back-shell/Makefile:build/top.mk:servers/slapd/back-shell/Makefile.in:build/mod.mk] [servers/slapd/back-sock/Makefile:build/top.mk:servers/slapd/back-sock/Makefile.in:build/mod.mk] [servers/slapd/back-sql/Makefile:build/top.mk:servers/slapd/back-sql/Makefile.in:build/mod.mk] [servers/slapd/shell-backends/Makefile:build/top.mk:servers/slapd/shell-backends/Makefile.in:build/srv.mk] [servers/slapd/slapi/Makefile:build/top.mk:servers/slapd/slapi/Makefile.in:build/lib.mk:build/lib-shared.mk] [servers/slapd/overlays/Makefile:build/top.mk:servers/slapd/overlays/Makefile.in:build/lib.mk] [tests/Makefile:build/top.mk:tests/Makefile.in:build/dir.mk] [tests/run] [tests/progs/Makefile:build/top.mk:tests/progs/Makefile.in:build/rules.mk]) AC_CONFIG_COMMANDS([default],[[ chmod +x tests/run date > stamp-h BACKENDSC="servers/slapd/backends.c" echo "Making $BACKENDSC" rm -f $BACKENDSC cat > $BACKENDSC << ENDX /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* This file is automatically generated by configure; please do not edit. */ #include "portable.h" #include "slap.h" ENDX if test "${STATIC_BACKENDS}"; then for b in config ${STATIC_BACKENDS}; do bb=`echo "${b}" | sed -e 's/back-//'` cat >> $BACKENDSC << ENDX extern BI_init ${bb}_back_initialize; ENDX done cat >> $BACKENDSC << ENDX BackendInfo slap_binfo[] = { ENDX for b in config ${STATIC_BACKENDS}; do bb=`echo "${b}" | sed -e 's/back-//'` echo " Add ${bb} ..." cat >> $BACKENDSC << ENDX { "${bb}", ${bb}_back_initialize }, ENDX done cat >> $BACKENDSC << ENDX { NULL, NULL }, }; /* end of generated file */ ENDX fi OVERLAYSC="servers/slapd/overlays/statover.c" echo "Making $OVERLAYSC" rm -f $OVERLAYSC cat > $OVERLAYSC << ENDX /* This work is part of OpenLDAP Software . * * Copyright 1998-2015 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* This file is automatically generated by configure; please do not edit. */ #include "portable.h" #include "slap.h" ENDX if test "${STATIC_OVERLAYS}"; then for o in ${STATIC_OVERLAYS}; do oo=`echo "${o}" | sed -e 's/.o$//' -e 's/_x$//'` cat >> $OVERLAYSC << ENDX extern OV_init ${oo}_initialize; ENDX done fi cat >> $OVERLAYSC << ENDX OverlayInit slap_oinfo[] = { ENDX if test "${STATIC_OVERLAYS}"; then for o in ${STATIC_OVERLAYS}; do oo=`echo "${o}" | sed -e 's/.o$//' -e 's/_x$//'` echo " Add ${oo} ..." cat >> $OVERLAYSC << ENDX { "${oo}", ${oo}_initialize }, ENDX done fi cat >> $OVERLAYSC << ENDX { NULL, NULL }, }; /* end of generated file */ ENDX if test "${ol_cv_mkdep}" = no; then echo '(Do not "make depend"; we do not know how to build dependencies)' else echo 'Please run "make depend" to build dependencies' fi ]],[[ STATIC_BACKENDS="$SLAPD_STATIC_BACKENDS" STATIC_OVERLAYS="$SLAPD_STATIC_OVERLAYS" ]]) AC_OUTPUT openldap-2.4.42+dfsg/doc/0000755000175000017500000000000012563463333013605 5ustar ryanryanopenldap-2.4.42+dfsg/doc/Makefile.in0000644000175000017500000000103312563404150015637 0ustar ryanryan## doc Makefile.in for OpenLDAP # $OpenLDAP$ ## This work is part of OpenLDAP Software . ## ## Copyright 1998-2015 The OpenLDAP Foundation. ## All rights reserved. ## ## Redistribution and use in source and binary forms, with or without ## modification, are permitted only as authorized by the OpenLDAP ## Public License. ## ## A copy of this license is available in the file LICENSE in the ## top-level directory of the distribution or, alternatively, at ## . SUBDIRS= man openldap-2.4.42+dfsg/doc/man/0000755000175000017500000000000012563404150014350 5ustar ryanryanopenldap-2.4.42+dfsg/doc/man/Makefile.in0000644000175000017500000000105212563404150016413 0ustar ryanryan# man Makefile.in for OpenLDAP # $OpenLDAP$ ## This work is part of OpenLDAP Software . ## ## Copyright 1998-2015 The OpenLDAP Foundation. ## All rights reserved. ## ## Redistribution and use in source and binary forms, with or without ## modification, are permitted only as authorized by the OpenLDAP ## Public License. ## ## A copy of this license is available in the file LICENSE in the ## top-level directory of the distribution or, alternatively, at ## . SUBDIRS= man1 man3 man5 man8 openldap-2.4.42+dfsg/doc/man/man3/0000755000175000017500000000000012563404150015206 5ustar ryanryanopenldap-2.4.42+dfsg/doc/man/man3/ldap_first_attribute.3.links0000644000175000017500000000002612563404150022621 0ustar ryanryanldap_next_attribute.3 openldap-2.4.42+dfsg/doc/man/man3/ldap_sort.30000644000175000017500000000103712563404150017262 0ustar ryanryan.TH LDAP_SORT 3 "RELEASEDATE" "OpenLDAP LDVERSION" .\" $OpenLDAP$ .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_sort_entries, ldap_sort_values, ldap_sort_strcasecmp \- LDAP sorting routines (deprecated) .SH LIBRARY OpenLDAP LDAP (libldap, \-lldap) .SH DESCRIPTION The .BR ldap_sort_entries (), .BR ldap_sort_values (), and .BR ldap_sort_strcasecmp () are deprecated. .LP .so Deprecated .SH SEE ALSO .BR ldap (3) .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man3/ldap_get_values.3.links0000644000175000017500000000015212563404150021545 0ustar ryanryanldap_get_values_len.3 ldap_value_free.3 ldap_value_free_len.3 ldap_count_values.3 ldap_count_values_len.3 openldap-2.4.42+dfsg/doc/man/man3/ldap_memory.3.links0000644000175000017500000000014012563404150020714 0ustar ryanryanldap_memfree.3 ldap_memvfree.3 ldap_memalloc.3 ldap_memcalloc.3 ldap_memrealloc.3 ldap_strdup.3 openldap-2.4.42+dfsg/doc/man/man3/Makefile.in0000644000175000017500000000103012563404150017245 0ustar ryanryan# man3 Makefile.in for OpenLDAP # $OpenLDAP$ ## This work is part of OpenLDAP Software . ## ## Copyright 1998-2015 The OpenLDAP Foundation. ## All rights reserved. ## ## Redistribution and use in source and binary forms, with or without ## modification, are permitted only as authorized by the OpenLDAP ## Public License. ## ## A copy of this license is available in the file LICENSE in the ## top-level directory of the distribution or, alternatively, at ## . MANSECT=3 openldap-2.4.42+dfsg/doc/man/man3/ldap_url.30000644000175000017500000000543312563404150017101 0ustar ryanryan.TH LDAP_URL 3 "RELEASEDATE" "OpenLDAP LDVERSION" .\" $OpenLDAP$ .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_is_ldap_url, ldap_url_parse, ldap_free_urldesc \- LDAP Uniform Resource Locator routines .SH LIBRARY OpenLDAP LDAP (libldap, \-lldap) .SH SYNOPSIS .nf .ft B #include .LP .ft B int ldap_is_ldap_url( const char *url ) .LP .ft B int ldap_url_parse( const char *url, LDAPURLDesc **ludpp ) .LP typedef struct ldap_url_desc { char * lud_scheme; /* URI scheme */ char * lud_host; /* LDAP host to contact */ int lud_port; /* port on host */ char * lud_dn; /* base for search */ char ** lud_attrs; /* list of attributes */ int lud_scope; /* a LDAP_SCOPE_... value */ char * lud_filter; /* LDAP search filter */ char ** lud_exts; /* LDAP extensions */ int lud_crit_exts; /* true if any extension is critical */ /* may contain additional fields for internal use */ } LDAPURLDesc; .LP .ft B void ldap_free_urldesc( LDAPURLDesc *ludp ); .SH DESCRIPTION These routines support the use of LDAP URLs (Uniform Resource Locators) as detailed in RFC 4516. LDAP URLs look like this: .nf \fBldap://\fP\fIhostport\fP\fB/\fP\fIdn\fP[\fB?\fP\fIattrs\fP[\fB?\fP\fIscope\fP[\fB?\fP\fIfilter\fP[\fB?\fP\fIexts\fP]]]] where: \fIhostport\fP is a host name with an optional ":portnumber" \fIdn\fP is the search base \fIattrs\fP is a comma separated list of attributes to request \fIscope\fP is one of these three strings: base one sub (default=base) \fIfilter\fP is filter \fIexts\fP are recognized set of LDAP and/or API extensions. Example: ldap://ldap.example.net/dc=example,dc=net?cn,sn?sub?(cn=*) .fi .LP URLs that are wrapped in angle-brackets and/or preceded by "URL:" are also tolerated. Alternative LDAP schemes such as ldaps:// and ldapi:// may be parsed using the below routines as well. .LP .B ldap_is_ldap_url() returns a non-zero value if \fIurl\fP looks like an LDAP URL (as opposed to some other kind of URL). It can be used as a quick check for an LDAP URL; the .B ldap_url_parse() routine should be used if a more thorough check is needed. .LP .B ldap_url_parse() breaks down an LDAP URL passed in \fIurl\fP into its component pieces. If successful, zero is returned, an LDAP URL description is allocated, filled in, and \fIludpp\fP is set to point to it. If an error occurs, a non-zero URL error code is returned. .LP .B ldap_free_urldesc() should be called to free an LDAP URL description that was obtained from a call to .B ldap_url_parse(). .SH SEE ALSO .nf .BR ldap (3) .BR "RFC 4516" " " .SH ACKNOWLEDGEMENTS .fi .so ../Project openldap-2.4.42+dfsg/doc/man/man3/ldap_abandon.30000644000175000017500000000314412563404150017676 0ustar ryanryan.TH LDAP_ABANDON 3 "RELEASEDATE" "OpenLDAP LDVERSION" .\" $OpenLDAP$ .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_abandon_ext \- Abandon an LDAP operation in progress .SH LIBRARY OpenLDAP LDAP (libldap, \-lldap) .SH SYNOPSIS .nf .B #include .LP .ft B int ldap_abandon_ext( .RS .ft B LDAP *\fIld\fB, Bint \fImsgid\fB, LDAPControl **\fIsctrls\fB, LDAPControl **\fIcctrls\fB ); .RE .fi .SH DESCRIPTION The .B ldap_abandon_ext() routine is used to send a LDAP Abandon request for an operation in progress. The \fImsgid\fP passed should be the message id of an outstanding LDAP operation, such as returned by .BR ldap_search_ext (3). .LP .BR ldap_abandon_ext () checks to see if the result of the operation has already come in. If it has, it deletes it from the queue of pending messages. If not, it sends an LDAP abandon request to the LDAP server. .LP The caller can expect that the result of an abandoned operation will not be returned from a future call to .BR ldap_result (3). .LP .B ldap_abandon_ext() allows server and client controls to be passed in via the .I sctrls and .I cctrls parameters, respectively. .LP .B ldap_abandon_ext() returns a code indicating success or, in the case of failure, the nature of the failure. See .BR ldap_error (3) for details. .SH DEPRECATED INTERFACES The .B ldap_abandon() routine is deprecated in favor of the .B ldap_abandon_ext() routine. .LP .so Deprecated .SH SEE ALSO .BR ldap (3), .BR ldap_error (3), .BR ldap_result (3), .BR ldap_search_ext (3) .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man3/ldap_first_entry.30000644000175000017500000000415412563404150020646 0ustar ryanryan.TH LDAP_FIRST_ENTRY 3 "RELEASEDATE" "OpenLDAP LDVERSION" .\" $OpenLDAP$ .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_first_entry, ldap_next_entry, ldap_count_entries \- LDAP result entry parsing and counting routines .SH LIBRARY OpenLDAP LDAP (libldap, \-lldap) .SH SYNOPSIS .nf .ft B #include .LP .ft B int ldap_count_entries( LDAP *ld, LDAPMessage *result ) .LP .ft B LDAPMessage *ldap_first_entry( LDAP *ld, LDAPMessage *result ) .LP .ft B LDAPMessage *ldap_next_entry( LDAP *ld, LDAPMessage *entry ) .SH DESCRIPTION .LP These routines are used to parse results received from .BR ldap_result (3) or the synchronous LDAP search operation routines .BR ldap_search_s (3) and .BR ldap_search_st (3). .LP The .B ldap_first_entry() routine is used to retrieve the first entry in a chain of search results. It takes the \fIresult\fP as returned by a call to .BR ldap_result (3) or .BR ldap_search_s (3) or .BR ldap_search_st (3) and returns a pointer to the first entry in the result. .LP This pointer should be supplied on a subsequent call to .B ldap_next_entry() to get the next entry, the result of which should be supplied to the next call to .BR ldap_next_entry() , etc. .B ldap_next_entry() will return NULL when there are no more entries. The entries returned from these calls are used in calls to the routines described in .BR ldap_get_dn (3), .BR ldap_first_attribute (3), .BR ldap_get_values (3), etc. .LP A count of the number of entries in the search result can be obtained by calling .BR ldap_count_entries() . .SH ERRORS If an error occurs in .B ldap_first_entry() or .BR ldap_next_entry() , NULL is returned and the ld_errno field in the \fIld\fP parameter is set to indicate the error. If an error occurs in .BR ldap_count_entries() , -1 is returned, and .B ld_errno is set appropriately. See .BR ldap_error (3) for a description of possible error codes. .SH SEE ALSO .BR ldap (3), .BR ldap_result (3), .BR ldap_search (3), .BR ldap_first_attribute (3), .BR ldap_get_values (3), .BR ldap_get_dn (3) .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man3/ldap_compare.3.links0000644000175000017500000000007112563404150021035 0ustar ryanryanldap_compare_s.3 ldap_compare_ext.3 ldap_compare_ext_s.3 openldap-2.4.42+dfsg/doc/man/man3/ldap_rename.30000644000175000017500000000461312563404150017545 0ustar ryanryan.TH LDAP_RENAME 3 "RELEASEDATE" "OpenLDAP LDVERSION" .\" $OpenLDAP$ .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_rename, ldap_rename_s \- Renames the specified entry. .SH LIBRARY OpenLDAP LDAP (libldap, \-lldap) .SH SYNOPSIS .nf .ft B #include .LP .ft B int ldap_rename( ld, dn, newrdn, newparent, deleteoldrdn, sctrls[], cctrls[], msgidp ); .ft LDAP *ld; const char *dn, *newrdn, *newparent; int deleteoldrdn; LDAPControl *sctrls[], *cctrls[]; int *msgidp); .LP .ft B int ldap_rename_s( ld, dn, newrdn, newparent, deleteoldrdn, sctrls[], cctrls[] ); .ft LDAP *ld; const char *dn, *newrdn, *newparent; int deleteoldrdn; LDAPControl *sctrls[], *cctrls[]; .SH DESCRIPTION These routines are used to perform a LDAP rename operation. The function changes the leaf component of an entry's distinguished name and optionally moves the entry to a new parent container. The .B ldap_rename_s performs a rename operation synchronously. The method takes \fIdn\fP, which points to the distinguished name of the entry whose attribute is being compared, \fInewparent\fP,the distinguished name of the entry's new parent. If this parameter is NULL, only the RDN is changed. The root DN is specified by passing a zero length string, "". \fIdeleteoldrdn\fP specifies whether the old RDN should be retained or deleted. Zero indicates that the old RDN should be retained. If you choose this option, the attribute will contain both names (the old and the new). Non-zero indicates that the old RDN should be deleted. \fIserverctrls\fP points to an array of LDAPControl structures that list the client controls to use with this extended operation. Use NULL to specify no client controls. \fIclientctrls\fP points to an array of LDAPControl structures that list the client controls to use with the search. .LP .B ldap_rename works just like .B ldap_rename_s, but the operation is asynchronous. It returns the message id of the request it initiated. The result of this operation can be obtained by calling .BR ldap_result(3). .SH ERRORS .B ldap_rename() returns \-1 in case of error initiating the request, and will set the \fIld_errno\fP field in the \fIld\fP parameter to indicate the error. .BR ldap_rename_s() returns the LDAP error code resulting from the rename operation. .SH SEE ALSO .BR ldap (3), .BR ldap_modify (3) .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man3/ldap_parse_reference.30000644000175000017500000000406112563404150021423 0ustar ryanryan.TH LDAP_PARSE_REFERENCE 3 "RELEASEDATE" "OpenLDAP LDVERSION" .\" $OpenLDAP$ .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_parse_reference \- Extract referrals and controls from a reference message .SH LIBRARY OpenLDAP LDAP (libldap, \-lldap) .SH SYNOPSIS .nf .ft B #include .LP .ft B int ldap_parse_reference( LDAP *ld, LDAPMessage *reference, char ***referralsp, LDAPControl ***serverctrlsp, int freeit ) .SH DESCRIPTION .LP The .B ldap_parse_reference() routine is used to extract referrals and controls from a reference message. The \fIreference\fP parameter is a reference message as returned by a call to .BR ldap_first_reference (3) , .BR ldap_next_reference (3) , .BR ldap_first_message (3) , .BR ldap_next_message (3) , or .BR ldap_result (3) . .LP The \fIreferralsp\fP parameter will be filled in with an allocated array of character strings. The strings are copies of the referrals contained in the parsed message. The array should be freed by calling .BR ldap_value_free (3) . If \fIreferralsp\fP is NULL, no referrals are returned. If no referrals were returned, \fI*referralsp\fP is set to NULL. .LP The \fIserverctrlsp\fP parameter will be filled in with an allocated array of controls copied from the parsed message. The array should be freed by calling .BR ldap_controls_free (3). If \fIserverctrlsp\fP is NULL, no controls are returned. If no controls were returned, \fI*serverctrlsp\fP is set to NULL. .LP The \fIfreeit\fP parameter determines whether the parsed message is freed or not after the extraction. Any non-zero value will make it free the message. The .BR ldap_msgfree (3) routine can also be used to free the message later. .SH ERRORS Upon success LDAP_SUCCESS is returned. Otherwise the values of the \fIreferralsp\fP and \fIserverctrlsp\fP parameters are undefined. .SH SEE ALSO .BR ldap (3), .BR ldap_first_reference (3), .BR ldap_first_message (3), .BR ldap_result (3), .BR ldap_get_values (3), .BR ldap_controls_free (3) .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man3/ldap_first_reference.3.links0000644000175000017500000000005612563404150022557 0ustar ryanryanldap_next_reference.3 ldap_count_references.3 openldap-2.4.42+dfsg/doc/man/man3/ldap_dup.30000644000175000017500000000645712563404150017076 0ustar ryanryan.TH LDAP_OPEN 3 "RELEASEDATE" "OpenLDAP LDVERSION" .\" $OpenLDAP$ .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_dup, ldap_destroy, \- Duplicate and destroy LDAP session handles .SH LIBRARY OpenLDAP LDAP (libldap, \-lldap) .SH SYNOPSIS .nf .ft B #include .LP .ft B LDAP *ldap_dup( .RS .ft B LDAP *\fIold\fB ); .RE .LP .ft B int ldap_destroy( .RS .ft B LDAP *\fIold\fB ); .RE .SH DESCRIPTION .LP .B ldap_dup() duplicates an existing LDAP .RB ( "LDAP *" ) session handle. The new session handle may be used concurrently with the original session handle. In a threaded environment, different threads may execute concurrent requests on the same connection/session without fear of contamination. Each session handle manages its own private error results. .LP .B ldap_destroy() destroys an existing session handle. .LP The .B ldap_dup() and .B ldap_destroy() functions are used in conjunction with a "thread safe" version of .B libldap .RB ( libldap_r ) to enable operation thread safe API calls, so that a single session may be simultaneously used across multiple threads with consistent error handling. .LP When a session is created through the use of one of the session creation functions including .BR ldap_open (3), .BR ldap_init (3), .BR ldap_initialize (3) or .BR ldap_init_fd (3) an .B "LDAP *" session handle is returned to the application. The session handle may be shared amongst threads, however the error codes are unique to a session handle. Multiple threads performing different operations using the same session handle will result in inconsistent error codes and return values. .LP To prevent this confusion, .B ldap_dup() is used duplicate an existing session handle so that multiple threads can share the session, and maintain consistent error information and results. .LP The message queues for a session are shared between sibling session handles. Results of operations on a sibling session handles are accessible to all the sibling session handles. Applications desiring results associated with a specific operation should provide the appropriate msgid to .BR ldap_result() . Applications should avoid calling .B ldap_result() with .B LDAP_RES_ANY as that may "steal" and return results in the calling thread that another operation in a different thread, using a different session handle, may require to complete. .LP When .B ldap_unbind() is called on a session handle with siblings, all the siblings become invalid. .LP Siblings must be destroyed using .BR ldap_destroy() . Session handle resources associated with the original .RB ( "LDAP *" ) will be freed when the last session handle is destroyed or when .B ldap_unbind() is called, if no other session handles currently exist. .SH ERRORS If an error occurs, .B ldap_dup() will return NULL and .I errno should be set appropriately. .B ldap_destroy() will directly return the LDAP code associated to the error (or .I LDAP_SUCCESS in case of success); .I errno should be set as well whenever appropriate. .SH SEE ALSO .BR ldap_open (3), .BR ldap_init (3), .BR ldap_initialize (3), .BR ldap_init_fd (3), .BR errno (3) .SH ACKNOWLEDGEMENTS This work is based on the previously proposed .B LDAP C API Concurrency Extensions draft .BR ( draft-zeilenga-ldap-c-api-concurrency-00.txt ) effort. .so ../Project openldap-2.4.42+dfsg/doc/man/man3/ldap_get_option.30000644000175000017500000004547512563404150020460 0ustar ryanryan.TH LDAP_GET_OPTION 3 "RELEASEDATE" "OpenLDAP LDVERSION" .\" $OpenLDAP$ .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_get_option, ldap_set_option \- LDAP option handling routines .SH LIBRARY OpenLDAP LDAP (libldap, \-lldap) .SH SYNOPSIS .nf .B #include .LP .BI "int ldap_get_option(LDAP *" ld ", int " option ", void *" outvalue ");" .LP .BI "int ldap_set_option(LDAP *" ld ", int " option ", const void *" invalue ");" .SH DESCRIPTION .LP These routines provide access to options stored either in a LDAP handle or as global options, where applicable. They make use of a neutral interface, where the type of the value either retrieved by .BR ldap_get_option (3) or set by .BR ldap_set_option (3) is cast to .BR "void *" . The actual type is determined based on the value of the .B option argument. Global options are set/retrieved by passing a NULL LDAP handle. LDAP handles inherit their default settings from the global options in effect at the time the handle is created. .TP .B LDAP_OPT_API_FEATURE_INFO Fills-in a .BR "LDAPAPIFeatureInfo" ; .BR outvalue must be a .BR "LDAPAPIFeatureInfo *" , pointing to an already allocated struct. The .B ldapaif_info_version field of the struct must be initialized to .B LDAP_FEATURE_INFO_VERSION before making the call. The .B ldapaif_name field must be set to the name of a feature to query. This is a read-only option. .TP .B LDAP_OPT_API_INFO Fills-in a .BR "LDAPAPIInfo" ; .BR outvalue must be a .BR "LDAPAPIInfo *" , pointing to an already allocated struct. The .B ldapai_info_version field of the struct must be initialized to .B LDAP_API_INFO_VERSION before making the call. If the version passed in does not match the current library version, the expected version number will be stored in the struct and the call will fail. The caller is responsible for freeing the elements of the .B ldapai_extensions array and the array itself using .BR ldap_memfree (3). The caller must also free the .BR ldapi_vendor_name . This is a read-only option. .TP .B LDAP_OPT_CLIENT_CONTROLS Sets/gets the client-side controls to be used for all operations. This is now deprecated as modern LDAP C API provides replacements for all main operations which accepts client-side controls as explicit arguments; see for example .BR ldap_search_ext (3), .BR ldap_add_ext (3), .BR ldap_modify_ext (3) and so on. .BR outvalue must be .BR "LDAPControl ***" , and the caller is responsible of freeing the returned controls, if any, by calling .BR ldap_controls_free (3), while .BR invalue must be .BR "LDAPControl *const *" ; the library duplicates the controls passed via .BR invalue . .TP .B LDAP_OPT_CONNECT_ASYNC Sets/gets the status of the asynchronous connect flag. .BR invalue should either be .BR LDAP_OPT_OFF or .BR LDAP_OPT_ON ; .BR outvalue must be .BR "int *" . When set, the library will call .BR connect (2) and return, without waiting for response. This leaves the handle in a connecting state. Subsequent calls to library routines will poll for completion of the connect before performing further operations. As a consequence, library calls that need to establish a connection with a DSA do not block even for the network timeout (option .BR LDAP_OPT_NETWORK_TIMEOUT ). This option is OpenLDAP specific. .TP .B LDAP_OPT_CONNECT_CB This option allows to set a connect callback. .B invalue must be a .BR "const struct ldap_conncb *" . Callbacks are executed in last in-first served order. Handle-specific callbacks are executed first, followed by global ones. Right before freeing the callback structure, the .B lc_del callback handler is passed a .B NULL .BR Sockbuf . Calling .BR ldap_get_option (3) for this option removes the callback whose pointer matches .BR outvalue . This option is OpenLDAP specific. .TP .B LDAP_OPT_DEBUG_LEVEL Sets/gets the debug level of the client library. .BR invalue must be a .BR "const int *" ; .BR outvalue must be a .BR "int *" . Valid debug levels are .BR LDAP_DEBUG_ANY , .BR LDAP_DEBUG_ARGS , .BR LDAP_DEBUG_BER , .BR LDAP_DEBUG_CONNS , .BR LDAP_DEBUG_NONE , .BR LDAP_DEBUG_PACKETS , .BR LDAP_DEBUG_PARSE , and .BR LDAP_DEBUG_TRACE . This option is OpenLDAP specific. .TP .B LDAP_OPT_DEFBASE Sets/gets a string containing the DN to be used as default base for search operations. .BR outvalue must be a .BR "char **" , and the caller is responsible of freeing the returned string by calling .BR ldap_memfree (3), while .BR invalue must be a .BR "const char *" ; the library duplicates the corresponding string. This option is OpenLDAP specific. .TP .B LDAP_OPT_DEREF Sets/gets the value that defines when alias dereferencing must occur. .BR invalue must be .BR "const int *" ; .BR outvalue must be .BR "int *" . They cannot be NULL. The value of .BR *invalue should be one of .BR LDAP_DEREF_NEVER (the default), .BR LDAP_DEREF_SEARCHING , .BR LDAP_DEREF_FINDING , or .BR LDAP_DEREF_ALWAYS . Note that this has ever been the only means to determine alias dereferencing within search operations. .TP .B LDAP_OPT_DESC Returns the file descriptor associated to the socket buffer of the LDAP handle passed in as .BR ld ; .BR outvalue must be a .BR "int *" . This is a read-only, handle-specific option. .TP .B LDAP_OPT_DIAGNOSTIC_MESSAGE Sets/gets a string containing the error string associated to the LDAP handle. This option was formerly known as .BR LDAP_OPT_ERROR_STRING . .BR outvalue must be a .BR "char **" , and the caller is responsible of freeing the returned string by calling .BR ldap_memfree (3), while .BR invalue must be a .BR "char *" ; the library duplicates the corresponding string. .TP .B LDAP_OPT_HOST_NAME Sets/gets a space-separated list of hosts to be contacted by the library when trying to establish a connection. This is now deprecated in favor of .BR LDAP_OPT_URI . .BR outvalue must be a .BR "char **" , and the caller is responsible of freeing the resulting string by calling .BR ldap_memfree (3), while .BR invalue must be a .BR "const char *" ; the library duplicates the corresponding string. .TP .B LDAP_OPT_MATCHED_DN Sets/gets a string containing the matched DN associated to the LDAP handle. .BR outvalue must be a .BR "char **" , and the caller is responsible of freeing the returned string by calling .BR ldap_memfree (3), while .BR invalue must be a .BR "const char *" ; the library duplicates the corresponding string. .TP .B LDAP_OPT_NETWORK_TIMEOUT Sets/gets the network timeout value after which .BR poll (2)/ select (2) following a .BR connect (2) returns in case of no activity. .B outvalue must be a .BR "struct timeval **" (the caller has to free .BR *outvalue ) , and .B invalue must be a .BR "const struct timeval *" . They cannot be NULL. Using a struct with seconds set to \-1 results in an infinite timeout, which is the default. This option is OpenLDAP specific. .TP .B LDAP_OPT_PROTOCOL_VERSION Sets/gets the protocol version. .BR outvalue and .BR invalue must be .BR "int *" . .TP .B LDAP_OPT_REFERRAL_URLS Sets/gets an array containing the referral URIs associated to the LDAP handle. .BR outvalue must be a .BR "char ***" , and the caller is responsible of freeing the returned string by calling .BR ldap_memvfree (3), while .BR invalue must be a NULL-terminated .BR "char *const *" ; the library duplicates the corresponding string. This option is OpenLDAP specific. .TP .B LDAP_OPT_REFERRALS Determines whether the library should implicitly chase referrals or not. .BR invalue must be .BR "const int *" ; its value should either be .BR LDAP_OPT_OFF or .BR LDAP_OPT_ON . .BR outvalue must be .BR "int *" . .\".TP .\".B LDAP_OPT_REFHOPLIMIT .\"This option is OpenLDAP specific. .\"It is not currently implemented. .TP .B LDAP_OPT_RESTART Determines whether the library should implicitly restart connections (FIXME). .BR invalue must be .BR "const int *" ; its value should either be .BR LDAP_OPT_OFF or .BR LDAP_OPT_ON . .BR outvalue must be .BR "int *" . .TP .B LDAP_OPT_RESULT_CODE Sets/gets the LDAP result code associated to the handle. This option was formerly known as .BR LDAP_OPT_ERROR_NUMBER . .BR invalue must be a .BR "const int *" . .BR outvalue must be a .BR "int *" . .TP .B LDAP_OPT_SERVER_CONTROLS Sets/gets the server-side controls to be used for all operations. This is now deprecated as modern LDAP C API provides replacements for all main operations which accepts server-side controls as explicit arguments; see for example .BR ldap_search_ext (3), .BR ldap_add_ext (3), .BR ldap_modify_ext (3) and so on. .BR outvalue must be .BR "LDAPControl ***" , and the caller is responsible of freeing the returned controls, if any, by calling .BR ldap_controls_free (3), while .BR invalue must be .BR "LDAPControl *const *" ; the library duplicates the controls passed via .BR invalue . .TP .B LDAP_OPT_SESSION_REFCNT Returns the reference count associated with the LDAP handle passed in as .BR ld ; .BR outvalue must be a .BR "int *" . This is a read-only, handle-specific option. This option is OpenLDAP specific. .TP .B LDAP_OPT_SIZELIMIT Sets/gets the value that defines the maximum number of entries to be returned by a search operation. .BR invalue must be .BR "const int *" , while .BR outvalue must be .BR "int *" ; They cannot be NULL. .TP .B LDAP_OPT_SOCKBUF Returns a pointer to the socket buffer of the LDAP handle passed in as .BR ld ; .BR outvalue must be a .BR "Sockbuf **" . This is a read-only, handle-specific option. This option is OpenLDAP specific. .TP .B LDAP_OPT_TIMELIMIT Sets/gets the value that defines the time limit after which a search operation should be terminated by the server. .BR invalue must be .BR "const int *" , while .BR outvalue must be .BR "int *" , and they cannot be NULL. .TP .B LDAP_OPT_TIMEOUT Sets/gets a timeout value for the synchronous API calls. .B outvalue must be a .BR "struct timeval **" (the caller has to free .BR *outvalue ) , and .B invalue must be a .BR "struct timeval *" , and they cannot be NULL. Using a struct with seconds set to \-1 results in an infinite timeout, which is the default. This option is OpenLDAP specific. .TP .B LDAP_OPT_URI Sets/gets a comma- or space-separated list of URIs to be contacted by the library when trying to establish a connection. .BR outvalue must be a .BR "char **" , and the caller is responsible of freeing the resulting string by calling .BR ldap_memfree (3), while .BR invalue must be a .BR "const char *" ; the library parses the string into a list of .BR LDAPURLDesc structures, so the invocation of .BR ldap_set_option (3) may fail if URL parsing fails. URIs may only contain the .BR schema , the .BR host , and the .BR port fields. This option is OpenLDAP specific. .SH SASL OPTIONS The SASL options are OpenLDAP specific. .TP .B LDAP_OPT_X_SASL_AUTHCID Gets the SASL authentication identity; .BR outvalue must be a .BR "char **" , its content needs to be freed by the caller using .BR ldap_memfree (3). .TP .B LDAP_OPT_X_SASL_AUTHZID Gets the SASL authorization identity; .BR outvalue must be a .BR "char **" , its content needs to be freed by the caller using .BR ldap_memfree (3). .TP .B LDAP_OPT_X_SASL_MAXBUFSIZE Gets/sets SASL maximum buffer size; .BR invalue must be .BR "const ber_len_t *" , while .BR outvalue must be .BR "ber_len_t *" . See also .BR LDAP_OPT_X_SASL_SECPROPS . .TP .B LDAP_OPT_X_SASL_MECH Gets the SASL mechanism; .BR outvalue must be a .BR "char **" , its content needs to be freed by the caller using .BR ldap_memfree (3). .TP .B LDAP_OPT_X_SASL_MECHLIST Gets the list of the available mechanisms, in form of a NULL-terminated array of strings; .BR outvalue must be .BR "char ***" . The caller must not free or otherwise muck with it. .TP .B LDAP_OPT_X_SASL_NOCANON Sets/gets the NOCANON flag. When unset, the hostname is canonicalized. .BR invalue must be .BR "const int *" ; its value should either be .BR LDAP_OPT_OFF or .BR LDAP_OPT_ON . .BR outvalue must be .BR "int *" . .TP .B LDAP_OPT_X_SASL_REALM Gets the SASL realm; .BR outvalue must be a .BR "char **" , its content needs to be freed by the caller using .BR ldap_memfree (3). .TP .B LDAP_OPT_X_SASL_SECPROPS Sets the SASL secprops; .BR invalue must be a .BR "char *" , containing a comma-separated list of properties. Legal values are: .BR none , .BR nodict , .BR noplain , .BR noactive , .BR passcred , .BR forwardsec , .BR noanonymous , .BR minssf= , .BR maxssf= , .BR maxbufsize= . .TP .B LDAP_OPT_X_SASL_SSF Gets the SASL SSF; .BR outvalue must be a .BR "ber_len_t *" . .TP .B LDAP_OPT_X_SASL_SSF_EXTERNAL Sets the SASL SSF value related to an authentication performed using an EXTERNAL mechanism; .BR invalue must be a .BR "const ber_len_t *" . .TP .B LDAP_OPT_X_SASL_SSF_MAX Gets/sets SASL maximum SSF; .BR invalue must be .BR "const ber_len_t *" , while .BR outvalue must be .BR "ber_len_t *" . See also .BR LDAP_OPT_X_SASL_SECPROPS . .TP .B LDAP_OPT_X_SASL_SSF_MIN Gets/sets SASL minimum SSF; .BR invalue must be .BR "const ber_len_t *" , while .BR outvalue must be .BR "ber_len_t *" . See also .BR LDAP_OPT_X_SASL_SECPROPS . .TP .B LDAP_OPT_X_SASL_USERNAME Gets the SASL username; .BR outvalue must be a .BR "char **" . Its content needs to be freed by the caller using .BR ldap_memfree (3). .SH TCP OPTIONS The TCP options are OpenLDAP specific. Mainly intended for use with Linux, they may not be portable. .TP .B LDAP_OPT_X_KEEPALIVE_IDLE Sets/gets the number of seconds a connection needs to remain idle before TCP starts sending keepalive probes. .BR invalue must be .BR "const int *" ; .BR outvalue must be .BR "int *" . .TP .B LDAP_OPT_X_KEEPALIVE_PROBES Sets/gets the maximum number of keepalive probes TCP should send before dropping the connection. .BR invalue must be .BR "const int *" ; .BR outvalue must be .BR "int *" . .TP .B LDAP_OPT_X_KEEPALIVE_INTERVAL Sets/gets the interval in seconds between individual keepalive probes. .BR invalue must be .BR "const int *" ; .BR outvalue must be .BR "int *" . .SH TLS OPTIONS The TLS options are OpenLDAP specific. .\".TP .\".B LDAP_OPT_X_TLS .\"Sets/gets the TLS mode. .TP .B LDAP_OPT_X_TLS_CACERTDIR Sets/gets the path of the directory containing CA certificates. .BR invalue must be .BR "const char *" ; .BR outvalue must be .BR "char **" , and its contents need to be freed by the caller using .BR ldap_memfree (3). .TP .B LDAP_OPT_X_TLS_CACERTFILE Sets/gets the full-path of the CA certificate file. .BR invalue must be .BR "const char *" ; .BR outvalue must be .BR "char **" , and its contents need to be freed by the caller using .BR ldap_memfree (3). .TP .B LDAP_OPT_X_TLS_CERTFILE Sets/gets the full-path of the certificate file. .BR invalue must be .BR "const char *" ; .BR outvalue must be .BR "char **" , and its contents need to be freed by the caller using .BR ldap_memfree (3). .TP .B LDAP_OPT_X_TLS_CIPHER_SUITE Sets/gets the allowed cipher suite. .BR invalue must be .BR "const char *" ; .BR outvalue must be .BR "char **" , and its contents need to be freed by the caller using .BR ldap_memfree (3). .TP .B LDAP_OPT_X_TLS_CONNECT_ARG Sets/gets the connection callback argument. .BR invalue must be .BR "const void *" ; .BR outvalue must be .BR "void **" . .TP .B LDAP_OPT_X_TLS_CONNECT_CB Sets/gets the connection callback handle. .BR invalue must be .BR "const LDAP_TLS_CONNECT_CB *" ; .BR outvalue must be .BR "LDAP_TLS_CONNECT_CB **" . .TP .B LDAP_OPT_X_TLS_CRLCHECK Sets/gets the CRL evaluation strategy, one of .BR LDAP_OPT_X_TLS_CRL_NONE , .BR LDAP_OPT_X_TLS_CRL_PEER , or .BR LDAP_OPT_X_TLS_CRL_ALL . .BR invalue must be .BR "const int *" ; .BR outvalue must be .BR "int *" . Requires OpenSSL. .TP .B LDAP_OPT_X_TLS_CRLFILE Sets/gets the full-path of the CRL file. .BR invalue must be .BR "const char *" ; .BR outvalue must be .BR "char **" , and its contents need to be freed by the caller using .BR ldap_memfree (3). This option is only valid for GnuTLS. .TP .B LDAP_OPT_X_TLS_CTX Sets/gets the TLS library context. New TLS sessions will inherit their default settings from this library context. .BR invalue must be .BR "const void *" ; .BR outvalue must be .BR "void **" . When using the OpenSSL library this is an SSL_CTX*. When using other crypto libraries this is a pointer to an OpenLDAP private structure. Applications generally should not use this option or attempt to manipulate this structure. .TP .B LDAP_OPT_X_TLS_DHFILE Gets/sets the full-path of the file containing the parameters for Diffie-Hellman ephemeral key exchange. .BR invalue must be .BR "const char *" ; .BR outvalue must be .BR "char **" , and its contents need to be freed by the caller using .BR ldap_memfree (3). Ignored by GnuTLS and Mozilla NSS. .TP .B LDAP_OPT_X_TLS_KEYFILE Sets/gets the full-path of the certificate key file. .BR invalue must be .BR "const char *" ; .BR outvalue must be .BR "char **" , and its contents need to be freed by the caller using .BR ldap_memfree (3). .TP .B LDAP_OPT_X_TLS_NEWCTX Instructs the library to create a new TLS library context. .BR invalue must be .BR "const int *" . A non-zero value pointed to by .BR invalue tells the library to create a context for a server. .TP .B LDAP_OPT_X_TLS_PROTOCOL_MIN Sets/gets the minimum protocol version. .BR invalue must be .BR "const int *" ; .BR outvalue must be .BR "int *" . .TP .B LDAP_OPT_X_TLS_RANDOM_FILE Sets/gets the random file when .B /dev/random and .B /dev/urandom are not available. .BR invalue must be .BR "const char *" ; .BR outvalue must be .BR "char **" , and its contents need to be freed by the caller using .BR ldap_memfree (3). Ignored by GnuTLS older than version 2.2. Ignored by Mozilla NSS. .TP .B LDAP_OPT_X_TLS_REQUIRE_CERT Sets/gets the peer certificate checking strategy, one of .BR LDAP_OPT_X_TLS_NEVER , .BR LDAP_OPT_X_TLS_HARD , .BR LDAP_OPT_X_TLS_DEMAND , .BR LDAP_OPT_X_TLS_ALLOW , .BR LDAP_OPT_X_TLS_TRY . .TP .B LDAP_OPT_X_TLS_SSL_CTX Gets the TLS session context associated with this handle. .BR outvalue must be .BR "void **" . When using the OpenSSL library this is an SSL*. When using other crypto libraries this is a pointer to an OpenLDAP private structure. Applications generally should not use this option. .SH ERRORS On success, the functions return .BR LDAP_OPT_SUCCESS , while they may return .B LDAP_OPT_ERROR to indicate a generic option handling error. Occasionally, more specific errors can be returned, like .B LDAP_NO_MEMORY to indicate a failure in memory allocation. .SH NOTES The LDAP libraries with the .B LDAP_OPT_REFERRALS option set to .B LDAP_OPT_ON (default value) automatically follow referrals using an anonymous bind. Application developers are encouraged to either implement consistent referral chasing features, or explicitly disable referral chasing by setting that option to .BR LDAP_OPT_OFF . .P The protocol version used by the library defaults to LDAPv2 (now historic), which corresponds to the .B LDAP_VERSION2 macro. Application developers are encouraged to explicitly set .B LDAP_OPT_PROTOCOL_VERSION to LDAPv3, using the .B LDAP_VERSION3 macro, or to allow users to select the protocol version. .SH SEE ALSO .BR ldap (3), .BR ldap_error (3), .B RFC 4422 (http://www.rfc-editor.org), .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man3/ldap_parse_vlv_control.30000644000175000017500000000405412563404150022036 0ustar ryanryan.TH LDAP_PARSE_VLV_CONTROL 3 "RELEASEDATE" "OpenLDAP LDVERSION" .\" $OpenLDAP$ .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_parse_vlv_control \- Decode the information returned from a search operation that used a VLV (virtual list view) control .SH LIBRARY OpenLDAP LDAP (libldap, \-lldap) .SH SYNOPSIS .nf .ft B #include .LP .ft B int ldap_parse_vlv_control( ld, ctrlp, target_posp, list_countp, contextp, errcodep ) .ft LDAP *ld; LDAPControl **ctrlp; unsigned long *target_posp, *list_countp; struct berval **contextp; int *errcodep; .SH DESCRIPTION The .B ldap_parse_vlv_control is used to decode the information returned from a search operation that used a VLV (virtual list view)control. It takes a null terminated array of LDAPControl structures, usually obtained by a call to the .BR ldap_parse_result function, a \fItarget_pos\fP which points to the list index of the target entry. If this parameter is NULL, the target position is not returned. The index returned is an approximation of the position of the target entry. It is not guaranteed to be exact. The parameter \fIlist_countp\fP points to the server's estimate of the size of the list. If this parameter is NULL, the size is not returned. \fIcontextp\fP is a pointer to the address of a berval structure that contains a server-generated context identifier if server returns one. If server does not return a context identifier, the server returns a NULL in this parameter. If this parameter is set to NULL, the context identifier is not returned. You should use this returned context in the next call to create a VLV control. When the berval structure is no longer needed, you should free the memory by calling the \fIber_bvfree function.e\fP \fIerrcodep\fP is an output parameter, which points to the result code returned by the server. If this parameter is NULL, the result code is not returned. .LP See ldap.h for a list of possible return codes. .SH SEE ALSO .BR ldap_search (3) .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man3/ldap_sort.3.links0000644000175000017500000000007612563404150020403 0ustar ryanryanldap_sort_entries.3 ldap_sort_values.3 ldap_sort_strcasecmp.3 openldap-2.4.42+dfsg/doc/man/man3/lber-types.3.links0000644000175000017500000000023212563404150020474 0ustar ryanryanber_bvarray_add.3 ber_bvarray_free.3 ber_bvdup.3 ber_bvecadd.3 ber_bvecfree.3 ber_bvfree.3 ber_bvstr.3 ber_bvstrdup.3 ber_dupbv.3 ber_free.3 ber_str2bv.3 openldap-2.4.42+dfsg/doc/man/man3/ldap_add.30000644000175000017500000000372112563404150017025 0ustar ryanryan.TH LDAP_ADD 3 "RELEASEDATE" "OpenLDAP LDVERSION" .\" $OpenLDAP$ .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_add_ext, ldap_add_ext_s \- Perform an LDAP add operation .SH LIBRARY OpenLDAP LDAP (libldap, \-lldap) .SH SYNOPSIS .ft B #include .LP .ft B .nf int ldap_add_ext( .RS .ft B LDAP *\fIld, const char *\fIdn\fB, LDAPMod **\fIattrs\fB, LDAPControl **\fIsctrls\fB, LDAPControl **\fIcctrls\fB, int *\fImsgidp\fB ); .RE .LP .ft B .nf int ldap_add_ext_s( .RS LDAP *\fIld\fB, const char *\fIdn\fB, LDAPMod **\fIattrs\fB, LDAPControl *\fIsctrls\fB, LDAPControl *\fIcctrls\fB ); .RE .fi .SH DESCRIPTION The .B ldap_add_ext_s() routine is used to perform an LDAP add operation. It takes \fIdn\fP, the DN of the entry to add, and \fIattrs\fP, a null-terminated array of the entry's attributes. The LDAPMod structure is used to represent attributes, with the \fImod_type\fP and \fImod_values\fP fields being used as described under .BR ldap_modify_ext (3), and the \fIldap_op\fP field being used only if you need to specify the LDAP_MOD_BVALUES option. Otherwise, it should be set to zero. .LP Note that all entries except that specified by the last component in the given DN must already exist. .B ldap_add_ext_s() returns an code indicating success or, in the case of failure, indicating the nature of failure of the operation. See .BR ldap_error (3) for more details. .LP The .B ldap_add_ext() routine works just like .BR ldap_add_ext_s() , but it is asynchronous. It returns the message id of the request it initiated. The result of this operation can be obtained by calling .BR ldap_result (3). .SH DEPRECATED INTERFACES The .BR ldap_add () and .BR ldap_add_s () routines are deprecated in favor of the .BR ldap_add_ext () and .BR ldap_add_ext_s () routines, respectively. .LP .so Deprecated .SH SEE ALSO .BR ldap (3), .BR ldap_error (3), .BR ldap_modify (3) .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man3/ldap_dup.3.links0000644000175000017500000000001712563404150020177 0ustar ryanryanldap_destroy.3 openldap-2.4.42+dfsg/doc/man/man3/ldap_get_dn.30000644000175000017500000001456212563404150017542 0ustar ryanryan.TH LDAP_GET_DN 3 "RELEASEDATE" "OpenLDAP LDVERSION" .\" $OpenLDAP$ .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_get_dn, ldap_explode_dn, ldap_explode_rdn, ldap_dn2ufn \- LDAP DN handling routines .SH LIBRARY OpenLDAP LDAP (libldap, \-lldap) .SH SYNOPSIS .nf .ft B #include .LP .ft B char *ldap_get_dn( LDAP *ld, LDAPMessage *entry ) .LP .ft B int ldap_str2dn( const char *str, LDAPDN *dn, unsigned flags ) .LP .ft B void ldap_dnfree( LDAPDN dn ) .LP .ft B int ldap_dn2str( LDAPDN dn, char **str, unsigned flags ) .LP .ft B char **ldap_explode_dn( const char *dn, int notypes ) .LP .ft B char **ldap_explode_rdn( const char *rdn, int notypes ) .LP .ft B char *ldap_dn2ufn( const char * dn ) .LP .ft B char *ldap_dn2dcedn( const char * dn ) .LP .ft B char *ldap_dcedn2dn( const char * dn ) .LP .ft B char *ldap_dn2ad_canonical( const char * dn ) .SH DESCRIPTION These routines allow LDAP entry names (Distinguished Names, or DNs) to be obtained, parsed, converted to a user-friendly form, and tested. A DN has the form described in RFC 4414 "Lightweight Directory Access Protocol (LDAP): String Representation of Distinguished Names". .LP The .B ldap_get_dn() routine takes an \fIentry\fP as returned by .BR ldap_first_entry (3) or .BR ldap_next_entry (3) and returns a copy of the entry's DN. Space for the DN will be obtained dynamically and should be freed by the caller using .BR ldap_memfree (3). .LP .B ldap_str2dn() parses a string representation of a distinguished name contained in .B str into its components, which are stored in .B dn as .B ldap_ava structures, arranged in .B LDAPAVA, .B LDAPRDN, and .B LDAPDN terms. Space for .B dn will be obtained dynamically and should be freed by the caller using .BR ldap_dnfree (3). The .B LDAPDN is defined as: .nf .ft B typedef struct ldap_ava { struct berval la_attr; struct berval la_value; unsigned la_flags; } LDAPAVA; typedef LDAPAVA** LDAPRDN; typedef LDAPRDN* LDAPDN; .ft .fi The attribute types and the attribute values are not normalized. The .B la_flags can be either .B LDAP_AVA_STRING or .B LDAP_AVA_BINARY, the latter meaning that the value is BER/DER encoded and thus must be represented as, quoting from RFC 4514, " ... an octothorpe character ('#' ASCII 35) followed by the hexadecimal representation of each of the bytes of the BER encoding of the X.500 AttributeValue." The .B flags parameter to .B ldap_str2dn() can be .LP .nf LDAP_DN_FORMAT_LDAPV3 LDAP_DN_FORMAT_LDAPV2 LDAP_DN_FORMAT_DCE .fi which defines what DN syntax is expected (according to RFC 4514, RFC 1779 and DCE, respectively). The format can be \fIOR\fPed to the flags .LP .nf LDAP_DN_P_NO_SPACES LDAP_DN_P_NO_SPACE_AFTER_RDN ... LDAP_DN_PEDANTIC .fi The latter is a shortcut for all the previous limitations. .LP .B LDAP_DN_P_NO_SPACES does not allow extra spaces in the dn; the default is to silently eliminate spaces around AVA separators ('='), RDN component separators ('+' for LDAPv3/LDAPv2 or ',' for DCE) and RDN separators (',' LDAPv3/LDAPv2 or '/' for DCE). .LP .B LDAP_DN_P_NO_SPACE_AFTER_RDN does not allow a single space after RDN separators. .LP .B ldap_dn2str() performs the inverse operation, yielding in .B str a string representation of .B dn. It allows the same values for .B flags as .B ldap_str2dn(), plus .LP .nf LDAP_DN_FORMAT_UFN LDAP_DN_FORMAT_AD_CANONICAL .fi for user-friendly naming (RFC 1781) and AD canonical. .LP The following routines are viewed as deprecated in favor of .B ldap_str2dn() and .BR ldap_dn2str(). They are provided to support legacy applications. .LP The .B ldap_explode_dn() routine takes a DN as returned by .B ldap_get_dn() and breaks it up into its component parts. Each part is known as a Relative Distinguished Name, or RDN. .B ldap_explode_dn() returns a NULL-terminated array, each component of which contains an RDN from the DN. The \fInotypes\fP parameter is used to request that only the RDN values be returned, not their types. For example, the DN "cn=Bob, c=US" would return as either { "cn=Bob", "c=US", NULL } or { "Bob", "US", NULL }, depending on whether notypes was 0 or 1, respectively. Assertion values in RDN strings may included escaped characters. The result can be freed by calling .BR ldap_value_free (3). .LP Similarly, the .B ldap_explode_rdn() routine takes an RDN as returned by .B ldap_explode_dn(dn,0) and breaks it up into its "type=value" component parts (or just "value", if the \fInotypes\fP parameter is set). Note the value is not unescaped. The result can be freed by calling .BR ldap_value_free (3). .LP .B ldap_dn2ufn() is used to turn a DN as returned by .BR ldap_get_dn (3) into a more user-friendly form, stripping off all type names. See "Using the Directory to Achieve User Friendly Naming" (RFC 1781) for more details on the UFN format. Due to the ambiguous nature of the format, it is generally only used for display purposes. The space for the UFN returned is obtained dynamically and the user is responsible for freeing it via a call to .BR ldap_memfree (3). .LP .B ldap_dn2dcedn() is used to turn a DN as returned by .BR ldap_get_dn (3) into a DCE-style DN, e.g. a string with most-significant to least significant rdns separated by slashes ('/'); rdn components are separated by commas (','). Only printable chars (e.g. LDAPv2 printable string) are allowed, at least in this implementation. .B ldap_dcedn2dn() performs the opposite operation. .B ldap_dn2ad_canonical() turns a DN into a AD canonical name, which is basically a DCE dn with attribute types omitted. The trailing domain, if present, is turned in a DNS-like domain. The space for the returned value is obtained dynamically and the user is responsible for freeing it via a call to .BR ldap_memfree (3). .SH ERRORS If an error occurs in .BR ldap_get_dn() , NULL is returned and the .B ld_errno field in the \fIld\fP parameter is set to indicate the error. See .BR ldap_error (3) for a description of possible error codes. .BR ldap_explode_dn() , .BR ldap_explode_rdn() , .B ldap_dn2ufn(), .B ldap_dn2dcedn(), .B ldap_dcedn2dn(), and .B ldap_dn2ad_canonical() will return NULL with .BR errno (3) set appropriately in case of trouble. .SH NOTES These routines dynamically allocate memory that the caller must free. .SH SEE ALSO .BR ldap (3), .BR ldap_error (3), .BR ldap_first_entry (3), .BR ldap_memfree (3), .BR ldap_value_free (3) .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man3/ldap_result.30000644000175000017500000001024212563404150017607 0ustar ryanryan.TH LDAP_RESULT 3 "RELEASEDATE" "OpenLDAP LDVERSION" .\" $OpenLDAP$ .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_result \- Wait for the result of an LDAP operation .SH LIBRARY OpenLDAP LDAP (libldap, \-lldap) .SH SYNOPSIS .nf .ft B #include .LP .ft B int ldap_result( LDAP *ld, int msgid, int all, struct timeval *timeout, LDAPMessage **result ); int ldap_msgfree( LDAPMessage *msg ); int ldap_msgtype( LDAPMessage *msg ); int ldap_msgid( LDAPMessage *msg ); .ft .SH DESCRIPTION The .B ldap_result() routine is used to wait for and return the result of an operation previously initiated by one of the LDAP asynchronous operation routines (e.g., .BR ldap_search_ext (3), .BR ldap_modify_ext (3), etc.). Those routines all return \-1 in case of error, and an invocation identifier upon successful initiation of the operation. The invocation identifier is picked by the library and is guaranteed to be unique across the LDAP session. It can be used to request the result of a specific operation from .B ldap_result() through the \fImsgid\fP parameter. .LP The .B ldap_result() routine will block or not, depending upon the setting of the \fItimeout\fP parameter. If timeout is not a NULL pointer, it specifies a maximum interval to wait for the selection to complete. If timeout is a NULL pointer, the LDAP_OPT_TIMEOUT value set by .BR ldap_set_option (3) is used. With the default setting, the select blocks indefinitely. To effect a poll, the timeout argument should be a non-NULL pointer, pointing to a zero-valued timeval structure. To obtain the behavior of the default setting, bypassing any value set by .BR ldap_set_option (3), set to -1 the \fItv_sec\fP field of the \fItimeout\fP parameter. See .BR select (2) for further details. .LP If the result of a specific operation is required, \fImsgid\fP should be set to the invocation identifier returned when the operation was initiated, otherwise LDAP_RES_ANY or LDAP_RES_UNSOLICITED should be supplied to wait for any or unsolicited response. .LP The \fIall\fP parameter, if non-zero, causes .B ldap_result() to return all responses with msgid, otherwise only the next response is returned. This is commonly used to obtain all the responses of a search operation. .LP A search response is made up of zero or more search entries, zero or more search references, and zero or more extended partial responses followed by a search result. If \fIall\fP is set to 0, search entries will be returned one at a time as they come in, via separate calls to .BR ldap_result() . If it's set to 1, the search response will only be returned in its entirety, i.e., after all entries, all references, all extended partial responses, and the final search result have been received. .SH RETURN VALUE Upon success, the type of the result received is returned and the \fIresult\fP parameter will contain the result of the operation; otherwise, the \fIresult\fP parameter is undefined. This result should be passed to the LDAP parsing routines, .BR ldap_first_message (3) and friends, for interpretation. .LP The possible result types returned are: .LP .nf LDAP_RES_BIND (0x61) LDAP_RES_SEARCH_ENTRY (0x64) LDAP_RES_SEARCH_REFERENCE (0x73) LDAP_RES_SEARCH_RESULT (0x65) LDAP_RES_MODIFY (0x67) LDAP_RES_ADD (0x69) LDAP_RES_DELETE (0x6b) LDAP_RES_MODDN (0x6d) LDAP_RES_COMPARE (0x6f) LDAP_RES_EXTENDED (0x78) LDAP_RES_INTERMEDIATE (0x79) .fi .LP The .B ldap_msgfree() routine is used to free the memory allocated for result(s) by .B ldap_result() or .BR ldap_search_ext_s (3) and friends. It takes a pointer to the result or result chain to be freed and returns the type of the last message in the chain. If the parameter is NULL, the function does nothing and returns zero. .LP The .B ldap_msgtype() routine returns the type of a message. .LP The .B ldap_msgid() routine returns the message id of a message. .SH ERRORS .B ldap_result() returns \-1 if something bad happens, and zero if the timeout specified was exceeded. .B ldap_msgtype() and .B ldap_msgid() return \-1 on error. .SH SEE ALSO .BR ldap (3), .BR ldap_first_message (3), .BR select (2) .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man3/ldap_parse_result.3.links0000644000175000017500000000007312563404150022121 0ustar ryanryanldap_parse_sasl_bind_result.3 ldap_parse_extended_result.3 openldap-2.4.42+dfsg/doc/man/man3/ldap_get_option.3.links0000644000175000017500000000002212563404150021552 0ustar ryanryanldap_set_option.3 openldap-2.4.42+dfsg/doc/man/man3/ldap_delete.30000644000175000017500000000437112563404150017541 0ustar ryanryan.TH LDAP_DELETE 3 "RELEASEDATE" "OpenLDAP LDVERSION" .\" $OpenLDAP$ .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_delete, ldap_delete_s, ldap_delete_ext, ldap_delete_ext_s \- Perform an LDAP delete operation. .SH LIBRARY OpenLDAP LDAP (libldap, \-lldap) .SH SYNOPSIS .nf .ft B #include .LP .ft B int ldap_delete_s(ld, dn) .ft LDAP *ld; char *dn; .LP .ft B int ldap_delete(ld, dn) .ft LDAP *ld; char *dn; .LP .ft B int ldap_delete_ext(ld, dn, serverctrls, clientctrls, msgidp) .ft LDAP *ld; char *dn; LDAPControl **serverctrls, **clientctrls; int *msgidp; .LP .ft B int ldap_delete_ext_s(ld, dn, serverctrls, clientctrls) .ft LDAP *ld; char *dn; LDAPControl **serverctrls, **clientctrls; .SH DESCRIPTION The .B ldap_delete_s() routine is used to perform an LDAP delete operation synchronously. It takes \fIdn\fP, the DN of the entry to be deleted. It returns an LDAP error code, indicating the success or failure of the operation. .LP The .B ldap_delete() routine is used to perform an LDAP delete operation asynchronously. It takes the same parameters as .BR ldap_delete_s(), but returns the message id of the request it initiated. The result of the delete can be obtained by a subsequent call to .BR ldap_result (3). .LP The .B ldap_delete_ext() routine allows server and client controls to be specified to extend the delete request. This routine is asynchronous like ldap_delete(), but its return value is an LDAP error code. It stores the message id of the request in the integer pointed to by msgidp. .LP The .B ldap_delete_ext_s() routine is the synchronous version of .BR ldap_delete_ext(). It also returns an LDAP error code indicating success or failure of the operation. .SH ERRORS .B ldap_delete_s() returns an LDAP error code which can be interpreted by calling one of .BR ldap_perror (3) and friends. .B ldap_delete() returns \-1 if something went wrong initiating the request. It returns the non-negative message id of the request if things went ok. .LP .B ldap_delete_ext() and .B ldap_delete_ext_s() return some Non-zero value if something went wrong initiating the request, else return 0. .SH SEE ALSO .BR ldap (3), .BR ldap_error (3) .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man3/ldap_abandon.3.links0000644000175000017500000000002312563404150021006 0ustar ryanryanldap_abandon_ext.3 openldap-2.4.42+dfsg/doc/man/man3/ldap_rename.3.links0000644000175000017500000000002012563404150020650 0ustar ryanryanldap_rename_s.3 openldap-2.4.42+dfsg/doc/man/man3/lber-encode.3.links0000644000175000017500000000024212563404150020566 0ustar ryanryanber_alloc_t.3 ber_flush.3 ber_printf.3 ber_put_int.3 ber_put_ostring.3 ber_put_string.3 ber_put_null.3 ber_put_enum.3 ber_start_set.3 ber_put_seq.3 ber_put_set.3 openldap-2.4.42+dfsg/doc/man/man3/ldap_first_reference.30000644000175000017500000000405712563404150021445 0ustar ryanryan.TH LDAP_FIRST_REFERENCE 3 "RELEASEDATE" "OpenLDAP LDVERSION" .\" $OpenLDAP$ .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_first_reference, ldap_next_reference, ldap_count_references \- Stepping through continuation references in a result chain .SH LIBRARY OpenLDAP LDAP (libldap, \-lldap) .SH SYNOPSIS .nf .ft B #include .LP .ft B int ldap_count_references( LDAP *ld, LDAPMessage *result ) .LP .ft B LDAPMessage *ldap_first_reference( LDAP *ld, LDAPMessage *result ) .LP .ft B LDAPMessage *ldap_next_reference( LDAP *ld, LDAPMessage *reference ) .SH DESCRIPTION .LP These routines are used to step through the continuation references in a result chain received from .BR ldap_result (3) or the synchronous LDAP search operation routines. .LP The .B ldap_first_reference() routine is used to retrieve the first reference message in a result chain. It takes the \fIresult\fP as returned by a call to .BR ldap_result (3) , .BR ldap_search_s (3) or .BR ldap_search_st (3) and returns a pointer to the first reference message in the result chain. .LP This pointer should be supplied on a subsequent call to .B ldap_next_reference() to get the next reference message, the result of which should be supplied to the next call to .BR ldap_next_reference() , etc. .B ldap_next_reference() will return NULL when there are no more reference messages. The reference messages returned from these calls are used by .BR ldap_parse_reference (3) to extract referrals and controls. .LP A count of the number of reference messages in the search result can be obtained by calling .BR ldap_count_references() . It can also be used to count the number of reference messages remaining in a result chain. .SH ERRORS If an error occurs in .B ldap_first_reference() or .BR ldap_next_reference() , NULL is returned. If an error occurs in .BR ldap_count_references() , -1 is returned. .SH SEE ALSO .BR ldap (3), .BR ldap_result (3), .BR ldap_search (3), .BR ldap_parse_reference (3) .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man3/ldap_tls.3.links0000644000175000017500000000011212563404150020205 0ustar ryanryanldap_start_tls.3 ldap_start_tls_s.3 ldap_tls_inplace.3 ldap_install_tls.3 openldap-2.4.42+dfsg/doc/man/man3/Deprecated0000644000175000017500000000067212563404150017176 0ustar ryanryanDeprecated interfaces generally remain in the library. The macro LDAP_DEPRECATED can be defined to a non-zero value (e.g., -DLDAP_DEPRECATED=1) when compiling program designed to use deprecated interfaces. It is recommended that developers writing new programs, or updating old programs, avoid use of deprecated interfaces. Over time, it is expected that documentation (and, eventually, support) for deprecated interfaces to be eliminated. openldap-2.4.42+dfsg/doc/man/man3/ldap_bind.3.links0000644000175000017500000000026512563404150020330 0ustar ryanryanldap_bind_s.3 ldap_simple_bind.3 ldap_simple_bind_s.3 ldap_sasl_bind.3 ldap_sasl_bind_s.3 ldap_unbind.3 ldap_unbind_ext.3 ldap_unbind_s.3 ldap_unbind_ext_s.3 ldap_set_rebind_proc.3 openldap-2.4.42+dfsg/doc/man/man3/ldap_first_message.30000644000175000017500000000452112563404150021127 0ustar ryanryan.TH LDAP_FIRST_MESSAGE 3 "RELEASEDATE" "OpenLDAP LDVERSION" .\" $OpenLDAP$ .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_first_message, ldap_next_message, ldap_count_messages \- Stepping through messages in a result chain .SH LIBRARY OpenLDAP LDAP (libldap, \-lldap) .SH SYNOPSIS .nf .ft B #include .LP .ft B int ldap_count_messages( LDAP *ld, LDAPMessage *result ) .LP .ft B LDAPMessage *ldap_first_message( LDAP *ld, LDAPMessage *result ) .LP .ft B LDAPMessage *ldap_next_message( LDAP *ld, LDAPMessage *message ) .SH DESCRIPTION .LP These routines are used to step through the messages in a result chain received from .BR ldap_result (3) . For search operations, the result chain can contain referral, entry and result messages. The .BR ldap_msgtype (3) function can be used to distinguish between the different message types. .LP The .B ldap_first_message() routine is used to retrieve the first message in a result chain. It takes the \fIresult\fP as returned by a call to .BR ldap_result (3) , .BR ldap_search_s (3) or .BR ldap_search_st (3) and returns a pointer to the first message in the result chain. .LP This pointer should be supplied on a subsequent call to .B ldap_next_message() to get the next message, the result of which should be supplied to the next call to .BR ldap_next_message() , etc. .B ldap_next_message() will return NULL when there are no more messages. .LP These functions are useful when using routines like .BR ldap_parse_result (3) that only operate on the first result in the chain. .LP A count of the number of messages in the result chain can be obtained by calling .BR ldap_count_messages() . It can also be used to count the number of remaining messages in a chain if called with a message, entry or reference returned by .B ldap_first_message() , .B ldap_next_message() , .BR ldap_first_entry (3) , .BR ldap_next_entry (3) , .BR ldap_first_reference (3) , .BR ldap_next_reference (3) . .SH ERRORS If an error occurs in .B ldap_first_message() or .BR ldap_next_message() , NULL is returned. If an error occurs in .BR ldap_count_messages() , -1 is returned. .SH SEE ALSO .BR ldap (3), .BR ldap_search (3), .BR ldap_result (3), .BR ldap_parse_result (3), .BR ldap_first_entry (3), .BR ldap_first_reference (3) .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man3/ldap_result.3.links0000644000175000017500000000005312563404150020725 0ustar ryanryanldap_msgfree.3 ldap_msgtype.3 ldap_msgid.3 openldap-2.4.42+dfsg/doc/man/man3/lber-decode.30000644000175000017500000003016712563404150017446 0ustar ryanryan.TH LBER_DECODE 3 "RELEASEDATE" "OpenLDAP LDVERSION" .\" $OpenLDAP$ .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ber_get_next, ber_skip_tag, ber_peek_tag, ber_scanf, ber_get_int, ber_get_enum, ber_get_stringb, ber_get_stringa, ber_get_stringal, ber_get_stringbv, ber_get_null, ber_get_boolean, ber_get_bitstring, ber_first_element, ber_next_element \- OpenLDAP LBER simplified Basic Encoding Rules library routines for decoding .SH LIBRARY OpenLDAP LBER (liblber, \-llber) .SH SYNOPSIS .B #include .LP .BI "ber_tag_t ber_get_next(Sockbuf *" sb ", ber_len_t *" len ", BerElement *" ber ");" .LP .BI "ber_tag_t ber_skip_tag(BerElement *" ber ", ber_len_t *" len ");" .LP .BI "ber_tag_t ber_peek_tag(BerElement *" ber ", ber_len_t *" len ");" .LP .BI "ber_tag_t ber_scanf(BerElement *" ber ", const char *" fmt ", ...);" .LP .BI "ber_tag_t ber_get_int(BerElement *" ber ", ber_int_t *" num ");" .LP .BI "ber_tag_t ber_get_enum(BerElement *" ber ", ber_int_t *" num ");" .LP .BI "ber_tag_t ber_get_stringb(BerElement *" ber ", char *" buf ", ber_len_t *" len ");" .LP .BI "ber_tag_t ber_get_stringa(BerElement *" ber ", char **" buf ");" .LP .BI "ber_tag_t ber_get_stringal(BerElement *" ber ", struct berval **" bv ");" .LP .BI "ber_tag_t ber_get_stringbv(BerElement *" ber ", struct berval *" bv ", int " alloc ");" .LP .BI "ber_tag_t ber_get_null(BerElement *" ber ");" .LP .BI "ber_tag_t ber_get_boolean(BerElement *" ber ", ber_int_t *" bool ");" .LP .BI "ber_tag_t ber_get_bitstringa(BerElement *" ber ", char **" buf ", ber_len_t *" blen ");" .LP .BI "ber_tag_t ber_first_element(BerElement *" ber ", ber_len_t *" len ", char **" cookie ");" .LP .BI "ber_tag_t ber_next_element(BerElement *" ber ", ber_len_t *" len ", const char *" cookie ");" .SH DESCRIPTION .LP These routines provide a subroutine interface to a simplified implementation of the Basic Encoding Rules of ASN.1. The version of BER these routines support is the one defined for the LDAP protocol. The encoding rules are the same as BER, except that only definite form lengths are used, and bitstrings and octet strings are always encoded in primitive form. This man page describes the decoding routines in the lber library. See .BR lber-encode (3) for details on the corresponding encoding routines. Consult .BR lber-types (3) for information about types, allocators, and deallocators. .LP Normally, the only routines that need to be called by an application are .BR ber_get_next () to get the next BER element and .BR ber_scanf () to do the actual decoding. In some cases, .BR ber_peek_tag () may also need to be called in normal usage. The other routines are provided for those applications that need more control than .BR ber_scanf () provides. In general, these routines return the tag of the element decoded, or LBER_ERROR if an error occurred. .LP The .BR ber_get_next () routine is used to read the next BER element from the given Sockbuf, \fIsb\fP. It strips off and returns the leading tag, strips off and returns the length of the entire element in \fIlen\fP, and sets up \fIber\fP for subsequent calls to .BR ber_scanf () et al to decode the element. See .BR lber-sockbuf (3) for details of the Sockbuf implementation of the \fIsb\fP parameter. .LP The .BR ber_scanf () routine is used to decode a BER element in much the same way that .BR scanf (3) works. It reads from \fIber\fP, a pointer to a BerElement such as returned by .BR ber_get_next (), interprets the bytes according to the format string \fIfmt\fP, and stores the results in its additional arguments. The format string contains conversion specifications which are used to direct the interpretation of the BER element. The format string can contain the following characters. .RS .LP .TP 3 .B a Octet string. A char ** should be supplied. Memory is allocated, filled with the contents of the octet string, null-terminated, and returned in the parameter. The caller should free the returned string using .BR ber_memfree (). .TP .B A Octet string. A variant of "\fBa\fP". A char ** should be supplied. Memory is allocated, filled with the contents of the octet string, null-terminated, and returned in the parameter, unless a zero-length string would result; in that case, the arg is set to NULL. The caller should free the returned string using .BR ber_memfree (). .TP .B s Octet string. A char * buffer should be supplied, followed by a pointer to a ber_len_t initialized to the size of the buffer. Upon return, the null-terminated octet string is put into the buffer, and the ber_len_t is set to the actual size of the octet string. .TP .B O Octet string. A struct ber_val ** should be supplied, which upon return points to a dynamically allocated struct berval containing the octet string and its length. The caller should free the returned structure using .BR ber_bvfree (). .TP .B o Octet string. A struct ber_val * should be supplied, which upon return contains the dynamically allocated octet string and its length. The caller should free the returned octet string using .BR ber_memfree (). .TP .B m Octet string. A struct ber_val * should be supplied, which upon return contains the octet string and its length. The string resides in memory assigned to the BerElement, and must not be freed by the caller. .TP .B b Boolean. A pointer to a ber_int_t should be supplied. .TP .B e Enumeration. A pointer to a ber_int_t should be supplied. .TP .B i Integer. A pointer to a ber_int_t should be supplied. .TP .B B Bitstring. A char ** should be supplied which will point to the dynamically allocated bits, followed by a ber_len_t *, which will point to the length (in bits) of the bitstring returned. .TP .B n Null. No parameter is required. The element is simply skipped if it is recognized. .TP .B v Sequence of octet strings. A char *** should be supplied, which upon return points to a dynamically allocated null-terminated array of char *'s containing the octet strings. NULL is returned if the sequence is empty. The caller should free the returned array and octet strings using .BR ber_memvfree (). .TP .B V Sequence of octet strings with lengths. A struct berval *** should be supplied, which upon return points to a dynamically allocated null-terminated array of struct berval *'s containing the octet strings and their lengths. NULL is returned if the sequence is empty. The caller should free the returned structures using .BR ber_bvecfree (). .TP .B W Sequence of octet strings with lengths. A BerVarray * should be supplied, which upon return points to a dynamically allocated array of struct berval's containing the octet strings and their lengths. The array is terminated by a struct berval with a NULL bv_val string pointer. NULL is returned if the sequence is empty. The caller should free the returned structures using .BR ber_bvarray_free (). .TP .B M Sequence of octet strings with lengths. This is a generalized form of the previous three formats. A void ** (ptr) should be supplied, followed by a ber_len_t * (len) and a ber_len_t (off). Upon return (ptr) will point to a dynamically allocated array whose elements are all of size (*len). A struct berval will be filled starting at offset (off) in each element. The strings in each struct berval reside in memory assigned to the BerElement and must not be freed by the caller. The array is terminated by a struct berval with a NULL bv_val string pointer. NULL is returned if the sequence is empty. The number of elements in the array is also stored in (*len) on return. The caller should free the returned array using .BR ber_memfree (). .TP .B l Length of the next element. A pointer to a ber_len_t should be supplied. .TP .B t Tag of the next element. A pointer to a ber_tag_t should be supplied. .TP .B T Skip element and return its tag. A pointer to a ber_tag_t should be supplied. .TP .B x Skip element. The next element is skipped. .TP .B { Begin sequence. No parameter is required. The initial sequence tag and length are skipped. .TP .B } End sequence. No parameter is required and no action is taken. .TP .B [ Begin set. No parameter is required. The initial set tag and length are skipped. .TP .B ] End set. No parameter is required and no action is taken. .RE .LP The .BR ber_get_int () routine tries to interpret the next element as an integer, returning the result in \fInum\fP. The tag of whatever it finds is returned on success, LBER_ERROR (\-1) on failure. .LP The .BR ber_get_stringb () routine is used to read an octet string into a preallocated buffer. The \fIlen\fP parameter should be initialized to the size of the buffer, and will contain the length of the octet string read upon return. The buffer should be big enough to take the octet string value plus a terminating NULL byte. .LP The .BR ber_get_stringa () routine is used to dynamically allocate space into which an octet string is read. The caller should free the returned string using .BR ber_memfree(). .LP The .BR ber_get_stringal () routine is used to dynamically allocate space into which an octet string and its length are read. It takes a struct berval **, and returns the result in this parameter. The caller should free the returned structure using .BR ber_bvfree(). .LP The .BR ber_get_stringbv () routine is used to read an octet string and its length into the provided struct berval *. If the \fIalloc\fP parameter is zero, the string will reside in memory assigned to the BerElement, and must not be freed by the caller. If the \fIalloc\fP parameter is non-zero, the string will be copied into dynamically allocated space which should be returned using .BR ber_memfree (). .LP The .BR ber_get_null () routine is used to read a NULL element. It returns the tag of the element it skips over. .LP The .BR ber_get_boolean () routine is used to read a boolean value. It is called the same way that .BR ber_get_int () is called. .LP The .BR ber_get_enum () routine is used to read a enumeration value. It is called the same way that .BR ber_get_int () is called. .LP The .BR ber_get_bitstringa () routine is used to read a bitstring value. It takes a char ** which will hold the dynamically allocated bits, followed by an ber_len_t *, which will point to the length (in bits) of the bitstring returned. The caller should free the returned string using .BR ber_memfree (). .LP The .BR ber_first_element () routine is used to return the tag and length of the first element in a set or sequence. It also returns in \fIcookie\fP a magic cookie parameter that should be passed to subsequent calls to ber_next_element(), which returns similar information. .SH EXAMPLES Assume the variable \fIber\fP contains a lightweight BER encoding of the following ASN.1 object: .LP .nf AlmostASearchRequest := SEQUENCE { baseObject DistinguishedName, scope ENUMERATED { baseObject (0), singleLevel (1), wholeSubtree (2) }, derefAliases ENUMERATED { neverDerefaliases (0), derefInSearching (1), derefFindingBaseObj (2), alwaysDerefAliases (3) }, sizelimit INTEGER (0 .. 65535), timelimit INTEGER (0 .. 65535), attrsOnly BOOLEAN, attributes SEQUENCE OF AttributeType } .fi .LP The element can be decoded using .BR ber_scanf () as follows. .LP .nf ber_int_t scope, deref, size, time, attrsonly; char *dn, **attrs; ber_tag_t tag; tag = ber_scanf( ber, "{aeeiib{v}}", &dn, &scope, &deref, &size, &time, &attrsonly, &attrs ); if( tag == LBER_ERROR ) { /* error */ } else { /* success */ } ber_memfree( dn ); ber_memvfree( attrs ); .fi .SH ERRORS If an error occurs during decoding, generally these routines return LBER_ERROR ((ber_tag_t)\-1). .LP .SH NOTES .LP The return values for all of these functions are declared in the .B header file. Some routines may dynamically allocate memory which must be freed by the caller using supplied deallocation routines. .SH SEE ALSO .BR lber-encode (3), .BR lber-memory (3), .BR lber-sockbuf (3), .BR lber-types (3) .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man3/ldap_open.3.links0000644000175000017500000000010512563404150020346 0ustar ryanryanldap_init.3 ldap_initialize.3 ldap_set_urllist_proc.3 ldap_init_fd.3 openldap-2.4.42+dfsg/doc/man/man3/ldap_error.3.links0000644000175000017500000000011612563404150020540 0ustar ryanryanldap_perror.3 ld_errno.3 ldap_result2error.3 ldap_errlist.3 ldap_err2string.3 openldap-2.4.42+dfsg/doc/man/man3/ldap.30000644000175000017500000002020712563404150016213 0ustar ryanryan.TH LDAP 3 "RELEASEDATE" "OpenLDAP LDVERSION" .\" $OpenLDAP$ .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap \- OpenLDAP Lightweight Directory Access Protocol API .SH LIBRARY OpenLDAP LDAP (libldap, \-lldap) .SH SYNOPSIS .nf .ft B #include .ft .fi .SH DESCRIPTION .LP The Lightweight Directory Access Protocol (LDAP) (RFC 4510) provides access to X.500 directory services. These services may be stand\-alone or part of a distributed directory service. This client API supports LDAP over TCP (RFC 4511), LDAP over TLS/SSL, and LDAP over IPC (UNIX domain sockets). This API supports SASL (RFC 4513) and Start TLS (RFC 4513) as well as a number of protocol extensions. This API is loosely based upon IETF/LDAPEXT C LDAP API draft specification, a (orphaned) work in progress. .LP The OpenLDAP Software package includes a stand\-alone server in .BR slapd (8), various LDAP clients, and an LDAP client library used to provide programmatic access to the LDAP protocol. This man page gives an overview of the LDAP library routines. .LP Both synchronous and asynchronous APIs are provided. Also included are various routines to parse the results returned from these routines. These routines are found in the \-lldap library. .LP The basic interaction is as follows. A session handle is created using .BR ldap_initialize (3) and set the protocol version to 3 by calling .BR ldap_set_option (3). The underlying session is established first operation is issued. This would generally be a Start TLS or Bind operation, or a Search operation to read attributes of the Root DSE. A Start TLS operation is performed by calling .BR ldap_start_tls_s (3). A LDAP bind operation is performed by calling .BR ldap_sasl_bind (3) or one of its friends. A Search operation is performed by calling ldap_search_ext_s(3) or one of its friends. Subsequently, additional operations are performed by calling one of the synchronous or asynchronous routines (e.g., .BR ldap_compare_ext_s (3) or .BR ldap_compare_ext (3) followed by .BR ldap_result (3)). Results returned from these routines are interpreted by calling the LDAP parsing routines such as .BR ldap_parse_result (3). The LDAP association and underlying connection is terminated by calling .BR ldap_unbind_ext (3). Errors can be interpreted by calling .BR ldap_err2string (3). .SH LDAP versions This library supports version 3 of the Lightweight Directory Access Protocol (LDAPv3) as defined in RFC 4510. It also supports a variant of version 2 of LDAP as defined by U-Mich LDAP and, to some degree, RFC 1777. Version 2 (all variants) are considered obsolete. Version 3 should be used instead. .LP For backwards compatibility reasons, the library defaults to version 2. Hence, all new applications (and all actively maintained applications) should use .BR ldap_set_option (3) to select version 3. The library manual pages assume version 3 has been selected. .SH INPUT and OUTPUT PARAMETERS All character string input/output is expected to be/is UTF-8 encoded Unicode (version 3.2). .LP Distinguished names (DN) (and relative distinguished names (RDN) to be passed to the LDAP routines should conform to RFC 4514 UTF-8 string representation. .LP Search filters to be passed to the search routines are to be constructed by hand and should conform to RFC 4515 UTF-8 string representation. .LP LDAP URLs to be passed to routines are expected to conform to RFC 4516 format. The .BR ldap_url (3) routines can be used to work with LDAP URLs. .LP LDAP controls to be passed to routines can be manipulated using the .BR ldap_controls (3) routines. .SH DISPLAYING RESULTS Results obtained from the search routines can be output by hand, by calling .BR ldap_first_entry (3) and .BR ldap_next_entry (3) to step through the entries returned, .BR ldap_first_attribute (3) and .BR ldap_next_attribute (3) to step through an entry's attributes, and .BR ldap_get_values (3) to retrieve a given attribute's values. Attribute values may or may not be displayable. .SH UTILITY ROUTINES Also provided are various utility routines. The .BR ldap_sort (3) routines are used to sort the entries and values returned via the ldap search routines. .SH DEPRECATED INTERFACES A number of interfaces are now considered deprecated. For instance, ldap_add(3) is deprecated in favor of ldap_add_ext(3). .so Deprecated .SH BER LIBRARY Also included in the distribution is a set of lightweight Basic Encoding Rules routines. These routines are used by the LDAP library routines to encode and decode LDAP protocol elements using the (slightly simplified) Basic Encoding Rules defined by LDAP. They are not normally used directly by an LDAP application program except in the handling of controls and extended operations. The routines provide a printf and scanf\-like interface, as well as lower\-level access. These routines are discussed in .BR lber\-decode (3), .BR lber\-encode (3), .BR lber\-memory (3), and .BR lber\-types (3). .SH INDEX .TP 20 .SM ldap_initialize(3) initialize the LDAP library without opening a connection to a server .TP .SM ldap_result(3) wait for the result from an asynchronous operation .TP .SM ldap_abandon_ext(3) abandon (abort) an asynchronous operation .TP .SM ldap_add_ext(3) asynchronously add an entry .TP .SM ldap_add_ext_s(3) synchronously add an entry .TP .SM ldap_sasl_bind(3) asynchronously bind to the directory .TP .SM ldap_sasl_bind_s(3) synchronously bind to the directory .TP .SM ldap_unbind_ext(3) synchronously unbind from the LDAP server and close the connection .TP .SM ldap_unbind(3) and ldap_unbind_s(3) are equivalent to .BR ldap_unbind_ext (3) .TP .SM ldap_memfree(3) dispose of memory allocated by LDAP routines. .TP .SM ldap_compare_ext(3) asynchronously compare to a directory entry .TP .SM ldap_compare_ext_s(3) synchronously compare to a directory entry .TP .SM ldap_delete_ext(3) asynchronously delete an entry .TP .SM ldap_delete_ext_s(3) synchronously delete an entry .TP .SM ld_errno(3) LDAP error indication .TP .SM ldap_errlist(3) list of LDAP errors and their meanings .TP .SM ldap_err2string(3) convert LDAP error indication to a string .TP .SM ldap_extended_operation(3) asynchronously perform an arbitrary extended operation .TP .SM ldap_extended_operation_s(3) synchronously perform an arbitrary extended operation .TP .SM ldap_first_attribute(3) return first attribute name in an entry .TP .SM ldap_next_attribute(3) return next attribute name in an entry .TP .SM ldap_first_entry(3) return first entry in a chain of search results .TP .SM ldap_next_entry(3) return next entry in a chain of search results .TP .SM ldap_count_entries(3) return number of entries in a search result .TP .SM ldap_get_dn(3) extract the DN from an entry .TP .SM ldap_get_values_len(3) return an attribute's values with lengths .TP .SM ldap_value_free_len(3) free memory allocated by ldap_get_values_len(3) .TP .SM ldap_count_values_len(3) return number of values .TP .SM ldap_modify_ext(3) asynchronously modify an entry .TP .SM ldap_modify_ext_s(3) synchronously modify an entry .TP .SM ldap_mods_free(3) free array of pointers to mod structures used by ldap_modify_ext(3) .TP .SM ldap_rename(3) asynchronously rename an entry .TP .SM ldap_rename_s(3) synchronously rename an entry .TP .SM ldap_msgfree(3) free results allocated by ldap_result(3) .TP .SM ldap_msgtype(3) return the message type of a message from ldap_result(3) .TP .SM ldap_msgid(3) return the message id of a message from ldap_result(3) .TP .SM ldap_search_ext(3) asynchronously search the directory .TP .SM ldap_search_ext_s(3) synchronously search the directory .TP .SM ldap_is_ldap_url(3) check a URL string to see if it is an LDAP URL .TP .SM ldap_url_parse(3) break up an LDAP URL string into its components .TP .SM ldap_sort_entries(3) sort a list of search results .TP .SM ldap_sort_values(3) sort a list of attribute values .TP .SM ldap_sort_strcasecmp(3) case insensitive string comparison .SH SEE ALSO .BR ldap.conf (5), .BR slapd (8), .BR draft-ietf-ldapext-ldap-c-api-xx.txt \ .SH ACKNOWLEDGEMENTS .so ../Project .LP These API manual pages are loosely based upon descriptions provided in the IETF/LDAPEXT C LDAP API Internet Draft, a (orphaned) work in progress. openldap-2.4.42+dfsg/doc/man/man3/ldap_modify.3.links0000644000175000017500000000010712563404150020676 0ustar ryanryanldap_modify_s.3 ldap_modify_ext.3 ldap_modify_ext_s.3 ldap_mods_free.3 openldap-2.4.42+dfsg/doc/man/man3/ldap_schema.3.links0000644000175000017500000000060212563404150020647 0ustar ryanryanldap_str2syntax.3 ldap_syntax2str.3 ldap_syntax2name.3 ldap_syntax_free.3 ldap_str2matchingrule.3 ldap_matchingrule2str.3 ldap_matchingrule2name.3 ldap_matchingrule_free.3 ldap_str2attributetype.3 ldap_attributetype2str.3 ldap_attributetype2name.3 ldap_attributetype_free.3 ldap_str2objectclass.3 ldap_objectclass2str.3 ldap_objectclass2name.3 ldap_objectclass_free.3 ldap_scherr2str.3 openldap-2.4.42+dfsg/doc/man/man3/ldap_controls.30000644000175000017500000000527712563404150020150 0ustar ryanryan.TH LDAP_CONTROLS 3 "RELEASEDATE" "OpenLDAP LDVERSION" .\" $OpenLDAP$ .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_control_create, ldap_control_find, ldap_control_dup, ldap_controls_dup, ldap_control_free, ldap_controls_free \- LDAP control manipulation routines .SH LIBRARY OpenLDAP LDAP (libldap, \-lldap) .SH SYNOPSIS .B #include .LP .BI "int ldap_control_create(const char *" oid ", int " iscritical ", struct berval *" value ", int " dupval ", LDAPControl **" ctrlp ");" .LP .BI "LDAPControl *ldap_control_find( const char *" oid ", LDAPControl **" ctrls ", LDAPControl ***" nextctrlp ");" .LP .BI "LDAPControl *ldap_control_dup(LDAPControl *" ctrl ");" .LP .BI "LDAPControl **ldap_controls_dup(LDAPControl **" ctrls ");" .LP .BI "void ldap_control_free(LDAPControl *" ctrl ");" .LP .BI "void ldap_controls_free(LDAPControl **" ctrls ");" .SH DESCRIPTION These routines are used to manipulate structures used for LDAP controls. .BR ldap_control_create () creates a control with the specified .I OID using the contents of the .I value parameter for the control value, if any. The content of .I value is duplicated if .I dupval is non-zero. The .I iscritical parameter must be non-zero for a critical control. The created control is returned in the .I ctrlp parameter. The routine returns .B LDAP_SUCCESS on success or some other error code on failure. The content of .IR value , for supported control types, can be prepared using helpers provided by this implementation of libldap, usually in the form .BR "ldap_create__control_value" (). Otherwise, it can be BER-encoded using the functionalities of liblber. .BR ldap_control_find () searches the NULL-terminated .I ctrls array for a control whose OID matches the .I oid parameter. The routine returns a pointer to the control if found, NULL otherwise. If the parameter .I nextctrlp is not NULL, on return it will point to the next control in the array, and can be passed to the .BR ldap_control_find () routine for subsequent calls, to find further occurrences of the same control type. The use of this function is discouraged; the recommended way of handling controls in responses consists in going through the array of controls, dealing with each of them in the returned order, since it could matter. .BR ldap_control_dup () duplicates an individual control structure, and .BR ldap_controls_dup () duplicates a NULL-terminated array of controls. .BR ldap_control_free () frees an individual control structure, and .BR ldap_controls_free () frees a NULL-terminated array of controls. .SH SEE ALSO .BR ldap (3), .BR ldap_error (3) .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man3/ldap_compare.30000644000175000017500000000403212563404150017717 0ustar ryanryan.TH LDAP_COMPARE 3 "RELEASEDATE" "OpenLDAP LDVERSION" .\" $OpenLDAP$ .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_compare, ldap_compare_s, ldap_compare_ext, ldap_compare_ext_s \- Perform an LDAP compare operation. .SH LIBRARY OpenLDAP LDAP (libldap, \-lldap) .SH SYNOPSIS .nf .ft B #include .LP .ft B int ldap_compare_ext( .RS .ft B LDAP *\fIld\fB, char *\fIdn\fB, char *\fIattr\fB, const struct berval *\fIbvalue\fB, LDAPControl **\fIserverctrls\fB, LDAPControl **\fIclientctrls\fB, int *\fImsgidp\fB ); .RE .LP .ft B int ldap_compare_ext_s( .RS .ft B LDAP *\fIld\fB, char *\fIdn\fB, char *\fIattr\fB, const struct berval *\fIbvalue\fB, LDAPControl **\fIserverctrls\fB, LDAPControl **\fIclientctrls\fB ); .RE .SH DESCRIPTION The .B ldap_compare_ext_s() routine is used to perform an LDAP compare operation synchronously. It takes \fIdn\fP, the DN of the entry upon which to perform the compare, and \fIattr\fP and \fIvalue\fP, the attribute description and value to compare to those found in the entry. It returns a code, which will be LDAP_COMPARE_TRUE if the entry contains the attribute value and LDAP_COMPARE_FALSE if it does not. Otherwise, an error code is returned that indicates the nature of the problem. See .BR ldap (3) for details. .LP The .B ldap_compare_ext() routine is used to perform an LDAP compare operation asynchronously. It takes the same parameters as .BR ldap_compare_ext_s() , but provides the message id of the request it initiated in the integer pointed to \fImsgidp\fP. The result of the compare can be obtained by a subsequent call to .BR ldap_result (3). .LP Both routines allow server and client controls to be specified to extend the compare request. .SH DEPRECATED INTERFACES The routines .BR ldap_compare () and .BR ldap_compare_s () are deprecated in favor of .BR ldap_compare_ext () and .BR ldap_compare_ext_s (), respectively. .LP .so Deprecated .SH SEE ALSO .BR ldap (3), .BR ldap_error (3) .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man3/lber-decode.3.links0000644000175000017500000000032612563404150020557 0ustar ryanryanber_get_next.3 ber_skip_tag.3 ber_peek_tag.3 ber_scanf.3 ber_get_int.3 ber_get_stringa.3 ber_get_stringb.3 ber_get_null.3 ber_get_enum.3 ber_get_boolean.3 ber_get_bitstring.3 ber_first_element.3 ber_next_element.3 openldap-2.4.42+dfsg/doc/man/man3/lber-sockbuf.30000644000175000017500000001273712563404150017662 0ustar ryanryan.TH LBER_SOCKBUF 3 "RELEASEDATE" "OpenLDAP LDVERSION" .\" $OpenLDAP$ .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ber_sockbuf_alloc, ber_sockbuf_free, ber_sockbuf_ctrl, ber_sockbuf_add_io, ber_sockbuf_remove_io, Sockbuf_IO \- OpenLDAP LBER I/O infrastructure .SH LIBRARY OpenLDAP LBER (liblber, \-llber) .SH SYNOPSIS .B #include .LP .B Sockbuf *ber_sockbuf_alloc( void ); .LP .BI "void ber_sockbuf_free(Sockbuf *" sb ");" .LP .BI "int ber_sockbuf_ctrl(Sockbuf *" sb ", int " opt ", void *" arg ");" .LP .BI "int ber_sockbuf_add_io(Sockbuf *" sb ", Sockbuf_IO *" sbio ", int " layer ", void *" arg ");" .LP .BI "int ber_sockbuf_remove_io(Sockbuf *" sb ", Sockbuf_IO *" sbio ", int " layer ");" .LP .nf .B typedef struct sockbuf_io_desc { .BI "int " sbiod_level ";" .BI "Sockbuf *" sbiod_sb ";" .BI "Sockbuf_IO *" sbiod_io ";" .BI "void *" sbiod_pvt ";" .BI "struct sockbuf_io_desc *" sbiod_next ";" .B } Sockbuf_IO_Desc; .LP .B typedef struct sockbuf_io { .BI "int (*" sbi_setup ")(Sockbuf_IO_Desc *" sbiod ", void *" arg ");" .BI "int (*" sbi_remove ")(Sockbuf_IO_Desc *" sbiod ");" .BI "int (*" sbi_ctrl ")(Sockbuf_IO_Desc *" sbiod ", int " opt ", void *" arg ");" .BI "ber_slen_t (*" sbi_read ")(Sockbuf_IO_Desc *" sbiod ", void *" buf ", ber_len_t " len ");" .BI "ber_slen_t (*" sbi_write ")(Sockbuf_IO_Desc *" sbiod ", void *" buf ", ber_len_t " len ");" .BI "int (*" sbi_close ")(Sockbuf_IO_Desc *" sbiod ");" .B } Sockbuf_IO; .SH DESCRIPTION .LP These routines are used to manage the low level I/O operations performed by the Lightweight BER library. They are called implicitly by the other libraries and usually do not need to be called directly from applications. The I/O framework is modularized and new transport layers can be supported by appropriately defining a .B Sockbuf_IO structure and installing it onto an existing .BR Sockbuf . .B Sockbuf structures are allocated and freed by .BR ber_sockbuf_alloc () and .BR ber_sockbuf_free (), respectively. The .BR ber_sockbuf_ctrl () function is used to get and set options related to a .B Sockbuf or to a specific I/O layer of the .BR Sockbuf . The .BR ber_sockbuf_add_io () and .BR ber_sockbuf_remove_io () functions are used to add and remove specific I/O layers on a .BR Sockbuf . Options for .BR ber_sockbuf_ctrl () include: .TP .B LBER_SB_OPT_HAS_IO Takes a .B Sockbuf_IO * argument and returns 1 if the given handler is installed on the .BR Sockbuf , otherwise returns 0. .TP .B LBER_SB_OPT_GET_FD Retrieves the file descriptor associated to the .BR Sockbuf ; .B arg must be a .BR "ber_socket_t *" . The return value will be 1 if a valid descriptor was present, \-1 otherwise. .TP .B LBER_SB_OPT_SET_FD Sets the file descriptor of the .B Sockbuf to the descriptor pointed to by .BR arg ; .B arg must be a .BR "ber_socket_t *" . The return value will always be 1. .TP .B LBER_SB_OPT_SET_NONBLOCK Toggles the non-blocking state of the file descriptor associated to the .BR Sockbuf . .B arg should be NULL to disable and non-NULL to enable the non-blocking state. The return value will be 1 for success, \-1 otherwise. .TP .B LBER_SB_OPT_DRAIN Flush (read and discard) all available input on the .BR Sockbuf . The return value will be 1. .TP .B LBER_SB_OPT_NEEDS_READ Returns non-zero if input is waiting to be read. .TP .B LBER_SB_OPT_NEEDS_WRITE Returns non-zero if the .B Sockbuf is ready to be written. .TP .B LBER_SB_OPT_GET_MAX_INCOMING Returns the maximum allowed size of an incoming message; .B arg must be a .BR "ber_len_t *" . The return value will be 1. .TP .B LBER_SB_OPT_SET_MAX_INCOMING Sets the maximum allowed size of an incoming message; .B arg must be a .BR "ber_len_t *" . The return value will be 1. .LP Options not in this list will be passed down to each .B Sockbuf_IO handler in turn until one of them processes it. If the option is not handled .BR ber_sockbuf_ctrl () will return 0. .LP Multiple .B Sockbuf_IO handlers can be stacked in multiple layers to provide various functionality. Currently defined layers include .TP .B LBER_SBIOD_LEVEL_PROVIDER the lowest layer, talking directly to a network .TP .B LBER_SBIOD_LEVEL_TRANSPORT an intermediate layer .TP .B LBER_SBIOD_LEVEL_APPLICATION a higher layer .LP Currently defined .B Sockbuf_IO handlers in liblber include .TP .B ber_sockbuf_io_tcp The default stream-oriented provider .TP .B ber_sockbuf_io_fd A stream-oriented provider for local IPC sockets .TP .B ber_sockbuf_io_dgram A datagram-oriented provider. This handler is only present if the liblber library was built with LDAP_CONNECTIONLESS defined. .TP .B ber_sockbuf_io_readahead A buffering layer, usually used with a datagram provider to hide the datagram semantics from upper layers. .TP .B ber_sockbuf_io_debug A generic handler that outputs hex dumps of all traffic. This handler may be inserted multiple times at arbitrary layers to show the flow of data between other handlers. .LP Additional handlers may be present in libldap if support for them was enabled: .TP .B ldap_pvt_sockbuf_io_sasl An application layer handler for SASL encoding/decoding. .TP .B sb_tls_sbio A transport layer handler for SSL/TLS encoding/decoding. Note that this handler is private to the library and is not exposed in the API. .LP The provided handlers are all instantiated implicitly by libldap, and applications generally will not need to directly manipulate them. .SH SEE ALSO .BR lber-decode (3), .BR lber-encode (3), .BR lber-types (3), .BR ldap_get_option (3) .LP .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man3/ldap_error.30000644000175000017500000001353112563404150017426 0ustar ryanryan.TH LDAP_ERROR 3 "RELEASEDATE" "OpenLDAP LDVERSION" .\" $OpenLDAP$ .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_perror, ld_errno, ldap_result2error, ldap_errlist, ldap_err2string \- LDAP protocol error handling routines .SH LIBRARY OpenLDAP LDAP (libldap, \-lldap) .SH SYNOPSIS .nf .ft B #include .LP .ft B char *ldap_err2string( int \fIerr\fB ); .SH DESCRIPTION The .B ldap_err2string() routine provides short description of the various codes returned by routines in this library. The returned string is a pointer to a static area that should not be modified. These codes are either negative, indicating an API error code; positive, indicating an LDAP resultCode other than \'success' (0), or - zero, indicating both successful use of the API and the LDAP resultCode \'success' (0). The code associated with an LDAP session is accessible using .BR ldap_get_option (3) and .BR ldap_set_option (3) with the .B LDAP_OPT_RESULT_CODE option (previously called .BR LDAP_OPT_ERROR_NUMBER ). .SH PROTOCOL RESULT CODES This section provides a partial list of protocol codes recognized by the library. As LDAP is extensible, additional values may be returned. A complete listing of \fIregistered\fP LDAP result codes can be obtained from the \fIInternet Assigned Numbers Authority\fP . .LP .TP 20 .SM LDAP_SUCCESS The request was successful. .TP .SM LDAP_OPERATIONS_ERROR An operations error occurred. .TP .SM LDAP_PROTOCOL_ERROR A protocol violation was detected. .TP .SM LDAP_TIMELIMIT_EXCEEDED An LDAP time limit was exceeded. .TP .SM LDAP_SIZELIMIT_EXCEEDED An LDAP size limit was exceeded. .TP .SM LDAP_COMPARE_FALSE A compare operation returned false. .TP .SM LDAP_COMPARE_TRUE A compare operation returned true. .TP .SM LDAP_STRONG_AUTH_NOT_SUPPORTED The LDAP server does not support strong authentication. .TP .SM LDAP_STRONG_AUTH_REQUIRED Strong authentication is required for the operation. .TP .SM LDAP_PARTIAL_RESULTS Partial results only returned. .TP .SM LDAP_NO_SUCH_ATTRIBUTE The attribute type specified does not exist in the entry. .TP .SM LDAP_UNDEFINED_TYPE The attribute type specified is invalid. .TP .SM LDAP_INAPPROPRIATE_MATCHING Filter type not supported for the specified attribute. .TP .SM LDAP_CONSTRAINT_VIOLATION An attribute value specified violates some constraint (e.g., a postalAddress has too many lines, or a line that is too long). .TP .SM LDAP_TYPE_OR_VALUE_EXISTS An attribute type or attribute value specified already exists in the entry. .TP .SM LDAP_INVALID_SYNTAX An invalid attribute value was specified. .TP .SM LDAP_NO_SUCH_OBJECT The specified object does not exist in The Directory. .TP .SM LDAP_ALIAS_PROBLEM An alias in The Directory points to a nonexistent entry. .TP .SM LDAP_INVALID_DN_SYNTAX A syntactically invalid DN was specified. .TP .SM LDAP_IS_LEAF The object specified is a leaf. .TP .SM LDAP_ALIAS_DEREF_PROBLEM A problem was encountered when dereferencing an alias. .TP .SM LDAP_INAPPROPRIATE_AUTH Inappropriate authentication was specified (e.g., LDAP_AUTH_SIMPLE was specified and the entry does not have a userPassword attribute). .TP .SM LDAP_INVALID_CREDENTIALS Invalid credentials were presented (e.g., the wrong password). .TP .SM LDAP_INSUFFICIENT_ACCESS The user has insufficient access to perform the operation. .TP .SM LDAP_BUSY The DSA is busy. .TP .SM LDAP_UNAVAILABLE The DSA is unavailable. .TP .SM LDAP_UNWILLING_TO_PERFORM The DSA is unwilling to perform the operation. .TP .SM LDAP_LOOP_DETECT A loop was detected. .TP .SM LDAP_NAMING_VIOLATION A naming violation occurred. .TP .SM LDAP_OBJECT_CLASS_VIOLATION An object class violation occurred (e.g., a "must" attribute was missing from the entry). .TP .SM LDAP_NOT_ALLOWED_ON_NONLEAF The operation is not allowed on a nonleaf object. .TP .SM LDAP_NOT_ALLOWED_ON_RDN The operation is not allowed on an RDN. .TP .SM LDAP_ALREADY_EXISTS The entry already exists. .TP .SM LDAP_NO_OBJECT_CLASS_MODS Object class modifications are not allowed. .TP .SM LDAP_OTHER An unknown error occurred. .SH API ERROR CODES This section provides a complete list of API error codes recognized by the library. Note that LDAP_SUCCESS indicates success of an API call in addition to representing the return of the LDAP \'success' resultCode. .LP .TP 20 .SM LDAP_SERVER_DOWN The LDAP library can't contact the LDAP server. .TP .SM LDAP_LOCAL_ERROR Some local error occurred. This is usually a failed dynamic memory allocation. .TP .SM LDAP_ENCODING_ERROR An error was encountered encoding parameters to send to the LDAP server. .TP .SM LDAP_DECODING_ERROR An error was encountered decoding a result from the LDAP server. .TP .SM LDAP_TIMEOUT A timelimit was exceeded while waiting for a result. .TP .SM LDAP_AUTH_UNKNOWN The authentication method specified to ldap_bind() is not known. .TP .SM LDAP_FILTER_ERROR An invalid filter was supplied to ldap_search() (e.g., unbalanced parentheses). .TP .SM LDAP_PARAM_ERROR An ldap routine was called with a bad parameter. .TP .SM LDAP_NO_MEMORY An memory allocation (e.g., malloc(3) or other dynamic memory allocator) call failed in an ldap library routine. .TP .SM LDAP_USER_CANCELED Indicates the user cancelled the operation. .TP .SM LDAP_CONNECT_ERROR Indicates a connection problem. .TP .SM LDAP_NOT_SUPPORTED Indicates the routine was called in a manner not supported by the library. .TP .SM LDAP_CONTROL_NOT_FOUND Indicates the control provided is unknown to the client library. .TP .SM LDAP_NO_RESULTS_RETURNED Indicates no results returned. .TP .SM LDAP_MORE_RESULTS_TO_RETURN Indicates more results could be returned. .TP .SM LDAP_CLIENT_LOOP Indicates the library has detected a loop in its processing. .TP .SM LDAP_REFERRAL_LIMIT_EXCEEDED Indicates the referral limit has been exceeded. .SH DEPRECATED .so Deprecated .SH SEE ALSO .BR ldap (3), .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man3/ldap_controls.3.links0000644000175000017500000000017212563404150021254 0ustar ryanryanldap_control_create.3 ldap_control_find.3 ldap_control_dup.3 ldap_controls_dup.3 ldap_control_free.3 ldap_controls_free.3 openldap-2.4.42+dfsg/doc/man/man3/ldap_open.30000644000175000017500000001333012563404150017233 0ustar ryanryan.TH LDAP_OPEN 3 "RELEASEDATE" "OpenLDAP LDVERSION" .\" $OpenLDAP$ .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_init, ldap_initialize, ldap_open \- Initialize the LDAP library and open a connection to an LDAP server .SH LIBRARY OpenLDAP LDAP (libldap, \-lldap) .SH SYNOPSIS .nf .ft B #include .LP .ft B LDAP *ldap_open(host, port) .ft char *host; int port; .LP .ft B LDAP *ldap_init(host, port) .ft char *host; int port; .LP .ft B int ldap_initialize(ldp, uri) .ft LDAP **ldp; char *uri; .LP .ft B int ldap_set_urllist_proc(ld, proc, params) .ft LDAP *ld; LDAP_URLLIST_PROC *proc; void *params; .LP .ft B int (LDAP_URLLIST_PROC)(ld, urllist, url, params); .ft LDAP *ld; LDAPURLDesc **urllist; LDAPURLDesc **url; void *params; .LP .ft B #include .LP .ft B int ldap_init_fd(fd, proto, uri, ldp) .ft ber_socket_t fd; int proto; char *uri; LDAP **ldp; .SH DESCRIPTION .LP .B ldap_open() opens a connection to an LDAP server and allocates an LDAP structure which is used to identify the connection and to maintain per-connection information. .B ldap_init() allocates an LDAP structure but does not open an initial connection. .B ldap_initialize() allocates an LDAP structure but does not open an initial connection. .B ldap_init_fd() allocates an LDAP structure using an existing connection on the provided socket. One of these routines must be called before any operations are attempted. .LP .B ldap_open() takes \fIhost\fP, the hostname on which the LDAP server is running, and \fIport\fP, the port number to which to connect. If the default IANA-assigned port of 389 is desired, LDAP_PORT should be specified for \fIport\fP. The \fIhost\fP parameter may contain a blank-separated list of hosts to try to connect to, and each host may optionally by of the form \fIhost:port\fP. If present, the \fI:port\fP overrides the \fIport\fP parameter to .BR ldap_open() . Upon successfully making a connection to an LDAP server, .B ldap_open() returns a pointer to an opaque LDAP structure, which should be passed to subsequent calls to .BR ldap_bind() , .BR ldap_search() , etc. Certain fields in the LDAP structure can be set to indicate size limit, time limit, and how aliases are handled during operations; read and write access to those fields must occur by calling .BR ldap_get_option (3) and .BR ldap_set_option (3) respectively, whenever possible. .LP .B ldap_init() acts just like .BR ldap_open() , but does not open a connection to the LDAP server. The actual connection open will occur when the first operation is attempted. .LP .B ldap_initialize() acts like .BR ldap_init() , but it returns an integer indicating either success or the failure reason, and it allows to specify details for the connection in the schema portion of the URI. The .I uri parameter may be a comma- or whitespace-separated list of URIs containing only the .IR schema , the .IR host , and the .I port fields. Apart from .BR ldap , other (non-standard) recognized values of the .I schema field are .B ldaps (LDAP over TLS), .B ldapi (LDAP over IPC), and .B cldap (connectionless LDAP). If other fields are present, the behavior is undefined. .LP At this time, .B ldap_open() and .B ldap_init() are deprecated in favor of .BR ldap_initialize() , essentially because the latter allows to specify a schema in the URI and it explicitly returns an error code. .LP .B ldap_init_fd() allows an LDAP structure to be initialized using an already-opened connection. The .I proto parameter should be one of LDAP_PROTO_TCP, LDAP_PROTO_UDP, or LDAP_PROTO_IPC for a connection using TCP, UDP, or IPC, respectively. The value LDAP_PROTO_EXT may also be specified if user-supplied sockbuf handlers are going to be used. Note that support for UDP is not implemented unless libldap was built with LDAP_CONNECTIONLESS defined. The .I uri parameter may optionally be provided for informational purposes. .LP .B ldap_set_urllist_proc() allows to set a function .I proc of type .I LDAP_URLLIST_PROC that is called when a successful connection can be established. This function receives the list of URIs parsed from the .I uri string originally passed to .BR ldap_initialize() , and the one that successfully connected. The function may manipulate the URI list; the typical use consists in moving the successful URI to the head of the list, so that subsequent attempts to connect to one of the URIs using the same LDAP handle will try it first. If .I ld is null, .I proc is set as a global parameter that is inherited by all handlers within the process that are created after the call to .BR ldap_set_urllist_proc() . By default, no .I LDAP_URLLIST_PROC is set. In a multithreaded environment, .B ldap_set_urllist_proc() must be called before any concurrent operation using the LDAP handle is started. Note: the first call into the LDAP library also initializes the global options for the library. As such the first call should be single-threaded or otherwise protected to insure that only one call is active. It is recommended that .BR ldap_get_option () or .BR ldap_set_option () be used in the program's main thread before any additional threads are created. See .BR ldap_get_option (3). .SH ERRORS If an error occurs, .B ldap_open() and .B ldap_init() will return NULL and .I errno should be set appropriately. .B ldap_initialize() and .B ldap_init_fd() will directly return the LDAP code associated to the error (or .I LDAP_SUCCESS in case of success); .I errno should be set as well whenever appropriate. .B ldap_set_urllist_proc() returns LDAP_OPT_ERROR on error, and LDAP_OPT_SUCCESS on success. .SH SEE ALSO .BR ldap (3), .BR ldap_bind (3), .BR ldap_get_option (3), .BR ldap_set_option (3), .BR lber-sockbuf (3), .BR errno (3) .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man3/ldap_schema.30000644000175000017500000002104312563404150017532 0ustar ryanryan.TH LDAP_SCHEMA 3 "RELEASEDATE" "OpenLDAP LDVERSION" .\" $OpenLDAP$ .\" Copyright 2000-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_str2syntax, ldap_syntax2str, ldap_syntax2name, ldap_syntax_free, ldap_str2matchingrule, ldap_matchingrule2str, ldap_matchingrule2name, ldap_matchingrule_free, ldap_str2attributetype, ldap_attributetype2str, ldap_attributetype2name, ldap_attributetype_free, ldap_str2objectclass, ldap_objectclass2str, ldap_objectclass2name, ldap_objectclass_free, ldap_scherr2str \- Schema definition handling routines .SH LIBRARY OpenLDAP LDAP (libldap, \-lldap) .SH SYNOPSIS .nf .ft B #include #include .LP .ft B LDAPSyntax * ldap_str2syntax(s, code, errp, flags) .ft const char * s; int * code; const char ** errp; const int flags; .LP .ft B char * ldap_syntax2str(syn) .ft const LDAPSyntax * syn; .LP .ft B const char * ldap_syntax2name(syn) .ft LDAPSyntax * syn; .LP .ft B ldap_syntax_free(syn) .ft LDAPSyntax * syn; .LP .ft B LDAPMatchingRule * ldap_str2matchingrule(s, code, errp, flags) .ft const char * s; int * code; const char ** errp; const int flags; .LP .ft B char * ldap_matchingrule2str(mr); .ft const LDAPMatchingRule * mr; .LP .ft B const char * ldap_matchingrule2name(mr) .ft LDAPMatchingRule * mr; .LP .ft B ldap_matchingrule_free(mr) .ft LDAPMatchingRule * mr; .LP .ft B LDAPAttributeType * ldap_str2attributetype(s, code, errp, flags) .ft const char * s; int * code; const char ** errp; const int flags; .LP .ft B char * ldap_attributetype2str(at) .ft const LDAPAttributeType * at; .LP .ft B const char * ldap_attributetype2name(at) .ft LDAPAttributeType * at; .LP .ft B ldap_attributetype_free(at) .ft LDAPAttributeType * at; .LP .ft B LDAPObjectClass * ldap_str2objectclass(s, code, errp, flags) .ft const char * s; int * code; const char ** errp; const int flags; .LP .ft B char * ldap_objectclass2str(oc) .ft const LDAPObjectClass * oc; .LP .ft B const char * ldap_objectclass2name(oc) .ft LDAPObjectClass * oc; .LP .ft B ldap_objectclass_free(oc) .ft LDAPObjectClass * oc; .LP .ft B char * ldap_scherr2str(code) .ft int code; .SH DESCRIPTION These routines are used to parse schema definitions in the syntax defined in RFC 4512 into structs and handle these structs. These routines handle four kinds of definitions: syntaxes, matching rules, attribute types and object classes. For each definition kind, four routines are provided. .LP .B ldap_str2xxx() takes a definition in RFC 4512 format in argument .IR s as a NUL-terminated string and returns, if possible, a pointer to a newly allocated struct of the appropriate kind. The caller is responsible for freeing the struct by calling .B ldap_xxx_free() when not needed any longer. The routine returns NULL if some problem happened. In this case, the integer pointed at by argument .IR code will receive an error code (see below the description of .B ldap_scherr2str() for an explanation of the values) and a pointer to a NUL-terminated string will be placed where requested by argument .IR errp , indicating where in argument .IR s the error happened, so it must not be freed by the caller. Argument .IR flags is a bit mask of parsing options controlling the relaxation of the syntax recognized. The following values are defined: .TP .B LDAP_SCHEMA_ALLOW_NONE strict parsing according to RFC 4512. .TP .B LDAP_SCHEMA_ALLOW_NO_OID permit definitions that do not contain an initial OID. .TP .B LDAP_SCHEMA_ALLOW_QUOTED permit quotes around some items that should not have them. .TP .B LDAP_SCHEMA_ALLOW_DESCR permit a .B descr instead of a numeric OID in places where the syntax expect the latter. .TP .B LDAP_SCHEMA_ALLOW_DESCR_PREFIX permit that the initial numeric OID contains a prefix in .B descr format. .TP .B LDAP_SCHEMA_ALLOW_ALL be very liberal, include all options. .LP The structures returned are as follows: .sp .RS .nf .ne 7 .ta 8n 16n 32n typedef struct ldap_schema_extension_item { char *lsei_name; /* Extension name */ char **lsei_values; /* Extension values */ } LDAPSchemaExtensionItem; typedef struct ldap_syntax { char *syn_oid; /* OID */ char **syn_names; /* Names */ char *syn_desc; /* Description */ LDAPSchemaExtensionItem **syn_extensions; /* Extension */ } LDAPSyntax; typedef struct ldap_matchingrule { char *mr_oid; /* OID */ char **mr_names; /* Names */ char *mr_desc; /* Description */ int mr_obsolete; /* Is obsolete? */ char *mr_syntax_oid; /* Syntax of asserted values */ LDAPSchemaExtensionItem **mr_extensions; /* Extensions */ } LDAPMatchingRule; typedef struct ldap_attributetype { char *at_oid; /* OID */ char **at_names; /* Names */ char *at_desc; /* Description */ int at_obsolete; /* Is obsolete? */ char *at_sup_oid; /* OID of superior type */ char *at_equality_oid; /* OID of equality matching rule */ char *at_ordering_oid; /* OID of ordering matching rule */ char *at_substr_oid; /* OID of substrings matching rule */ char *at_syntax_oid; /* OID of syntax of values */ int at_syntax_len; /* Suggested minimum maximum length */ int at_single_value; /* Is single-valued? */ int at_collective; /* Is collective? */ int at_no_user_mod; /* Are changes forbidden through LDAP? */ int at_usage; /* Usage, see below */ LDAPSchemaExtensionItem **at_extensions; /* Extensions */ } LDAPAttributeType; typedef struct ldap_objectclass { char *oc_oid; /* OID */ char **oc_names; /* Names */ char *oc_desc; /* Description */ int oc_obsolete; /* Is obsolete? */ char **oc_sup_oids; /* OIDs of superior classes */ int oc_kind; /* Kind, see below */ char **oc_at_oids_must; /* OIDs of required attribute types */ char **oc_at_oids_may; /* OIDs of optional attribute types */ LDAPSchemaExtensionItem **oc_extensions; /* Extensions */ } LDAPObjectClass; .ta .fi .RE .PP Some integer fields (those described with a question mark) have a truth value, for these fields the possible values are: .TP .B LDAP_SCHEMA_NO The answer to the question is no. .TP .B LDAP_SCHEMA_YES The answer to the question is yes. .LP For attribute types, the following usages are possible: .TP .B LDAP_SCHEMA_USER_APPLICATIONS the attribute type is non-operational. .TP .B LDAP_SCHEMA_DIRECTORY_OPERATION the attribute type is operational and is pertinent to the directory itself, i.e. it has the same value on all servers that master the entry containing this attribute type. .TP .B LDAP_SCHEMA_DISTRIBUTED_OPERATION the attribute type is operational and is pertinent to replication, shadowing or other distributed directory aspect. TBC. .TP .B LDAP_SCHEMA_DSA_OPERATION the attribute type is operational and is pertinent to the directory server itself, i.e. it may have different values for the same entry when retrieved from different servers that master the entry. .LP Object classes can be of three kinds: .TP .B LDAP_SCHEMA_ABSTRACT the object class is abstract, i.e. there cannot be entries of this class alone. .TP .B LDAP_SCHEMA_STRUCTURAL the object class is structural, i.e. it describes the main role of the entry. On some servers, once the entry is created the set of structural object classes assigned cannot be changed: none of those present can be removed and none other can be added. .TP .B LDAP_SCHEMA_AUXILIARY the object class is auxiliary, i.e. it is intended to go with other, structural, object classes. These can be added or removed at any time if attribute types are added or removed at the same time as needed by the set of object classes resulting from the operation. .LP Routines .B ldap_xxx2name() return a canonical name for the definition. .LP Routines .B ldap_xxx2str() return a string representation in the format described by RFC 4512 of the struct passed in the argument. The string is a newly allocated string that must be freed by the caller. These routines may return NULL if no memory can be allocated for the string. .LP .B ldap_scherr2str() returns a NUL-terminated string with a text description of the error found. This is a pointer to a static area, so it must not be freed by the caller. The argument .IR code comes from one of the parsing routines and can adopt the following values: .TP .B LDAP_SCHERR_OUTOFMEM Out of memory. .TP .B LDAP_SCHERR_UNEXPTOKEN Unexpected token. .TP .B LDAP_SCHERR_NOLEFTPAREN Missing opening parenthesis. .TP .B LDAP_SCHERR_NORIGHTPAREN Missing closing parenthesis. .TP .B LDAP_SCHERR_NODIGIT Expecting digit. .TP .B LDAP_SCHERR_BADNAME Expecting a name. .TP .B LDAP_SCHERR_BADDESC Bad description. .TP .B LDAP_SCHERR_BADSUP Bad superiors. .TP .B LDAP_SCHERR_DUPOPT Duplicate option. .TP .B LDAP_SCHERR_EMPTY Unexpected end of data. .SH SEE ALSO .BR ldap (3) .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man3/lber-memory.30000644000175000017500000000243612563404150017531 0ustar ryanryan.TH LBER_MEMORY 3 "RELEASEDATE" "OpenLDAP LDVERSION" .\" $OpenLDAP$ .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ber_memalloc, ber_memcalloc, ber_memrealloc, ber_memfree, ber_memvfree \- OpenLDAP LBER memory allocators .SH LIBRARY OpenLDAP LBER (liblber, \-llber) .SH SYNOPSIS .B #include .LP .BI "void *ber_memalloc(ber_len_t " bytes ");" .LP .BI "void *ber_memcalloc(ber_len_t " nelems ", ber_len_t " bytes ");" .LP .BI "void *ber_memrealloc(void *" ptr ", ber_len_t " bytes ");" .LP .BI "void ber_memfree(void *" ptr ");" .LP .BI "void ber_memvfree(void **" vec ");" .SH DESCRIPTION .LP These routines are used to allocate/deallocate memory used/returned by the Lightweight BER library as required by .BR lber-encode (3) and .BR lber-decode (3). .BR ber_memalloc (), .BR ber_memcalloc (), .BR ber_memrealloc (), and .BR ber_memfree () are used exactly like the standard .BR malloc (3), .BR calloc (3), .BR realloc (3), and .BR free (3) routines, respectively. The .BR ber_memvfree () routine is used to free a dynamically allocated array of pointers to arbitrary dynamically allocated objects. .SH SEE ALSO .BR lber-decode (3), .BR lber-encode (3), .BR lber-types (3) .LP .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man3/ldap_modify.30000644000175000017500000000737612563404150017576 0ustar ryanryan.TH LDAP_MODIFY 3 "RELEASEDATE" "OpenLDAP LDVERSION" .\" $OpenLDAP$ .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_modify_ext, ldap_modify_ext_s \- Perform an LDAP modify operation .SH LIBRARY OpenLDAP LDAP (libldap, \-lldap) .SH SYNOPSIS .nf .ft B #include .LP .ft B int ldap_modify_ext( .RS .ft B LDAP *\fIld\fB, char *\fIdn\fB, LDAPMod *\fImods[]\fB, LDAPControl **\fIsctrls\fB, LDAPControl **\fIcctrls\fB, int *\fImsgidp\fB ); .RE .LP .nf .ft B int ldap_modify_ext_s( .RS .ft B LDAP *\fIld\fB, char *\fIdn\fB, LDAPMod *\fImods[]\fB, LDAPControl **\fIsctrls\fB, LDAPControl **\fIcctrls\fB ); .RE .LP .nf .ft B void ldap_mods_free( .RS .ft B LDAPMod **\fImods\fB, int \fIfreemods\fB ); .RE .SH DESCRIPTION The routine .B ldap_modify_ext_s() is used to perform an LDAP modify operation. \fIdn\fP is the DN of the entry to modify, and \fImods\fP is a null-terminated array of modifications to make to the entry. Each element of the \fImods\fP array is a pointer to an LDAPMod structure, which is defined below. .LP .nf typedef struct ldapmod { int mod_op; char *mod_type; union { char **modv_strvals; struct berval **modv_bvals; } mod_vals; struct ldapmod *mod_next; } LDAPMod; #define mod_values mod_vals.modv_strvals #define mod_bvalues mod_vals.modv_bvals .ft .fi .LP The \fImod_op\fP field is used to specify the type of modification to perform and should be one of LDAP_MOD_ADD, LDAP_MOD_DELETE, or LDAP_MOD_REPLACE. The \fImod_type\fP and \fImod_values\fP fields specify the attribute type to modify and a null-terminated array of values to add, delete, or replace respectively. The \fImod_next\fP field is used only by the LDAP server and may be ignored by the client. .LP If you need to specify a non-string value (e.g., to add a photo or audio attribute value), you should set \fImod_op\fP to the logical OR of the operation as above (e.g., LDAP_MOD_REPLACE) and the constant LDAP_MOD_BVALUES. In this case, \fImod_bvalues\fP should be used instead of \fImod_values\fP, and it should point to a null-terminated array of struct bervals, as defined in . .LP For LDAP_MOD_ADD modifications, the given values are added to the entry, creating the attribute if necessary. For LDAP_MOD_DELETE modifications, the given values are deleted from the entry, removing the attribute if no values remain. If the entire attribute is to be deleted, the \fImod_values\fP field should be set to NULL. For LDAP_MOD_REPLACE modifications, the attribute will have the listed values after the modification, having been created if necessary. All modifications are performed in the order in which they are listed. .LP .B ldap_mods_free() can be used to free each element of a NULL-terminated array of mod structures. If \fIfreemods\fP is non-zero, the \fImods\fP pointer itself is freed as well. .LP .B ldap_modify_ext_s() returns a code indicating success or, in the case of failure, indicating the nature of the failure. See .BR ldap_error (3) for details .LP The .B ldap_modify_ext() operation works the same way as .BR ldap_modify_ext_s() , except that it is asynchronous. The integer that \fImsgidp\fP points to is set to the message id of the modify request. The result of the operation can be obtained by calling .BR ldap_result (3). .LP Both .B ldap_modify_ext() and .B ldap_modify_ext_s() allows server and client controls to be passed in via the sctrls and cctrls parameters, respectively. .SH DEPRECATED INTERFACES The .B ldap_modify() and .B ldap_modify_s() routines are deprecated in favor of the .B ldap_modify_ext() and .B ldap_modify_ext_s() routines, respectively. .LP .so Deprecated .SH SEE ALSO .BR ldap (3), .BR ldap_error (3), .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man3/ldap_search.30000644000175000017500000001065212563404150017543 0ustar ryanryan.TH LDAP_SEARCH 3 "RELEASEDATE" "OpenLDAP LDVERSION" .\" $OpenLDAP$ .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_search, ldap_search_s, ldap_search_st, ldap_search_ext, ldap_search_ext_s \- Perform an LDAP search operation .SH LIBRARY OpenLDAP LDAP (libldap, \-lldap) .SH SYNOPSIS .nf .ft B #include #include .LP .ft B int ldap_search_ext( .RS LDAP *\fIld\fB, char *\fIbase\fB, int \fIscope\fB, char *\fIfilter\fB, char *\fIattrs\fB[], int \fIattrsonly\fB, LDAPControl **\fIserverctrls\fB, LDAPControl **\fIclientctrls\fB, struct timeval *\fItimeout\fB, int \fIsizelimit\fB, int *\fImsgidp\fB ); .RE .LP .ft B int ldap_search_ext_s( .RS LDAP *\fIld\fB, char *\fIbase\fB, int \fIscope\fB, char *\fIfilter\fB, char *\fIattrs\fB[], int \fIattrsonly\fB, LDAPControl **\fIserverctrls\fB, LDAPControl **\fIclientctrls\fB, struct timeval *\fItimeout\fB, int \fIsizelimit\fB, LDAPMessage **\fIres\fB ); .RE .SH DESCRIPTION These routines are used to perform LDAP search operations. The .B ldap_search_ext_s() routine does the search synchronously (i.e., not returning until the operation completes), providing a pointer to the resulting LDAP messages at the location pointed to by the \fIres\fP parameter. .LP The .B ldap_search_ext() routine is the asynchronous version, initiating the search and returning the message id of the operation it initiated in the integer pointed to by the \fImsgidp\fP parameter. .LP The \fIbase\fP parameter is the DN of the entry at which to start the search. .LP The \fIscope\fP parameter is the scope of the search and should be one of LDAP_SCOPE_BASE, to search the object itself, LDAP_SCOPE_ONELEVEL, to search the object's immediate children, LDAP_SCOPE_SUBTREE, to search the object and all its descendants, or LDAP_SCOPE_CHILDREN, to search all of the descendants. Note that the latter requires the server support the LDAP Subordinates Search Scope extension. .LP The \fIfilter\fP is a string representation of the filter to apply in the search. The string should conform to the format specified in RFC 4515 as extended by RFC 4526. For instance, "(cn=Jane Doe)". Note that use of the extension requires the server to support the LDAP Absolute True/False Filter extension. NULL may be specified to indicate the library should send the filter (objectClass=*). .LP The \fIattrs\fP parameter is a null-terminated array of attribute descriptions to return from matching entries. If NULL is specified, the return of all user attributes is requested. The description "*" (LDAP_ALL_USER_ATTRIBUTES) may be used to request all user attributes to be returned. The description "+"(LDAP_ALL_OPERATIONAL_ATTRIBUTES) may be used to request all operational attributes to be returned. Note that this requires the server to support the LDAP All Operational Attribute extension. To request no attributes, the description "1.1" (LDAP_NO_ATTRS) should be listed by itself. .LP The \fIattrsonly\fP parameter should be set to a non-zero value if only attribute descriptions are wanted. It should be set to zero (0) if both attributes descriptions and attribute values are wanted. .LP The \fIserverctrls\fP and \fIclientctrls\fP parameters may be used to specify server and client controls, respectively. .LP The .B ldap_search_ext_s() routine is the synchronous version of .BR ldap_search_ext(). .LP It also returns a code indicating success or, in the case of failure, indicating the nature of the failure of the operation. See .BR ldap_error (3) for details. .SH NOTES Note that both read and list functionality are subsumed by these routines, by using a filter like "(objectclass=*)" and a scope of LDAP_SCOPE_BASE (to emulate read) or LDAP_SCOPE_ONELEVEL (to emulate list). .LP These routines may dynamically allocate memory. The caller is responsible for freeing such memory using supplied deallocation routines. Return values are contained in . .LP Note that \fIres\fR parameter of .B ldap_search_ext_s() and .B ldap_search_s() should be freed with .B ldap_msgfree() regardless of return value of these functions. .SH DEPRECATED INTERFACES The .B ldap_search() routine is deprecated in favor of the .B ldap_search_ext() routine. The .B ldap_search_s() and .B ldap_search_st() routines are deprecated in favor of the .B ldap_search_ext_s() routine. .LP .so Deprecated .SH SEE ALSO .BR ldap (3), .BR ldap_result (3), .BR ldap_error (3) .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man3/ldap_extended_operation.3.links0000644000175000017500000000003512563404150023267 0ustar ryanryanldap_extended_operation_s.3 openldap-2.4.42+dfsg/doc/man/man3/ldap_delete.3.links0000644000175000017500000000006612563404150020655 0ustar ryanryanldap_delete_s.3 ldap_delete_ext.3 ldap_delete_ext_s.3 openldap-2.4.42+dfsg/doc/man/man3/ldap_parse_result.30000644000175000017500000000730512563404150021007 0ustar ryanryan.TH LDAP_PARSE_RESULT 3 "RELEASEDATE" "OpenLDAP LDVERSION" .\" $OpenLDAP$ .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_parse_result \- Parsing results .SH LIBRARY OpenLDAP LDAP (libldap, \-lldap) .SH SYNOPSIS .nf .ft B #include .LP .ft B int ldap_parse_result( LDAP *ld, LDAPMessage *result, int *errcodep, char **matcheddnp, char **errmsgp, char ***referralsp, LDAPControl ***serverctrlsp, int freeit ) .LP .ft B int ldap_parse_sasl_bind_result( LDAP *ld, LDAPMessage *result, struct berval **servercredp, int freeit ) .LP .ft B int ldap_parse_extended_result( LDAP *ld, LDAPMessage *result, char **retoidp, struct berval **retdatap, int freeit ) .SH DESCRIPTION .LP These routines are used to extract information from a result message. They will operate on the first result message in a chain of search results (skipping past other message types). They take the \fIresult\fP as returned by a call to .BR ldap_result (3), .BR ldap_search_s (3) or .BR ldap_search_st (3). In addition to .BR ldap_parse_result() , the routines .B ldap_parse_sasl_bind_result() and .B ldap_parse_extended_result() are used to get all the result information from SASL bind and extended operations. .LP The \fIerrcodep\fP parameter will be filled in with the result code from the result message. .LP The server might supply a matched DN string in the message indicating how much of a name in a request was recognized. The \fImatcheddnp\fP parameter will be filled in with this string if supplied, else it will be NULL. If a string is returned, it should be freed using .BR ldap_memfree (3). .LP The \fIerrmsgp\fP parameter will be filled in with the error message field from the parsed message. This string should be freed using .BR ldap_memfree (3). .LP The \fIreferralsp\fP parameter will be filled in with an allocated array of referral strings from the parsed message. This array should be freed using .BR ldap_memvfree (3). If no referrals were returned, \fI*referralsp\fP is set to NULL. .LP The \fIserverctrlsp\fP parameter will be filled in with an allocated array of controls copied from the parsed message. The array should be freed using .BR ldap_controls_free (3). If no controls were returned, \fI*serverctrlsp\fP is set to NULL. .LP The \fIfreeit\fP parameter determines whether the parsed message is freed or not after the extraction. Any non-zero value will make it free the message. The .BR ldap_msgfree (3) routine can also be used to free the message later. .LP For SASL bind results, the \fIservercredp\fP parameter will be filled in with an allocated berval structure containing the credentials from the server if present. The structure should be freed using .BR ber_bvfree (3). .LP For extended results, the \fIretoidp\fP parameter will be filled in with the dotted-OID text representation of the name of the extended operation response. The string should be freed using .BR ldap_memfree (3). If no OID was returned, \fI*retoidp\fP is set to NULL. .LP For extended results, the \fIretdatap\fP parameter will be filled in with a pointer to a berval structure containing the data from the extended operation response. The structure should be freed using .BR ber_bvfree (3). If no data were returned, \fI*retdatap\fP is set to NULL. .LP For all the above result parameters, NULL values can be used in calls in order to ignore certain fields. .SH ERRORS Upon success LDAP_SUCCESS is returned. Otherwise the values of the result parameters are undefined. .SH SEE ALSO .BR ldap (3), .BR ldap_result (3), .BR ldap_search (3), .BR ldap_memfree (3), .BR ldap_memvfree (3), .BR ldap_get_values (3), .BR ldap_controls_free (3), .BR lber-types (3) .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man3/ldap_bind.30000644000175000017500000002653612563404150017222 0ustar ryanryan.TH LDAP_BIND 3 "RELEASEDATE" "OpenLDAP LDVERSION" .\" $OpenLDAP$ .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_bind, ldap_bind_s, ldap_simple_bind, ldap_simple_bind_s, ldap_sasl_bind, ldap_sasl_bind_s, ldap_sasl_interactive_bind_s, ldap_parse_sasl_bind_result, ldap_unbind, ldap_unbind_s, ldap_unbind_ext, ldap_unbind_ext_s, ldap_set_rebind_proc \- LDAP bind routines .SH LIBRARY OpenLDAP LDAP (libldap, \-lldap) .SH SYNOPSIS .nf .B #include .LP .BI "int ldap_bind(LDAP *" ld ", const char *" who ", const char *" cred "," .RS .BI "int " method ");" .RE .LP .BI "int ldap_bind_s(LDAP *" ld ", const char *" who ", const char *" cred "," .RS .BI "int " method ");" .RE .LP .BI "int ldap_simple_bind(LDAP *" ld ", const char *" who ", const char *" passwd ");" .LP .BI "int ldap_simple_bind_s(LDAP *" ld ", const char *" who ", const char *" passwd ");" .LP .BI "int ldap_sasl_bind(LDAP *" ld ", const char *" dn ", const char *" mechanism "," .RS .BI "struct berval *" cred ", LDAPControl *" sctrls "[]," .BI "LDAPControl *" cctrls "[], int *" msgidp ");" .RE .LP .BI "int ldap_sasl_bind_s(LDAP *" ld ", const char *" dn ", const char *" mechanism "," .RS .BI "struct berval *" cred ", LDAPControl *" sctrls "[]," .BI "LDAPControl *" cctrls "[], struct berval **" servercredp ");" .RE .LP .BI "int ldap_parse_sasl_bind_result(LDAP *" ld ", LDAPMessage *" res "," .RS .BI "struct berval **" servercredp ", int " freeit ");" .RE .LP .BI "int ldap_sasl_interactive_bind_s(LDAP *" ld ", const char *" dn "," .RS .BI "const char *" mechs "," .BI "LDAPControl *" sctrls "[], LDAPControl *" cctrls "[]," .BI "unsigned " flags ", LDAP_SASL_INTERACT_PROC *" interact "," .BI "void *" defaults ");" .RE .LP .BI "int ldap_sasl_interactive_bind(LDAP *" ld ", const char *" dn "," .RS .BI "const char *" mechs "," .BI "LDAPControl *" sctrls "[], LDAPControl *" cctrls "[]," .BI "unsigned " flags ", LDAP_SASL_INTERACT_PROC *" interact "," .BI "void *" defaults ", LDAPMessage *" result "," .BI "const char **" rmechp ", int *" msgidp ");" .RE .LP .BI "int (LDAP_SASL_INTERACT_PROC)(LDAP *" ld ", unsigned " flags ", void *" defaults ", void *" sasl_interact ");" .LP .BI "int ldap_unbind(LDAP *" ld ");" .LP .BI "int ldap_unbind_s(LDAP *" ld ");" .LP .BI "int ldap_unbind_ext(LDAP *" ld ", LDAPControl *" sctrls "[]," .RS .BI "LDAPControl *" cctrls "[]);" .RE .LP .BI "int ldap_unbind_ext_s(LDAP *" ld ", LDAPControl *" sctrls "[]," .RS .BI "LDAPControl *" cctrls "[]);" .RE .LP .BI "int ldap_set_rebind_proc (LDAP *" ld ", LDAP_REBIND_PROC *" ldap_proc ", void *" params ");" .LP .BI "int (LDAP_REBIND_PROC)(LDAP *" ld ", LDAP_CONST char *" url ", ber_tag_t " request ", ber_int_t " msgid ", void *" params ");" .SH DESCRIPTION .LP These routines provide various interfaces to the LDAP bind operation. After an association with an LDAP server is made using .BR ldap_init (3), an LDAP bind operation should be performed before other operations are attempted over the connection. An LDAP bind is required when using Version 2 of the LDAP protocol; it is optional for Version 3 but is usually needed due to security considerations. .LP There are three types of bind calls, ones providing simple authentication, ones providing SASL authentication, and general routines capable of doing either simple or SASL authentication. .LP .B SASL (Simple Authentication and Security Layer) can negotiate one of many different kinds of authentication. Both synchronous and asynchronous versions of each variant of the bind call are provided. All routines take \fIld\fP as their first parameter, as returned from .BR ldap_init (3). .SH SIMPLE AUTHENTICATION The simplest form of the bind call is .BR ldap_simple_bind_s() . It takes the DN to bind as in \fIwho\fP, and the userPassword associated with the entry in \fIpasswd\fP. It returns an LDAP error indication (see .BR ldap_error (3)). The .B ldap_simple_bind() call is asynchronous, taking the same parameters but only initiating the bind operation and returning the message id of the request it sent. The result of the operation can be obtained by a subsequent call to .BR ldap_result (3). .SH GENERAL AUTHENTICATION The .B ldap_bind() and .B ldap_bind_s() routines can be used when the authentication method to use needs to be selected at runtime. They both take an extra \fImethod\fP parameter selecting the authentication method to use. It should be set to LDAP_AUTH_SIMPLE to select simple authentication. .B ldap_bind() returns the message id of the request it initiates. .B ldap_bind_s() returns an LDAP error indication. .SH SASL AUTHENTICATION For SASL binds the server always ignores any provided DN, so the .I dn parameter should always be NULL. .BR ldap_sasl_bind_s () sends a single SASL bind request with the given SASL .I mechanism and credentials in the .I cred parameter. The format of the credentials depends on the particular SASL mechanism in use. For mechanisms that provide mutual authentication the server's credentials will be returned in the .I servercredp parameter. The routine returns an LDAP error indication (see .BR ldap_error (3)). The .BR ldap_sasl_bind () call is asynchronous, taking the same parameters but only sending the request and returning the message id of the request it sent. The result of the operation can be obtained by a subsequent call to .BR ldap_result (3). The result must be additionally parsed by .BR ldap_parse_sasl_bind_result () to obtain any server credentials sent from the server. .LP Many SASL mechanisms require multiple message exchanges to perform a complete authentication. Applications should generally use .BR ldap_sasl_interactive_bind_s () rather than calling the basic .BR ldap_sasl_bind () functions directly. The .I mechs parameter should contain a space-separated list of candidate mechanisms to use. If this parameter is NULL or empty the library will query the supportedSASLMechanisms attribute from the server's rootDSE for the list of SASL mechanisms the server supports. The .I flags parameter controls the interaction used to retrieve any necessary SASL authentication parameters and should be one of: .TP LDAP_SASL_AUTOMATIC use defaults if available, prompt otherwise .TP LDAP_SASL_INTERACTIVE always prompt .TP LDAP_SASL_QUIET never prompt .LP The .I interact function uses the provided .I defaults to handle requests from the SASL library for particular authentication parameters. There is no defined format for the .I defaults information; it is up to the caller to use whatever format is appropriate for the supplied .I interact function. The .I sasl_interact parameter comes from the underlying SASL library. When used with Cyrus SASL this is an array of .B sasl_interact_t structures. The Cyrus SASL library will prompt for a variety of inputs, including: .TP SASL_CB_GETREALM the realm for the authentication attempt .TP SASL_CB_AUTHNAME the username to authenticate .TP SASL_CB_PASS the password for the provided username .TP SASL_CB_USER the username to use for proxy authorization .TP SASL_CB_NOECHOPROMPT generic prompt for input with input echoing disabled .TP SASL_CB_ECHOPROMPT generic prompt for input with input echoing enabled .TP SASL_CB_LIST_END indicates the end of the array of prompts .LP See the Cyrus SASL documentation for more details. .LP Applications which need to manage connections asynchronously may use .BR ldap_sasl_interactive_bind () instead of the synchronous version. A valid mechs parameter must be supplied, otherwise the library will be forced to query the server for a list of supported mechanisms, and this query will be performed synchronously. The other parameters are the same as for the synchronous function, with three additional parameters. The actual SASL mechanism that was used, and the message ID for use with .BR ldap_result () will be returned in rmechp and msgidp, respectively. The value in rmechp must not be modified by the caller and must be passed back on each subsequent call. The message obtained from .BR ldap_result () must be passed in the result parameter. This parameter must be NULL when initiating a new Bind. The caller must free the result message after each call using .BR ldap_msgfree (). The .BR ldap_sasl_interactive_bind () function returns an LDAP result code. If the code is LDAP_SASL_BIND_IN_PROGRESS then the Bind is not complete yet, and this function must be called again with the next result from the server. .SH REBINDING .LP The .B ldap_set_rebind_proc function() sets the process to use for binding when an operation returns a referral. This function is used when an application needs to bind to another server in order to follow a referral or search continuation reference. .LP The function takes \fIld\fP, the \fIrebind\fP function, and the \fIparams\fP, the arbitrary data like state information which the client might need to properly rebind. The LDAP_OPT_REFERRALS option in the \fIld\fP must be set to ON for the libraries to use the rebind function. Use the .BR ldap_set_option function to set the value. .LP The rebind function parameters are as follows: .LP The \fIld\fP parameter must be used by the application when binding to the referred server if the application wants the libraries to follow the referral. .LP The \fIurl\fP parameter points to the URL referral string received from the LDAP server. The LDAP application can use the .BR ldap_url_parse (3) function to parse the string into its components. .LP The \fIrequest\fP parameter specifies the type of request that generated the referral. .LP The \fImsgid\fP parameter specifies the message ID of the request generating the referral. .LP The \fIparams\fP parameter is the same value as passed originally to the .BR ldap_set_rebind_proc () function. .LP The LDAP libraries set all the parameters when they call the rebind function. The application should not attempt to free either the ld or the url structures in the rebind function. .LP The application must supply to the rebind function the required authentication information such as, user name, password, and certificates. The rebind function must use a synchronous bind method. .SH UNBINDING The .B ldap_unbind() call is used to unbind from the directory, terminate the current association, and free the resources contained in the \fIld\fP structure. Once it is called, the connection to the LDAP server is closed, and the \fIld\fP structure is invalid. The .B ldap_unbind_s() call is just another name for .BR ldap_unbind() ; both of these calls are synchronous in nature. .LP The .B ldap_unbind_ext() and .B ldap_unbind_ext_s() allows the operations to specify controls. .SH ERRORS Asynchronous routines will return \-1 in case of error, setting the \fIld_errno\fP parameter of the \fIld\fP structure. Synchronous routines return whatever \fIld_errno\fP is set to. See .BR ldap_error (3) for more information. .SH NOTES If an anonymous bind is sufficient for the application, the rebind process need not be provided. The LDAP libraries with the LDAP_OPT_REFERRALS option set to ON (default value) will automatically follow referrals using an anonymous bind. .LP If the application needs stronger authentication than an anonymous bind, you need to provide a rebind process for that authentication method. The bind method must be synchronous. .SH SEE ALSO .BR ldap (3), .BR ldap_error (3), .BR ldap_open (3), .BR ldap_set_option (3), .BR ldap_url_parse (3) .B RFC 4422 (http://www.rfc-editor.org), .B Cyrus SASL (http://asg.web.cmu.edu/sasl/) .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man3/ldap_first_entry.3.links0000644000175000017500000000004712563404150021762 0ustar ryanryanldap_next_entry.3 ldap_count_entries.3 openldap-2.4.42+dfsg/doc/man/man3/lber-types.30000644000175000017500000001420712563404150017364 0ustar ryanryan.TH LBER_TYPES 3 "RELEASEDATE" "OpenLDAP LDVERSION" .\" $OpenLDAP$ .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ber_int_t, ber_uint_t, ber_len_t, ber_slen_t, ber_tag_t, struct berval, BerValue, BerVarray, BerElement, ber_bvfree, ber_bvecfree, ber_bvecadd, ber_bvarray_free, ber_bvarray_add, ber_bvdup, ber_dupbv, ber_bvstr, ber_bvstrdup, ber_str2bv, ber_alloc_t, ber_init, ber_init2, ber_free \- OpenLDAP LBER types and allocation functions .SH LIBRARY OpenLDAP LBER (liblber, \-llber) .SH SYNOPSIS .B #include .LP .nf .ft B typedef impl_tag_t ber_tag_t; typedef impl_int_t ber_int_t; typedef impl_uint_t ber_uint_t; typedef impl_len_t ber_len_t; typedef impl_slen_t ber_slen_t; typedef struct berval { ber_len_t bv_len; char *bv_val; } BerValue, *BerVarray; typedef struct berelement BerElement; .ft .fi .LP .BI "void ber_bvfree(struct berval *" bv ");" .LP .BI "void ber_bvecfree(struct berval **" bvec ");" .LP .BI "void ber_bvecadd(struct berval ***" bvec ", struct berval *" bv ");" .LP .BI "void ber_bvarray_free(struct berval *" bvarray ");" .LP .BI "void ber_bvarray_add(BerVarray *" bvarray ", BerValue *" bv ");" .LP .BI "struct berval *ber_bvdup(const struct berval *" bv ");" .LP .BI "struct berval *ber_dupbv(const struct berval *" dst ", struct berval *" src ");" .LP .BI "struct berval *ber_bvstr(const char *" str ");" .LP .BI "struct berval *ber_bvstrdup(const char *" str ");" .LP .BI "struct berval *ber_str2bv(const char *" str ", ber_len_t " len ", int " dup ", struct berval *" bv ");" .LP .BI "BerElement *ber_alloc_t(int " options ");" .LP .BI "BerElement *ber_init(struct berval *" bv ");" .LP .BI "void ber_init2(BerElement *" ber ", struct berval *" bv ", int " options ");" .LP .BI "void ber_free(BerElement *" ber ", int " freebuf ");" .SH DESCRIPTION .LP The following are the basic types and structures defined for use with the Lightweight BER library. .LP .B ber_int_t is a signed integer of at least 32 bits. It is commonly equivalent to .BR int . .B ber_uint_t is the unsigned variant of .BR ber_int_t . .LP .B ber_len_t is an unsigned integer of at least 32 bits used to represent a length. It is commonly equivalent to a .BR size_t . .B ber_slen_t is the signed variant to .BR ber_len_t . .LP .B ber_tag_t is an unsigned integer of at least 32 bits used to represent a BER tag. It is commonly equivalent to a .BR unsigned\ long . .LP The actual definitions of the integral impl_TYPE_t types are platform specific. .LP .BR BerValue , commonly used as .BR struct\ berval , is used to hold an arbitrary sequence of octets. .B bv_val points to .B bv_len octets. .B bv_val is not necessarily terminated by a NULL (zero) octet. .BR ber_bvfree () frees a BerValue, pointed to by \fIbv\fP, returned from this API. If \fIbv\fP is NULL, the routine does nothing. .LP .BR ber_bvecfree () frees an array of BerValues (and the array), pointed to by \fIbvec\fP, returned from this API. If \fIbvec\fP is NULL, the routine does nothing. .BR ber_bvecadd () appends the \fIbv\fP pointer to the \fIbvec\fP array. Space for the array is allocated as needed. The end of the array is marked by a NULL pointer. .LP .BR ber_bvarray_free () frees an array of BerValues (and the array), pointed to by \fIbvarray\fP, returned from this API. If \fIbvarray\fP is NULL, the routine does nothing. .BR ber_bvarray_add () appends the contents of the BerValue pointed to by \fIbv\fP to the \fIbvarray\fP array. Space for the new element is allocated as needed. The end of the array is marked by a BerValue with a NULL bv_val field. .LP .BR ber_bvdup () returns a copy of a BerValue. The routine returns NULL upon error (e.g. out of memory). The caller should use .BR ber_bvfree () to deallocate the resulting BerValue. .BR ber_dupbv () copies a BerValue from \fIsrc\fP to \fIdst\fP. If \fIdst\fP is NULL a new BerValue will be allocated to hold the copy. The routine returns NULL upon error, otherwise it returns a pointer to the copy. If \fIdst\fP is NULL the caller should use .BR ber_bvfree () to deallocate the resulting BerValue, otherwise .BR ber_memfree () should be used to deallocate the \fIdst->bv_val\fP. (The .BR ber_bvdup () function is internally implemented as ber_dupbv(NULL, bv). .BR ber_bvdup () is provided only for compatibility with an expired draft of the LDAP C API; .BR ber_dupbv () is the preferred interface.) .LP .BR ber_bvstr () returns a BerValue containing the string pointed to by \fIstr\fP. .BR ber_bvstrdup () returns a BerValue containing a copy of the string pointed to by \fIstr\fP. .BR ber_str2bv () returns a BerValue containing the string pointed to by \fIstr\fP, whose length may be optionally specified in \fIlen\fP. If \fIdup\fP is non-zero, the BerValue will contain a copy of \fIstr\fP. If \fIlen\fP is zero, the number of bytes to copy will be determined by .BR strlen (3), otherwise \fIlen\fP bytes will be copied. If \fIbv\fP is non-NULL, the result will be stored in the given BerValue, otherwise a new BerValue will be allocated to store the result. NOTE: Both .BR ber_bvstr () and .BR ber_bvstrdup () are implemented as macros using .BR ber_str2bv () in this version of the library. .LP .B BerElement is an opaque structure used to maintain state information used in encoding and decoding. .BR ber_alloc_t () is used to create an empty BerElement structure. If .B LBER_USE_DER is specified for the .I options parameter then data lengths for data written to the BerElement will be encoded in the minimal number of octets required, otherwise they will always be written as four byte values. .BR ber_init () creates a BerElement structure that is initialized with a copy of the data in its .I bv parameter. .BR ber_init2 () initializes an existing BerElement .I ber using the data in the .I bv parameter. The data is referenced directly, not copied. The .I options parameter is the same as for .BR ber_alloc_t (). .BR ber_free () frees a BerElement pointed to by \fIber\fP. If \fIber\fP is NULL, the routine does nothing. If \fIfreebuf\fP is zero, the internal buffer is not freed. .SH SEE ALSO .BR lber-encode (3), .BR lber-decode (3), .BR lber-memory (3) .LP .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man3/ldap_modrdn.3.links0000644000175000017500000000006012563404150020670 0ustar ryanryanldap_modrdn_s.3 ldap_modrdn2.3 ldap_modrdn2_s.3 openldap-2.4.42+dfsg/doc/man/man3/ldap_memory.30000644000175000017500000000246212563404150017606 0ustar ryanryan.TH LDAP_MEMORY 3 "RELEASEDATE" "OpenLDAP LDVERSION" .\" $OpenLDAP$ .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_memfree, ldap_memvfree, ldap_memalloc, ldap_memcalloc, ldap_memrealloc, ldap_strdup \- LDAP memory allocation routines .SH LIBRARY OpenLDAP LDAP (libldap, \-lldap) .SH SYNOPSIS .B #include .LP .BI "void ldap_memfree(void *" p ");" .LP .BI "void ldap_memvfree(void **" v ");" .LP .BI "void *ldap_memalloc(ber_len_t " s ");" .LP .BI "void *ldap_memcalloc(ber_len_t " n ", ber_len_t " s ");" .LP .BI "void *ldap_memrealloc(void *" p ", ber_len_t " s ");" .LP .BI "char *ldap_strdup(LDAP_CONST char *" p ");" .SH DESCRIPTION These routines are used to allocate/deallocate memory used/returned by the LDAP library. .BR ldap_memalloc (), .BR ldap_memcalloc (), .BR ldap_memrealloc (), and .BR ldap_memfree () are used exactly like the standard .BR malloc (3), .BR calloc (3), .BR realloc (3), and .BR free (3) routines, respectively. The .BR ldap_memvfree () routine is used to free a dynamically allocated array of pointers to arbitrary dynamically allocated objects. The .BR ldap_strdup () routine is used exactly like the standard .BR strdup (3) routine. .SH SEE ALSO .BR ldap (3) .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man3/lber-encode.30000644000175000017500000002151312563404150017453 0ustar ryanryan.TH LBER_ENCODE 3 "RELEASEDATE" "OpenLDAP LDVERSION" .\" $OpenLDAP$ .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ber_alloc_t, ber_flush, ber_flush2, ber_printf, ber_put_int, ber_put_enum, ber_put_ostring, ber_put_string, ber_put_null, ber_put_boolean, ber_put_bitstring, ber_start_seq, ber_start_set, ber_put_seq, ber_put_set \- OpenLDAP LBER simplified Basic Encoding Rules library routines for encoding .SH LIBRARY OpenLDAP LBER (liblber, \-llber) .SH SYNOPSIS .B #include .LP .BI "BerElement *ber_alloc_t(int " options ");" .LP .BI "int ber_flush(Sockbuf *" sb ", BerElement *" ber ", int " freeit ");" .LP .BI "int ber_flush2(Sockbuf *" sb ", BerElement *" ber ", int " freeit ");" .LP .BI "int ber_printf(BerElement *" ber ", const char *" fmt ", ...);" .LP .BI "int ber_put_int(BerElement *" ber ", ber_int_t " num ", ber_tag_t " tag ");" .LP .BI "int ber_put_enum(BerElement *" ber ", ber_int_t " num ", ber_tag_t " tag ");" .LP .BI "int ber_put_ostring(BerElement *" ber ", const char *" str ", ber_len_t " len ", ber_tag_t " tag ");" .LP .BI "int ber_put_string(BerElement *" ber ", const char *" str ", ber_tag_t " tag ");" .LP .BI "int ber_put_null(BerElement *" ber ", ber_tag_t " tag ");" .LP .BI "int ber_put_boolean(BerElement *" ber ", ber_int_t " bool ", ber_tag_t " tag ");" .LP .BI "int ber_put_bitstring(BerElement *" ber ", const char *" str ", ber_len_t " blen ", ber_tag_t " tag ");" .LP .BI "int ber_start_seq(BerElement *" ber ", ber_tag_t " tag ");" .LP .BI "int ber_start_set(BerElement *" ber ", ber_tag_t " tag ");" .LP .BI "int ber_put_seq(BerElement *" ber ");" .LP .BI "int ber_put_set(BerElement *" ber ");" .SH DESCRIPTION .LP These routines provide a subroutine interface to a simplified implementation of the Basic Encoding Rules of ASN.1. The version of BER these routines support is the one defined for the LDAP protocol. The encoding rules are the same as BER, except that only definite form lengths are used, and bitstrings and octet strings are always encoded in primitive form. This man page describes the encoding routines in the lber library. See .BR lber-decode (3) for details on the corresponding decoding routines. Consult .BR lber-types (3) for information about types, allocators, and deallocators. .LP Normally, the only routines that need to be called by an application are .BR ber_alloc_t () to allocate a BER element for encoding, .BR ber_printf () to do the actual encoding, and .BR ber_flush2 () to actually write the element. The other routines are provided for those applications that need more control than .BR ber_printf () provides. In general, these routines return the length of the element encoded, or -1 if an error occurred. .LP The .BR ber_alloc_t () routine is used to allocate a new BER element. It should be called with an argument of LBER_USE_DER. .LP The .BR ber_flush2 () routine is used to actually write the element to a socket (or file) descriptor, once it has been fully encoded (using .BR ber_printf () and friends). See .BR lber-sockbuf (3) for more details on the Sockbuf implementation of the \fIsb\fP parameter. If the \fIfreeit\fP parameter is non-zero, the supplied \fIber\fP will be freed. If \fILBER_FLUSH_FREE_ON_SUCCESS\fP is used, the \fIber\fP is only freed when successfully flushed, otherwise it is left intact; if \fILBER_FLUSH_FREE_ON_ERROR\fP is used, the \fIber\fP is only freed when an error occurs, otherwise it is left intact; if \fILBER_FLUSH_FREE_ALWAYS\fP is used, the \fIber\fP is freed anyway. This function differs from the original .BR ber_flush (3) function, whose behavior corresponds to that indicated for \fILBER_FLUSH_FREE_ON_SUCCESS\fP. Note that in the future, the behavior of .BR ber_flush (3) with \fIfreeit\fP non-zero might change into that of .BR ber_flush2 (3) with \fIfreeit\fP set to \fILBER_FLUSH_FREE_ALWAYS\fP. .LP The .BR ber_printf () routine is used to encode a BER element in much the same way that .BR sprintf (3) works. One important difference, though, is that some state information is kept with the \fIber\fP parameter so that multiple calls can be made to .BR ber_printf () to append things to the end of the BER element. .BR Ber_printf () writes to \fIber\fP, a pointer to a BerElement such as returned by .BR ber_alloc_t (). It interprets and formats its arguments according to the format string \fIfmt\fP. The format string can contain the following characters: .RS .LP .TP 3 .B b Boolean. An ber_int_t parameter should be supplied. A boolean element is output. .TP .B e Enumeration. An ber_int_t parameter should be supplied. An enumeration element is output. .TP .B i Integer. An ber_int_t parameter should be supplied. An integer element is output. .TP .B B Bitstring. A char * pointer to the start of the bitstring is supplied, followed by the number of bits in the bitstring. A bitstring element is output. .TP .B n Null. No parameter is required. A null element is output. .TP .B o Octet string. A char * is supplied, followed by the length of the string pointed to. An octet string element is output. .TP .B O Octet string. A struct berval * is supplied. An octet string element is output. .TP .B s Octet string. A null-terminated string is supplied. An octet string element is output, not including the trailing NULL octet. .TP .B t Tag. A ber_tag_t specifying the tag to give the next element is provided. This works across calls. .TP .B v Several octet strings. A null-terminated array of char *'s is supplied. Note that a construct like '{v}' is required to get an actual SEQUENCE OF octet strings. .TP .B V Several octet strings. A null-terminated array of struct berval *'s is supplied. Note that a construct like '{V}' is required to get an actual SEQUENCE OF octet strings. .TP .B W Several octet strings. An array of struct berval's is supplied. The array is terminated by a struct berval with a NULL bv_val. Note that a construct like '{W}' is required to get an actual SEQUENCE OF octet strings. .TP .B { Begin sequence. No parameter is required. .TP .B } End sequence. No parameter is required. .TP .B [ Begin set. No parameter is required. .TP .B ] End set. No parameter is required. .RE .LP The .BR ber_put_int () routine writes the integer element \fInum\fP to the BER element \fIber\fP. .LP The .BR ber_put_enum () routine writes the enumeration element \fInum\fP to the BER element \fIber\fP. .LP The .BR ber_put_boolean () routine writes the boolean value given by \fIbool\fP to the BER element. .LP The .BR ber_put_bitstring () routine writes \fIblen\fP bits starting at \fIstr\fP as a bitstring value to the given BER element. Note that \fIblen\fP is the length \fIin bits\fP of the bitstring. .LP The .BR ber_put_ostring () routine writes \fIlen\fP bytes starting at \fIstr\fP to the BER element as an octet string. .LP The .BR ber_put_string () routine writes the null-terminated string (minus the terminating '\0') to the BER element as an octet string. .LP The .BR ber_put_null () routine writes a NULL element to the BER element. .LP The .BR ber_start_seq () routine is used to start a sequence in the BER element. The .BR ber_start_set () routine works similarly. The end of the sequence or set is marked by the nearest matching call to .BR ber_put_seq () or .BR ber_put_set (), respectively. .SH EXAMPLES Assuming the following variable declarations, and that the variables have been assigned appropriately, an lber encoding of the following ASN.1 object: .LP .nf AlmostASearchRequest := SEQUENCE { baseObject DistinguishedName, scope ENUMERATED { baseObject (0), singleLevel (1), wholeSubtree (2) }, derefAliases ENUMERATED { neverDerefaliases (0), derefInSearching (1), derefFindingBaseObj (2), alwaysDerefAliases (3) }, sizelimit INTEGER (0 .. 65535), timelimit INTEGER (0 .. 65535), attrsOnly BOOLEAN, attributes SEQUENCE OF AttributeType } .fi .LP can be achieved like so: .LP .nf int rc; ber_int_t scope, ali, size, time, attrsonly; char *dn, **attrs; BerElement *ber; /* ... fill in values ... */ ber = ber_alloc_t( LBER_USE_DER ); if ( ber == NULL ) { /* error */ } rc = ber_printf( ber, "{siiiib{v}}", dn, scope, ali, size, time, attrsonly, attrs ); if( rc == \-1 ) { /* error */ } else { /* success */ } .fi .SH ERRORS If an error occurs during encoding, generally these routines return \-1. .LP .SH NOTES .LP The return values for all of these functions are declared in the header file. .SH SEE ALSO .BR lber-decode (3), .BR lber-memory (3), .BR lber-sockbuf (3), .BR lber-types (3) .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man3/ldap_modrdn.30000644000175000017500000000402212563404150017553 0ustar ryanryan.TH LDAP_MODRDN 3 "RELEASEDATE" "OpenLDAP LDVERSION" .\" $OpenLDAP$ .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_modrdn, ldap_modrdn_s, ldap_modrdn2, ldap_modrdn2_s \- Perform an LDAP modify RDN operation .SH LIBRARY OpenLDAP LDAP (libldap, \-lldap) .SH SYNOPSIS .nf .ft B #include .LP .ft B int ldap_modrdn(ld, dn, newrdn) .ft LDAP \(**ld; char \(**dn, \(**newrdn; .LP .ft B .LP .ft B int ldap_modrdn_s(ld, dn, newrdn) .ft LDAP \(**ld; char \(**dn, \(**newrdn; .LP .ft B int ldap_modrdn2(ld, dn, newrdn, deleteoldrdn) .ft LDAP \(**ld; char \(**dn, \(**newrdn; int deleteoldrdn; .LP .ft B int ldap_modrdn2_s(ld, dn, newrdn, deleteoldrdn) .ft LDAP \(**ld; char \(**dn, \(**newrdn; int deleteoldrdn; .SH DESCRIPTION The .B ldap_modrdn() and .B ldap_modrdn_s() routines perform an LDAP modify RDN operation. They both take \fIdn\fP, the DN of the entry whose RDN is to be changed, and \fInewrdn\fP, the new RDN to give the entry. The old RDN of the entry is never kept as an attribute of the entry. .B ldap_modrdn() is asynchronous, returning the message id of the operation it initiates. .B ldap_modrdn_s() is synchronous, returning the LDAP error code indicating the success or failure of the operation. Use of these routines is deprecated. Use the versions described below instead. .LP The .B ldap_modrdn2() and .B ldap_modrdn2_s() routines also perform an LDAP modify RDN operation, taking the same parameters as above. In addition, they both take the \fIdeleteoldrdn\fP parameter which is used as a boolean value to indicate whether the old RDN values should be deleted from the entry or not. .SH ERRORS The synchronous (_s) versions of these routines return an LDAP error code, either LDAP_SUCCESS or an error if there was trouble. The asynchronous versions return \-1 in case of trouble, setting the .B ld_errno field of \fIld\fP. See .BR ldap_error (3) for more details. .SH SEE ALSO .BR ldap (3), .BR ldap_error (3) .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man3/ldap_url.3.links0000644000175000017500000000007012563404150020210 0ustar ryanryanldap_is_ldap_url.3 ldap_url_parse.3 ldap_free_urldesc.3 openldap-2.4.42+dfsg/doc/man/man3/ldap_parse_sort_control.30000644000175000017500000000262512563404150022220 0ustar ryanryan.TH LDAP_PARSE_SORT-CONTROL 3 "RELEASEDATE" "OpenLDAP LDVERSION" .\" $OpenLDAP$ .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_parse_sort_control \- Decode the information returned from a search operation that used a server-side sort control .SH LIBRARY OpenLDAP LDAP (libldap, \-lldap) .SH SYNOPSIS .nf .ft B #include .LP .ft B int ldap_parse_sort_control(ld, ctrls, returnCode, attribute) .ft LDAP *ld; LDAPControl **ctrls; unsigned long *returnCode; char **attribute; .SH DESCRIPTION This function is used to parse the results returned in a search operation that uses a server-side sort control. .LP It takes a null terminated array of LDAPControl structures usually obtained by a call to the .BR ldap_parse_result function. A returncode which points to the sort control result code,and an array of LDAPControl structures that list the client controls to use with the search. The function also takes an out parameter \fIattribute\fP and if the sort operation fails, the server may return a string that indicates the first attribute in the sortKey list that caused the failure. If this parameter is NULL, no string is returned. If a string is returned, the memory should be freed by calling the ldap_memfree function. .SH NOTES .SH SEE ALSO .BR ldap_result (3), .BR ldap_controls_free (3) .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man3/ldap_sync.30000644000175000017500000002300212563404150017243 0ustar ryanryan.TH LDAP_SYNC 3 "RELEASEDATE" "OpenLDAP LDVERSION" .\" $OpenLDAP$ .\" Copyright 2006-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_sync_init, ldap_sync_init_refresh_only, ldap_sync_init_refresh_and_persist, ldap_sync_poll \- LDAP sync routines .SH LIBRARY OpenLDAP LDAP (libldap, \-lldap) .SH SYNOPSIS .nf .B #include .LP .BI "int ldap_sync_init(ldap_sync_t *" ls ", int " mode ");" .LP .BI "int ldap_sync_init_refresh_only(ldap_sync_t *" ls ");" .LP .BI "int ldap_sync_init_refresh_and_persist(ldap_sync_t *" ls ");" .LP .BI "int ldap_sync_poll(ldap_sync_t *" ls ");" .LP .BI "ldap_sync_t * ldap_sync_initialize(ldap_sync_t *" ls ");" .LP .BI "void ldap_sync_destroy(ldap_sync_t *" ls ", int " freeit ");" .LP .BI "typedef int (*" ldap_sync_search_entry_f ")(ldap_sync_t *" ls "," .RS .BI "LDAPMessage *" msg ", struct berval *" entryUUID "," .BI "ldap_sync_refresh_t " phase ");" .RE .LP .BI "typedef int (*" ldap_sync_search_reference_f ")(ldap_sync_t *" ls "," .RS .BI "LDAPMessage *" msg ");" .RE .LP .BI "typedef int (*" ldap_sync_intermediate_f ")(ldap_sync_t *" ls "," .RS .BI "LDAPMessage *" msg ", BerVarray " syncUUIDs "," .BI "ldap_sync_refresh_t " phase ");" .RE .LP .BI "typedef int (*" ldap_sync_search_result_f ")(ldap_sync_t *" ls "," .RS .BI "LDAPMessage *" msg ", int " refreshDeletes ");" .RE .SH DESCRIPTION .LP These routines provide an interface to the LDAP Content Synchronization operation (RFC 4533). They require an .BR ldap_sync_t structure to be set up with parameters required for various phases of the operation; this includes setting some handlers for special events. All handlers take a pointer to the \fBldap_sync_t\fP structure as the first argument, and a pointer to the \fBLDAPMessage\fP structure as received from the server by the client library, plus, occasionally, other specific arguments. The members of the \fBldap_sync_t\fP structure are: .TP .BI "char *" ls_base The search base; by default, the .B BASE option in .BR ldap.conf (5). .TP .BI "int " ls_scope The search scope (one of .BR LDAP_SCOPE_BASE , .BR LDAP_SCOPE_ONELEVEL , .BR LDAP_SCOPE_SUBORDINATE or .BR LDAP_SCOPE_SUBTREE ; see .B ldap.h for details). .TP .BI "char *" ls_filter The filter (RFC 4515); by default, .BR (objectClass=*) . .TP .BI "char **" ls_attrs The requested attributes; by default .BR NULL , indicating all user attributes. .TP .BI "int " ls_timelimit The requested time limit (in seconds); by default .BR 0 , to indicate no limit. .TP .BI "int " ls_sizelimit The requested size limit (in entries); by default .BR 0 , to indicate no limit. .TP .BI "int " ls_timeout The desired timeout during polling with .BR ldap_sync_poll (3). A value of .BR \-1 means that polling is blocking, so .BR ldap_sync_poll (3) will not return until a message is received; a value of .BR 0 means that polling returns immediately, no matter if any response is available or not; a positive value represents the timeout the .BR ldap_sync_poll (3) function will wait for response before returning, unless a message is received; in that case, .BR ldap_sync_poll (3) returns as soon as the message is available. .TP .BI "ldap_sync_search_entry_f " ls_search_entry A function that is called whenever an entry is returned. The .BR msg argument is the .BR LDAPMessage that contains the searchResultEntry; it can be parsed using the regular client API routines, like .BR ldap_get_dn (3), .BR ldap_first_attribute (3), and so on. The .BR entryUUID argument contains the entryUUID of the entry. The .BR phase argument indicates the type of operation: one of .BR LDAP_SYNC_CAPI_PRESENT , .BR LDAP_SYNC_CAPI_ADD , .BR LDAP_SYNC_CAPI_MODIFY , .BR LDAP_SYNC_CAPI_DELETE ; in case of .BR LDAP_SYNC_CAPI_PRESENT or .BR LDAP_SYNC_CAPI_DELETE , only the DN is contained in the .IR LDAPMessage ; in case of .BR LDAP_SYNC_CAPI_MODIFY , the whole entry is contained in the .IR LDAPMessage , and the application is responsible of determining the differences between the new view of the entry provided by the caller and the data already known. .TP .BI "ldap_sync_search_reference_f " ls_search_reference A function that is called whenever a search reference is returned. The .BR msg argument is the .BR LDAPMessage that contains the searchResultReference; it can be parsed using the regular client API routines, like .BR ldap_parse_reference (3). .TP .BI "ldap_sync_intermediate_f " ls_intermediate A function that is called whenever something relevant occurs during the refresh phase of the search, which is marked by an \fIintermediateResponse\fP message type. The .BR msg argument is the .BR LDAPMessage that contains the intermediate response; it can be parsed using the regular client API routines, like .BR ldap_parse_intermediate (3). The .BR syncUUIDs argument contains an array of UUIDs of the entries that depends on the value of the .BR phase argument. In case of .BR LDAP_SYNC_CAPI_PRESENTS , the "present" phase is being entered; this means that the following sequence of results will consist in entries in "present" sync state. In case of .BR LDAP_SYNC_CAPI_DELETES , the "deletes" phase is being entered; this means that the following sequence of results will consist in entries in "delete" sync state. In case of .BR LDAP_SYNC_CAPI_PRESENTS_IDSET , the message contains a set of UUIDs of entries that are present; it replaces a "presents" phase. In case of .BR LDAP_SYNC_CAPI_DELETES_IDSET , the message contains a set of UUIDs of entries that have been deleted; it replaces a "deletes" phase. In case of .BR LDAP_SYNC_CAPI_DONE, a "presents" phase with "refreshDone" set to "TRUE" has been returned to indicate that the refresh phase of refreshAndPersist is over, and the client should start polling. Except for the .BR LDAP_SYNC_CAPI_PRESENTS_IDSET and .BR LDAP_SYNC_CAPI_DELETES_IDSET cases, .BR syncUUIDs is NULL. .BR .TP .BI "ldap_sync_search_result_f " ls_search_result A function that is called whenever a searchResultDone is returned. In refreshAndPersist this can only occur when the server decides that the search must be interrupted. The .BR msg argument is the .BR LDAPMessage that contains the response; it can be parsed using the regular client API routines, like .BR ldap_parse_result (3). The .BR refreshDeletes argument is not relevant in this case; it should always be \-1. .TP .BI "void *" ls_private A pointer to private data. The client may register here a pointer to data the handlers above may need. .TP .BI "LDAP *" ls_ld A pointer to a LDAP structure that is used to connect to the server. It is the responsibility of the client to initialize the structure and to provide appropriate authentication and security in place. .SH "GENERAL USE" A .B ldap_sync_t structure is initialized by calling .BR ldap_sync_initialize(3). This simply clears out the contents of an already existing .B ldap_sync_t structure, and sets appropriate values for some members. After that, the caller is responsible for setting up the connection (member .BR ls_ld ), eventually setting up transport security (TLS), for binding and any other initialization. The caller must also fill all the documented search-related fields of the .B ldap_sync_t structure. At the end of a session, the structure can be cleaned up by calling .BR ldap_sync_destroy (3), which takes care of freeing all data assuming it was allocated by .BR ldap_mem* (3) routines. Otherwise, the caller should take care of destroying and zeroing out the documented search-related fields, and call .BR ldap_sync_destroy (3) to free undocumented members set by the API. .SH "REFRESH ONLY" The .BR refreshOnly functionality is obtained by periodically calling .BR ldap_sync_init (3) with mode set to .BR LDAP_SYNC_REFRESH_ONLY , or, which is equivalent, by directly calling .BR ldap_sync_init_refresh_only (3). The state of the search, and the consistency of the search parameters, is preserved across calls by passing the .B ldap_sync_t structure as left by the previous call. .SH "REFRESH AND PERSIST" The .BR refreshAndPersist functionality is obtained by calling .BR ldap_sync_init (3) with mode set to .BR LDAP_SYNC_REFRESH_AND_PERSIST , or, which is equivalent, by directly calling .BR ldap_sync_init_refresh_and_persist (3) and, after a successful return, by repeatedly polling with .BR ldap_sync_poll (3) according to the desired pattern. A client may insert a call to .BR ldap_sync_poll (3) into an external loop to check if any modification was returned; in this case, it might be appropriate to set .BR ls_timeout to 0, or to set it to a finite, small value. Otherwise, if the client's main purpose consists in waiting for responses, a timeout of \-1 is most suitable, so that the function only returns after some data has been received and handled. .SH ERRORS All routines return any LDAP error resulting from a lower-level error in the API calls they are based on, or LDAP_SUCCESS in case of success. .BR ldap_sync_poll (3) may return .BR LDAP_SYNC_REFRESH_REQUIRED if a full refresh is requested by the server. In this case, it is appropriate to call .BR ldap_sync_init (3) again, passing the same .B ldap_sync_t structure as resulted from any previous call. .SH NOTES .SH SEE ALSO .BR ldap (3), .BR ldap_search_ext (3), .BR ldap_result (3) ; .B RFC 4533 (http://www.rfc-editor.org), .SH AUTHOR Designed and implemented by Pierangelo Masarati, based on RFC 4533 and loosely inspired by syncrepl code in .BR slapd (8). .SH ACKNOWLEDGEMENTS Initially developed by .BR "SysNet s.n.c." .B OpenLDAP is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). .B OpenLDAP is derived from University of Michigan LDAP 3.3 Release. openldap-2.4.42+dfsg/doc/man/man3/ldap_tls.30000644000175000017500000000264112563404150017077 0ustar ryanryan.TH LDAP_TLS 3 "RELEASEDATE" "OpenLDAP LDVERSION" .\" $OpenLDAP$ .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_start_tls, ldap_start_tls_s, ldap_tls_inplace, ldap_install_tls \- LDAP TLS initialization routines .SH LIBRARY OpenLDAP LDAP (libldap, \-lldap) .SH SYNOPSIS .B #include .LP .BI "int ldap_start_tls(LDAP *" ld ");" .LP .BI "int ldap_start_tls_s(LDAP *" ld ", LDAPControl **" serverctrls ", LDAPControl **" clientctrls ");" .LP .BI "int ldap_tls_inplace(LDAP *" ld ");" .LP .BI "int ldap_install_tls(LDAP *" ld ");" .SH DESCRIPTION These routines are used to initiate TLS processing on an LDAP session. .BR ldap_start_tls_s () sends a StartTLS request to a server, waits for the reply, and then installs TLS handlers on the session if the request succeeded. The routine returns .B LDAP_SUCCESS if everything succeeded, otherwise it returns an LDAP error code. .BR ldap_start_tls () sends a StartTLS request to a server and does nothing else. It returns .B LDAP_SUCCESS if the request was sent successfully. .BR ldap_tls_inplace () returns 1 if TLS handlers have been installed on the specified session, 0 otherwise. .BR ldap_install_tls () installs the TLS handlers on the given session. It returns .B LDAP_LOCAL_ERROR if TLS is already installed. .SH SEE ALSO .BR ldap (3), .BR ldap_error (3) .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man3/ldap_get_dn.3.links0000644000175000017500000000022412563404150020647 0ustar ryanryanldap_explode_dn.3 ldap_explode_rdn.3 ldap_dn2ufn.3 ldap_str2dn.3 ldap_dnfree.3 ldap_dn2str.3 ldap_dn2dcedn.3 ldap_dcedn2dn.3 ldap_dn2ad_canonical.3 openldap-2.4.42+dfsg/doc/man/man3/ldap_get_values.30000644000175000017500000000475112563404150020437 0ustar ryanryan.TH LDAP_GET_VALUES 3 "RELEASEDATE" "OpenLDAP LDVERSION" .\" $OpenLDAP$ .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_get_values, ldap_get_values_len, ldap_count_values \- LDAP attribute value handling routines .SH LIBRARY OpenLDAP LDAP (libldap, \-lldap) .SH SYNOPSIS .nf .ft B #include .LP .ft B char **ldap_get_values(ld, entry, attr) .ft LDAP *ld; LDAPMessage *entry; char *attr; .LP .ft B struct berval **ldap_get_values_len(ld, entry, attr) .ft LDAP *ld; LDAPMessage *entry; char *attr; .LP .ft B int ldap_count_values(vals) .ft char **vals; .LP .ft B int ldap_count_values_len(vals) .ft struct berval **vals; .LP .ft B void ldap_value_free(vals) .ft char **vals; .LP .ft B void ldap_value_free_len(vals) .ft struct berval **vals; .SH DESCRIPTION These routines are used to retrieve and manipulate attribute values from an LDAP entry as returned by .BR ldap_first_entry (3) or .BR ldap_next_entry (3). .B ldap_get_values() takes the \fIentry\fP and the attribute \fIattr\fP whose values are desired and returns a NULL-terminated array of the attribute's values. \fIattr\fP may be an attribute type as returned from .BR ldap_first_attribute (3) or .BR ldap_next_attribute (3), or if the attribute type is known it can simply be given. .LP The number of values in the array can be counted by calling .BR ldap_count_values() . The array of values returned can be freed by calling .BR ldap_value_free() . .LP If the attribute values are binary in nature, and thus not suitable to be returned as an array of char *'s, the .B ldap_get_values_len() routine can be used instead. It takes the same parameters as .BR ldap_get_values() , but returns a NULL-terminated array of pointers to berval structures, each containing the length of and a pointer to a value. .LP The number of values in the array can be counted by calling .BR ldap_count_values_len() . The array of values returned can be freed by calling .BR ldap_value_free_len() . .SH ERRORS If an error occurs in .B ldap_get_values() or .BR ldap_get_values_len() , NULL is returned and the .B ld_errno field in the \fIld\fP parameter is set to indicate the error. See .BR ldap_error (3) for a description of possible error codes. .SH NOTES These routines dynamically allocate memory which the caller must free using the supplied routines. .SH SEE ALSO .BR ldap (3), .BR ldap_first_entry (3), .BR ldap_first_attribute (3), .BR ldap_error (3) .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man3/ldap_add.3.links0000644000175000017500000000005512563404150020141 0ustar ryanryanldap_add_s.3 ldap_add_ext.3 ldap_add_ext_s.3 openldap-2.4.42+dfsg/doc/man/man3/ldap_search.3.links0000644000175000017500000000010712563404150020654 0ustar ryanryanldap_search_s.3 ldap_search_st.3 ldap_search_ext.3 ldap_search_ext_s.3 openldap-2.4.42+dfsg/doc/man/man3/ldap_first_attribute.30000644000175000017500000000407012563404150021505 0ustar ryanryan.TH LDAP_FIRST_ATTRIBUTE 3 "RELEASEDATE" "OpenLDAP LDVERSION" .\" $OpenLDAP$ .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_first_attribute, ldap_next_attribute \- step through LDAP entry attributes .SH LIBRARY OpenLDAP LDAP (libldap, \-lldap) .SH SYNOPSIS .nf .ft B #include .LP .ft B char *ldap_first_attribute( LDAP *ld, LDAPMessage *entry, BerElement **berptr ) .LP .ft B char *ldap_next_attribute( LDAP *ld, LDAPMessage *entry, BerElement *ber ) .SH DESCRIPTION The .B ldap_first_attribute() and .B ldap_next_attribute() routines are used to step through the attributes in an LDAP entry. .B ldap_first_attribute() takes an \fIentry\fP as returned by .BR ldap_first_entry (3) or .BR ldap_next_entry (3) and returns a pointer to character string containing the first attribute description in the entry. .B ldap_next_attribute() returns the next attribute description in the entry. .LP It also returns, in \fIberptr\fP, a pointer to a BerElement it has allocated to keep track of its current position. This pointer should be passed to subsequent calls to .B ldap_next_attribute() and is used to effectively step through the entry's attributes. The caller is solely responsible for freeing the BerElement pointed to by \fIberptr\fP when it is no longer needed by calling .BR ber_free (3). When calling .BR ber_free (3) in this instance, be sure the second argument is 0. .LP The attribute names returned are suitable for inclusion in a call to .BR ldap_get_values (3) to retrieve the attribute's values. .SH ERRORS If an error occurs, NULL is returned and the ld_errno field in the \fIld\fP parameter is set to indicate the error. See .BR ldap_error (3) for a description of possible error codes. .SH NOTES The .B ldap_first_attribute() and .B ldap_next_attribute() return dynamically allocated memory that must be freed by the caller via .BR ldap_memfree (3). .SH SEE ALSO .BR ldap (3), .BR ldap_first_entry (3), .BR ldap_get_values (3), .BR ldap_error (3) .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man3/ldap_extended_operation.30000644000175000017500000000435012563404150022154 0ustar ryanryan.TH LDAP_EXTENDED_OPERATION 3 "RELEASEDATE" "OpenLDAP LDVERSION" .\" $OpenLDAP$ .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_extended_operation, ldap_extended_operation_s \- Extends the LDAP operations to the LDAP server. .SH LIBRARY OpenLDAP LDAP (libldap, \-lldap) .SH SYNOPSIS .nf .ft B #include .LP .ft B int ldap_extended_operation( .RS .ft B LDAP *\fIld\fB, const char *\fIrequestoid\fB, const struct berval *\fIrequestdata\fB, LDAPControl **\fIsctrls\fB, LDAPControl **\fIcctrls\fB, int *\fImsgidp\fB ); .RE .LP .ft B int ldap_extended_operation_s( .RS .ft B LDAP *\fIld\fB, const char *\fIrequestoid\fB, const struct berval *\fIrequestdata\fB, LDAPControl **\fIsctrls\fB, LDAPControl **\fIcctrls\fB, char **\fIretoidp\fB, struct berval **\fIretdatap\fB ); .RE .SH DESCRIPTION The .B ldap_extended_operation_s() routine is used to synchronously perform an LDAP extended operation. It takes \fIrequestoid\fP, which points to a dotted-decimal OID string identifying the extended operation to perform. \fIrequestdata\fP is the data required for the request, \fIsctrls\fP is an array of LDAPControl structures to use with this extended operation, \fIcctrls\fP is an array of LDAPControl structures that list the client controls to use with this extended operation. .LP The output parameter \fIretoidp\fP points to a dotted-decimal OID string returned by the LDAP server. The memory used by the string should be freed with the .BR ldap_memfree (3) function. The output parameter \fIretdatap\fP points to a pointer to a berval structure that contains the returned data. If no data is returned by the server, the pointer is set this to NULL. The memory used by this structure should be freed with the .BR ber_bvfree (3) function. .LP The .B ldap_extended_operation() works just like .BR ldap_extended_operation_s() , but the operation is asynchronous. It provides the message id of the request it initiated in the integer pointed to be \fImsgidp\fP. The result of this operation can be obtained by calling .BR ldap_result(3). .SH SEE ALSO .BR ber_bvfree (3), .BR ldap_memfree (3), .BR ldap_parse_extended_result (3), .BR ldap_result (3) .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man3/ldap_first_message.3.links0000644000175000017500000000005212563404150022241 0ustar ryanryanldap_next_message.3 ldap_count_messages.3 openldap-2.4.42+dfsg/doc/man/man8/0000755000175000017500000000000012563404150015213 5ustar ryanryanopenldap-2.4.42+dfsg/doc/man/man8/slappasswd.80000644000175000017500000001031712563404150017467 0ustar ryanryan.TH SLAPPASSWD 8C "RELEASEDATE" "OpenLDAP LDVERSION" .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .\" $OpenLDAP$ .SH NAME slappasswd \- OpenLDAP password utility .SH SYNOPSIS .B SBINDIR/slappasswd [\c .BR \-v ] [\c .BR \-u ] [\c .BR \-g \||\| \-s \ \fIsecret\fR \||\| \fB\-T \ \fIfile\fR] [\c .BI \-h \ hash\fR] [\c .BI \-c \ salt-format\fR] [\c .BR \-n ] [\c .BI \-o \ option\fR[ = value\fR]] .LP .SH DESCRIPTION .LP .B Slappasswd is used to generate an userPassword value suitable for use with .BR ldapmodify (1), .BR slapd.conf (5) .I rootpw configuration directive or the .BR slapd\-config (5) .I olcRootPW configuration directive. . .SH OPTIONS .TP .B \-v enable verbose mode. .TP .B \-u Generate RFC 2307 userPassword values (the default). Future versions of this program may generate alternative syntaxes by default. This option is provided for forward compatibility. .TP .BI \-s \ secret The secret to hash. If this, .B \-g and .B \-T are absent, the user will be prompted for the secret to hash. .BR \-s , .B \-g and .B \-T are mutually exclusive flags. .TP .BI \-g Generate the secret. If this, .B \-s and .B \-T are absent, the user will be prompted for the secret to hash. .BR \-s , .B \-g and .B \-T are mutually exclusive flags. If this is present, .I {CLEARTEXT} is used as scheme. .B \-g and .B \-h are mutually exclusive flags. .TP .BI \-T \ "file" Hash the contents of the file. If this, .B \-g and .B \-s are absent, the user will be prompted for the secret to hash. .BR \-s , .B \-g and .B \-T and mutually exclusive flags. .TP .BI \-h \ "scheme" If \fB\-h\fP is specified, one of the following RFC 2307 schemes may be specified: .BR {CRYPT} , .BR {MD5} , .BR {SMD5} , .BR {SSHA} ", and" .BR {SHA} . The default is .BR {SSHA} . Note that scheme names may need to be protected, due to .B { and .BR } , from expansion by the user's command interpreter. .B {SHA} and .B {SSHA} use the SHA-1 algorithm (FIPS 160-1), the latter with a seed. .B {MD5} and .B {SMD5} use the MD5 algorithm (RFC 1321), the latter with a seed. .B {CRYPT} uses the .BR crypt (3). .B {CLEARTEXT} indicates that the new password should be added to userPassword as clear text. Unless .I {CLEARTEXT} is used, this flag is incompatible with option .BR \-g . .TP .BI \-c \ crypt-salt-format Specify the format of the salt passed to .BR crypt (3) when generating {CRYPT} passwords. This string needs to be in .BR sprintf (3) format and may include one (and only one) .B %s conversion. This conversion will be substituted with a string of random characters from [A\-Za\-z0\-9./]. For example, .RB ' %.2s ' provides a two character salt and .RB ' $1$%.8s ' tells some versions of .BR crypt (3) to use an MD5 algorithm and provides 8 random characters of salt. The default is .RB ' %s ' , which provides 31 characters of salt. .TP .BI \-n Omit the trailing newline; useful to pipe the credentials into a command. .TP .BI \-o \ option\fR[ = value\fR] Specify an .I option with a(n optional) .IR value . Possible generic options/values are: .LP .nf module\-path= (see `\fBmodulepath\fP' in slapd.conf(5)) module\-load= (see `\fBmoduleload\fP' in slapd.conf(5)) .in You can load a dynamically loadable password hash module by using this option. .SH LIMITATIONS The practice of storing hashed passwords in userPassword violates Standard Track (RFC 4519) schema specifications and may hinder interoperability. A new attribute type, authPassword, to hold hashed passwords has been defined (RFC 3112), but is not yet implemented in .BR slapd (8). .LP It should also be noted that the behavior of .BR crypt (3) is platform specific. .SH "SECURITY CONSIDERATIONS" Use of hashed passwords does not protect passwords during protocol transfer. TLS or other eavesdropping protections should be in-place before using LDAP simple bind. .LP The hashed password values should be protected as if they were clear text passwords. .SH "SEE ALSO" .BR ldappasswd (1), .BR ldapmodify (1), .BR slapd (8), .BR slapd.conf (5), .BR slapd\-config (5), .B RFC 2307\fP, .B RFC 4519\fP, .B RFC 3112 .LP "OpenLDAP Administrator's Guide" (http://www.OpenLDAP.org/doc/admin/) .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man8/Makefile.in0000644000175000017500000000103012563404150017252 0ustar ryanryan# man8 Makefile.in for OpenLDAP # $OpenLDAP$ ## This work is part of OpenLDAP Software . ## ## Copyright 1998-2015 The OpenLDAP Foundation. ## All rights reserved. ## ## Redistribution and use in source and binary forms, with or without ## modification, are permitted only as authorized by the OpenLDAP ## Public License. ## ## A copy of this license is available in the file LICENSE in the ## top-level directory of the distribution or, alternatively, at ## . MANSECT=8 openldap-2.4.42+dfsg/doc/man/man8/slapacl.80000644000175000017500000001021112563404150016716 0ustar ryanryan.TH SLAPACL 8C "RELEASEDATE" "OpenLDAP LDVERSION" .\" Copyright 2004-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .\" $OpenLDAP$ .SH NAME slapacl \- Check access to a list of attributes. .SH SYNOPSIS .B SBINDIR/slapacl .BI \-b \ DN [\c .BI \-d \ debug-level\fR] [\c .BI \-D \ authcDN\ \fR| .BI \-U \ authcID\fR] [\c .BI \-f \ slapd.conf\fR] [\c .BI \-F \ confdir\fR] [\c .BI \-o \ option\fR[ = value\fR]] [\c .BR \-u ] [\c .BR \-v ] [\c .BI \-X \ authzID\ \fR| .BI "\-o \ authzDN=" DN\fR] [\c .IR attr [\fB/\fI access ][\fB:\fI value ]]\fR\ [...] .LP .SH DESCRIPTION .LP .B slapacl is used to check the behavior of .BR slapd (8) by verifying access to directory data according to the access control list directives defined in its configuration. . It opens the .BR slapd.conf (5) configuration file or the .BR slapd\-config (5) backend, reads in the .BR access / olcAccess directives, and then parses the .B attr list given on the command-line; if none is given, access to the .B entry pseudo-attribute is tested. .LP .SH OPTIONS .TP .BI \-b \ DN specify the .I DN which access is requested to; the corresponding entry is fetched from the database, and thus it must exist. The .I DN is also used to determine what rules apply; thus, it must be in the naming context of a configured database. See also .BR \-u . .TP .BI \-d \ debug-level enable debugging messages as defined by the specified .IR debug-level ; see .BR slapd (8) for details. .TP .BI \-D \ authcDN specify a DN to be used as identity through the test session when selecting appropriate .B clauses in access lists. .TP .BI \-f \ slapd.conf specify an alternative .BR slapd.conf (5) file. .TP .BI \-F \ confdir specify a config directory. If both .B \-f and .B \-F are specified, the config file will be read and converted to config directory format and written to the specified directory. If neither option is specified, an attempt to read the default config directory will be made before trying to use the default config file. If a valid config directory exists then the default config file is ignored. .TP .BI \-o \ option\fR[ = value\fR] Specify an .I option with a(n optional) .IR value . Possible generic options/values are: .LP .nf syslog= (see `\-s' in slapd(8)) syslog\-level= (see `\-S' in slapd(8)) syslog\-user= (see `\-l' in slapd(8)) .fi .RS Possible options/values specific to .B slapacl are: .RE .nf authzDN domain peername sasl_ssf sockname sockurl ssf tls_ssf transport_ssf .fi .RS See the related fields in .BR slapd.access (5) for details. .RE .TP .BI \-u do not fetch the entry from the database. In this case, if the entry does not exist, a fake entry with the .I DN given with the .B \-b option is used, with no attributes. As a consequence, those rules that depend on the contents of the target object will not behave as with the real object. The .I DN given with the .B \-b option is still used to select what rules apply; thus, it must be in the naming context of a configured database. See also .BR \-b . .TP .BI \-U \ authcID specify an ID to be mapped to a .B DN as by means of .B authz\-regexp or .B authz\-rewrite rules (see .BR slapd.conf (5) for details); mutually exclusive with .BR \-D . .TP .B \-v enable verbose mode. .TP .BI \-X \ authzID specify an authorization ID to be mapped to a .B DN as by means of .B authz\-regexp or .B authz\-rewrite rules (see .BR slapd.conf (5) for details); mutually exclusive with \fB\-o\fP \fBauthzDN=\fIDN\fR. .SH EXAMPLES The command .LP .nf .ft tt SBINDIR/slapacl \-f ETCDIR/slapd.conf \-v \\ \-U bjorn \-b "o=University of Michigan,c=US" \\ "o/read:University of Michigan" .ft .fi tests whether the user .I bjorn can access the attribute .I o of the entry .I o=University of Michigan,c=US at .I read level. .SH "SEE ALSO" .BR ldap (3), .BR slapd (8), .BR slaptest (8), .BR slapauth (8) .LP "OpenLDAP Administrator's Guide" (http://www.OpenLDAP.org/doc/admin/) .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man8/slapadd.80000644000175000017500000001225412563404150016720 0ustar ryanryan.TH SLAPADD 8C "RELEASEDATE" "OpenLDAP LDVERSION" .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .\" $OpenLDAP$ .SH NAME slapadd \- Add entries to a SLAPD database .SH SYNOPSIS .B SBINDIR/slapadd [\c .BI \-b \ suffix\fR] [\c .BR \-c ] [\c .BI \-d \ debug-level\fR] [\c .BI \-f \ slapd.conf\fR] [\c .BI \-F \ confdir\fR] [\c .BR \-g ] [\c .BI \-j \ lineno\fR] [\c .BI \-l \ ldif-file\fR] [\c .BI \-n \ dbnum\fR] [\c .BI \-o \ option\fR[ = value\fR]] [\c .BR \-q ] [\c .BR \-s ] [\c .BI \-S \ SID\fR] [\c .BR \-u ] [\c .BR \-v ] [\c .BR \-w ] .SH DESCRIPTION .LP .B Slapadd is used to add entries specified in LDAP Directory Interchange Format (LDIF) to a .BR slapd (8) database. It opens the given database determined by the database number or suffix and adds entries corresponding to the provided LDIF to the database. Databases configured as .B subordinate of this one are also updated, unless \fB\-g\fP is specified. The LDIF input is read from standard input or the specified file. All files eventually created by .BR slapadd will belong to the identity .BR slapadd is run as, so make sure you either run .BR slapadd with the same identity .BR slapd (8) will be run as (see option .B \-u in .BR slapd (8)), or change file ownership before running .BR slapd (8). Note: slapadd will also perform the relevant indexing whilst adding the database if any are configured. For specfic details, please see .BR slapindex (8). .SH OPTIONS .TP .BI \-b \ suffix Use the specified \fIsuffix\fR to determine which database to add entries to. The \fB\-b\fP cannot be used in conjunction with the .B \-n option. .TP .B \-c enable continue (ignore errors) mode. .TP .BI \-d \ debug-level enable debugging messages as defined by the specified .IR debug-level ; see .BR slapd (8) for details. .TP .BI \-f \ slapd.conf specify an alternative .BR slapd.conf (5) file. .TP .BI \-F \ confdir specify a config directory. If both .B \-f and .B \-F are specified, the config file will be read and converted to config directory format and written to the specified directory. If neither option is specified, an attempt to read the default config directory will be made before trying to use the default config file. If a valid config directory exists then the default config file is ignored. If dry-run mode is also specified, no conversion will occur. .TP .B \-g disable subordinate gluing. Only the specified database will be processed, and not its glued subordinates (if any). .TP .BI \-j \ lineno Jump to the specified line number in the LDIF file before processing any entries. This allows a load that was aborted due to errors in the input LDIF to be resumed after the errors are corrected. .TP .BI \-l \ ldif-file Read LDIF from the specified file instead of standard input. .TP .BI \-n \ dbnum Add entries to the \fIdbnum\fR-th database listed in the configuration file. The .B \-n cannot be used in conjunction with the .B \-b option. To populate the config database .BR slapd\-config (5), use .B \-n 0 as it is always the first database. It must physically exist on the filesystem prior to this, however. .TP .BI \-o \ option\fR[ = value\fR] Specify an .I option with a(n optional) .IR value . Possible generic options/values are: .LP .nf syslog= (see `\-s' in slapd(8)) syslog\-level= (see `\-S' in slapd(8)) syslog\-user= (see `\-l' in slapd(8)) schema-check={yes|no} value-check={yes|no} .in The \fIschema\-check\fR option toggles schema checking (default on); the \fIvalue\-check\fR option toggles value checking (default off). The latter is incompatible with \fB-q\fR. .TP .B \-q enable quick (fewer integrity checks) mode. Does fewer consistency checks on the input data, and no consistency checks when writing the database. Improves the load time but if any errors or interruptions occur the resulting database will be unusable. .TP .B \-s disable schema checking. This option is intended to be used when loading databases containing special objects, such as fractional objects on a partial replica. Loading normal objects which do not conform to schema may result in unexpected and ill behavior. .TP .BI \-S \ SID Server ID to use in generated entryCSN. Also used for contextCSN if \fB\-w\fP is set as well. Defaults to \fB0\fP. .TP .B \-u enable dry-run (don't write to backend) mode. .TP .B \-v enable verbose mode. .TP .BI \-w write syncrepl context information. After all entries are added, the contextCSN will be updated with the greatest CSN in the database. .SH LIMITATIONS Your .BR slapd (8) should not be running when you do this to ensure consistency of the database. .LP .B slapadd may not provide naming or schema checks. It is advisable to use .BR ldapadd (1) when adding new entries into an existing directory. .SH EXAMPLES To import the entries specified in file .B ldif into your .BR slapd (8) database give the command: .LP .nf .ft tt SBINDIR/slapadd \-l ldif .ft .fi .SH "SEE ALSO" .BR ldap (3), .BR ldif (5), .BR slapcat (8), .BR slapindex (8), .BR ldapadd (1), .BR slapd (8) .LP "OpenLDAP Administrator's Guide" (http://www.OpenLDAP.org/doc/admin/) .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man8/slapcat.80000644000175000017500000001143312563404150016735 0ustar ryanryan.TH SLAPCAT 8C "RELEASEDATE" "OpenLDAP LDVERSION" .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .\" $OpenLDAP$ .SH NAME slapcat \- SLAPD database to LDIF utility .SH SYNOPSIS .B SBINDIR/slapcat [\c .BI \-a filter\fR] [\c .BI \-b suffix\fR] [\c .BR \-c ] [\c .BI \-d debug-level\fR] [\c .BI \-f slapd.conf\fR] [\c .BI \-F confdir\fR] [\c .BR \-g ] [\c .BI \-H URI\fR] [\c .BI \-l ldif-file\fR] [\c .BI \-n dbnum\fR] [\c .BI \-o option\fR[ = value\fR]] [\c .BI \-s subtree-dn\fR] [\c .BR \-v ] .LP .SH DESCRIPTION .LP .B Slapcat is used to generate an LDAP Directory Interchange Format (LDIF) output based upon the contents of a .BR slapd (8) database. It opens the given database determined by the database number or suffix and writes the corresponding LDIF to standard output or the specified file. Databases configured as .B subordinate of this one are also output, unless \fB\-g\fP is specified. .LP The entry records are presented in database order, not superior first order. The entry records will include all (user and operational) attributes stored in the database. The entry records will not include dynamically generated attributes (such as subschemaSubentry). .LP The output of slapcat is intended to be used as input to .BR slapadd (8). The output of slapcat cannot generally be used as input to .BR ldapadd (1) or other LDAP clients without first editing the output. This editing would normally include reordering the records into superior first order and removing no-user-modification operational attributes. .SH OPTIONS .TP .BI \-a \ filter Only dump entries matching the asserted filter. For example slapcat \-a \\ "(!(entryDN:dnSubtreeMatch:=ou=People,dc=example,dc=com))" will dump all but the "ou=People,dc=example,dc=com" subtree of the "dc=example,dc=com" database. Deprecated; use \fB-H\fP \fIldap:///???(filter)\fP instead. .TP .BI \-b \ suffix Use the specified \fIsuffix\fR to determine which database to generate output for. The \fB\-b\fP cannot be used in conjunction with the .B \-n option. .TP .B \-c Enable continue (ignore errors) mode. Multiple occorrences of .B \-c make .BR slapcat (8) try harder. .TP .BI \-d \ debug-level Enable debugging messages as defined by the specified .IR debug-level ; see .BR slapd (8) for details. .TP .BI \-f \ slapd.conf Specify an alternative .BR slapd.conf (5) file. .TP .BI \-F \ confdir specify a config directory. If both .B \-f and .B \-F are specified, the config file will be read and converted to config directory format and written to the specified directory. If neither option is specified, an attempt to read the default config directory will be made before trying to use the default config file. If a valid config directory exists then the default config file is ignored. .TP .B \-g disable subordinate gluing. Only the specified database will be processed, and not its glued subordinates (if any). .TP .B \-H \ URI use dn, scope and filter from URI to only handle matching entries. .TP .BI \-l \ ldif-file Write LDIF to specified file instead of standard output. .TP .BI \-n \ dbnum Generate output for the \fIdbnum\fR-th database listed in the configuration file. The config database .BR slapd\-config (5), is always the first database, so use .B \-n 0 to select it. The .B \-n cannot be used in conjunction with the .B \-b option. .TP .BI \-o \ option\fR[ = value\fR] Specify an .I option with a(n optional) .IR value . Possible generic options/values are: .LP .nf syslog= (see `\-s' in slapd(8)) syslog\-level= (see `\-S' in slapd(8)) syslog\-user= (see `\-l' in slapd(8)) ldif-wrap={no|} .in \fIn\fP is the number of columns allowed for the LDIF output (\fIn\fP equal to \fI0\fP uses the default, corresponding to 78). The minimum is 2, leaving space for one character and one continuation character. Use \fIno\fP for no wrap. .TP .BI \-s \ subtree-dn Only dump entries in the subtree specified by this DN. Implies \fB\-b\fP \fIsubtree-dn\fP if no .B \-b or .B \-n option is given. Deprecated; use \fB-H\fP \fIldap:///subtree-dn\fP instead. .TP .B \-v Enable verbose mode. .SH LIMITATIONS For some backend types, your .BR slapd (8) should not be running (at least, not in read-write mode) when you do this to ensure consistency of the database. It is always safe to run .B slapcat with the .BR slapd\-bdb (5), .BR slapd\-hdb (5), and .BR slapd\-null (5) backends. .SH EXAMPLES To make a text backup of your SLAPD database and put it in a file called .BR ldif , give the command: .LP .nf .ft tt SBINDIR/slapcat \-l ldif .ft .fi .SH "SEE ALSO" .BR ldap (3), .BR ldif (5), .BR slapadd (8), .BR ldapadd (1), .BR slapd (8) .LP "OpenLDAP Administrator's Guide" (http://www.OpenLDAP.org/doc/admin/) .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man8/slapd.80000644000175000017500000002560012563404150016412 0ustar ryanryan.TH SLAPD 8C "RELEASEDATE" "OpenLDAP LDVERSION" .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .\" $OpenLDAP$ .SH NAME slapd \- Stand-alone LDAP Daemon .SH SYNOPSIS .B LIBEXECDIR/slapd [\c .BR \-4 | \-6 ] [\c .BR \-T \ { acl \||\| a [ dd ]\||\| auth \||\| c [ at ]\||\| .BR d [ n ]\||\| i [ ndex ]\||\| p [ asswd ]\||\| s [ chema ]\||\| t [ est ]}] [\c .BI \-d \ debug-level\fR] [\c .BI \-f \ slapd-config-file\fR] [\c .BI \-F \ slapd-config-directory\fR] [\c .BI \-h \ URLs\fR] [\c .BI \-n \ service-name\fR] [\c .BI \-s \ syslog-level\fR] [\c .BI \-l \ syslog-local-user\fR] [\c .BI \-o \ option\fR[ = value\fR]] [\c .BI \-r \ directory\fR] [\c .BI \-u \ user\fR] [\c .BI \-g \ group\fR] [\c .BI \-c \ cookie\fR] .SH DESCRIPTION .LP .B Slapd is the stand-alone LDAP daemon. It listens for LDAP connections on any number of ports (default \fB389\fP), responding to the LDAP operations it receives over these connections. .B slapd is typically invoked at boot time, usually out of .BR /etc/rc.local . Upon startup, .B slapd normally forks and disassociates itself from the invoking tty. If configured in the config file (or config directory), the .B slapd process will print its process ID (see .BR getpid (2)) to a .B .pid file, as well as the command line options during invocation to an .B .args file (see .BR slapd.conf (5)). If the .B \-d flag is given, even with a zero argument, .B slapd will not fork and disassociate from the invoking tty. .LP See the "OpenLDAP Administrator's Guide" for more details on .BR slapd . .SH OPTIONS .TP .B \-4 Listen on IPv4 addresses only. .TP .B \-6 Listen on IPv6 addresses only. .TP .BI \-T \ tool Run in Tool mode. The \fItool\fP argument selects whether to run as .IR slapadd , .IR slapcat , .IR slapdn , .IR slapindex , .IR slappasswd , .IR slapschema , or .I slaptest (\fIslapacl\fP and \fIslapauth\fP need the entire \fBacl\fP and \fBauth\fP option value to be spelled out, as \fBa\fP is reserved to .IR slapadd ). This option should be the first option specified when it is used; any remaining options will be interpreted by the corresponding slap tool program, according to the respective man pages. Note that these tool programs will usually be symbolic links to .BR slapd . This option is provided for situations where symbolic links are not provided or not usable. .TP .BI \-d \ debug-level Turn on debugging as defined by .IR debug-level . If this option is specified, even with a zero argument, .B slapd will not fork or disassociate from the invoking terminal. Some general operation and status messages are printed for any value of \fIdebug-level\fP. \fIdebug-level\fP is taken as a bit string, with each bit corresponding to a different kind of debugging information. See for details. Comma-separated arrays of friendly names can be specified to select debugging output of the corresponding debugging information. All the names recognized by the \fIloglevel\fP directive described in \fBslapd.conf\fP(5) are supported. If \fIdebug-level\fP is \fB?\fP, a list of installed debug-levels is printed, and slapd exits. Remember that if you turn on packet logging, packets containing bind passwords will be output, so if you redirect the log to a logfile, that file should be read-protected. .TP .BI \-s \ syslog-level This option tells .B slapd at what debug-level debugging statements should be logged to the .BR syslog (8) facility. The value \fIsyslog-level\fP can be set to any value or combination allowed by the \fB\-d\fP switch. Slapd logs all messages selected by \fIsyslog-leveli\fP at the .BR syslog (3) severity debug-level \fBDEBUG\fP, on the unit specified with \fB\-l\fP. .TP .BI \-n \ service-name Specifies the service name for logging and other purposes. Defaults to basename of argv[0], i.e.: "slapd". .TP .BI \-l \ syslog-local-user Selects the local user of the .BR syslog (8) facility. Value can be .BR LOCAL0 , through .BR LOCAL7 , as well as .B USER and .BR DAEMON . The default is .BR LOCAL4 . However, this option is only permitted on systems that support local users with the .BR syslog (8) facility. Logging to syslog(8) occurs at the "DEBUG" severity debug-level. .TP .BI \-f \ slapd-config-file Specifies the slapd configuration file. The default is .BR ETCDIR/slapd.conf . .TP .BI \-F \ slapd-config-directory Specifies the slapd configuration directory. The default is .BR ETCDIR/slapd.d . If both .B \-f and .B \-F are specified, the config file will be read and converted to config directory format and written to the specified directory. If neither option is specified, slapd will attempt to read the default config directory before trying to use the default config file. If a valid config directory exists then the default config file is ignored. All of the slap tools that use the config options observe this same behavior. .TP .BI \-h \ URLlist .B slapd will by default serve .B ldap:/// (LDAP over TCP on all interfaces on default LDAP port). That is, it will bind using INADDR_ANY and port \fB389\fP. The .B \-h option may be used to specify LDAP (and other scheme) URLs to serve. For example, if slapd is given .BR "\-h \(dqldap://127.0.0.1:9009/ ldaps:/// ldapi:///\(dq" , it will listen on 127.0.0.1:9009 for LDAP, 0.0.0.0:636 for LDAP over TLS, and LDAP over IPC (Unix domain sockets). Host 0.0.0.0 represents INADDR_ANY (any interface). A space separated list of URLs is expected. The URLs should be of the LDAP, LDAPS, or LDAPI schemes, and generally without a DN or other optional parameters (excepting as discussed below). Support for the latter two schemes depends on selected configuration options. Hosts may be specified by name or IPv4 and IPv6 address formats. Ports, if specified, must be numeric. The default ldap:// port is \fB389\fP and the default ldaps:// port is \fB636\fP. For LDAP over IPC, .B name is the name of the socket, and no .B port is required, nor allowed; note that directory separators must be URL-encoded, like any other characters that are special to URLs; so the socket /usr/local/var/ldapi must be specified as ldapi://%2Fusr%2Flocal%2Fvar%2Fldapi The default location for the IPC socket is LOCALSTATEDIR/run/ldapi The listener permissions are indicated by "x\-mod=\-rwxrwxrwx", "x\-mod=0777" or "x\-mod=777", where any of the "rwx" can be "\-" to suppress the related permission, while any of the "7" can be any legal octal digit, according to chmod(1). The listeners can take advantage of the "x\-mod" extension to apply rough limitations to operations, e.g. allow read operations ("r", which applies to search and compare), write operations ("w", which applies to add, delete, modify and modrdn), and execute operations ("x", which means bind is required). "User" permissions apply to authenticated users, while "other" apply to anonymous users; "group" permissions are ignored. For example, "ldap:///????x\-mod=\-rw\-\-\-\-\-\-\-" means that read and write is only allowed for authenticated connections, and bind is required for all operations. This feature is experimental, and requires to be manually enabled at configure time. .TP .BI \-r \ directory Specifies a directory to become the root directory. slapd will change the current working directory to this directory and then .BR chroot (2) to this directory. This is done after opening listeners but before reading any configuration file or initializing any backend. When used as a security mechanism, it should be used in conjunction with .B \-u and .B \-g options. .TP .BI \-u \ user .B slapd will run slapd with the specified user name or id, and that user's supplementary group access list as set with initgroups(3). The group ID is also changed to this user's gid, unless the \fB\-g\fP option is used to override. Note when used with .BR \-r , slapd will use the user database in the change root environment. Note that on some systems, running as a non-privileged user will prevent passwd back-ends from accessing the encrypted passwords. Note also that any shell back-ends will run as the specified non-privileged user. .TP .BI \-g \ group .B slapd will run with the specified group name or id. Note when used with .BR \-r , slapd will use the group database in the change root environment. .TP .BI \-c \ cookie This option provides a cookie for the syncrepl replication consumer. The cookie is a comma separated list of \fIname=value\fP pairs. Currently supported syncrepl cookie fields are .BR rid , .BR sid , and .BR csn . .B rid identifies a replication thread within the consumer server and is used to find the syncrepl specification in .BR slapd.conf (5) or .BR slapd\-config (5) having the matching replication identifier in its definition. The .B rid must be provided in order for any other specified values to be used. .B sid is the server id in a multi-master/mirror-mode configuration. .B csn is the commit sequence number received by a previous synchronization and represents the state of the consumer replica content which the syncrepl engine will synchronize to the current provider content. In case of \fImirror-mode\fP or \fImulti-master\fP replication agreement, multiple .B csn values, semicolon separated, can appear. Use only the .B rid part to force a full reload. .TP .BI \-o \ option\fR[ = value\fR] This option provides a generic means to specify options without the need to reserve a separate letter for them. It supports the following options: .RS .TP .BR slp= { on \||\| off \||\| \fIslp-attrs\fP } When SLP support is compiled into slapd, disable it (\fBoff\fP), enable it by registering at SLP DAs without specific SLP attributes (\fBon\fP), or with specific SLP attributes .I slp-attrs that must be an SLP attribute list definition according to the SLP standard. For example, \fB"slp=(tree=production),(server-type=OpenLDAP),(server\-version=2.4.15)"\fP registers at SLP DAs with the three SLP attributes tree, server-type and server-version that have the values given above. This allows to specifically query the SLP DAs for LDAP servers holding the .I production tree in case multiple trees are available. .RE .SH EXAMPLES To start .I slapd and have it fork and detach from the terminal and start serving the LDAP databases defined in the default config file, just type: .LP .nf .ft tt LIBEXECDIR/slapd .ft .fi .LP To start .B slapd with an alternate configuration file, and turn on voluminous debugging which will be printed on standard error, type: .LP .nf .ft tt LIBEXECDIR/slapd \-f /var/tmp/slapd.conf \-d 255 .ft .fi .LP To test whether the configuration file is correct or not, type: .LP .nf .ft tt LIBEXECDIR/slapd \-Tt .ft .fi .LP .SH "SEE ALSO" .BR ldap (3), .BR slapd.conf (5), .BR slapd\-config (5), .BR slapd.access (5), .BR slapacl (8), .BR slapadd (8), .BR slapauth (8), .BR slapcat (8), .BR slapdn (8), .BR slapindex (8), .BR slappasswd (8), .BR slapschema (8), .BR slaptest (8). .LP "OpenLDAP Administrator's Guide" (http://www.OpenLDAP.org/doc/admin/) .SH BUGS See http://www.openldap.org/its/ .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man8/slaptest.80000644000175000017500000000474112563404150017151 0ustar ryanryan.TH SLAPTEST 8C "RELEASEDATE" "OpenLDAP LDVERSION" .\" Copyright 2004-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .\" $OpenLDAP$ .SH NAME slaptest \- Check the suitability of the OpenLDAP slapd configuration .SH SYNOPSIS .B SBINDIR/slaptest [\c .BI \-d \ debug-level\fR] [\c .BI \-f \ slapd.conf\fR] [\c .BI \-F \ confdir\fR] [\c .BI \-n dbnum\fR] [\c .BI \-o \ option\fR[ = value\fR]] [\c .BR \-Q ] [\c .BR \-u ] [\c .BR \-v ] .LP .SH DESCRIPTION .LP .B Slaptest is used to check the conformance of the .BR slapd (8) configuration. It opens the .BR slapd.conf (5) configuration file or the .BR slapd\-config (5) backend, and parses it according to the general and the backend-specific rules, checking its sanity. .LP .SH OPTIONS .TP .BI \-d \ debug-level enable debugging messages as defined by the specified .IR debug-level ; see .BR slapd (8) for details. .TP .BI \-f \ slapd.conf specify an alternative .BR slapd.conf (5) file. .TP .BI \-F \ confdir specify a config directory. If both .B \-f and .B \-F are specified, the config file will be read and converted to config directory format and written to the specified directory. If neither option is specified, slaptest will attempt to read the default config directory before trying to use the default config file. If a valid config directory exists then the default config file is ignored. If dry-run mode is also specified, no conversion will occur. .TP .BI \-n \ dbnum Just open and test the \fIdbnum\fR-th database listed in the configuration file. To only test the config database .BR slapd\-config (5), use .B \-n 0 as it is always the first database. .TP .BI \-o \ option\fR[ = value\fR] Specify an .I option with a(n optional) .IR value . Possible generic options/values are: .LP .nf syslog= (see `\-s' in slapd(8)) syslog\-level= (see `\-S' in slapd(8)) syslog\-user= (see `\-l' in slapd(8)) .fi .TP .BI \-Q Be extremely quiet: only the exit code indicates success (0) or not (any other value). .TP .B \-u enable dry-run mode (i.e. don't fail if databases cannot be opened, but config is fine). .TP .B \-v enable verbose mode. .SH EXAMPLES To check a .BR slapd.conf (5) give the command: .LP .nf .ft tt SBINDIR/slaptest \-f /ETCDIR/slapd.conf \-v .ft .fi .SH "SEE ALSO" .BR ldap (3), .BR slapd (8), .BR slapdn (8) .LP "OpenLDAP Administrator's Guide" (http://www.OpenLDAP.org/doc/admin/) .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man8/slapauth.80000644000175000017500000000603412563404150017130 0ustar ryanryan.TH SLAPAUTH 8C "RELEASEDATE" "OpenLDAP LDVERSION" .\" Copyright 2004-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .\" $OpenLDAP$ .SH NAME slapauth \- Check a list of string-represented IDs for LDAP authc/authz .SH SYNOPSIS .B SBINDIR/slapauth [\c .BI \-d \ debug-level\fR] [\c .BI \-f \ slapd.conf\fR] [\c .BI \-F \ confdir\fR] [\c .BI \-M \ mech\fR] [\c .BI \-o \ option\fR[ = value\fR]] [\c .BI \-R \ realm\fR] [\c .BI \-U \ authcID\fR] [\c .BR \-v ] [\c .BI \-X \ authzID\fR] .IR ID \ [ ... ] .LP .SH DESCRIPTION .LP .B Slapauth is used to check the behavior of the slapd in mapping identities for authentication and authorization purposes, as specified in .BR slapd.conf (5). It opens the .BR slapd.conf (5) configuration file or the .BR slapd\-config (5) backend, reads in the .BR authz\-policy / olcAuthzPolicy and .BR authz\-regexp / olcAuthzRegexp directives, and then parses the .I ID list given on the command-line. .LP .SH OPTIONS .TP .BI \-d \ debug-level enable debugging messages as defined by the specified .IR debug-level ; see .BR slapd (8) for details. .TP .BI \-f \ slapd.conf specify an alternative .BR slapd.conf (5) file. .TP .BI \-F \ confdir specify a config directory. If both .B \-f and .B \-F are specified, the config file will be read and converted to config directory format and written to the specified directory. If neither option is specified, an attempt to read the default config directory will be made before trying to use the default config file. If a valid config directory exists then the default config file is ignored. .TP .BI \-M \ mech specify a mechanism. .TP .BI \-o \ option\fR[ = value\fR] Specify an .I option with a(n optional) .IR value . Possible generic options/values are: .LP .nf syslog= (see `\-s' in slapd(8)) syslog\-level= (see `\-S' in slapd(8)) syslog\-user= (see `\-l' in slapd(8)) .fi .TP .BI \-R \ realm specify a realm. .TP .BI \-U \ authcID specify an ID to be used as .I authcID throughout the test session. If present, and if no .I authzID is given, the IDs in the ID list are treated as .IR authzID . .TP .BI \-X \ authzID specify an ID to be used as .I authzID throughout the test session. If present, and if no .I authcID is given, the IDs in the ID list are treated as .IR authcID . If both .I authcID and .I authzID are given via command line switch, the ID list cannot be present. .TP .B \-v enable verbose mode. .SH EXAMPLES The command .LP .nf .ft tt SBINDIR/slapauth \-f /ETCDIR/slapd.conf \-v \\ \-U bjorn \-X u:bjensen .ft .fi tests whether the user .I bjorn can assume the identity of the user .I bjensen provided the directives .LP .nf .ft tt authz\-policy from authz\-regexp "^uid=([^,]+).*,cn=auth$" "ldap:///dc=example,dc=net??sub?uid=$1" .ft .fi are defined in .BR slapd.conf (5). .SH "SEE ALSO" .BR ldap (3), .BR slapd (8), .BR slaptest (8) .LP "OpenLDAP Administrator's Guide" (http://www.OpenLDAP.org/doc/admin/) .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man8/slapschema.80000644000175000017500000001123712563404150017430 0ustar ryanryan.TH SLAPSCHEMA 8C "RELEASEDATE" "OpenLDAP LDVERSION" .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .\" $OpenLDAP$ .SH NAME slapschema \- SLAPD in-database schema checking utility .SH SYNOPSIS .B SBINDIR/slapschema [\c .BI \-a filter\fR] [\c .BI \-b suffix\fR] [\c .BR \-c ] [\c .BI \-d debug-level\fR] [\c .BI \-f slapd.conf\fR] [\c .BI \-F confdir\fR] [\c .BR \-g ] [\c .BI \-H URI\fR] [\c .BI \-l error-file\fR] [\c .BI \-n dbnum\fR] [\c .BI \-o option\fR[ = value\fR]] [\c .BI \-s subtree-dn\fR] [\c .BR \-v ] .LP .SH DESCRIPTION .LP .B Slapschema is used to check schema compliance of the contents of a .BR slapd (8) database. It opens the given database determined by the database number or suffix and checks the compliance of its contents with the corresponding schema. Errors are written to standard output or the specified file. Databases configured as .B subordinate of this one are also output, unless \fB\-g\fP is specified. .LP Administrators may need to modify existing schema items, including adding new required attributes to objectClasses, removing existing required or allowed attributes from objectClasses, entirely removing objectClasses, or any other change that may result in making perfectly valid entries no longer compliant with the modified schema. The execution of the .B slapschema tool after modifying the schema can point out inconsistencies that would otherwise surface only when inconsistent entries need to be modified. .LP The entry records are checked in database order, not superior first order. The entry records will be checked considering all (user and operational) attributes stored in the database. Dynamically generated attributes (such as subschemaSubentry) will not be considered. .SH OPTIONS .TP .BI \-a \ filter Only check entries matching the asserted filter. For example slapschema \-a \\ "(!(entryDN:dnSubtreeMatch:=ou=People,dc=example,dc=com))" will check all but the "ou=People,dc=example,dc=com" subtree of the "dc=example,dc=com" database. Deprecated; use \fB-H\fP \fIldap:///???(filter)\fP instead. .TP .BI \-b \ suffix Use the specified \fIsuffix\fR to determine which database to check. The \fB\-b\fP cannot be used in conjunction with the .B \-n option. .TP .B \-c Enable continue (ignore errors) mode. .TP .BI \-d \ debug-level Enable debugging messages as defined by the specified .IR debug-level ; see .BR slapd (8) for details. .TP .BI \-f \ slapd.conf Specify an alternative .BR slapd.conf (5) file. .TP .BI \-F \ confdir specify a config directory. If both .B \-f and .B \-F are specified, the config file will be read and converted to config directory format and written to the specified directory. If neither option is specified, an attempt to read the default config directory will be made before trying to use the default config file. If a valid config directory exists then the default config file is ignored. .TP .B \-g disable subordinate gluing. Only the specified database will be processed, and not its glued subordinates (if any). .TP .B \-H \ URI use dn, scope and filter from URI to only handle matching entries. .TP .BI \-l \ error-file Write errors to specified file instead of standard output. .TP .BI \-n \ dbnum Check the \fIdbnum\fR\-th database listed in the configuration file. The config database .BR slapd\-config (5), is always the first database, so use .B \-n 0 The .B \-n cannot be used in conjunction with the .B \-b option. .TP .BI \-o \ option\fR[ = value\fR] Specify an .I option with a(n optional) .IR value . Possible generic options/values are: .LP .nf syslog= (see `\-s' in slapd(8)) syslog\-level= (see `\-S' in slapd(8)) syslog\-user= (see `\-l' in slapd(8)) .fi .TP .BI \-s \ subtree-dn Only check entries in the subtree specified by this DN. Implies \fB\-b\fP \fIsubtree-dn\fP if no .B \-b nor .B \-n option is given. Deprecated; use \fB-H\fP \fIldap:///subtree-dn\fP instead. .TP .B \-v Enable verbose mode. .SH LIMITATIONS For some backend types, your .BR slapd (8) should not be running (at least, not in read-write mode) when you do this to ensure consistency of the database. It is always safe to run .B slapschema with the .BR slapd\-bdb (5), .BR slapd\-hdb (5), and .BR slapd\-null (5) backends. .SH EXAMPLES To check the schema compliance of your SLAPD database after modifications to the schema, and put any error in a file called .BR errors.ldif , give the command: .LP .nf .ft tt SBINDIR/slapschema \-l errors.ldif .ft .fi .SH "SEE ALSO" .BR ldap (3), .BR ldif (5), .BR slapd (8) .LP "OpenLDAP Administrator's Guide" (http://www.OpenLDAP.org/doc/admin/) .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man8/slapdn.80000644000175000017500000000447312563404150016575 0ustar ryanryan.TH SLAPDN 8C "RELEASEDATE" "OpenLDAP LDVERSION" .\" Copyright 2004-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .\" $OpenLDAP$ .SH NAME slapdn \- Check a list of string-represented LDAP DNs based on schema syntax .SH SYNOPSIS .B SBINDIR/slapdn [\c .BI \-d \ debug-level\fR] [\c .BI \-f \ slapd.conf\fR] [\c .BI \-F \ confdir\fR] [\c .BR \-N | \-P ] [\c .BI \-o \ option\fR[ = value\fR]] [\c .BR \-v ] .IR DN \ [...] .LP .SH DESCRIPTION .LP .B Slapdn is used to check the conformance of a DN based on the schema defined in .BR slapd (8) and that loaded via .BR slapd.conf (5). It opens the .BR slapd.conf (5) configuration file or the slapd\-config (5) backend, reads in the schema definitions, and then parses the .I DN list given on the command-line. .LP .SH OPTIONS .TP .BI \-d \ debug-level enable debugging messages as defined by the specified .IR debug-level ; see .BR slapd (8) for details. .TP .BI \-f \ slapd.conf specify an alternative .BR slapd.conf (5) file. .TP .BI \-F \ confdir specify a config directory. If both .B \-f and .B \-F are specified, the config file will be read and converted to config directory format and written to the specified directory. If neither option is specified, an attempt to read the default config directory will be made before trying to use the default config file. If a valid config directory exists then the default config file is ignored. .TP .BI \-N only output a normalized form of the \fIDN\fP, suitable to be used in a normalization tool; incompatible with .BR \-P . .TP .BI \-o \ option\fR[ = value\fR] Specify an .I option with a(n optional) .IR value . Possible generic options/values are: .LP .nf syslog= (see `\-s' in slapd(8)) syslog\-level= (see `\-S' in slapd(8)) syslog\-user= (see `\-l' in slapd(8)) .fi .TP .BI \-P only output a prettified form of the \fIDN\fP, suitable to be used in a check and beautification tool; incompatible with .BR \-N . .TP .B \-v enable verbose mode. .SH EXAMPLES To check a .B DN give the command: .LP .nf .ft tt SBINDIR/slapdn \-f /ETCDIR/slapd.conf \-v DN .ft .fi .SH "SEE ALSO" .BR ldap (3), .BR slapd (8), .BR slaptest (8) .LP "OpenLDAP Administrator's Guide" (http://www.OpenLDAP.org/doc/admin/) .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man8/slapindex.80000644000175000017500000000761012563404150017277 0ustar ryanryan.TH SLAPINDEX 8C "RELEASEDATE" "OpenLDAP LDVERSION" .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .\" $OpenLDAP$ .SH NAME slapindex \- Reindex entries in a SLAPD database .SH SYNOPSIS .B SBINDIR/slapindex [\c .BI \-b \ suffix\fR] [\c .BR \-c ] [\c .BI \-d \ debug-level\fR] [\c .BI \-f \ slapd.conf\fR] [\c .BI \-F \ confdir\fR] [\c .BR \-g ] [\c .BI \-n \ dbnum\fR] [\c .BI \-o \ option\fR[ = value\fR]] [\c .BR \-q ] [\c .BR \-t ] [\c .BR \-v ] [\c .IR attr [ ... ]] .B .LP .SH DESCRIPTION .LP .B Slapindex is used to regenerate .BR slapd (8) indices based upon the current contents of a database. It opens the given database determined by the database number or suffix and updates the indices for all values of all attributes of all entries. If a list of specific attributes is provided on the command line, only the indices for those attributes will be regenerated. Databases configured as .B subordinate of this one are also re-indexed, unless \fB\-g\fP is specified. All files eventually created by .BR slapindex will belong to the identity .BR slapindex is run as, so make sure you either run .BR slapindex with the same identity .BR slapd (8) will be run as (see option .B \-u in .BR slapd (8)), or change file ownership before running .BR slapd (8). .SH OPTIONS .TP .BI \-b \ suffix Use the specified \fIsuffix\fR to determine which database to generate output for. The \fB\-b\fP cannot be used in conjunction with the .B \-n option. .TP .B \-c enable continue (ignore errors) mode. .TP .BI \-d \ debug-level enable debugging messages as defined by the specified .IR debug-level ; see .BR slapd (8) for details. .TP .BI \-f \ slapd.conf specify an alternative .BR slapd.conf (5) file. .TP .BI \-F \ confdir specify a config directory. If both .B \-f and .B \-F are specified, the config file will be read and converted to config directory format and written to the specified directory. If neither option is specified, an attempt to read the default config directory will be made before trying to use the default config file. If a valid config directory exists then the default config file is ignored. .TP .B \-g disable subordinate gluing. Only the specified database will be processed, and not its glued subordinates (if any). .TP .BI \-n \ dbnum Generate output for the \fIdbnum\fR-th database listed in the configuration file. The config database .BR slapd\-config (5), is always the first database, so use .B \-n 0 The .B \-n cannot be used in conjunction with the .B \-b option. .TP .BI \-o \ option\fR[ = value\fR] Specify an .I option with a(n optional) .IR value . Possible generic options/values are: .LP .nf syslog= (see `\-s' in slapd(8)) syslog\-level= (see `\-S' in slapd(8)) syslog\-user= (see `\-l' in slapd(8)) .fi .TP .B \-q enable quick (fewer integrity checks) mode. Performs no consistency checks when writing the database. Improves indexing time, .B however the database will most likely be unusable if any errors or interruptions occur. .TP .B \-t enable truncate mode. Truncates (empties) an index database before indexing any entries. May only be used with Quick mode. .TP .B \-v enable verbose mode. .SH LIMITATIONS Your .BR slapd (8) should not be running (at least, not in read-write mode) when you do this to ensure consistency of the database. .LP This command provides ample opportunity for the user to obtain and drink their favorite beverage. .SH EXAMPLES To reindex your SLAPD database, give the command: .LP .nf .ft tt SBINDIR/slapindex .ft .fi To regenerate the index for only a specific attribute, e.g. "uid", give the command: .LP .nf .ft tt SBINDIR/slapindex uid .ft .fi .SH "SEE ALSO" .BR ldap (3), .BR ldif (5), .BR slapadd (8), .BR ldapadd (1), .BR slapd (8) .LP "OpenLDAP Administrator's Guide" (http://www.OpenLDAP.org/doc/admin/) .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/Project0000644000175000017500000000034112563404150015677 0ustar ryanryan.\" Shared Project Acknowledgement Text .B "OpenLDAP Software" is developed and maintained by The OpenLDAP Project . .B "OpenLDAP Software" is derived from University of Michigan LDAP 3.3 Release. openldap-2.4.42+dfsg/doc/man/man1/0000755000175000017500000000000012563404150015204 5ustar ryanryanopenldap-2.4.42+dfsg/doc/man/man1/Makefile.in0000644000175000017500000000103012563404150017243 0ustar ryanryan# man1 Makefile.in for OpenLDAP # $OpenLDAP$ ## This work is part of OpenLDAP Software . ## ## Copyright 1998-2015 The OpenLDAP Foundation. ## All rights reserved. ## ## Redistribution and use in source and binary forms, with or without ## modification, are permitted only as authorized by the OpenLDAP ## Public License. ## ## A copy of this license is available in the file LICENSE in the ## top-level directory of the distribution or, alternatively, at ## . MANSECT=1 openldap-2.4.42+dfsg/doc/man/man1/ldapmodify.1.links0000644000175000017500000000001212563404150020526 0ustar ryanryanldapadd.1 openldap-2.4.42+dfsg/doc/man/man1/ldapsearch.10000644000175000017500000003332112563404150017376 0ustar ryanryan.TH LDAPSEARCH 1 "RELEASEDATE" "OpenLDAP LDVERSION" .\" $OpenLDAP$ .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldapsearch \- LDAP search tool .SH SYNOPSIS .B ldapsearch [\c .BR \-V [ V ]] [\c .BI \-d \ debuglevel\fR] [\c .BR \-n ] [\c .BR \-v ] [\c .BR \-c ] [\c .BR \-u ] [\c .BR \-t [ t ]] [\c .BI \-T \ path\fR] [\c .BI \-F \ prefix\fR] [\c .BR \-A ] [\c .BR \-L [ L [ L ]]] [\c .BI \-S \ attribute\fR] [\c .BI \-b \ searchbase\fR] [\c .BR \-s \ { base \||\| one \||\| sub \||\| children }] [\c .BR \-a \ { never \||\| always \||\| search \||\| find }] [\c .BI \-l \ timelimit\fR] [\c .BI \-z \ sizelimit\fR] [\c .BI \-f \ file\fR] [\c .BR \-M [ M ]] [\c .BR \-x ] [\c .BI \-D \ binddn\fR] [\c .BR \-W ] [\c .BI \-w \ passwd\fR] [\c .BI \-y \ passwdfile\fR] [\c .BI \-H \ ldapuri\fR] [\c .BI \-h \ ldaphost\fR] [\c .BI \-p \ ldapport\fR] [\c .BR \-P \ { 2 \||\| 3 }] [\c .BR \-e \ [ ! ] \fIext\fP [ =\fIextparam\fP ]] [\c .BR \-E \ [ ! ] \fIext\fP [ =\fIextparam\fP ]] [\c .BI \-o \ opt \fR[= optparam \fR]] [\c .BI \-O \ security-properties\fR] [\c .BR \-I ] [\c .BR \-Q ] [\c .BR \-N ] [\c .BI \-U \ authcid\fR] [\c .BI \-R \ realm\fR] [\c .BI \-X \ authzid\fR] [\c .BI \-Y \ mech\fR] [\c .BR \-Z [ Z ]] .I filter [\c .IR attrs... ] .SH DESCRIPTION .I ldapsearch is a shell-accessible interface to the .BR ldap_search_ext (3) library call. .LP .B ldapsearch opens a connection to an LDAP server, binds, and performs a search using specified parameters. The \fIfilter\fP should conform to the string representation for search filters as defined in RFC 4515. If not provided, the default filter, \fB(objectClass=*)\fP, is used. .LP If .B ldapsearch finds one or more entries, the attributes specified by \fIattrs\fP are returned. If \fB*\fP is listed, all user attributes are returned. If \fB+\fP is listed, all operational attributes are returned. If no \fIattrs\fP are listed, all user attributes are returned. If only 1.1 is listed, no attributes will be returned. .LP The search results are displayed using an extended version of LDIF. Option \fI\-L\fP controls the format of the output. .SH OPTIONS .TP .BR \-V [ V ] Print version info. If \fB\-VV\fP is given, only the version information is printed. .TP .BI \-d \ debuglevel Set the LDAP debugging level to \fIdebuglevel\fP. .B ldapsearch must be compiled with LDAP_DEBUG defined for this option to have any effect. .TP .B \-n Show what would be done, but don't actually perform the search. Useful for debugging in conjunction with \fB\-v\fP. .TP .B \-v Run in verbose mode, with many diagnostics written to standard output. .TP .B \-c Continuous operation mode. Errors are reported, but ldapsearch will continue with searches. The default is to exit after reporting an error. Only useful in conjunction with \fB\-f\fP. .TP .B \-u Include the User Friendly Name form of the Distinguished Name (DN) in the output. .TP .BR \-t [ t ] A single \fB\-t\fP writes retrieved non-printable values to a set of temporary files. This is useful for dealing with values containing non-character data such as jpegPhoto or audio. A second \fB\-t\fP writes all retrieved values to files. .TP .BI \-T \ path Write temporary files to directory specified by \fIpath\fP (default: \fB/var/tmp/\fP) .TP .BI \-F \ prefix URL prefix for temporary files. Default is \fBfile://\fIpath\fP where \fIpath\fP is \fB/var/tmp/\fP or specified with \fB\-T\fP. .TP .B \-A Retrieve attributes only (no values). This is useful when you just want to see if an attribute is present in an entry and are not interested in the specific values. .TP .B \-L Search results are display in LDAP Data Interchange Format detailed in .BR ldif (5). A single \fB\-L\fP restricts the output to LDIFv1. A second \fB\-L\fP disables comments. A third \fB\-L\fP disables printing of the LDIF version. The default is to use an extended version of LDIF. .TP .BI \-S \ attribute Sort the entries returned based on \fIattribute\fP. The default is not to sort entries returned. If \fIattribute\fP is a zero-length string (""), the entries are sorted by the components of their Distinguished Name. See .BR ldap_sort (3) for more details. Note that .B ldapsearch normally prints out entries as it receives them. The use of the \fB\-S\fP option defeats this behavior, causing all entries to be retrieved, then sorted, then printed. .TP .BI \-b \ searchbase Use \fIsearchbase\fP as the starting point for the search instead of the default. .TP .BR \-s \ { base \||\| one \||\| sub \||\| children } Specify the scope of the search to be one of .BR base , .BR one , .BR sub , or .B children to specify a base object, one-level, subtree, or children search. The default is .BR sub . Note: .I children scope requires LDAPv3 subordinate feature extension. .TP .BR \-a \ { never \||\| always \||\| search \||\| find } Specify how aliases dereferencing is done. Should be one of .BR never , .BR always , .BR search , or .B find to specify that aliases are never dereferenced, always dereferenced, dereferenced when searching, or dereferenced only when locating the base object for the search. The default is to never dereference aliases. .TP .BI \-l \ timelimit wait at most \fItimelimit\fP seconds for a search to complete. A timelimit of .I 0 (zero) or .I none means no limit. A timelimit of .I max means the maximum integer allowable by the protocol. A server may impose a maximal timelimit which only the root user may override. .TP .BI \-z \ sizelimit retrieve at most \fIsizelimit\fP entries for a search. A sizelimit of .I 0 (zero) or .I none means no limit. A sizelimit of .I max means the maximum integer allowable by the protocol. A server may impose a maximal sizelimit which only the root user may override. .TP .BI \-f \ file Read a series of lines from \fIfile\fP, performing one LDAP search for each line. In this case, the \fIfilter\fP given on the command line is treated as a pattern where the first and only occurrence of \fB%s\fP is replaced with a line from \fIfile\fP. Any other occurrence of the the \fB%\fP character in the pattern will be regarded as an error. Where it is desired that the search filter include a \fB%\fP character, the character should be encoded as \fB\\25\fP (see RFC 4515). If \fIfile\fP is a single \fB\-\fP character, then the lines are read from standard input. .B ldapsearch will exit when the first non-successful search result is returned, unless \fB\-c\fP is used. .TP .BR \-M [ M ] Enable manage DSA IT control. .B \-MM makes control critical. .TP .B \-x Use simple authentication instead of SASL. .TP .BI \-D \ binddn Use the Distinguished Name \fIbinddn\fP to bind to the LDAP directory. For SASL binds, the server is expected to ignore this value. .TP .B \-W Prompt for simple authentication. This is used instead of specifying the password on the command line. .TP .BI \-w \ passwd Use \fIpasswd\fP as the password for simple authentication. .TP .BI \-y \ passwdfile Use complete contents of \fIpasswdfile\fP as the password for simple authentication. .TP .BI \-H \ ldapuri Specify URI(s) referring to the ldap server(s); a list of URI, separated by whitespace or commas is expected; only the protocol/host/port fields are allowed. As an exception, if no host/port is specified, but a DN is, the DN is used to look up the corresponding host(s) using the DNS SRV records, according to RFC 2782. The DN must be a non-empty sequence of AVAs whose attribute type is "dc" (domain component), and must be escaped according to RFC 2396. .TP .BI \-h \ ldaphost Specify an alternate host on which the ldap server is running. Deprecated in favor of \fB\-H\fP. .TP .BI \-p \ ldapport Specify an alternate TCP port where the ldap server is listening. Deprecated in favor of \fB\-H\fP. .TP .BR \-P \ { 2 \||\| 3 } Specify the LDAP protocol version to use. .TP .BR \-e \ [ ! ] \fIext\fP [ =\fIextparam\fP ] .TP .BR \-E \ [ ! ] \fIext\fP [ =\fIextparam\fP ] Specify general extensions with \fB\-e\fP and search extensions with \fB\-E\fP. \'\fB!\fP\' indicates criticality. General extensions: .nf [!]assert= (an RFC 4515 Filter) !authzid= ("dn:" or "u:") [!]bauthzid (RFC 3829 authzid control) [!]chaining[=[/]] [!]manageDSAit [!]noop ppolicy [!]postread[=] (a comma-separated attribute list) [!]preread[=] (a comma-separated attribute list) [!]relax sessiontracking abandon,cancel,ignore (SIGINT sends abandon/cancel, or ignores response; if critical, doesn't wait for SIGINT. not really controls) .fi Search extensions: .nf !dontUseCopy [!]domainScope (domain scope) [!]mv= (matched values filter) [!]pr=[/prompt|noprompt] (paged results/prompt) [!]sss=[\-][/[\-]...] (server side sorting) [!]subentries[=true|false] (subentries) [!]sync=ro[/] (LDAP Sync refreshOnly) rp[/][/] (LDAP Sync refreshAndPersist) [!]vlv=/(//|:) (virtual list view) [!]deref=derefAttr:attr[,attr[...]][;derefAttr:attr[,attr[...]]] [!][=] .fi .TP .BI \-o \ opt \fR[= optparam \fR] Specify general options. General options: .nf nettimeout= (in seconds, or "none" or "max") ldif-wrap= (in columns, or "no" for no wrapping) .fi .TP .BI \-O \ security-properties Specify SASL security properties. .TP .B \-I Enable SASL Interactive mode. Always prompt. Default is to prompt only as needed. .TP .B \-Q Enable SASL Quiet mode. Never prompt. .TP .B \-N Do not use reverse DNS to canonicalize SASL host name. .TP .BI \-U \ authcid Specify the authentication ID for SASL bind. The form of the ID depends on the actual SASL mechanism used. .TP .BI \-R \ realm Specify the realm of authentication ID for SASL bind. The form of the realm depends on the actual SASL mechanism used. .TP .BI \-X \ authzid Specify the requested authorization ID for SASL bind. .I authzid must be one of the following formats: .BI dn: "" or .BI u: .TP .BI \-Y \ mech Specify the SASL mechanism to be used for authentication. If it's not specified, the program will choose the best mechanism the server knows. .TP .BR \-Z [ Z ] Issue StartTLS (Transport Layer Security) extended operation. If you use \fB\-ZZ\fP, the command will require the operation to be successful. .SH OUTPUT FORMAT If one or more entries are found, each entry is written to standard output in LDAP Data Interchange Format or .BR ldif (5): .LP .nf version: 1 # bjensen, example, net dn: uid=bjensen,dc=example,dc=net objectClass: person objectClass: dcObject uid: bjensen cn: Barbara Jensen sn: Jensen ... .fi .LP If the \fB\-t\fP option is used, the URI of a temporary file is used in place of the actual value. If the \fB\-A\fP option is given, only the "attributename" part is written. .SH EXAMPLE The following command: .LP .nf ldapsearch \-LLL "(sn=smith)" cn sn telephoneNumber .fi .LP will perform a subtree search (using the default search base and other parameters defined in .BR ldap.conf (5)) for entries with a surname (sn) of smith. The common name (cn), surname (sn) and telephoneNumber values will be retrieved and printed to standard output. The output might look something like this if two entries are found: .LP .nf dn: uid=jts,dc=example,dc=com cn: John Smith cn: John T. Smith sn: Smith sn;lang\-en: Smith sn;lang\-de: Schmidt telephoneNumber: 1 555 123\-4567 dn: uid=sss,dc=example,dc=com cn: Steve Smith cn: Steve S. Smith sn: Smith sn;lang\-en: Smith sn;lang\-de: Schmidt telephoneNumber: 1 555 765\-4321 .fi .LP The command: .LP .nf ldapsearch \-LLL \-u \-t "(uid=xyz)" jpegPhoto audio .fi .LP will perform a subtree search using the default search base for entries with user id of "xyz". The user friendly form of the entry's DN will be output after the line that contains the DN itself, and the jpegPhoto and audio values will be retrieved and written to temporary files. The output might look like this if one entry with one value for each of the requested attributes is found: .LP .nf dn: uid=xyz,dc=example,dc=com ufn: xyz, example, com audio:< file:///tmp/ldapsearch\-audio\-a19924 jpegPhoto:< file:///tmp/ldapsearch\-jpegPhoto\-a19924 .fi .LP This command: .LP .nf ldapsearch \-LLL \-s one \-b "c=US" "(o=University*)" o description .fi .LP will perform a one-level search at the c=US level for all entries whose organization name (o) begins with \fBUniversity\fP. The organization name and description attribute values will be retrieved and printed to standard output, resulting in output similar to this: .LP .nf dn: o=University of Alaska Fairbanks,c=US o: University of Alaska Fairbanks description: Preparing Alaska for a brave new yesterday description: leaf node only dn: o=University of Colorado at Boulder,c=US o: University of Colorado at Boulder description: No personnel information description: Institution of education and research dn: o=University of Colorado at Denver,c=US o: University of Colorado at Denver o: UCD o: CU/Denver o: CU\-Denver description: Institute for Higher Learning and Research dn: o=University of Florida,c=US o: University of Florida o: UFl description: Warper of young minds ... .fi .SH DIAGNOSTICS Exit status is zero if no errors occur. Errors result in a non-zero exit status and a diagnostic message being written to standard error. .SH "SEE ALSO" .BR ldapadd (1), .BR ldapdelete (1), .BR ldapmodify (1), .BR ldapmodrdn (1), .BR ldap.conf (5), .BR ldif (5), .BR ldap (3), .BR ldap_search_ext (3), .BR ldap_sort (3) .SH AUTHOR The OpenLDAP Project .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man1/ldapmodrdn.10000644000175000017500000001504012563404150017412 0ustar ryanryan.TH LDAPMODRDN 1 "RELEASEDATE" "OpenLDAP LDVERSION" .\" $OpenLDAP$ .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldapmodrdn \- LDAP rename entry tool .SH SYNOPSIS .B ldapmodrdn [\c .BR \-V [ V ]] [\c .BI \-d \ debuglevel\fR] [\c .BR \-n ] [\c .BR \-v ] [\c .BR \-r ] [\c .BI \-s \ newsup\fR] [\c .BR \-c ] [\c .BI \-f \ file\fR] [\c .BR \-M [ M ]] [\c .BR \-x ] [\c .BI \-D \ binddn\fR] [\c .BR \-W ] [\c .BI \-w \ passwd\fR] [\c .BI \-y \ passwdfile\fR] [\c .BI \-H \ ldapuri\fR] [\c .BI \-h \ ldaphost\fR] [\c .BI \-p \ ldapport\fR] [\c .BR \-P \ { 2 \||\| 3 }] [\c .BR \-e \ [ ! ] \fIext\fP [ =\fIextparam\fP ]] [\c .BR \-E \ [ ! ] \fIext\fP [ =\fIextparam\fP ]] [\c .BI \-o \ opt \fR[= optparam \fR]] [\c .BI \-O \ security-properties\fR] [\c .BR \-I ] [\c .BR \-Q ] [\c .BR \-N ] [\c .BI \-U \ authcid\fR] [\c .BI \-R \ realm\fR] [\c .BI \-X \ authzid\fR] [\c .BI \-Y \ mech\fR] [\c .BR \-Z [ Z ]] [\c .I dn rdn\fR] .SH DESCRIPTION .B ldapmodrdn is a shell-accessible interface to the .BR ldap_rename (3) library call. .LP .B ldapmodrdn opens a connection to an LDAP server, binds, and modifies the RDN of entries. The entry information is read from standard input, from \fIfile\fP through the use of the .RI \- f option, or from the command-line pair \fIdn\fP and \fIrdn\fP. .SH OPTIONS .TP .BR \-V [ V ] Print version info. If \fB\-VV\fP is given, only the version information is printed. .TP .BI \-d \ debuglevel Set the LDAP debugging level to \fIdebuglevel\fP. .B ldapmodrdn must be compiled with LDAP_DEBUG defined for this option to have any effect. .TP .B \-n Show what would be done, but don't actually change entries. Useful for debugging in conjunction with \fB\-v\fP. .TP .B \-v Use verbose mode, with many diagnostics written to standard output. .TP .B \-r Remove old RDN values from the entry. Default is to keep old values. .TP .BI \-s \ newsup Specify a new superior entry. (I.e., move the target entry and make it a child of the new superior.) This option is not supported in LDAPv2. .TP .B \-c Continuous operation mode. Errors are reported, but ldapmodrdn will continue with modifications. The default is to exit after reporting an error. .TP .BI \-f \ file Read the entry modification information from \fIfile\fP instead of from standard input or the command-line. .TP .BR \-M [ M ] Enable manage DSA IT control. .B \-MM makes control critical. .TP .B \-x Use simple authentication instead of SASL. .TP .BI \-D \ binddn Use the Distinguished Name \fIbinddn\fP to bind to the LDAP directory. For SASL binds, the server is expected to ignore this value. .TP .B \-W Prompt for simple authentication. This is used instead of specifying the password on the command line. .TP .BI \-w \ passwd Use \fIpasswd\fP as the password for simple authentication. .TP .BI \-y \ passwdfile Use complete contents of \fIpasswdfile\fP as the password for simple authentication. .TP .BI \-H \ ldapuri Specify URI(s) referring to the ldap server(s); only the protocol/host/port fields are allowed; a list of URI, separated by whitespace or commas is expected. .TP .BI \-h \ ldaphost Specify an alternate host on which the ldap server is running. Deprecated in favor of \fB\-H\fP. .TP .BI \-p \ ldapport Specify an alternate TCP port where the ldap server is listening. Deprecated in favor of \fB\-H\fP. .TP .BR \-P \ { 2 \||\| 3 } Specify the LDAP protocol version to use. .TP .BR \-e \ [ ! ] \fIext\fP [ =\fIextparam\fP ] .TP .BR \-E \ [ ! ] \fIext\fP [ =\fIextparam\fP ] Specify general extensions with \fB\-e\fP and modrdn extensions with \fB\-E\fP. \'\fB!\fP\' indicates criticality. General extensions: .nf [!]assert= (an RFC 4515 Filter) !authzid= ("dn:" or "u:") [!]bauthzid (RFC 3829 authzid control) [!]chaining[=[/]] [!]manageDSAit [!]noop ppolicy [!]postread[=] (a comma-separated attribute list) [!]preread[=] (a comma-separated attribute list) [!]relax sessiontracking abandon,cancel,ignore (SIGINT sends abandon/cancel, or ignores response; if critical, doesn't wait for SIGINT. not really controls) .fi Modrdn extensions: .nf (none) .fi .TP .BI \-o \ opt \fR[= optparam \fR] Specify general options. General options: .nf nettimeout= (in seconds, or "none" or "max") ldif-wrap= (in columns, or "no" for no wrapping) .fi .TP .BI \-O \ security-properties Specify SASL security properties. .TP .B \-I Enable SASL Interactive mode. Always prompt. Default is to prompt only as needed. .TP .B \-Q Enable SASL Quiet mode. Never prompt. .TP .B \-N Do not use reverse DNS to canonicalize SASL host name. .TP .BI \-U \ authcid Specify the authentication ID for SASL bind. The form of the ID depends on the actual SASL mechanism used. .TP .BI \-R \ realm Specify the realm of authentication ID for SASL bind. The form of the realm depends on the actual SASL mechanism used. .TP .BI \-X \ authzid Specify the requested authorization ID for SASL bind. .I authzid must be one of the following formats: .BI dn: "" or .BI u: .TP .BI \-Y \ mech Specify the SASL mechanism to be used for authentication. If it's not specified, the program will choose the best mechanism the server knows. .TP .BR \-Z [ Z ] Issue StartTLS (Transport Layer Security) extended operation. If you use \fB\-ZZ\fP, the command will require the operation to be successful. .SH INPUT FORMAT If the command-line arguments \fIdn\fP and \fIrdn\fP are given, \fIrdn\fP will replace the RDN of the entry specified by the DN, \fIdn\fP. .LP Otherwise, the contents of \fIfile\fP (or standard input if no \fB\-f\fP flag is given) should consist of one or more entries. .LP .nf Distinguished Name (DN) Relative Distinguished Name (RDN) .fi .LP One or more blank lines may be used to separate each DN/RDN pair. .SH EXAMPLE Assuming that the file .B /tmp/entrymods exists and has the contents: .LP .nf cn=Modify Me,dc=example,dc=com cn=The New Me .fi .LP the command: .LP .nf ldapmodrdn \-r \-f /tmp/entrymods .fi .LP will change the RDN of the "Modify Me" entry from "Modify Me" to "The New Me" and the old cn, "Modify Me" will be removed. .LP .SH DIAGNOSTICS Exit status is 0 if no errors occur. Errors result in a non-zero exit status and a diagnostic message being written to standard error. .SH "SEE ALSO" .BR ldapadd (1), .BR ldapdelete (1), .BR ldapmodify (1), .BR ldapsearch (1), .BR ldap.conf (5), .BR ldap (3), .BR ldap_rename (3) .SH AUTHOR The OpenLDAP Project .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man1/ldapdelete.10000644000175000017500000001456612563404150017405 0ustar ryanryan.TH LDAPDELETE 1 "RELEASEDATE" "OpenLDAP LDVERSION" .\" $OpenLDAP$ .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldapdelete \- LDAP delete entry tool .SH SYNOPSIS .B ldapdelete [\c .BR \-V [ V ]] [\c .BI \-d \ debuglevel\fR] [\c .BR \-n ] [\c .BR \-v ] [\c .BR \-c ] [\c .BI \-f \ file\fR] [\c .BR \-r ] [\c .BI \-z \ sizelimit\fR] [\c .BR \-M [ M ]] [\c .BR \-x ] [\c .BI \-D \ binddn\fR] [\c .BR \-W ] [\c .BI \-w \ passwd\fR] [\c .BI \-y \ passwdfile\fR] [\c .BI \-H \ ldapuri\fR] [\c .BI \-h \ ldaphost\fR] [\c .BI \-p \ ldapport\fR] [\c .BR \-P \ { 2 \||\| 3 }] [\c .BR \-e \ [ ! ] \fIext\fP [ =\fIextparam\fP ]] [\c .BR \-E \ [ ! ] \fIext\fP [ =\fIextparam\fP ]] [\c .BI \-o \ opt \fR[= optparam \fR]] [\c .BI \-O \ security-properties\fR] [\c .BR \-I ] [\c .BR \-Q ] [\c .BR \-N ] [\c .BI \-U \ authcid\fR] [\c .BI \-R \ realm\fR] [\c .BI \-X \ authzid\fR] [\c .BI \-Y \ mech\fR] [\c .BR \-Z [ Z ]] [\c .IR DN \ [ ... ]] .SH DESCRIPTION .I ldapdelete is a shell-accessible interface to the .BR ldap_delete_ext (3) library call. .LP .B ldapdelete opens a connection to an LDAP server, binds, and deletes one or more entries. If one or more \fIDN\fP arguments are provided, entries with those Distinguished Names are deleted. Each \fIDN\fP should be provided using the LDAPv3 string representation as defined in RFC 4514. If no \fIDN\fP arguments are provided, a list of DNs is read from standard input (or from \fIfile\fP if the \fB\-f\fP flag is used). .SH OPTIONS .TP .BR \-V [ V ] Print version info. If \fB\-VV\fP is given, only the version information is printed. .TP .BI \-d \ debuglevel Set the LDAP debugging level to \fIdebuglevel\fP. .B ldapdelete must be compiled with LDAP_DEBUG defined for this option to have any effect. .TP .B \-n Show what would be done, but don't actually delete entries. Useful for debugging in conjunction with \fB\-v\fP. .TP .B \-v Use verbose mode, with many diagnostics written to standard output. .TP .B \-c Continuous operation mode. Errors are reported, but .B ldapdelete will continue with deletions. The default is to exit after reporting an error. .TP .BI \-f \ file Read a series of DNs from \fIfile\fP, one per line, performing an LDAP delete for each. .TP .B \-r Do a recursive delete. If the DN specified isn't a leaf, its children, and all their children are deleted down the tree. No verification is done, so if you add this switch, ldapdelete will happily delete large portions of your tree. Use with care. .TP .BI \-z \ sizelimit Use \fIsizelimit\fP when searching for children DN to delete, to circumvent any server-side size limit. Only useful in conjunction with \fB\-r\fP. .TP .BR \-M [ M ] Enable manage DSA IT control. .B \-MM makes control critical. .TP .B \-x Use simple authentication instead of SASL. .TP .BI \-D \ binddn Use the Distinguished Name \fIbinddn\fP to bind to the LDAP directory. For SASL binds, the server is expected to ignore this value. .TP .B \-W Prompt for simple authentication. This is used instead of specifying the password on the command line. .TP .BI \-w \ passwd Use \fIpasswd\fP as the password for simple authentication. .TP .BI \-y \ passwdfile Use complete contents of \fIpasswdfile\fP as the password for simple authentication. .TP .BI \-H \ ldapuri Specify URI(s) referring to the ldap server(s); only the protocol/host/port fields are allowed; a list of URI, separated by whitespace or commas is expected. .TP .BI \-h \ ldaphost Specify an alternate host on which the ldap server is running. Deprecated in favor of \fB\-H\fP. .TP .BI \-p \ ldapport Specify an alternate TCP port where the ldap server is listening. Deprecated in favor of \fB\-H\fP. .TP .BR \-P \ { 2 \||\| 3 } Specify the LDAP protocol version to use. .TP .BR \-e \ [ ! ] \fIext\fP [ =\fIextparam\fP ] .TP .BR \-E \ [ ! ] \fIext\fP [ =\fIextparam\fP ] Specify general extensions with \fB\-e\fP and delete extensions with \fB\-E\fP. \'\fB!\fP\' indicates criticality. General extensions: .nf [!]assert= (an RFC 4515 Filter) !authzid= ("dn:" or "u:") [!]bauthzid (RFC 3829 authzid control) [!]chaining[=[/]] [!]manageDSAit [!]noop ppolicy [!]postread[=] (a comma-separated attribute list) [!]preread[=] (a comma-separated attribute list) [!]relax sessiontracking abandon,cancel,ignore (SIGINT sends abandon/cancel, or ignores response; if critical, doesn't wait for SIGINT. not really controls) .fi Delete extensions: .nf (none) .fi .TP .BI \-o \ opt \fR[= optparam \fR] Specify general options. General options: .nf nettimeout= (in seconds, or "none" or "max") ldif-wrap= (in columns, or "no" for no wrapping) .fi .TP .BI \-O \ security-properties Specify SASL security properties. .TP .B \-I Enable SASL Interactive mode. Always prompt. Default is to prompt only as needed. .TP .B \-Q Enable SASL Quiet mode. Never prompt. .TP .B \-N Do not use reverse DNS to canonicalize SASL host name. .TP .BI \-U \ authcid Specify the authentication ID for SASL bind. The form of the identity depends on the actual SASL mechanism used. .TP .BI \-R \ realm Specify the realm of authentication ID for SASL bind. The form of the realm depends on the actual SASL mechanism used. .TP .BI \-X \ authzid Specify the requested authorization ID for SASL bind. .I authzid must be one of the following formats: .BI dn: "" or .BI u: .TP .BI \-Y \ mech Specify the SASL mechanism to be used for authentication. If it's not specified, the program will choose the best mechanism the server knows. .TP .BR \-Z [ Z ] Issue StartTLS (Transport Layer Security) extended operation. If you use \fB\-ZZ\fP, the command will require the operation to be successful. .SH EXAMPLE The following command: .LP .nf ldapdelete "cn=Delete Me,dc=example,dc=com" .fi .LP will attempt to delete the entry named "cn=Delete Me,dc=example,dc=com". Of course it would probably be necessary to supply authentication credentials. .SH DIAGNOSTICS Exit status is 0 if no errors occur. Errors result in a non-zero exit status and a diagnostic message being written to standard error. .SH "SEE ALSO" .BR ldap.conf (5), .BR ldapadd (1), .BR ldapmodify (1), .BR ldapmodrdn (1), .BR ldapsearch (1), .BR ldap (3), .BR ldap_delete_ext (3) .SH AUTHOR The OpenLDAP Project .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man1/ldapmodify.10000644000175000017500000002064212563404150017422 0ustar ryanryan.TH LDAPMODIFY 1 "RELEASEDATE" "OpenLDAP LDVERSION" .\" $OpenLDAP$ .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldapmodify, ldapadd \- LDAP modify entry and LDAP add entry tools .SH SYNOPSIS .B ldapmodify [\c .BR \-V [ V ]] [\c .BI \-d \ debuglevel\fR] [\c .BR \-n ] [\c .BR \-v ] [\c .BR \-a ] [\c .BR \-c ] [\c .BI \-f \ file\fR] [\c .BI \-S \ file\fR] [\c .BR \-M [ M ]] [\c .BR \-x ] [\c .BI \-D \ binddn\fR] [\c .BR \-W ] [\c .BI \-w \ passwd\fR] [\c .BI \-y \ passwdfile\fR] [\c .BI \-H \ ldapuri\fR] [\c .BI \-h \ ldaphost\fR] [\c .BI \-p \ ldapport\fR] [\c .BR \-P \ { 2 \||\| 3 }] [\c .BR \-e \ [ ! ] \fIext\fP [ =\fIextparam\fP ]] [\c .BR \-E \ [ ! ] \fIext\fP [ =\fIextparam\fP ]] [\c .BI \-o \ opt \fR[= optparam \fR]] [\c .BI \-O \ security-properties\fR] [\c .BR \-I ] [\c .BR \-Q ] [\c .BR \-N ] [\c .BI \-U \ authcid\fR] [\c .BI \-R \ realm\fR] [\c .BI \-X \ authzid\fR] [\c .BI \-Y \ mech\fR] [\c .BR \-Z [ Z ]] .LP .B ldapadd [\c .BR \-V [ V ]] [\c .BI \-d \ debuglevel\fR] [\c .BR \-n ] [\c .BR \-v ] [\c .BR \-c ] [\c .BI \-f \ file\fR] [\c .BI \-S \ file\fR] [\c .BR \-M [ M ]] [\c .BR \-x ] [\c .BI \-D \ binddn\fR] [\c .BR \-W ] [\c .BI \-w \ passwd\fR] [\c .BI \-y \ passwdfile\fR] [\c .BI \-H \ ldapuri\fR] [\c .BI \-h \ ldaphost\fR] [\c .BI \-p \ ldapport\fR] [\c .BR \-P \ { 2 \||\| 3 }] [\c .BR \-e \ [ ! ] \fIext\fP [ =\fIextparam\fP ]] [\c .BR \-E \ [ ! ] \fIext\fP [ =\fIextparam\fP ]] [\c .BI \-o \ opt \fR[= optparam \fR]] [\c .BI \-O \ security-properties\fR] [\c .BR \-I ] [\c .BR \-Q ] [\c .BR \-N ] [\c .BI \-U \ authcid\fR] [\c .BI \-R \ realm\fR] [\c .BI \-X \ authzid\fR] [\c .BI \-Y \ mech\fR] [\c .BR \-Z [ Z ]] .SH DESCRIPTION .B ldapmodify is a shell-accessible interface to the .BR ldap_add_ext (3), .BR ldap_modify_ext (3), .BR ldap_delete_ext (3) and .BR ldap_rename (3). library calls. .B ldapadd is implemented as a hard link to the ldapmodify tool. When invoked as .B ldapadd the \fB\-a\fP (add new entry) flag is turned on automatically. .LP .B ldapmodify opens a connection to an LDAP server, binds, and modifies or adds entries. The entry information is read from standard input or from \fIfile\fP through the use of the \fB\-f\fP option. .SH OPTIONS .TP .BR \-V [ V ] Print version info. If \fB\-VV\fP is given, only the version information is printed. .TP .BI \-d \ debuglevel Set the LDAP debugging level to \fIdebuglevel\fP. .B ldapmodify must be compiled with LDAP_DEBUG defined for this option to have any effect. .TP .B \-n Show what would be done, but don't actually modify entries. Useful for debugging in conjunction with \fB\-v\fP. .TP .B \-v Use verbose mode, with many diagnostics written to standard output. .TP .B \-a Add new entries. The default for .B ldapmodify is to modify existing entries. If invoked as .BR ldapadd , this flag is always set. .TP .B \-c Continuous operation mode. Errors are reported, but .B ldapmodify will continue with modifications. The default is to exit after reporting an error. .TP .BI \-f \ file Read the entry modification information from \fIfile\fP instead of from standard input. .TP .BI \-S \ file Add or change records which were skipped due to an error are written to \fIfile\fP and the error message returned by the server is added as a comment. Most useful in conjunction with \fB\-c\fP. .TP .BR \-M [ M ] Enable manage DSA IT control. .B \-MM makes control critical. .TP .B \-x Use simple authentication instead of SASL. .TP .BI \-D \ binddn Use the Distinguished Name \fIbinddn\fP to bind to the LDAP directory. For SASL binds, the server is expected to ignore this value. .TP .B \-W Prompt for simple authentication. This is used instead of specifying the password on the command line. .TP .BI \-w \ passwd Use \fIpasswd\fP as the password for simple authentication. .TP .BI \-y \ passwdfile Use complete contents of \fIpasswdfile\fP as the password for simple authentication. .TP .BI \-H \ ldapuri Specify URI(s) referring to the ldap server(s); only the protocol/host/port fields are allowed; a list of URI, separated by whitespace or commas is expected. .TP .BI \-h \ ldaphost Specify an alternate host on which the ldap server is running. Deprecated in favor of \fB\-H\fP. .TP .BI \-p \ ldapport Specify an alternate TCP port where the ldap server is listening. Deprecated in favor of \fB\-H\fP. .TP .BR \-P \ { 2 \||\| 3 } Specify the LDAP protocol version to use. .TP .BR \-e \ [ ! ] \fIext\fP [ =\fIextparam\fP ] .TP .BR \-E \ [ ! ] \fIext\fP [ =\fIextparam\fP ] Specify general extensions with \fB\-e\fP and modify extensions with \fB\-E\fP. \'\fB!\fP\' indicates criticality. General extensions: .nf [!]assert= (an RFC 4515 Filter) !authzid= ("dn:" or "u:") [!]bauthzid (RFC 3829 authzid control) [!]chaining[=[/]] [!]manageDSAit [!]noop ppolicy [!]postread[=] (a comma-separated attribute list) [!]preread[=] (a comma-separated attribute list) [!]relax sessiontracking abandon,cancel,ignore (SIGINT sends abandon/cancel, or ignores response; if critical, doesn't wait for SIGINT. not really controls) .fi Modify extensions: .nf [!]txn[=abort|commit] .fi .TP .BI \-o \ opt \fR[= optparam \fR]] Specify general options. General options: .nf nettimeout= (in seconds, or "none" or "max") ldif-wrap= (in columns, or "no" for no wrapping) .fi .TP .BI \-O \ security-properties Specify SASL security properties. .TP .B \-I Enable SASL Interactive mode. Always prompt. Default is to prompt only as needed. .TP .B \-Q Enable SASL Quiet mode. Never prompt. .TP .B \-N Do not use reverse DNS to canonicalize SASL host name. .TP .BI \-U \ authcid Specify the authentication ID for SASL bind. The form of the ID depends on the actual SASL mechanism used. .TP .BI \-R \ realm Specify the realm of authentication ID for SASL bind. The form of the realm depends on the actual SASL mechanism used. .TP .BI \-X \ authzid Specify the requested authorization ID for SASL bind. .I authzid must be one of the following formats: .BI dn: "" or .BI u: .TP .BI \-Y \ mech Specify the SASL mechanism to be used for authentication. If it's not specified, the program will choose the best mechanism the server knows. .TP .BR \-Z [ Z ] Issue StartTLS (Transport Layer Security) extended operation. If you use .B \-ZZ\c , the command will require the operation to be successful. .SH INPUT FORMAT The contents of \fIfile\fP (or standard input if no \fB\-f\fP flag is given on the command line) must conform to the format defined in .BR ldif (5) (LDIF as defined in RFC 2849). .SH EXAMPLES Assuming that the file .B /tmp/entrymods exists and has the contents: .LP .nf dn: cn=Modify Me,dc=example,dc=com changetype: modify replace: mail mail: modme@example.com \- add: title title: Grand Poobah \- add: jpegPhoto jpegPhoto:< file:///tmp/modme.jpeg \- delete: description \- .fi .LP the command: .LP .nf ldapmodify \-f /tmp/entrymods .fi .LP will replace the contents of the "Modify Me" entry's .I mail attribute with the value "modme@example.com", add a .I title of "Grand Poobah", and the contents of the file "/tmp/modme.jpeg" as a .IR jpegPhoto , and completely remove the .I description attribute. .LP Assuming that the file .B /tmp/newentry exists and has the contents: .LP .nf dn: cn=Barbara Jensen,dc=example,dc=com objectClass: person cn: Barbara Jensen cn: Babs Jensen sn: Jensen title: the world's most famous mythical manager mail: bjensen@example.com uid: bjensen .fi .LP the command: .LP .nf ldapadd \-f /tmp/newentry .fi .LP will add a new entry for Babs Jensen, using the values from the file .B /tmp/newentry. .LP Assuming that the file .B /tmp/entrymods exists and has the contents: .LP .nf dn: cn=Barbara Jensen,dc=example,dc=com changetype: delete .fi .LP the command: .LP .nf ldapmodify \-f /tmp/entrymods .fi .LP will remove Babs Jensen's entry. .SH DIAGNOSTICS Exit status is zero if no errors occur. Errors result in a non-zero exit status and a diagnostic message being written to standard error. .SH "SEE ALSO" .BR ldapadd (1), .BR ldapdelete (1), .BR ldapmodrdn (1), .BR ldapsearch (1), .BR ldap.conf (5), .BR ldap (3), .BR ldap_add_ext (3), .BR ldap_delete_ext (3), .BR ldap_modify_ext (3), .BR ldap_modrdn_ext (3), .BR ldif (5). .SH AUTHOR The OpenLDAP Project .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man1/ldapurl.10000644000175000017500000000745512563404150016744 0ustar ryanryan.TH LDAPURL 1 "RELEASEDATE" "OpenLDAP LDVERSION" .\" $OpenLDAP$ .\" Copyright 2008-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldapurl \- LDAP URL formatting tool .SH SYNOPSIS .B ldapurl [\c .BR \-a \ attrs\fR] [\c .BI \-b \ searchbase\fR] [\c .BR \-e \ [ ! ] \fIext\fP [ =\fIextparam\fP ]] [\c .BR \-E \ [ ! ] \fIext\fP [ =\fIextparam\fP ]] [\c .BI \-f \ filter\fR] [\c .BI \-H \ ldapuri\fR] [\c .BI \-h \ ldaphost\fR] [\c .BI \-p \ ldapport\fR] [\c .BR \-s \ { base \||\| one \||\| sub \||\| children }] [\c .BI \-S \ scheme\fR] .SH DESCRIPTION .I ldapurl is a command that allows to either compose or decompose LDAP URIs. .LP When invoked with the \fB\-H\fP option, .B ldapurl extracts the components of the \fIldapuri\fP option argument, unescaping hex-escaped chars as required. It basically acts as a frontend to the .BR ldap_url_parse (3) call. Otherwise, it builds an LDAP URI based on the components passed with the appropriate options, performing the inverse operation. Option \fB\-H\fP is incompatible with options .BR \-a , .BR \-b , .BR \-E , .BR \-f , .BR \-H , .BR \-h , .BR \-p , .BR \-S , and .BR \-s . .SH OPTIONS .TP .TP .BI \-a \ attrs Set a comma-separated list of attribute selectors. .TP .BI \-b \ searchbase Set the \fIsearchbase\fP. .TP .BR \-e \ [ ! ] \fIext\fP [ =\fIextparam\fP ] Specify general extensions with \fB\-e\fP \'\fB!\fP\' indicates criticality. General extensions: .nf [!]assert= (an RFC 4515 Filter) !authzid= ("dn:" or "u:") [!]bauthzid (RFC 3829 authzid control) [!]chaining[=[/]] [!]manageDSAit [!]noop ppolicy [!]postread[=] (a comma-separated attribute list) [!]preread[=] (a comma-separated attribute list) [!]relax sessiontracking abandon,cancel,ignore (SIGINT sends abandon/cancel, or ignores response; if critical, doesn't wait for SIGINT. not really controls) .fi .TP .BR \-E \ [ ! ] \fIext\fP [ =\fIextparam\fP ] Set URL extensions; incompatible with .BR \-H . .TP .BI \-f \ filter Set the URL filter. No particular check on conformity with RFC 4515 LDAP filters is performed, but the value is hex-escaped as required. .TP .BI \-H \ ldapuri Specify URI to be exploded. .TP .BI \-h \ ldaphost Set the host. .TP .BI \-p \ ldapport Set the TCP port. .TP .BI \-S \ scheme Set the URL scheme. Defaults for other fields, like \fIldapport\fP, may depend on the value of \fIscheme\fP. .TP .BR \-s \ { base \||\| one \||\| sub \||\| children } Specify the scope of the search to be one of .BR base , .BR one , .BR sub , or .B children to specify a base object, one-level, subtree, or children search. The default is .BR sub . Note: .B children scope requires LDAPv3 subordinate feature extension. .SH OUTPUT FORMAT If the \fB\-H\fP option is used, the \fIldapuri\fP supplied is exploded in its components, which are printed to standard output in an LDIF-like form. .LP Otherwise, the URI built using the values passed with the other options is printed to standard output. .SH EXAMPLE The following command: .LP .nf ldapurl \-h ldap.example.com \-b dc=example,dc=com \-s sub \-f "(cn=Some One)" .fi .LP returns .LP .nf ldap://ldap.example.com:389/dc=example,dc=com??sub?(cn=Some%20One) .fi .LP The command: .LP .nf ldapurl \-H ldap://ldap.example.com:389/dc=example,dc=com??sub?(cn=Some%20One) .fi .LP returns .LP .nf scheme: ldap host: ldap.example.com port: 389 dn: dc=example,dc=com scope: sub filter: (cn=Some One) .fi .LP .SH DIAGNOSTICS Exit status is zero if no errors occur. Errors result in a non-zero exit status and a diagnostic message being written to standard error. .SH "SEE ALSO" .BR ldap (3), .BR ldap_url_parse (3), .SH AUTHOR The OpenLDAP Project .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man1/ldapwhoami.10000644000175000017500000001124412563404150017415 0ustar ryanryan.TH LDAPWHOAMI 1 "RELEASEDATE" "OpenLDAP LDVERSION" .\" $OpenLDAP$ .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldapwhoami \- LDAP who am i? tool .SH SYNOPSIS .B ldapwhoami [\c .BR \-V [ V ]] [\c .BI \-d \ debuglevel\fR] [\c .BR \-n ] [\c .BR \-v ] [\c .BR \-x ] [\c .BI \-D \ binddn\fR] [\c .BR \-W ] [\c .BI \-w \ passwd\fR] [\c .BI \-y \ passwdfile\fR] [\c .BI \-H \ ldapuri\fR] [\c .BI \-h \ ldaphost\fR] [\c .BI \-p \ ldapport\fR] [\c .BR \-e \ [ ! ] \fIext\fP [ =\fIextparam\fP ]] [\c .BR \-E \ [ ! ] \fIext\fP [ =\fIextparam\fP ]] [\c .BI \-o \ opt \fR[= optparam \fR]] [\c .BI \-O \ security-properties\fR] [\c .BR \-I ] [\c .BR \-Q ] [\c .BR \-N ] [\c .BI \-U \ authcid\fR] [\c .BI \-R \ realm\fR] [\c .BI \-X \ authzid\fR] [\c .BI \-Y \ mech\fR] [\c .BR \-Z [ Z ]] .SH DESCRIPTION .I ldapwhoami implements the LDAP "Who Am I?" extended operation. .LP .B ldapwhoami opens a connection to an LDAP server, binds, and performs a whoami operation. .SH OPTIONS .TP .BR \-V [ V ] Print version info. If \fB\-VV\fP is given, only the version information is printed. .TP .BI \-d \ debuglevel Set the LDAP debugging level to \fIdebuglevel\fP. .B ldapwhoami must be compiled with LDAP_DEBUG defined for this option to have any effect. .TP .B \-n Show what would be done, but don't actually perform the whoami operation. Useful for debugging in conjunction with \fB\-v\fP. .TP .B \-v Run in verbose mode, with many diagnostics written to standard output. .TP .B \-x Use simple authentication instead of SASL. .TP .BI \-D \ binddn Use the Distinguished Name \fIbinddn\fP to bind to the LDAP directory. For SASL binds, the server is expected to ignore this value. .TP .B \-W Prompt for simple authentication. This is used instead of specifying the password on the command line. .TP .BI \-w \ passwd Use \fIpasswd\fP as the password for simple authentication. .TP .BI \-y \ passwdfile Use complete contents of \fIpasswdfile\fP as the password for simple authentication. .TP .BI \-H \ ldapuri Specify URI(s) referring to the ldap server(s); only the protocol/host/port fields are allowed; a list of URI, separated by whitespace or commas is expected. .TP .BI \-h \ ldaphost Specify an alternate host on which the ldap server is running. Deprecated in favor of \fB\-H\fP. .TP .BI \-p \ ldapport Specify an alternate TCP port where the ldap server is listening. Deprecated in favor of \fB\-H\fP. .TP .BR \-e \ [ ! ] \fIext\fP [ =\fIextparam\fP ] .TP .BR \-E \ [ ! ] \fIext\fP [ =\fIextparam\fP ] Specify general extensions with \fB\-e\fP and whoami extensions with \fB\-E\fP. \'\fB!\fP\' indicates criticality. General extensions: .nf [!]assert= (an RFC 4515 Filter) !authzid= ("dn:" or "u:") [!]bauthzid (RFC 3829 authzid control) [!]chaining[=[/]] [!]manageDSAit [!]noop ppolicy [!]postread[=] (a comma-separated attribute list) [!]preread[=] (a comma-separated attribute list) [!]relax sessiontracking abandon,cancel,ignore (SIGINT sends abandon/cancel, or ignores response; if critical, doesn't wait for SIGINT. not really controls) .fi WhoAmI extensions: .nf (none) .fi .TP .BI \-o \ opt \fR[= optparam \fR] Specify general options. General options: .nf nettimeout= (in seconds, or "none" or "max") ldif-wrap= (in columns, or "no" for no wrapping) .fi .TP .BI \-O \ security-properties Specify SASL security properties. .TP .B \-I Enable SASL Interactive mode. Always prompt. Default is to prompt only as needed. .TP .B \-Q Enable SASL Quiet mode. Never prompt. .TP .B \-N Do not use reverse DNS to canonicalize SASL host name. .TP .BI \-U \ authcid Specify the authentication ID for SASL bind. The form of the ID depends on the actual SASL mechanism used. .TP .BI \-R \ realm Specify the realm of authentication ID for SASL bind. The form of the realm depends on the actual SASL mechanism used. .TP .BI \-X \ authzid Specify the requested authorization ID for SASL bind. .I authzid must be one of the following formats: .BI dn: "" or .BI u: .TP .BI \-Y \ mech Specify the SASL mechanism to be used for authentication. If it's not specified, the program will choose the best mechanism the server knows. .TP .BR \-Z [ Z ] Issue StartTLS (Transport Layer Security) extended operation. If you use \fB\-ZZ\fP, the command will require the operation to be successful. .SH EXAMPLE .nf ldapwhoami \-x \-D "cn=Manager,dc=example,dc=com" \-W .fi .SH "SEE ALSO" .BR ldap.conf (5), .BR ldap (3), .BR ldap_extended_operation (3) .SH AUTHOR The OpenLDAP Project .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man1/ldapcompare.10000644000175000017500000001452112563404150017560 0ustar ryanryan.TH LDAPCOMPARE 1 "RELEASEDATE" "OpenLDAP LDVERSION" .\" $OpenLDAP$ .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldapcompare \- LDAP compare tool .SH SYNOPSIS .B ldapcompare [\c .BR \-V [ V ]] [\c .BI \-d \ debuglevel\fR] [\c .BR \-n ] [\c .BR \-v ] [\c .BR \-z ] [\c .BR \-M [ M ]] [\c .BR \-x ] [\c .BI \-D \ binddn\fR] [\c .BR \-W ] [\c .BI \-w \ passwd\fR] [\c .BI \-y \ passwdfile\fR] [\c .BI \-H \ ldapuri\fR] [\c .BI \-h \ ldaphost\fR] [\c .BI \-p \ ldapport\fR] [\c .BR \-P \ { 2 \||\| 3 }] [\c .BR \-e \ [ ! ] \fIext\fP [ =\fIextparam\fP ]] [\c .BR \-E \ [ ! ] \fIext\fP [ =\fIextparam\fP ]] [\c .BI \-o \ opt \fR[= optparam \fR]] [\c .BI \-O \ security-properties\fR] [\c .BR \-I ] [\c .BR \-Q ] [\c .BR \-N ] [\c .BI \-U \ authcid\fR] [\c .BI \-R \ realm\fR] [\c .BI \-X \ authzid\fR] [\c .BI \-Y \ mech\fR] [\c .BR \-Z [ Z ]] .IR DN {\c .BI attr: value | .BI attr:: b64value\fR} .SH DESCRIPTION .I ldapcompare is a shell-accessible interface to the .BR ldap_compare_ext (3) library call. .LP .B ldapcompare opens a connection to an LDAP server, binds, and performs a compare using specified parameters. The \fIDN\fP should be a distinguished name in the directory. \fIAttr\fP should be a known attribute. If followed by one colon, the assertion \fIvalue\fP should be provided as a string. If followed by two colons, the base64 encoding of the value is provided. The result code of the compare is provided as the exit code and, unless ran with \fB\-z\fP, the program prints TRUE, FALSE, or UNDEFINED on standard output. .LP .SH OPTIONS .TP .BR \-V [ V ] Print version info. If \fB\-VV\fP is given, only the version information is printed. .TP .BI \-d \ debuglevel Set the LDAP debugging level to \fIdebuglevel\fP. .B ldapcompare must be compiled with LDAP_DEBUG defined for this option to have any effect. .TP .B \-n Show what would be done, but don't actually perform the compare. Useful for debugging in conjunction with \fB\-v\fP. .TP .B \-v Run in verbose mode, with many diagnostics written to standard output. .TP .B \-z Run in quiet mode, no output is written. You must check the return status. Useful in shell scripts. .TP .BR \-M [ M ] Enable manage DSA IT control. .B \-MM makes control critical. .TP .B \-x Use simple authentication instead of SASL. .TP .BI \-D \ binddn Use the Distinguished Name \fIbinddn\fP to bind to the LDAP directory. For SASL binds, the server is expected to ignore this value. .TP .B \-W Prompt for simple authentication. This is used instead of specifying the password on the command line. .TP .BI \-w \ passwd Use \fIpasswd\fP as the password for simple authentication. .TP .BI \-y \ passwdfile Use complete contents of \fIpasswdfile\fP as the password for simple authentication. Note that \fIcomplete\fP means that any leading or trailing whitespaces, including newlines, will be considered part of the password and, unlike other software, they will not be stripped. As a consequence, passwords stored in files by commands like .BR echo (1) will not behave as expected, since .BR echo (1) by default appends a trailing newline to the echoed string. The recommended portable way to store a cleartext password in a file for use with this option is to use .BR slappasswd (8) with \fI{CLEARTEXT}\fP as hash and the option \fB\-n\fP. .TP .BI \-H \ ldapuri Specify URI(s) referring to the ldap server(s); only the protocol/host/port fields are allowed; a list of URI, separated by whitespace or commas is expected. .TP .BI \-h \ ldaphost Specify an alternate host on which the ldap server is running. Deprecated in favor of \fB\-H\fP. .TP .BI \-p \ ldapport Specify an alternate TCP port where the ldap server is listening. Deprecated in favor of \fB\-H\fP. .TP .BR \-P \ { 2 \||\| 3 } Specify the LDAP protocol version to use. .TP .BR \-e \ [ ! ] \fIext\fP [ =\fIextparam\fP ] .TP .BR \-E \ [ ! ] \fIext\fP [ =\fIextparam\fP ] Specify general extensions with \fB\-e\fP and compare extensions with \fB\-E\fP. \'\fB!\fP\' indicates criticality. General extensions: .nf [!]assert= (an RFC 4515 Filter) !authzid= ("dn:" or "u:") [!]bauthzid (RFC 3829 authzid control) [!]chaining[=[/]] [!]manageDSAit [!]noop ppolicy [!]postread[=] (a comma-separated attribute list) [!]preread[=] (a comma-separated attribute list) [!]relax sessiontracking abandon,cancel,ignore (SIGINT sends abandon/cancel, or ignores response; if critical, doesn't wait for SIGINT. not really controls) .fi Compare extensions: .nf !dontUseCopy .fi .TP .BI \-o \ opt \fR[= optparam \fR] Specify general options. General options: .nf nettimeout= (in seconds, or "none" or "max") ldif-wrap= (in columns, or "no" for no wrapping) .fi .TP .BI \-O \ security-properties Specify SASL security properties. .TP .B \-I Enable SASL Interactive mode. Always prompt. Default is to prompt only as needed. .TP .B \-Q Enable SASL Quiet mode. Never prompt. .TP .B \-N Do not use reverse DNS to canonicalize SASL host name. .TP .BI \-U \ authcid Specify the authentication ID for SASL bind. The form of the ID depends on the actual SASL mechanism used. .TP .BI \-R \ realm Specify the realm of authentication ID for SASL bind. The form of the realm depends on the actual SASL mechanism used. .TP .BI \-X \ authzid Specify the requested authorization ID for SASL bind. .I authzid must be one of the following formats: .BI dn: "" or .BI u: .TP .BI \-Y \ mech Specify the SASL mechanism to be used for authentication. If it's not specified, the program will choose the best mechanism the server knows. .TP .BR \-Z [ Z ] Issue StartTLS (Transport Layer Security) extended operation. If you use \fB\-ZZ\fP, the command will require the operation to be successful. .SH EXAMPLES .nf ldapcompare "uid=babs,dc=example,dc=com" sn:Jensen ldapcompare "uid=babs,dc=example,dc=com" sn::SmVuc2Vu .fi are all equivalent. .SH LIMITATIONS Requiring the value be passed on the command line is limiting and introduces some security concerns. The command should support a mechanism to specify the location (file name or URL) to read the value from. .SH "SEE ALSO" .BR ldap.conf (5), .BR ldif (5), .BR ldap (3), .BR ldap_compare_ext (3) .SH AUTHOR The OpenLDAP Project .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man1/ldappasswd.10000644000175000017500000001314412563404150017433 0ustar ryanryan.TH LDAPPASSWD 1 "RELEASEDATE" "OpenLDAP LDVERSION" .\" $OpenLDAP$ .\" Copyright 1998-2015 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldappasswd \- change the password of an LDAP entry .SH SYNOPSIS .B ldappasswd [\c .BR \-V [ V ]] [\c .BI \-d \ debuglevel\fR] [\c .BR \-n ] [\c .BR \-v ] [\c .BR \-A ] [\c .BI \-a \ oldPasswd\fR] [\c .BI \-t \ oldpasswdfile\fR] [\c .BR \-S ] [\c .BI \-s \ newPasswd\fR] [\c .BI \-T \ newpasswdfile\fR] [\c .BR \-x ] [\c .BI \-D \ binddn\fR] [\c .BR \-W ] [\c .BI \-w \ passwd\fR] [\c .BI \-y \ passwdfile\fR] [\c .BI \-H \ ldapuri\fR] [\c .BI \-h \ ldaphost\fR] [\c .BI \-p \ ldapport\fR] [\c .BR \-e \ [ ! ] \fIext\fP [ =\fIextparam\fP ]] [\c .BR \-E \ [ ! ] \fIext\fP [ =\fIextparam\fP ]] [\c .BI \-o \ opt \fR[= optparam \fR]] [\c .BI \-O \ security-properties\fR] [\c .BR \-I ] [\c .BR \-Q ] [\c .BR \-N ] [\c .BI \-U \ authcid\fR] [\c .BI \-R \ realm\fR] [\c .BI \-X \ authzid\fR] [\c .BI \-Y \ mech\fR] [\c .BR \-Z [ Z ]] [\c .IR user ] .SH DESCRIPTION .B ldappasswd is a tool to set the password of an LDAP user. .B ldappasswd uses the LDAPv3 Password Modify (RFC 3062) extended operation. .LP .B ldappasswd sets the password of associated with the user [or an optionally specified .IR user ]. If the new password is not specified on the command line and the user doesn't enable prompting, the server will be asked to generate a password for the user. .LP .B ldappasswd is neither designed nor intended to be a replacement for .BR passwd (1) and should not be installed as such. .SH OPTIONS .TP .BR \-V [ V ] Print version info. If \fB\-VV\fP is given, only the version information is printed. .TP .BI \-d \ debuglevel Set the LDAP debugging level to \fIdebuglevel\fP. .B ldappasswd must be compiled with LDAP_DEBUG defined for this option to have any effect. .TP .B \-n Do not set password. (Can be useful when used in conjunction with \fB\-v\fP or \fB\-d\fP) .TP .B \-v Increase the verbosity of output. Can be specified multiple times. .TP .BI \-A Prompt for old password. This is used instead of specifying the password on the command line. .TP .BI \-a \ oldPasswd Set the old password to \fIoldPasswd\fP. .TP .BI \-t \ oldPasswdFile Set the old password to the contents of \fIoldPasswdFile\fP. .TP .BI \-S Prompt for new password. This is used instead of specifying the password on the command line. .TP .BI \-s \ newPasswd Set the new password to \fInewPasswd\fP. .TP .BI \-T \ newPasswdFile Set the new password to the contents of \fInewPasswdFile\fP. .TP .B \-x Use simple authentication instead of SASL. .TP .BI \-D \ binddn Use the Distinguished Name \fIbinddn\fP to bind to the LDAP directory. For SASL binds, the server is expected to ignore this value. .TP .BI \-W Prompt for bind password. This is used instead of specifying the password on the command line. .TP .BI \-w \ passwd Use \fIpasswd\fP as the password to bind with. .TP .BI \-y \ passwdfile Use complete contents of \fIpasswdfile\fP as the password for simple authentication. .TP .BI \-H \ ldapuri Specify URI(s) referring to the ldap server(s); only the protocol/host/port fields are allowed; a list of URI, separated by whitespace or commas is expected. .TP .BI \-h \ ldaphost Specify an alternate host on which the ldap server is running. Deprecated in favor of \fB\-H\fP. .TP .BI \-p \ ldapport Specify an alternate TCP port where the ldap server is listening. Deprecated in favor of \fB\-H\fP. .TP .BR \-e \ [ ! ] \fIext\fP [ =\fIextparam\fP ] .TP .BR \-E \ [ ! ] \fIext\fP [ =\fIextparam\fP ] Specify general extensions with \fB\-e\fP and passwd modify extensions with \fB\-E\fP. \'\fB!\fP\' indicates criticality. General extensions: .nf [!]assert= (an RFC 4515 Filter) !authzid= ("dn:" or "u:") [!]bauthzid (RFC 3829 authzid control) [!]chaining[=[/]] [!]manageDSAit [!]noop ppolicy [!]postread[=] (a comma-separated attribute list) [!]preread[=] (a comma-separated attribute list) [!]relax sessiontracking abandon,cancel,ignore (SIGINT sends abandon/cancel, or ignores response; if critical, doesn't wait for SIGINT. not really controls) .fi Passwd Modify extensions: .nf (none) .fi .TP .BI \-o \ opt \fR[= optparam \fR]] Specify general options. General options: .nf nettimeout= (in seconds, or "none" or "max") ldif-wrap= (in columns, or "no" for no wrapping) .fi .TP .BI \-O \ security-properties Specify SASL security properties. .TP .B \-I Enable SASL Interactive mode. Always prompt. Default is to prompt only as needed. .TP .B \-Q Enable SASL Quiet mode. Never prompt. .TP .B \-N Do not use reverse DNS to canonicalize SASL host name. .TP .BI \-U \ authcid Specify the authentication ID for SASL bind. The form of the ID depends on the actual SASL mechanism used. .TP .BI \-R \ realm Specify the realm of authentication ID for SASL bind. The form of the realm depends on the actual SASL mechanism used. .TP .BI \-X \ authzid Specify the requested authorization ID for SASL bind. .I authzid must be one of the following formats: .BI dn: "" or .BI u: \fP. .TP .BI \-Y \ mech Specify the SASL mechanism to be used for authentication. If it's not specified, the program will choose the best mechanism the server knows. .TP .BR \-Z [ Z ] Issue StartTLS (Transport Layer Security) extended operation. If you use \fB\-ZZ\fP, the command will require the operation to be successful .SH SEE ALSO .BR ldap_sasl_bind (3), .BR ldap_extended_operation (3), .BR ldap_start_tls_s (3) .SH AUTHOR The OpenLDAP Project .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man1/ldapexop.10000644000175000017500000001346712563404150017115 0ustar ryanryan.\" $OpenLDAP$ .\" This contribution is derived from OpenLDAP Software. .\" All of the modifications to OpenLDAP Software represented in this .\" contribution were developed by Peter Marschall . .\" I have not assigned rights and/or interest in this work to any party. .\" .\" Copyright 2009 Peter Marschall .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted only as authorized by the OpenLDAP Public License. .\" .\" A copy of this license is available in file LICENSE in the .\" top-level directory of the distribution or, alternatively, at .\" http://www.OpenLDAP.org/license.html. .TH LDAPEXOP 1 .SH NAME ldapexop \- issue LDAP extended operations .SH SYNOPSIS ldapexop [\c .BR \-V [ V ]] [\c .BI \-d \ debuglevel\fR] [\c .BR \-n ] [\c .BR \-v ] [\c .BI \-f \ file\fR] [\c .BR \-x ] [\c .BI \-D \ binddn\fR] [\c .BR \-W ] [\c .BI \-w \ passwd\fR] [\c .BI \-y \ passwdfile\fR] [\c .BI \-H \ URI\fR] [\c .BI \-h \ ldaphost\fR] [\c .BI \-p \ ldapport\fR] [\c .BR \-e \ [ ! ] \fIext\fP [ =\fIextparam\fP ]] [\c .BI \-o \ opt \fR[= optparam \fR]] [\c .BI \-O \ security-properties\fR] [\c .BR \-I ] [\c .BR \-Q ] [\c .BR \-N ] [\c .BI \-U \ authcid\fR] [\c .BI \-R \ realm\fR] [\c .BI \-X \ authzid\fR] [\c .BI \-Y \ mech\fR] [\c .BR \-Z [ Z ]] {\c .I oid | .BI oid: data | .BI oid:: b64data | .B whoami | .BI cancel \ cancel-id | .BI refresh \ DN \ \fR[\fIttl\fR]} .SH DESCRIPTION ldapexop issues the LDAP extended operation specified by \fBoid\fP or one of the special keywords \fBwhoami\fP, \fBcancel\fP, or \fBrefresh\fP. Additional data for the extended operation can be passed to the server using \fIdata\fP or base-64 encoded as \fIb64data\fP in the case of \fBoid\fP, or using the additional parameters in the case of the specially named extended operations above. Please note that ldapexop behaves differently for the same extended operation when it was given as an OID or as a specialliy named operation: Calling ldapexop with the OID of the \fBwhoami\fP (RFC 4532) extended operation .nf ldapexop [] 1.3.6.1.4.1.4203.1.11.3 .fi yields .nf # extended operation response data:: .fi while calling it with the keyword \fBwhoami\fP .nf ldapexop [] whoami .fi results in .nf dn: .fi .SH OPTIONS .TP .BI \-V [ V ] Print version info. If\fB\-VV\fP is given, only the version information is printed. .TP .BI \-d \ debuglevel Set the LDAP debugging level to \fIdebuglevel\fP. .TP .BI \-n Show what would be done but don't actually do it. Useful for debugging in conjunction with \fB\-v\fP. .TP .BI \-v Run in verbose mode, with many diagnostics written to standard output. .TP .BI \-f \ file Read operations from \fIfile\fP. .TP .BI \-x Use simple authentication instead of SASL. .TP .BI \-D \ binddn Use the Distinguished Name \fIbinddn\fP to bind to the LDAP directory. .TP .BI \-W Prompt for simple authentication. This is used instead of specifying the password on the command line. .TP .BI \-w \ passwd Use \fIpasswd\fP as the password for simple authentication. .TP .BI \-y \ passwdfile Use complete contents of \fIpasswdfile\fP as the password for simple authentication. .TP .BI \-H \ URI Specify URI(s) referring to the ldap server(s); only the protocol/host/port fields are allowed; a list of URI, separated by whitespace or commas is expected. .TP .BI \-h \ ldaphost Specify the host on which the ldap server is running. Deprecated in favor of \fB\-H\fP. .TP .BI \-p \ ldapport Specify the TCP port where the ldap server is listening. Deprecated in favor of \fB\-H\fP. .TP .BR \-e \ [ ! ] \fIext\fP [ =\fIextparam\fP ] Specify general extensions. \'!\' indicates criticality. .nf [!]assert= (an RFC 4515 Filter) !authzid= ("dn:" or "u:") [!]bauthzid (RFC 3829 authzid control) [!]chaining[=[/]] [!]manageDSAit [!]noop ppolicy [!]postread[=] (a comma-separated attribute list) [!]preread[=] (a comma-separated attribute list) [!]relax sessiontracking abandon,cancel,ignore (SIGINT sends abandon/cancel, or ignores response; if critical, doesn't wait for SIGINT. not really controls) .fi .TP .BI \-o \ opt \fR[= optparam \fR] Specify general options. General options: .nf nettimeout= (in seconds, or "none" or "max") ldif-wrap= (in columns, or "no" for no wrapping) .fi .TP .BI \-O \ security-properties Specify SASL security properties. .TP .BI \-I Enable SASL Interactive mode. Always prompt. Default is to prompt only as needed. .TP .BI \-Q Enable SASL Quiet mode. Never prompt. .TP .B \-N Do not use reverse DNS to canonicalize SASL host name. .TP .BI \-U \ authcid Specify the authentication ID for SASL bind. The form of the ID depends on the actual SASL mechanism used. .TP .BI \-R \ realm Specify the realm of authentication ID for SASL bind. The form of the realm depends on the actual SASL mechanism used. .TP .BI \-X \ authzid Specify the requested authorization ID for SASL bind. .I authzid must be one of the following formats: .BI dn: "" or .BI u: .TP .BI \-Y \ mech Specify the SASL mechanism to be used for authentication. Without this option, the program will choose the best mechanism the server knows. .TP .BR \-Z [ Z ] Issue StartTLS (Transport Layer Security) extended operation. Giving it twice (\fB\-ZZ\fP) will require the operation to be successful. .SH DIAGNOSTICS Exit status is zero if no errors occur. Errors result in a non-zero exit status and a diagnostic message being written to standard error. .SH "SEE ALSO" .BR ldap_extended_operation_s (3) .SH AUTHOR This manual page was written by Peter Marschall based on \fBldapexop\fP's usage message and a few tests with \fBldapexop\fP. Do not expect it to be complete or absolutely correct. .SH ACKNOWLEDGEMENTS .so ../Project openldap-2.4.42+dfsg/doc/man/man5/0000755000175000017500000000000012563404150015210 5ustar ryanryanopenldap-2.4.42+dfsg/doc/man/man5/slapd-meta.50000644000175000017500000012744512563404150017342 0ustar ryanryan.TH SLAPD-META 5 "RELEASEDATE" "OpenLDAP LDVERSION" .\" Copyright 1998-2015 The OpenLDAP Foundation, All Rights Reserved. .\" Copying restrictions apply. See the COPYRIGHT file. .\" Copyright 2001, Pierangelo Masarati, All rights reserved. .\" $OpenLDAP$ .\" .\" Portions of this document should probably be moved to slapd-ldap(5) .\" and maybe manual pages for librewrite. .\" .SH NAME slapd\-meta \- metadirectory backend to slapd .SH SYNOPSIS ETCDIR/slapd.conf .SH DESCRIPTION The .B meta backend to .BR slapd (8) performs basic LDAP proxying with respect to a set of remote LDAP servers, called "targets". The information contained in these servers can be presented as belonging to a single Directory Information Tree (DIT). .LP A basic knowledge of the functionality of the .BR slapd\-ldap (5) backend is recommended. This backend has been designed as an enhancement of the ldap backend. The two backends share many features (actually they also share portions of code). While the .B ldap backend is intended to proxy operations directed to a single server, the .B meta backend is mainly intended for proxying of multiple servers and possibly naming context masquerading. These features, although useful in many scenarios, may result in excessive overhead for some applications, so its use should be carefully considered. In the examples section, some typical scenarios will be discussed. The proxy instance of .BR slapd (8) must contain schema information for the attributes and objectClasses used in filters, request DN and request-related data in general. It should also contain schema information for the data returned by the proxied server. It is the responsibility of the proxy administrator to keep the schema of the proxy lined up with that of the proxied server. .LP Note: When looping back to the same instance of \fBslapd\fP(8), each connection requires a new thread; as a consequence, \fBslapd\fP(8) must be compiled with thread support, and the \fBthreads\fP parameter may need some tuning; in those cases, unless the multiple target feature is required, one may consider using \fBslapd\-relay\fP(5) instead, which performs the relayed operation internally and thus reuses the same connection. .SH EXAMPLES There are examples in various places in this document, as well as in the slapd/back\-meta/data/ directory in the OpenLDAP source tree. .SH CONFIGURATION These .B slapd.conf options apply to the META backend database. That is, they must follow a "database meta" line and come before any subsequent "backend" or "database" lines. Other database options are described in the .BR slapd.conf (5) manual page. .LP Note: In early versions of back-ldap and back-meta it was recommended to always set .LP .RS .nf lastmod off .fi .RE .LP for .B ldap and .B meta databases. This was required because operational attributes related to entry creation and modification should not be proxied, as they could be mistakenly written to the target server(s), generating an error. The current implementation automatically sets lastmod to \fBoff\fP, so its use is redundant and should be omitted. .SH SPECIAL CONFIGURATION DIRECTIVES Target configuration starts with the "uri" directive. All the configuration directives that are not specific to targets should be defined first for clarity, including those that are common to all backends. They are: .TP .B conn\-ttl