diff options
167 files changed, 4495 insertions, 11062 deletions
diff --git a/.gdbinit b/.gdbinit new file mode 100644 index 00000000..5b52a899 --- /dev/null +++ b/.gdbinit @@ -0,0 +1 @@ +set disable-randomization on @@ -0,0 +1,6 @@ +" vim can use per directory configuration files. To enable that neat feature only two little lines are needed in your ~/.vimrc: +" set exrc " enable per-directory .vimrc files +" set secure " disable unsafe commands in local .vimrc files + +set ts=8 +set noexpandtab @@ -54,6 +54,9 @@ Makefile.settings: clean: $(subdirs) rm -f *.o $(OUTFILE) core utils/bitlbeed init/bitlbee*.service $(MAKE) -C tests clean +ifdef SKYPE_PI + $(MAKE) -C protocols/skype clean +endif distclean: clean $(subdirs) rm -rf .depend @@ -166,17 +169,17 @@ $(OTR_PI): %.so: $(_SRCDIR_)%.c $(SKYPE_PI): $(_SRCDIR_)protocols/skype/skype.c @echo '*' Building plugin skype - @$(CC) $(CFLAGS) -fPIC -shared $< -o $@ + @$(CC) $(CFLAGS) $(SKYPEFLAGS) $< -o $@ $(objects): %.o: $(_SRCDIR_)%.c @echo '*' Compiling $< - @$(CC) -c $(CFLAGS) $< -o $@ + @$(CC) -c $(CFLAGS) $(CFLAGS_BITLBEE) $< -o $@ $(objects): Makefile Makefile.settings config.h $(OUTFILE): $(objects) $(subdirs) @echo '*' Linking $(OUTFILE) - @$(CC) $(objects) $(subdirobjs) -o $(OUTFILE) $(LFLAGS) $(EFLAGS) + @$(CC) $(objects) $(subdirobjs) -o $(OUTFILE) $(LDFLAGS_BITLBEE) $(LFLAGS) $(EFLAGS) ifndef DEBUG @echo '*' Stripping $(OUTFILE) @-$(STRIP) $(OUTFILE) @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2004 Wilmer van der Gaast and others * + * Copyright 2002-2013 Wilmer van der Gaast and others * \********************************************************************/ /* Main file */ @@ -38,10 +38,10 @@ extern "C" { #define _WIN32_WINNT 0x0501 #define PACKAGE "BitlBee" -#define BITLBEE_VERSION "3.0.5" +#define BITLBEE_VERSION "3.2" #define VERSION BITLBEE_VERSION #define BITLBEE_VER(a,b,c) (((a) << 16) + ((b) << 8) + (c)) -#define BITLBEE_VERSION_CODE BITLBEE_VER(3, 0, 5) +#define BITLBEE_VERSION_CODE BITLBEE_VER(3, 2, 0) #define MAX_STRING 511 @@ -40,6 +40,8 @@ skype=0 events=glib ssl=auto +pie=1 + arch=`uname -s` cpu=`uname -m` @@ -78,6 +80,7 @@ Option Description Default --debug=0/1 Disable/enable debugging $debug --strip=0/1 Disable/enable binary stripping $strip +--pie=0/1 Build position independent executable $pie --gcov=0/1 Disable/enable test coverage reporting $gcov --plugins=0/1 Disable/enable plugins support $plugins --otr=0/1/auto/plugin @@ -86,9 +89,10 @@ Option Description Default Disable/enable Skype support $skype --events=... Event handler (glib, libevent) $events ---ssl=... SSL library to use (gnutls, nss, openssl, bogus, auto) +--ssl=... SSL library to use (gnutls, nss, openssl, auto) $ssl + --target=... Cross compilation target same as host EOF exit; @@ -198,6 +202,11 @@ else [ -z "$CFLAGS" ] && CFLAGS="-O2 -fno-strict-aliasing" fi +if [ "$pie" = "1" ]; then + echo 'CFLAGS_BITLBEE=-fPIE' >> Makefile.settings + echo 'LDFLAGS_BITLBEE=-pie' >> Makefile.settings +fi + echo CFLAGS=$CFLAGS $CPPFLAGS >> Makefile.settings echo CFLAGS+=-I${srcdir} -I${srcdir}/lib -I${srcdir}/protocols -I. >> Makefile.settings @@ -384,20 +393,20 @@ elif [ "$ssl" = "sspi" ]; then elif [ "$ssl" = "openssl" ]; then echo echo 'No detection code exists for OpenSSL. Make sure that you have a complete' - echo 'install of OpenSSL (including devel/header files) before reporting' + echo 'installation of OpenSSL (including devel/header files) before reporting' echo 'compilation problems.' echo echo 'Also, keep in mind that the OpenSSL is, according to some people, not' - echo 'completely GPL-compatible. Using GnuTLS or NSS is recommended and better' - echo 'supported by us. However, on many BSD machines, OpenSSL can be considered' - echo 'part of the operating system, which makes it GPL-compatible.' + echo 'completely GPL-compatible. Using GnuTLS is recommended and better supported' + echo 'by us. However, on many BSD machines, OpenSSL can be considered part of the' + echo 'operating system, which makes it GPL-compatible.' echo echo 'For more info, see: http://www.openssl.org/support/faq.html#LEGAL2' echo ' http://www.gnome.org/~markmc/openssl-and-the-gpl.html' echo echo 'Please note that distributing a BitlBee binary which links to OpenSSL is' echo 'probably illegal. If you want to create and distribute a binary BitlBee' - echo 'package, you really should use GnuTLS or NSS instead.' + echo 'package, you really should use GnuTLS instead.' echo echo 'Also, the OpenSSL license requires us to say this:' echo ' * "This product includes software developed by the OpenSSL Project' @@ -406,19 +415,6 @@ elif [ "$ssl" = "openssl" ]; then echo 'EFLAGS+=-lssl -lcrypto' >> Makefile.settings ret=1 -elif [ "$ssl" = "bogus" ]; then - echo - echo 'Using bogus SSL code. This means some features will not work properly.' - - ## Yes, you, at the console! How can you authenticate if you don't have any SSL!? - if [ "$msn" = "1" -o "$yahoo" = "1" ]; then - echo - echo 'WARNING: The MSN and Yahoo! modules will not work without SSL. Disabling.' - msn=0 - yahoo=0 - fi - - ret=1 else echo echo 'ERROR: Unknown SSL library specified.' @@ -429,20 +425,11 @@ if [ "$ret" = "0" ]; then echo echo 'ERROR: Could not find a suitable SSL library (GnuTLS, libnss or OpenSSL).' echo ' Please note that this script doesn'\''t have detection code for OpenSSL,' - echo ' so if you want to use that, you have to select it by hand. If you don'\''t' - echo ' need SSL support, you can select the "bogus" SSL library. (--ssl=bogus)' + echo ' so if you want to use that, you have to select it by hand.' exit 1 fi; -if [ "$msn" = "1" -a "$ssl" != "openssl" -a "$ssl" != "gnutls" ]; then - # Needed for MSN only. OpenSSL exports nice cipher functions already, - # in case of GnuTLS we should be able to use gcrypt. Otherwise, use - # built-in stuff. (Since right now those are the only two supported - # SSL modules anyway, this is mostly unnecessary.) - echo 'DES=des.o' >> Makefile.settings -fi - echo 'SSL_CLIENT=ssl_'$ssl'.o' >> Makefile.settings if detect_resolv_dynamic || detect_resolv_static; then @@ -526,6 +513,11 @@ elif [ "$otr" = "plugin" ]; then fi if [ "$skype" = "1" -o "$skype" = "plugin" ]; then + if [ "$arch" = "Darwin" ]; then + echo "SKYPEFLAGS=-dynamiclib -undefined dynamic_lookup" >> Makefile.settings + else + echo "SKYPEFLAGS=-fPIC -shared" >> Makefile.settings + fi echo 'SKYPE_PI=skype.so' >> Makefile.settings protocols_mods="$protocol_mods skype(plugin)" fi @@ -623,7 +615,7 @@ fi case "$CC" in *gcc* ) echo CFLAGS+=-MMD -MF .depend/\$@.d >> Makefile.settings - for i in . lib protocols protocols/*/; do + for i in . lib tests protocols protocols/*/; do mkdir -p $i/.depend done esac @@ -721,6 +713,12 @@ else echo ' Debugging disabled.' fi +if [ "$pie" = "1" ]; then + echo ' Building PIE executable' +else + echo ' Building non-PIE executable' +fi + if [ "$strip" = "1" ]; then echo ' Binary stripping enabled.' else diff --git a/debian/bitlbee-common.postrm b/debian/bitlbee-common.postrm index de48e229..92465c4a 100644 --- a/debian/bitlbee-common.postrm +++ b/debian/bitlbee-common.postrm @@ -12,5 +12,5 @@ fi update-rc.d bitlbee remove > /dev/null 2>&1 || true rm -f /etc/default/bitlbee -deluser --system --remove-home bitlbee || true +deluser --system bitlbee || true rm -rf /var/lib/bitlbee ## deluser doesn't seem to do this for homedirs in /var diff --git a/debian/bitlbee-dev.postinst b/debian/bitlbee-dev.postinst new file mode 100644 index 00000000..e5e3e7fd --- /dev/null +++ b/debian/bitlbee-dev.postinst @@ -0,0 +1,14 @@ +#!/bin/sh +set -e + +# Replace documentation directory with symlink +docdir="/usr/share/doc/bitlbee-dev" +if [ -d $docdir ] && [ ! -L $docdir ]; then + if rmdir $docdir 2>/dev/null; then + ln -sf bitlbee-common $docdir + fi +fi + +#DEBHELPER# + +exit 0 diff --git a/debian/bitlbee.postinst b/debian/bitlbee.postinst new file mode 100644 index 00000000..18209bd4 --- /dev/null +++ b/debian/bitlbee.postinst @@ -0,0 +1,14 @@ +#!/bin/sh +set -e + +# Replace documentation directory with symlink +docdir="/usr/share/doc/bitlbee" +if [ -d $docdir ] && [ ! -L $docdir ]; then + if rmdir $docdir 2>/dev/null; then + ln -sf bitlbee-common $docdir + fi +fi + +#DEBHELPER# + +exit 0 diff --git a/debian/changelog b/debian/changelog index 11e08f5c..bdafe497 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,37 @@ +bitlbee (3.2-1) unstable; urgency=high + + * New upstream release. + * Depend on gnutls-dev instead of libgnutls-dev. (Closes: #691766) + * Also, drop nss dependency. GnuTLS is supported officially, the rest is + use-at-your-own-risk (so compile it yourself). + + -- Wilmer van der Gaast <wilmer@gaast.net> Mon, 14 Jan 2013 22:34:06 +0000 + +bitlbee (3.0.6-1) unstable; urgency=low + + * New upstream release. + + -- Wilmer van der Gaast <wilmer@gaast.net> Sun, 28 Oct 2012 19:58:33 +0000 + +bitlbee (3.0.5-1.2) unstable; urgency=low + + * Non-maintainer upload. + * debian/bitlbee{,-dev}.postinst: Fix directory to symlink upgrade in + postinst. (Closes: #687865) + + -- David Prévot <taffit@debian.org> Wed, 26 Sep 2012 23:20:41 -0400 + +bitlbee (3.0.5-1.1) unstable; urgency=low + + * Non-maintainer upload. + * Fix "fails to install, purge, and install again": + remove --remove-home option from deluser call in bitlbee-common.postrm. + The option needs perl-modules which is not guaranteed to be there, and the + directory gets removed manually anyway. + (Closes: #681146) + + -- gregor herrmann <gregoa@debian.org> Thu, 26 Jul 2012 18:44:36 +0200 + bitlbee (3.0.5-1) unstable; urgency=low * New upstream release. diff --git a/debian/control b/debian/control index 181feccb..1f92aa2c 100644 --- a/debian/control +++ b/debian/control @@ -4,7 +4,7 @@ Priority: optional Maintainer: Wilmer van der Gaast <wilmer@gaast.net> Uploaders: Jelmer Vernooij <jelmer@samba.org> Standards-Version: 3.9.1 -Build-Depends: libglib2.0-dev (>= 2.4), libevent-dev, libgnutls-dev | libnss-dev (>= 1.6), po-debconf, libpurple-dev, libotr2-dev, debhelper (>= 6.0.7~), asciidoc +Build-Depends: libglib2.0-dev (>= 2.4), libevent-dev, gnutls-dev | libgnutls-dev, po-debconf, libpurple-dev, libotr2-dev, debhelper (>= 6.0.7~), asciidoc Homepage: http://www.bitlbee.org/ Vcs-Bzr: http://code.bitlbee.org/bitlbee/ DM-Upload-Allowed: yes diff --git a/debian/copyright b/debian/copyright index a29a43b3..9002c219 100644 --- a/debian/copyright +++ b/debian/copyright @@ -4,11 +4,20 @@ Mon, 8 Jul 2002 13:17:42 +0200. The source can be downloaded from http://www.bitlbee.org/ Authors: Wilmer van der Gaast, Sjoerd Hemminga, Jelmer Vernooij, - Maurits Dijkstra and others. + Maurits Dijkstra, Geert Mulders, Miklos Vajna and others. + +Mainly Copyright 2002-2012 Wilmer van der Gaast. + + +Bits of third party code, also GPLed: +* Some parts (mostly protocols/oscar/) are borrowed from Gaim (version + 0.58), now known as Pidgin <http://www.pidgin.im/>. +* protocols/yahoo/ is libyahoo2 <http://libyahoo2.sf.net/>. + +Other license (but GPL-compatible): +* lib/json.[ch] is from <https://github.com/udp/json-parser> and licensed + under the modified BSD license. -Mainly Copyright 2002-2004 Wilmer van der Gaast. -Some parts are borrowed from Gaim (version 0.58) <http://gaim.sf.net/>. -For the copyrights on those parts, please read the Gaim source code. BitlBee License: @@ -32,362 +41,15 @@ BitlBee License: The SGML-formatted documentation is written by Jelmer Vernooij -<jelmer@nl.linux.org> under the GNU Free Documentation License: +<jelmer@samba.org> under the GNU Free Documentation License: ============================================================================ - GNU Free Documentation License - Version 1.1, March 2000 - - Copyright (C) 2000 Free Software Foundation, Inc. - 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - -0. PREAMBLE - -The purpose of this License is to make a manual, textbook, or other -written document "free" in the sense of freedom: to assure everyone -the effective freedom to copy and redistribute it, with or without -modifying it, either commercially or noncommercially. Secondarily, -this License preserves for the author and publisher a way to get -credit for their work, while not being considered responsible for -modifications made by others. - -This License is a kind of "copyleft", which means that derivative -works of the document must themselves be free in the same sense. It -complements the GNU General Public License, which is a copyleft -license designed for free software. - -We have designed this License in order to use it for manuals for free -software, because free software needs free documentation: a free -program should come with manuals providing the same freedoms that the -software does. But this License is not limited to software manuals; -it can be used for any textual work, regardless of subject matter or -whether it is published as a printed book. We recommend this License -principally for works whose purpose is instruction or reference. - - -1. APPLICABILITY AND DEFINITIONS - -This License applies to any manual or other work that contains a -notice placed by the copyright holder saying it can be distributed -under the terms of this License. The "Document", below, refers to any -such manual or work. Any member of the public is a licensee, and is -addressed as "you". - -A "Modified Version" of the Document means any work containing the -Document or a portion of it, either copied verbatim, or with -modifications and/or translated into another language. - -A "Secondary Section" is a named appendix or a front-matter section of -the Document that deals exclusively with the relationship of the -publishers or authors of the Document to the Document's overall subject -(or to related matters) and contains nothing that could fall directly -within that overall subject. (For example, if the Document is in part a -textbook of mathematics, a Secondary Section may not explain any -mathematics.) The relationship could be a matter of historical -connection with the subject or with related matters, or of legal, -commercial, philosophical, ethical or political position regarding -them. - -The "Invariant Sections" are certain Secondary Sections whose titles -are designated, as being those of Invariant Sections, in the notice -that says that the Document is released under this License. - -The "Cover Texts" are certain short passages of text that are listed, -as Front-Cover Texts or Back-Cover Texts, in the notice that says that -the Document is released under this License. - -A "Transparent" copy of the Document means a machine-readable copy, -represented in a format whose specification is available to the -general public, whose contents can be viewed and edited directly and -straightforwardly with generic text editors or (for images composed of -pixels) generic paint programs or (for drawings) some widely available -drawing editor, and that is suitable for input to text formatters or -for automatic translation to a variety of formats suitable for input -to text formatters. A copy made in an otherwise Transparent file -format whose markup has been designed to thwart or discourage -subsequent modification by readers is not Transparent. A copy that is -not "Transparent" is called "Opaque". - -Examples of suitable formats for Transparent copies include plain -ASCII without markup, Texinfo input format, LaTeX input format, SGML -or XML using a publicly available DTD, and standard-conforming simple -HTML designed for human modification. Opaque formats include -PostScript, PDF, proprietary formats that can be read and edited only -by proprietary word processors, SGML or XML for which the DTD and/or -processing tools are not generally available, and the -machine-generated HTML produced by some word processors for output -purposes only. - -The "Title Page" means, for a printed book, the title page itself, -plus such following pages as are needed to hold, legibly, the material -this License requires to appear in the title page. For works in -formats which do not have any title page as such, "Title Page" means -the text near the most prominent appearance of the work's title, -preceding the beginning of the body of the text. - - -2. VERBATIM COPYING - -You may copy and distribute the Document in any medium, either -commercially or noncommercially, provided that this License, the -copyright notices, and the license notice saying this License applies -to the Document are reproduced in all copies, and that you add no other -conditions whatsoever to those of this License. You may not use -technical measures to obstruct or control the reading or further -copying of the copies you make or distribute. However, you may accept -compensation in exchange for copies. If you distribute a large enough -number of copies you must also follow the conditions in section 3. - -You may also lend copies, under the same conditions stated above, and -you may publicly display copies. - - -3. COPYING IN QUANTITY - -If you publish printed copies of the Document numbering more than 100, -and the Document's license notice requires Cover Texts, you must enclose -the copies in covers that carry, clearly and legibly, all these Cover -Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on -the back cover. Both covers must also clearly and legibly identify -you as the publisher of these copies. The front cover must present -the full title with all words of the title equally prominent and -visible. You may add other material on the covers in addition. -Copying with changes limited to the covers, as long as they preserve -the title of the Document and satisfy these conditions, can be treated -as verbatim copying in other respects. - -If the required texts for either cover are too voluminous to fit -legibly, you should put the first ones listed (as many as fit -reasonably) on the actual cover, and continue the rest onto adjacent -pages. - -If you publish or distribute Opaque copies of the Document numbering -more than 100, you must either include a machine-readable Transparent -copy along with each Opaque copy, or state in or with each Opaque copy -a publicly-accessible computer-network location containing a complete -Transparent copy of the Document, free of added material, which the -general network-using public has access to download anonymously at no -charge using public-standard network protocols. If you use the latter -option, you must take reasonably prudent steps, when you begin -distribution of Opaque copies in quantity, to ensure that this -Transparent copy will remain thus accessible at the stated location -until at least one year after the last time you distribute an Opaque -copy (directly or through your agents or retailers) of that edition to -the public. - -It is requested, but not required, that you contact the authors of the -Document well before redistributing any large number of copies, to give -them a chance to provide you with an updated version of the Document. - - -4. MODIFICATIONS - -You may copy and distribute a Modified Version of the Document under -the conditions of sections 2 and 3 above, provided that you release -the Modified Version under precisely this License, with the Modified -Version filling the role of the Document, thus licensing distribution -and modification of the Modified Version to whoever possesses a copy -of it. In addition, you must do these things in the Modified Version: - -A. Use in the Title Page (and on the covers, if any) a title distinct - from that of the Document, and from those of previous versions - (which should, if there were any, be listed in the History section - of the Document). You may use the same title as a previous version - if the original publisher of that version gives permission. -B. List on the Title Page, as authors, one or more persons or entities - responsible for authorship of the modifications in the Modified - Version, together with at least five of the principal authors of the - Document (all of its principal authors, if it has less than five). -C. State on the Title page the name of the publisher of the - Modified Version, as the publisher. -D. Preserve all the copyright notices of the Document. -E. Add an appropriate copyright notice for your modifications - adjacent to the other copyright notices. -F. Include, immediately after the copyright notices, a license notice - giving the public permission to use the Modified Version under the - terms of this License, in the form shown in the Addendum below. -G. Preserve in that license notice the full lists of Invariant Sections - and required Cover Texts given in the Document's license notice. -H. Include an unaltered copy of this License. -I. Preserve the section entitled "History", and its title, and add to - it an item stating at least the title, year, new authors, and - publisher of the Modified Version as given on the Title Page. If - there is no section entitled "History" in the Document, create one - stating the title, year, authors, and publisher of the Document as - given on its Title Page, then add an item describing the Modified - Version as stated in the previous sentence. -J. Preserve the network location, if any, given in the Document for - public access to a Transparent copy of the Document, and likewise - the network locations given in the Document for previous versions - it was based on. These may be placed in the "History" section. - You may omit a network location for a work that was published at - least four years before the Document itself, or if the original - publisher of the version it refers to gives permission. -K. In any section entitled "Acknowledgements" or "Dedications", - preserve the section's title, and preserve in the section all the - substance and tone of each of the contributor acknowledgements - and/or dedications given therein. -L. Preserve all the Invariant Sections of the Document, - unaltered in their text and in their titles. Section numbers - or the equivalent are not considered part of the section titles. -M. Delete any section entitled "Endorsements". Such a section - may not be included in the Modified Version. -N. Do not retitle any existing section as "Endorsements" - or to conflict in title with any Invariant Section. - -If the Modified Version includes new front-matter sections or -appendices that qualify as Secondary Sections and contain no material -copied from the Document, you may at your option designate some or all -of these sections as invariant. To do this, add their titles to the -list of Invariant Sections in the Modified Version's license notice. -These titles must be distinct from any other section titles. - -You may add a section entitled "Endorsements", provided it contains -nothing but endorsements of your Modified Version by various -parties--for example, statements of peer review or that the text has -been approved by an organization as the authoritative definition of a -standard. - -You may add a passage of up to five words as a Front-Cover Text, and a -passage of up to 25 words as a Back-Cover Text, to the end of the list -of Cover Texts in the Modified Version. Only one passage of -Front-Cover Text and one of Back-Cover Text may be added by (or -through arrangements made by) any one entity. If the Document already -includes a cover text for the same cover, previously added by you or -by arrangement made by the same entity you are acting on behalf of, -you may not add another; but you may replace the old one, on explicit -permission from the previous publisher that added the old one. - -The author(s) and publisher(s) of the Document do not by this License -give permission to use their names for publicity for or to assert or -imply endorsement of any Modified Version. - - -5. COMBINING DOCUMENTS - -You may combine the Document with other documents released under this -License, under the terms defined in section 4 above for modified -versions, provided that you include in the combination all of the -Invariant Sections of all of the original documents, unmodified, and -list them all as Invariant Sections of your combined work in its -license notice. - -The combined work need only contain one copy of this License, and -multiple identical Invariant Sections may be replaced with a single -copy. If there are multiple Invariant Sections with the same name but -different contents, make the title of each such section unique by -adding at the end of it, in parentheses, the name of the original -author or publisher of that section if known, or else a unique number. -Make the same adjustment to the section titles in the list of -Invariant Sections in the license notice of the combined work. - -In the combination, you must combine any sections entitled "History" -in the various original documents, forming one section entitled -"History"; likewise combine any sections entitled "Acknowledgements", -and any sections entitled "Dedications". You must delete all sections -entitled "Endorsements." - - -6. COLLECTIONS OF DOCUMENTS - -You may make a collection consisting of the Document and other documents -released under this License, and replace the individual copies of this -License in the various documents with a single copy that is included in -the collection, provided that you follow the rules of this License for -verbatim copying of each of the documents in all other respects. - -You may extract a single document from such a collection, and distribute -it individually under this License, provided you insert a copy of this -License into the extracted document, and follow this License in all -other respects regarding verbatim copying of that document. - - -7. AGGREGATION WITH INDEPENDENT WORKS - -A compilation of the Document or its derivatives with other separate -and independent documents or works, in or on a volume of a storage or -distribution medium, does not as a whole count as a Modified Version -of the Document, provided no compilation copyright is claimed for the -compilation. Such a compilation is called an "aggregate", and this -License does not apply to the other self-contained works thus compiled -with the Document, on account of their being thus compiled, if they -are not themselves derivative works of the Document. - -If the Cover Text requirement of section 3 is applicable to these -copies of the Document, then if the Document is less than one quarter -of the entire aggregate, the Document's Cover Texts may be placed on -covers that surround only the Document within the aggregate. -Otherwise they must appear on covers around the whole aggregate. - - -8. TRANSLATION - -Translation is considered a kind of modification, so you may -distribute translations of the Document under the terms of section 4. -Replacing Invariant Sections with translations requires special -permission from their copyright holders, but you may include -translations of some or all Invariant Sections in addition to the -original versions of these Invariant Sections. You may include a -translation of this License provided that you also include the -original English version of this License. In case of a disagreement -between the translation and the original English version of this -License, the original English version will prevail. - - -9. TERMINATION - -You may not copy, modify, sublicense, or distribute the Document except -as expressly provided for under this License. Any other attempt to -copy, modify, sublicense or distribute the Document is void, and will -automatically terminate your rights under this License. However, -parties who have received copies, or rights, from you under this -License will not have their licenses terminated so long as such -parties remain in full compliance. - - -10. FUTURE REVISIONS OF THIS LICENSE - -The Free Software Foundation may publish new, revised versions -of the GNU Free Documentation License from time to time. Such new -versions will be similar in spirit to the present version, but may -differ in detail to address new problems or concerns. See -http://www.gnu.org/copyleft/. - -Each version of the License is given a distinguishing version number. -If the Document specifies that a particular numbered version of this -License "or any later version" applies to it, you have the option of -following the terms and conditions either of that specified version or -of any later version that has been published (not as a draft) by the -Free Software Foundation. If the Document does not specify a version -number of this License, you may choose any version ever published (not -as a draft) by the Free Software Foundation. - - -ADDENDUM: How to use this License for your documents - -To use this License in a document you have written, include a copy of -the License in the document and put the following copyright and -license notices just after the title page: - - Copyright (c) YEAR YOUR NAME. - Permission is granted to copy, distribute and/or modify this document - under the terms of the GNU Free Documentation License, Version 1.1 - or any later version published by the Free Software Foundation; - with the Invariant Sections being LIST THEIR TITLES, with the - Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST. - A copy of the license is included in the section entitled "GNU - Free Documentation License". - -If you have no Invariant Sections, write "with no Invariant Sections" -instead of saying which ones are invariant. If you have no -Front-Cover Texts, write "no Front-Cover Texts" instead of -"Front-Cover Texts being LIST"; likewise for Back-Cover Texts. - -If your document contains nontrivial examples of program code, we -recommend releasing these examples in parallel under your choice of -free software license, such as the GNU General Public License, -to permit their use in free software. +Copyright (c) 2002-2012 Jelmer Vernooij, Wilmer van der Gaast. + +Permission is granted to copy, distribute and/or modify this document +under the terms of the GNU Free Documentation License, Version 1.1 or +any later version published by the Free Software Foundation; with no +Invariant Sections, with no Front-Cover Texts, and with no Back-Cover +Texts. A copy of the license is included in the section entitled `GNU +Free Documentation License''. ============================================================================ diff --git a/debian/source/options b/debian/source/options new file mode 100644 index 00000000..91a9b784 --- /dev/null +++ b/debian/source/options @@ -0,0 +1 @@ +--diff-ignore='(^|/)\.bzr' diff --git a/doc/AUTHORS b/doc/AUTHORS index 6dab1040..24901bee 100644 --- a/doc/AUTHORS +++ b/doc/AUTHORS @@ -1,19 +1,32 @@ -Current developers: +Core team: Wilmer van der Gaast <wilmer@gaast.net> Main developer -Jelmer 'ctrlsoft' Vernooij <jelmer@samba.org> - Documentation, general hacking, Win32 port -Maurits Dijkstra <mauritsd@xs4all.nl> - Daemon dude, plus some other stuff +Other contributors: +Miklos Vajna <vmiklos@vmiklos.hu> + Skype module -Retired developer: +pesco <pesco@khjk.org> + OTR support + + +Retired developers: Sjoerd 'lucumo' Hemminga <sjoerd@hemminga-online.nl> NickServ, documentation -The development team wishes to thank Sjoerd for his contributions to the -Bee. +Jelmer 'ctrlsoft' Vernooij <jelmer@samba.org> + Documentation, general hacking, Win32 port + +Maurits Dijkstra <mauritsd@xs4all.nl> + Daemon dude, plus some other stuff + +Geert Mulders <g.c.w.m.mulders@gmail.com> + Initial version of the Twitter module + +ulim <a.sporto+bee@gmail.com> +Marijn Kruisselbrink + File transfer support diff --git a/doc/CHANGES b/doc/CHANGES index 9375225f..7ead8466 100644 --- a/doc/CHANGES +++ b/doc/CHANGES @@ -3,6 +3,45 @@ found in the bzr commit logs, for example you can try: http://bugs.bitlbee.org/bitlbee/timeline?daysback=90&changeset=on +Version 3.2: +- By far the most important change, a thorough update to the Twitter + module: + * Now using Twitter API 1.1, + * which means it's now using JSON instead of XML, + * which means access to the streaming API (Twitter only, other Twitter + API services don't seem to have it). No more 60-second polls, #twitter + looks even more like real IRC now! + * Also, the streaming API means nice things like receiving DMs. + * show_ids, already enabled by default for a while, now uses hexa- + decimal numbers, which means a 256-entry backlog instead of just 100. + * Added a mode=strict setting which requires everything to be a command. + The "post" command should then be used to post a Tweet. +- Jabber module bugfix that fixes connection issues with at least Google + Talk but reportedly some other servers (OpenFire?) as well. +- SSL modules improved a little bit. GnuTLS module now supports SNI and + session caching. Shouldn't change much, but hopefully reduces latency + and bandwidth usage a little bit. +- A bunch of other fixes/improvements here and there. + +Finished 6 Jan 2013 + +Version 3.0.6: +- Updated MSN module to speak MSNP18: + * Biggest change is that this brings MPOP support (you can sign in to + one account from multiple locations). + * Restored support for *sending* offline messages. + * Some support for federated (i.e. Yahoo!) contacts. (Only messages + might work, you won't see them online.) +- Twitter: + * Work-around for stalls that are still happening sometimes. + * Added "favourite" command. + * "show_ids" enabled by default. +- Handle see-other-host Jabber messages which should fix support for + MSN-XMPP. +- Misc. fixes and improvements. + +Finished 14 Oct 2012 + Version 3.0.5: - SSL certificate verification (edit your bitlbee.conf to enable it). Works only with GnuTLS! diff --git a/doc/bitlbee.8 b/doc/bitlbee.8 index d01ec39e..b5aa7705 100644 --- a/doc/bitlbee.8 +++ b/doc/bitlbee.8 @@ -12,7 +12,7 @@ .\" along with this program; see the file COPYING. If not, write to .\" the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. .\" -.TH bitlbee 8 "07 March 2004" +.TH bitlbee 8 "19 May 2010" .SH NAME BitlBee \- IRC gateway to IM chat networks .SH SYNOPSIS @@ -113,7 +113,3 @@ Foundation, Inc., 59 Temple PLace, Suite 330, Boston, MA 02111-1307 USA .SH AUTHORS .PP Wilmer van der Gaast <wilmer@gaast.net> -.BR - Jelmer Vernooij <jelmer@vernstok.nl> -.BR - Maurits Dijkstra <mauritsd@xs4all.nl> diff --git a/doc/user-guide/commands.xml b/doc/user-guide/commands.xml index 12bbf4bc..3af469c6 100644 --- a/doc/user-guide/commands.xml +++ b/doc/user-guide/commands.xml @@ -68,7 +68,7 @@ </bitlbee-command> <bitlbee-command name="twitter"> - <syntax>account add twitter <handle> [<password>]</syntax> + <syntax>account add twitter <handle></syntax> <description> <para> @@ -94,11 +94,11 @@ </bitlbee-command> <bitlbee-command name="identica"> - <syntax>account add identica <handle> [<password>]</syntax> + <syntax>account add identica <handle></syntax> <description> <para> - Same protocol as <emphasis>twitter</emphasis>, but defaults to a <emphasis>base_url</emphasis> pointing at identi.ca, and with OAuth disabled. + Same protocol as <emphasis>twitter</emphasis>, but defaults to a <emphasis>base_url</emphasis> pointing at identi.ca. It also works with OAuth (so don't specify your password). </para> </description> </bitlbee-command> @@ -834,6 +834,7 @@ <bitlbee-setting name="commands" type="boolean" scope="account"> <default>true</default> + <possible-values>true, false, strict</possible-values> <description> <para> @@ -847,11 +848,12 @@ <varlistentry><term>report <screenname|#id></term><listitem><para>Report the given user (or the user who posted the tweet with the given ID) for sending spam. This will also block them.</para></listitem></varlistentry> <varlistentry><term>follow <screenname></term><listitem><para>Start following a person</para></listitem></varlistentry> <varlistentry><term>unfollow <screenname></term><listitem><para>Stop following a person</para></listitem></varlistentry> + <varlistentry><term>favourite <screenname|#id></term><listitem><para>Favo<emphasis>u</emphasis>rite the given user's most recent tweet, or the given tweet ID.</para></listitem></varlistentry> <varlistentry><term>post <message></term><listitem><para>Post a tweet</para></listitem></varlistentry> </variablelist> <para> - Anything that doesn't look like a command will be treated as a tweet. Watch out for typos! :-) + Anything that doesn't look like a command will be treated as a tweet. Watch out for typos, or to avoid this behaviour, you can set this setting to <emphasis>strict</emphasis>, which causes the <emphasis>post</emphasis> command to become mandatory for posting a tweet. </para> </description> </bitlbee-setting> @@ -927,6 +929,10 @@ </para> <para> + With a ! prefix an inverted channel can be created, for example with this setting set to <emphasis>!group</emphasis> you can create a channel with all users <emphasis>not</emphasis> in that group. + </para> + + <para> Note that, when creating a new channel, BitlBee will try to preconfigure the channel for you, based on the channel name. See <emphasis>help channels</emphasis>. </para> </description> @@ -1021,6 +1027,21 @@ </description> </bitlbee-setting> + + <bitlbee-setting name="stream" type="boolean" scope="account"> + <default>true</default> + + <description> + <para> + For Twitter accounts, this setting enables use of the Streaming API. This automatically gives you incoming DMs as well. + </para> + + <para> + For other Twitter-like services, this setting is not supported. + </para> + </description> + + </bitlbee-setting> <bitlbee-setting name="target_url_length" type="integer" scope="account"> <default>20</default> @@ -1336,7 +1357,7 @@ </bitlbee-setting> <bitlbee-setting name="show_ids" type="boolean" scope="account"> - <default>false</default> + <default>true</default> <description> <para> @@ -1500,15 +1521,15 @@ </bitlbee-setting> <bitlbee-setting name="tls" type="boolean" scope="account"> - <default>try</default> + <default>true</default> <description> <para> - Newer Jabber servers allow clients to convert a plain-text session to a TLS/SSL-encrypted session. Normally (with this setting set to <emphasis>try</emphasis>) BitlBee will do this, if possible. + By default (with this setting enabled), BitlBee will require Jabber servers to offer encryption via StartTLS and refuse to connect if they don't. </para> <para> - If you want to force BitlBee to use TLS sessions only (and to give up if that doesn't seem to be possible) you can set this setting to <emphasis>true</emphasis>. Set it to <emphasis>false</emphasis> if you want the session to remain plain-text. + If you set this to "try", BitlBee will use StartTLS only if it's offered. With the setting disabled, StartTLS support will be ignored and avoided entirely. </para> </description> </bitlbee-setting> @@ -1766,11 +1787,15 @@ <bitlbee-command name="group"> <short-description>Contact group management</short-description> - <syntax>group list</syntax> + <syntax>group [ list | info <group> ]</syntax> <description> <para> - Only the <emphasis>group list</emphasis> command is supported at the moment, which shows a list of all groups defined so far. + The <emphasis>group list</emphasis> command shows a list of all groups defined so far. + </para> + + <para> + The <emphasis>group info</emphasis> command shows a list of all members of a the group <group>. </para> <para> diff --git a/doc/user-guide/help.xml b/doc/user-guide/help.xml index 48ed8a48..e40a04d1 100644 --- a/doc/user-guide/help.xml +++ b/doc/user-guide/help.xml @@ -25,7 +25,7 @@ You can read more about them with <emphasis>help <subject></emphasis> </para> <para> -BitlBee is written by Wilmer van der Gaast together with Jelmer Vernooij, Maurits Dijkstra and others. Bugs can be reported at <ulink link="http://bugs.bitlbee.org/">http://bugs.bitlbee.org/</ulink>. +Some more help can be found on <ulink link="http://wiki.bitlbee.org/">http://wiki.bitlbee.org/</ulink>. Bugs can be reported at <ulink link="http://bugs.bitlbee.org/">http://bugs.bitlbee.org/</ulink>. </para> <para> diff --git a/doc/user-guide/misc.xml b/doc/user-guide/misc.xml index 3eb5dd68..ac2734ca 100644 --- a/doc/user-guide/misc.xml +++ b/doc/user-guide/misc.xml @@ -385,4 +385,14 @@ by updating your <emphasis>bitlbee.conf</emphasis>. </para> </sect1> +<sect1 id="whatsnew030200"> +<title>New stuff in BitlBee 3.2</title> + +<para> +Upgradeed to Twitter API version 1.1. This is necessary because previous +versions will stop working from March 2013. At the same time, BitlBee now +supports the streaming API and incoming direct messages. +</para> +</sect1> + </chapter> @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2010 Wilmer van der Gaast and others * + * Copyright 2002-2012 Wilmer van der Gaast and others * \********************************************************************/ /* IPC - communication between BitlBee processes */ @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2004 Wilmer van der Gaast and others * + * Copyright 2002-2012 Wilmer van der Gaast and others * \********************************************************************/ /* The IRC-based UI (for now the only one) */ @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2010 Wilmer van der Gaast and others * + * Copyright 2002-2013 Wilmer van der Gaast and others * \********************************************************************/ /* The IRC-based UI (for now the only one) */ @@ -206,11 +206,13 @@ typedef struct irc_channel_user typedef enum { - IRC_CC_TYPE_DEFAULT, - IRC_CC_TYPE_REST, - IRC_CC_TYPE_GROUP, - IRC_CC_TYPE_ACCOUNT, - IRC_CC_TYPE_PROTOCOL, + IRC_CC_TYPE_DEFAULT = 0x00001, + IRC_CC_TYPE_REST = 0x00002, /* Still not implemented. */ + IRC_CC_TYPE_GROUP = 0x00004, + IRC_CC_TYPE_ACCOUNT = 0x00008, + IRC_CC_TYPE_PROTOCOL = 0x00010, + IRC_CC_TYPE_MASK = 0x000ff, + IRC_CC_TYPE_INVERT = 0x00100, } irc_control_channel_type_t; struct irc_control_channel diff --git a/irc_channel.c b/irc_channel.c index 7dc9f885..4e8c0bb5 100644 --- a/irc_channel.c +++ b/irc_channel.c @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2010 Wilmer van der Gaast and others * + * Copyright 2002-2013 Wilmer van der Gaast and others * \********************************************************************/ /* The IRC-based UI - Representing (virtual) channels. */ @@ -669,7 +669,7 @@ static char *set_eval_by_account( set_t *set, char *value ) return SET_INVALID; icc->account = acc; - if( icc->type == IRC_CC_TYPE_ACCOUNT ) + if( ( icc->type & IRC_CC_TYPE_MASK ) == IRC_CC_TYPE_ACCOUNT ) bee_irc_channel_update( ic->irc, ic, NULL ); return g_strdup( acc->tag ); @@ -679,17 +679,27 @@ static char *set_eval_fill_by( set_t *set, char *value ) { struct irc_channel *ic = set->data; struct irc_control_channel *icc = ic->data; + char *s; - if( strcmp( value, "all" ) == 0 ) - icc->type = IRC_CC_TYPE_DEFAULT; - else if( strcmp( value, "rest" ) == 0 ) - icc->type = IRC_CC_TYPE_REST; - else if( strcmp( value, "group" ) == 0 ) - icc->type = IRC_CC_TYPE_GROUP; - else if( strcmp( value, "account" ) == 0 ) - icc->type = IRC_CC_TYPE_ACCOUNT; - else if( strcmp( value, "protocol" ) == 0 ) - icc->type = IRC_CC_TYPE_PROTOCOL; + icc->type &= ~( IRC_CC_TYPE_MASK | IRC_CC_TYPE_INVERT ); + + s = value; + if( s[0] == '!' ) + { + icc->type |= IRC_CC_TYPE_INVERT; + s ++; + } + + if( strcmp( s, "all" ) == 0 ) + icc->type |= IRC_CC_TYPE_DEFAULT; + else if( strcmp( s, "rest" ) == 0 ) + icc->type |= IRC_CC_TYPE_REST; + else if( strcmp( s, "group" ) == 0 ) + icc->type |= IRC_CC_TYPE_GROUP; + else if( strcmp( s, "account" ) == 0 ) + icc->type |= IRC_CC_TYPE_ACCOUNT; + else if( strcmp( s, "protocol" ) == 0 ) + icc->type |= IRC_CC_TYPE_PROTOCOL; else return SET_INVALID; @@ -703,7 +713,7 @@ static char *set_eval_by_group( set_t *set, char *value ) struct irc_control_channel *icc = ic->data; icc->group = bee_group_by_name( ic->irc->b, value, TRUE ); - if( icc->type == IRC_CC_TYPE_GROUP ) + if( ( icc->type & IRC_CC_TYPE_MASK ) == IRC_CC_TYPE_GROUP ) bee_irc_channel_update( ic->irc, ic, NULL ); return g_strdup( icc->group->name ); @@ -719,7 +729,7 @@ static char *set_eval_by_protocol( set_t *set, char *value ) return SET_INVALID; icc->protocol = prpl; - if( icc->type == IRC_CC_TYPE_PROTOCOL ) + if( ( icc->type & IRC_CC_TYPE_MASK ) == IRC_CC_TYPE_PROTOCOL ) bee_irc_channel_update( ic->irc, ic, NULL ); return value; @@ -775,22 +785,32 @@ fail: gboolean irc_channel_wants_user( irc_channel_t *ic, irc_user_t *iu ) { struct irc_control_channel *icc = ic->data; + gboolean ret = FALSE; if( iu->bu == NULL ) return FALSE; - switch( icc->type ) + switch( icc->type & IRC_CC_TYPE_MASK ) { case IRC_CC_TYPE_GROUP: - return iu->bu->group == icc->group; + ret = iu->bu->group == icc->group; + break; case IRC_CC_TYPE_ACCOUNT: - return iu->bu->ic->acc == icc->account; + ret = iu->bu->ic->acc == icc->account; + break; case IRC_CC_TYPE_PROTOCOL: - return iu->bu->ic->acc->prpl == icc->protocol; + ret = iu->bu->ic->acc->prpl == icc->protocol; + break; case IRC_CC_TYPE_DEFAULT: default: - return TRUE; + ret = TRUE; + break; } + + if( icc->type & IRC_CC_TYPE_INVERT ) + ret = !ret; + + return ret; } static gboolean control_channel_free( irc_channel_t *ic ) diff --git a/irc_commands.c b/irc_commands.c index 9a46f882..740d3eb2 100644 --- a/irc_commands.c +++ b/irc_commands.c @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2010 Wilmer van der Gaast and others * + * Copyright 2002-2012 Wilmer van der Gaast and others * \********************************************************************/ /* IRC commands */ @@ -381,6 +381,8 @@ static void irc_cmd_privmsg( irc_t *irc, char **cmd ) static void irc_cmd_notice( irc_t *irc, char **cmd ) { + irc_user_t *iu; + if( !cmd[2] ) { irc_send_num( irc, 412, ":No text to send" ); @@ -391,6 +393,8 @@ static void irc_cmd_notice( irc_t *irc, char **cmd ) for lag checks, so try to support that. */ if( nick_cmp( cmd[1], irc->user->nick ) == 0 ) irc_send_msg( irc->user, "NOTICE", irc->user->nick, cmd[2], NULL ); + else if( ( iu = irc_user_by_name( irc, cmd[1] ) ) ) + iu->f->privmsg( iu, cmd[2] ); } static void irc_cmd_nickserv( irc_t *irc, char **cmd ) @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2010 Wilmer van der Gaast and others * + * Copyright 2002-2012 Wilmer van der Gaast and others * \********************************************************************/ /* Some glue to put the IRC and the IM stuff together. */ @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2010 Wilmer van der Gaast and others * + * Copyright 2002-2012 Wilmer van der Gaast and others * \********************************************************************/ /* The IRC-based UI - Sending responses to commands/etc. */ @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2004 Wilmer van der Gaast and others * + * Copyright 2002-2012 Wilmer van der Gaast and others * \********************************************************************/ /* Stuff to handle, save and search IRC buddies */ diff --git a/lib/Makefile b/lib/Makefile index 76c41fc3..f20b3797 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -12,7 +12,7 @@ _SRCDIR_ := $(_SRCDIR_)lib/ endif # [SH] Program variables -objects = arc.o base64.o $(DES) $(EVENT_HANDLER) ftutil.o http_client.o ini.o md5.o misc.o oauth.o oauth2.o proxy.o sha1.o $(SSL_CLIENT) url.o xmltree.o +objects = arc.o base64.o $(EVENT_HANDLER) ftutil.o http_client.o ini.o json.o json_util.o md5.o misc.o oauth.o oauth2.o proxy.o sha1.o $(SSL_CLIENT) url.o xmltree.o LFLAGS += -r @@ -41,6 +41,6 @@ $(objects): ../Makefile.settings Makefile $(objects): %.o: $(_SRCDIR_)%.c @echo '*' Compiling $< - @$(CC) -c $(CFLAGS) $< -o $@ + @$(CC) -c $(CFLAGS) $(CFLAGS_BITLBEE) $< -o $@ -include .depend/*.d diff --git a/lib/des.c b/lib/des.c deleted file mode 100644 index 3b9cc8d5..00000000 --- a/lib/des.c +++ /dev/null @@ -1,646 +0,0 @@ -/* - * FIPS-46-3 compliant 3DES implementation - * - * Copyright (C) 2001-2003 Christophe Devine - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Modified for BitlBee: Added a function compatible with the existing - * function in ssl_openssl.c, fairly specialised for MSN auth (since that's - * all this is used for at least for now). - * - * Added some consts to the tables at the top, and disabled some 64-bit - * and 128-bit key code that I don't need. - * - * *Many* thanks to Christophe for this compact and easy to import code. - */ - -#include <string.h> -#include <glib.h> -#include "des.h" - -/* the eight DES S-boxes */ - -static const uint32_t SB1[64] = -{ - 0x01010400, 0x00000000, 0x00010000, 0x01010404, - 0x01010004, 0x00010404, 0x00000004, 0x00010000, - 0x00000400, 0x01010400, 0x01010404, 0x00000400, - 0x01000404, 0x01010004, 0x01000000, 0x00000004, - 0x00000404, 0x01000400, 0x01000400, 0x00010400, - 0x00010400, 0x01010000, 0x01010000, 0x01000404, - 0x00010004, 0x01000004, 0x01000004, 0x00010004, - 0x00000000, 0x00000404, 0x00010404, 0x01000000, - 0x00010000, 0x01010404, 0x00000004, 0x01010000, - 0x01010400, 0x01000000, 0x01000000, 0x00000400, - 0x01010004, 0x00010000, 0x00010400, 0x01000004, - 0x00000400, 0x00000004, 0x01000404, 0x00010404, - 0x01010404, 0x00010004, 0x01010000, 0x01000404, - 0x01000004, 0x00000404, 0x00010404, 0x01010400, - 0x00000404, 0x01000400, 0x01000400, 0x00000000, - 0x00010004, 0x00010400, 0x00000000, 0x01010004 -}; - -static const uint32_t SB2[64] = -{ - 0x80108020, 0x80008000, 0x00008000, 0x00108020, - 0x00100000, 0x00000020, 0x80100020, 0x80008020, - 0x80000020, 0x80108020, 0x80108000, 0x80000000, - 0x80008000, 0x00100000, 0x00000020, 0x80100020, - 0x00108000, 0x00100020, 0x80008020, 0x00000000, - 0x80000000, 0x00008000, 0x00108020, 0x80100000, - 0x00100020, 0x80000020, 0x00000000, 0x00108000, - 0x00008020, 0x80108000, 0x80100000, 0x00008020, - 0x00000000, 0x00108020, 0x80100020, 0x00100000, - 0x80008020, 0x80100000, 0x80108000, 0x00008000, - 0x80100000, 0x80008000, 0x00000020, 0x80108020, - 0x00108020, 0x00000020, 0x00008000, 0x80000000, - 0x00008020, 0x80108000, 0x00100000, 0x80000020, - 0x00100020, 0x80008020, 0x80000020, 0x00100020, - 0x00108000, 0x00000000, 0x80008000, 0x00008020, - 0x80000000, 0x80100020, 0x80108020, 0x00108000 -}; - -static const uint32_t SB3[64] = -{ - 0x00000208, 0x08020200, 0x00000000, 0x08020008, - 0x08000200, 0x00000000, 0x00020208, 0x08000200, - 0x00020008, 0x08000008, 0x08000008, 0x00020000, - 0x08020208, 0x00020008, 0x08020000, 0x00000208, - 0x08000000, 0x00000008, 0x08020200, 0x00000200, - 0x00020200, 0x08020000, 0x08020008, 0x00020208, - 0x08000208, 0x00020200, 0x00020000, 0x08000208, - 0x00000008, 0x08020208, 0x00000200, 0x08000000, - 0x08020200, 0x08000000, 0x00020008, 0x00000208, - 0x00020000, 0x08020200, 0x08000200, 0x00000000, - 0x00000200, 0x00020008, 0x08020208, 0x08000200, - 0x08000008, 0x00000200, 0x00000000, 0x08020008, - 0x08000208, 0x00020000, 0x08000000, 0x08020208, - 0x00000008, 0x00020208, 0x00020200, 0x08000008, - 0x08020000, 0x08000208, 0x00000208, 0x08020000, - 0x00020208, 0x00000008, 0x08020008, 0x00020200 -}; - -static const uint32_t SB4[64] = -{ - 0x00802001, 0x00002081, 0x00002081, 0x00000080, - 0x00802080, 0x00800081, 0x00800001, 0x00002001, - 0x00000000, 0x00802000, 0x00802000, 0x00802081, - 0x00000081, 0x00000000, 0x00800080, 0x00800001, - 0x00000001, 0x00002000, 0x00800000, 0x00802001, - 0x00000080, 0x00800000, 0x00002001, 0x00002080, - 0x00800081, 0x00000001, 0x00002080, 0x00800080, - 0x00002000, 0x00802080, 0x00802081, 0x00000081, - 0x00800080, 0x00800001, 0x00802000, 0x00802081, - 0x00000081, 0x00000000, 0x00000000, 0x00802000, - 0x00002080, 0x00800080, 0x00800081, 0x00000001, - 0x00802001, 0x00002081, 0x00002081, 0x00000080, - 0x00802081, 0x00000081, 0x00000001, 0x00002000, - 0x00800001, 0x00002001, 0x00802080, 0x00800081, - 0x00002001, 0x00002080, 0x00800000, 0x00802001, - 0x00000080, 0x00800000, 0x00002000, 0x00802080 -}; - -static const uint32_t SB5[64] = -{ - 0x00000100, 0x02080100, 0x02080000, 0x42000100, - 0x00080000, 0x00000100, 0x40000000, 0x02080000, - 0x40080100, 0x00080000, 0x02000100, 0x40080100, - 0x42000100, 0x42080000, 0x00080100, 0x40000000, - 0x02000000, 0x40080000, 0x40080000, 0x00000000, - 0x40000100, 0x42080100, 0x42080100, 0x02000100, - 0x42080000, 0x40000100, 0x00000000, 0x42000000, - 0x02080100, 0x02000000, 0x42000000, 0x00080100, - 0x00080000, 0x42000100, 0x00000100, 0x02000000, - 0x40000000, 0x02080000, 0x42000100, 0x40080100, - 0x02000100, 0x40000000, 0x42080000, 0x02080100, - 0x40080100, 0x00000100, 0x02000000, 0x42080000, - 0x42080100, 0x00080100, 0x42000000, 0x42080100, - 0x02080000, 0x00000000, 0x40080000, 0x42000000, - 0x00080100, 0x02000100, 0x40000100, 0x00080000, - 0x00000000, 0x40080000, 0x02080100, 0x40000100 -}; - -static const uint32_t SB6[64] = -{ - 0x20000010, 0x20400000, 0x00004000, 0x20404010, - 0x20400000, 0x00000010, 0x20404010, 0x00400000, - 0x20004000, 0x00404010, 0x00400000, 0x20000010, - 0x00400010, 0x20004000, 0x20000000, 0x00004010, - 0x00000000, 0x00400010, 0x20004010, 0x00004000, - 0x00404000, 0x20004010, 0x00000010, 0x20400010, - 0x20400010, 0x00000000, 0x00404010, 0x20404000, - 0x00004010, 0x00404000, 0x20404000, 0x20000000, - 0x20004000, 0x00000010, 0x20400010, 0x00404000, - 0x20404010, 0x00400000, 0x00004010, 0x20000010, - 0x00400000, 0x20004000, 0x20000000, 0x00004010, - 0x20000010, 0x20404010, 0x00404000, 0x20400000, - 0x00404010, 0x20404000, 0x00000000, 0x20400010, - 0x00000010, 0x00004000, 0x20400000, 0x00404010, - 0x00004000, 0x00400010, 0x20004010, 0x00000000, - 0x20404000, 0x20000000, 0x00400010, 0x20004010 -}; - -static const uint32_t SB7[64] = -{ - 0x00200000, 0x04200002, 0x04000802, 0x00000000, - 0x00000800, 0x04000802, 0x00200802, 0x04200800, - 0x04200802, 0x00200000, 0x00000000, 0x04000002, - 0x00000002, 0x04000000, 0x04200002, 0x00000802, - 0x04000800, 0x00200802, 0x00200002, 0x04000800, - 0x04000002, 0x04200000, 0x04200800, 0x00200002, - 0x04200000, 0x00000800, 0x00000802, 0x04200802, - 0x00200800, 0x00000002, 0x04000000, 0x00200800, - 0x04000000, 0x00200800, 0x00200000, 0x04000802, - 0x04000802, 0x04200002, 0x04200002, 0x00000002, - 0x00200002, 0x04000000, 0x04000800, 0x00200000, - 0x04200800, 0x00000802, 0x00200802, 0x04200800, - 0x00000802, 0x04000002, 0x04200802, 0x04200000, - 0x00200800, 0x00000000, 0x00000002, 0x04200802, - 0x00000000, 0x00200802, 0x04200000, 0x00000800, - 0x04000002, 0x04000800, 0x00000800, 0x00200002 -}; - -static const uint32_t SB8[64] = -{ - 0x10001040, 0x00001000, 0x00040000, 0x10041040, - 0x10000000, 0x10001040, 0x00000040, 0x10000000, - 0x00040040, 0x10040000, 0x10041040, 0x00041000, - 0x10041000, 0x00041040, 0x00001000, 0x00000040, - 0x10040000, 0x10000040, 0x10001000, 0x00001040, - 0x00041000, 0x00040040, 0x10040040, 0x10041000, - 0x00001040, 0x00000000, 0x00000000, 0x10040040, - 0x10000040, 0x10001000, 0x00041040, 0x00040000, - 0x00041040, 0x00040000, 0x10041000, 0x00001000, - 0x00000040, 0x10040040, 0x00001000, 0x00041040, - 0x10001000, 0x00000040, 0x10000040, 0x10040000, - 0x10040040, 0x10000000, 0x00040000, 0x10001040, - 0x00000000, 0x10041040, 0x00040040, 0x10000040, - 0x10040000, 0x10001000, 0x10001040, 0x00000000, - 0x10041040, 0x00041000, 0x00041000, 0x00001040, - 0x00001040, 0x00040040, 0x10000000, 0x10041000 -}; - -/* PC1: left and right halves bit-swap */ - -static const uint32_t LHs[16] = -{ - 0x00000000, 0x00000001, 0x00000100, 0x00000101, - 0x00010000, 0x00010001, 0x00010100, 0x00010101, - 0x01000000, 0x01000001, 0x01000100, 0x01000101, - 0x01010000, 0x01010001, 0x01010100, 0x01010101 -}; - -static const uint32_t RHs[16] = -{ - 0x00000000, 0x01000000, 0x00010000, 0x01010000, - 0x00000100, 0x01000100, 0x00010100, 0x01010100, - 0x00000001, 0x01000001, 0x00010001, 0x01010001, - 0x00000101, 0x01000101, 0x00010101, 0x01010101, -}; - -/* platform-independant 32-bit integer manipulation macros */ - -#define GET_UINT32(n,b,i) \ -{ \ - (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ - | ( (uint32_t) (b)[(i) + 1] << 16 ) \ - | ( (uint32_t) (b)[(i) + 2] << 8 ) \ - | ( (uint32_t) (b)[(i) + 3] ); \ -} - -#define PUT_UINT32(n,b,i) \ -{ \ - (b)[(i) ] = (uint8_t) ( (n) >> 24 ); \ - (b)[(i) + 1] = (uint8_t) ( (n) >> 16 ); \ - (b)[(i) + 2] = (uint8_t) ( (n) >> 8 ); \ - (b)[(i) + 3] = (uint8_t) ( (n) ); \ -} - -/* Initial Permutation macro */ - -#define DES_IP(X,Y) \ -{ \ - T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \ - T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \ - T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \ - T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \ - Y = ((Y << 1) | (Y >> 31)) & 0xFFFFFFFF; \ - T = (X ^ Y) & 0xAAAAAAAA; Y ^= T; X ^= T; \ - X = ((X << 1) | (X >> 31)) & 0xFFFFFFFF; \ -} - -/* Final Permutation macro */ - -#define DES_FP(X,Y) \ -{ \ - X = ((X << 31) | (X >> 1)) & 0xFFFFFFFF; \ - T = (X ^ Y) & 0xAAAAAAAA; X ^= T; Y ^= T; \ - Y = ((Y << 31) | (Y >> 1)) & 0xFFFFFFFF; \ - T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \ - T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \ - T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \ - T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \ -} - -/* DES round macro */ - -#define DES_ROUND(X,Y) \ -{ \ - T = *SK++ ^ X; \ - Y ^= SB8[ (T ) & 0x3F ] ^ \ - SB6[ (T >> 8) & 0x3F ] ^ \ - SB4[ (T >> 16) & 0x3F ] ^ \ - SB2[ (T >> 24) & 0x3F ]; \ - \ - T = *SK++ ^ ((X << 28) | (X >> 4)); \ - Y ^= SB7[ (T ) & 0x3F ] ^ \ - SB5[ (T >> 8) & 0x3F ] ^ \ - SB3[ (T >> 16) & 0x3F ] ^ \ - SB1[ (T >> 24) & 0x3F ]; \ -} - -/* DES key schedule */ - -int des_main_ks( uint32_t SK[32], const uint8_t key[8] ) -{ - int i; - uint32_t X, Y, T; - - GET_UINT32( X, key, 0 ); - GET_UINT32( Y, key, 4 ); - - /* Permuted Choice 1 */ - - T = ((Y >> 4) ^ X) & 0x0F0F0F0F; X ^= T; Y ^= (T << 4); - T = ((Y ) ^ X) & 0x10101010; X ^= T; Y ^= (T ); - - X = (LHs[ (X ) & 0xF] << 3) | (LHs[ (X >> 8) & 0xF ] << 2) - | (LHs[ (X >> 16) & 0xF] << 1) | (LHs[ (X >> 24) & 0xF ] ) - | (LHs[ (X >> 5) & 0xF] << 7) | (LHs[ (X >> 13) & 0xF ] << 6) - | (LHs[ (X >> 21) & 0xF] << 5) | (LHs[ (X >> 29) & 0xF ] << 4); - - Y = (RHs[ (Y >> 1) & 0xF] << 3) | (RHs[ (Y >> 9) & 0xF ] << 2) - | (RHs[ (Y >> 17) & 0xF] << 1) | (RHs[ (Y >> 25) & 0xF ] ) - | (RHs[ (Y >> 4) & 0xF] << 7) | (RHs[ (Y >> 12) & 0xF ] << 6) - | (RHs[ (Y >> 20) & 0xF] << 5) | (RHs[ (Y >> 28) & 0xF ] << 4); - - X &= 0x0FFFFFFF; - Y &= 0x0FFFFFFF; - - /* calculate subkeys */ - - for( i = 0; i < 16; i++ ) - { - if( i < 2 || i == 8 || i == 15 ) - { - X = ((X << 1) | (X >> 27)) & 0x0FFFFFFF; - Y = ((Y << 1) | (Y >> 27)) & 0x0FFFFFFF; - } - else - { - X = ((X << 2) | (X >> 26)) & 0x0FFFFFFF; - Y = ((Y << 2) | (Y >> 26)) & 0x0FFFFFFF; - } - - *SK++ = ((X << 4) & 0x24000000) | ((X << 28) & 0x10000000) - | ((X << 14) & 0x08000000) | ((X << 18) & 0x02080000) - | ((X << 6) & 0x01000000) | ((X << 9) & 0x00200000) - | ((X >> 1) & 0x00100000) | ((X << 10) & 0x00040000) - | ((X << 2) & 0x00020000) | ((X >> 10) & 0x00010000) - | ((Y >> 13) & 0x00002000) | ((Y >> 4) & 0x00001000) - | ((Y << 6) & 0x00000800) | ((Y >> 1) & 0x00000400) - | ((Y >> 14) & 0x00000200) | ((Y ) & 0x00000100) - | ((Y >> 5) & 0x00000020) | ((Y >> 10) & 0x00000010) - | ((Y >> 3) & 0x00000008) | ((Y >> 18) & 0x00000004) - | ((Y >> 26) & 0x00000002) | ((Y >> 24) & 0x00000001); - - *SK++ = ((X << 15) & 0x20000000) | ((X << 17) & 0x10000000) - | ((X << 10) & 0x08000000) | ((X << 22) & 0x04000000) - | ((X >> 2) & 0x02000000) | ((X << 1) & 0x01000000) - | ((X << 16) & 0x00200000) | ((X << 11) & 0x00100000) - | ((X << 3) & 0x00080000) | ((X >> 6) & 0x00040000) - | ((X << 15) & 0x00020000) | ((X >> 4) & 0x00010000) - | ((Y >> 2) & 0x00002000) | ((Y << 8) & 0x00001000) - | ((Y >> 14) & 0x00000808) | ((Y >> 9) & 0x00000400) - | ((Y ) & 0x00000200) | ((Y << 7) & 0x00000100) - | ((Y >> 7) & 0x00000020) | ((Y >> 3) & 0x00000011) - | ((Y << 2) & 0x00000004) | ((Y >> 21) & 0x00000002); - } - - return( 0 ); -} - -#if TEST -int des_set_key( des_context *ctx, uint8_t key[8] ) -{ - int i; - - /* setup encryption subkeys */ - - des_main_ks( ctx->esk, key ); - - /* setup decryption subkeys */ - - for( i = 0; i < 32; i += 2 ) - { - ctx->dsk[i ] = ctx->esk[30 - i]; - ctx->dsk[i + 1] = ctx->esk[31 - i]; - } - - return( 0 ); -} - -/* DES 64-bit block encryption/decryption */ - -void des_crypt( uint32_t SK[32], uint8_t input[8], uint8_t output[8] ) -{ - uint32_t X, Y, T; - - GET_UINT32( X, input, 0 ); - GET_UINT32( Y, input, 4 ); - - DES_IP( X, Y ); - - DES_ROUND( Y, X ); DES_ROUND( X, Y ); - DES_ROUND( Y, X ); DES_ROUND( X, Y ); - DES_ROUND( Y, X ); DES_ROUND( X, Y ); - DES_ROUND( Y, X ); DES_ROUND( X, Y ); - DES_ROUND( Y, X ); DES_ROUND( X, Y ); - DES_ROUND( Y, X ); DES_ROUND( X, Y ); - DES_ROUND( Y, X ); DES_ROUND( X, Y ); - DES_ROUND( Y, X ); DES_ROUND( X, Y ); - - DES_FP( Y, X ); - - PUT_UINT32( Y, output, 0 ); - PUT_UINT32( X, output, 4 ); -} - -void des_encrypt( des_context *ctx, uint8_t input[8], uint8_t output[8] ) -{ - des_crypt( ctx->esk, input, output ); -} - -void des_decrypt( des_context *ctx, uint8_t input[8], uint8_t output[8] ) -{ - des_crypt( ctx->dsk, input, output ); -} - -/* Triple-DES key schedule */ - -int des3_set_2keys( des3_context *ctx, const uint8_t key1[8], const uint8_t key2[8] ) -{ - int i; - - des_main_ks( ctx->esk , key1 ); - des_main_ks( ctx->dsk + 32, key2 ); - - for( i = 0; i < 32; i += 2 ) - { - ctx->dsk[i ] = ctx->esk[30 - i]; - ctx->dsk[i + 1] = ctx->esk[31 - i]; - - ctx->esk[i + 32] = ctx->dsk[62 - i]; - ctx->esk[i + 33] = ctx->dsk[63 - i]; - - ctx->esk[i + 64] = ctx->esk[ i]; - ctx->esk[i + 65] = ctx->esk[ 1 + i]; - - ctx->dsk[i + 64] = ctx->dsk[ i]; - ctx->dsk[i + 65] = ctx->dsk[ 1 + i]; - } - - return( 0 ); -} -#endif - -int des3_set_3keys( des3_context *ctx, const uint8_t key1[8], const uint8_t key2[8], - const uint8_t key3[8] ) -{ - int i; - - des_main_ks( ctx->esk , key1 ); - des_main_ks( ctx->dsk + 32, key2 ); - des_main_ks( ctx->esk + 64, key3 ); - - for( i = 0; i < 32; i += 2 ) - { - ctx->dsk[i ] = ctx->esk[94 - i]; - ctx->dsk[i + 1] = ctx->esk[95 - i]; - - ctx->esk[i + 32] = ctx->dsk[62 - i]; - ctx->esk[i + 33] = ctx->dsk[63 - i]; - - ctx->dsk[i + 64] = ctx->esk[30 - i]; - ctx->dsk[i + 65] = ctx->esk[31 - i]; - } - - return( 0 ); -} - -/* Triple-DES 64-bit block encryption/decryption */ - -void des3_crypt( uint32_t SK[96], uint8_t input[8], uint8_t output[8] ) -{ - uint32_t X, Y, T; - - GET_UINT32( X, input, 0 ); - GET_UINT32( Y, input, 4 ); - - DES_IP( X, Y ); - - DES_ROUND( Y, X ); DES_ROUND( X, Y ); - DES_ROUND( Y, X ); DES_ROUND( X, Y ); - DES_ROUND( Y, X ); DES_ROUND( X, Y ); - DES_ROUND( Y, X ); DES_ROUND( X, Y ); - DES_ROUND( Y, X ); DES_ROUND( X, Y ); - DES_ROUND( Y, X ); DES_ROUND( X, Y ); - DES_ROUND( Y, X ); DES_ROUND( X, Y ); - DES_ROUND( Y, X ); DES_ROUND( X, Y ); - - DES_ROUND( X, Y ); DES_ROUND( Y, X ); - DES_ROUND( X, Y ); DES_ROUND( Y, X ); - DES_ROUND( X, Y ); DES_ROUND( Y, X ); - DES_ROUND( X, Y ); DES_ROUND( Y, X ); - DES_ROUND( X, Y ); DES_ROUND( Y, X ); - DES_ROUND( X, Y ); DES_ROUND( Y, X ); - DES_ROUND( X, Y ); DES_ROUND( Y, X ); - DES_ROUND( X, Y ); DES_ROUND( Y, X ); - - DES_ROUND( Y, X ); DES_ROUND( X, Y ); - DES_ROUND( Y, X ); DES_ROUND( X, Y ); - DES_ROUND( Y, X ); DES_ROUND( X, Y ); - DES_ROUND( Y, X ); DES_ROUND( X, Y ); - DES_ROUND( Y, X ); DES_ROUND( X, Y ); - DES_ROUND( Y, X ); DES_ROUND( X, Y ); - DES_ROUND( Y, X ); DES_ROUND( X, Y ); - DES_ROUND( Y, X ); DES_ROUND( X, Y ); - - DES_FP( Y, X ); - - PUT_UINT32( Y, output, 0 ); - PUT_UINT32( X, output, 4 ); -} - -void des3_encrypt( des3_context *ctx, uint8_t input[8], uint8_t output[8] ) -{ - des3_crypt( ctx->esk, input, output ); -} - -void des3_decrypt( des3_context *ctx, uint8_t input[8], uint8_t output[8] ) -{ - des3_crypt( ctx->dsk, input, output ); -} - -size_t ssl_des3_encrypt( const unsigned char *key, size_t key_len, const unsigned char *input, - size_t input_len, const unsigned char *iv, unsigned char **res ) -{ - des3_context ctx3; - size_t off; - uint8_t buf[8]; - - /* Keep it simple, for as long as this is just used for MSN auth anyway. */ - if( key_len != 24 || ( input_len % 8 ) != 0 ) - return 0; - - *res = g_malloc( input_len ); - des3_set_3keys( &ctx3, key, key + 8, key + 16 ); - - /* This loop does CBC 3DES. */ - memcpy( buf, iv, 8 ); - for( off = 0; off < input_len; off += 8 ) - { - int i; - - for( i = 0; i < 8; i ++ ) - buf[i] ^= input[off+i]; - des3_encrypt( &ctx3, buf, buf ); - memcpy( *res + off, buf, 8 ); - } - - return input_len; -} - -#ifdef TEST - -#include <string.h> -#include <stdio.h> - -/* - * Triple-DES Monte Carlo Test: ECB mode - * source: NIST - tripledes-vectors.zip - */ - -static const unsigned char DES3_keys[3][8] = -{ - { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, - { 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01 }, - { 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23 } -}; - -static const unsigned char DES3_init[8] = -{ - 0x4E, 0x6F, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74 -}; - -static const unsigned char DES3_enc_test[3][8] = -{ - { 0x6A, 0x2A, 0x19, 0xF4, 0x1E, 0xCA, 0x85, 0x4B }, - { 0x03, 0xE6, 0x9F, 0x5B, 0xFA, 0x58, 0xEB, 0x42 }, - { 0xDD, 0x17, 0xE8, 0xB8, 0xB4, 0x37, 0xD2, 0x32 } -}; - -static const unsigned char DES3_dec_test[3][8] = -{ - { 0xCD, 0xD6, 0x4F, 0x2F, 0x94, 0x27, 0xC1, 0x5D }, - { 0x69, 0x96, 0xC8, 0xFA, 0x47, 0xA2, 0xAB, 0xEB }, - { 0x83, 0x25, 0x39, 0x76, 0x44, 0x09, 0x1A, 0x0A } -}; - -int main( void ) -{ - int m, n, i; - des_context ctx; - des3_context ctx3; - unsigned char buf[8]; - - for( m = 0; m < 2; m++ ) - { - printf( "\n Triple-DES Monte Carlo Test (ECB mode) - " ); - - if( m == 0 ) printf( "encryption\n\n" ); - if( m == 1 ) printf( "decryption\n\n" ); - - for( n = 0; n < 3; n++ ) - { - printf( " Test %d, key size = %3d bits: ", - n + 1, 64 + n * 64 ); - - fflush( stdout ); - - memcpy( buf, DES3_init, 8 ); - - switch( n ) - { - case 0: - des_set_key( &ctx, DES3_keys[0] ); - break; - - case 1: - des3_set_2keys( &ctx3, DES3_keys[0], - DES3_keys[1] ); - break; - - case 2: - des3_set_3keys( &ctx3, DES3_keys[0], - DES3_keys[1], - DES3_keys[2] ); - break; - } - - for( i = 0; i < 10000; i++ ) - { - if( n == 0 ) - { - if( m == 0 ) des_encrypt( &ctx, buf, buf ); - if( m == 1 ) des_decrypt( &ctx, buf, buf ); - } - else - { - if( m == 0 ) des3_encrypt( &ctx3, buf, buf ); - if( m == 1 ) des3_decrypt( &ctx3, buf, buf ); - } - } - - if( ( m == 0 && memcmp( buf, DES3_enc_test[n], 8 ) ) || - ( m == 1 && memcmp( buf, DES3_dec_test[n], 8 ) ) ) - { - printf( "failed!\n" ); - return( 1 ); - } - - printf( "passed.\n" ); - } - } - - printf( "\n" ); - - return( 0 ); -} - -#endif diff --git a/lib/des.h b/lib/des.h deleted file mode 100644 index 92fbfd22..00000000 --- a/lib/des.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * FIPS-46-3 compliant 3DES implementation - * - * Copyright (C) 2001-2003 Christophe Devine - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _DES_H -#define _DES_H - -#include <stdint.h> - -typedef struct -{ - uint32_t esk[32]; /* DES encryption subkeys */ - uint32_t dsk[32]; /* DES decryption subkeys */ -} -des_context; - -typedef struct -{ - uint32_t esk[96]; /* Triple-DES encryption subkeys */ - uint32_t dsk[96]; /* Triple-DES decryption subkeys */ -} -des3_context; - -int des_set_key( des_context *ctx, uint8_t key[8] ); -void des_encrypt( des_context *ctx, uint8_t input[8], uint8_t output[8] ); -void des_decrypt( des_context *ctx, uint8_t input[8], uint8_t output[8] ); - -int des3_set_2keys( des3_context *ctx, const uint8_t key1[8], const uint8_t key2[8] ); -int des3_set_3keys( des3_context *ctx, const uint8_t key1[8], const uint8_t key2[8], - const uint8_t key3[8] ); - -void des3_encrypt( des3_context *ctx, uint8_t input[8], uint8_t output[8] ); -void des3_decrypt( des3_context *ctx, uint8_t input[8], uint8_t output[8] ); - -#endif /* des.h */ diff --git a/lib/http_client.c b/lib/http_client.c index 98a99f7c..b384e1f0 100644 --- a/lib/http_client.c +++ b/lib/http_client.c @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2011 Wilmer van der Gaast and others * + * Copyright 2002-2012 Wilmer van der Gaast and others * \********************************************************************/ /* HTTP(S) module */ @@ -72,7 +72,7 @@ struct http_request *http_dorequest( char *host, int port, int ssl, char *reques if( getenv( "BITLBEE_DEBUG" ) ) printf( "About to send HTTP request:\n%s\n", req->request ); - return( req ); + return req; } struct http_request *http_dorequest_url( char *url_string, http_input_function func, gpointer data ) @@ -192,12 +192,14 @@ static gboolean http_ssl_connected( gpointer data, int returncode, void *source, return http_connected( data, req->fd, cond ); } +static gboolean http_handle_headers( struct http_request *req ); + static gboolean http_incoming_data( gpointer data, int source, b_input_condition cond ) { struct http_request *req = data; - int evil_server = 0; - char buffer[2048]; - char *end1, *end2; + char buffer[4096]; + char *s; + size_t content_length; int st; if( req->inpa > 0 ) @@ -216,12 +218,12 @@ static gboolean http_incoming_data( gpointer data, int source, b_input_condition servers that LOVE to send invalid TLS packets that abort connections! \o/ */ - goto got_reply; + goto eof; } } else if( st == 0 ) { - goto got_reply; + goto eof; } } else @@ -237,28 +239,70 @@ static gboolean http_incoming_data( gpointer data, int source, b_input_condition } else if( st == 0 ) { - goto got_reply; + goto eof; } } - if( st > 0 ) + if( st > 0 && !req->sbuf ) { req->reply_headers = g_realloc( req->reply_headers, req->bytes_read + st + 1 ); memcpy( req->reply_headers + req->bytes_read, buffer, st ); req->bytes_read += st; + + st = 0; + } + + if( st >= 0 && ( req->flags & HTTPC_STREAMING ) ) + { + if( !req->reply_body && + ( strstr( req->reply_headers, "\r\n\r\n" ) || + strstr( req->reply_headers, "\n\n" ) ) ) + { + size_t hlen; + + /* We've now received all headers, so process them once + before we start feeding back data. */ + if( !http_handle_headers( req ) ) + return FALSE; + + hlen = req->reply_body - req->reply_headers; + + req->sblen = req->bytes_read - hlen; + req->sbuf = g_memdup( req->reply_body, req->sblen + 1 ); + req->reply_headers = g_realloc( req->reply_headers, hlen + 1 ); + + req->reply_body = req->sbuf; + } + + if( st > 0 ) + { + int pos = req->reply_body - req->sbuf; + req->sbuf = g_realloc( req->sbuf, req->sblen + st + 1 ); + memcpy( req->sbuf + req->sblen, buffer, st ); + req->bytes_read += st; + req->sblen += st; + req->sbuf[req->sblen] = '\0'; + req->reply_body = req->sbuf + pos; + req->body_size = req->sblen - pos; + } + + if( req->reply_body ) + req->func( req ); } + if( ssl_pending( req->ssl ) ) + return http_incoming_data( data, source, cond ); + /* There will be more! */ req->inpa = b_input_add( req->fd, req->ssl ? ssl_getdirection( req->ssl ) : B_EV_IO_READ, http_incoming_data, req ); - if( ssl_pending( req->ssl ) ) - return http_incoming_data( data, source, cond ); - else - return FALSE; + return FALSE; -got_reply: +eof: + req->flags |= HTTPC_EOF; + /* Maybe if the webserver is overloaded, or when there's bad SSL support... */ if( req->bytes_read == 0 ) @@ -267,8 +311,50 @@ got_reply: goto cleanup; } + if( !( req->flags & HTTPC_STREAMING ) ) + { + /* Returns FALSE if we were redirected, in which case we should abort + and not run any callback yet. */ + if( !http_handle_headers( req ) ) + return FALSE; + } + +cleanup: + if( req->ssl ) + ssl_disconnect( req->ssl ); + else + closesocket( req->fd ); + + if( ( s = get_rfc822_header( req->reply_headers, "Content-Length", 0 ) ) && + sscanf( s, "%zd", &content_length ) == 1 ) + { + if( content_length < req->body_size ) + { + req->status_code = -1; + g_free( req->status_string ); + req->status_string = g_strdup( "Response truncated" ); + } + } + g_free( s ); + + if( getenv( "BITLBEE_DEBUG" ) && req ) + printf( "Finishing HTTP request with status: %s\n", + req->status_string ? req->status_string : "NULL" ); + + req->func( req ); + http_free( req ); + return FALSE; +} + +/* Splits headers and body. Checks result code, in case of 300s it'll handle + redirects. If this returns FALSE, don't call any callbacks! */ +static gboolean http_handle_headers( struct http_request *req ) +{ + char *end1, *end2; + int evil_server = 0; + /* Zero termination is very convenient. */ - req->reply_headers[req->bytes_read] = 0; + req->reply_headers[req->bytes_read] = '\0'; /* Find the separation between headers and body, and keep stupid webservers in mind. */ @@ -287,7 +373,7 @@ got_reply: else { req->status_string = g_strdup( "Malformed HTTP reply" ); - goto cleanup; + return TRUE; } *end1 = 0; @@ -304,7 +390,7 @@ got_reply: if( ( end1 = strchr( req->reply_headers, ' ' ) ) != NULL ) { - if( sscanf( end1 + 1, "%d", &req->status_code ) != 1 ) + if( sscanf( end1 + 1, "%hd", &req->status_code ) != 1 ) { req->status_string = g_strdup( "Can't parse status code" ); req->status_code = -1; @@ -347,7 +433,7 @@ got_reply: if( loc == NULL ) /* We can't handle this redirect... */ { req->status_string = g_strdup( "Can't locate Location: header" ); - goto cleanup; + return TRUE; } loc += 11; @@ -367,7 +453,7 @@ got_reply: req->status_string = g_strdup( "Can't handle recursive redirects" ); - goto cleanup; + return TRUE; } else { @@ -378,7 +464,7 @@ got_reply: s = strstr( loc, "\r\n" ); if( s == NULL ) - goto cleanup; + return TRUE; url = g_new0( url_t, 1 ); *s = 0; @@ -387,7 +473,7 @@ got_reply: { req->status_string = g_strdup( "Malformed redirect URL" ); g_free( url ); - goto cleanup; + return TRUE; } /* Find all headers and, if necessary, the POST request contents. @@ -399,7 +485,7 @@ got_reply: { req->status_string = g_strdup( "Error while rebuilding request string" ); g_free( url ); - goto cleanup; + return TRUE; } /* More or less HTTP/1.0 compliant, from my reading of RFC 2616. @@ -465,7 +551,7 @@ got_reply: { req->status_string = g_strdup( "Connection problem during redirect" ); g_free( new_request ); - goto cleanup; + return TRUE; } g_free( req->request ); @@ -478,23 +564,40 @@ got_reply: return FALSE; } - /* Assume that a closed connection means we're finished, this indeed - breaks with keep-alive connections and faulty connections. */ - req->finished = 1; + return TRUE; +} + +void http_flush_bytes( struct http_request *req, size_t len ) +{ + if( len <= 0 || len > req->body_size || !( req->flags & HTTPC_STREAMING ) ) + return; + + req->reply_body += len; + req->body_size -= len; + + if( req->reply_body - req->sbuf >= 512 ) + { + char *new = g_memdup( req->reply_body, req->body_size + 1 ); + g_free( req->sbuf ); + req->reply_body = req->sbuf = new; + req->sblen = req->body_size; + } +} -cleanup: +void http_close( struct http_request *req ) +{ + if( !req ) + return; + + if( req->inpa > 0 ) + b_event_remove( req->inpa ); + if( req->ssl ) ssl_disconnect( req->ssl ); else closesocket( req->fd ); - if( getenv( "BITLBEE_DEBUG" ) && req ) - printf( "Finishing HTTP request with status: %s\n", - req->status_string ? req->status_string : "NULL" ); - - req->func( req ); http_free( req ); - return FALSE; } static void http_free( struct http_request *req ) @@ -502,6 +605,6 @@ static void http_free( struct http_request *req ) g_free( req->request ); g_free( req->reply_headers ); g_free( req->status_string ); + g_free( req->sbuf ); g_free( req ); } - diff --git a/lib/http_client.h b/lib/http_client.h index 27c484ff..ca427118 100644 --- a/lib/http_client.h +++ b/lib/http_client.h @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2005 Wilmer van der Gaast and others * + * Copyright 2002-2012 Wilmer van der Gaast and others * \********************************************************************/ /* HTTP(S) module */ @@ -25,23 +25,26 @@ /* http_client allows you to talk (asynchronously, again) to HTTP servers. In the "background" it will send the whole query and wait for a complete - response to come back. Right now it's only used by the MSN Passport - authentication code, but it might be useful for other things too (for - example the AIM usericon patch uses this so icons can be stored on - webservers instead of the local filesystem). + response to come back. Initially written for MS Passport authentication, + but used for many other things now like OAuth and Twitter. - Didn't test this too much, but it seems to work well. Just don't look - at the code that handles HTTP 30x redirects. ;-) The function is - probably not very useful for downloading lots of data since it keeps - everything in a memory buffer until the download is completed (and - can't pass any data or whatever before then). It's very useful for - doing quick requests without blocking the whole program, though. */ + It's very useful for doing quick requests without blocking the whole + program. Unfortunately it doesn't support fancy stuff like HTTP keep- + alives. */ #include <glib.h> #include "ssl_client.h" struct http_request; +typedef enum http_client_flags +{ + HTTPC_STREAMING = 1, + HTTPC_EOF = 2, + + /* Let's reserve 0x1000000+ for lib users. */ +} http_client_flags_t; + /* Your callback function should look like this: */ typedef void (*http_input_function)( struct http_request * ); @@ -52,28 +55,31 @@ struct http_request { char *request; /* The request to send to the server. */ int request_length; /* Its size. */ - int status_code; /* The numeric HTTP status code. (Or -1 + short status_code; /* The numeric HTTP status code. (Or -1 if something really went wrong) */ char *status_string; /* The error text. */ char *reply_headers; char *reply_body; int body_size; /* The number of bytes in reply_body. */ - int finished; /* Set to non-0 if the request was completed - successfully. */ - int redir_ttl; /* You can set it to 0 if you don't want + short redir_ttl; /* You can set it to 0 if you don't want http_client to follow them. */ + http_client_flags_t flags; + http_input_function func; gpointer data; /* Please don't touch the things down here, you shouldn't need them. */ - void *ssl; int fd; int inpa; int bytes_written; int bytes_read; + + /* Used in streaming mode. Caller should read from reply_body. */ + char *sbuf; + size_t sblen; }; /* The _url variant is probably more useful than the raw version. The raw @@ -82,3 +88,7 @@ struct http_request are also supported (using ssl_client). */ struct http_request *http_dorequest( char *host, int port, int ssl, char *request, http_input_function func, gpointer data ); struct http_request *http_dorequest_url( char *url_string, http_input_function func, gpointer data ); + +/* For streaming connections only; flushes len bytes at the start of the buffer. */ +void http_flush_bytes( struct http_request *req, size_t len ); +void http_close( struct http_request *req ); diff --git a/lib/json.c b/lib/json.c new file mode 100644 index 00000000..fb973001 --- /dev/null +++ b/lib/json.c @@ -0,0 +1,743 @@ + +/* vim: set et ts=3 sw=3 ft=c: + * + * Copyright (C) 2012 James McLaughlin et al. All rights reserved. + * https://github.com/udp/json-parser + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + +#include "json.h" + +#ifdef _MSC_VER + #ifndef _CRT_SECURE_NO_WARNINGS + #define _CRT_SECURE_NO_WARNINGS + #endif +#endif + +#ifdef __cplusplus + const struct _json_value json_value_none; /* zero-d by ctor */ +#else + const struct _json_value json_value_none = { 0 }; +#endif + +#include <glib.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <ctype.h> + +typedef unsigned short json_uchar; + +static unsigned char hex_value (json_char c) +{ + if (c >= 'A' && c <= 'F') + return (c - 'A') + 10; + + if (c >= 'a' && c <= 'f') + return (c - 'a') + 10; + + if (c >= '0' && c <= '9') + return c - '0'; + + return 0xFF; +} + +typedef struct +{ + json_settings settings; + int first_pass; + + unsigned long used_memory; + + unsigned int uint_max; + unsigned long ulong_max; + +} json_state; + +static void * json_alloc (json_state * state, unsigned long size, int zero) +{ + void * mem; + + if ((state->ulong_max - state->used_memory) < size) + return 0; + + if (state->settings.max_memory + && (state->used_memory += size) > state->settings.max_memory) + { + return 0; + } + + if (! (mem = zero ? calloc (size, 1) : malloc (size))) + return 0; + + return mem; +} + +static int new_value + (json_state * state, json_value ** top, json_value ** root, json_value ** alloc, json_type type) +{ + json_value * value; + int values_size; + + if (!state->first_pass) + { + value = *top = *alloc; + *alloc = (*alloc)->_reserved.next_alloc; + + if (!*root) + *root = value; + + switch (value->type) + { + case json_array: + + if (! (value->u.array.values = (json_value **) json_alloc + (state, value->u.array.length * sizeof (json_value *), 0)) ) + { + return 0; + } + + break; + + case json_object: + + values_size = sizeof (*value->u.object.values) * value->u.object.length; + + if (! ((*(void **) &value->u.object.values) = json_alloc + (state, values_size + ((unsigned long) value->u.object.values), 0)) ) + { + return 0; + } + + value->_reserved.object_mem = (*(char **) &value->u.object.values) + values_size; + + break; + + case json_string: + + if (! (value->u.string.ptr = (json_char *) json_alloc + (state, (value->u.string.length + 1) * sizeof (json_char), 0)) ) + { + return 0; + } + + break; + + default: + break; + }; + + value->u.array.length = 0; + + return 1; + } + + value = (json_value *) json_alloc (state, sizeof (json_value), 1); + + if (!value) + return 0; + + if (!*root) + *root = value; + + value->type = type; + value->parent = *top; + + if (*alloc) + (*alloc)->_reserved.next_alloc = value; + + *alloc = *top = value; + + return 1; +} + +#define e_off \ + ((int) (i - cur_line_begin)) + +#define whitespace \ + case '\n': ++ cur_line; cur_line_begin = i; \ + case ' ': case '\t': case '\r' + +#define string_add(b) \ + do { if (!state.first_pass) string [string_length] = b; ++ string_length; } while (0); + +const static int + flag_next = 1, flag_reproc = 2, flag_need_comma = 4, flag_seek_value = 8, flag_exponent = 16, + flag_got_exponent_sign = 32, flag_escaped = 64, flag_string = 128, flag_need_colon = 256, + flag_done = 512; + +json_value * json_parse_ex (json_settings * settings, const json_char * json, char * error_buf) +{ + json_char error [128]; + unsigned int cur_line; + const json_char * cur_line_begin, * i; + json_value * top, * root, * alloc = 0; + json_state state; + int flags; + + error[0] = '\0'; + + memset (&state, 0, sizeof (json_state)); + memcpy (&state.settings, settings, sizeof (json_settings)); + + memset (&state.uint_max, 0xFF, sizeof (state.uint_max)); + memset (&state.ulong_max, 0xFF, sizeof (state.ulong_max)); + + state.uint_max -= 8; /* limit of how much can be added before next check */ + state.ulong_max -= 8; + + for (state.first_pass = 1; state.first_pass >= 0; -- state.first_pass) + { + json_uchar uchar; + unsigned char uc_b1, uc_b2, uc_b3, uc_b4; + json_char * string = 0; + unsigned int string_length = 0; + + top = root = 0; + flags = flag_seek_value; + + cur_line = 1; + cur_line_begin = json; + + for (i = json ;; ++ i) + { + json_char b = *i; + + if (flags & flag_done) + { + if (!b) + break; + + switch (b) + { + whitespace: + continue; + + default: + sprintf (error, "%d:%d: Trailing garbage: `%c`", cur_line, e_off, b); + goto e_failed; + }; + } + + if (flags & flag_string) + { + if (!b) + { sprintf (error, "Unexpected EOF in string (at %d:%d)", cur_line, e_off); + goto e_failed; + } + + if (string_length > state.uint_max) + goto e_overflow; + + if (flags & flag_escaped) + { + flags &= ~ flag_escaped; + + switch (b) + { + case 'b': string_add ('\b'); break; + case 'f': string_add ('\f'); break; + case 'n': string_add ('\n'); break; + case 'r': string_add ('\r'); break; + case 't': string_add ('\t'); break; + case 'u': + + if ((uc_b1 = hex_value (*++ i)) == 0xFF || (uc_b2 = hex_value (*++ i)) == 0xFF + || (uc_b3 = hex_value (*++ i)) == 0xFF || (uc_b4 = hex_value (*++ i)) == 0xFF) + { + sprintf (error, "Invalid character value `%c` (at %d:%d)", b, cur_line, e_off); + goto e_failed; + } + + uc_b1 = uc_b1 * 16 + uc_b2; + uc_b2 = uc_b3 * 16 + uc_b4; + + uchar = ((json_char) uc_b1) * 256 + uc_b2; + + if (sizeof (json_char) >= sizeof (json_uchar) || (uc_b1 == 0 && uc_b2 <= 0x7F)) + { + string_add ((json_char) uchar); + break; + } + + if (uchar <= 0x7FF) + { + if (state.first_pass) + string_length += 2; + else + { string [string_length ++] = 0xC0 | ((uc_b2 & 0xC0) >> 6) | ((uc_b1 & 0x7) << 2); + string [string_length ++] = 0x80 | (uc_b2 & 0x3F); + } + + break; + } + + if (state.first_pass) + string_length += 3; + else + { string [string_length ++] = 0xE0 | ((uc_b1 & 0xF0) >> 4); + string [string_length ++] = 0x80 | ((uc_b1 & 0xF) << 2) | ((uc_b2 & 0xC0) >> 6); + string [string_length ++] = 0x80 | (uc_b2 & 0x3F); + } + + break; + + default: + string_add (b); + }; + + continue; + } + + if (b == '\\') + { + flags |= flag_escaped; + continue; + } + + if (b == '"') + { + if (!state.first_pass) + string [string_length] = 0; + + flags &= ~ flag_string; + string = 0; + + switch (top->type) + { + case json_string: + + top->u.string.length = string_length; + flags |= flag_next; + + break; + + case json_object: + + if (state.first_pass) + (*(json_char **) &top->u.object.values) += string_length + 1; + else + { + top->u.object.values [top->u.object.length].name + = (json_char *) top->_reserved.object_mem; + + (*(json_char **) &top->_reserved.object_mem) += string_length + 1; + } + + flags |= flag_seek_value | flag_need_colon; + continue; + + default: + break; + }; + } + else + { + string_add (b); + continue; + } + } + + if (flags & flag_seek_value) + { + switch (b) + { + whitespace: + continue; + + case ']': + + if (top->type == json_array) + flags = (flags & ~ (flag_need_comma | flag_seek_value)) | flag_next; + else if (!state.settings.settings & json_relaxed_commas) + { sprintf (error, "%d:%d: Unexpected ]", cur_line, e_off); + goto e_failed; + } + + break; + + default: + + if (flags & flag_need_comma) + { + if (b == ',') + { flags &= ~ flag_need_comma; + continue; + } + else + { sprintf (error, "%d:%d: Expected , before %c", cur_line, e_off, b); + goto e_failed; + } + } + + if (flags & flag_need_colon) + { + if (b == ':') + { flags &= ~ flag_need_colon; + continue; + } + else + { sprintf (error, "%d:%d: Expected : before %c", cur_line, e_off, b); + goto e_failed; + } + } + + flags &= ~ flag_seek_value; + + switch (b) + { + case '{': + + if (!new_value (&state, &top, &root, &alloc, json_object)) + goto e_alloc_failure; + + continue; + + case '[': + + if (!new_value (&state, &top, &root, &alloc, json_array)) + goto e_alloc_failure; + + flags |= flag_seek_value; + continue; + + case '"': + + if (!new_value (&state, &top, &root, &alloc, json_string)) + goto e_alloc_failure; + + flags |= flag_string; + + string = top->u.string.ptr; + string_length = 0; + + continue; + + case 't': + + if (*(++ i) != 'r' || *(++ i) != 'u' || *(++ i) != 'e') + goto e_unknown_value; + + if (!new_value (&state, &top, &root, &alloc, json_boolean)) + goto e_alloc_failure; + + top->u.boolean = 1; + + flags |= flag_next; + break; + + case 'f': + + if (*(++ i) != 'a' || *(++ i) != 'l' || *(++ i) != 's' || *(++ i) != 'e') + goto e_unknown_value; + + if (!new_value (&state, &top, &root, &alloc, json_boolean)) + goto e_alloc_failure; + + flags |= flag_next; + break; + + case 'n': + + if (*(++ i) != 'u' || *(++ i) != 'l' || *(++ i) != 'l') + goto e_unknown_value; + + if (!new_value (&state, &top, &root, &alloc, json_null)) + goto e_alloc_failure; + + flags |= flag_next; + break; + + default: + + if (isdigit (b) || b == '-') + { + if (!new_value (&state, &top, &root, &alloc, json_integer)) + goto e_alloc_failure; + + flags &= ~ (flag_exponent | flag_got_exponent_sign); + + if (state.first_pass) + continue; + + if (top->type == json_double) + top->u.dbl = g_ascii_strtod (i, (json_char **) &i); + else + top->u.integer = g_ascii_strtoll (i, (json_char **) &i, 10); + + flags |= flag_next | flag_reproc; + } + else + { sprintf (error, "%d:%d: Unexpected %c when seeking value", cur_line, e_off, b); + goto e_failed; + } + }; + }; + } + else + { + switch (top->type) + { + case json_object: + + switch (b) + { + whitespace: + continue; + + case '"': + + if (flags & flag_need_comma && (!state.settings.settings & json_relaxed_commas)) + { + sprintf (error, "%d:%d: Expected , before \"", cur_line, e_off); + goto e_failed; + } + + flags |= flag_string; + + string = (json_char *) top->_reserved.object_mem; + string_length = 0; + + break; + + case '}': + + flags = (flags & ~ flag_need_comma) | flag_next; + break; + + case ',': + + if (flags & flag_need_comma) + { + flags &= ~ flag_need_comma; + break; + } + + default: + + sprintf (error, "%d:%d: Unexpected `%c` in object", cur_line, e_off, b); + goto e_failed; + }; + + break; + + case json_integer: + case json_double: + + if (isdigit (b)) + continue; + + if (b == 'e' || b == 'E') + { + if (!(flags & flag_exponent)) + { + flags |= flag_exponent; + top->type = json_double; + + continue; + } + } + else if (b == '+' || b == '-') + { + if (flags & flag_exponent && !(flags & flag_got_exponent_sign)) + { + flags |= flag_got_exponent_sign; + continue; + } + } + else if (b == '.' && top->type == json_integer) + { + top->type = json_double; + continue; + } + + flags |= flag_next | flag_reproc; + break; + + default: + break; + }; + } + + if (flags & flag_reproc) + { + flags &= ~ flag_reproc; + -- i; + } + + if (flags & flag_next) + { + flags = (flags & ~ flag_next) | flag_need_comma; + + if (!top->parent) + { + /* root value done */ + + flags |= flag_done; + continue; + } + + if (top->parent->type == json_array) + flags |= flag_seek_value; + + if (!state.first_pass) + { + json_value * parent = top->parent; + + switch (parent->type) + { + case json_object: + + parent->u.object.values + [parent->u.object.length].value = top; + + break; + + case json_array: + + parent->u.array.values + [parent->u.array.length] = top; + + break; + + default: + break; + }; + } + + if ( (++ top->parent->u.array.length) > state.uint_max) + goto e_overflow; + + top = top->parent; + + continue; + } + } + + alloc = root; + } + + return root; + +e_unknown_value: + + sprintf (error, "%d:%d: Unknown value", cur_line, e_off); + goto e_failed; + +e_alloc_failure: + + strcpy (error, "Memory allocation failure"); + goto e_failed; + +e_overflow: + + sprintf (error, "%d:%d: Too long (caught overflow)", cur_line, e_off); + goto e_failed; + +e_failed: + + if (error_buf) + { + if (*error) + strcpy (error_buf, error); + else + strcpy (error_buf, "Unknown error"); + } + + if (state.first_pass) + alloc = root; + + while (alloc) + { + top = alloc->_reserved.next_alloc; + free (alloc); + alloc = top; + } + + if (!state.first_pass) + json_value_free (root); + + return 0; +} + +json_value * json_parse (const json_char * json) +{ + json_settings settings; + memset (&settings, 0, sizeof (json_settings)); + + return json_parse_ex (&settings, json, 0); +} + +void json_value_free (json_value * value) +{ + json_value * cur_value; + + if (!value) + return; + + value->parent = 0; + + while (value) + { + switch (value->type) + { + case json_array: + + if (!value->u.array.length) + { + free (value->u.array.values); + break; + } + + value = value->u.array.values [-- value->u.array.length]; + continue; + + case json_object: + + if (!value->u.object.length) + { + free (value->u.object.values); + break; + } + + value = value->u.object.values [-- value->u.object.length].value; + continue; + + case json_string: + + free (value->u.string.ptr); + break; + + default: + break; + }; + + cur_value = value; + value = value->parent; + free (cur_value); + } +} + + diff --git a/lib/json.h b/lib/json.h new file mode 100644 index 00000000..3800565a --- /dev/null +++ b/lib/json.h @@ -0,0 +1,192 @@ + +/* vim: set et ts=3 sw=3 ft=c: + * + * Copyright (C) 2012 James McLaughlin et al. All rights reserved. + * https://github.com/udp/json-parser + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + +#ifndef _JSON_H +#define _JSON_H + +#ifndef json_char + #define json_char char +#endif + +#ifdef __cplusplus + + #include <string.h> + + extern "C" + { + +#endif + +typedef struct +{ + unsigned long max_memory; + int settings; + +} json_settings; + +#define json_relaxed_commas 1 + +typedef enum +{ + json_none, + json_object, + json_array, + json_integer, + json_double, + json_string, + json_boolean, + json_null + +} json_type; + +extern const struct _json_value json_value_none; + +typedef struct _json_value +{ + struct _json_value * parent; + + json_type type; + + union + { + int boolean; + long long integer; + double dbl; + + struct + { + unsigned int length; + json_char * ptr; /* null terminated */ + + } string; + + struct + { + unsigned int length; + + struct + { + json_char * name; + struct _json_value * value; + + } * values; + + } object; + + struct + { + unsigned int length; + struct _json_value ** values; + + } array; + + } u; + + union + { + struct _json_value * next_alloc; + void * object_mem; + + } _reserved; + + + /* Some C++ operator sugar */ + + #ifdef __cplusplus + + public: + + inline _json_value () + { memset (this, 0, sizeof (_json_value)); + } + + inline const struct _json_value &operator [] (int index) const + { + if (type != json_array || index < 0 + || ((unsigned int) index) >= u.array.length) + { + return json_value_none; + } + + return *u.array.values [index]; + } + + inline const struct _json_value &operator [] (const char * index) const + { + if (type != json_object) + return json_value_none; + + for (unsigned int i = 0; i < u.object.length; ++ i) + if (!strcmp (u.object.values [i].name, index)) + return *u.object.values [i].value; + + return json_value_none; + } + + inline operator const char * () const + { + switch (type) + { + case json_string: + return u.string.ptr; + + default: + return ""; + }; + } + + inline operator long () const + { return u.integer; + } + + inline operator bool () const + { return u.boolean != 0; + } + + #endif + +} json_value; + +json_value * json_parse + (const json_char * json); + +json_value * json_parse_ex + (json_settings * settings, const json_char * json, char * error); + +void json_value_free (json_value *); + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif + + diff --git a/lib/json_util.c b/lib/json_util.c new file mode 100644 index 00000000..2f1bc7e8 --- /dev/null +++ b/lib/json_util.c @@ -0,0 +1,62 @@ +/***************************************************************************\ +* * +* BitlBee - An IRC to IM gateway * +* Helper functions for json.c * +* * +* Copyright 2012-2012 Wilmer van der Gaast <wilmer@gaast.net> * +* * +* This library is free software; you can redistribute it and/or * +* modify it under the terms of the GNU Lesser General Public * +* License as published by the Free Software Foundation, version * +* 2.1. * +* * +* This library is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +* Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * +* * +****************************************************************************/ + +#include <stdlib.h> +#include <string.h> +#include <glib.h> + +#include "json_util.h" + +json_value *json_o_get( const json_value *obj, const json_char *name ) +{ + int i; + + if( !obj || obj->type != json_object ) + return NULL; + + for( i = 0; i < obj->u.object.length; ++ i) + if( strcmp( obj->u.object.values[i].name, name ) == 0 ) + return obj->u.object.values[i].value; + + return NULL; +} + +const char *json_o_str( const json_value *obj, const json_char *name ) +{ + json_value *ret = json_o_get( obj, name ); + + if( ret && ret->type == json_string ) + return ret->u.string.ptr; + else + return NULL; +} + +char *json_o_strdup( const json_value *obj, const json_char *name ) +{ + json_value *ret = json_o_get( obj, name ); + + if( ret && ret->type == json_string && ret->u.string.ptr ) + return g_memdup( ret->u.string.ptr, ret->u.string.length + 1 ); + else + return NULL; +} diff --git a/lib/json_util.h b/lib/json_util.h new file mode 100644 index 00000000..c2ddb0d1 --- /dev/null +++ b/lib/json_util.h @@ -0,0 +1,35 @@ +/***************************************************************************\ +* * +* BitlBee - An IRC to IM gateway * +* Helper functions for json.c * +* * +* Copyright 2012-2012 Wilmer van der Gaast <wilmer@gaast.net> * +* * +* This library is free software; you can redistribute it and/or * +* modify it under the terms of the GNU Lesser General Public * +* License as published by the Free Software Foundation, version * +* 2.1. * +* * +* This library is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +* Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * +* * +****************************************************************************/ + +#include "json.h" + +#define JSON_O_FOREACH(o, k, v) \ + char *k; json_value *v; int __i; \ + for( __i = 0; ( __i < (o)->u.object.length ) && \ + ( k = (o)->u.object.values[__i].name ) && \ + ( v = (o)->u.object.values[__i].value ); \ + __i ++ ) + +json_value *json_o_get( const json_value *obj, const json_char *name ); +const char *json_o_str( const json_value *obj, const json_char *name ); +char *json_o_strdup( const json_value *obj, const json_char *name ); @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2006 Wilmer van der Gaast and others * + * Copyright 2002-2012 Wilmer van der Gaast and others * \********************************************************************/ /* @@ -10,7 +10,7 @@ * * Copyright (C) 1998-1999, Mark Spencer <markster@marko.net> * (and possibly other members of the Gaim team) - * Copyright 2002-2006 Wilmer van der Gaast <wilmer@gaast.net> + * Copyright 2002-2012 Wilmer van der Gaast <wilmer@gaast.net> */ /* @@ -729,10 +729,10 @@ char **split_command_parts( char *command ) return cmd; } -char *get_rfc822_header( char *text, char *header, int len ) +char *get_rfc822_header( const char *text, const char *header, int len ) { int hlen = strlen( header ), i; - char *ret; + const char *ret; if( text == NULL ) return NULL; @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2004 Wilmer van der Gaast and others * + * Copyright 2002-2012 Wilmer van der Gaast and others * \********************************************************************/ /* Misc. functions */ @@ -67,6 +67,6 @@ G_MODULE_EXPORT char *word_wrap( const char *msg, int line_len ); G_MODULE_EXPORT gboolean ssl_sockerr_again( void *ssl ); G_MODULE_EXPORT int md5_verify_password( char *password, char *hash ); G_MODULE_EXPORT char **split_command_parts( char *command ); -G_MODULE_EXPORT char *get_rfc822_header( char *text, char *header, int len ); +G_MODULE_EXPORT char *get_rfc822_header( const char *text, const char *header, int len ); #endif diff --git a/lib/oauth2.c b/lib/oauth2.c index 87965d04..6921a6d5 100644 --- a/lib/oauth2.c +++ b/lib/oauth2.c @@ -3,7 +3,7 @@ * BitlBee - An IRC to IM gateway * * Simple OAuth client (consumer) implementation. * * * -* Copyright 2010-2011 Wilmer van der Gaast <wilmer@gaast.net> * +* Copyright 2010-2012 Wilmer van der Gaast <wilmer@gaast.net> * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -25,6 +25,7 @@ #include "http_client.h" #include "oauth2.h" #include "oauth.h" +#include "json.h" #include "url.h" char *oauth2_url( const struct oauth2_service *sp ) @@ -43,7 +44,6 @@ struct oauth2_access_token_data gpointer data; }; -static char *oauth2_json_dumb_get( const char *json, const char *key ); static void oauth2_access_token_done( struct http_request *req ); int oauth2_access_token( const struct oauth2_service *sp, @@ -102,7 +102,7 @@ static void oauth2_access_token_done( struct http_request *req ) { struct oauth2_access_token_data *cb_data = req->data; char *atoken = NULL, *rtoken = NULL; - const char *content_type; + char *content_type; if( getenv( "BITLBEE_DEBUG" ) && req->reply_body ) printf( "%s\n", req->reply_body ); @@ -114,8 +114,22 @@ static void oauth2_access_token_done( struct http_request *req ) } else if( content_type && strstr( content_type, "application/json" ) ) { - atoken = oauth2_json_dumb_get( req->reply_body, "access_token" ); - rtoken = oauth2_json_dumb_get( req->reply_body, "refresh_token" ); + json_value *js = json_parse( req->reply_body ); + if( js && js->type == json_object ) + { + int i; + + for( i = 0; i < js->u.object.length; i ++ ) + { + if( js->u.object.values[i].value->type != json_string ) + continue; + if( strcmp( js->u.object.values[i].name, "access_token" ) == 0 ) + atoken = g_strdup( js->u.object.values[i].value->u.string.ptr ); + if( strcmp( js->u.object.values[i].name, "refresh_token" ) == 0 ) + rtoken = g_strdup( js->u.object.values[i].value->u.string.ptr ); + } + } + json_value_free( js ); } else { @@ -131,66 +145,8 @@ static void oauth2_access_token_done( struct http_request *req ) printf( "Extracted atoken=%s rtoken=%s\n", atoken, rtoken ); cb_data->func( cb_data->data, atoken, rtoken ); + g_free( content_type ); g_free( atoken ); g_free( rtoken ); g_free( cb_data ); } - -/* Super dumb. I absolutely refuse to use/add a complete json parser library - (adding a new dependency to BitlBee for the first time in.. 6 years?) just - to parse 100 bytes of data. So I have to do my own parsing because OAuth2 - dropped support for XML. (GRRR!) This is very dumb and for example won't - work for integer values, nor will it strip/handle backslashes. */ -static char *oauth2_json_dumb_get( const char *json, const char *key ) -{ - int is_key = 0; /* 1 == reading key, 0 == reading value */ - int found_key = 0; - - while( json && *json ) - { - /* Grab strings and see if they're what we're looking for. */ - if( *json == '"' || *json == '\'' ) - { - char q = *json; - const char *str_start; - json ++; - str_start = json; - - while( *json ) - { - /* \' and \" are not string terminators. */ - if( *json == '\\' && json[1] == q ) - json ++; - /* But without a \ it is. */ - else if( *json == q ) - break; - json ++; - } - if( *json == '\0' ) - return NULL; - - if( is_key && strncmp( str_start, key, strlen( key ) ) == 0 ) - { - found_key = 1; - } - else if( !is_key && found_key ) - { - char *ret = g_memdup( str_start, json - str_start + 1 ); - ret[json-str_start] = '\0'; - return ret; - } - - } - else if( *json == '{' || *json == ',' ) - { - found_key = 0; - is_key = 1; - } - else if( *json == ':' ) - is_key = 0; - - json ++; - } - - return NULL; -} diff --git a/lib/ssl_bogus.c b/lib/ssl_bogus.c deleted file mode 100644 index e134201d..00000000 --- a/lib/ssl_bogus.c +++ /dev/null @@ -1,76 +0,0 @@ - /********************************************************************\ - * BitlBee -- An IRC to other IM-networks gateway * - * * - * Copyright 2002-2004 Wilmer van der Gaast and others * - \********************************************************************/ - -/* SSL module - dummy version */ - -/* - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License with - the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; - if not, write to the Free Software Foundation, Inc., 59 Temple Place, - Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ssl_client.h" - -int ssl_errno; - -void ssl_init( void ) -{ -} - -void *ssl_connect( char *host, int port, gboolean verify, ssl_input_function func, gpointer data ) -{ - return( NULL ); -} - -int ssl_read( void *conn, char *buf, int len ) -{ - return( -1 ); -} - -int ssl_write( void *conn, const char *buf, int len ) -{ - return( -1 ); -} - -void ssl_disconnect( void *conn_ ) -{ -} - -int ssl_getfd( void *conn ) -{ - return( -1 ); -} - -void *ssl_starttls( int fd, char *hostname, gboolean verify, ssl_input_function func, gpointer data ) -{ - return NULL; -} - -b_input_condition ssl_getdirection( void *conn ) -{ - return B_EV_IO_READ; -} - -int ssl_pending( void *conn ) -{ - return 0; -} - -char *ssl_verify_strerror( int code ) -{ - return NULL; -} diff --git a/lib/ssl_gnutls.c b/lib/ssl_gnutls.c index 93601ba6..b698e630 100644 --- a/lib/ssl_gnutls.c +++ b/lib/ssl_gnutls.c @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2011 Wilmer van der Gaast and others * + * Copyright 2002-2012 Wilmer van der Gaast and others * \********************************************************************/ /* SSL module - GnuTLS version */ @@ -37,7 +37,7 @@ int ssl_errno = 0; static gboolean initialized = FALSE; -gnutls_certificate_credentials xcred; +gnutls_certificate_credentials_t xcred; #include <limits.h> @@ -59,9 +59,11 @@ struct scd char *hostname; gboolean verify; - gnutls_session session; + gnutls_session_t session; }; +static GHashTable *session_cache; + static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond ); static gboolean ssl_starttls_real( gpointer data, gint source, b_input_condition cond ); static gboolean ssl_handshake( gpointer data, gint source, b_input_condition cond ); @@ -84,8 +86,10 @@ void ssl_init( void ) { gnutls_certificate_set_x509_trust_file( xcred, global.conf->cafile, GNUTLS_X509_FMT_PEM ); - /* Not needed in GnuTLS 2.11+ but we support older versions for now. */ - gnutls_certificate_set_verify_flags( xcred, GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT ); + /* Not needed in GnuTLS 2.11+ (enabled by default there) so + don't do it (resets possible other defaults). */ + if( !gnutls_check_version( "2.11" ) ) + gnutls_certificate_set_verify_flags( xcred, GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT ); } initialized = TRUE; @@ -94,6 +98,8 @@ void ssl_init( void ) gnutls_global_set_log_level( 3 ); */ + session_cache = g_hash_table_new_full( g_str_hash, g_str_equal, g_free, g_free ); + atexit( ssl_deinit ); } @@ -101,18 +107,20 @@ static void ssl_deinit( void ) { gnutls_global_deinit(); gnutls_certificate_free_credentials( xcred ); + g_hash_table_destroy( session_cache ); + session_cache = NULL; } void *ssl_connect( char *host, int port, gboolean verify, ssl_input_function func, gpointer data ) { struct scd *conn = g_new0( struct scd, 1 ); - conn->fd = proxy_connect( host, port, ssl_connected, conn ); conn->func = func; conn->data = data; conn->inpa = -1; conn->hostname = g_strdup( host ); conn->verify = verify && global.conf->cafile; + conn->fd = proxy_connect( host, port, ssl_connected, conn ); if( conn->fd < 0 ) { @@ -131,7 +139,7 @@ void *ssl_starttls( int fd, char *hostname, gboolean verify, ssl_input_function conn->func = func; conn->data = data; conn->inpa = -1; - conn->hostname = hostname; + conn->hostname = g_strdup( hostname ); /* For now, SSL verification is globally enabled by setting the cafile setting in bitlbee.conf. Commented out by default because probably @@ -168,9 +176,9 @@ static int verify_certificate_callback( gnutls_session_t session ) int gnutlsret; int verifyret = 0; gnutls_x509_crt_t cert; - const char *hostname; + struct scd *conn; - hostname = gnutls_session_get_ptr( session ); + conn = gnutls_session_get_ptr( session ); gnutlsret = gnutls_certificate_verify_peers2( session, &status ); if( gnutlsret < 0 ) @@ -208,7 +216,7 @@ static int verify_certificate_callback( gnutls_session_t session ) if( cert_list == NULL || gnutls_x509_crt_import( cert, &cert_list[0], GNUTLS_X509_FMT_DER ) < 0 ) return VERIFY_CERT_ERROR; - if( !gnutls_x509_crt_check_hostname( cert, hostname ) ) + if( !gnutls_x509_crt_check_hostname( cert, conn->hostname ) ) { verifyret |= VERIFY_CERT_INVALID; verifyret |= VERIFY_CERT_WRONG_HOSTNAME; @@ -219,6 +227,45 @@ static int verify_certificate_callback( gnutls_session_t session ) return verifyret; } +struct ssl_session +{ + size_t size; + char data[]; +}; + +static void ssl_cache_add( struct scd *conn ) +{ + size_t data_size; + struct ssl_session *data; + char *hostname; + + if( !conn->hostname || + gnutls_session_get_data( conn->session, NULL, &data_size ) != 0 ) + return; + + data = g_malloc( sizeof( struct ssl_session ) + data_size ); + if( gnutls_session_get_data( conn->session, data->data, &data->size ) != 0 ) + { + g_free( data ); + return; + } + + hostname = g_strdup( conn->hostname ); + g_hash_table_insert( session_cache, hostname, data ); +} + +static void ssl_cache_resume( struct scd *conn ) +{ + struct ssl_session *data; + + if( conn->hostname && + ( data = g_hash_table_lookup( session_cache, conn->hostname ) ) ) + { + gnutls_session_set_data( conn->session, data->data, data->size ); + g_hash_table_remove( session_cache, conn->hostname ); + } +} + char *ssl_verify_strerror( int code ) { GString *ret = g_string_new( "" ); @@ -264,16 +311,20 @@ static gboolean ssl_connected( gpointer data, gint source, b_input_condition con ssl_init(); gnutls_init( &conn->session, GNUTLS_CLIENT ); - if( conn->verify ) - gnutls_session_set_ptr( conn->session, (void *) conn->hostname ); + gnutls_session_set_ptr( conn->session, (void *) conn ); #if GNUTLS_VERSION_NUMBER < 0x020c00 gnutls_transport_set_lowat( conn->session, 0 ); #endif gnutls_set_default_priority( conn->session ); gnutls_credentials_set( conn->session, GNUTLS_CRD_CERTIFICATE, xcred ); + if( conn->hostname && !isdigit( conn->hostname[0] ) ) + gnutls_server_name_set( conn->session, GNUTLS_NAME_DNS, + conn->hostname, strlen( conn->hostname ) ); sock_make_nonblocking( conn->fd ); - gnutls_transport_set_ptr( conn->session, (gnutls_transport_ptr) GNUTLS_STUPID_CAST conn->fd ); + gnutls_transport_set_ptr( conn->session, (gnutls_transport_ptr_t) GNUTLS_STUPID_CAST conn->fd ); + + ssl_cache_resume( conn ); return ssl_handshake( data, source, cond ); } @@ -315,7 +366,8 @@ static gboolean ssl_handshake( gpointer data, gint source, b_input_condition con { /* For now we can't handle non-blocking perfectly everywhere... */ sock_make_blocking( conn->fd ); - + + ssl_cache_add( conn ); conn->established = TRUE; conn->func( conn->data, 0, conn, cond ); } @@ -399,6 +451,7 @@ void ssl_disconnect( void *conn_ ) if( conn->session ) gnutls_deinit( conn->session ); + g_free( conn->hostname ); g_free( conn ); } diff --git a/lib/ssl_nss.c b/lib/ssl_nss.c index d50620d5..e8de884f 100644 --- a/lib/ssl_nss.c +++ b/lib/ssl_nss.c @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2005 Wilmer van der Gaast and others * + * Copyright 2002-2012 Wilmer van der Gaast and others * \********************************************************************/ /* SSL module - NSS version */ @@ -39,39 +39,46 @@ #include <seccomon.h> #include <secerr.h> #include <sslerr.h> +#include <assert.h> +#include <unistd.h> int ssl_errno = 0; static gboolean initialized = FALSE; -struct scd -{ +#define SSLDEBUG 0 + +struct scd { ssl_input_function func; gpointer data; int fd; + char *hostname; PRFileDesc *prfd; gboolean established; gboolean verify; }; -static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond ); -static gboolean ssl_starttls_real( gpointer data, gint source, b_input_condition cond ); +static gboolean ssl_connected(gpointer data, gint source, + b_input_condition cond); +static gboolean ssl_starttls_real(gpointer data, gint source, + b_input_condition cond); - -static SECStatus nss_auth_cert (void *arg, PRFileDesc *socket, PRBool checksig, PRBool isserver) +static SECStatus nss_auth_cert(void *arg, PRFileDesc * socket, PRBool checksig, + PRBool isserver) { return SECSuccess; } -static SECStatus nss_bad_cert (void *arg, PRFileDesc *socket) +static SECStatus nss_bad_cert(void *arg, PRFileDesc * socket) { PRErrorCode err; - if(!arg) return SECFailure; + if (!arg) + return SECFailure; - *(PRErrorCode *)arg = err = PORT_GetError(); + *(PRErrorCode *) arg = err = PORT_GetError(); - switch(err) { + switch (err) { case SEC_ERROR_INVALID_AVA: case SEC_ERROR_INVALID_TIME: case SEC_ERROR_BAD_SIGNATURE: @@ -93,52 +100,63 @@ static SECStatus nss_bad_cert (void *arg, PRFileDesc *socket) } } - -void ssl_init( void ) +void ssl_init(void) { - PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); + PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); + // https://www.mozilla.org/projects/security/pki/nss/ref/ssl/sslfnc.html#1234224 + // This NSS function is not intended for use with SSL, which + // requires that the certificate and key database files be + // opened. Relates to whole non-verification of servers for now. NSS_NoDB_Init(NULL); NSS_SetDomesticPolicy(); initialized = TRUE; } -void *ssl_connect( char *host, int port, gboolean verify, ssl_input_function func, gpointer data ) +void *ssl_connect(char *host, int port, gboolean verify, + ssl_input_function func, gpointer data) { - struct scd *conn = g_new0( struct scd, 1 ); - - conn->fd = proxy_connect( host, port, ssl_connected, conn ); + struct scd *conn = g_new0(struct scd, 1); + + conn->fd = proxy_connect(host, port, ssl_connected, conn); conn->func = func; conn->data = data; - - if( conn->fd < 0 ) - { - g_free( conn ); - return( NULL ); + conn->hostname = g_strdup(host); + + if (conn->fd < 0) { + g_free(conn->hostname); + g_free(conn); + return (NULL); } - - if( !initialized ) - { + + if (!initialized) { ssl_init(); } - - return( conn ); + return (conn); } -static gboolean ssl_starttls_real( gpointer data, gint source, b_input_condition cond ) +static gboolean ssl_starttls_real(gpointer data, gint source, + b_input_condition cond) { struct scd *conn = data; - return ssl_connected( conn, conn->fd, B_EV_IO_WRITE ); + return ssl_connected(conn, conn->fd, B_EV_IO_WRITE); } -void *ssl_starttls( int fd, char *hostname, gboolean verify, ssl_input_function func, gpointer data ) +void *ssl_starttls(int fd, char *hostname, gboolean verify, + ssl_input_function func, gpointer data) { - struct scd *conn = g_new0( struct scd, 1 ); + struct scd *conn = g_new0(struct scd, 1); conn->fd = fd; conn->func = func; conn->data = data; + conn->hostname = hostname; + + /* For now, SSL verification is globally enabled by setting the cafile + setting in bitlbee.conf. Commented out by default because probably + not everyone has this file in the same place and plenty of folks + may not have the cert of their private Jabber server in it. */ conn->verify = verify && global.conf->cafile; /* This function should be called via a (short) timeout instead of @@ -150,108 +168,255 @@ void *ssl_starttls( int fd, char *hostname, gboolean verify, ssl_input_function In short, doing things like this makes the rest of the code a lot simpler. */ - b_timeout_add( 1, ssl_starttls_real, conn ); + b_timeout_add(1, ssl_starttls_real, conn); return conn; } -static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond ) +static gboolean ssl_connected(gpointer data, gint source, + b_input_condition cond) { struct scd *conn = data; - + /* Right now we don't have any verification functionality for NSS. */ - if( conn->verify ) - { - conn->func( conn->data, 1, NULL, cond ); - if( source >= 0 ) closesocket( source ); - g_free( conn ); + if (conn->verify) { + conn->func(conn->data, 1, NULL, cond); + if (source >= 0) + closesocket(source); + g_free(conn->hostname); + g_free(conn); return FALSE; } - - if( source == -1 ) + + if (source == -1) goto ssl_connected_failure; - + /* Until we find out how to handle non-blocking I/O with NSS... */ - sock_make_blocking( conn->fd ); - + sock_make_blocking(conn->fd); + conn->prfd = SSL_ImportFD(NULL, PR_ImportTCPSocket(source)); + if (!conn->prfd) + goto ssl_connected_failure; SSL_OptionSet(conn->prfd, SSL_SECURITY, PR_TRUE); SSL_OptionSet(conn->prfd, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE); - SSL_BadCertHook(conn->prfd, (SSLBadCertHandler)nss_bad_cert, NULL); - SSL_AuthCertificateHook(conn->prfd, (SSLAuthCertificate)nss_auth_cert, (void *)CERT_GetDefaultCertDB()); + SSL_BadCertHook(conn->prfd, (SSLBadCertHandler) nss_bad_cert, NULL); + SSL_AuthCertificateHook(conn->prfd, (SSLAuthCertificate) nss_auth_cert, + (void *)CERT_GetDefaultCertDB()); + SSL_SetURL(conn->prfd, conn->hostname); SSL_ResetHandshake(conn->prfd, PR_FALSE); if (SSL_ForceHandshake(conn->prfd)) { goto ssl_connected_failure; } - - + conn->established = TRUE; - conn->func( conn->data, 0, conn, cond ); + conn->func(conn->data, 0, conn, cond); return FALSE; - - ssl_connected_failure: - - conn->func( conn->data, 0, NULL, cond ); - - PR_Close( conn -> prfd ); - if( source >= 0 ) closesocket( source ); - g_free( conn ); - + + ssl_connected_failure: + + conn->func(conn->data, 0, NULL, cond); + + if (conn->prfd) + PR_Close(conn->prfd); + if (source >= 0) + closesocket(source); + g_free(conn->hostname); + g_free(conn); + return FALSE; } -int ssl_read( void *conn, char *buf, int len ) +int ssl_read(void *conn, char *buf, int len) { - if( !((struct scd*)conn)->established ) - return( 0 ); - - return( PR_Read( ((struct scd*)conn)->prfd, buf, len ) ); + int st; + PRErrorCode PR_err; + + if (!((struct scd *)conn)->established) { + ssl_errno = SSL_NOHANDSHAKE; + return -1; + } + + st = PR_Read(((struct scd *)conn)->prfd, buf, len); + PR_err = PR_GetError(); + + ssl_errno = SSL_OK; + if (PR_err == PR_WOULD_BLOCK_ERROR) + ssl_errno = SSL_AGAIN; + + if (SSLDEBUG && getenv("BITLBEE_DEBUG") && st > 0) + len = write(STDERR_FILENO, buf, st); + + return st; } -int ssl_write( void *conn, const char *buf, int len ) +int ssl_write(void *conn, const char *buf, int len) { - if( !((struct scd*)conn)->established ) - return( 0 ); - - return( PR_Write ( ((struct scd*)conn)->prfd, buf, len ) ); + int st; + PRErrorCode PR_err; + + if (!((struct scd *)conn)->established) { + ssl_errno = SSL_NOHANDSHAKE; + return -1; + } + st = PR_Write(((struct scd *)conn)->prfd, buf, len); + PR_err = PR_GetError(); + + ssl_errno = SSL_OK; + if (PR_err == PR_WOULD_BLOCK_ERROR) + ssl_errno = SSL_AGAIN; + + if (SSLDEBUG && getenv("BITLBEE_DEBUG") && st > 0) + len = write(2, buf, st); + + return st; } -int ssl_pending( void *conn ) +int ssl_pending(void *conn) { - struct scd *c = (struct scd *) conn; + struct scd *c = (struct scd *)conn; - if( c == NULL ) { + if (c == NULL) { return 0; } - return ( c->established && SSL_DataPending( c->prfd ) > 0 ); + return (c->established && SSL_DataPending(c->prfd) > 0); } -void ssl_disconnect( void *conn_ ) +void ssl_disconnect(void *conn_) { struct scd *conn = conn_; - - PR_Close( conn->prfd ); - closesocket( conn->fd ); - - g_free( conn ); + + // When we swich to NSS_Init, we should have here + // NSS_Shutdown(); + + if (conn->prfd) + PR_Close(conn->prfd); + + g_free(conn->hostname); + g_free(conn); } -int ssl_getfd( void *conn ) +int ssl_getfd(void *conn) { - return( ((struct scd*)conn)->fd ); + return (((struct scd *)conn)->fd); } -b_input_condition ssl_getdirection( void *conn ) +b_input_condition ssl_getdirection(void *conn) { /* Just in case someone calls us, let's return the most likely case: */ return B_EV_IO_READ; } -char *ssl_verify_strerror( int code ) +char *ssl_verify_strerror(int code) +{ + return + g_strdup + ("SSL certificate verification not supported by BitlBee NSS code."); +} + +size_t ssl_des3_encrypt(const unsigned char *key, size_t key_len, + const unsigned char *input, size_t input_len, + const unsigned char *iv, unsigned char **res) { - return g_strdup( "SSL certificate verification not supported by BitlBee NSS code." ); +#define CIPHER_MECH CKM_DES3_CBC +#define MAX_OUTPUT_LEN 72 + + int len1; + unsigned int len2; + + PK11Context *ctx = NULL; + PK11SlotInfo *slot = NULL; + SECItem keyItem; + SECItem ivItem; + SECItem *secParam = NULL; + PK11SymKey *symKey = NULL; + + size_t rc; + SECStatus rv; + + if (!initialized) { + ssl_init(); + } + + keyItem.data = (unsigned char *)key; + keyItem.len = key_len; + + slot = PK11_GetBestSlot(CIPHER_MECH, NULL); + if (slot == NULL) { + fprintf(stderr, "PK11_GetBestSlot failed (err %d)\n", + PR_GetError()); + rc = 0; + goto out; + } + + symKey = + PK11_ImportSymKey(slot, CIPHER_MECH, PK11_OriginUnwrap, CKA_ENCRYPT, + &keyItem, NULL); + if (symKey == NULL) { + fprintf(stderr, "PK11_ImportSymKey failed (err %d)\n", + PR_GetError()); + rc = 0; + goto out; + } + + ivItem.data = (unsigned char *)iv; + /* See msn_soap_passport_sso_handle_response in protocols/msn/soap.c */ + ivItem.len = 8; + + secParam = PK11_ParamFromIV(CIPHER_MECH, &ivItem); + if (secParam == NULL) { + fprintf(stderr, "PK11_ParamFromIV failed (err %d)\n", + PR_GetError()); + rc = 0; + goto out; + } + + ctx = + PK11_CreateContextBySymKey(CIPHER_MECH, CKA_ENCRYPT, symKey, + secParam); + if (ctx == NULL) { + fprintf(stderr, "PK11_CreateContextBySymKey failed (err %d)\n", + PR_GetError()); + rc = 0; + goto out; + } + + *res = g_new0(unsigned char, MAX_OUTPUT_LEN); + + rv = PK11_CipherOp(ctx, *res, &len1, MAX_OUTPUT_LEN, + (unsigned char *)input, input_len); + if (rv != SECSuccess) { + fprintf(stderr, "PK11_CipherOp failed (err %d)\n", + PR_GetError()); + rc = 0; + goto out; + } + + assert(len1 <= MAX_OUTPUT_LEN); + + rv = PK11_DigestFinal(ctx, *res + len1, &len2, + (unsigned int)MAX_OUTPUT_LEN - len1); + if (rv != SECSuccess) { + fprintf(stderr, "PK11_DigestFinal failed (err %d)\n", + PR_GetError()); + rc = 0; + goto out; + } + + rc = len1 + len2; + + out: + if (ctx) + PK11_DestroyContext(ctx, PR_TRUE); + if (symKey) + PK11_FreeSymKey(symKey); + if (secParam) + SECITEM_FreeItem(secParam, PR_TRUE); + if (slot) + PK11_FreeSlot(slot); + + return rc; } diff --git a/lib/ssl_openssl.c b/lib/ssl_openssl.c index c1aa6b1b..3486f044 100644 --- a/lib/ssl_openssl.c +++ b/lib/ssl_openssl.c @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2004 Wilmer van der Gaast and others * + * Copyright 2002-2012 Wilmer van der Gaast and others * \********************************************************************/ /* SSL module - OpenSSL version */ @@ -46,13 +46,16 @@ struct scd int fd; gboolean established; gboolean verify; + char *hostname; int inpa; int lasterr; /* Necessary for SSL_get_error */ SSL *ssl; - SSL_CTX *ssl_ctx; }; +static SSL_CTX *ssl_ctx; + +static void ssl_conn_free( struct scd *conn ); static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond ); static gboolean ssl_starttls_real( gpointer data, gint source, b_input_condition cond ); static gboolean ssl_handshake( gpointer data, gint source, b_input_condition cond ); @@ -60,9 +63,14 @@ static gboolean ssl_handshake( gpointer data, gint source, b_input_condition con void ssl_init( void ) { - initialized = TRUE; + const SSL_METHOD *meth; + SSL_library_init(); - // SSLeay_add_ssl_algorithms(); + + meth = TLSv1_client_method(); + ssl_ctx = SSL_CTX_new( meth ); + + initialized = TRUE; } void *ssl_connect( char *host, int port, gboolean verify, ssl_input_function func, gpointer data ) @@ -72,13 +80,14 @@ void *ssl_connect( char *host, int port, gboolean verify, ssl_input_function fun conn->fd = proxy_connect( host, port, ssl_connected, conn ); if( conn->fd < 0 ) { - g_free( conn ); + ssl_conn_free( conn ); return NULL; } conn->func = func; conn->data = data; conn->inpa = -1; + conn->hostname = g_strdup( host ); return conn; } @@ -92,6 +101,7 @@ void *ssl_starttls( int fd, char *hostname, gboolean verify, ssl_input_function conn->data = data; conn->inpa = -1; conn->verify = verify && global.conf->cafile; + conn->hostname = g_strdup( hostname ); /* This function should be called via a (short) timeout instead of directly from here, because these SSL calls are *supposed* to be @@ -117,15 +127,13 @@ static gboolean ssl_starttls_real( gpointer data, gint source, b_input_condition static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond ) { struct scd *conn = data; - const SSL_METHOD *meth; - /* Right now we don't have any verification functionality for OpenSSL. */ - if( conn->verify ) { + /* Right now we don't have any verification functionality for OpenSSL. */ conn->func( conn->data, 1, NULL, cond ); if( source >= 0 ) closesocket( source ); - g_free( conn ); + ssl_conn_free( conn ); return FALSE; } @@ -138,12 +146,11 @@ static gboolean ssl_connected( gpointer data, gint source, b_input_condition con ssl_init(); } - meth = TLSv1_client_method(); - conn->ssl_ctx = SSL_CTX_new( meth ); - if( conn->ssl_ctx == NULL ) + + if( ssl_ctx == NULL ) goto ssl_connected_failure; - conn->ssl = SSL_new( conn->ssl_ctx ); + conn->ssl = SSL_new( ssl_ctx ); if( conn->ssl == NULL ) goto ssl_connected_failure; @@ -151,23 +158,14 @@ static gboolean ssl_connected( gpointer data, gint source, b_input_condition con sock_make_nonblocking( conn->fd ); SSL_set_fd( conn->ssl, conn->fd ); + if( conn->hostname && !isdigit( conn->hostname[0] ) ) + SSL_set_tlsext_host_name( conn->ssl, conn->hostname ); + return ssl_handshake( data, source, cond ); ssl_connected_failure: conn->func( conn->data, 0, NULL, cond ); - - if( conn->ssl ) - { - SSL_shutdown( conn->ssl ); - SSL_free( conn->ssl ); - } - if( conn->ssl_ctx ) - { - SSL_CTX_free( conn->ssl_ctx ); - } - if( source >= 0 ) closesocket( source ); - g_free( conn ); - + ssl_disconnect( conn ); return FALSE; } @@ -183,14 +181,7 @@ static gboolean ssl_handshake( gpointer data, gint source, b_input_condition con if( conn->lasterr != SSL_ERROR_WANT_READ && conn->lasterr != SSL_ERROR_WANT_WRITE ) { conn->func( conn->data, 0, NULL, cond ); - - SSL_shutdown( conn->ssl ); - SSL_free( conn->ssl ); - SSL_CTX_free( conn->ssl_ctx ); - - if( source >= 0 ) closesocket( source ); - g_free( conn ); - + ssl_disconnect( conn ); return FALSE; } @@ -260,6 +251,14 @@ int ssl_pending( void *conn ) SSL_pending( ((struct scd*)conn)->ssl ) > 0 : 0; } +static void ssl_conn_free( struct scd *conn ) +{ + SSL_free( conn->ssl ); + g_free( conn->hostname ); + g_free( conn ); + +} + void ssl_disconnect( void *conn_ ) { struct scd *conn = conn_; @@ -272,9 +271,7 @@ void ssl_disconnect( void *conn_ ) closesocket( conn->fd ); - SSL_free( conn->ssl ); - SSL_CTX_free( conn->ssl_ctx ); - g_free( conn ); + ssl_conn_free( conn ); } int ssl_getfd( void *conn ) diff --git a/lib/xmltree.c b/lib/xmltree.c index 3906029c..0726d387 100644 --- a/lib/xmltree.c +++ b/lib/xmltree.c @@ -3,7 +3,7 @@ * BitlBee - An IRC to IM gateway * * Simple XML (stream) parse tree handling code (Jabber/XMPP, mainly) * * * -* Copyright 2006 Wilmer van der Gaast <wilmer@gaast.net> * +* Copyright 2006-2012 Wilmer van der Gaast <wilmer@gaast.net> * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public * @@ -162,9 +162,8 @@ int xt_handle( struct xt_parser *xt, struct xt_node *node, int depth ) xt_status st; int i; - /* Just in case someone likes infinite loops... */ if( xt->root == NULL ) - return 0; + return 1; if( node == NULL ) return xt_handle( xt, xt->root, depth ); @@ -262,15 +261,21 @@ void xt_cleanup( struct xt_parser *xt, struct xt_node *node, int depth ) } } -struct xt_node *xt_from_string( const char *in ) +struct xt_node *xt_from_string( const char *in, int len ) { struct xt_parser *parser; - struct xt_node *ret; + struct xt_node *ret = NULL; + + if( len == 0 ) + len = strlen( in ); parser = xt_new( NULL, NULL ); - xt_feed( parser, in, strlen( in ) ); - ret = parser->root; - parser->root = NULL; + xt_feed( parser, in, len ); + if( parser->cur == NULL ) + { + ret = parser->root; + parser->root = NULL; + } xt_free( parser ); return ret; diff --git a/lib/xmltree.h b/lib/xmltree.h index cfd3361c..a41cbac1 100644 --- a/lib/xmltree.h +++ b/lib/xmltree.h @@ -3,7 +3,7 @@ * BitlBee - An IRC to IM gateway * * Simple XML (stream) parse tree handling code (Jabber/XMPP, mainly) * * * -* Copyright 2006 Wilmer van der Gaast <wilmer@gaast.net> * +* Copyright 2006-2012 Wilmer van der Gaast <wilmer@gaast.net> * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public * @@ -81,7 +81,7 @@ void xt_reset( struct xt_parser *xt ); int xt_feed( struct xt_parser *xt, const char *text, int text_len ); int xt_handle( struct xt_parser *xt, struct xt_node *node, int depth ); void xt_cleanup( struct xt_parser *xt, struct xt_node *node, int depth ); -struct xt_node *xt_from_string( const char *in ); +struct xt_node *xt_from_string( const char *in, int text_len ); char *xt_to_string( struct xt_node *node ); char *xt_to_string_i( struct xt_node *node ); void xt_print( struct xt_node *node ); @@ -13,6 +13,6 @@ information. The developers of the Bee hope you have a buzzing time. -* BitlBee development team: wilmer, jelmer, Maurits +* BitlBee development team. ... Buzzing, haha, get it? @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2010 Wilmer van der Gaast and others * + * Copyright 2002-2012 Wilmer van der Gaast and others * \********************************************************************/ /* Some stuff to fetch, save and handle nicknames for your buddies */ @@ -133,7 +133,10 @@ char *nick_gen( bee_user_t *bu ) { chop = fmt[1]; if( chop == '\0' ) + { + g_string_free( ret, TRUE ); return NULL; + } fmt += 2; } else if( isdigit( *fmt ) ) @@ -186,6 +189,7 @@ char *nick_gen( bee_user_t *bu ) } else { + g_string_free( ret, TRUE ); return NULL; } } @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2010 Wilmer van der Gaast and others * + * Copyright 2002-2012 Wilmer van der Gaast and others * \********************************************************************/ /* @@ -236,7 +236,7 @@ gboolean otr_irc_new(irc_t *irc) s = set_add( &irc->b->set, "otr_color_encrypted", "true", set_eval_bool, irc ); - s = set_add( &irc->b->set, "otr_policy", "oppurtunistic", set_eval_list, irc ); + s = set_add( &irc->b->set, "otr_policy", "opportunistic", set_eval_list, irc ); l = g_slist_prepend( NULL, "never" ); l = g_slist_prepend( l, "opportunistic" ); l = g_slist_prepend( l, "manual" ); diff --git a/protocols/Makefile b/protocols/Makefile index e93f3b23..b4565ab6 100644 --- a/protocols/Makefile +++ b/protocols/Makefile @@ -54,6 +54,6 @@ $(objects): ../Makefile.settings Makefile $(objects): %.o: $(_SRCDIR_)%.c @echo '*' Compiling $< - @$(CC) -c $(CFLAGS) $< -o $@ + @$(CC) -c $(CFLAGS) $(CFLAGS_BITLBEE) $< -o $@ -include .depend/*.d diff --git a/protocols/account.c b/protocols/account.c index 020a55cd..dec9c3ea 100644 --- a/protocols/account.c +++ b/protocols/account.c @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2010 Wilmer van der Gaast and others * + * Copyright 2002-2013 Wilmer van der Gaast and others * \********************************************************************/ /* Account management functions */ @@ -153,18 +153,14 @@ char *set_eval_account( set_t *set, char *value ) } else if( strcmp( set->key, "password" ) == 0 ) { - if( value ) - { - g_free( acc->pass ); - acc->pass = g_strdup( value ); - return NULL; /* password shouldn't be visible in plaintext! */ - } - else - { - /* NULL can (should) be stored in the set_t - variable, but is otherwise not correct. */ - return SET_INVALID; - } + /* set -del should be allowed now, but I don't want to have any + NULL pointers to have to deal with. */ + if( !value ) + value = ""; + + g_free( acc->pass ); + acc->pass = g_strdup( value ); + return NULL; /* password shouldn't be visible in plaintext! */ } else if( strcmp( set->key, "tag" ) == 0 ) { @@ -353,7 +349,7 @@ void account_on( bee_t *bee, account_t *a ) a->reconnect = 0; a->prpl->login( a ); - if( a->ic && !( a->ic->flags & OPT_SLOW_LOGIN ) ) + if( a->ic && !( a->ic->flags & ( OPT_SLOW_LOGIN | OPT_LOGGED_IN ) ) ) a->ic->keepalive = b_timeout_add( 120000, account_on_timeout, a->ic ); } @@ -372,8 +368,11 @@ static gboolean account_on_timeout( gpointer d, gint fd, b_input_condition cond { struct im_connection *ic = d; - imcb_error( ic, "Connection timeout" ); - imc_logout( ic, TRUE ); + if( !( ic->flags & ( OPT_SLOW_LOGIN | OPT_LOGGED_IN ) ) ) + { + imcb_error( ic, "Connection timeout" ); + imc_logout( ic, TRUE ); + } return FALSE; } diff --git a/protocols/account.h b/protocols/account.h index ddc2b3e7..ed3ca531 100644 --- a/protocols/account.h +++ b/protocols/account.h @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2004 Wilmer van der Gaast and others * + * Copyright 2002-2013 Wilmer van der Gaast and others * \********************************************************************/ /* Account management functions */ @@ -68,6 +68,7 @@ typedef enum { ACC_FLAG_AWAY_MESSAGE = 0x01, /* Supports away messages instead of just states. */ ACC_FLAG_STATUS_MESSAGE = 0x02, /* Supports status messages (without being away). */ + ACC_FLAG_HANDLE_DOMAINS = 0x04, /* Contact handles need a domain portion. */ } account_flag_t; #endif diff --git a/protocols/jabber/Makefile b/protocols/jabber/Makefile index 20bc1259..b5c3b107 100644 --- a/protocols/jabber/Makefile +++ b/protocols/jabber/Makefile @@ -37,7 +37,7 @@ $(objects): ../../Makefile.settings Makefile $(objects): %.o: $(_SRCDIR_)%.c @echo '*' Compiling $< - @$(CC) -c $(CFLAGS) $< -o $@ + @$(CC) -c $(CFLAGS) $(CFLAGS_BITLBEE) $< -o $@ jabber_mod.o: $(objects) @echo '*' Linking jabber_mod.o diff --git a/protocols/jabber/conference.c b/protocols/jabber/conference.c index 0a66b461..c8930f83 100644 --- a/protocols/jabber/conference.c +++ b/protocols/jabber/conference.c @@ -3,7 +3,7 @@ * BitlBee - An IRC to IM gateway * * Jabber module - Conference rooms * * * -* Copyright 2007 Wilmer van der Gaast <wilmer@gaast.net> * +* Copyright 2007-2012 Wilmer van der Gaast <wilmer@gaast.net> * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c index 5b9149af..6f79b2d1 100644 --- a/protocols/jabber/io.c +++ b/protocols/jabber/io.c @@ -3,7 +3,7 @@ * BitlBee - An IRC to IM gateway * * Jabber module - I/O stuff (plain, SSL), queues, etc * * * -* Copyright 2006 Wilmer van der Gaast <wilmer@gaast.net> * +* Copyright 2006-2012 Wilmer van der Gaast <wilmer@gaast.net> * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -452,8 +452,39 @@ static xt_status jabber_pkt_proceed_tls( struct xt_node *node, gpointer data ) static xt_status jabber_pkt_stream_error( struct xt_node *node, gpointer data ) { struct im_connection *ic = data; + struct jabber_data *jd = ic->proto_data; int allow_reconnect = TRUE; struct jabber_error *err; + struct xt_node *host; + + if( !( ic->flags & OPT_LOGGED_IN ) && + ( host = xt_find_node( node->children, "see-other-host" ) ) && + host->text ) + { + char *s; + int port = set_getint( &ic->acc->set, "port" ); + + /* Let's try to obey this request, if we're not logged + in yet (i.e. not have too much state yet). */ + if( jd->ssl ) + ssl_disconnect( jd->ssl ); + closesocket( jd->fd ); + b_event_remove( jd->r_inpa ); + b_event_remove( jd->w_inpa ); + + jd->ssl = NULL; + jd->r_inpa = jd->w_inpa = 0; + jd->flags &= JFLAG_XMLCONSOLE; + + s = strchr( host->text, ':' ); + if( s != NULL ) + sscanf( s + 1, "%d", &port ); + + imcb_log( ic, "Redirected to %s", host->text ); + jd->fd = proxy_connect( host->text, port, jabber_connected_plain, ic ); + + return XT_ABORT; + } err = jabber_error_parse( node, XMLNS_STREAM_ERROR ); diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index b5a37a30..31b92049 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -3,7 +3,7 @@ * BitlBee - An IRC to IM gateway * * Jabber module - IQ packets * * * -* Copyright 2006 Wilmer van der Gaast <wilmer@gaast.net> * +* Copyright 2006-2012 Wilmer van der Gaast <wilmer@gaast.net> * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -127,6 +127,7 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) XMLNS_CHATSTATES, XMLNS_MUC, XMLNS_PING, + XMLNS_RECEIPTS, XMLNS_SI, XMLNS_BYTESTREAMS, XMLNS_FILETRANSFER, diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index dbae9ff9..dab4afdf 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -3,7 +3,7 @@ * BitlBee - An IRC to IM gateway * * Jabber module - Main file * * * -* Copyright 2006 Wilmer van der Gaast <wilmer@gaast.net> * +* Copyright 2006-2013 Wilmer van der Gaast <wilmer@gaast.net> * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -84,7 +84,7 @@ static void jabber_init( account_t *acc ) s = set_add( &acc->set, "ssl", "false", set_eval_bool, acc ); s->flags |= ACC_SET_OFFLINE_ONLY; - s = set_add( &acc->set, "tls", "try", set_eval_tls, acc ); + s = set_add( &acc->set, "tls", "true", set_eval_tls, acc ); s->flags |= ACC_SET_OFFLINE_ONLY; s = set_add( &acc->set, "tls_verify", "true", set_eval_bool, acc ); @@ -95,7 +95,8 @@ static void jabber_init( account_t *acc ) s = set_add( &acc->set, "xmlconsole", "false", set_eval_bool, acc ); s->flags |= ACC_SET_OFFLINE_ONLY; - acc->flags |= ACC_FLAG_AWAY_MESSAGE | ACC_FLAG_STATUS_MESSAGE; + acc->flags |= ACC_FLAG_AWAY_MESSAGE | ACC_FLAG_STATUS_MESSAGE | + ACC_FLAG_HANDLE_DOMAINS; } static void jabber_generate_id_hash( struct jabber_data *jd ); @@ -230,7 +231,7 @@ void jabber_connect( struct im_connection *ic ) non-standard ports... */ if( set_getbool( &acc->set, "ssl" ) ) { - jd->ssl = ssl_connect( connect_to, set_getint( &acc->set, "port" ), FALSE, jabber_connected_ssl, ic ); + jd->ssl = ssl_connect( connect_to, set_getint( &acc->set, "port" ), set_getbool( &acc->set, "tls_verify" ), jabber_connected_ssl, ic ); jd->fd = jd->ssl ? ssl_getfd( jd->ssl ) : -1; } else diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index d11d2fe8..006da9a3 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -3,7 +3,7 @@ * BitlBee - An IRC to IM gateway * * Jabber module - Main file * * * -* Copyright 2006 Wilmer van der Gaast <wilmer@gaast.net> * +* Copyright 2006-2013 Wilmer van der Gaast <wilmer@gaast.net> * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -195,7 +195,7 @@ struct jabber_transfer struct sockaddr_storage saddr; }; -#define JABBER_XMLCONSOLE_HANDLE "xmlconsole" +#define JABBER_XMLCONSOLE_HANDLE "_xmlconsole" #define JABBER_OAUTH_HANDLE "jabber_oauth" /* Prefixes to use for packet IDs (mainly for IQ packets ATM). Usually the @@ -226,6 +226,7 @@ struct jabber_transfer #define XMLNS_TIME_OLD "jabber:iq:time" /* XEP-0090 */ #define XMLNS_TIME "urn:xmpp:time" /* XEP-0202 */ #define XMLNS_PING "urn:xmpp:ping" /* XEP-0199 */ +#define XMLNS_RECEIPTS "urn:xmpp:receipts" /* XEP-0184 */ #define XMLNS_VCARD "vcard-temp" /* XEP-0054 */ #define XMLNS_DELAY "jabber:x:delay" /* XEP-0091 */ #define XMLNS_XDATA "jabber:x:data" /* XEP-0004 */ diff --git a/protocols/jabber/message.c b/protocols/jabber/message.c index 85c71c9d..1c832bee 100644 --- a/protocols/jabber/message.c +++ b/protocols/jabber/message.c @@ -3,7 +3,7 @@ * BitlBee - An IRC to IM gateway * * Jabber module - Handling of message(s) (tags), etc * * * -* Copyright 2006 Wilmer van der Gaast <wilmer@gaast.net> * +* Copyright 2006-2012 Wilmer van der Gaast <wilmer@gaast.net> * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -28,12 +28,34 @@ xt_status jabber_pkt_message( struct xt_node *node, gpointer data ) struct im_connection *ic = data; char *from = xt_find_attr( node, "from" ); char *type = xt_find_attr( node, "type" ); + char *id = xt_find_attr( node, "id" ); struct xt_node *body = xt_find_node( node->children, "body" ), *c; + struct xt_node *request = xt_find_node( node->children, "request" ); struct jabber_buddy *bud = NULL; char *s, *room = NULL, *reason = NULL; if( !from ) return XT_HANDLED; /* Consider this packet corrupted. */ + + if( request && id ) + { + /* Send a message receipt (XEP-0184), looking like this: + * <message + * from='kingrichard@royalty.england.lit/throne' + * id='bi29sg183b4v' + * to='northumberland@shakespeare.lit/westminster'> + * <received xmlns='urn:xmpp:receipts' id='richard2-4.1.247'/> + * </message> */ + struct xt_node *received, *receipt; + + received = xt_new_node( "received", NULL, NULL ); + xt_add_attr( received, "xmlns", XMLNS_RECEIPTS ); + xt_add_attr( received, "id", id ); + receipt = jabber_make_packet( "message", NULL, from, received ); + + jabber_write_packet( ic, receipt ); + xt_free_node( receipt ); + } bud = jabber_buddy_by_jid( ic, from, GET_BUDDY_EXACT ); diff --git a/protocols/jabber/sasl.c b/protocols/jabber/sasl.c index f25d44c4..450b5b28 100644 --- a/protocols/jabber/sasl.c +++ b/protocols/jabber/sasl.c @@ -3,7 +3,7 @@ * BitlBee - An IRC to IM gateway * * Jabber module - SASL authentication * * * -* Copyright 2006 Wilmer van der Gaast <wilmer@gaast.net> * +* Copyright 2006-2012 Wilmer van der Gaast <wilmer@gaast.net> * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -386,6 +386,7 @@ xt_status sasl_pkt_challenge( struct xt_node *node, gpointer data ) else { /* We found rspauth, but don't really care... */ + g_free( s ); } s = reply ? tobase64( reply ) : NULL; diff --git a/protocols/jabber/si.c b/protocols/jabber/si.c index 4b0e57c4..f5f3b2fe 100644 --- a/protocols/jabber/si.c +++ b/protocols/jabber/si.c @@ -292,9 +292,11 @@ int jabber_si_handle_request( struct im_connection *ic, struct xt_node *node, st requestok = FALSE; } - *s = '/'; + if( s ) + *s = '/'; } - else + + if( !requestok ) { reply = jabber_make_error_packet( node, "item-not-found", "cancel", NULL ); if (!jabber_write_packet( ic, reply )) diff --git a/protocols/msn/Makefile b/protocols/msn/Makefile index 49b8d597..417bab78 100644 --- a/protocols/msn/Makefile +++ b/protocols/msn/Makefile @@ -37,7 +37,7 @@ $(objects): ../../Makefile.settings Makefile $(objects): %.o: $(_SRCDIR_)%.c @echo '*' Compiling $< - @$(CC) -c $(CFLAGS) $< -o $@ + @$(CC) -c $(CFLAGS) $(CFLAGS_BITLBEE) $< -o $@ msn_mod.o: $(objects) @echo '*' Linking msn_mod.o diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index b1bd4b0a..ad01ca24 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2010 Wilmer van der Gaast and others * + * Copyright 2002-2013 Wilmer van der Gaast and others * \********************************************************************/ /* MSN module - Main file; functions to be called from BitlBee */ @@ -43,7 +43,8 @@ static void msn_init( account_t *acc ) set_add( &acc->set, "mail_notifications", "false", set_eval_bool, acc ); set_add( &acc->set, "switchboard_keepalives", "false", set_eval_bool, acc ); - acc->flags |= ACC_FLAG_AWAY_MESSAGE | ACC_FLAG_STATUS_MESSAGE; + acc->flags |= ACC_FLAG_AWAY_MESSAGE | ACC_FLAG_STATUS_MESSAGE | + ACC_FLAG_HANDLE_DOMAINS; } static void msn_login( account_t *acc ) @@ -52,6 +53,7 @@ static void msn_login( account_t *acc ) struct msn_data *md = g_new0( struct msn_data, 1 ); ic->proto_data = md; + ic->flags |= OPT_PONGS | OPT_PONGED; if( strchr( acc->user, '@' ) == NULL ) { @@ -97,6 +99,7 @@ static void msn_logout( struct im_connection *ic ) g_free( md->tokens[i] ); g_free( md->lock_key ); g_free( md->pp_policy ); + g_free( md->uuid ); while( md->groups ) { @@ -138,6 +141,8 @@ static void msn_logout( struct im_connection *ic ) static int msn_buddy_msg( struct im_connection *ic, char *who, char *message, int away ) { + struct bee_user *bu = bee_user_by_handle( ic->bee, ic, who ); + struct msn_buddy_data *bd = bu ? bu->data : NULL; struct msn_switchboard *sb; #ifdef DEBUG @@ -147,7 +152,11 @@ static int msn_buddy_msg( struct im_connection *ic, char *who, char *message, in } else #endif - if( ( sb = msn_sb_by_handle( ic, who ) ) ) + if( bd && bd->flags & MSN_BUDDY_FED ) + { + msn_ns_sendmessage( ic, bu, message ); + } + else if( ( sb = msn_sb_by_handle( ic, who ) ) ) { return( msn_sb_sendmessage( sb, message ) ); } @@ -189,11 +198,29 @@ static void msn_set_away( struct im_connection *ic, char *state, char *message ) else if( ( md->away_state = msn_away_state_by_name( state ) ) == NULL ) md->away_state = msn_away_state_list + 1; - if( !msn_ns_write( ic, -1, "CHG %d %s\r\n", ++md->trId, md->away_state->code ) ) + if( !msn_ns_write( ic, -1, "CHG %d %s %d:%02d\r\n", ++md->trId, md->away_state->code, MSN_CAP1, MSN_CAP2 ) ) return; - uux = g_markup_printf_escaped( "<Data><PSM>%s</PSM><CurrentMedia></CurrentMedia>" - "</Data>", message ? message : "" ); + uux = g_markup_printf_escaped( "<EndpointData><Capabilities>%d:%02d" + "</Capabilities></EndpointData>", + MSN_CAP1, MSN_CAP2 ); + msn_ns_write( ic, -1, "UUX %d %zd\r\n%s", ++md->trId, strlen( uux ), uux ); + g_free( uux ); + + uux = g_markup_printf_escaped( "<PrivateEndpointData><EpName>%s</EpName>" + "<Idle>%s</Idle><ClientType>%d</ClientType>" + "<State>%s</State></PrivateEndpointData>", + md->uuid, + strcmp( md->away_state->code, "IDL" ) ? "false" : "true", + 1, /* ? */ + md->away_state->code ); + msn_ns_write( ic, -1, "UUX %d %zd\r\n%s", ++md->trId, strlen( uux ), uux ); + g_free( uux ); + + uux = g_markup_printf_escaped( "<Data><DDP></DDP><PSM>%s</PSM>" + "<CurrentMedia></CurrentMedia>" + "<MachineGuid>%s</MachineGuid></Data>", + message ? message : "", md->uuid ); msn_ns_write( ic, -1, "UUX %d %zd\r\n%s", ++md->trId, strlen( uux ), uux ); g_free( uux ); } @@ -231,13 +258,9 @@ static void msn_chat_msg( struct groupchat *c, char *message, int flags ) static void msn_chat_invite( struct groupchat *c, char *who, char *message ) { struct msn_switchboard *sb = msn_sb_by_chat( c ); - char buf[1024]; if( sb ) - { - g_snprintf( buf, sizeof( buf ), "CAL %d %s\r\n", ++sb->trId, who ); - msn_sb_write( sb, buf, strlen( buf ) ); - } + msn_sb_write( sb, "CAL %d %s\r\n", ++sb->trId, who ); } static void msn_chat_leave( struct groupchat *c ) @@ -245,7 +268,7 @@ static void msn_chat_leave( struct groupchat *c ) struct msn_switchboard *sb = msn_sb_by_chat( c ); if( sb ) - msn_sb_write( sb, "OUT\r\n", 5 ); + msn_sb_write( sb, "OUT\r\n" ); } static struct groupchat *msn_chat_with( struct im_connection *ic, char *who ) @@ -339,8 +362,27 @@ static char *set_eval_display_name( set_t *set, char *value ) static void msn_buddy_data_add( bee_user_t *bu ) { struct msn_data *md = bu->ic->proto_data; - bu->data = g_new0( struct msn_buddy_data, 1 ); + struct msn_buddy_data *bd; + char *handle; + + bd = bu->data = g_new0( struct msn_buddy_data, 1 ); g_tree_insert( md->domaintree, bu->handle, bu ); + + for( handle = bu->handle; isdigit( *handle ); handle ++ ); + if( *handle == ':' ) + { + /* Pass a nick hint so hopefully the stupid numeric prefix + won't show up to the user. */ + char *s = strchr( ++handle, '@' ); + if( s ) + { + handle = g_strndup( handle, s - handle ); + imcb_buddy_nick_hint( bu->ic, bu->handle, handle ); + g_free( handle ); + } + + bd->flags |= MSN_BUDDY_FED; + } } static void msn_buddy_data_free( bee_user_t *bu ) diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h index bf7cdfa8..eb5f7dd8 100644 --- a/protocols/msn/msn.h +++ b/protocols/msn/msn.h @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2010 Wilmer van der Gaast and others * + * Copyright 2002-2012 Wilmer van der Gaast and others * \********************************************************************/ /* MSN module */ @@ -52,13 +52,21 @@ #define MSNP11_PROD_ID "PROD01065C%ZFN6F" */ +/* <= BitlBee 3.0.5 #define MSNP11_PROD_KEY "ILTXC!4IXB5FB*PX" #define MSNP11_PROD_ID "PROD0119GSJUC$18" -#define MSNP_VER "MSNP15" -#define MSNP_BUILD "8.5.1288" +*/ + +#define MSNP11_PROD_KEY "C1BX{V4W}Q3*10SM" +#define MSNP11_PROD_ID "PROD0120PW!CCV9@" +#define MSNP_VER "MSNP18" +#define MSNP_BUILD "14.0.8117.416" #define MSN_SB_NEW -24062002 +#define MSN_CAP1 0xC000 +#define MSN_CAP2 0x0000 + #define MSN_MESSAGE_HEADERS "MIME-Version: 1.0\r\n" \ "Content-Type: text/plain; charset=UTF-8\r\n" \ "User-Agent: BitlBee " BITLBEE_VERSION "\r\n" \ @@ -117,6 +125,7 @@ struct msn_data int trId; char *tokens[4]; char *lock_key, *pp_policy; + char *uuid; GSList *msgq, *grpq, *soapq; GSList *switchboards; @@ -188,6 +197,7 @@ typedef enum MSN_BUDDY_RL = 8, MSN_BUDDY_PL = 16, MSN_BUDDY_ADL_SYNCED = 256, + MSN_BUDDY_FED = 512, } msn_buddy_flags_t; struct msn_buddy_data @@ -221,15 +231,16 @@ extern GSList *msn_connections; extern GSList *msn_switchboards; /* ns.c */ -int msn_ns_write( struct im_connection *ic, int fd, const char *fmt, ... ); +int msn_ns_write( struct im_connection *ic, int fd, const char *fmt, ... ) G_GNUC_PRINTF( 3, 4 ); gboolean msn_ns_connect( struct im_connection *ic, struct msn_handler_data *handler, const char *host, int port ); void msn_ns_close( struct msn_handler_data *handler ); void msn_auth_got_passport_token( struct im_connection *ic, const char *token, const char *error ); void msn_auth_got_contact_list( struct im_connection *ic ); int msn_ns_finish_login( struct im_connection *ic ); +int msn_ns_sendmessage( struct im_connection *ic, struct bee_user *bu, const char *text ); +void msn_ns_oim_send_queue( struct im_connection *ic, GSList **msgq ); /* msn_util.c */ -int msn_logged_in( struct im_connection *ic ); int msn_buddy_list_add( struct im_connection *ic, msn_buddy_flags_t list, const char *who, const char *realname_, const char *group ); int msn_buddy_list_remove( struct im_connection *ic, msn_buddy_flags_t list, const char *who, const char *group ); void msn_buddy_ask( bee_user_t *bu ); @@ -241,6 +252,7 @@ gint msn_domaintree_cmp( gconstpointer a_, gconstpointer b_ ); struct msn_group *msn_group_by_name( struct im_connection *ic, const char *name ); struct msn_group *msn_group_by_id( struct im_connection *ic, const char *id ); int msn_ns_set_display_name( struct im_connection *ic, const char *value ); +const char *msn_normalize_handle( const char *handle ); /* tables.c */ const struct msn_away_state *msn_away_state_by_number( int number ); @@ -249,9 +261,9 @@ const struct msn_away_state *msn_away_state_by_name( char *name ); const struct msn_status_code *msn_status_by_number( int number ); /* sb.c */ -int msn_sb_write( struct msn_switchboard *sb, const char *fmt, ... ); +int msn_sb_write( struct msn_switchboard *sb, const char *fmt, ... ) G_GNUC_PRINTF( 2, 3 );; struct msn_switchboard *msn_sb_create( struct im_connection *ic, char *host, int port, char *key, int session ); -struct msn_switchboard *msn_sb_by_handle( struct im_connection *ic, char *handle ); +struct msn_switchboard *msn_sb_by_handle( struct im_connection *ic, const char *handle ); struct msn_switchboard *msn_sb_by_chat( struct groupchat *c ); struct msn_switchboard *msn_sb_spare( struct im_connection *ic ); int msn_sb_sendmessage( struct msn_switchboard *sb, char *text ); diff --git a/protocols/msn/msn_util.c b/protocols/msn/msn_util.c index d5a74a47..c6afd29a 100644 --- a/protocols/msn/msn_util.c +++ b/protocols/msn/msn_util.c @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2010 Wilmer van der Gaast and others * + * Copyright 2002-2012 Wilmer van der Gaast and others * \********************************************************************/ /* MSN module - Miscellaneous utilities */ @@ -29,13 +29,6 @@ #include "soap.h" #include <ctype.h> -int msn_logged_in( struct im_connection *ic ) -{ - imcb_connected( ic ); - - return( 0 ); -} - static char *adlrml_entry( const char *handle_, msn_buddy_flags_t list ) { char *domain, handle[strlen(handle_)+1]; @@ -536,3 +529,11 @@ int msn_ns_set_display_name( struct im_connection *ic, const char *value ) and won't give proper feedback yet if it doesn't. */ return msn_ns_write( ic, -1, "PRP %d MFN %s\r\n", ++md->trId, fn ); } + +const char *msn_normalize_handle( const char *handle ) +{ + if( strncmp( handle, "1:", 2 ) == 0 ) + return handle + 2; + else + return handle; +} diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index 5436270e..7acf4654 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2010 Wilmer van der Gaast and others * + * Copyright 2002-2012 Wilmer van der Gaast and others * \********************************************************************/ /* MSN module - Notification server callbacks */ @@ -24,9 +24,11 @@ */ #include <ctype.h> +#include <sys/utsname.h> #include "nogaim.h" #include "msn.h" #include "md5.h" +#include "sha1.h" #include "soap.h" #include "xmltree.h" @@ -110,6 +112,23 @@ static gboolean msn_ns_connected( gpointer data, gint source, b_input_condition handler->rxlen = 0; handler->rxq = g_new0( char, 1 ); + if( md->uuid == NULL ) + { + struct utsname name; + sha1_state_t sha[1]; + + /* UUID == SHA1("BitlBee" + my hostname + MSN username) */ + sha1_init( sha ); + sha1_append( sha, (void*) "BitlBee", 7 ); + if( uname( &name ) == 0 ) + { + sha1_append( sha, (void*) name.nodename, strlen( name.nodename ) ); + } + sha1_append( sha, (void*) ic->acc->user, strlen( ic->acc->user ) ); + md->uuid = sha1_random_uuid( sha ); + memcpy( md->uuid, "b171be3e", 8 ); /* :-P */ + } + if( msn_ns_write( ic, source, "VER %d %s CVR0\r\n", ++md->trId, MSNP_VER ) ) { handler->inpa = b_input_add( handler->fd, B_EV_IO_READ, msn_ns_callback, handler ); @@ -352,9 +371,11 @@ static int msn_ns_command( struct msn_handler_data *handler, char **cmd, int num g_free( resp ); return st; } - else if( strcmp( cmd[0], "ILN" ) == 0 ) + else if( strcmp( cmd[0], "ILN" ) == 0 || strcmp( cmd[0], "NLN" ) == 0 ) { const struct msn_away_state *st; + const char *handle; + int cap = 0; if( num_parts < 6 ) { @@ -362,59 +383,45 @@ static int msn_ns_command( struct msn_handler_data *handler, char **cmd, int num imc_logout( ic, TRUE ); return( 0 ); } + /* ILN and NLN are more or less the same, except ILN has a trId + at the start, and NLN has a capability field at the end. + Does ILN still exist BTW? */ + if( cmd[0][1] == 'I' ) + cmd ++; + else + cap = atoi( cmd[4] ); + + handle = msn_normalize_handle( cmd[2] ); + if( strcmp( handle, ic->acc->user ) == 0 ) + return 1; /* That's me! */ - http_decode( cmd[5] ); - imcb_rename_buddy( ic, cmd[3], cmd[5] ); + http_decode( cmd[3] ); + imcb_rename_buddy( ic, handle, cmd[3] ); - st = msn_away_state_by_code( cmd[2] ); + st = msn_away_state_by_code( cmd[1] ); if( !st ) { /* FIXME: Warn/Bomb about unknown away state? */ st = msn_away_state_list + 1; } - imcb_buddy_status( ic, cmd[3], OPT_LOGGED_IN | - ( st != msn_away_state_list ? OPT_AWAY : 0 ), + imcb_buddy_status( ic, handle, OPT_LOGGED_IN | + ( st != msn_away_state_list ? OPT_AWAY : 0 ) | + ( cap & 1 ? OPT_MOBILE : 0 ), st->name, NULL ); + + msn_sb_stop_keepalives( msn_sb_by_handle( ic, handle ) ); } else if( strcmp( cmd[0], "FLN" ) == 0 ) { + const char *handle; + if( cmd[1] == NULL ) return 1; - imcb_buddy_status( ic, cmd[1], 0, NULL, NULL ); - - msn_sb_start_keepalives( msn_sb_by_handle( ic, cmd[1] ), TRUE ); - } - else if( strcmp( cmd[0], "NLN" ) == 0 ) - { - const struct msn_away_state *st; - int cap; - - if( num_parts < 6 ) - { - imcb_error( ic, "Syntax error" ); - imc_logout( ic, TRUE ); - return( 0 ); - } - - http_decode( cmd[4] ); - cap = atoi( cmd[5] ); - imcb_rename_buddy( ic, cmd[2], cmd[4] ); - - st = msn_away_state_by_code( cmd[1] ); - if( !st ) - { - /* FIXME: Warn/Bomb about unknown away state? */ - st = msn_away_state_list + 1; - } - - imcb_buddy_status( ic, cmd[2], OPT_LOGGED_IN | - ( st != msn_away_state_list ? OPT_AWAY : 0 ) | - ( cap & 1 ? OPT_MOBILE : 0 ), - st->name, NULL ); - - msn_sb_stop_keepalives( msn_sb_by_handle( ic, cmd[2] ) ); + handle = msn_normalize_handle( cmd[1] ); + imcb_buddy_status( ic, handle, 0, NULL, NULL ); + msn_sb_start_keepalives( msn_sb_by_handle( ic, handle ), TRUE ); } else if( strcmp( cmd[0], "RNG" ) == 0 ) { @@ -461,7 +468,7 @@ static int msn_ns_command( struct msn_handler_data *handler, char **cmd, int num } else { - sb->who = g_strdup( cmd[5] ); + sb->who = g_strdup( msn_normalize_handle( cmd[5] ) ); } } else if( strcmp( cmd[0], "OUT" ) == 0 ) @@ -554,8 +561,8 @@ static int msn_ns_command( struct msn_handler_data *handler, char **cmd, int num else if( strcmp( cmd[0], "UBX" ) == 0 ) { /* Status message. */ - if( num_parts >= 4 ) - handler->msglen = atoi( cmd[3] ); + if( num_parts >= 3 ) + handler->msglen = atoi( cmd[2] ); } else if( strcmp( cmd[0], "NOT" ) == 0 ) { @@ -564,6 +571,15 @@ static int msn_ns_command( struct msn_handler_data *handler, char **cmd, int num if( num_parts >= 2 ) handler->msglen = atoi( cmd[1] ); } + else if( strcmp( cmd[0], "UBM" ) == 0 ) + { + if( num_parts >= 7 ) + handler->msglen = atoi( cmd[6] ); + } + else if( strcmp( cmd[0], "QNG" ) == 0 ) + { + ic->flags |= OPT_PONGED; + } else if( isdigit( cmd[0][0] ) ) { int num = atoi( cmd[0] ); @@ -667,7 +683,57 @@ static int msn_ns_message( struct msn_handler_data *handler, char *msg, int msgl } else if( g_strncasecmp( ct, "text/x-msmsgsactivemailnotification", 35 ) == 0 ) { - /* Sorry, but this one really is *USELESS* */ + } + else if( g_strncasecmp( ct, "text/x-msmsgsinitialmdatanotification", 37 ) == 0 || + g_strncasecmp( ct, "text/x-msmsgsoimnotification", 28 ) == 0 ) + { + /* We received an offline message. Or at least notification + that there is one waiting for us. Fetching the message(s) + and purging them from the server is a lot of SOAPy work + not worth doing IMHO. Also I thought it was possible to + have the notification server send them directly, I was + pretty sure I saw Pidgin do it.. + + At least give a notification for now, seems like a + reasonable thing to do. Only problem is, they'll keep + coming back at login time until you read them using a + different client. :-( */ + + char *xml = get_rfc822_header( body, "Mail-Data:", blen ); + struct xt_node *md, *m; + + if( !xml ) + return 1; + md = xt_from_string( xml, 0 ); + if( !md ) + return 1; + + for( m = md->children; ( m = xt_find_node( m, "M" ) ); m = m->next ) + { + struct xt_node *e = xt_find_node( m->children, "E" ); + struct xt_node *rt = xt_find_node( m->children, "RT" ); + struct tm tp; + time_t msgtime = 0; + + if( !e || !e->text ) + continue; + + memset( &tp, 0, sizeof( tp ) ); + if( rt && rt->text && + sscanf( rt->text, "%4d-%2d-%2dT%2d:%2d:%2d.", + &tp.tm_year, &tp.tm_mon, &tp.tm_mday, + &tp.tm_hour, &tp.tm_min, &tp.tm_sec ) == 6 ) + { + tp.tm_year -= 1900; + tp.tm_mon --; + msgtime = mktime_utc( &tp ); + + } + imcb_buddy_msg( ic, e->text, "<< \002BitlBee\002 - Received offline message. BitlBee can't show these. >>", 0, msgtime ); + } + + g_free( xml ); + xt_free_node( md ); } else { @@ -682,19 +748,19 @@ static int msn_ns_message( struct msn_handler_data *handler, char *msg, int msgl struct xt_node *ubx, *psm; char *psm_text = NULL; - ubx = xt_from_string( msg ); + ubx = xt_from_string( msg, msglen ); if( ubx && strcmp( ubx->name, "Data" ) == 0 && ( psm = xt_find_node( ubx->children, "PSM" ) ) ) psm_text = psm->text; - imcb_buddy_status_msg( ic, cmd[1], psm_text ); + imcb_buddy_status_msg( ic, msn_normalize_handle( cmd[1] ), psm_text ); xt_free_node( ubx ); } else if( strcmp( cmd[0], "ADL" ) == 0 ) { struct xt_node *adl, *d, *c; - if( !( adl = xt_from_string( msg ) ) ) + if( !( adl = xt_from_string( msg, msglen ) ) ) return 1; for( d = adl->children; d; d = d->next ) @@ -715,6 +781,8 @@ static int msn_ns_message( struct msn_handler_data *handler, char *msg, int msgl ( cn = xt_find_attr( c, "n" ) ) == NULL ) continue; + /* FIXME: Use "t" here, guess I should just add it + as a prefix like elsewhere in the protocol. */ handle = g_strdup_printf( "%s@%s", cn, dn ); if( !( ( bu = bee_user_by_handle( ic->bee, ic, handle ) ) || ( bu = bee_user_new( ic->bee, ic, handle, 0 ) ) ) ) @@ -740,8 +808,37 @@ static int msn_ns_message( struct msn_handler_data *handler, char *msg, int msgl } } } + else if( strcmp( cmd[0], "UBM" ) == 0 ) + { + /* This one will give us msgs from federated networks. Technically + it should also get us offline messages, but I don't know how + I can signal MSN servers to use it. */ + char *ct, *handle; + + if( strcmp( cmd[1], ic->acc->user ) == 0 ) + { + /* With MPOP, you'll get copies of your own msgs from other + sessions. Discard those at least for now. */ + return 1; + } + + ct = get_rfc822_header( msg, "Content-Type", msglen ); + if( strncmp( ct, "text/plain", 10 ) != 0 ) + { + /* Typing notification or something? */ + g_free( ct ); + return 1; + } + if( strcmp( cmd[2], "1" ) != 0 ) + handle = g_strdup_printf( "%s:%s", cmd[2], cmd[1] ); + else + handle = g_strdup( cmd[1] ); + + imcb_buddy_msg( ic, handle, body, 0, 0 ); + g_free( handle ); + } - return( 1 ); + return 1; } void msn_auth_got_passport_token( struct im_connection *ic, const char *token, const char *error ) @@ -756,7 +853,7 @@ void msn_auth_got_passport_token( struct im_connection *ic, const char *token, c if( token ) { - msn_ns_write( ic, -1, "USR %d SSO S %s %s\r\n", ++md->trId, md->tokens[0], token ); + msn_ns_write( ic, -1, "USR %d SSO S %s %s {%s}\r\n", ++md->trId, md->tokens[0], token, md->uuid ); } else { @@ -808,7 +905,7 @@ static gboolean msn_ns_send_adl_1( gpointer key, gpointer value, gpointer data ) c = xt_new_node( "c", NULL, NULL ); xt_add_attr( c, "n", handle ); xt_add_attr( c, "l", l ); - xt_add_attr( c, "t", "1" ); /* 1 means normal, 4 means mobile? */ + xt_add_attr( c, "t", "1" ); /* FIXME: Network type, i.e. 32 for Y!MSG */ xt_insert_child( d, c ); /* Do this in batches of 100. */ @@ -885,3 +982,60 @@ int msn_ns_finish_login( struct im_connection *ic ) return 1; } + +int msn_ns_sendmessage( struct im_connection *ic, bee_user_t *bu, const char *text ) +{ + struct msn_data *md = ic->proto_data; + int type = 0; + char *buf, *handle; + + if( strncmp( text, "\r\r\r", 3 ) == 0 ) + /* Err. Shouldn't happen but I guess it can. Don't send others + any of the "SHAKE THAT THING" messages. :-D */ + return 1; + + /* This might be a federated contact. Get its network number, + prefixed to bu->handle with a colon. Default is 1. */ + for( handle = bu->handle; isdigit( *handle ); handle ++ ) + type = type * 10 + *handle - '0'; + if( *handle == ':' ) + handle ++; + else + type = 1; + + buf = g_strdup_printf( "%s%s", MSN_MESSAGE_HEADERS, text ); + + if( msn_ns_write( ic, -1, "UUM %d %s %d %d %zd\r\n%s", + ++md->trId, handle, type, + 1, /* type == IM (not nudge/typing) */ + strlen( buf ), buf ) ) + return 1; + else + return 0; +} + +void msn_ns_oim_send_queue( struct im_connection *ic, GSList **msgq ) +{ + GSList *l; + + for( l = *msgq; l; l = l->next ) + { + struct msn_message *m = l->data; + bee_user_t *bu = bee_user_by_handle( ic->bee, ic, m->who ); + + if( bu ) + if( !msn_ns_sendmessage( ic, bu, m->text ) ) + return; + } + + while( *msgq != NULL ) + { + struct msn_message *m = (*msgq)->data; + + g_free( m->who ); + g_free( m->text ); + g_free( m ); + + *msgq = g_slist_remove( *msgq, m ); + } +} diff --git a/protocols/msn/sb.c b/protocols/msn/sb.c index 45e74cb0..1cd1c743 100644 --- a/protocols/msn/sb.c +++ b/protocols/msn/sb.c @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2010 Wilmer van der Gaast and others * + * Copyright 2002-2012 Wilmer van der Gaast and others * \********************************************************************/ /* MSN module - Switchboard server callbacks and utilities */ @@ -121,7 +121,7 @@ struct msn_switchboard *msn_sb_create( struct im_connection *ic, char *host, int return( sb ); } -struct msn_switchboard *msn_sb_by_handle( struct im_connection *ic, char *handle ) +struct msn_switchboard *msn_sb_by_handle( struct im_connection *ic, const char *handle ) { struct msn_data *md = ic->proto_data; struct msn_switchboard *sb; @@ -307,6 +307,7 @@ gboolean msn_sb_connected( gpointer data, gint source, b_input_condition cond ) { struct msn_switchboard *sb = data; struct im_connection *ic; + struct msn_data *md; char buf[1024]; /* Are we still alive? */ @@ -314,6 +315,7 @@ gboolean msn_sb_connected( gpointer data, gint source, b_input_condition cond ) return FALSE; ic = sb->ic; + md = ic->proto_data; if( source != sb->fd ) { @@ -331,9 +333,9 @@ gboolean msn_sb_connected( gpointer data, gint source, b_input_condition cond ) sb->handler->exec_message = msn_sb_message; if( sb->session == MSN_SB_NEW ) - g_snprintf( buf, sizeof( buf ), "USR %d %s %s\r\n", ++sb->trId, ic->acc->user, sb->key ); + g_snprintf( buf, sizeof( buf ), "USR %d %s;{%s} %s\r\n", ++sb->trId, ic->acc->user, md->uuid, sb->key ); else - g_snprintf( buf, sizeof( buf ), "ANS %d %s %s %d\r\n", ++sb->trId, ic->acc->user, sb->key, sb->session ); + g_snprintf( buf, sizeof( buf ), "ANS %d %s;{%s} %s %d\r\n", ++sb->trId, ic->acc->user, md->uuid, sb->key, sb->session ); if( msn_sb_write( sb, "%s", buf ) ) sb->inp = b_input_add( sb->fd, B_EV_IO_READ, msn_sb_callback, sb ); @@ -452,18 +454,31 @@ static int msn_sb_command( struct msn_handler_data *handler, char **cmd, int num { char buf[1024]; - if( num == 1 ) + /* For as much as I understand this MPOP stuff now, a + switchboard has two (or more) roster entries per + participant. One "bare JID" and one JID;UUID. Ignore + the latter. */ + if( !strchr( cmd[4], ';' ) ) { - g_snprintf( buf, sizeof( buf ), "MSN groupchat session %d", sb->session ); - sb->chat = imcb_chat_new( ic, buf ); + /* HACK: Since even 1:1 chats now have >2 participants + (ourselves included) it gets hard to tell them apart + from rooms. Let's hope this is enough: */ + if( sb->chat == NULL && num != tot ) + { + g_snprintf( buf, sizeof( buf ), "MSN groupchat session %d", sb->session ); + sb->chat = imcb_chat_new( ic, buf ); + + g_free( sb->who ); + sb->who = NULL; + } - g_free( sb->who ); - sb->who = NULL; + if( sb->chat ) + imcb_chat_add_buddy( sb->chat, cmd[4] ); } - imcb_chat_add_buddy( sb->chat, cmd[4] ); - - if( num == tot ) + /* We have the full roster, start showing the channel to + the user. */ + if( num == tot && sb->chat ) { imcb_chat_add_buddy( sb->chat, ic->acc->user ); } @@ -506,6 +521,10 @@ static int msn_sb_command( struct msn_handler_data *handler, char **cmd, int num return( 0 ); } + /* See IRO above. Handle "bare JIDs" only. */ + if( strchr( cmd[1], ';' ) ) + return 1; + if( sb->who && g_strcasecmp( cmd[1], sb->who ) == 0 ) { /* The user we wanted to talk to is finally there, let's send the queued messages then. */ @@ -540,6 +559,10 @@ static int msn_sb_command( struct msn_handler_data *handler, char **cmd, int num return( st ); } + else if( strcmp( cmd[1], ic->acc->user ) == 0 ) + { + /* Well, gee thanks. Thanks for letting me know I've arrived.. */ + } else if( sb->who ) { debug( "Converting chat with %s to a groupchat because %s joined the session.", sb->who, cmd[1] ); @@ -612,7 +635,7 @@ static int msn_sb_command( struct msn_handler_data *handler, char **cmd, int num as a spare for a next conversation sounds more sane to me. The server will clean it up when it's idle for too long. */ } - else if( sb->chat ) + else if( sb->chat && !strchr( cmd[1], ';' ) ) { imcb_chat_remove_buddy( sb->chat, cmd[1], "" ); } @@ -628,12 +651,9 @@ static int msn_sb_command( struct msn_handler_data *handler, char **cmd, int num /* If the person is offline, send an offline message instead, and don't report an error. */ - /* TODO: Support for OIMs that works. (#874) */ - /* if( num == 217 ) - msn_soap_oim_send_queue( ic, &sb->msgq ); + msn_ns_oim_send_queue( ic, &sb->msgq ); else - */ imcb_error( ic, "Error reported by switchboard server: %s", err->text ); if( err->flags & STATUS_SB_FATAL ) diff --git a/protocols/msn/soap.c b/protocols/msn/soap.c index da32c291..b994172b 100644 --- a/protocols/msn/soap.c +++ b/protocols/msn/soap.c @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2010 Wilmer van der Gaast and others * + * Copyright 2002-2012 Wilmer van der Gaast and others * \********************************************************************/ /* MSN module - All the SOAPy XML stuff. @@ -228,7 +228,7 @@ static void msn_soap_debug_print( const char *headers, const char *payload ) if( payload ) { - struct xt_node *xt = xt_from_string( payload ); + struct xt_node *xt = xt_from_string( payload, 0 ); if( xt ) xt_print( xt ); xt_free_node( xt ); diff --git a/protocols/msn/soap.h b/protocols/msn/soap.h index d6a1f75e..cb731ea7 100644 --- a/protocols/msn/soap.h +++ b/protocols/msn/soap.h @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2010 Wilmer van der Gaast and others * + * Copyright 2002-2012 Wilmer van der Gaast and others * \********************************************************************/ /* MSN module - All the SOAPy XML stuff. diff --git a/protocols/nogaim.c b/protocols/nogaim.c index 773e3877..2f75a7b8 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2010 Wilmer van der Gaast and others * + * Copyright 2002-2012 Wilmer van der Gaast and others * \********************************************************************/ /* @@ -260,12 +260,32 @@ static gboolean send_keepalive( gpointer d, gint fd, b_input_condition cond ) { struct im_connection *ic = d; + if( ( ic->flags & OPT_PONGS ) && !( ic->flags & OPT_PONGED ) ) + { + /* This protocol is expected to ack keepalives and hasn't + since the last time we were here. */ + imcb_error( ic, "Connection timeout" ); + imc_logout( ic, TRUE ); + return FALSE; + } + ic->flags &= ~OPT_PONGED; + if( ic->acc->prpl->keepalive ) ic->acc->prpl->keepalive( ic ); return TRUE; } +void start_keepalives( struct im_connection *ic, int interval ) +{ + b_event_remove( ic->keepalive ); + ic->keepalive = b_timeout_add( interval, send_keepalive, ic ); + + /* Connecting successfully counts as a first successful pong. */ + if( ic->flags & OPT_PONGS ) + ic->flags |= OPT_PONGED; +} + void imcb_connected( struct im_connection *ic ) { /* MSN servers sometimes redirect you to a different server and do @@ -276,9 +296,8 @@ void imcb_connected( struct im_connection *ic ) imcb_log( ic, "Logged in" ); - b_event_remove( ic->keepalive ); - ic->keepalive = b_timeout_add( 60000, send_keepalive, ic ); ic->flags |= OPT_LOGGED_IN; + start_keepalives( ic, 60000 ); /* Necessary to send initial presence status, even if we're not away. */ imc_away_send_update( ic ); diff --git a/protocols/nogaim.h b/protocols/nogaim.h index a98b7054..3fd940b5 100644 --- a/protocols/nogaim.h +++ b/protocols/nogaim.h @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2010 Wilmer van der Gaast and others * + * Copyright 2002-2012 Wilmer van der Gaast and others * \********************************************************************/ /* @@ -15,7 +15,7 @@ * * Copyright (C) 1998-1999, Mark Spencer <markster@marko.net> * (and possibly other members of the Gaim team) - * Copyright 2002-2007 Wilmer van der Gaast <wilmer@gaast.net> + * Copyright 2002-2012 Wilmer van der Gaast <wilmer@gaast.net> */ /* @@ -67,6 +67,8 @@ #define OPT_TYPING 0x00000100 /* Some pieces of code make assumptions */ #define OPT_THINKING 0x00000200 /* about these values... Stupid me! */ #define OPT_NOOTR 0x00001000 /* protocol not suitable for OTR */ +#define OPT_PONGS 0x00010000 /* Service sends us keep-alives */ +#define OPT_PONGED 0x00020000 /* Received a keep-alive during last interval */ /* ok. now the fun begins. first we create a connection structure */ struct im_connection @@ -87,11 +89,8 @@ struct im_connection GSList *deny; int permdeny; - char displayname[128]; char *away; - int evil; - /* BitlBee */ bee_t *bee; @@ -126,7 +125,6 @@ struct buddy { char name[80]; char show[BUDDY_ALIAS_MAXLEN]; int present; - int evil; time_t signon; time_t idle; int uc; @@ -197,7 +195,7 @@ struct prpl { void (* add_deny) (struct im_connection *, char *who); void (* rem_permit) (struct im_connection *, char *who); void (* rem_deny) (struct im_connection *, char *who); - /* Doesn't actually have UI hooks. */ + /* Doesn't actually have UI hooks. Not used at all, can be removed. */ void (* set_permit_deny)(struct im_connection *); /* Request profile info. Free-formatted stuff, the IM module gives back diff --git a/protocols/oscar/Makefile b/protocols/oscar/Makefile index b26484ec..8088bdb6 100644 --- a/protocols/oscar/Makefile +++ b/protocols/oscar/Makefile @@ -38,7 +38,7 @@ $(objects): ../../Makefile.settings Makefile $(objects): %.o: $(_SRCDIR_)%.c @echo '*' Compiling $< - @$(CC) -c $(CFLAGS) $< -o $@ + @$(CC) -c $(CFLAGS) $(CFLAGS_BITLBEE) $< -o $@ oscar_mod.o: $(objects) @echo '*' Linking oscar_mod.o diff --git a/protocols/oscar/aim.h b/protocols/oscar/aim.h index 479f8fd0..3f26b392 100644 --- a/protocols/oscar/aim.h +++ b/protocols/oscar/aim.h @@ -409,15 +409,6 @@ typedef struct { #define AIM_USERINFO_PRESENT_CAPABILITIES 0x00000080 #define AIM_USERINFO_PRESENT_SESSIONLEN 0x00000100 -const char *aim_userinfo_sn(aim_userinfo_t *ui); -guint16 aim_userinfo_flags(aim_userinfo_t *ui); -guint16 aim_userinfo_idle(aim_userinfo_t *ui); -float aim_userinfo_warnlevel(aim_userinfo_t *ui); -time_t aim_userinfo_membersince(aim_userinfo_t *ui); -time_t aim_userinfo_onlinesince(aim_userinfo_t *ui); -guint32 aim_userinfo_sessionlen(aim_userinfo_t *ui); -int aim_userinfo_hascap(aim_userinfo_t *ui, guint32 cap); - #define AIM_FLAG_UNCONFIRMED 0x0001 /* "damned transients" */ #define AIM_FLAG_ADMINISTRATOR 0x0002 #define AIM_FLAG_AOL 0x0004 @@ -473,7 +464,6 @@ int aim_writetlvchain(aim_bstream_t *bs, aim_tlvlist_t **list); int aim_addtlvtochain8(aim_tlvlist_t **list, const guint16 t, const guint8 v); int aim_addtlvtochain16(aim_tlvlist_t **list, const guint16 t, const guint16 v); int aim_addtlvtochain32(aim_tlvlist_t **list, const guint16 type, const guint32 v); -int aim_addtlvtochain_availmsg(aim_tlvlist_t **list, const guint16 type, const char *msg); int aim_addtlvtochain_raw(aim_tlvlist_t **list, const guint16 t, const guint16 l, const guint8 *v); int aim_addtlvtochain_caps(aim_tlvlist_t **list, const guint16 t, const guint32 caps); int aim_addtlvtochain_noval(aim_tlvlist_t **list, const guint16 type); @@ -600,13 +590,7 @@ struct aim_chat_invitation { #define AIM_WARN_ANON 0x01 -int aim_sendpauseack(aim_session_t *sess, aim_conn_t *conn); -int aim_send_warning(aim_session_t *sess, aim_conn_t *conn, const char *destsn, guint32 flags); -int aim_nop(aim_session_t *, aim_conn_t *); int aim_flap_nop(aim_session_t *sess, aim_conn_t *conn); -int aim_bos_setidle(aim_session_t *, aim_conn_t *, guint32); -int aim_bos_changevisibility(aim_session_t *, aim_conn_t *, int, const char *); -int aim_bos_setbuddylist(aim_session_t *, aim_conn_t *, const char *); int aim_bos_setprofile(aim_session_t *sess, aim_conn_t *conn, const char *profile, const char *awaymsg, guint32 caps); int aim_bos_setgroupperm(aim_session_t *, aim_conn_t *, guint32 mask); int aim_bos_setprivacyflags(aim_session_t *, aim_conn_t *, guint32); @@ -615,8 +599,6 @@ int aim_reqservice(aim_session_t *, aim_conn_t *, guint16); int aim_bos_reqrights(aim_session_t *, aim_conn_t *); int aim_bos_reqbuddyrights(aim_session_t *, aim_conn_t *); int aim_bos_reqlocaterights(aim_session_t *, aim_conn_t *); -int aim_setdirectoryinfo(aim_session_t *sess, aim_conn_t *conn, const char *first, const char *middle, const char *last, const char *maiden, const char *nickname, const char *street, const char *city, const char *state, const char *zip, int country, guint16 privacy); -int aim_setuserinterests(aim_session_t *sess, aim_conn_t *conn, const char *interest1, const char *interest2, const char *interest3, const char *interest4, const char *interest5, guint16 privacy); int aim_setextstatus(aim_session_t *sess, aim_conn_t *conn, guint32 status); struct aim_fileheader_t *aim_getlisting(aim_session_t *sess, FILE *); @@ -626,7 +608,6 @@ struct aim_fileheader_t *aim_getlisting(aim_session_t *sess, FILE *); #define AIM_CLIENTTYPE_WINAIM 0x0002 #define AIM_CLIENTTYPE_WINAIM41 0x0003 #define AIM_CLIENTTYPE_AOL_TOC 0x0004 -unsigned short aim_fingerprintclient(unsigned char *msghdr, int len); #define AIM_RATE_CODE_CHANGE 0x0001 #define AIM_RATE_CODE_WARNING 0x0002 @@ -646,8 +627,6 @@ int aim_oft_getfile_end(aim_session_t *sess, aim_conn_t *conn); #define AIM_SENDMEMBLOCK_FLAG_ISREQUEST 0 #define AIM_SENDMEMBLOCK_FLAG_ISHASH 1 -int aim_sendmemblock(aim_session_t *sess, aim_conn_t *conn, guint32 offset, guint32 len, const guint8 *buf, guint8 flag); - #define AIM_GETINFO_GENERALINFO 0x00001 #define AIM_GETINFO_AWAYMESSAGE 0x00003 #define AIM_GETINFO_CAPABILITIES 0x0004 @@ -673,12 +652,9 @@ int aim_handlerendconnect(aim_session_t *sess, aim_conn_t *cur); #define AIM_TRANSFER_DENY_NOTSUPPORTED 0x0000 #define AIM_TRANSFER_DENY_DECLINE 0x0001 #define AIM_TRANSFER_DENY_NOTACCEPTING 0x0002 -int aim_denytransfer(aim_session_t *sess, const char *sender, const guint8 *cookie, unsigned short code); aim_conn_t *aim_accepttransfer(aim_session_t *sess, aim_conn_t *conn, const char *sn, const guint8 *cookie, const guint8 *ip, guint16 listingfiles, guint16 listingtotsize, guint16 listingsize, guint32 listingchecksum, guint16 rendid); int aim_getinfo(aim_session_t *, aim_conn_t *, const char *, unsigned short); -int aim_sendbuddyoncoming(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *info); -int aim_sendbuddyoffgoing(aim_session_t *sess, aim_conn_t *conn, const char *sn); #define AIM_IMPARAM_FLAG_CHANMSGS_ALLOWED 0x00000001 #define AIM_IMPARAM_FLAG_MISSEDCALLS_ENABLED 0x00000002 @@ -746,16 +722,12 @@ struct aim_chat_exchangeinfo { int aim_chat_send_im(aim_session_t *sess, aim_conn_t *conn, guint16 flags, const char *msg, int msglen); int aim_chat_join(aim_session_t *sess, aim_conn_t *conn, guint16 exchange, const char *roomname, guint16 instance); -int aim_chat_attachname(aim_conn_t *conn, guint16 exchange, const char *roomname, guint16 instance); -char *aim_chat_getname(aim_conn_t *conn); -aim_conn_t *aim_chat_getconn(aim_session_t *, const char *name); int aim_chatnav_reqrights(aim_session_t *sess, aim_conn_t *conn); int aim_chat_invite(aim_session_t *sess, aim_conn_t *conn, const char *sn, const char *msg, guint16 exchange, const char *roomname, guint16 instance); int aim_chatnav_createroom(aim_session_t *sess, aim_conn_t *conn, const char *name, guint16 exchange); -int aim_chat_leaveroom(aim_session_t *sess, const char *name); /* aim_util.c */ /* @@ -811,10 +783,6 @@ int aim_chat_leaveroom(aim_session_t *sess, const char *name); (((*((buf)+3)) << 24) & 0xff000000)) -int aimutil_putstr(u_char *, const char *, int); -int aimutil_tokslen(char *toSearch, int index, char dl); -int aimutil_itemcnt(char *toSearch, char dl); -char *aimutil_itemidx(char *toSearch, int index, char dl); int aim_sncmp(const char *a, const char *b); #include <aim_internal.h> diff --git a/protocols/oscar/aim_internal.h b/protocols/oscar/aim_internal.h index 80a9c758..e4cdd0a2 100644 --- a/protocols/oscar/aim_internal.h +++ b/protocols/oscar/aim_internal.h @@ -111,9 +111,6 @@ aim_snac_t *aim_remsnac(aim_session_t *, aim_snacid_t id); void aim_cleansnacs(aim_session_t *, int maxage); int aim_putsnac(aim_bstream_t *, guint16 family, guint16 type, guint16 flags, aim_snacid_t id); -aim_conn_t *aim_cloneconn(aim_session_t *sess, aim_conn_t *src); -void aim_clonehandlers(aim_session_t *sess, aim_conn_t *dest, aim_conn_t *src); - int aim_oft_buildheader(unsigned char *,struct aim_fileheader_t *); int aim_parse_unknown(aim_session_t *, aim_frame_t *, ...); @@ -194,12 +191,9 @@ int aim_freecookie(aim_session_t *sess, aim_msgcookie_t *cookie); int aim_cookie_free(aim_session_t *sess, aim_msgcookie_t *cookie); int aim_extractuserinfo(aim_session_t *sess, aim_bstream_t *bs, aim_userinfo_t *); -int aim_putuserinfo(aim_bstream_t *bs, aim_userinfo_t *info); int aim_chat_readroominfo(aim_bstream_t *bs, struct aim_chat_roominfo *outinfo); -int aim_request_directim(aim_session_t *sess, const char *destsn, guint8 *ip, guint16 port, guint8 *ckret); -int aim_request_sendfile(aim_session_t *sess, const char *sn, const char *filename, guint16 numfiles, guint32 totsize, guint8 *ip, guint16 port, guint8 *ckret); void aim_conn_close_rend(aim_session_t *sess, aim_conn_t *conn); void aim_conn_kill_rend(aim_session_t *sess, aim_conn_t *conn); @@ -209,6 +203,5 @@ void aim_conn_kill_chat(aim_session_t *sess, aim_conn_t *conn); int aim_setversions(aim_session_t *sess, aim_conn_t *conn); int aim_reqrates(aim_session_t *, aim_conn_t *); int aim_rates_addparam(aim_session_t *, aim_conn_t *); -int aim_rates_delparam(aim_session_t *, aim_conn_t *); #endif /* __AIM_INTERNAL_H__ */ diff --git a/protocols/oscar/bos.c b/protocols/oscar/bos.c index e7f12f79..4a1c5036 100644 --- a/protocols/oscar/bos.c +++ b/protocols/oscar/bos.c @@ -55,86 +55,6 @@ int aim_bos_setgroupperm(aim_session_t *sess, aim_conn_t *conn, guint32 mask) return aim_genericreq_l(sess, conn, 0x0009, 0x0004, &mask); } -/* - * Modify permit/deny lists (group 9, types 5, 6, 7, and 8) - * - * Changes your visibility depending on changetype: - * - * AIM_VISIBILITYCHANGE_PERMITADD: Lets provided list of names see you - * AIM_VISIBILITYCHANGE_PERMIDREMOVE: Removes listed names from permit list - * AIM_VISIBILITYCHANGE_DENYADD: Hides you from provided list of names - * AIM_VISIBILITYCHANGE_DENYREMOVE: Lets list see you again - * - * list should be a list of - * screen names in the form "Screen Name One&ScreenNameTwo&" etc. - * - * Equivelents to options in WinAIM: - * - Allow all users to contact me: Send an AIM_VISIBILITYCHANGE_DENYADD - * with only your name on it. - * - Allow only users on my Buddy List: Send an - * AIM_VISIBILITYCHANGE_PERMITADD with the list the same as your - * buddy list - * - Allow only the uesrs below: Send an AIM_VISIBILITYCHANGE_PERMITADD - * with everyone listed that you want to see you. - * - Block all users: Send an AIM_VISIBILITYCHANGE_PERMITADD with only - * yourself in the list - * - Block the users below: Send an AIM_VISIBILITYCHANGE_DENYADD with - * the list of users to be blocked - * - * XXX ye gods. - */ -int aim_bos_changevisibility(aim_session_t *sess, aim_conn_t *conn, int changetype, const char *denylist) -{ - aim_frame_t *fr; - int packlen = 0; - guint16 subtype; - char *localcpy = NULL, *tmpptr = NULL; - int i; - int listcount; - aim_snacid_t snacid; - - if (!denylist) - return -EINVAL; - - if (changetype == AIM_VISIBILITYCHANGE_PERMITADD) - subtype = 0x05; - else if (changetype == AIM_VISIBILITYCHANGE_PERMITREMOVE) - subtype = 0x06; - else if (changetype == AIM_VISIBILITYCHANGE_DENYADD) - subtype = 0x07; - else if (changetype == AIM_VISIBILITYCHANGE_DENYREMOVE) - subtype = 0x08; - else - return -EINVAL; - - localcpy = g_strdup(denylist); - - listcount = aimutil_itemcnt(localcpy, '&'); - packlen = aimutil_tokslen(localcpy, 99, '&') + listcount + 9; - - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, packlen))) { - g_free(localcpy); - return -ENOMEM; - } - - snacid = aim_cachesnac(sess, 0x0009, subtype, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0009, subtype, 0x00, snacid); - - for (i = 0; (i < (listcount - 1)) && (i < 99); i++) { - tmpptr = aimutil_itemidx(localcpy, i, '&'); - - aimbs_put8(&fr->data, strlen(tmpptr)); - aimbs_putraw(&fr->data, (guint8 *)tmpptr, strlen(tmpptr)); - - g_free(tmpptr); - } - g_free(localcpy); - - aim_tx_enqueue(sess, fr); - - return 0; -} - static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) { diff --git a/protocols/oscar/buddylist.c b/protocols/oscar/buddylist.c index a7b461f2..3335c5ab 100644 --- a/protocols/oscar/buddylist.c +++ b/protocols/oscar/buddylist.c @@ -90,61 +90,3 @@ int buddylist_modfirst(aim_session_t *sess, aim_module_t *mod) return 0; } - -/* - * aim_add_buddy() - * - * Adds a single buddy to your buddy list after login. - * - * XXX this should just be an extension of setbuddylist() - * - */ -int aim_add_buddy(aim_session_t *sess, aim_conn_t *conn, const char *sn) -{ - aim_frame_t *fr; - aim_snacid_t snacid; - - if (!sn || !strlen(sn)) - return -EINVAL; - - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+1+strlen(sn)))) - return -ENOMEM; - - snacid = aim_cachesnac(sess, 0x0003, 0x0004, 0x0000, sn, strlen(sn)+1); - aim_putsnac(&fr->data, 0x0003, 0x0004, 0x0000, snacid); - - aimbs_put8(&fr->data, strlen(sn)); - aimbs_putraw(&fr->data, (guint8 *)sn, strlen(sn)); - - aim_tx_enqueue(sess, fr); - - return 0; -} - -/* - * XXX generalise to support removing multiple buddies (basically, its - * the same as setbuddylist() but with a different snac subtype). - * - */ -int aim_remove_buddy(aim_session_t *sess, aim_conn_t *conn, const char *sn) -{ - aim_frame_t *fr; - aim_snacid_t snacid; - - if (!sn || !strlen(sn)) - return -EINVAL; - - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+1+strlen(sn)))) - return -ENOMEM; - - snacid = aim_cachesnac(sess, 0x0003, 0x0005, 0x0000, sn, strlen(sn)+1); - aim_putsnac(&fr->data, 0x0003, 0x0005, 0x0000, snacid); - - aimbs_put8(&fr->data, strlen(sn)); - aimbs_putraw(&fr->data, (guint8 *)sn, strlen(sn)); - - aim_tx_enqueue(sess, fr); - - return 0; -} - diff --git a/protocols/oscar/buddylist.h b/protocols/oscar/buddylist.h index 9a325279..55189581 100644 --- a/protocols/oscar/buddylist.h +++ b/protocols/oscar/buddylist.h @@ -16,8 +16,4 @@ #define AIM_CB_BUD_OFFGOING 0x000c #define AIM_CB_BUD_DEFAULT 0xffff -/* aim_buddylist.c */ -int aim_add_buddy(aim_session_t *, aim_conn_t *, const char *); -int aim_remove_buddy(aim_session_t *, aim_conn_t *, const char *); - #endif /* __OSCAR_BUDDYLIST_H__ */ diff --git a/protocols/oscar/chat.c b/protocols/oscar/chat.c index a5db8fba..d8399563 100644 --- a/protocols/oscar/chat.c +++ b/protocols/oscar/chat.c @@ -27,65 +27,6 @@ void aim_conn_kill_chat(aim_session_t *sess, aim_conn_t *conn) return; } -char *aim_chat_getname(aim_conn_t *conn) -{ - struct chatconnpriv *ccp; - - if (!conn) - return NULL; - - if (conn->type != AIM_CONN_TYPE_CHAT) - return NULL; - - ccp = (struct chatconnpriv *)conn->priv; - - return ccp->name; -} - -/* XXX get this into conn.c -- evil!! */ -aim_conn_t *aim_chat_getconn(aim_session_t *sess, const char *name) -{ - aim_conn_t *cur; - - for (cur = sess->connlist; cur; cur = cur->next) { - struct chatconnpriv *ccp = (struct chatconnpriv *)cur->priv; - - if (cur->type != AIM_CONN_TYPE_CHAT) - continue; - if (!cur->priv) { - imcb_error(sess->aux_data, "chat connection with no name!"); - continue; - } - - if (strcmp(ccp->name, name) == 0) - break; - } - - return cur; -} - -int aim_chat_attachname(aim_conn_t *conn, guint16 exchange, const char *roomname, guint16 instance) -{ - struct chatconnpriv *ccp; - - if (!conn || !roomname) - return -EINVAL; - - if (conn->priv) - g_free(conn->priv); - - if (!(ccp = g_malloc(sizeof(struct chatconnpriv)))) - return -ENOMEM; - - ccp->exchange = exchange; - ccp->name = g_strdup(roomname); - ccp->instance = instance; - - conn->priv = (void *)ccp; - - return 0; -} - /* * Send a Chat Message. * @@ -253,18 +194,6 @@ int aim_chat_readroominfo(aim_bstream_t *bs, struct aim_chat_roominfo *outinfo) return 0; } -int aim_chat_leaveroom(aim_session_t *sess, const char *name) -{ - aim_conn_t *conn; - - if (!(conn = aim_chat_getconn(sess, name))) - return -ENOENT; - - aim_conn_close(conn); - - return 0; -} - /* * conn must be a BOS connection! */ diff --git a/protocols/oscar/conn.c b/protocols/oscar/conn.c index 77ffd50f..a178761e 100644 --- a/protocols/oscar/conn.c +++ b/protocols/oscar/conn.c @@ -353,50 +353,6 @@ aim_conn_t *aim_getconn_type_all(aim_session_t *sess, int type) } /** - * aim_cloneconn - clone an aim_conn_t - * @sess: session containing parent - * @src: connection to clone - * - * A new connection is allocated, and the values are filled in - * appropriately. Note that this function sets the new connnection's - * ->priv pointer to be equal to that of its parent: only the pointer - * is copied, not the data it points to. - * - * This function returns a pointer to the new aim_conn_t, or %NULL on - * error - */ -aim_conn_t *aim_cloneconn(aim_session_t *sess, aim_conn_t *src) -{ - aim_conn_t *conn; - - if (!(conn = aim_conn_getnext(sess))) - return NULL; - - conn->fd = src->fd; - conn->type = src->type; - conn->subtype = src->subtype; - conn->seqnum = src->seqnum; - conn->priv = src->priv; - conn->internal = src->internal; - conn->lastactivity = src->lastactivity; - conn->forcedlatency = src->forcedlatency; - conn->sessv = src->sessv; - aim_clonehandlers(sess, conn, src); - - if (src->inside) { - /* - * XXX should clone this section as well, but since currently - * this function only gets called for some of that rendezvous - * crap, and not on SNAC connections, its probably okay for - * now. - * - */ - } - - return conn; -} - -/** * aim_newconn - Open a new connection * @sess: Session to create connection in * @type: Type of connection to create diff --git a/protocols/oscar/icq.c b/protocols/oscar/icq.c index c2f8dda6..bd1ba1d1 100644 --- a/protocols/oscar/icq.c +++ b/protocols/oscar/icq.c @@ -70,44 +70,6 @@ int aim_icq_ackofflinemsgs(aim_session_t *sess) return 0; } -int aim_icq_sendxmlreq(aim_session_t *sess, const char *xml) -{ - aim_conn_t *conn; - aim_frame_t *fr; - aim_snacid_t snacid; - int bslen; - - if (!xml || !strlen(xml)) - return -EINVAL; - - if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0015))) - return -EINVAL; - - bslen = 2 + 10 + 2 + strlen(xml) + 1; - - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 4 + bslen))) - return -ENOMEM; - - snacid = aim_cachesnac(sess, 0x0015, 0x0002, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0015, 0x0002, 0x0000, snacid); - - /* For simplicity, don't bother using a tlvlist */ - aimbs_put16(&fr->data, 0x0001); - aimbs_put16(&fr->data, bslen); - - aimbs_putle16(&fr->data, bslen - 2); - aimbs_putle32(&fr->data, atoi(sess->sn)); - aimbs_putle16(&fr->data, 0x07d0); /* I command thee. */ - aimbs_putle16(&fr->data, snacid); /* eh. */ - aimbs_putle16(&fr->data, 0x0998); /* shrug. */ - aimbs_putle16(&fr->data, strlen(xml) + 1); - aimbs_putraw(&fr->data, (guint8 *)xml, strlen(xml) + 1); - - aim_tx_enqueue(sess, fr); - - return 0; -} - int aim_icq_getallinfo(aim_session_t *sess, const char *uin) { aim_conn_t *conn; @@ -153,43 +115,6 @@ int aim_icq_getallinfo(aim_session_t *sess, const char *uin) return 0; } -int aim_icq_getsimpleinfo(aim_session_t *sess, const char *uin) -{ - aim_conn_t *conn; - aim_frame_t *fr; - aim_snacid_t snacid; - int bslen; - - if (!uin || uin[0] < '0' || uin[0] > '9') - return -EINVAL; - - if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0015))) - return -EINVAL; - - bslen = 2 + 4 + 2 + 2 + 2 + 4; - - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 4 + bslen))) - return -ENOMEM; - - snacid = aim_cachesnac(sess, 0x0015, 0x0002, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0015, 0x0002, 0x0000, snacid); - - /* For simplicity, don't bother using a tlvlist */ - aimbs_put16(&fr->data, 0x0001); - aimbs_put16(&fr->data, bslen); - - aimbs_putle16(&fr->data, bslen - 2); - aimbs_putle32(&fr->data, atoi(sess->sn)); - aimbs_putle16(&fr->data, 0x07d0); /* I command thee. */ - aimbs_putle16(&fr->data, snacid); /* eh. */ - aimbs_putle16(&fr->data, 0x051f); /* shrug. */ - aimbs_putle32(&fr->data, atoi(uin)); - - aim_tx_enqueue(sess, fr); - - return 0; -} - static void aim_icq_freeinfo(struct aim_icq_info *info) { int i; diff --git a/protocols/oscar/icq.h b/protocols/oscar/icq.h index c496f39c..41b3efb9 100644 --- a/protocols/oscar/icq.h +++ b/protocols/oscar/icq.h @@ -93,6 +93,5 @@ struct aim_icq_info { int aim_icq_reqofflinemsgs(aim_session_t *sess); int aim_icq_ackofflinemsgs(aim_session_t *sess); int aim_icq_getallinfo(aim_session_t *sess, const char *uin); -int aim_icq_getsimpleinfo(aim_session_t *sess, const char *uin); #endif /* __OSCAR_ICQ_H__ */ diff --git a/protocols/oscar/im.c b/protocols/oscar/im.c index 231dd959..05e06e91 100644 --- a/protocols/oscar/im.c +++ b/protocols/oscar/im.c @@ -24,83 +24,6 @@ #include "info.h" /* - * Takes a msghdr (and a length) and returns a client type - * code. Note that this is *only a guess* and has a low likelihood - * of actually being accurate. - * - * Its based on experimental data, with the help of Eric Warmenhoven - * who seems to have collected a wide variety of different AIM clients. - * - * - * Heres the current collection: - * 0501 0003 0101 0101 01 AOL Mobile Communicator, WinAIM 1.0.414 - * 0501 0003 0101 0201 01 WinAIM 2.0.847, 2.1.1187, 3.0.1464, - * 4.3.2229, 4.4.2286 - * 0501 0004 0101 0102 0101 WinAIM 4.1.2010, libfaim (right here) - * 0501 0001 0101 01 AOL v6.0, CompuServe 2000 v6.0, any - * TOC client - * - * Note that in this function, only the feature bytes are tested, since - * the rest will always be the same. - * - */ -guint16 aim_fingerprintclient(guint8 *msghdr, int len) -{ - static const struct { - guint16 clientid; - int len; - guint8 data[10]; - } fingerprints[] = { - /* AOL Mobile Communicator, WinAIM 1.0.414 */ - { AIM_CLIENTTYPE_MC, - 3, {0x01, 0x01, 0x01}}, - - /* WinAIM 2.0.847, 2.1.1187, 3.0.1464, 4.3.2229, 4.4.2286 */ - { AIM_CLIENTTYPE_WINAIM, - 3, {0x01, 0x01, 0x02}}, - - /* WinAIM 4.1.2010, libfaim */ - { AIM_CLIENTTYPE_WINAIM41, - 4, {0x01, 0x01, 0x01, 0x02}}, - - /* AOL v6.0, CompuServe 2000 v6.0, any TOC client */ - { AIM_CLIENTTYPE_AOL_TOC, - 1, {0x01}}, - - { 0, 0} - }; - int i; - - if (!msghdr || (len <= 0)) - return AIM_CLIENTTYPE_UNKNOWN; - - for (i = 0; fingerprints[i].len; i++) { - if (fingerprints[i].len != len) - continue; - if (memcmp(fingerprints[i].data, msghdr, fingerprints[i].len) == 0) - return fingerprints[i].clientid; - } - - return AIM_CLIENTTYPE_UNKNOWN; -} - -/* This should be endian-safe now... but who knows... */ -guint16 aim_iconsum(const guint8 *buf, int buflen) -{ - guint32 sum; - int i; - - for (i = 0, sum = 0; i + 1 < buflen; i += 2) - sum += (buf[i+1] << 8) + buf[i]; - if (i < buflen) - sum += buf[i]; - - sum = ((sum & 0xffff0000) >> 16) + (sum & 0x0000ffff); - - return (guint16)sum; -} - -/* * Send an ICBM (instant message). * * @@ -366,483 +289,6 @@ int aim_send_im(aim_session_t *sess, const char *destsn, guint16 flags, const ch return aim_send_im_ext(sess, &args); } -/* - * This is also performance sensitive. (If you can believe it...) - * - */ -int aim_send_icon(aim_session_t *sess, const char *sn, const guint8 *icon, int iconlen, time_t stamp, guint16 iconsum) -{ - aim_conn_t *conn; - int i; - guint8 ck[8]; - aim_frame_t *fr; - aim_snacid_t snacid; - - if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004))) - return -EINVAL; - - if (!sn || !icon || (iconlen <= 0) || (iconlen >= MAXICONLEN)) - return -EINVAL; - - for (i = 0; i < 8; i++) - aimutil_put8(ck+i, (guint8) rand()); - - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+8+2+1+strlen(sn)+2+2+2+8+16+2+2+2+2+2+2+2+4+4+4+iconlen+strlen(AIM_ICONIDENT)+2+2))) - return -ENOMEM; - - snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid); - - /* - * Cookie - */ - aimbs_putraw(&fr->data, ck, 8); - - /* - * Channel (2) - */ - aimbs_put16(&fr->data, 0x0002); - - /* - * Dest sn - */ - aimbs_put8(&fr->data, strlen(sn)); - aimbs_putraw(&fr->data, (guint8 *)sn, strlen(sn)); - - /* - * TLV t(0005) - * - * Encompasses everything below. - */ - aimbs_put16(&fr->data, 0x0005); - aimbs_put16(&fr->data, 2+8+16+6+4+4+iconlen+4+4+4+strlen(AIM_ICONIDENT)); - - aimbs_put16(&fr->data, 0x0000); - aimbs_putraw(&fr->data, ck, 8); - aim_putcap(&fr->data, AIM_CAPS_BUDDYICON); - - /* TLV t(000a) */ - aimbs_put16(&fr->data, 0x000a); - aimbs_put16(&fr->data, 0x0002); - aimbs_put16(&fr->data, 0x0001); - - /* TLV t(000f) */ - aimbs_put16(&fr->data, 0x000f); - aimbs_put16(&fr->data, 0x0000); - - /* TLV t(2711) */ - aimbs_put16(&fr->data, 0x2711); - aimbs_put16(&fr->data, 4+4+4+iconlen+strlen(AIM_ICONIDENT)); - aimbs_put16(&fr->data, 0x0000); - aimbs_put16(&fr->data, iconsum); - aimbs_put32(&fr->data, iconlen); - aimbs_put32(&fr->data, stamp); - aimbs_putraw(&fr->data, icon, iconlen); - aimbs_putraw(&fr->data, (guint8 *)AIM_ICONIDENT, strlen(AIM_ICONIDENT)); - - /* TLV t(0003) */ - aimbs_put16(&fr->data, 0x0003); - aimbs_put16(&fr->data, 0x0000); - - aim_tx_enqueue(sess, fr); - - return 0; -} - -/* - * This only works for ICQ 2001b (thats 2001 not 2000). Better, only - * send it to clients advertising the RTF capability. In fact, if you send - * it to a client that doesn't support that capability, the server will gladly - * bounce it back to you. - * - * You'd think this would be in icq.c, but, well, I'm trying to stick with - * the one-group-per-file scheme as much as possible. This could easily - * be an exception, since Rendezvous IMs are external of the Oscar core, - * and therefore are undefined. Really I just need to think of a good way to - * make an interface similar to what AOL actually uses. But I'm not using COM. - * - */ -int aim_send_rtfmsg(aim_session_t *sess, struct aim_sendrtfmsg_args *args) -{ - const char rtfcap[] = {"{97B12751-243C-4334-AD22-D6ABF73F1492}"}; /* AIM_CAPS_ICQRTF capability in string form */ - aim_conn_t *conn; - int i; - guint8 ck[8]; - aim_frame_t *fr; - aim_snacid_t snacid; - int servdatalen; - - if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004))) - return -EINVAL; - - if (!args || !args->destsn || !args->rtfmsg) - return -EINVAL; - - servdatalen = 2+2+16+2+4+1+2 + 2+2+4+4+4 + 2+4+2+strlen(args->rtfmsg)+1 + 4+4+4+strlen(rtfcap)+1; - - for (i = 0; i < 8; i++) - aimutil_put8(ck+i, (guint8) rand()); - - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+128+servdatalen))) - return -ENOMEM; - - snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid); - - /* - * Cookie - */ - aimbs_putraw(&fr->data, ck, 8); - - /* - * Channel (2) - */ - aimbs_put16(&fr->data, 0x0002); - - /* - * Dest sn - */ - aimbs_put8(&fr->data, strlen(args->destsn)); - aimbs_putraw(&fr->data, (guint8 *)args->destsn, strlen(args->destsn)); - - /* - * TLV t(0005) - * - * Encompasses everything below. - */ - aimbs_put16(&fr->data, 0x0005); - aimbs_put16(&fr->data, 2+8+16 + 2+2+2 + 2+2 + 2+2+servdatalen); - - aimbs_put16(&fr->data, 0x0000); - aimbs_putraw(&fr->data, ck, 8); - aim_putcap(&fr->data, AIM_CAPS_ICQSERVERRELAY); - - /* - * t(000a) l(0002) v(0001) - */ - aimbs_put16(&fr->data, 0x000a); - aimbs_put16(&fr->data, 0x0002); - aimbs_put16(&fr->data, 0x0001); - - /* - * t(000f) l(0000) v() - */ - aimbs_put16(&fr->data, 0x000f); - aimbs_put16(&fr->data, 0x0000); - - /* - * Service Data TLV - */ - aimbs_put16(&fr->data, 0x2711); - aimbs_put16(&fr->data, servdatalen); - - aimbs_putle16(&fr->data, 11 + 16 /* 11 + (sizeof CLSID) */); - aimbs_putle16(&fr->data, 9); - aim_putcap(&fr->data, AIM_CAPS_EMPTY); - aimbs_putle16(&fr->data, 0); - aimbs_putle32(&fr->data, 0); - aimbs_putle8(&fr->data, 0); - aimbs_putle16(&fr->data, 0x03ea); /* trid1 */ - - aimbs_putle16(&fr->data, 14); - aimbs_putle16(&fr->data, 0x03eb); /* trid2 */ - aimbs_putle32(&fr->data, 0); - aimbs_putle32(&fr->data, 0); - aimbs_putle32(&fr->data, 0); - - aimbs_putle16(&fr->data, 0x0001); - aimbs_putle32(&fr->data, 0); - aimbs_putle16(&fr->data, strlen(args->rtfmsg)+1); - aimbs_putraw(&fr->data, (guint8 *)args->rtfmsg, strlen(args->rtfmsg)+1); - - aimbs_putle32(&fr->data, args->fgcolor); - aimbs_putle32(&fr->data, args->bgcolor); - aimbs_putle32(&fr->data, strlen(rtfcap)+1); - aimbs_putraw(&fr->data, (guint8 *)rtfcap, strlen(rtfcap)+1); - - aim_tx_enqueue(sess, fr); - - return 0; -} - -int aim_request_directim(aim_session_t *sess, const char *destsn, guint8 *ip, guint16 port, guint8 *ckret) -{ - aim_conn_t *conn; - guint8 ck[8]; - aim_frame_t *fr; - aim_snacid_t snacid; - aim_tlvlist_t *tl = NULL, *itl = NULL; - int hdrlen, i; - guint8 *hdr; - aim_bstream_t hdrbs; - - if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004))) - return -EINVAL; - - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 256+strlen(destsn)))) - return -ENOMEM; - - snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid); - - /* - * Generate a random message cookie - * - * This cookie needs to be alphanumeric and NULL-terminated to be - * TOC-compatible. - * - * XXX have I mentioned these should be generated in msgcookie.c? - * - */ - for (i = 0; i < 7; i++) - ck[i] = 0x30 + ((guint8) rand() % 10); - ck[7] = '\0'; - - if (ckret) - memcpy(ckret, ck, 8); - - /* Cookie */ - aimbs_putraw(&fr->data, ck, 8); - - /* Channel */ - aimbs_put16(&fr->data, 0x0002); - - /* Destination SN */ - aimbs_put8(&fr->data, strlen(destsn)); - aimbs_putraw(&fr->data, (guint8 *)destsn, strlen(destsn)); - - aim_addtlvtochain_noval(&tl, 0x0003); - - hdrlen = 2+8+16+6+8+6+4; - hdr = g_malloc(hdrlen); - aim_bstream_init(&hdrbs, hdr, hdrlen); - - aimbs_put16(&hdrbs, 0x0000); - aimbs_putraw(&hdrbs, ck, 8); - aim_putcap(&hdrbs, AIM_CAPS_IMIMAGE); - - aim_addtlvtochain16(&itl, 0x000a, 0x0001); - aim_addtlvtochain_raw(&itl, 0x0003, 4, ip); - aim_addtlvtochain16(&itl, 0x0005, port); - aim_addtlvtochain_noval(&itl, 0x000f); - - aim_writetlvchain(&hdrbs, &itl); - - aim_addtlvtochain_raw(&tl, 0x0005, aim_bstream_curpos(&hdrbs), hdr); - - aim_writetlvchain(&fr->data, &tl); - - g_free(hdr); - aim_freetlvchain(&itl); - aim_freetlvchain(&tl); - - aim_tx_enqueue(sess, fr); - - return 0; -} - -int aim_request_sendfile(aim_session_t *sess, const char *sn, const char *filename, guint16 numfiles, guint32 totsize, guint8 *ip, guint16 port, guint8 *ckret) -{ - aim_conn_t *conn; - int i; - guint8 ck[8]; - aim_frame_t *fr; - aim_snacid_t snacid; - - if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004))) - return -EINVAL; - - if (!sn || !filename) - return -EINVAL; - - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+8+2+1+strlen(sn)+2+2+2+8+16+6+8+6+4+2+2+2+2+4+strlen(filename)+4))) - return -ENOMEM; - - snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid); - - for (i = 0; i < 7; i++) - aimutil_put8(ck+i, 0x30 + ((guint8) rand() % 10)); - ck[7] = '\0'; - - if (ckret) - memcpy(ckret, ck, 8); - - /* - * Cookie - */ - aimbs_putraw(&fr->data, ck, 8); - - /* - * Channel (2) - */ - aimbs_put16(&fr->data, 0x0002); - - /* - * Dest sn - */ - aimbs_put8(&fr->data, strlen(sn)); - aimbs_putraw(&fr->data, (guint8 *)sn, strlen(sn)); - - /* - * TLV t(0005) - * - * Encompasses everything below. Gee. - */ - aimbs_put16(&fr->data, 0x0005); - aimbs_put16(&fr->data, 2+8+16+6+8+6+4+2+2+2+2+4+strlen(filename)+4); - - aimbs_put16(&fr->data, 0x0000); - aimbs_putraw(&fr->data, ck, 8); - aim_putcap(&fr->data, AIM_CAPS_SENDFILE); - - /* TLV t(000a) */ - aimbs_put16(&fr->data, 0x000a); - aimbs_put16(&fr->data, 0x0002); - aimbs_put16(&fr->data, 0x0001); - - /* TLV t(0003) (IP) */ - aimbs_put16(&fr->data, 0x0003); - aimbs_put16(&fr->data, 0x0004); - aimbs_putraw(&fr->data, ip, 4); - - /* TLV t(0005) (port) */ - aimbs_put16(&fr->data, 0x0005); - aimbs_put16(&fr->data, 0x0002); - aimbs_put16(&fr->data, port); - - /* TLV t(000f) */ - aimbs_put16(&fr->data, 0x000f); - aimbs_put16(&fr->data, 0x0000); - - /* TLV t(2711) */ - aimbs_put16(&fr->data, 0x2711); - aimbs_put16(&fr->data, 2+2+4+strlen(filename)+4); - - /* ? */ - aimbs_put16(&fr->data, 0x0001); - aimbs_put16(&fr->data, numfiles); - aimbs_put32(&fr->data, totsize); - aimbs_putraw(&fr->data, (guint8 *)filename, strlen(filename)); - - /* ? */ - aimbs_put32(&fr->data, 0x00000000); - - aim_tx_enqueue(sess, fr); - - return 0; -} - -/** - * Request the status message of the given ICQ user. - * - * @param sess The oscar session. - * @param sn The UIN of the user of whom you wish to request info. - * @param type The type of info you wish to request. This should be the current - * state of the user, as one of the AIM_ICQ_STATE_* defines. - * @return Return 0 if no errors, otherwise return the error number. - */ -int aim_send_im_ch2_geticqmessage(aim_session_t *sess, const char *sn, int type) -{ - aim_conn_t *conn; - int i; - guint8 ck[8]; - aim_frame_t *fr; - aim_snacid_t snacid; - - if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)) || !sn) - return -EINVAL; - - for (i = 0; i < 8; i++) - aimutil_put8(ck+i, (guint8) rand()); - - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+8+2+1+strlen(sn) + 4+0x5e + 4))) - return -ENOMEM; - - snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid); - - /* Cookie */ - aimbs_putraw(&fr->data, ck, 8); - - /* Channel (2) */ - aimbs_put16(&fr->data, 0x0002); - - /* Dest sn */ - aimbs_put8(&fr->data, strlen(sn)); - aimbs_putraw(&fr->data, (guint8 *)sn, strlen(sn)); - - /* TLV t(0005) - Encompasses almost everything below. */ - aimbs_put16(&fr->data, 0x0005); /* T */ - aimbs_put16(&fr->data, 0x005e); /* L */ - { /* V */ - aimbs_put16(&fr->data, 0x0000); - - /* Cookie */ - aimbs_putraw(&fr->data, ck, 8); - - /* Put the 16 byte server relay capability */ - aim_putcap(&fr->data, AIM_CAPS_ICQSERVERRELAY); - - /* TLV t(000a) */ - aimbs_put16(&fr->data, 0x000a); - aimbs_put16(&fr->data, 0x0002); - aimbs_put16(&fr->data, 0x0001); - - /* TLV t(000f) */ - aimbs_put16(&fr->data, 0x000f); - aimbs_put16(&fr->data, 0x0000); - - /* TLV t(2711) */ - aimbs_put16(&fr->data, 0x2711); - aimbs_put16(&fr->data, 0x0036); - { /* V */ - aimbs_putle16(&fr->data, 0x001b); /* L */ - aimbs_putle16(&fr->data, 0x0008); /* AAA - Protocol version */ - aimbs_putle32(&fr->data, 0x00000000); /* Unknown */ - aimbs_putle32(&fr->data, 0x00000000); /* Unknown */ - aimbs_putle32(&fr->data, 0x00000000); /* Unknown */ - aimbs_putle32(&fr->data, 0x00000000); /* Unknown */ - aimbs_putle16(&fr->data, 0x0000); /* Unknown */ - aimbs_putle16(&fr->data, 0x0003); /* Client features? */ - aimbs_putle16(&fr->data, 0x0000); /* Unknown */ - aimbs_putle8(&fr->data, 0x00); /* Unkizown */ - aimbs_putle16(&fr->data, 0xffff); /* Sequence number? XXX - This should decrement by 1 with each request */ - - aimbs_putle16(&fr->data, 0x000e); /* L */ - aimbs_putle16(&fr->data, 0xffff); /* Sequence number? XXX - This should decrement by 1 with each request */ - aimbs_putle32(&fr->data, 0x00000000); /* Unknown */ - aimbs_putle32(&fr->data, 0x00000000); /* Unknown */ - aimbs_putle32(&fr->data, 0x00000000); /* Unknown */ - - /* The type of status message being requested */ - if (type & AIM_ICQ_STATE_CHAT) - aimbs_putle16(&fr->data, 0x03ec); - else if(type & AIM_ICQ_STATE_DND) - aimbs_putle16(&fr->data, 0x03eb); - else if(type & AIM_ICQ_STATE_OUT) - aimbs_putle16(&fr->data, 0x03ea); - else if(type & AIM_ICQ_STATE_BUSY) - aimbs_putle16(&fr->data, 0x03e9); - else if(type & AIM_ICQ_STATE_AWAY) - aimbs_putle16(&fr->data, 0x03e8); - - aimbs_putle16(&fr->data, 0x0000); /* Status? */ - aimbs_putle16(&fr->data, 0x0001); /* Priority of this message? */ - aimbs_putle16(&fr->data, 0x0001); /* L? */ - aimbs_putle8(&fr->data, 0x00); /* Null termination? */ - } /* End TLV t(2711) */ - } /* End TLV t(0005) */ - - /* TLV t(0003) */ - aimbs_put16(&fr->data, 0x0003); - aimbs_put16(&fr->data, 0x0000); - - aim_tx_enqueue(sess, fr); - - return 0; -} - /** * answers status message requests * @param sess the oscar session @@ -1052,61 +498,6 @@ static int mpmsg_addsection(aim_session_t *sess, aim_mpmsg_t *mpm, guint16 chars return 0; } -int aim_mpmsg_addraw(aim_session_t *sess, aim_mpmsg_t *mpm, guint16 charset, guint16 charsubset, const guint8 *data, guint16 datalen) -{ - guint8 *dup; - - if (!(dup = g_malloc(datalen))) - return -1; - memcpy(dup, data, datalen); - - if (mpmsg_addsection(sess, mpm, charset, charsubset, dup, datalen) == -1) { - g_free(dup); - return -1; - } - - return 0; -} - -/* XXX should provide a way of saying ISO-8859-1 specifically */ -int aim_mpmsg_addascii(aim_session_t *sess, aim_mpmsg_t *mpm, const char *ascii) -{ - char *dup; - - if (!(dup = g_strdup(ascii))) - return -1; - - if (mpmsg_addsection(sess, mpm, 0x0000, 0x0000, (guint8 *)dup, (guint16) strlen(ascii)) == -1) { - g_free(dup); - return -1; - } - - return 0; -} - -int aim_mpmsg_addunicode(aim_session_t *sess, aim_mpmsg_t *mpm, const guint16 *unicode, guint16 unicodelen) -{ - guint8 *buf; - aim_bstream_t bs; - int i; - - if (!(buf = g_malloc(unicodelen * 2))) - return -1; - - aim_bstream_init(&bs, buf, unicodelen * 2); - - /* We assume unicode is in /host/ byte order -- convert to network */ - for (i = 0; i < unicodelen; i++) - aimbs_put16(&bs, unicode[i]); - - if (mpmsg_addsection(sess, mpm, 0x0002, 0x0000, buf, aim_bstream_curpos(&bs)) == -1) { - g_free(buf); - return -1; - } - - return 0; -} - void aim_mpmsg_free(aim_session_t *sess, aim_mpmsg_t *mpm) { aim_mpmsg_section_t *cur; @@ -1790,44 +1181,6 @@ static int incomingim(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, a } /* - * Possible codes: - * AIM_TRANSFER_DENY_NOTSUPPORTED -- "client does not support" - * AIM_TRANSFER_DENY_DECLINE -- "client has declined transfer" - * AIM_TRANSFER_DENY_NOTACCEPTING -- "client is not accepting transfers" - * - */ -int aim_denytransfer(aim_session_t *sess, const char *sender, const guint8 *cookie, guint16 code) -{ - aim_conn_t *conn; - aim_frame_t *fr; - aim_snacid_t snacid; - aim_tlvlist_t *tl = NULL; - - if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004))) - return -EINVAL; - - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+8+2+1+strlen(sender)+6))) - return -ENOMEM; - - snacid = aim_cachesnac(sess, 0x0004, 0x000b, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0004, 0x000b, 0x0000, snacid); - - aimbs_putraw(&fr->data, cookie, 8); - - aimbs_put16(&fr->data, 0x0002); /* channel */ - aimbs_put8(&fr->data, strlen(sender)); - aimbs_putraw(&fr->data, (guint8 *)sender, strlen(sender)); - - aim_addtlvtochain16(&tl, 0x0003, code); - aim_writetlvchain(&fr->data, &tl); - aim_freetlvchain(&tl); - - aim_tx_enqueue(sess, fr); - - return 0; -} - -/* * aim_reqicbmparaminfo() * * Request ICBM parameter information. diff --git a/protocols/oscar/im.h b/protocols/oscar/im.h index 42a8a6b1..34d5e238 100644 --- a/protocols/oscar/im.h +++ b/protocols/oscar/im.h @@ -46,9 +46,6 @@ typedef struct aim_mpmsg_s { } aim_mpmsg_t; int aim_mpmsg_init(aim_session_t *sess, aim_mpmsg_t *mpm); -int aim_mpmsg_addraw(aim_session_t *sess, aim_mpmsg_t *mpm, guint16 charset, guint16 charsubset, const guint8 *data, guint16 datalen); -int aim_mpmsg_addascii(aim_session_t *sess, aim_mpmsg_t *mpm, const char *ascii); -int aim_mpmsg_addunicode(aim_session_t *sess, aim_mpmsg_t *mpm, const guint16 *unicode, guint16 unicodelen); void aim_mpmsg_free(aim_session_t *sess, aim_mpmsg_t *mpm); /* @@ -85,16 +82,6 @@ struct aim_sendimext_args { }; /* - * Arguments to aim_send_rtfmsg(). - */ -struct aim_sendrtfmsg_args { - const char *destsn; - guint32 fgcolor; - guint32 bgcolor; - const char *rtfmsg; /* must be in RTF */ -}; - -/* * This information is provided in the Incoming ICBM callback for * Channel 1 ICBM's. * @@ -182,18 +169,14 @@ struct aim_incomingim_ch4_args { char *msg; /* Reason for auth request, deny, or accept */ }; -int aim_send_rtfmsg(aim_session_t *sess, struct aim_sendrtfmsg_args *args); int aim_send_im_ext(aim_session_t *sess, struct aim_sendimext_args *args); int aim_send_im(aim_session_t *, const char *destsn, unsigned short flags, const char *msg); -int aim_send_icon(aim_session_t *sess, const char *sn, const guint8 *icon, int iconlen, time_t stamp, guint16 iconsum); -guint16 aim_iconsum(const guint8 *buf, int buflen); int aim_send_typing(aim_session_t *sess, aim_conn_t *conn, int typing); int aim_send_im_direct(aim_session_t *, aim_conn_t *, const char *msg, int len); const char *aim_directim_getsn(aim_conn_t *conn); aim_conn_t *aim_directim_initiate(aim_session_t *, const char *destsn); aim_conn_t *aim_directim_connect(aim_session_t *, const char *sn, const char *addr, const guint8 *cookie); -int aim_send_im_ch2_geticqmessage(aim_session_t *sess, const char *sn, int type); int aim_im_sendmtn(aim_session_t *sess, guint16 type1, const char *sn, guint16 type2); int aim_send_im_ch2_statusmessage(aim_session_t *sess, const char *sender, const guint8 *cookie, const char *message, const guint8 state, const guint16 dc); diff --git a/protocols/oscar/info.c b/protocols/oscar/info.c index 7cc1dbbc..a5a65147 100644 --- a/protocols/oscar/info.c +++ b/protocols/oscar/info.c @@ -40,79 +40,6 @@ int aim_getinfo(aim_session_t *sess, aim_conn_t *conn, const char *sn, guint16 i return 0; } -const char *aim_userinfo_sn(aim_userinfo_t *ui) -{ - - if (!ui) - return NULL; - - return ui->sn; -} - -guint16 aim_userinfo_flags(aim_userinfo_t *ui) -{ - - if (!ui) - return 0; - - return ui->flags; -} - -guint16 aim_userinfo_idle(aim_userinfo_t *ui) -{ - - if (!ui) - return 0; - - return ui->idletime; -} - -float aim_userinfo_warnlevel(aim_userinfo_t *ui) -{ - - if (!ui) - return 0.00; - - return (ui->warnlevel / 10); -} - -time_t aim_userinfo_membersince(aim_userinfo_t *ui) -{ - - if (!ui) - return 0; - - return (time_t)ui->membersince; -} - -time_t aim_userinfo_onlinesince(aim_userinfo_t *ui) -{ - - if (!ui) - return 0; - - return (time_t)ui->onlinesince; -} - -guint32 aim_userinfo_sessionlen(aim_userinfo_t *ui) -{ - - if (!ui) - return 0; - - return ui->sessionlen; -} - -int aim_userinfo_hascap(aim_userinfo_t *ui, guint32 cap) -{ - - if (!ui || !(ui->present & AIM_USERINFO_PRESENT_CAPABILITIES)) - return -1; - - return !!(ui->capabilities & cap); -} - - /* * Capability blocks. * @@ -486,113 +413,6 @@ int aim_extractuserinfo(aim_session_t *sess, aim_bstream_t *bs, aim_userinfo_t * } /* - * Inverse of aim_extractuserinfo() - */ -int aim_putuserinfo(aim_bstream_t *bs, aim_userinfo_t *info) -{ - aim_tlvlist_t *tlvlist = NULL; - - if (!bs || !info) - return -EINVAL; - - aimbs_put8(bs, strlen(info->sn)); - aimbs_putraw(bs, (guint8 *)info->sn, strlen(info->sn)); - - aimbs_put16(bs, info->warnlevel); - - - aim_addtlvtochain16(&tlvlist, 0x0001, info->flags); - aim_addtlvtochain32(&tlvlist, 0x0002, info->membersince); - aim_addtlvtochain32(&tlvlist, 0x0003, info->onlinesince); - aim_addtlvtochain16(&tlvlist, 0x0004, info->idletime); - -#if ICQ_OSCAR_SUPPORT - if (atoi(info->sn) != 0) { - aim_addtlvtochain16(&tlvlist, 0x0006, info->icqinfo.status); - aim_addtlvtochain32(&tlvlist, 0x000a, info->icqinfo.ipaddr); - } -#endif - - aim_addtlvtochain_caps(&tlvlist, 0x000d, info->capabilities); - - aim_addtlvtochain32(&tlvlist, (guint16)((info->flags & AIM_FLAG_AOL) ? 0x0010 : 0x000f), info->sessionlen); - - aimbs_put16(bs, aim_counttlvchain(&tlvlist)); - aim_writetlvchain(bs, &tlvlist); - aim_freetlvchain(&tlvlist); - - return 0; -} - -int aim_sendbuddyoncoming(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *info) -{ - aim_frame_t *fr; - aim_snacid_t snacid; - - if (!sess || !conn || !info) - return -EINVAL; - - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152))) - return -ENOMEM; - - snacid = aim_cachesnac(sess, 0x0003, 0x000b, 0x0000, NULL, 0); - - aim_putsnac(&fr->data, 0x0003, 0x000b, 0x0000, snacid); - aim_putuserinfo(&fr->data, info); - - aim_tx_enqueue(sess, fr); - - return 0; -} - -int aim_sendbuddyoffgoing(aim_session_t *sess, aim_conn_t *conn, const char *sn) -{ - aim_frame_t *fr; - aim_snacid_t snacid; - - if (!sess || !conn || !sn) - return -EINVAL; - - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+1+strlen(sn)))) - return -ENOMEM; - - snacid = aim_cachesnac(sess, 0x0003, 0x000c, 0x0000, NULL, 0); - - aim_putsnac(&fr->data, 0x0003, 0x000c, 0x0000, snacid); - aimbs_put8(&fr->data, strlen(sn)); - aimbs_putraw(&fr->data, (guint8 *)sn, strlen(sn)); - - aim_tx_enqueue(sess, fr); - - return 0; -} - -/* - * Huh? What is this? - */ -int aim_0002_000b(aim_session_t *sess, aim_conn_t *conn, const char *sn) -{ - aim_frame_t *fr; - aim_snacid_t snacid; - - if (!sess || !conn || !sn) - return -EINVAL; - - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+1+strlen(sn)))) - return -ENOMEM; - - snacid = aim_cachesnac(sess, 0x0002, 0x000b, 0x0000, NULL, 0); - - aim_putsnac(&fr->data, 0x0002, 0x000b, 0x0000, snacid); - aimbs_put8(&fr->data, strlen(sn)); - aimbs_putraw(&fr->data, (guint8 *)sn, strlen(sn)); - - aim_tx_enqueue(sess, fr); - - return 0; -} - -/* * Normally contains: * t(0001) - short containing max profile length (value = 1024) * t(0002) - short - unknown (value = 16) [max MIME type length?] diff --git a/protocols/oscar/info.h b/protocols/oscar/info.h index b4d99e9f..5651f187 100644 --- a/protocols/oscar/info.h +++ b/protocols/oscar/info.h @@ -39,6 +39,4 @@ #define AIM_CAPS_EXTCHAN2 0x00100000 #define AIM_CAPS_LAST 0x00200000 -int aim_0002_000b(aim_session_t *sess, aim_conn_t *conn, const char *sn); - #endif /* __OSCAR_INFO_H__ */ diff --git a/protocols/oscar/misc.c b/protocols/oscar/misc.c index 58fb6c31..950cd852 100644 --- a/protocols/oscar/misc.c +++ b/protocols/oscar/misc.c @@ -13,56 +13,6 @@ #include <aim.h> -/* - * aim_bos_setbuddylist(buddylist) - * - * This just builds the "set buddy list" command then queues it. - * - * buddy_list = "Screen Name One&ScreenNameTwo&"; - * - * TODO: Clean this up. - * - * XXX: I can't stress the TODO enough. - * - */ -int aim_bos_setbuddylist(aim_session_t *sess, aim_conn_t *conn, const char *buddy_list) -{ - aim_frame_t *fr; - aim_snacid_t snacid; - int len = 0; - char *localcpy = NULL; - char *tmpptr = NULL; - - if (!buddy_list || !(localcpy = g_strdup(buddy_list))) - return -EINVAL; - - for (tmpptr = strtok(localcpy, "&"); tmpptr; ) { - len += 1 + strlen(tmpptr); - tmpptr = strtok(NULL, "&"); - } - - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+len))) - return -ENOMEM; - - snacid = aim_cachesnac(sess, 0x0003, 0x0004, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0003, 0x0004, 0x0000, snacid); - - strncpy(localcpy, buddy_list, strlen(buddy_list) + 1); - - for (tmpptr = strtok(localcpy, "&"); tmpptr; ) { - - aimbs_put8(&fr->data, strlen(tmpptr)); - aimbs_putraw(&fr->data, (guint8 *)tmpptr, strlen(tmpptr)); - tmpptr = strtok(NULL, "&"); - } - - aim_tx_enqueue(sess, fr); - - g_free(localcpy); - - return 0; -} - /* * aim_bos_setprofile(profile) * @@ -126,40 +76,6 @@ int aim_bos_reqbuddyrights(aim_session_t *sess, aim_conn_t *conn) } /* - * Send a warning to destsn. - * - * Flags: - * AIM_WARN_ANON Send as an anonymous (doesn't count as much) - * - * returns -1 on error (couldn't alloc packet), 0 on success. - * - */ -int aim_send_warning(aim_session_t *sess, aim_conn_t *conn, const char *destsn, guint32 flags) -{ - aim_frame_t *fr; - aim_snacid_t snacid; - guint16 outflags = 0x0000; - - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, strlen(destsn)+13))) - return -ENOMEM; - - snacid = aim_cachesnac(sess, 0x0004, 0x0008, 0x0000, destsn, strlen(destsn)+1); - - aim_putsnac(&fr->data, 0x0004, 0x0008, 0x0000, snacid); - - if (flags & AIM_WARN_ANON) - outflags |= 0x0001; - - aimbs_put16(&fr->data, outflags); - aimbs_put8(&fr->data, strlen(destsn)); - aimbs_putraw(&fr->data, (guint8 *)destsn, strlen(destsn)); - - aim_tx_enqueue(sess, fr); - - return 0; -} - -/* * Generic routine for sending commands. * * @@ -255,90 +171,6 @@ int aim_bos_reqlocaterights(aim_session_t *sess, aim_conn_t *conn) return aim_genericreq_n(sess, conn, 0x0002, 0x0002); } -/* - * Set directory profile data (not the same as aim_bos_setprofile!) - * - * privacy: 1 to allow searching, 0 to disallow. - */ -int aim_setdirectoryinfo(aim_session_t *sess, aim_conn_t *conn, const char *first, const char *middle, const char *last, const char *maiden, const char *nickname, const char *street, const char *city, const char *state, const char *zip, int country, guint16 privacy) -{ - aim_frame_t *fr; - aim_snacid_t snacid; - aim_tlvlist_t *tl = NULL; - - - aim_addtlvtochain16(&tl, 0x000a, privacy); - - if (first) - aim_addtlvtochain_raw(&tl, 0x0001, strlen(first), (guint8 *)first); - if (last) - aim_addtlvtochain_raw(&tl, 0x0002, strlen(last), (guint8 *)last); - if (middle) - aim_addtlvtochain_raw(&tl, 0x0003, strlen(middle), (guint8 *)middle); - if (maiden) - aim_addtlvtochain_raw(&tl, 0x0004, strlen(maiden), (guint8 *)maiden); - - if (state) - aim_addtlvtochain_raw(&tl, 0x0007, strlen(state), (guint8 *)state); - if (city) - aim_addtlvtochain_raw(&tl, 0x0008, strlen(city), (guint8 *)city); - - if (nickname) - aim_addtlvtochain_raw(&tl, 0x000c, strlen(nickname), (guint8 *)nickname); - if (zip) - aim_addtlvtochain_raw(&tl, 0x000d, strlen(zip), (guint8 *)zip); - - if (street) - aim_addtlvtochain_raw(&tl, 0x0021, strlen(street), (guint8 *)street); - - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+aim_sizetlvchain(&tl)))) - return -ENOMEM; - - snacid = aim_cachesnac(sess, 0x0002, 0x0009, 0x0000, NULL, 0); - - aim_putsnac(&fr->data, 0x0002, 0x0009, 0x0000, snacid); - aim_writetlvchain(&fr->data, &tl); - aim_freetlvchain(&tl); - - aim_tx_enqueue(sess, fr); - - return 0; -} - -/* XXX pass these in better */ -int aim_setuserinterests(aim_session_t *sess, aim_conn_t *conn, const char *interest1, const char *interest2, const char *interest3, const char *interest4, const char *interest5, guint16 privacy) -{ - aim_frame_t *fr; - aim_tlvlist_t *tl = NULL; - - /* ?? privacy ?? */ - aim_addtlvtochain16(&tl, 0x000a, privacy); - - if (interest1) - aim_addtlvtochain_raw(&tl, 0x0000b, strlen(interest1), (guint8 *)interest1); - if (interest2) - aim_addtlvtochain_raw(&tl, 0x0000b, strlen(interest2), (guint8 *)interest2); - if (interest3) - aim_addtlvtochain_raw(&tl, 0x0000b, strlen(interest3), (guint8 *)interest3); - if (interest4) - aim_addtlvtochain_raw(&tl, 0x0000b, strlen(interest4), (guint8 *)interest4); - if (interest5) - aim_addtlvtochain_raw(&tl, 0x0000b, strlen(interest5), (guint8 *)interest5); - - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+aim_sizetlvchain(&tl)))) - return -ENOMEM; - - aim_cachesnac(sess, 0x0002, 0x000f, 0x0000, NULL, 0); - - aim_putsnac(&fr->data, 0x0002, 0x000f, 0x0000, 0); - aim_writetlvchain(&fr->data, &tl); - aim_freetlvchain(&tl); - - aim_tx_enqueue(sess, fr); - - return 0; -} - /* * Should be generic enough to handle the errors for all groups. * diff --git a/protocols/oscar/oscar.c b/protocols/oscar/oscar.c index 8fbd3026..05be086d 100644 --- a/protocols/oscar/oscar.c +++ b/protocols/oscar/oscar.c @@ -946,9 +946,6 @@ static int gaim_parse_oncoming(aim_session_t *sess, aim_frame_t *fr, ...) { g_hash_table_insert(od->ips, uin, (gpointer) (long) info->icqinfo.ipaddr); } - if (!aim_sncmp(ic->acc->user, info->sn)) - g_snprintf(ic->displayname, sizeof(ic->displayname), "%s", info->sn); - tmp = normalize(info->sn); imcb_buddy_status(ic, tmp, flags, state_string, NULL); imcb_buddy_times(ic, tmp, signon, time_idle); @@ -1535,17 +1532,6 @@ static int gaim_parse_ratechange(aim_session_t *sess, aim_frame_t *fr, ...) { } static int gaim_selfinfo(aim_session_t *sess, aim_frame_t *fr, ...) { - va_list ap; - aim_userinfo_t *info; - struct im_connection *ic = sess->aux_data; - - va_start(ap, fr); - info = va_arg(ap, aim_userinfo_t *); - va_end(ap); - - ic->evil = info->warnlevel/10; - /* ic->correction_time = (info->onlinesince - ic->login_time); */ - return 1; } @@ -2102,47 +2088,6 @@ static int gaim_ssi_parseack( aim_session_t *sess, aim_frame_t *fr, ... ) return( 1 ); } -static void oscar_set_permit_deny(struct im_connection *ic) { - struct oscar_data *od = (struct oscar_data *)ic->proto_data; - if (od->icq) { - GSList *list; - char buf[MAXMSGLEN]; - int at; - - switch(ic->permdeny) { - case 1: - aim_bos_changevisibility(od->sess, od->conn, AIM_VISIBILITYCHANGE_DENYADD, ic->acc->user); - break; - case 2: - aim_bos_changevisibility(od->sess, od->conn, AIM_VISIBILITYCHANGE_PERMITADD, ic->acc->user); - break; - case 3: - list = ic->permit; - at = 0; - while (list) { - at += g_snprintf(buf + at, sizeof(buf) - at, "%s&", (char *)list->data); - list = list->next; - } - aim_bos_changevisibility(od->sess, od->conn, AIM_VISIBILITYCHANGE_PERMITADD, buf); - break; - case 4: - list = ic->deny; - at = 0; - while (list) { - at += g_snprintf(buf + at, sizeof(buf) - at, "%s&", (char *)list->data); - list = list->next; - } - aim_bos_changevisibility(od->sess, od->conn, AIM_VISIBILITYCHANGE_DENYADD, buf); - break; - default: - break; - } - } else { - if (od->sess->ssi.received_data) - aim_ssi_setpermdeny(od->sess, od->conn, ic->permdeny, 0xffffffff); - } -} - static void oscar_add_permit(struct im_connection *ic, char *who) { struct oscar_data *od = (struct oscar_data *)ic->proto_data; if (od->icq) { @@ -2623,7 +2568,6 @@ void oscar_initmodule() ret->add_deny = oscar_add_deny; ret->rem_permit = oscar_rem_permit; ret->rem_deny = oscar_rem_deny; - ret->set_permit_deny = oscar_set_permit_deny; ret->send_typing = oscar_send_typing; ret->handle_cmp = aim_sncmp; diff --git a/protocols/oscar/oscar_util.c b/protocols/oscar/oscar_util.c index 0ce06bd9..7d41d383 100644 --- a/protocols/oscar/oscar_util.c +++ b/protocols/oscar/oscar_util.c @@ -1,96 +1,6 @@ #include <aim.h> #include <ctype.h> -int aimutil_putstr(u_char *dest, const char *src, int len) -{ - memcpy(dest, src, len); - return len; -} - -/* - * Tokenizing functions. Used to portably replace strtok/sep. - * -- DMP. - * - */ -int aimutil_tokslen(char *toSearch, int index, char dl) -{ - int curCount = 1; - char *next; - char *last; - int toReturn; - - last = toSearch; - next = strchr(toSearch, dl); - - while(curCount < index && next != NULL) { - curCount++; - last = next + 1; - next = strchr(last, dl); - } - - if ((curCount < index) || (next == NULL)) - toReturn = strlen(toSearch) - (curCount - 1); - else - toReturn = next - toSearch - (curCount - 1); - - return toReturn; -} - -int aimutil_itemcnt(char *toSearch, char dl) -{ - int curCount; - char *next; - - curCount = 1; - - next = strchr(toSearch, dl); - - while(next != NULL) { - curCount++; - next = strchr(next + 1, dl); - } - - return curCount; -} - -char *aimutil_itemidx(char *toSearch, int index, char dl) -{ - int curCount; - char *next; - char *last; - char *toReturn; - - curCount = 0; - - last = toSearch; - next = strchr(toSearch, dl); - - while (curCount < index && next != NULL) { - curCount++; - last = next + 1; - next = strchr(last, dl); - } - - if (curCount < index) { - toReturn = g_strdup(""); - } - next = strchr(last, dl); - - if (curCount < index) { - toReturn = g_strdup(""); - } else { - if (next == NULL) { - toReturn = g_malloc((strlen(last) + 1) * sizeof(char)); - strcpy(toReturn, last); - } else { - toReturn = g_malloc((next - last + 1) * sizeof(char)); - memcpy(toReturn, last, (next - last)); - toReturn[next - last] = '\0'; - } - } - return toReturn; -} - /* * int snlen(const char *) * diff --git a/protocols/oscar/rxhandlers.c b/protocols/oscar/rxhandlers.c index 7014e693..bd071505 100644 --- a/protocols/oscar/rxhandlers.c +++ b/protocols/oscar/rxhandlers.c @@ -285,18 +285,6 @@ aim_rxcallback_t aim_callhandler(aim_session_t *sess, aim_conn_t *conn, guint16 return aim_callhandler(sess, conn, family, AIM_CB_SPECIAL_DEFAULT); } -void aim_clonehandlers(aim_session_t *sess, aim_conn_t *dest, aim_conn_t *src) -{ - struct aim_rxcblist_s *cur; - - for (cur = (struct aim_rxcblist_s *)src->handlerlist; cur; cur = cur->next) { - aim_conn_addhandler(sess, dest, cur->family, cur->type, - cur->handler, cur->flags); - } - - return; -} - static int aim_callhandler_noparam(aim_session_t *sess, aim_conn_t *conn,guint16 family, guint16 type, aim_frame_t *ptr) { aim_rxcallback_t userfunc; diff --git a/protocols/oscar/search.c b/protocols/oscar/search.c index 3570e4df..4e0d3858 100644 --- a/protocols/oscar/search.c +++ b/protocols/oscar/search.c @@ -8,27 +8,6 @@ #include <aim.h> -int aim_usersearch_address(aim_session_t *sess, aim_conn_t *conn, const char *address) -{ - aim_frame_t *fr; - aim_snacid_t snacid; - - if (!sess || !conn || !address) - return -EINVAL; - - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+strlen(address)))) - return -ENOMEM; - - snacid = aim_cachesnac(sess, 0x000a, 0x0002, 0x0000, g_strdup(address), strlen(address)+1); - aim_putsnac(&fr->data, 0x000a, 0x0002, 0x0000, snacid); - - aimbs_putraw(&fr->data, (guint8 *)address, strlen(address)); - - aim_tx_enqueue(sess, fr); - - return 0; -} - /* XXX can this be integrated with the rest of the error handling? */ static int error(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) { diff --git a/protocols/oscar/search.h b/protocols/oscar/search.h index 77eeb265..d5cf9b4d 100644 --- a/protocols/oscar/search.h +++ b/protocols/oscar/search.h @@ -1,6 +1,4 @@ #ifndef __OSCAR_SEARCH_H__ #define __OSCAR_SEARCH_H__ -int aim_usersearch_address(aim_session_t *, aim_conn_t *, const char *); - #endif /* __OSCAR_SEARCH_H__ */ diff --git a/protocols/oscar/service.c b/protocols/oscar/service.c index a2678764..a3b37c33 100644 --- a/protocols/oscar/service.c +++ b/protocols/oscar/service.c @@ -360,28 +360,6 @@ int aim_rates_addparam(aim_session_t *sess, aim_conn_t *conn) return 0; } -/* Delete Rate Parameter (group 1, type 9) */ -int aim_rates_delparam(aim_session_t *sess, aim_conn_t *conn) -{ - aim_conn_inside_t *ins = (aim_conn_inside_t *)conn->inside; - aim_frame_t *fr; - aim_snacid_t snacid; - struct rateclass *rc; - - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 512))) - return -ENOMEM; - - snacid = aim_cachesnac(sess, 0x0001, 0x0009, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0001, 0x0009, 0x0000, snacid); - - for (rc = ins->rates; rc; rc = rc->next) - aimbs_put16(&fr->data, rc->classid); - - aim_tx_enqueue(sess, fr); - - return 0; -} - /* Rate Change (group 1, type 0x0a) */ static int ratechange(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) { @@ -430,43 +408,6 @@ static int serverpause(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, return 0; } -/* - * Service Pause Acknowledgement (group 1, type 0x0c) - * - * It is rather important that aim_sendpauseack() gets called for the exact - * same connection that the Server Pause callback was called for, since - * libfaim extracts the data for the SNAC from the connection structure. - * - * Of course, if you don't do that, more bad things happen than just what - * libfaim can cause. - * - */ -int aim_sendpauseack(aim_session_t *sess, aim_conn_t *conn) -{ - aim_frame_t *fr; - aim_snacid_t snacid; - aim_conn_inside_t *ins = (aim_conn_inside_t *)conn->inside; - struct snacgroup *sg; - - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1024))) - return -ENOMEM; - - snacid = aim_cachesnac(sess, 0x0001, 0x000c, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0001, 0x000c, 0x0000, snacid); - - /* - * This list should have all the groups that the original - * Host Online / Server Ready said this host supports. And - * we want them all back after the migration. - */ - for (sg = ins->groups; sg; sg = sg->next) - aimbs_put16(&fr->data, sg->group); - - aim_tx_enqueue(sess, fr); - - return 0; -} - /* Service Resume (group 1, type 0x0d) */ static int serverresume(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) { @@ -519,20 +460,6 @@ static int evilnotify(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, a } /* - * Idle Notification (group 1, type 0x11) - * - * Should set your current idle time in seconds. Note that this should - * never be called consecutively with a non-zero idle time. That makes - * OSCAR do funny things. Instead, just set it once you go idle, and then - * call it again with zero when you're back. - * - */ -int aim_bos_setidle(aim_session_t *sess, aim_conn_t *conn, guint32 idletime) -{ - return aim_genericreq_l(sess, conn, 0x0001, 0x0011, &idletime); -} - -/* * Service Migrate (group 1, type 0x12) * * This is the final SNAC sent on the original connection during a migration. @@ -636,17 +563,6 @@ int aim_bos_setprivacyflags(aim_session_t *sess, aim_conn_t *conn, guint32 flags return aim_genericreq_l(sess, conn, 0x0001, 0x0014, &flags); } -/* - * No-op (group 1, type 0x16) - * - * WinAIM sends these every 4min or so to keep the connection alive. Its not - * real necessary. - * - */ -int aim_nop(aim_session_t *sess, aim_conn_t *conn) -{ - return aim_genericreq_n(sess, conn, 0x0001, 0x0016); -} /* * Set client versions (group 1, subtype 0x17) @@ -810,94 +726,6 @@ static int memrequest(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, a return 0; } -/* Client verification reply (group 1, subtype 0x20) */ -int aim_sendmemblock(aim_session_t *sess, aim_conn_t *conn, guint32 offset, guint32 len, const guint8 *buf, guint8 flag) -{ - aim_frame_t *fr; - aim_snacid_t snacid; - - if (!sess || !conn) - return -EINVAL; - - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+2+16))) - return -ENOMEM; - - snacid = aim_cachesnac(sess, 0x0001, 0x0020, 0x0000, NULL, 0); - - aim_putsnac(&fr->data, 0x0001, 0x0020, 0x0000, snacid); - aimbs_put16(&fr->data, 0x0010); /* md5 is always 16 bytes */ - - if ((flag == AIM_SENDMEMBLOCK_FLAG_ISHASH) && buf && (len == 0x10)) { /* we're getting a hash */ - - aimbs_putraw(&fr->data, buf, 0x10); - - } else if (buf && (len > 0)) { /* use input buffer */ - md5_state_t state; - md5_byte_t digest[0x10]; - - md5_init(&state); - md5_append(&state, (const md5_byte_t *)buf, len); - md5_finish(&state, digest); - - aimbs_putraw(&fr->data, (guint8 *)digest, 0x10); - - } else if (len == 0) { /* no length, just hash NULL (buf is optional) */ - md5_state_t state; - guint8 nil = '\0'; - md5_byte_t digest[0x10]; - - /* - * These MD5 routines are stupid in that you have to have - * at least one append. So thats why this doesn't look - * real logical. - */ - md5_init(&state); - md5_append(&state, (const md5_byte_t *)&nil, 0); - md5_finish(&state, digest); - - aimbs_putraw(&fr->data, (guint8 *)digest, 0x10); - - } else { - - /* - * This data is correct for AIM 3.5.1670. - * - * Using these blocks is as close to "legal" as you can get - * without using an AIM binary. - * - */ - if ((offset == 0x03ffffff) && (len == 0x03ffffff)) { - -#if 1 /* with "AnrbnrAqhfzcd" */ - aimbs_put32(&fr->data, 0x44a95d26); - aimbs_put32(&fr->data, 0xd2490423); - aimbs_put32(&fr->data, 0x93b8821f); - aimbs_put32(&fr->data, 0x51c54b01); -#else /* no filename */ - aimbs_put32(&fr->data, 0x1df8cbae); - aimbs_put32(&fr->data, 0x5523b839); - aimbs_put32(&fr->data, 0xa0e10db3); - aimbs_put32(&fr->data, 0xa46d3b39); -#endif - -/* len can't be 0 here anyway... - } else if ((offset == 0x00001000) && (len == 0x00000000)) { - - aimbs_put32(&fr->data, 0xd41d8cd9); - aimbs_put32(&fr->data, 0x8f00b204); - aimbs_put32(&fr->data, 0xe9800998); - aimbs_put32(&fr->data, 0xecf8427e); -*/ - } else - imcb_error(sess->aux_data, "Warning: unknown hash request"); - - } - - aim_tx_enqueue(sess, fr); - - return 0; -} - static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) { diff --git a/protocols/oscar/ssi.c b/protocols/oscar/ssi.c index f37d98e5..e8502f68 100644 --- a/protocols/oscar/ssi.c +++ b/protocols/oscar/ssi.c @@ -262,28 +262,6 @@ int aim_ssi_getpermdeny(struct aim_ssi_item *list) } /** - * Locally find the presence flag item, and return the setting. The returned setting is a - * bitmask of the user flags that you are visible to. See the AIM_FLAG_* #defines - * in aim.h - * - * @param list A pointer to the current list of items. - * @return Return the current visibility mask. - */ -guint32 aim_ssi_getpresence(struct aim_ssi_item *list) -{ - struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, NULL, NULL, AIM_SSI_TYPE_PRESENCEPREFS); - if (cur) { - aim_tlvlist_t *tlvlist = cur->data; - if (tlvlist) { - aim_tlv_t *tlv = aim_gettlv(tlvlist, 0x00c9, 1); - if (tlv && tlv->length) - return aimutil_get32(tlv->value); - } - } - return 0xFFFFFFFF; -} - -/** * Add the given packet to the holding queue. We totally need to send SSI SNACs one at * a time, so we have a local queue where packets get put before they are sent, and * then we send stuff one at a time, nice and orderly-like. @@ -344,143 +322,6 @@ static int aim_ssi_dispatch(aim_session_t *sess, aim_conn_t *conn) } /** - * Send SNACs necessary to remove all SSI data from the server list, - * and then free the local copy as well. - * - * @param sess The oscar session. - * @param conn The bos connection for this session. - * @return Return 0 if no errors, otherwise return the error number. - */ -int aim_ssi_deletelist(aim_session_t *sess, aim_conn_t *conn) -{ - int num; - struct aim_ssi_item *cur, **items; - - for (cur=sess->ssi.items, num=0; cur; cur=cur->next) - num++; - - if (!(items = g_new0(struct aim_ssi_item *, num))) - return -ENOMEM; - - for (cur=sess->ssi.items, num=0; cur; cur=cur->next) { - items[num] = cur; - num++; - } - - aim_ssi_addmoddel(sess, conn, items, num, AIM_CB_SSI_DEL); - g_free(items); - aim_ssi_dispatch(sess, conn); - aim_ssi_freelist(sess); - - return 0; -} - -/** - * This "cleans" the ssi list. It does a few things, with the intent of making - * sure there ain't nothin' wrong with your SSI. - * -Make sure all buddies are in a group, and all groups have the correct - * additional data. - * -Make sure there are no empty groups in the list. While there is nothing - * wrong empty groups in the SSI, it's wiser to not have them. - * - * @param sess The oscar session. - * @param conn The bos connection for this session. - * @return Return 0 if no errors, otherwise return the error number. - */ -int aim_ssi_cleanlist(aim_session_t *sess, aim_conn_t *conn) -{ - unsigned int i; - struct aim_ssi_item *cur, *parentgroup; - - /* Make sure we actually need to clean out the list */ - for (cur=sess->ssi.items, i=0; cur && !i; cur=cur->next) - /* Any buddies directly in the master group */ - if ((cur->type == AIM_SSI_TYPE_BUDDY) && (cur->gid == 0x0000)) - i++; - if (!i) - return 0; - - /* Remove all the additional data from all groups */ - for (cur=sess->ssi.items; cur; cur=cur->next) - if ((cur->data) && (cur->type == AIM_SSI_TYPE_GROUP)) { - aim_freetlvchain((aim_tlvlist_t **)&cur->data); - cur->data = NULL; - } - - /* If there are buddies directly in the master group, make sure */ - /* there is a group to put them in. Any group, any group at all. */ - for (cur=sess->ssi.items; ((cur) && ((cur->type != AIM_SSI_TYPE_BUDDY) || (cur->gid != 0x0000))); cur=cur->next); - if (!cur) { - for (parentgroup=sess->ssi.items; ((parentgroup) && (parentgroup->type!=AIM_SSI_TYPE_GROUP) && (parentgroup->gid==0x0000)); parentgroup=parentgroup->next); - if (!parentgroup) { - char *newgroup; - newgroup = (char*)g_malloc(strlen("Unknown")+1); - strcpy(newgroup, "Unknown"); - aim_ssi_addgroups(sess, conn, &newgroup, 1); - } - } - - /* Set parentgroup equal to any arbitray group */ - for (parentgroup=sess->ssi.items; parentgroup->gid==0x0000 || parentgroup->type!=AIM_SSI_TYPE_GROUP; parentgroup=parentgroup->next); - - /* If there are any buddies directly in the master group, put them in a real group */ - for (cur=sess->ssi.items; cur; cur=cur->next) - if ((cur->type == AIM_SSI_TYPE_BUDDY) && (cur->gid == 0x0000)) { - aim_ssi_addmoddel(sess, conn, &cur, 1, AIM_CB_SSI_DEL); - cur->gid = parentgroup->gid; - aim_ssi_addmoddel(sess, conn, &cur, 1, AIM_CB_SSI_ADD); - } - - /* Rebuild additional data for all groups */ - for (parentgroup=sess->ssi.items; parentgroup; parentgroup=parentgroup->next) - if (parentgroup->type == AIM_SSI_TYPE_GROUP) - aim_ssi_itemlist_rebuildgroup(&sess->ssi.items, parentgroup); - - /* Send a mod snac for all groups */ - i = 0; - for (cur=sess->ssi.items; cur; cur=cur->next) - if (cur->type == AIM_SSI_TYPE_GROUP) - i++; - if (i > 0) { - /* Allocate an array of pointers to each of the groups */ - struct aim_ssi_item **groups; - if (!(groups = g_new0(struct aim_ssi_item *, i))) - return -ENOMEM; - - for (cur=sess->ssi.items, i=0; cur; cur=cur->next) - if (cur->type == AIM_SSI_TYPE_GROUP) - groups[i] = cur; - - aim_ssi_addmoddel(sess, conn, groups, i, AIM_CB_SSI_MOD); - g_free(groups); - } - - /* Send a del snac for any empty groups */ - i = 0; - for (cur=sess->ssi.items; cur; cur=cur->next) - if ((cur->type == AIM_SSI_TYPE_GROUP) && !(cur->data)) - i++; - if (i > 0) { - /* Allocate an array of pointers to each of the groups */ - struct aim_ssi_item **groups; - if (!(groups = g_new0(struct aim_ssi_item *, i))) - return -ENOMEM; - - for (cur=sess->ssi.items, i=0; cur; cur=cur->next) - if ((cur->type == AIM_SSI_TYPE_GROUP) && !(cur->data)) - groups[i] = cur; - - aim_ssi_addmoddel(sess, conn, groups, i, AIM_CB_SSI_DEL); - g_free(groups); - } - - /* Begin sending SSI SNACs */ - aim_ssi_dispatch(sess, conn); - - return 0; -} - -/** * Add an array of screen names to the given group. * * @param sess The oscar session. @@ -998,128 +839,6 @@ int aim_ssi_delpord(aim_session_t *sess, aim_conn_t *conn, char **sn, unsigned i return 0; } -/** - * Stores your permit/deny setting on the server, and starts using it. - * - * @param sess The oscar session. - * @param conn The bos connection for this session. - * @param permdeny Your permit/deny setting. Can be one of the following: - * 1 - Allow all users - * 2 - Block all users - * 3 - Allow only the users below - * 4 - Block only the users below - * 5 - Allow only users on my buddy list - * @param vismask A bitmask of the class of users to whom you want to be - * visible. See the AIM_FLAG_BLEH #defines in aim.h - * @return Return 0 if no errors, otherwise return the error number. - */ -int aim_ssi_setpermdeny(aim_session_t *sess, aim_conn_t *conn, guint8 permdeny, guint32 vismask) { - struct aim_ssi_item *cur; //, *tmp; -// guint16 j; - aim_tlv_t *tlv; - - if (!sess || !conn) - return -EINVAL; - - /* Look up the permit/deny settings item */ - cur = aim_ssi_itemlist_finditem(sess->ssi.items, NULL, NULL, AIM_SSI_TYPE_PDINFO); - - if (cur) { - /* The permit/deny item exists */ - if (cur->data && (tlv = aim_gettlv(cur->data, 0x00ca, 1))) { - /* Just change the value of the x00ca TLV */ - if (tlv->length != 1) { - tlv->length = 1; - g_free(tlv->value); - tlv->value = (guint8 *)g_malloc(sizeof(guint8)); - } - tlv->value[0] = permdeny; - } else { - /* Need to add the x00ca TLV to the TLV chain */ - aim_addtlvtochain8((aim_tlvlist_t**)&cur->data, 0x00ca, permdeny); - } - - if (cur->data && (tlv = aim_gettlv(cur->data, 0x00cb, 1))) { - /* Just change the value of the x00cb TLV */ - if (tlv->length != 4) { - tlv->length = 4; - g_free(tlv->value); - tlv->value = (guint8 *)g_malloc(4*sizeof(guint8)); - } - aimutil_put32(tlv->value, vismask); - } else { - /* Need to add the x00cb TLV to the TLV chain */ - aim_addtlvtochain32((aim_tlvlist_t**)&cur->data, 0x00cb, vismask); - } - - /* Send the mod item SNAC */ - aim_ssi_addmoddel(sess, conn, &cur, 1, AIM_CB_SSI_MOD); - } else { - /* Need to add the permit/deny item */ - if (!(cur = aim_ssi_itemlist_add(&sess->ssi.items, NULL, NULL, AIM_SSI_TYPE_PDINFO))) - return -ENOMEM; - aim_addtlvtochain8((aim_tlvlist_t**)&cur->data, 0x00ca, permdeny); - aim_addtlvtochain32((aim_tlvlist_t**)&cur->data, 0x00cb, vismask); - aim_ssi_addmoddel(sess, conn, &cur, 1, AIM_CB_SSI_ADD); - } - - /* Begin sending SSI SNACs */ - aim_ssi_dispatch(sess, conn); - - return 0; -} - -/** - * Stores your setting for whether you should show up as idle or not. - * - * @param sess The oscar session. - * @param conn The bos connection for this session. - * @param presence I think it's a bitmask, but I only know what one of the bits is: - * 0x00000400 - Allow others to see your idle time - * @return Return 0 if no errors, otherwise return the error number. - */ -int aim_ssi_setpresence(aim_session_t *sess, aim_conn_t *conn, guint32 presence) { - struct aim_ssi_item *cur; //, *tmp; -// guint16 j; - aim_tlv_t *tlv; - - if (!sess || !conn) - return -EINVAL; - - /* Look up the item */ - cur = aim_ssi_itemlist_finditem(sess->ssi.items, NULL, NULL, AIM_SSI_TYPE_PRESENCEPREFS); - - if (cur) { - /* The item exists */ - if (cur->data && (tlv = aim_gettlv(cur->data, 0x00c9, 1))) { - /* Just change the value of the x00c9 TLV */ - if (tlv->length != 4) { - tlv->length = 4; - g_free(tlv->value); - tlv->value = (guint8 *)g_malloc(4*sizeof(guint8)); - } - aimutil_put32(tlv->value, presence); - } else { - /* Need to add the x00c9 TLV to the TLV chain */ - aim_addtlvtochain32((aim_tlvlist_t**)&cur->data, 0x00c9, presence); - } - - /* Send the mod item SNAC */ - aim_ssi_addmoddel(sess, conn, &cur, 1, AIM_CB_SSI_MOD); - } else { - /* Need to add the item */ - if (!(cur = aim_ssi_itemlist_add(&sess->ssi.items, NULL, NULL, AIM_SSI_TYPE_PRESENCEPREFS))) - return -ENOMEM; - aim_addtlvtochain32((aim_tlvlist_t**)&cur->data, 0x00c9, presence); - aim_ssi_addmoddel(sess, conn, &cur, 1, AIM_CB_SSI_ADD); - } - - /* Begin sending SSI SNACs */ - aim_ssi_dispatch(sess, conn); - - return 0; -} - /* * Request SSI Rights. */ @@ -1142,37 +861,6 @@ static int parserights(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, return ret; } -/* - * Request SSI Data. - * - * The data will only be sent if it is newer than the posted local - * timestamp and revision. - * - * Note that the client should never increment the revision, only the server. - * - */ -int aim_ssi_reqdata(aim_session_t *sess, aim_conn_t *conn, time_t localstamp, guint16 localrev) -{ - aim_frame_t *fr; - aim_snacid_t snacid; - - if (!sess || !conn) - return -EINVAL; - - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+4+2))) - return -ENOMEM; - - snacid = aim_cachesnac(sess, AIM_CB_FAM_SSI, AIM_CB_SSI_REQLIST, 0x0000, NULL, 0); - - aim_putsnac(&fr->data, AIM_CB_FAM_SSI, AIM_CB_SSI_REQLIST, 0x0000, snacid); - aimbs_put32(&fr->data, localstamp); - aimbs_put16(&fr->data, localrev); - - aim_tx_enqueue(sess, fr); - - return 0; -} - int aim_ssi_reqalldata(aim_session_t *sess, aim_conn_t *conn) { aim_frame_t *fr; diff --git a/protocols/oscar/ssi.h b/protocols/oscar/ssi.h index 94b18d60..60d9faa5 100644 --- a/protocols/oscar/ssi.h +++ b/protocols/oscar/ssi.h @@ -44,7 +44,6 @@ struct aim_ssi_item { /* These build the actual SNACs and queue them to be sent */ int aim_ssi_reqrights(aim_session_t *sess, aim_conn_t *conn); -int aim_ssi_reqdata(aim_session_t *sess, aim_conn_t *conn, time_t localstamp, guint16 localrev); int aim_ssi_reqalldata(aim_session_t *sess, aim_conn_t *conn); int aim_ssi_enable(aim_session_t *sess, aim_conn_t *conn); int aim_ssi_addmoddel(aim_session_t *sess, aim_conn_t *conn, struct aim_ssi_item **items, unsigned int num, guint16 subtype); @@ -56,10 +55,8 @@ struct aim_ssi_item *aim_ssi_itemlist_find(struct aim_ssi_item *list, guint16 gi struct aim_ssi_item *aim_ssi_itemlist_finditem(struct aim_ssi_item *list, char *gn, char *sn, guint16 type); struct aim_ssi_item *aim_ssi_itemlist_findparent(struct aim_ssi_item *list, char *sn); int aim_ssi_getpermdeny(struct aim_ssi_item *list); -guint32 aim_ssi_getpresence(struct aim_ssi_item *list); /* Send packets */ -int aim_ssi_cleanlist(aim_session_t *sess, aim_conn_t *conn); int aim_ssi_addbuddies(aim_session_t *sess, aim_conn_t *conn, char *gn, char **sn, unsigned int num, unsigned int flags); int aim_ssi_addmastergroup(aim_session_t *sess, aim_conn_t *conn); int aim_ssi_addgroups(aim_session_t *sess, aim_conn_t *conn, char **gn, unsigned int num); @@ -68,10 +65,7 @@ int aim_ssi_movebuddy(aim_session_t *sess, aim_conn_t *conn, char *oldgn, char * int aim_ssi_delbuddies(aim_session_t *sess, aim_conn_t *conn, char *gn, char **sn, unsigned int num); int aim_ssi_delmastergroup(aim_session_t *sess, aim_conn_t *conn); int aim_ssi_delgroups(aim_session_t *sess, aim_conn_t *conn, char **gn, unsigned int num); -int aim_ssi_deletelist(aim_session_t *sess, aim_conn_t *conn); int aim_ssi_delpord(aim_session_t *sess, aim_conn_t *conn, char **sn, unsigned int num, guint16 type); -int aim_ssi_setpermdeny(aim_session_t *sess, aim_conn_t *conn, guint8 permdeny, guint32 vismask); -int aim_ssi_setpresence(aim_session_t *sess, aim_conn_t *conn, guint32 presence); int aim_ssi_auth_request(aim_session_t *sess, aim_conn_t *conn, char *uin, char *reason); int aim_ssi_auth_reply(aim_session_t *sess, aim_conn_t *conn, char *uin, int yesno, char *reason); diff --git a/protocols/oscar/tlv.c b/protocols/oscar/tlv.c index 9d827caf..89ef6f26 100644 --- a/protocols/oscar/tlv.c +++ b/protocols/oscar/tlv.c @@ -222,39 +222,6 @@ int aim_addtlvtochain32(aim_tlvlist_t **list, const guint16 t, const guint32 v) } /** - * aim_addtlvtochain_availmsg - Add a ICQ availability message to a TLV chain - * @list: Destination chain - * @type: TLV type to add - * @val: Value to add - * - * Adds a available message to a TLV chain - * - */ -int aim_addtlvtochain_availmsg(aim_tlvlist_t **list, const guint16 t, const char *msg) -{ - int ret; - guint16 unknown_data = 0x00; - guint8 add_data_len = 4; - guint16 msg_len = strlen(msg); - guint8 total_len = strlen(msg) + add_data_len; - guint8 *data, *cur; - guint8 alloc_len = msg_len + (3*sizeof(guint16)) + (2*sizeof(guint8)); - data = cur = g_malloc(alloc_len); - - cur += aimutil_put16(cur, 2); - cur += aimutil_put8(cur, add_data_len); - cur += aimutil_put8(cur, total_len); - cur += aimutil_put16(cur, msg_len); - cur += aimutil_putstr(cur, msg, msg_len); - cur += aimutil_put16(cur, unknown_data); - - ret = aim_addtlvtochain_raw(list, t, alloc_len, data); - g_free(data); - - return ret; -} - -/** * aim_addtlvtochain_caps - Add a capability block to a TLV chain * @list: Destination chain * @type: TLV type to add @@ -279,18 +246,6 @@ int aim_addtlvtochain_caps(aim_tlvlist_t **list, const guint16 t, const guint32 return aim_addtlvtochain_raw(list, t, aim_bstream_curpos(&bs), buf); } -int aim_addtlvtochain_userinfo(aim_tlvlist_t **list, guint16 type, aim_userinfo_t *ui) -{ - guint8 buf[1024]; /* bleh */ - aim_bstream_t bs; - - aim_bstream_init(&bs, buf, sizeof(buf)); - - aim_putuserinfo(&bs, ui); - - return aim_addtlvtochain_raw(list, type, aim_bstream_curpos(&bs), buf); -} - /** * aim_addtlvtochain_noval - Add a blank TLV to a TLV chain * @list: Destination chain diff --git a/protocols/purple/Makefile b/protocols/purple/Makefile index e02641c1..562b4db1 100644 --- a/protocols/purple/Makefile +++ b/protocols/purple/Makefile @@ -38,7 +38,7 @@ $(objects): ../../Makefile.settings Makefile $(objects): %.o: $(_SRCDIR_)%.c @echo '*' Compiling $< - @$(CC) -c $(CFLAGS) $< -o $@ + @$(CC) -c $(CFLAGS) $(CFLAGS_BITLBEE) $< -o $@ purple_mod.o: $(objects) @echo '*' Linking purple_mod.o diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index d107dc2f..6e9682ed 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -3,7 +3,7 @@ * BitlBee - An IRC to IM gateway * * libpurple module - Main file * * * -* Copyright 2009-2010 Wilmer van der Gaast <wilmer@gaast.net> * +* Copyright 2009-2012 Wilmer van der Gaast <wilmer@gaast.net> * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * diff --git a/protocols/skype/.mailmap b/protocols/skype/.mailmap deleted file mode 100644 index cc8d43f9..00000000 --- a/protocols/skype/.mailmap +++ /dev/null @@ -1 +0,0 @@ -Miklos Vajna <vmiklos@frugalware.org> diff --git a/protocols/skype/HACKING b/protocols/skype/HACKING index f5516832..935856a7 100644 --- a/protocols/skype/HACKING +++ b/protocols/skype/HACKING @@ -17,10 +17,64 @@ python skyped.py -n -d 4) irssi -== Get the code from git -To get the code directly from git, you need: +== Tests -git clone git://vmiklos.hu/bitlbee-skype -cd bitlbee-skype -make autogen +The plugin is tested with a mocked IRC client and a mocked skyped. + +=== Requirements + +Python pexpect module is required to run the tests. + +To run tests with bitlbee built in a development tree and not (the one) +installed in the system (e.g. /usr), make sure to specify --plugindir= option to +./configure script during the build process: + +bitlbee% ./configure --skype=1 --plugindir="$(realpath .)" + +Otherwise bitlbee will try to load skype.so (among other things) from /usr/lib, +which is probably not what you want to test, or produce "Unknown protocol" +error. + +=== Running + +Tests can be run by running test.py script in this ("protocols/skype") +directory. + +For more control over how/which tests are being run from there, use "python -m +unittest" command: + +bitlbee/protocols/skype% python -m unittest test +bitlbee/protocols/skype% python -m unittest -f test +bitlbee/protocols/skype% python -m unittest test.Test.testMsg + +If bitlbee crashes during tests with SIGSEGV (segmentation fault), it's likely +that there is some problem with skype.c plugin. +To get a backtrace of such crash, use: + +bitlbee/protocols/skype% ATTACH_GDB=true python -m unittest test.Test.testMsg + +Example shows running "testMsg" test with gdb attached to bitlbee, which will +produce full backtrace in "t/gdb-<pid>.log" files (see pid in pexpect error +output of the test). + +=== Adding new tests + +To add a new test, the following steps are necessary: + +1) Add a new -skyped.mock file: just do the test manually, copy&paste the +skyped output and clean it up, so Alice talks to Bob. You can test the created +mock file by starting skyped with the -m option, and testing it from an IRC +client manually. + +2) Add a new -bitlbee.mock file: do the test manually from irssi, and use: + +/connect -rawlog rawlog localhost + +Then clean up the rawlog: the input lines are parsed as matching patterns, so +boring prefix/suffix text can be left out, non-interesting lines can be +deleted. The output lines still have to be strict IRC commands, as usual. + +3) Add the new test to test.py and run it! + +// vim: ft=asciidoc diff --git a/protocols/skype/Makefile b/protocols/skype/Makefile index 455a21f2..6548bfb9 100644 --- a/protocols/skype/Makefile +++ b/protocols/skype/Makefile @@ -3,10 +3,7 @@ ifdef _SRCDIR_ _SRCDIR_ := $(_SRCDIR_)protocols/skype/ endif -VERSION = 0.9.0 DATE := $(shell date +%Y-%m-%d) -# latest stable -BITLBEE_VERSION = 3.0.1 INSTALL = install ASCIIDOC = yes @@ -16,69 +13,17 @@ else MANPAGES = endif -ifeq ($(BITLBEE),yes) -LIBS = skype.$(SHARED_EXT) -else -LIBS = -endif - -all: $(LIBS) $(MANPAGES) - -skype.$(SHARED_EXT): $(_SRCDIR_)skype.c config.mak -ifeq ($(BITLBEE),yes) - $(CC) $(CFLAGS) $(SHARED_FLAGS) -o skype.$(SHARED_EXT) $(_SRCDIR_)skype.c $(LDFLAGS) -endif - -install: all install-doc -ifeq ($(BITLBEE),yes) - $(INSTALL) -d $(DESTDIR)$(plugindir) - $(INSTALL) skype.$(SHARED_EXT) $(DESTDIR)$(plugindir) -endif -ifeq ($(SKYPE4PY),yes) - $(INSTALL) -d $(DESTDIR)$(bindir) - $(INSTALL) -d $(DESTDIR)$(sysconfdir) - $(INSTALL) skyped.py $(DESTDIR)$(bindir)/skyped - perl -p -i -e 's|/usr/local/etc/skyped|$(sysconfdir)|' $(DESTDIR)$(bindir)/skyped - $(INSTALL) -m644 skyped.conf.dist $(DESTDIR)$(sysconfdir)/skyped.conf - perl -p -i -e 's|\$${prefix}|$(prefix)|' $(DESTDIR)$(sysconfdir)/skyped.conf - $(INSTALL) -m644 skyped.cnf $(DESTDIR)$(sysconfdir) -endif - -client: $(_SRCDIR_)client.c - -autogen: configure.ac - cp $(shell ls /usr/share/automake-*/install-sh | tail -n1) ./ - autoconf +all: $(MANPAGES) clean: - rm -f $(LIBS) $(MANPAGES) - -distclean: clean - rm -f config.log config.mak config.status $(MANPAGES) - -autoclean: distclean - rm -rf aclocal.m4 autom4te.cache configure install-sh + rm -f $(MANPAGES) # take this from the kernel check: - perl checkpatch.pl --no-tree --file skype.c + perl checkpatch.pl --show-types --ignore LONG_LINE,CAMELCASE --no-tree --file skype.c test: all - $(MAKE) -C t/ all - -dist: - git archive --format=tar --prefix=bitlbee-skype-$(VERSION)/ HEAD | tar xf - - mkdir -p bitlbee-skype-$(VERSION) - git log --no-merges |git name-rev --tags --stdin > bitlbee-skype-$(VERSION)/Changelog - make -C bitlbee-skype-$(VERSION) autogen - tar czf bitlbee-skype-$(VERSION).tar.gz bitlbee-skype-$(VERSION) - rm -rf bitlbee-skype-$(VERSION) - -release: - git tag $(VERSION) - $(MAKE) dist - gpg --comment "See http://vmiklos.hu/gpg/ for info" \ - -ba bitlbee-skype-$(VERSION).tar.gz + ./test.py doc: $(MANPAGES) @@ -91,17 +36,5 @@ endif uninstall-doc: rm -f $(DESTDIR)$(MANDIR)/man1/skyped.1* -HEADER.html: README Makefile - asciidoc -a toc -a numbered -a sectids -o HEADER.html -a icons -a data-uri --attribute iconsdir=./images/icons README - sed -i 's|@VERSION@|$(VERSION)|g' HEADER.html - sed -i 's|@BITLBEE_VERSION@|$(BITLBEE_VERSION)|g' HEADER.html - -Changelog: .git/refs/heads/master - git log --no-merges |git name-rev --tags --stdin >Changelog - -AUTHORS: .git/refs/heads/master - git shortlog -s -n |sed 's/.*\t//'> AUTHORS - %.1: $(_SRCDIR_)%.txt $(_SRCDIR_)asciidoc.conf - a2x --asciidoc-opts="-f $(_SRCDIR_)asciidoc.conf" \ - -a bs_version=$(VERSION) -a bs_date=$(DATE) -f manpage -D . $< + a2x --asciidoc-opts="-f $(_SRCDIR_)asciidoc.conf" -a bee_date=$(DATE) -f manpage -D . $< diff --git a/protocols/skype/README b/protocols/skype/README index 2c962d54..b9f22481 100644 --- a/protocols/skype/README +++ b/protocols/skype/README @@ -30,7 +30,7 @@ not..) == Requirements -* Skype >= 1.4.0.99. The latest version I've tested is 2.1.0.81. +* Skype >= 1.4.0.99. The latest version I've tested is 4.1.0.20. * BitlBee >= 3.0. The latest version I've tested is @BITLBEE_VERSION@. Use old versions (see the NEWS file about which one) if you have older BitlBee installed. @@ -144,62 +144,7 @@ This will install the plugin to where BitlBee expects them, which is === Configuring -- Set up `~/.skyped/skyped.conf`: Create the `~/.skyped` directory, copy - `skyped.conf` and `skyped.cnf` from - `/usr/local/etc/skyped/skyped.conf` to `~/.skyped`, adjust `username` - and `password`. The `username` should be your Skype login and the - `password` can be whatever you want, but you will have to specify that - one when adding the Skype account to BitlBee (see later). - -NOTE: Here, and later - `/usr/local/etc` can be different on your installation -if you used the `--sysconfdir` switch when running bitlbee-skype's `configure`. - -- Generate the SSL pem files: - ----- -# cd ~/.skyped -# openssl req -new -x509 -days 365 -nodes -config skyped.cnf -out skyped.cert.pem \ - -keyout skyped.key.pem ----- - -NOTE: Maybe you want to adjust the permissions in the `~/.skyped` -dir. For example make it readable by just your user. - -- Start `skyped` (the tcp server): - ----- -$ skyped ----- - -- Start your `IRC` client, connect to BitlBee and add your account: - ----- -account add skype <user> <pass> -account skype set server localhost ----- - -<user> should be your Skype account name, <pass> should be the one you declared -in `skyped.conf`. If you want to run skyped on a remote machine, replace -`localhost` with the name of the machine. - -If you are running skyped on a custom port: - ----- -account skype set port <port> ----- - -If you want to set your full name (optional): - ----- -account skype set display_name "John Smith" ----- - -If you want to see your skypeout contacts online as well (they are -offline by default): - ----- -account skype set skypeout_offline false ----- +See the manpage of `skyped`. == Setting up Skype in a VNC server (optional) @@ -346,12 +291,14 @@ $ skyped -n -d * `account skype set test_join true` -- Mood texts are not shown by default. If you want to see it: +- Mood texts are not shown by default. - * `account skype set show_moods true` + * If you want to see them: `account skype set show_moods true` + * If you want to change your mood text: `account skype set mood_text 'foo bar'` - Group support: + * To enable: `account skype set read_groups true` * Skype groups are told to BitlBee * The usual `/invite` in a group channel adds the buddy to the group in skype as well (and if necessary, it creates a new group in Skype) @@ -371,7 +318,7 @@ $ skyped -n -d == I would like to have support for ... If something does not work and it's not in the TODO section, then please -contact me! Please also try the link:HACKING[git version] before reporting a bug, your +contact me! Please also try the bzr version before reporting a bug, your problem may be already fixed there. In fact, of course, I wrote this documentation after figured out how to do this @@ -391,9 +338,6 @@ You can reach some screenshots link:shot[here]. == Additional resources -You can reach the Changelog link:Changelog[here], and a gitweb interface -http://vmiklos.hu/gitweb/?p=bitlbee-skype.git[here]. - The Skype API documentation is http://developer.skype.com/resources/public_api_ref.zip[here] if you're interested. diff --git a/protocols/skype/asciidoc.conf b/protocols/skype/asciidoc.conf index 24a649c1..f52b3ad6 100644 --- a/protocols/skype/asciidoc.conf +++ b/protocols/skype/asciidoc.conf @@ -4,14 +4,13 @@ ifdef::backend-docbook[] template::[header-declarations] <refentry> <refentryinfo> - <date>{bs_date}</date> + <date>{bee_date}</date> </refentryinfo> <refmeta> <refentrytitle>{mantitle}</refentrytitle> <manvolnum>{manvolnum}</manvolnum> - <refmiscinfo class="source">bitlbee-skype</refmiscinfo> - <refmiscinfo class="version">{bs_version}</refmiscinfo> - <refmiscinfo class="manual">bitlbee-skype manual</refmiscinfo> + <refmiscinfo class="source">BitlBee</refmiscinfo> + <refmiscinfo class="manual">BitlBee manual</refmiscinfo> </refmeta> <refnamediv> <refname>{manname}</refname> diff --git a/protocols/skype/skype.c b/protocols/skype/skype.c index 8638b5c1..7ce562d4 100644 --- a/protocols/skype/skype.c +++ b/protocols/skype/skype.c @@ -1,7 +1,7 @@ /* * skype.c - Skype plugin for BitlBee * - * Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012 by Miklos Vajna <vmiklos@frugalware.org> + * Copyright (c) 2007-2013 by Miklos Vajna <vmiklos@vmiklos.hu> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,7 +28,7 @@ #define SKYPE_DEFAULT_SERVER "localhost" #define SKYPE_DEFAULT_PORT "2727" -#define IRC_LINE_SIZE 1024 +#define IRC_LINE_SIZE 16384 #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) /* @@ -45,6 +45,8 @@ enum { enum { SKYPE_FILETRANSFER_NEW = 1, + SKYPE_FILETRANSFER_TRANSFERRING, + SKYPE_FILETRANSFER_COMPLETED, SKYPE_FILETRANSFER_FAILED }; @@ -80,6 +82,8 @@ struct skype_data { int call_out; /* Same for file transfers. */ int filetransfer_status; + /* Path of the file being transferred. */ + char *filetransfer_path; /* Using /j #nick we want to have a groupchat with two people. Usually * not (default). */ char *groupchat_with; @@ -113,6 +117,8 @@ struct skype_data { /* Pending user which has to be added to the next group which is * created. */ char *pending_user; + /* If the info command was used, to determine what to do with FULLNAME result. */ + int is_info; }; struct skype_away_state { @@ -189,7 +195,7 @@ int skype_printf(struct im_connection *ic, char *fmt, ...) static void skype_buddy_ask_yes(void *data) { struct skype_buddy_ask_data *bla = data; - skype_printf(bla->ic, "SET USER %s ISAUTHORIZED TRUE", + skype_printf(bla->ic, "SET USER %s ISAUTHORIZED TRUE\n", bla->handle); g_free(bla->handle); g_free(bla); @@ -198,7 +204,7 @@ static void skype_buddy_ask_yes(void *data) static void skype_buddy_ask_no(void *data) { struct skype_buddy_ask_data *bla = data; - skype_printf(bla->ic, "SET USER %s ISAUTHORIZED FALSE", + skype_printf(bla->ic, "SET USER %s ISAUTHORIZED FALSE\n", bla->handle); g_free(bla->handle); g_free(bla); @@ -213,8 +219,7 @@ void skype_buddy_ask(struct im_connection *ic, char *handle, char *message) bla->ic = ic; bla->handle = g_strdup(handle); - buf = g_strdup_printf("The user %s wants to add you to " - "his/her buddy list, saying: '%s'.", handle, message); + buf = g_strdup_printf("The user %s wants to add you to his/her buddy list, saying: '%s'.", handle, message); imcb_ask(ic, buf, bla, skype_buddy_ask_yes, skype_buddy_ask_no); g_free(buf); } @@ -222,7 +227,7 @@ void skype_buddy_ask(struct im_connection *ic, char *handle, char *message) static void skype_call_ask_yes(void *data) { struct skype_buddy_ask_data *bla = data; - skype_printf(bla->ic, "SET CALL %s STATUS INPROGRESS", + skype_printf(bla->ic, "SET CALL %s STATUS INPROGRESS\n", bla->handle); g_free(bla->handle); g_free(bla); @@ -231,7 +236,7 @@ static void skype_call_ask_yes(void *data) static void skype_call_ask_no(void *data) { struct skype_buddy_ask_data *bla = data; - skype_printf(bla->ic, "SET CALL %s STATUS FINISHED", + skype_printf(bla->ic, "SET CALL %s STATUS FINISHED\n", bla->handle); g_free(bla->handle); g_free(bla); @@ -316,8 +321,10 @@ static void skype_parse_users(struct im_connection *ic, char *line) char **i, **nicks; nicks = g_strsplit(line + 6, ", ", 0); - for (i = nicks; *i; i++) + for (i = nicks; *i; i++) { skype_printf(ic, "GET USER %s ONLINESTATUS\n", *i); + skype_printf(ic, "GET USER %s FULLNAME\n", *i); + } g_strfreev(nicks); } @@ -371,9 +378,17 @@ static void skype_parse_user(struct im_connection *ic, char *line) *buf ? buf : NULL); if (set_getbool(&ic->acc->set, "show_moods")) imcb_log(ic, "User `%s' changed mood text to `%s'", user, buf); - } else if (!strncmp(ptr, "FULLNAME ", 9)) - sd->info_fullname = g_strdup(ptr + 9); - else if (!strncmp(ptr, "PHONE_HOME ", 11)) + } else if (!strncmp(ptr, "FULLNAME ", 9)) { + char *name = ptr + 9; + if (sd->is_info) { + sd->is_info = FALSE; + sd->info_fullname = g_strdup(name); + } else { + char *buf = g_strdup_printf("%s@skype.com", user); + imcb_rename_buddy(ic, buf, name); + g_free(buf); + } + } else if (!strncmp(ptr, "PHONE_HOME ", 11)) sd->info_phonehome = g_strdup(ptr + 11); else if (!strncmp(ptr, "PHONE_OFFICE ", 13)) sd->info_phoneoffice = g_strdup(ptr + 13); @@ -408,8 +423,7 @@ static void skype_parse_user(struct im_connection *ic, char *line) sd->info_about = g_strdup(st->str); g_string_free(st, TRUE); } - } - else if (!strncmp(ptr, "BIRTHDAY ", 9)) { + } else if (!strncmp(ptr, "BIRTHDAY ", 9)) { sd->info_birthday = g_strdup(ptr + 9); GString *st = g_string_new("Contact Information\n"); @@ -565,10 +579,30 @@ static void skype_parse_user(struct im_connection *ic, char *line) } } -static void skype_parse_chatmessage(struct im_connection *ic, char *line) +static void skype_parse_chatmessage_said_emoted(struct im_connection *ic, struct groupchat *gc, char *body) { struct skype_data *sd = ic->proto_data; char buf[IRC_LINE_SIZE]; + if (!strcmp(sd->type, "SAID")) { + if (!sd->is_edit) + g_snprintf(buf, IRC_LINE_SIZE, "%s", body); + else { + g_snprintf(buf, IRC_LINE_SIZE, "%s %s", set_getstr(&ic->acc->set, "edit_prefix"), body); + sd->is_edit = 0; + } + } else + g_snprintf(buf, IRC_LINE_SIZE, "/me %s", body); + if (!gc) + /* Private message */ + imcb_buddy_msg(ic, sd->handle, buf, 0, 0); + else + /* Groupchat message */ + imcb_chat_msg(gc, sd->handle, buf, 0, 0); +} + +static void skype_parse_chatmessage(struct im_connection *ic, char *line) +{ + struct skype_data *sd = ic->proto_data; char *id = strchr(line, ' '); if (!++id) @@ -626,27 +660,7 @@ static void skype_parse_chatmessage(struct im_connection *ic, char *line) char *body = g_list_nth_data(sd->body, i); if (!strcmp(sd->type, "SAID") || !strcmp(sd->type, "EMOTED")) { - if (!strcmp(sd->type, "SAID")) { - if (!sd->is_edit) - g_snprintf(buf, IRC_LINE_SIZE, "%s", - body); - else { - g_snprintf(buf, IRC_LINE_SIZE, "%s %s", - set_getstr(&ic->acc->set, "edit_prefix"), - body); - sd->is_edit = 0; - } - } else - g_snprintf(buf, IRC_LINE_SIZE, "/me %s", - body); - if (!gc) - /* Private message */ - imcb_buddy_msg(ic, - sd->handle, buf, 0, 0); - else - /* Groupchat message */ - imcb_chat_msg(gc, - sd->handle, buf, 0, 0); + skype_parse_chatmessage_said_emoted(ic, gc, body); } else if (!strcmp(sd->type, "SETTOPIC") && gc) imcb_chat_topic(gc, sd->handle, body, 0); @@ -715,8 +729,7 @@ static void skype_parse_call(struct im_connection *ic, char *line) switch (sd->call_status) { case SKYPE_CALL_RINGING: if (sd->call_out) - imcb_log(ic, "You are currently ringing " - "the user %s.", info); + imcb_log(ic, "You are currently ringing the user %s.", info); else { g_snprintf(buf, IRC_LINE_SIZE, "The user %s is currently ringing you.", @@ -785,6 +798,15 @@ static void skype_parse_filetransfer(struct im_connection *ic, char *line) skype_printf(ic, "GET FILETRANSFER %s PARTNER_HANDLE\n", id); sd->filetransfer_status = SKYPE_FILETRANSFER_FAILED; + } else if (!strcmp(info, "STATUS COMPLETED")) { + skype_printf(ic, "GET FILETRANSFER %s PARTNER_HANDLE\n", id); + sd->filetransfer_status = SKYPE_FILETRANSFER_COMPLETED; + } else if (!strcmp(info, "STATUS TRANSFERRING")) { + skype_printf(ic, "GET FILETRANSFER %s PARTNER_HANDLE\n", id); + sd->filetransfer_status = SKYPE_FILETRANSFER_TRANSFERRING; + } else if (!strncmp(info, "FILEPATH ", 9)) { + info += 9; + sd->filetransfer_path = g_strdup(info); } else if (!strncmp(info, "PARTNER_HANDLE ", 15)) { info += 15; if (!sd->filetransfer_status) @@ -798,6 +820,16 @@ static void skype_parse_filetransfer(struct im_connection *ic, char *line) imcb_log(ic, "Failed to transfer file from user %s.", info); break; + case SKYPE_FILETRANSFER_COMPLETED: + imcb_log(ic, "File transfer from user %s completed.", info); + break; + case SKYPE_FILETRANSFER_TRANSFERRING: + if (sd->filetransfer_path) { + imcb_log(ic, "File transfer from user %s started, saving to %s.", info, sd->filetransfer_path); + g_free(sd->filetransfer_path); + sd->filetransfer_path = NULL; + } + break; } sd->filetransfer_status = 0; } @@ -897,7 +929,7 @@ static void skype_parse_group(struct im_connection *ic, char *line) if (!sd->pending_user) { /* Number of users changed in this group, query its type to see * if it's a custom one we should care about. */ - skype_printf(ic, "GET GROUP %s TYPE", id); + skype_printf(ic, "GET GROUP %s TYPE\n", id); return; } @@ -906,7 +938,7 @@ static void skype_parse_group(struct im_connection *ic, char *line) struct skype_group *sg = skype_group_by_id(ic, atoi(id)); if (sg) { - skype_printf(ic, "ALTER GROUP %d ADDUSER %s", sg->id, sd->pending_user); + skype_printf(ic, "ALTER GROUP %d ADDUSER %s\n", sg->id, sd->pending_user); g_free(sd->pending_user); sd->pending_user = NULL; } else @@ -914,7 +946,7 @@ static void skype_parse_group(struct im_connection *ic, char *line) "No skype group with id %s. That's probably a bug.", id); } else if (!strcmp(info, "TYPE CUSTOM_GROUP")) /* This one is interesting, query its users. */ - skype_printf(ic, "GET GROUP %s USERS", id); + skype_printf(ic, "GET GROUP %s USERS\n", id); } static void skype_parse_chat(struct im_connection *ic, char *line) @@ -982,8 +1014,8 @@ static void skype_parse_chat(struct im_connection *ic, char *line) g_free(sd->adder); sd->adder = NULL; } - } else if (!strncmp(info, "ACTIVEMEMBERS ", 14)) { - info += 14; + } else if (!strncmp(info, "MEMBERS ", 8) || !strncmp(info, "ACTIVEMEMBERS ", 14) ) { + info += 8; gc = bee_chat_by_title(ic->bee, ic, id); /* Hack! We set ->data to TRUE * while we're on the channel @@ -1045,6 +1077,9 @@ static void skype_parse_chats(struct im_connection *ic, char *line) static void skype_parse_groups(struct im_connection *ic, char *line) { + if (!set_getbool(&ic->acc->set, "read_groups")) + return; + char **i; char **groups = g_strsplit(line + 7, ", ", 0); @@ -1123,6 +1158,13 @@ static gboolean skype_read_callback(gpointer data, gint fd, return FALSE; /* Read the whole data. */ st = ssl_read(sd->ssl, buf, sizeof(buf)); + if (st >= IRC_LINE_SIZE-1) { + /* As we don't buffer incoming data, if IRC_LINE_SIZE amount of bytes + * were received, there's a good chance last message was truncated + * and the next recv() will yield garbage. */ + imcb_error(ic, "Unable to handle incoming data from skyped"); + st = 0; + } if (st > 0) { buf[st] = '\0'; /* Then split it up to lines. */ @@ -1177,8 +1219,12 @@ gboolean skype_start_stream(struct im_connection *ic) skype_printf(ic, "SET USERSTATUS ONLINE\n"); /* Auto join to bookmarked chats if requested.*/ - if (set_getbool(&ic->acc->set, "auto_join")) + if (set_getbool(&ic->acc->set, "auto_join")) { skype_printf(ic, "SEARCH BOOKMARKEDCHATS\n"); + skype_printf(ic, "SEARCH ACTIVECHATS\n"); + skype_printf(ic, "SEARCH MISSEDCHATS\n"); + skype_printf(ic, "SEARCH RECENTCHATS\n"); + } return st; } @@ -1227,7 +1273,7 @@ static void skype_logout(struct im_connection *ic) skype_printf(ic, "SET USERSTATUS OFFLINE\n"); - while( ic->groupchats ) + while (ic->groupchats) imcb_chat_free(ic->groupchats->data); for (i = 0; i < g_list_length(sd->groups); i++) { @@ -1314,7 +1360,16 @@ static char *skype_set_display_name(set_t *set, char *value) account_t *acc = set->data; struct im_connection *ic = acc->ic; - skype_printf(ic, "SET PROFILE FULLNAME %s", value); + skype_printf(ic, "SET PROFILE FULLNAME %s\n", value); + return value; +} + +static char *skype_set_mood_text(set_t *set, char *value) +{ + account_t *acc = set->data; + struct im_connection *ic = acc->ic; + + skype_printf(ic, "SET PROFILE MOOD_TEXT %s\n", value); return value; } @@ -1323,7 +1378,7 @@ static char *skype_set_balance(set_t *set, char *value) account_t *acc = set->data; struct im_connection *ic = acc->ic; - skype_printf(ic, "GET PROFILE PSTN_BALANCE"); + skype_printf(ic, "GET PROFILE PSTN_BALANCE\n"); return value; } @@ -1334,7 +1389,7 @@ static void skype_call(struct im_connection *ic, char *value) if (ptr) *ptr = '\0'; - skype_printf(ic, "CALL %s", nick); + skype_printf(ic, "CALL %s\n", nick); g_free(nick); } @@ -1343,7 +1398,7 @@ static void skype_hangup(struct im_connection *ic) struct skype_data *sd = ic->proto_data; if (sd->call_id) { - skype_printf(ic, "SET CALL %s STATUS FINISHED", + skype_printf(ic, "SET CALL %s STATUS FINISHED\n", sd->call_id); g_free(sd->call_id); sd->call_id = 0; @@ -1383,10 +1438,10 @@ static void skype_add_buddy(struct im_connection *ic, char *who, char *group) if (!sg) { /* No such group, we need to create it, then have to * add the user once it's created. */ - skype_printf(ic, "CREATE GROUP %s", group); + skype_printf(ic, "CREATE GROUP %s\n", group); sd->pending_user = g_strdup(nick); } else { - skype_printf(ic, "ALTER GROUP %d ADDUSER %s", sg->id, nick); + skype_printf(ic, "ALTER GROUP %d ADDUSER %s\n", sg->id, nick); } } } @@ -1463,11 +1518,13 @@ struct groupchat *skype_chat_with(struct im_connection *ic, char *who) static void skype_get_info(struct im_connection *ic, char *who) { + struct skype_data *sd = ic->proto_data; char *ptr, *nick; nick = g_strdup(who); ptr = strchr(nick, '@'); if (ptr) *ptr = '\0'; + sd->is_info = TRUE; skype_printf(ic, "GET USER %s FULLNAME\n", nick); skype_printf(ic, "GET USER %s PHONE_HOME\n", nick); skype_printf(ic, "GET USER %s PHONE_OFFICE\n", nick); @@ -1490,11 +1547,6 @@ static void skype_get_info(struct im_connection *ic, char *who) skype_printf(ic, "GET USER %s BIRTHDAY\n", nick); } -static void skype_set_my_name(struct im_connection *ic, char *info) -{ - skype_set_display_name(set_find(&ic->acc->set, "display_name"), info); -} - static void skype_init(account_t *acc) { set_t *s; @@ -1510,6 +1562,9 @@ static void skype_init(account_t *acc) acc); s->flags |= SET_NOSAVE | ACC_SET_ONLINE_ONLY; + s = set_add(&acc->set, "mood_text", NULL, skype_set_mood_text, acc); + s->flags |= ACC_SET_NOSAVE | ACC_SET_ONLINE_ONLY; + s = set_add(&acc->set, "call", NULL, skype_set_call, acc); s->flags |= SET_NOSAVE | ACC_SET_ONLINE_ONLY; @@ -1535,6 +1590,8 @@ static void skype_init(account_t *acc) s = set_add(&acc->set, "edit_prefix", "EDIT:", NULL, acc); + + s = set_add(&acc->set, "read_groups", "false", set_eval_bool, acc); } #if BITLBEE_VERSION_CODE > BITLBEE_VER(3, 0, 1) @@ -1546,12 +1603,14 @@ GList *skype_buddy_action_list(bee_user_t *bu) bu = bu; if (ret == NULL) { - static const struct buddy_action ba[3] = { + static const struct buddy_action ba[2] = { {"CALL", "Initiate a call" }, {"HANGUP", "Hang up a call" }, }; + int i; - ret = g_list_prepend(ret, (void *) ba + 0); + for (i = 0; i < ARRAY_SIZE(ba); i++) + ret = g_list_prepend(ret, (void *)(ba + i)); } return ret; @@ -1582,7 +1641,6 @@ void init_plugin(void) ret->logout = skype_logout; ret->buddy_msg = skype_buddy_msg; ret->get_info = skype_get_info; - ret->set_my_name = skype_set_my_name; ret->away_states = skype_away_states; ret->set_away = skype_set_away; ret->add_buddy = skype_add_buddy; diff --git a/protocols/skype/skyped.py b/protocols/skype/skyped.py index 07c08435..86b1e96a 100644 --- a/protocols/skype/skyped.py +++ b/protocols/skype/skyped.py @@ -1,32 +1,30 @@ #!/usr/bin/env python2.7 -# +# # skyped.py -# -# Copyright (c) 2007, 2008, 2009, 2010, 2011 by Miklos Vajna <vmiklos@frugalware.org> +# +# Copyright (c) 2007-2013 by Miklos Vajna <vmiklos@vmiklos.hu> # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. -# +# # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# +# # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, # USA. # import sys import os import signal -import locale import time import socket -import getopt import Skype4Py import hashlib from ConfigParser import ConfigParser, NoOptionError @@ -53,11 +51,12 @@ def eh(type, value, tb): gobject.MainLoop().quit() if options.conn: options.conn.close() - # shut down client if it's running - try: - skype.skype.Client.Shutdown() - except NameError: - pass + if not options.dont_start_skype: + # shut down client if it's running + try: + skype.skype.Client.Shutdown() + except NameError: + pass sys.exit("Exiting.") sys.excepthook = eh @@ -119,39 +118,35 @@ def skype_idle_handler(skype): try: c = skype.skype.Command("PING", Block=True) skype.skype.SendCommand(c) - except Skype4Py.SkypeAPIError, s: + except (Skype4Py.SkypeAPIError, AttributeError), s: dprint("Warning, pinging Skype failed (%s)." % (s)) + time.sleep(1) return True -def send(sock, txt): +def send(sock, txt, tries=10): global options - from time import sleep - count = 1 - done = False if hasgobject: - while (not done) and (count < 10): - try: - sock.send(txt) - done = True - except Exception, s: - count += 1 - dprint("Warning, sending '%s' failed (%s). count=%d" % (txt, s, count)) - sleep(1) - if not done: + if not options.conn: return + try: + done = sock.sendall(txt) + except socket.error as s: + dprint("Warning, sending '%s' failed (%s)." % (txt, s)) options.conn.close() + options.conn = False else: - while (not done) and (count < 10) and options.conn: + for attempt in xrange(1, tries+1): + if not options.conn: break if wait_for_lock(options.lock, 3, 10, "socket send"): try: - if options.conn: sock.send(txt) + if options.conn: done = sock.sendall(txt) options.lock.release() - done = True - except Exception, s: + except socket.error as s: options.lock.release() - count += 1 dprint("Warning, sending '%s' failed (%s). count=%d" % (txt, s, count)) - sleep(1) - if not done: + time.sleep(1) + else: + break + else: if options.conn: options.conn.close() options.conn = False @@ -206,9 +201,13 @@ def listener(sock, skype): certfile=options.config.sslcert, keyfile=options.config.sslkey, ssl_version=ssl.PROTOCOL_TLSv1) - except ssl.SSLError: - dprint("Warning, SSL init failed, did you create your certificate?") - return False + except (ssl.SSLError, socket.error) as err: + if isinstance(err, ssl.SSLError): + dprint("Warning, SSL init failed, did you create your certificate?") + return False + else: + dprint('Warning, SSL init failed') + return True if hasattr(options.conn, 'handshake'): try: options.conn.handshake() @@ -254,11 +253,13 @@ def dprint(msg): from time import strftime global options - now = strftime("%Y-%m-%d %H:%M:%S") - if options.debug: + import inspect + prefix = strftime("[%Y-%m-%d %H:%M:%S]") + " %s:%d" % inspect.stack()[1][1:3] + sanitized = msg + try: - print now + ": " + msg + print prefix + ": " + msg except Exception, s: try: sanitized = msg.encode("ascii", "backslashreplace") @@ -267,18 +268,57 @@ def dprint(msg): sanitized = "hex [" + msg.encode("hex") + "]" except Error, s: sanitized = "[unable to print debug message]" - print now + "~=" + sanitized + print prefix + "~=" + sanitized + + if options.log: + sock = open(options.log, "a") + sock.write(prefix + ": " + sanitized) + sock.close() + sys.stdout.flush() - if options.log: - sock = open(options.log, "a") - sock.write("%s: %s\n" % (now, msg)) - sock.close() + +class MockedSkype: + """Mock class for Skype4Py.Skype(), in case the -m option is used.""" + def __init__(self, mock): + sock = open(mock) + self.lines = sock.readlines() + + def SendCommand(self, c): + pass + + def Command(self, msg, Block): + if msg == "PING": + return ["PONG"] + line = self.lines[0].strip() + if not line.startswith(">> "): + raise Exception("Corrupted mock input") + line = line[3:] + if line != msg: + raise Exception("'%s' != '%s'" % (line, msg)) + self.lines = self.lines[1:] # drop the expected incoming line + ret = [] + while True: + # and now send back all the following lines, up to the next expected incoming line + if len(self.lines) == 0: + break + if self.lines[0].startswith(">> "): + break + if not self.lines[0].startswith("<< "): + raise Exception("Corrupted mock input") + ret.append(self.lines[0][3:].strip()) + self.lines = self.lines[1:] + return ret class SkypeApi: - def __init__(self): - self.skype = Skype4Py.Skype() - self.skype.OnNotify = self.recv - self.skype.Client.Start() + def __init__(self, mock): + global options + if not mock: + self.skype = Skype4Py.Skype() + self.skype.OnNotify = self.recv + if not options.dont_start_skype: + self.skype.Client.Start() + else: + self.skype = MockedSkype(mock) def recv(self, msg_text): global options @@ -333,48 +373,16 @@ class SkypeApi: try: c = self.skype.Command(e, Block=True) self.skype.SendCommand(c) - self.recv(c.Reply) + if hasattr(c, "Reply"): + self.recv(c.Reply) # Skype4Py answer + else: + for i in c: # mock may return multiple iterable answers + self.recv(i) except Skype4Py.SkypeError: pass except Skype4Py.SkypeAPIError, s: dprint("Warning, sending '%s' failed (%s)." % (e, s)) -class Options: - def __init__(self): - self.cfgpath = os.path.join(os.environ['HOME'], ".skyped", "skyped.conf") - # fall back to system-wide settings - self.syscfgpath = "/usr/local/etc/skyped/skyped.conf" - if os.path.exists(self.syscfgpath) and not os.path.exists(self.cfgpath): - self.cfgpath = self.syscfgpath - self.daemon = True - self.debug = False - self.help = False - self.host = "0.0.0.0" - self.log = None - self.port = None - self.version = False - # well, this is a bit hackish. we store the socket of the last connected client - # here and notify it. maybe later notify all connected clients? - self.conn = None - # this will be read first by the input handler - self.buf = None - - - def usage(self, ret): - print """Usage: skyped [OPTION]... - -skyped is a daemon that acts as a tcp server on top of a Skype instance. - -Options: - -c --config path to configuration file (default: %s) - -d --debug enable debug messages - -h --help this help - -H --host set the tcp host, supports IPv4 and IPv6 (default: %s) - -l --log set the log file in background mode (default: none) - -n --nofork don't run as daemon in the background - -p --port set the tcp port (default: %s) - -v --version display version information""" % (self.cfgpath, self.host, self.port) - sys.exit(ret) def serverloop(options, skype): timeout = 1; # in seconds @@ -417,58 +425,72 @@ def serverloop(options, skype): else: options.last_bitlbee_pong = now -if __name__=='__main__': - options = Options() - try: - opts, args = getopt.getopt(sys.argv[1:], "c:dhH:l:np:v", ["config=", "debug", "help", "host=", "log=", "nofork", "port=", "version"]) - except getopt.GetoptError: - options.usage(1) - for opt, arg in opts: - if opt in ("-c", "--config"): - options.cfgpath = arg - elif opt in ("-d", "--debug"): - options.debug = True - elif opt in ("-h", "--help"): - options.help = True - elif opt in ("-H", "--host"): - options.host = arg - elif opt in ("-l", "--log"): - options.log = arg - elif opt in ("-n", "--nofork"): - options.daemon = False - elif opt in ("-p", "--port"): - options.port = int(arg) - elif opt in ("-v", "--version"): - options.version = True - if options.help: - options.usage(0) - elif options.version: + +def main(args=None): + global options + global skype + + cfgpath = os.path.join(os.environ['HOME'], ".skyped", "skyped.conf") + syscfgpath = "/usr/local/etc/skyped/skyped.conf" + if not os.path.exists(cfgpath) and os.path.exists(syscfgpath): + cfgpath = syscfgpath # fall back to system-wide settings + port = 2727 + + import argparse + parser = argparse.ArgumentParser() + parser.add_argument('-c', '--config', + metavar='path', default=cfgpath, + help='path to configuration file (default: %(default)s)') + parser.add_argument('-H', '--host', default='0.0.0.0', + help='set the tcp host, supports IPv4 and IPv6 (default: %(default)s)') + parser.add_argument('-p', '--port', type=int, + help='set the tcp port (default: %(default)s)') + parser.add_argument('-l', '--log', metavar='path', + help='set the log file in background mode (default: none)') + parser.add_argument('-v', '--version', action='store_true', help='display version information') + parser.add_argument('-n', '--nofork', + action='store_true', help="don't run as daemon in the background") + parser.add_argument('-s', '--dont-start-skype', action='store_true', + help="assume that skype is running independently, don't try to start/stop it") + parser.add_argument('-m', '--mock', help='fake interactions with skype (only useful for tests)') + parser.add_argument('-d', '--debug', action='store_true', help='enable debug messages') + options = parser.parse_args(sys.argv[1:] if args is None else args) + + if options.version: print "skyped %s" % __version__ sys.exit(0) - # parse our config - if not os.path.exists(options.cfgpath): - print "Can't find configuration file at '%s'." % options.cfgpath - print "Use the -c option to specify an alternate one." - sys.exit(1) + + # well, this is a bit hackish. we store the socket of the last connected client + # here and notify it. maybe later notify all connected clients? + options.conn = None + # this will be read first by the input handler + options.buf = None + + if not os.path.exists(options.config): + parser.error(( "Can't find configuration file at '%s'. " + "Use the -c option to specify an alternate one." )% options.config) + + cfgpath = options.config options.config = ConfigParser() - options.config.read(options.cfgpath) - options.config.username = options.config.get('skyped', 'username').split('#')[0] - options.config.password = options.config.get('skyped', 'password').split('#')[0] - options.config.sslkey = os.path.expanduser(options.config.get('skyped', 'key').split('#')[0]) - options.config.sslcert = os.path.expanduser(options.config.get('skyped', 'cert').split('#')[0]) + options.config.read(cfgpath) + options.config.username = options.config.get('skyped', 'username').split('#', 1)[0] + options.config.password = options.config.get('skyped', 'password').split('#', 1)[0] + options.config.sslkey = os.path.expanduser(options.config.get('skyped', 'key').split('#', 1)[0]) + options.config.sslcert = os.path.expanduser(options.config.get('skyped', 'cert').split('#', 1)[0]) + # hack: we have to parse the parameters first to locate the # config file but the -p option should overwrite the value from # the config file try: - options.config.port = int(options.config.get('skyped', 'port').split('#')[0]) + options.config.port = int(options.config.get('skyped', 'port').split('#', 1)[0]) if not options.port: options.port = options.config.port except NoOptionError: pass if not options.port: - options.port = 2727 - dprint("Parsing config file '%s' done, username is '%s'." % (options.cfgpath, options.config.username)) - if options.daemon: + options.port = port + dprint("Parsing config file '%s' done, username is '%s'." % (cfgpath, options.config.username)) + if not options.nofork: pid = os.fork() if pid == 0: nullin = file(os.devnull, 'r') @@ -484,7 +506,7 @@ if __name__=='__main__': if hasgobject: server(options.host, options.port) try: - skype = SkypeApi() + skype = SkypeApi(options.mock) except Skype4Py.SkypeAPIError, s: sys.exit("%s. Are you sure you have started Skype?" % s) if hasgobject: @@ -496,3 +518,6 @@ if __name__=='__main__': options.conn = False options.lock = threading.Lock() server(options.host, options.port, skype) + + +if __name__ == '__main__': main() diff --git a/protocols/skype/skyped.txt b/protocols/skype/skyped.txt index 53f2626d..c5f9abb9 100644 --- a/protocols/skype/skyped.txt +++ b/protocols/skype/skyped.txt @@ -11,7 +11,7 @@ skyped [<options>] == DESCRIPTION Skype supports remote control of the GUI client only via X11 or DBus -messages. This is hard in care you want remote control. This daemon +messages. This is hard in case you want remote control. This daemon listens on a TCP port and runs on the same machine where the GUI client runs. It passes all the input it gets to Skype directly, except for a few commands which is related to authentication. The whole communication @@ -19,7 +19,37 @@ is done via SSL. == CONFIGURATION -See the README for information about how to configure this daemon. +- Set up `~/.skyped/skyped.conf`: Create the `~/.skyped` directory, copy + `skyped.conf` and `skyped.cnf` from `/usr/local/etc/skyped/` to `~/.skyped`, + adjust `username` and `password`. The `username` should be your Skype login and + the `password` can be whatever you want, but you will have to specify that one + when adding the Skype account to BitlBee (see later). + +NOTE: Here, and later - `/usr/local/etc` can be different on your installation +if you used the `--sysconfdir` switch when running the `configure` of BitlBee. + +- Generate the SSL pem files: + +---- +$ cd ~/.skyped +$ openssl req -new -x509 -days 365 -nodes -config skyped.cnf -out skyped.cert.pem \ + -keyout skyped.key.pem +---- + +- Start `skyped` (the TCP server), initially without detaching and enabling debug messages: + +---- +$ skyped -d -n +---- + +- Start your `IRC` client, connect to BitlBee and add your account: + +---- +account add skype <user> <pass> +---- + +`<user>` should be your Skype account name, `<pass>` should be the one you declared +in `skyped.conf`. == OPTIONS @@ -38,9 +68,15 @@ See the README for information about how to configure this daemon. -l, --log:: Set the log file in background mode (default: none) +-m, --mock=<file>:: + Mock mode: replay session from file, instead of connecting to Skype. + -n, --nofork:: Don't run as daemon in the background +-s, --dont-start-skype:: + Assume that skype is running independently, don't try to start/stop it. + -p, --port:: Set the tcp port (default: 2727) @@ -49,4 +85,4 @@ See the README for information about how to configure this daemon. == AUTHOR -Written by Miklos Vajna <vmiklos@frugalware.org> +Written by Miklos Vajna <vmiklos@vmiklos.hu> diff --git a/protocols/skype/t/Makefile b/protocols/skype/t/Makefile deleted file mode 100644 index 9c5e95f9..00000000 --- a/protocols/skype/t/Makefile +++ /dev/null @@ -1,33 +0,0 @@ -PORT=9876 -BITLBEE=/usr/sbin/bitlbee - -export TEST_SKYPE_ID=user -export TEST_SKYPE_PASSWORD=pass - -testfiles := $(wildcard irssi/*.test) -tests := $(patsubst %.test,%,$(testfiles)) - -.PHONY: $(tests) - -all: $(tests) - @echo "passed $$(echo $(testfiles)|wc -w) tests." - -$(tests): % : %.test - @echo "--- Running test $@ ---"; \ - if [ -r "$(BITLBEE)" -a -x "$(BITLBEE)" ]; then \ - bitlbee_binary="$(BITLBEE)"; \ - else \ - bitlbee_basename=`basename $(BITLBEE)`; \ - bitlbee_binary=`which $$bitlbee_basename`; \ - fi; \ - if ! ./livetest-bitlbee.sh "$$bitlbee_binary" $(PORT) irssi/livetest-irssi.sh $< >$@.log; then \ - echo Test failed, log: ;\ - cat $@.log;\ - exit 1;\ - fi;\ - echo "--- OK ---" ;\ - sleep 1 -clean: - rm -r irssi/*.log bitlbeetest.pid dotirssi livetest - - diff --git a/protocols/skype/t/add-yes-bitlbee.mock b/protocols/skype/t/add-yes-bitlbee.mock new file mode 100644 index 00000000..5f17fd33 --- /dev/null +++ b/protocols/skype/t/add-yes-bitlbee.mock @@ -0,0 +1,8 @@ +>> NOTICE AUTH +<< NICK alice +<< USER alice alice localhost :Alice +>> PRIVMSG &bitlbee +<< PRIVMSG &bitlbee :account add skype alice foo +<< PRIVMSG &bitlbee :account skype on +<< PRIVMSG &bitlbee :add skype bob +>> :bob!bob@skype.com JOIN :&bitlbee diff --git a/protocols/skype/t/add-yes-skyped.mock b/protocols/skype/t/add-yes-skyped.mock new file mode 100644 index 00000000..dea175a3 --- /dev/null +++ b/protocols/skype/t/add-yes-skyped.mock @@ -0,0 +1,23 @@ +>> SEARCH GROUPS CUSTOM +<< GROUPS 48, 49 +>> SEARCH FRIENDS +<< USERS echo123 +>> SET USERSTATUS ONLINE +<< USERSTATUS ONLINE +>> SET USERSTATUS ONLINE +<< USERSTATUS ONLINE +>> GET USER echo123 ONLINESTATUS +<< USER echo123 ONLINESTATUS ONLINE +>> GET USER echo123 FULLNAME +<< USER echo123 FULLNAME Echo / Sound Test Service +>> SET USER bob BUDDYSTATUS 2 Please authorize me +<< USER bob BUDDYSTATUS 2 +<< USER bob ISAUTHORIZED TRUE +<< USER bob ISBLOCKED FALSE +<< USER bob BUDDYSTATUS 2 +<< USER bob ONLINESTATUS OFFLINE +<< USER bob FULLNAME skype test203 +<< USER bob BUDDYSTATUS 3 +<< USER bob ONLINESTATUS OFFLINE +<< USER bob ONLINESTATUS ONLINE +<< USER bob TIMEZONE 90000 diff --git a/protocols/skype/t/added-no-bitlbee.mock b/protocols/skype/t/added-no-bitlbee.mock new file mode 100644 index 00000000..d7a70c66 --- /dev/null +++ b/protocols/skype/t/added-no-bitlbee.mock @@ -0,0 +1,9 @@ +>> NOTICE AUTH +<< NICK alice +<< USER alice alice localhost :Alice +>> PRIVMSG &bitlbee +<< PRIVMSG &bitlbee :account add skype alice foo +<< PRIVMSG &bitlbee :account skype on +>> PRIVMSG &bitlbee :skype - New request: The user bob wants to add you +<< PRIVMSG &bitlbee :no +>> PRIVMSG &bitlbee :skype - Rejected diff --git a/protocols/skype/t/added-no-skyped.mock b/protocols/skype/t/added-no-skyped.mock new file mode 100644 index 00000000..0e4bfc8a --- /dev/null +++ b/protocols/skype/t/added-no-skyped.mock @@ -0,0 +1,15 @@ +>> SEARCH GROUPS CUSTOM +<< GROUPS 48, 49 +>> SEARCH FRIENDS +<< USERS echo123 +>> SET USERSTATUS ONLINE +<< USERSTATUS ONLINE +>> SET USERSTATUS ONLINE +<< USERSTATUS ONLINE +>> GET USER echo123 ONLINESTATUS +<< USER echo123 ONLINESTATUS ONLINE +>> GET USER echo123 FULLNAME +<< USER echo123 FULLNAME Echo / Sound Test Service +<< USER bob RECEIVEDAUTHREQUEST Please allow me to see when you are online +>> SET USER bob ISAUTHORIZED FALSE +<< USER bob ISAUTHORIZED FALSE diff --git a/protocols/skype/t/added-yes-bitlbee.mock b/protocols/skype/t/added-yes-bitlbee.mock new file mode 100644 index 00000000..df068f89 --- /dev/null +++ b/protocols/skype/t/added-yes-bitlbee.mock @@ -0,0 +1,9 @@ +>> NOTICE AUTH +<< NICK alice +<< USER alice alice localhost :Alice +>> PRIVMSG &bitlbee +<< PRIVMSG &bitlbee :account add skype alice foo +<< PRIVMSG &bitlbee :account skype on +>> PRIVMSG &bitlbee :skype - New request: The user bob wants to add you +<< PRIVMSG &bitlbee :yes +>> :bob!bob@skype.com JOIN :&bitlbee diff --git a/protocols/skype/t/added-yes-skyped.mock b/protocols/skype/t/added-yes-skyped.mock new file mode 100644 index 00000000..fc3d756f --- /dev/null +++ b/protocols/skype/t/added-yes-skyped.mock @@ -0,0 +1,25 @@ +>> SEARCH GROUPS CUSTOM +<< GROUPS 48, 49 +>> SEARCH FRIENDS +<< USERS echo123 +>> SET USERSTATUS ONLINE +<< USERSTATUS ONLINE +>> SET USERSTATUS ONLINE +<< USERSTATUS ONLINE +>> GET USER echo123 ONLINESTATUS +<< USER echo123 ONLINESTATUS ONLINE +>> GET USER echo123 FULLNAME +<< USER echo123 FULLNAME Echo / Sound Test Service +<< USER bob RECEIVEDAUTHREQUEST Please allow me to see when you are online +>> SET USER bob ISAUTHORIZED TRUE +<< USER bob ISAUTHORIZED TRUE +<< USER bob RECEIVEDAUTHREQUEST +<< USER bob ISAUTHORIZED TRUE +<< USER bob ISBLOCKED FALSE +<< USER bob BUDDYSTATUS 3 +<< USER bob ONLINESTATUS OFFLINE +<< USER bob ONLINESTATUS ONLINE +<< USER bob TIMEZONE 90000 +<< USER bob FULLNAME Miklos V +<< USER bob LANGUAGE hu Hungarian +<< USER bob COUNTRY hu Hungary diff --git a/protocols/skype/t/bitlbee.conf b/protocols/skype/t/bitlbee.conf deleted file mode 100644 index e69de29b..00000000 --- a/protocols/skype/t/bitlbee.conf +++ /dev/null diff --git a/protocols/skype/t/call-bitlbee.mock b/protocols/skype/t/call-bitlbee.mock new file mode 100644 index 00000000..e480e7f3 --- /dev/null +++ b/protocols/skype/t/call-bitlbee.mock @@ -0,0 +1,11 @@ +>> NOTICE AUTH +<< NICK alice +<< USER alice alice localhost :alice +>> PRIVMSG &bitlbee +<< PRIVMSG &bitlbee :account add skype alice foo +<< PRIVMSG &bitlbee :account skype on +>> :bob!bob@skype.com JOIN :&bitlbee +<< PRIVMSG bob :CALL +>> PRIVMSG &bitlbee :skype - You are currently ringing the user bob. +<< PRIVMSG bob :HANGUP +>> PRIVMSG &bitlbee :skype - You cancelled the call to the user bob. diff --git a/protocols/skype/t/call-failed-bitlbee.mock b/protocols/skype/t/call-failed-bitlbee.mock new file mode 100644 index 00000000..aae1d99a --- /dev/null +++ b/protocols/skype/t/call-failed-bitlbee.mock @@ -0,0 +1,9 @@ +>> NOTICE AUTH +<< NICK alice +<< USER alice alice localhost :alice +>> PRIVMSG &bitlbee +<< PRIVMSG &bitlbee :account add skype alice foo +<< PRIVMSG &bitlbee :account skype on +>> PRIVMSG &bitlbee :skype - Logging in: Logged in +<< PRIVMSG bob :CALL +>> PRIVMSG &bitlbee :skype - Error: Call failed: User is offline diff --git a/protocols/skype/t/call-failed-skyped.mock b/protocols/skype/t/call-failed-skyped.mock new file mode 100644 index 00000000..30699f91 --- /dev/null +++ b/protocols/skype/t/call-failed-skyped.mock @@ -0,0 +1,21 @@ +>> SEARCH GROUPS CUSTOM +<< GROUPS 48, 49 +>> SEARCH FRIENDS +<< USERS echo123, bob +>> SET USERSTATUS ONLINE +<< USERSTATUS ONLINE +>> SET USERSTATUS ONLINE +<< USERSTATUS ONLINE +>> GET USER echo123 ONLINESTATUS +<< USER echo123 ONLINESTATUS ONLINE +>> GET USER echo123 FULLNAME +<< USER echo123 FULLNAME Echo / Sound Test Service +>> GET USER bob ONLINESTATUS +<< USER bob ONLINESTATUS OFFLINE +>> GET USER bob FULLNAME +<< USER bob FULLNAME Bob +>> CALL bob +<< CALL 216 STATUS UNPLACED +<< CALL 216 STATUS ROUTING +<< CALL 216 FAILUREREASON 3 +<< CALL 216 STATUS FAILED diff --git a/protocols/skype/t/call-skyped.mock b/protocols/skype/t/call-skyped.mock new file mode 100644 index 00000000..92947ba9 --- /dev/null +++ b/protocols/skype/t/call-skyped.mock @@ -0,0 +1,26 @@ +>> SEARCH GROUPS CUSTOM +<< GROUPS 48, 49 +>> SEARCH FRIENDS +<< USERS echo123, bob +>> SET USERSTATUS ONLINE +<< USERSTATUS ONLINE +>> SET USERSTATUS ONLINE +<< USERSTATUS ONLINE +>> GET USER echo123 ONLINESTATUS +<< USER echo123 ONLINESTATUS OFFLINE +>> GET USER echo123 FULLNAME +<< USER echo123 FULLNAME Echo / Sound Test Service +>> GET USER bob ONLINESTATUS +<< USER bob ONLINESTATUS ONLINE +>> GET USER bob FULLNAME +<< USER bob FULLNAME Bob +>> CALL bob +<< CALL 178 STATUS UNPLACED +<< CALL 178 STATUS ROUTING +<< CALL 178 STATUS RINGING +>> GET CALL 178 PARTNER_HANDLE +<< CALL 178 PARTNER_HANDLE bob +>> SET CALL 178 STATUS FINISHED +<< CALL 178 STATUS CANCELLED +>> GET CALL 178 PARTNER_HANDLE +<< CALL 178 PARTNER_HANDLE bob diff --git a/protocols/skype/t/called-no-bitlbee.mock b/protocols/skype/t/called-no-bitlbee.mock new file mode 100644 index 00000000..c69a0c8b --- /dev/null +++ b/protocols/skype/t/called-no-bitlbee.mock @@ -0,0 +1,10 @@ +>> NOTICE AUTH +<< NICK alice +<< USER alice alice localhost :Alice +>> PRIVMSG &bitlbee +<< PRIVMSG &bitlbee :account add skype alice foo +<< PRIVMSG &bitlbee :account skype on +>> PRIVMSG &bitlbee :skype - New request: The user bob is currently ringing you. +<< PRIVMSG &bitlbee :no +>> PRIVMSG &bitlbee :skype - Rejected: The user bob is currently ringing you. +>> PRIVMSG &bitlbee :skype - You refused the call from user bob. diff --git a/protocols/skype/t/called-no-skyped.mock b/protocols/skype/t/called-no-skyped.mock new file mode 100644 index 00000000..5152fe9e --- /dev/null +++ b/protocols/skype/t/called-no-skyped.mock @@ -0,0 +1,24 @@ +>> SEARCH GROUPS CUSTOM +<< GROUPS 48, 49 +>> SEARCH FRIENDS +<< USERS echo123, bob +>> SET USERSTATUS ONLINE +<< USERSTATUS ONLINE +>> SET USERSTATUS ONLINE +<< USERSTATUS ONLINE +>> GET USER echo123 ONLINESTATUS +<< USER echo123 ONLINESTATUS ONLINE +>> GET USER echo123 FULLNAME +<< USER echo123 FULLNAME Echo / Sound Test Service +>> GET USER bob ONLINESTATUS +<< USER bob ONLINESTATUS ONLINE +>> GET USER bob FULLNAME +<< USER bob FULLNAME Bob +<< CALL 212 CONF_ID 0 +<< CALL 212 STATUS RINGING +>> GET CALL 212 PARTNER_HANDLE +<< CALL 212 PARTNER_HANDLE bob +>> SET CALL 212 STATUS FINISHED +<< CALL 212 STATUS REFUSED +>> GET CALL 212 PARTNER_HANDLE +<< CALL 212 PARTNER_HANDLE bob diff --git a/protocols/skype/t/called-yes-bitlbee.mock b/protocols/skype/t/called-yes-bitlbee.mock new file mode 100644 index 00000000..47c54799 --- /dev/null +++ b/protocols/skype/t/called-yes-bitlbee.mock @@ -0,0 +1,9 @@ +>> NOTICE AUTH +<< NICK alice +<< USER alice alice localhost :Alice +>> PRIVMSG &bitlbee +<< PRIVMSG &bitlbee :account add skype alice foo +<< PRIVMSG &bitlbee :account skype on +>> PRIVMSG &bitlbee :skype - New request: The user bob is currently ringing you. +<< PRIVMSG &bitlbee :yes +>> PRIVMSG &bitlbee :skype - Accepted: The user bob is currently ringing you. diff --git a/protocols/skype/t/called-yes-skyped.mock b/protocols/skype/t/called-yes-skyped.mock new file mode 100644 index 00000000..67cdffe3 --- /dev/null +++ b/protocols/skype/t/called-yes-skyped.mock @@ -0,0 +1,22 @@ +>> SEARCH GROUPS CUSTOM +<< GROUPS 48, 49 +>> SEARCH FRIENDS +<< USERS echo123, bob +>> SET USERSTATUS ONLINE +<< USERSTATUS ONLINE +>> SET USERSTATUS ONLINE +<< USERSTATUS ONLINE +>> GET USER echo123 ONLINESTATUS +<< USER echo123 ONLINESTATUS ONLINE +>> GET USER echo123 FULLNAME +<< USER echo123 FULLNAME Echo / Sound Test Service +>> GET USER bob ONLINESTATUS +<< USER bob ONLINESTATUS ONLINE +>> GET USER bob FULLNAME +<< USER bob FULLNAME Bob +<< CALL 208 CONF_ID 0 +<< CALL 208 STATUS RINGING +>> GET CALL 208 PARTNER_HANDLE +<< CALL 208 PARTNER_HANDLE bob +>> SET CALL 208 STATUS INPROGRESS +<< CALL 208 STATUS INPROGRESS diff --git a/protocols/skype/t/ctcp-help-bitlbee.mock b/protocols/skype/t/ctcp-help-bitlbee.mock new file mode 100644 index 00000000..98522ec1 --- /dev/null +++ b/protocols/skype/t/ctcp-help-bitlbee.mock @@ -0,0 +1,9 @@ +>> NOTICE AUTH +<< NICK alice +<< USER alice alice localhost :Alice +>> PRIVMSG &bitlbee +<< PRIVMSG &bitlbee :account add skype alice foo +<< PRIVMSG &bitlbee :account skype on +>> :bob!bob@skype.com JOIN :&bitlbee +<< PRIVMSG bob :HELP +>> :bob!bob@skype.com NOTICE alice :HELP Supported CTCPs: HANGUP (Hang up a call), CALL (Initiate a call) diff --git a/protocols/skype/t/ctcp-help-skyped.mock b/protocols/skype/t/ctcp-help-skyped.mock new file mode 100644 index 00000000..eacff2e6 --- /dev/null +++ b/protocols/skype/t/ctcp-help-skyped.mock @@ -0,0 +1,16 @@ +>> SEARCH GROUPS CUSTOM +<< GROUPS 48, 49 +>> SEARCH FRIENDS +<< USERS echo123, bob +>> SET USERSTATUS ONLINE +<< USERSTATUS ONLINE +>> SET USERSTATUS ONLINE +<< USERSTATUS ONLINE +>> GET USER echo123 ONLINESTATUS +<< USER echo123 ONLINESTATUS ONLINE +>> GET USER echo123 FULLNAME +<< USER echo123 FULLNAME Echo / Sound Test Service +>> GET USER bob ONLINESTATUS +<< USER bob ONLINESTATUS ONLINE +>> GET USER bob FULLNAME +<< USER bob FULLNAME Bob diff --git a/protocols/skype/t/filetransfer-bitlbee.mock b/protocols/skype/t/filetransfer-bitlbee.mock new file mode 100644 index 00000000..a08e52bc --- /dev/null +++ b/protocols/skype/t/filetransfer-bitlbee.mock @@ -0,0 +1,10 @@ +>> NOTICE AUTH +<< NICK alice +<< USER alice alice localhost :Alice +>> PRIVMSG &bitlbee +<< PRIVMSG &bitlbee :account add skype alice foo +<< PRIVMSG &bitlbee :account skype on +>> :bob!bob@skype.com JOIN :&bitlbee +>> PRIVMSG &bitlbee :skype - The user bob offered a new file for you. +>> PRIVMSG &bitlbee :skype - File transfer from user bob started, saving to /home/alice/text.odt. +>> PRIVMSG &bitlbee :skype - File transfer from user bob completed. diff --git a/protocols/skype/t/filetransfer-skyped.mock b/protocols/skype/t/filetransfer-skyped.mock new file mode 100644 index 00000000..b24fcc94 --- /dev/null +++ b/protocols/skype/t/filetransfer-skyped.mock @@ -0,0 +1,37 @@ +>> SEARCH GROUPS CUSTOM +<< GROUPS 48, 49 +>> SEARCH FRIENDS +<< USERS echo123, bob +>> SET USERSTATUS ONLINE +<< USERSTATUS ONLINE +>> SET USERSTATUS ONLINE +<< USERSTATUS ONLINE +>> GET USER echo123 ONLINESTATUS +<< USER echo123 ONLINESTATUS ONLINE +>> GET USER echo123 FULLNAME +<< USER echo123 FULLNAME Echo / Sound Test Service +>> GET USER bob ONLINESTATUS +<< USER bob ONLINESTATUS ONLINE +>> GET USER bob FULLNAME +<< USER bob FULLNAME Bob +<< FILETRANSFER 208 TYPE INCOMING +<< FILETRANSFER 208 PARTNER_HANDLE bob +<< FILETRANSFER 208 PARTNER_DISPNAME bob +<< FILETRANSFER 208 FILENAME text.odt +<< FILETRANSFER 208 STATUS NEW +<< FILETRANSFER 208 FILESIZE 83534193 +<< FILETRANSFER 208 STARTTIME 1358458276 +<< FILETRANSFER 208 FINISHTIME 0 +<< FILETRANSFER 208 BYTESPERSECOND 0 +<< FILETRANSFER 208 BYTESTRANSFERRED 0 +<< FILETRANSFER 208 FILESIZE 83534193 +>> GET FILETRANSFER 208 PARTNER_HANDLE +<< FILETRANSFER 208 PARTNER_HANDLE bob +<< FILETRANSFER 208 FILEPATH /home/alice/text.odt +<< FILETRANSFER 208 STATUS CONNECTING +<< FILETRANSFER 208 STATUS TRANSFERRING +>> GET FILETRANSFER 208 PARTNER_HANDLE +<< FILETRANSFER 208 PARTNER_HANDLE bob +<< FILETRANSFER 208 STATUS COMPLETED +>> GET FILETRANSFER 208 PARTNER_HANDLE +<< FILETRANSFER 208 PARTNER_HANDLE bob diff --git a/protocols/skype/t/group-read-bitlbee.mock b/protocols/skype/t/group-read-bitlbee.mock new file mode 100644 index 00000000..0f001400 --- /dev/null +++ b/protocols/skype/t/group-read-bitlbee.mock @@ -0,0 +1,14 @@ +>> NOTICE AUTH +<< NICK alice +<< USER alice alice localhost :Alice +>> PRIVMSG &bitlbee +<< PRIVMSG &bitlbee :account add skype alice foo +<< PRIVMSG &bitlbee :account skype set read_groups true +<< PRIVMSG &bitlbee :account skype on +>> :bob!bob@skype.com JOIN :&bitlbee +>> :cecil!cecil@skype.com JOIN :&bitlbee +>> :daniel!daniel@skype.com JOIN :&bitlbee +<< JOIN &family +>> 353 alice = &family :@alice +bob +cecil @root +<< JOIN &work +>> 353 alice = &work :@alice +daniel @root diff --git a/protocols/skype/t/group-read-skyped.mock b/protocols/skype/t/group-read-skyped.mock new file mode 100644 index 00000000..148661a1 --- /dev/null +++ b/protocols/skype/t/group-read-skyped.mock @@ -0,0 +1,36 @@ +>> SEARCH GROUPS CUSTOM +<< GROUPS 70, 71 +>> SEARCH FRIENDS +<< USERS echo123, bob, cecil, daniel, emily +>> SET USERSTATUS ONLINE +<< USERSTATUS ONLINE +>> SET USERSTATUS ONLINE +<< USERSTATUS ONLINE +>> GET GROUP 70 DISPLAYNAME +<< GROUP 70 DISPLAYNAME Family +>> GET GROUP 70 USERS +<< GROUP 70 USERS bob, cecil +>> GET GROUP 71 DISPLAYNAME +<< GROUP 71 DISPLAYNAME Work +>> GET GROUP 71 USERS +<< GROUP 71 USERS daniel, emily +>> GET USER echo123 ONLINESTATUS +<< USER echo123 ONLINESTATUS ONLINE +>> GET USER echo123 FULLNAME +<< USER echo123 FULLNAME Echo / Sound Test Service +>> GET USER bob ONLINESTATUS +<< USER bob ONLINESTATUS ONLINE +>> GET USER bob FULLNAME +<< USER bob FULLNAME Bob +>> GET USER cecil ONLINESTATUS +<< USER cecil ONLINESTATUS ONLINE +>> GET USER cecil FULLNAME +<< USER cecil FULLNAME Cecil +>> GET USER daniel ONLINESTATUS +<< USER daniel ONLINESTATUS ONLINE +>> GET USER daniel FULLNAME +<< USER daniel FULLNAME Daniel +>> GET USER emily ONLINESTATUS +<< USER emily ONLINESTATUS OFFLINE +>> GET USER emily FULLNAME +<< USER emily FULLNAME Emily diff --git a/protocols/skype/t/groupchat-invite-bitlbee.mock b/protocols/skype/t/groupchat-invite-bitlbee.mock new file mode 100644 index 00000000..7b44427f --- /dev/null +++ b/protocols/skype/t/groupchat-invite-bitlbee.mock @@ -0,0 +1,11 @@ +>> NOTICE AUTH +<< NICK alice +<< USER alice alice localhost :Alice +>> PRIVMSG &bitlbee +<< PRIVMSG &bitlbee :account add skype alice foo +<< PRIVMSG &bitlbee :account skype on +>> :bob!bob@skype.com JOIN :&bitlbee +<< PRIVMSG &bitlbee :chat with bob +>> 353 alice = ##alice/$bob;a7ab206ec780 :@alice bob @root +<< INVITE cecil ##alice/$bob;a7ab206ec780 +>> cecil@skype.com JOIN :##alice/$bob;a7ab206ec780 diff --git a/protocols/skype/t/groupchat-invite-skyped.mock b/protocols/skype/t/groupchat-invite-skyped.mock new file mode 100644 index 00000000..214ebec0 --- /dev/null +++ b/protocols/skype/t/groupchat-invite-skyped.mock @@ -0,0 +1,48 @@ +>> SEARCH GROUPS CUSTOM +<< GROUPS 48, 49 +>> SEARCH FRIENDS +<< USERS echo123, bob, cecil +>> SET USERSTATUS ONLINE +<< USERSTATUS ONLINE +>> SET USERSTATUS ONLINE +<< USERSTATUS ONLINE +>> GET USER echo123 ONLINESTATUS +<< USER echo123 ONLINESTATUS ONLINE +>> GET USER echo123 FULLNAME +<< USER echo123 FULLNAME Echo / Sound Test Service +>> GET USER bob ONLINESTATUS +<< USER bob ONLINESTATUS ONLINE +>> GET USER bob FULLNAME +<< USER bob FULLNAME Bob +>> GET USER cecil ONLINESTATUS +<< USER cecil ONLINESTATUS ONLINE +>> GET USER cecil FULLNAME +<< USER cecil FULLNAME Cecil +>> CHAT CREATE bob +<< CHAT #alice/$bob;a7ab206ec78060f1 STATUS DIALOG +>> GET CHAT #alice/$bob;a7ab206ec78060f1 ADDER +<< CHAT #alice/$bob;a7ab206ec78060f1 ADDER +<< CHAT #alice/$bob;a7ab206ec78060f1 NAME #alice/$bob;a7ab206ec78060f1 +>> GET CHAT #alice/$bob;a7ab206ec78060f1 TOPIC +<< CHAT #alice/$bob;a7ab206ec78060f1 TOPIC +<< CHATMESSAGE 206 STATUS SENDING +<< CHAT #alice/$bob;a7ab206ec78060f1 STATUS DIALOG +<< CHATMEMBER 204 ROLE USER +<< CHAT #alice/$bob;a7ab206ec78060f1 MYROLE USER +<< CHAT #alice/$bob;a7ab206ec78060f1 MEMBERS bob alice +<< CHAT #alice/$bob;a7ab206ec78060f1 ACTIVEMEMBERS alice +<< CHAT #alice/$bob;a7ab206ec78060f1 STATUS DIALOG +<< CHAT #alice/$bob;a7ab206ec78060f1 TIMESTAMP 1358344213 +<< CHAT #alice/$bob;a7ab206ec78060f1 DIALOG_PARTNER bob +<< CHAT #alice/$bob;a7ab206ec78060f1 MEMBERS bob alice +<< CHAT #alice/$bob;a7ab206ec78060f1 FRIENDLYNAME bob +>> ALTER CHAT #alice/$bob;a7ab206ec78060f1 ADDMEMBERS cecil +<< ALTER CHAT ADDMEMBERS +<< CHAT #alice/$bob;a7ab206ec78060f1 STATUS MULTI_SUBSCRIBED +<< CHAT #alice/$bob;a7ab206ec78060f1 MEMBERS bob cecil alice +>> GET CHAT #alice/$bob;a7ab206ec78060f1 ADDER +<< CHAT #alice/$bob;a7ab206ec78060f1 ADDER +<< CHAT #alice/$bob;a7ab206ec78060f1 FRIENDLYNAME bob, cecil +>> GET CHAT #alice/$bob;a7ab206ec78060f1 TOPIC +<< CHAT #alice/$bob;a7ab206ec78060f1 TOPIC +<< CHATMESSAGE 210 STATUS SENDING diff --git a/protocols/skype/t/groupchat-invited-bitlbee.mock b/protocols/skype/t/groupchat-invited-bitlbee.mock new file mode 100644 index 00000000..f63b7d5c --- /dev/null +++ b/protocols/skype/t/groupchat-invited-bitlbee.mock @@ -0,0 +1,8 @@ +>> NOTICE AUTH +<< NICK alice +<< USER alice alice localhost :Alice +>> PRIVMSG &bitlbee +<< PRIVMSG &bitlbee :account add skype alice foo +<< PRIVMSG &bitlbee :account skype on +>> JOIN :##cecil/$bob;4d8cc9965791 +>> 353 alice = ##cecil/$bob;4d8cc9965791 :@alice bob cecil @root diff --git a/protocols/skype/t/groupchat-invited-skyped.mock b/protocols/skype/t/groupchat-invited-skyped.mock new file mode 100644 index 00000000..a5c754ce --- /dev/null +++ b/protocols/skype/t/groupchat-invited-skyped.mock @@ -0,0 +1,58 @@ +>> SEARCH GROUPS CUSTOM +<< GROUPS 48, 49 +>> SEARCH FRIENDS +<< USERS echo123, bob, cecil +>> SET USERSTATUS ONLINE +<< USERSTATUS ONLINE +>> SET USERSTATUS ONLINE +<< USERSTATUS ONLINE +>> GET USER echo123 ONLINESTATUS +<< USER echo123 ONLINESTATUS ONLINE +>> GET USER echo123 FULLNAME +<< USER echo123 FULLNAME Echo / Sound Test Service +>> GET USER bob ONLINESTATUS +<< USER bob ONLINESTATUS OFFLINE +>> GET USER bob FULLNAME +<< USER bob FULLNAME Bob +>> GET USER cecil ONLINESTATUS +<< USER cecil ONLINESTATUS OFFLINE +>> GET USER cecil FULLNAME +<< USER cecil FULLNAME Cecil +<< CHAT #cecil/$bob;4d8cc9965791c6b9 NAME #cecil/$bob;4d8cc9965791c6b9 +<< CHAT #cecil/$bob;4d8cc9965791c6b9 STATUS MULTI_SUBSCRIBED +<< CHAT #cecil/$bob;4d8cc9965791c6b9 STATUS MULTI_SUBSCRIBED +<< CHATMEMBER 186 ROLE USER +<< CHAT #cecil/$bob;4d8cc9965791c6b9 MYROLE USER +<< CHAT #cecil/$bob;4d8cc9965791c6b9 MEMBERS bob cecil alice +<< CHAT #cecil/$bob;4d8cc9965791c6b9 FRIENDLYNAME bob, cecil +<< CHAT #cecil/$bob;4d8cc9965791c6b9 ACTIVEMEMBERS bob alice +<< CHAT #cecil/$bob;4d8cc9965791c6b9 TIMESTAMP 1358276196 +<< CHAT #cecil/$bob;4d8cc9965791c6b9 ADDER bob +<< CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC +<< CHAT #cecil/$bob;4d8cc9965791c6b9 STATUS MULTI_SUBSCRIBED +<< CHATMESSAGE 188 STATUS RECEIVED +>> GET CHAT #cecil/$bob;4d8cc9965791c6b9 ADDER +<< CHAT #cecil/$bob;4d8cc9965791c6b9 ADDER bob +>> GET CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC +<< CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC +>> GET CHAT #cecil/$bob;4d8cc9965791c6b9 ADDER +<< CHAT #cecil/$bob;4d8cc9965791c6b9 ADDER bob +>> GET CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC +<< CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC +>> GET CHAT #cecil/$bob;4d8cc9965791c6b9 ADDER +<< CHAT #cecil/$bob;4d8cc9965791c6b9 ADDER bob +>> GET CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC +<< CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC +>> GET CHATMESSAGE 188 FROM_HANDLE +<< CHATMESSAGE 188 FROM_HANDLE bob +>> GET CHATMESSAGE 188 BODY +<< CHATMESSAGE 188 BODY +>> GET CHATMESSAGE 188 TYPE +<< CHATMESSAGE 188 TYPE ADDEDMEMBERS +>> GET CHATMESSAGE 188 CHATNAME +<< CHATMESSAGE 188 CHATNAME #cecil/$bob;4d8cc9965791c6b9 +<< CHATMESSAGE 189 STATUS READ +<< CHATMESSAGE 189 STATUS READ +<< CHATMEMBER 186 IS_ACTIVE TRUE +<< CHAT #cecil/$bob;4d8cc9965791c6b9 ACTIVEMEMBERS bob cecil alice +<< CHATMESSAGE 190 STATUS SENT diff --git a/protocols/skype/t/groupchat-leave-bitlbee.mock b/protocols/skype/t/groupchat-leave-bitlbee.mock new file mode 100644 index 00000000..36447cee --- /dev/null +++ b/protocols/skype/t/groupchat-leave-bitlbee.mock @@ -0,0 +1,11 @@ +>> NOTICE AUTH +<< NICK alice +<< USER alice alice localhost :Alice +>> PRIVMSG &bitlbee +<< PRIVMSG &bitlbee :account add skype alice foo +<< PRIVMSG &bitlbee :account skype set skypeconsole_receive true +<< PRIVMSG &bitlbee :account skype on +>> JOIN :##cecil/$bob;4d8cc9965791 +>> 353 alice = ##cecil/$bob;4d8cc9965791 :@alice bob cecil @root +<< PART ##cecil/$bob;4d8cc9965791 +>> PRIVMSG &bitlbee :alice: CHAT #cecil/$bob;4d8cc9965791c6b9 STATUS UNSUBSCRIBED diff --git a/protocols/skype/t/groupchat-leave-skyped.mock b/protocols/skype/t/groupchat-leave-skyped.mock new file mode 100644 index 00000000..86150d1c --- /dev/null +++ b/protocols/skype/t/groupchat-leave-skyped.mock @@ -0,0 +1,63 @@ +>> SEARCH GROUPS CUSTOM +<< GROUPS 48, 49 +>> SEARCH FRIENDS +<< USERS echo123, bob, cecil +>> SET USERSTATUS ONLINE +<< USERSTATUS ONLINE +>> SET USERSTATUS ONLINE +<< USERSTATUS ONLINE +>> GET USER echo123 ONLINESTATUS +<< USER echo123 ONLINESTATUS ONLINE +>> GET USER echo123 FULLNAME +<< USER echo123 FULLNAME Echo / Sound Test Service +>> GET USER bob ONLINESTATUS +<< USER bob ONLINESTATUS OFFLINE +>> GET USER bob FULLNAME +<< USER bob FULLNAME Bob +>> GET USER cecil ONLINESTATUS +<< USER cecil ONLINESTATUS OFFLINE +>> GET USER cecil FULLNAME +<< USER cecil FULLNAME Cecil +<< CHAT #cecil/$bob;4d8cc9965791c6b9 NAME #cecil/$bob;4d8cc9965791c6b9 +<< CHAT #cecil/$bob;4d8cc9965791c6b9 STATUS MULTI_SUBSCRIBED +<< CHAT #cecil/$bob;4d8cc9965791c6b9 STATUS MULTI_SUBSCRIBED +<< CHATMEMBER 186 ROLE USER +<< CHAT #cecil/$bob;4d8cc9965791c6b9 MYROLE USER +<< CHAT #cecil/$bob;4d8cc9965791c6b9 MEMBERS bob cecil alice +<< CHAT #cecil/$bob;4d8cc9965791c6b9 FRIENDLYNAME bob, cecil +<< CHAT #cecil/$bob;4d8cc9965791c6b9 ACTIVEMEMBERS bob alice +<< CHAT #cecil/$bob;4d8cc9965791c6b9 TIMESTAMP 1358276196 +<< CHAT #cecil/$bob;4d8cc9965791c6b9 ADDER bob +<< CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC +<< CHAT #cecil/$bob;4d8cc9965791c6b9 STATUS MULTI_SUBSCRIBED +<< CHATMESSAGE 188 STATUS RECEIVED +>> GET CHAT #cecil/$bob;4d8cc9965791c6b9 ADDER +<< CHAT #cecil/$bob;4d8cc9965791c6b9 ADDER bob +>> GET CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC +<< CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC +>> GET CHAT #cecil/$bob;4d8cc9965791c6b9 ADDER +<< CHAT #cecil/$bob;4d8cc9965791c6b9 ADDER bob +>> GET CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC +<< CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC +>> GET CHAT #cecil/$bob;4d8cc9965791c6b9 ADDER +<< CHAT #cecil/$bob;4d8cc9965791c6b9 ADDER bob +>> GET CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC +<< CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC +>> GET CHATMESSAGE 188 FROM_HANDLE +<< CHATMESSAGE 188 FROM_HANDLE bob +>> GET CHATMESSAGE 188 BODY +<< CHATMESSAGE 188 BODY +>> GET CHATMESSAGE 188 TYPE +<< CHATMESSAGE 188 TYPE ADDEDMEMBERS +>> GET CHATMESSAGE 188 CHATNAME +<< CHATMESSAGE 188 CHATNAME #cecil/$bob;4d8cc9965791c6b9 +<< CHATMESSAGE 189 STATUS READ +<< CHATMESSAGE 189 STATUS READ +<< CHATMEMBER 186 IS_ACTIVE TRUE +<< CHAT #cecil/$bob;4d8cc9965791c6b9 ACTIVEMEMBERS bob cecil alice +<< CHATMESSAGE 190 STATUS SENT +>> ALTER CHAT #cecil/$bob;4d8cc9965791c6b9 LEAVE +<< ALTER CHAT LEAVE +<< CHAT #cecil/$bob;4d8cc9965791c6b9 MEMBERS bob cecil +<< CHAT #cecil/$bob;4d8cc9965791c6b9 ACTIVEMEMBERS bob cecil +<< CHAT #cecil/$bob;4d8cc9965791c6b9 STATUS UNSUBSCRIBED diff --git a/protocols/skype/t/info-bitlbee.mock b/protocols/skype/t/info-bitlbee.mock new file mode 100644 index 00000000..a8896f6d --- /dev/null +++ b/protocols/skype/t/info-bitlbee.mock @@ -0,0 +1,9 @@ +>> NOTICE AUTH +<< NICK alice +<< USER alice alice localhost :Alice +>> PRIVMSG &bitlbee +<< PRIVMSG &bitlbee :account add skype alice foo +<< PRIVMSG &bitlbee :account skype on +>> :bob!bob@skype.com JOIN :&bitlbee +<< PRIVMSG &bitlbee :info bob +>> PRIVMSG &bitlbee :Full Name: Bob diff --git a/protocols/skype/t/info-skyped.mock b/protocols/skype/t/info-skyped.mock new file mode 100644 index 00000000..63076b09 --- /dev/null +++ b/protocols/skype/t/info-skyped.mock @@ -0,0 +1,46 @@ +>> SEARCH GROUPS CUSTOM +<< GROUPS 48, 49 +>> SEARCH FRIENDS +<< USERS echo123, bob +>> SET USERSTATUS ONLINE +<< USERSTATUS ONLINE +>> SET USERSTATUS ONLINE +<< USERSTATUS ONLINE +>> GET USER echo123 ONLINESTATUS +<< USER echo123 ONLINESTATUS ONLINE +>> GET USER echo123 FULLNAME +<< USER echo123 FULLNAME Echo / Sound Test Service +>> GET USER bob ONLINESTATUS +<< USER bob ONLINESTATUS ONLINE +>> GET USER bob FULLNAME +<< USER bob FULLNAME Bob +>> GET USER bob FULLNAME +<< USER bob FULLNAME Bob +>> GET USER bob PHONE_HOME +<< USER bob PHONE_HOME +>> GET USER bob PHONE_OFFICE +<< USER bob PHONE_OFFICE +>> GET USER bob PHONE_MOBILE +<< USER bob PHONE_MOBILE +>> GET USER bob NROF_AUTHED_BUDDIES +<< USER bob NROF_AUTHED_BUDDIES 145 +>> GET USER bob TIMEZONE +<< USER bob TIMEZONE 90000 +>> GET USER bob LASTONLINETIMESTAMP +<< USER bob LASTONLINETIMESTAMP 1358023469 +>> GET USER bob SEX +<< USER bob SEX MALE +>> GET USER bob LANGUAGE +<< USER bob LANGUAGE hu Hungarian +>> GET USER bob COUNTRY +<< USER bob COUNTRY hu Hungary +>> GET USER bob PROVINCE +<< USER bob PROVINCE +>> GET USER bob CITY +<< USER bob CITY Budapest +>> GET USER bob HOMEPAGE +<< USER bob HOMEPAGE +>> GET USER bob ABOUT +<< USER bob ABOUT +>> GET USER bob BIRTHDAY +<< USER bob BIRTHDAY 19781108 diff --git a/protocols/skype/t/irssi/livetest-irssi.sh b/protocols/skype/t/irssi/livetest-irssi.sh deleted file mode 100755 index a8e136cf..00000000 --- a/protocols/skype/t/irssi/livetest-irssi.sh +++ /dev/null @@ -1,109 +0,0 @@ -#!/usr/bin/env bash -ISCRIPT=$1 -OPT=$2 - -[ -n "$ISCRIPT" ] || { echo Syntax: `basename "$0"` irssi-test-script; exit 1; } - -# Load variables from test -eval `sed -e '1,/^###/!d;/^###/d' "$ISCRIPT"` - -#if [ "$OPT" == "checkvars" ]; then echo $TESTNEEDEDVARS; fi -RET=0 - -# Check if we have the neccessary environment variables for this test -for var in $TESTNEEDEDVARS; do - if [ -z `eval echo \$\{$var\}` ]; then - if [ "$OPT" != "checkvars" ]; then - echo Need environment variable "$var" for this test. - exit 66 - else - echo $var - RET=66 - fi - fi -done - -# if we got this far we're OK -if [ "$OPT" == "checkvars" ]; then exit $RET; fi - -[ -n "$PORT" ] || { echo 'Need the bitlbee listening port as environment variable PORT'; exit 1; } - -# Setup the irssi dir -( - rm -r dotirssi - mkdir -p dotirssi/scripts dotirssi/logs - cp "`dirname $0`"/trigger.pl dotirssi/scripts && - echo 'script load trigger.pl' >dotirssi/startup -) &>/dev/null || { echo Failed to setup irssi testdir; exit 1; } - -# write irssi config - -echo ' - -aliases = { - runtest = "'`sed -e "1,/^###/d;s/@LOGIN@/$TESTLOGIN/;s/@PASSWORD@/$TESTPASSWORD/" "$ISCRIPT" | tr '\n' ';'`'"; - expectbee = "/trigger add -publics -channels &bitlbee -regexp"; - expectjoin = "/trigger add -joins -masks *!$0@* $1-"; - expectmsg = "/trigger add -privmsgs -masks *!$0@* $1-"; -}; - -servers = ( { address = "localhost"; chatnet = "local"; port = "'$PORT'"; autoconnect="yes";}); - -settings = { - settings_autosave = "no"; - core = { real_name = "bitlbee-test"; user_name = "bitlbee-test"; nick = "bitlbeetest"; }; - "fe-text" = { actlist_sort = "refnum"; }; -}; - -chatnets = { local = { type = "IRC"; autosendcmd = "/runtest"; }; }; - -logs = { -"dotirssi/logs/status.log" = { auto_open = "yes"; level = "ALL"; items = ( { type = "window"; name = "1"; } ); }; -"dotirssi/logs/control.log" = { auto_open = "yes"; level = "ALL"; items = ( { type = "target"; name = "&bitlbee"; } ); }; -' >dotirssi/config - -for nick in $TESTLOGNICKS; do - echo ' - "dotirssi/logs/'$nick'.log" = { auto_open = "yes"; level = "ALL"; items = ( { type = "target"; name = "'$nick'"; } ); }; - ' >>dotirssi/config -done - -echo '};' >>dotirssi/config - -# Go! - -echo Running irssi... -screen -D -m irssi --config=dotirssi/config --home=dotirssi/ & - -# output logs - -submitlogs() { - perl -p -i -e "s/$TESTLOGIN/---TESTLOGIN---/;s/$TESTPASSWORD/---TESTPASSWORD---/" dotirssi/logs/*.log - - if [ "$OPT" == "tgz" ]; then - tar czf "`dirname $0`"/"`basename "$ISCRIPT"`".logs.tgz dotirssi/logs/*.log - elif [ "$OPT" == "ctest" ]; then - echo CTEST_FULL_OUTPUT - for log in dotirssi/logs/*.log; do - echo -n '<DartMeasurement name="'$log'" type="text/string"><![CDATA[' - cat "$log" - echo "]]></DartMeasurement>" - done - else - echo Test logs: dotirssi/logs/*.log - fi -} - -# timeout stuff - -t=$TESTDURATION -intval=1 -while (( t >= intval )); do - sleep $intval - kill -0 $! &>/dev/null || { echo screen/irssi terminated.; submitlogs; bash -c "cd dotirssi/logs && $TESTCHECKRESULT" >/dev/null; exit $?; } - t=$(( t - $intval )) -done -echo Killing screen/irssi... -kill $! -submitlogs -exit 22 diff --git a/protocols/skype/t/irssi/skype-call.test b/protocols/skype/t/irssi/skype-call.test deleted file mode 100644 index 8f502a59..00000000 --- a/protocols/skype/t/irssi/skype-call.test +++ /dev/null @@ -1,13 +0,0 @@ -TESTNEEDEDVARS="TEST_SKYPE_ID TEST_SKYPE_PASSWORD" -TESTDURATION=60 -TESTCHECKRESULT="grep '\[Test Passed\]' status.log" -TESTLOGIN="$TEST_SKYPE_ID" -TESTPASSWORD="$TEST_SKYPE_PASSWORD" -### Test receiving call output -/expectbee 'Welcome to the BitlBee' -command 'msg $$C register testing' -/expectbee 'Account successfully created' -command 'msg $$C account add skype @LOGIN@ @PASSWORD@' -/expectbee 'Account successfully added' -command 'msg $$C account 0 set test_join true' -/expectbee 'test_join' -command 'msg $$C account 0 on' -/expectjoin echo123 -command 'ctcp echo123 call' -/expectbee 'You are currently ringing the user' -command 'ctcp echo123 hangup' -/expectbee '(You cancelled the call|You finished the call)' -command 'quit Test Passed' diff --git a/protocols/skype/t/irssi/skype-info.test b/protocols/skype/t/irssi/skype-info.test deleted file mode 100644 index e8507321..00000000 --- a/protocols/skype/t/irssi/skype-info.test +++ /dev/null @@ -1,12 +0,0 @@ -TESTNEEDEDVARS="TEST_SKYPE_ID TEST_SKYPE_PASSWORD" -TESTDURATION=60 -TESTCHECKRESULT="grep '\[Test Passed\]' status.log" -TESTLOGIN="$TEST_SKYPE_ID" -TESTPASSWORD="$TEST_SKYPE_PASSWORD" -### Test receiving info output -/expectbee 'Welcome to the BitlBee' -command 'msg $$C register testing' -/expectbee 'Account successfully created' -command 'msg $$C account add skype @LOGIN@ @PASSWORD@' -/expectbee 'Account successfully added' -command 'msg $$C account 0 set test_join true' -/expectbee 'test_join' -command 'msg $$C account 0 on' -/expectjoin echo123 -command 'msg $$C info echo123' -/expectbee 'Full Name: Echo / Sound Test Service' -command 'quit Test Passed' diff --git a/protocols/skype/t/irssi/skype-login.test b/protocols/skype/t/irssi/skype-login.test deleted file mode 100644 index ca627002..00000000 --- a/protocols/skype/t/irssi/skype-login.test +++ /dev/null @@ -1,10 +0,0 @@ -TESTNEEDEDVARS="TEST_SKYPE_ID TEST_SKYPE_PASSWORD" -TESTDURATION=10 -TESTCHECKRESULT="grep '\[Test Passed\]' status.log" -TESTLOGIN="$TEST_SKYPE_ID" -TESTPASSWORD="$TEST_SKYPE_PASSWORD" -### Test login -/expectbee 'Welcome to the BitlBee' -command 'msg $$C register testing' -/expectbee 'Account successfully created' -command 'msg $$C account add skype @LOGIN@ @PASSWORD@' -/expectbee 'Account successfully added' -command 'msg $$C account 0 on' -/expectbee 'Logged in' -command 'quit Test Passed' diff --git a/protocols/skype/t/irssi/skype-msg.test b/protocols/skype/t/irssi/skype-msg.test deleted file mode 100644 index d35615cd..00000000 --- a/protocols/skype/t/irssi/skype-msg.test +++ /dev/null @@ -1,17 +0,0 @@ -TESTNEEDEDVARS="TEST_SKYPE_ID TEST_SKYPE_PASSWORD" -TESTDURATION=60 -TESTCHECKRESULT="grep '\[Test Passed\]' status.log" -TESTLOGIN="$TEST_SKYPE_ID" -TESTPASSWORD="$TEST_SKYPE_PASSWORD" -### Test sending and receiving messages -/expectbee 'Welcome to the BitlBee' -command 'msg $$C register testing' -/expectbee 'Account successfully created' -command 'msg $$C account add skype @LOGIN@ @PASSWORD@' -/expectbee 'Account successfully added' -command 'msg $$C account 0 set test_join true' -/expectbee 'test_join' -command 'msg $$C account 0 on' -# use builtin test service -/expectjoin echo123 -command 'msg $$C echo123: ping, say pong' -/expectbee 'pong' -command 'quit Test Passed' -# use a public bot as well, just in case the above one would fail -/expectjoin echo123 -command 'msg $$C add skype pam_bot' -/expectjoin pam_bot -command 'msg $$C pam_bot: pambot help' -/expectbee 'PamBot, thanks for chatting with me' -command 'quit Test Passed' diff --git a/protocols/skype/t/irssi/trigger.pl b/protocols/skype/t/irssi/trigger.pl deleted file mode 100644 index 02f8951f..00000000 --- a/protocols/skype/t/irssi/trigger.pl +++ /dev/null @@ -1,1225 +0,0 @@ -# trigger.pl - execute a command or replace text, triggered by an event in irssi -# Do /TRIGGER HELP or look at http://wouter.coekaerts.be/irssi/ for help - -# Copyright (C) 2002-2006 Wouter Coekaerts <wouter@coekaerts.be> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -use strict; -use Irssi 20020324 qw(command_bind command_runsub command signal_add_first signal_continue signal_stop signal_remove); -use Text::ParseWords; -use IO::File; -use vars qw($VERSION %IRSSI); - -$VERSION = '1.0'; -%IRSSI = ( - authors => 'Wouter Coekaerts', - contact => 'wouter@coekaerts.be', - name => 'trigger', - description => 'execute a command or replace text, triggered by an event in irssi', - license => 'GPLv2 or later', - url => 'http://wouter.coekaerts.be/irssi/', - changed => '$LastChangedDate: 2006-01-23 13:10:19 +0100 (Mon, 23 Jan 2006) $', -); - -sub cmd_help { - Irssi::print (<<'SCRIPTHELP_EOF', MSGLEVEL_CLIENTCRAP); - -TRIGGER LIST -TRIGGER SAVE -TRIGGER RELOAD -TRIGGER MOVE <number> <number> -TRIGGER DELETE <number> -TRIGGER CHANGE <number> ... -TRIGGER ADD ... - -When to match: -On which types of event to trigger: - These are simply specified by -name_of_the_type - The normal IRC event types are: - publics, %|privmsgs, pubactions, privactions, pubnotices, privnotices, joins, parts, quits, kicks, topics, invites, nick_changes, dcc_msgs, dcc_actions, dcc_ctcps - mode_channel: %|a mode on the (whole) channel (like +t, +i, +b) - mode_nick: %|a mode on someone in the channel (like +o, +v) - -all is an alias for all of those. - Additionally, there is: - rawin: %|raw text incoming from the server - send_command: %|commands you give to irssi - send_text: %|lines you type that aren't commands - beep: %|when irssi beeps - notify_join: %|someone in you notify list comes online - notify_part: %|someone in your notify list goes offline - notify_away: %|someone in your notify list goes away - notify_unaway: %|someone in your notify list goes unaway - notify_unidle: %|someone in your notify list stops idling - -Filters (conditions) the event has to satisfy. They all take one parameter. -If you can give a list, seperate elements by space and use quotes around the list. - -pattern: %|The message must match the given pattern. ? and * can be used as wildcards - -regexp: %|The message must match the given regexp. (see man perlre) - %|if -nocase is given as an option, the regexp or pattern is matched case insensitive - -tags: %|The servertag must be in the given list of tags - -channels: %|The event must be in one of the given list of channels. - Examples: %|-channels '#chan1 #chan2' or -channels 'IRCNet/#channel' - %|-channels 'EFNet/' means every channel on EFNet and is the same as -tags 'EFNet' - -masks: %|The person who triggers it must match one of the given list of masks - -hasmode: %|The person who triggers it must have the give mode - Examples: %|'-o' means not opped, '+ov' means opped OR voiced, '-o&-v' means not opped AND not voiced - -hasflag: %|Only trigger if if friends.pl (friends_shasta.pl) or people.pl is loaded and the person who triggers it has the given flag in the script (same syntax as -hasmode) - -other_masks - -other_hasmode - -other_hasflag: %|Same as above but for the victim for kicks or mode_nick. - -What to do when it matches: - -command: Execute the given Irssi-command - %|You are able to use $1, $2 and so on generated by your regexp pattern. - %|For multiple commands ; (or $;) can be used as seperator - %|The following variables are also expanded: - $T: %|Server tag - $C: %|Channel name - $N: %|Nickname of the person who triggered this command - $A: %|His address (foo@bar.com), - $I: %|His ident (foo) - $H: %|His hostname (bar.com) - $M: %|The complete message - ${other}: %|The victim for kicks or mode_nick - ${mode_type}: %|The type ('+' or '-') for a mode_channel or mode_nick - ${mode_char}: %|The mode char ('o' for ops, 'b' for ban,...) - ${mode_arg} : %|The argument to the mode (if there is one) - %|$\X, with X being one of the above expands (e.g. $\M), escapes all non-alphanumeric characters, so it can be used with /eval or /exec. Don't use /eval or /exec without this, it's not safe. - - -replace: %|replaces the matching part with the given replacement in the event (requires a -regexp or -pattern) - -once: %|remove the trigger if it is triggered, so it only executes once and then is forgotten. - -stop: %|stops the signal. It won't get displayed by Irssi. Like /IGNORE - -debug: %|print some debugging info - -Other options: - -disabled: %|Same as removing it, but keeps it in case you might need it later - -name: %|Give the trigger a name. You can refer to the trigger with this name in add/del/change commands - -Examples: - Knockout people who do a !list: - /TRIGGER ADD %|-publics -channels "#channel1 #channel2" -nocase -regexp ^!list -command "KN $N This is not a warez channel!" - React to !echo commands from people who are +o in your friends-script: - /TRIGGER ADD %|-publics -regexp '^!echo (.*)' -hasflag '+o' -command 'say echo: $1' - Ignore all non-ops on #channel: - /TRIGGER ADD %|-publics -actions -channels "#channel" -hasmode '-o' -stop - Send a mail to yourself every time a topic is changed: - /TRIGGER ADD %|-topics -command 'exec echo $\N changed topic of $\C to: $\M | mail you@somewhere.com -s topic' - - -Examples with -replace: - %|Replace every occurence of shit with sh*t, case insensitive: - /TRIGGER ADD %|-all -nocase -regexp shit -replace sh*t - %|Strip all colorcodes from *!lamer@*: - /TRIGGER ADD %|-all -masks *!lamer@* -regexp '\x03\d?\d?(,\d\d?)?|\x02|\x1f|\x16|\x06' -replace '' - %|Never let *!bot1@foo.bar or *!bot2@foo.bar hilight you - %|(this works by cutting your nick in 2 different parts, 'myn' and 'ick' here) - %|you don't need to understand the -replace argument, just trust that it works if the 2 parts separately don't hilight: - /TRIGGER ADD %|-all masks '*!bot1@foo.bar *!bot2@foo.bar' -regexp '(myn)(ick)' -nocase -replace '$1\x02\x02$2' - %|Avoid being hilighted by !top10 in eggdrops with stats.mod (but show your nick in bold): - /TRIGGER ADD %|-publics -regexp '(Top.0\(.*\): 1.*)(my)(nick)' -replace '$1\x02$2\x02\x02$3\x02' - %|Convert a Windows-1252 Euro to an ISO-8859-15 Euro (same effect as euro.pl): - /TRIGGER ADD %|-regexp '\x80' -replace '\xA4' - %|Show tabs as spaces, not the inverted I (same effect as tab_stop.pl): - /TRIGGER ADD %|-all -regexp '\t' -replace ' ' -SCRIPTHELP_EOF -} # / - -my @triggers; # array of all triggers -my %triggers_by_type; # hash mapping types on triggers of that type -my $recursion_depth = 0; -my $changed_since_last_save = 0; - -############### -### formats ### -############### - -Irssi::theme_register([ - 'trigger_header' => 'Triggers:', - 'trigger_line' => '%#$[-4]0 $1', - 'trigger_added' => 'Trigger $0 added: $1', - 'trigger_not_found' => 'Trigger {hilight $0} not found', - 'trigger_saved' => 'Triggers saved to $0', - 'trigger_loaded' => 'Triggers loaded from $0' -]); - -######################################### -### catch the signals & do your thing ### -######################################### - -# trigger types with a message and a channel -my @allchanmsg_types = qw(publics pubactions pubnotices pubctcps pubctcpreplies parts quits kicks topics); -# trigger types with a message -my @allmsg_types = (@allchanmsg_types, qw(privmsgs privactions privnotices privctcps privctcpreplies dcc_msgs dcc_actions dcc_ctcps)); -# trigger types with a channel -my @allchan_types = (@allchanmsg_types, qw(mode_channel mode_nick joins invites)); -# trigger types in -all -my @all_types = (@allmsg_types, qw(mode_channel mode_nick joins invites nick_changes)); -# trigger types with a server -my @all_server_types = (@all_types, qw(rawin notify_join notify_part notify_away notify_unaway notify_unidle)); -# all trigger types -my @trigger_types = (@all_server_types, qw(send_command send_text beep)); -#trigger types that are not in -all -#my @notall_types = grep {my $a=$_; return (!grep {$_ eq $a} @all_types);} @trigger_types; -my @notall_types = qw(rawin notify_join notify_part notify_away notify_unaway notify_unidle send_command send_text beep); - -my @signals = ( -# "message public", SERVER_REC, char *msg, char *nick, char *address, char *target -{ - 'types' => ['publics'], - 'signal' => 'message public', - 'sub' => sub {check_signal_message(\@_,1,$_[0],$_[4],$_[2],$_[3],'publics');}, -}, -# "message private", SERVER_REC, char *msg, char *nick, char *address -{ - 'types' => ['privmsgs'], - 'signal' => 'message private', - 'sub' => sub {check_signal_message(\@_,1,$_[0],undef,$_[2],$_[3],'privmsgs');}, -}, -# "message irc action", SERVER_REC, char *msg, char *nick, char *address, char *target -{ - 'types' => ['privactions','pubactions'], - 'signal' => 'message irc action', - 'sub' => sub { - if ($_[4] eq $_[0]->{nick}) { - check_signal_message(\@_,1,$_[0],undef,$_[2],$_[3],'privactions'); - } else { - check_signal_message(\@_,1,$_[0],$_[4],$_[2],$_[3],'pubactions'); - } - }, -}, -# "message irc notice", SERVER_REC, char *msg, char *nick, char *address, char *target -{ - 'types' => ['privnotices','pubnotices'], - 'signal' => 'message irc notice', - 'sub' => sub { - if ($_[4] eq $_[0]->{nick}) { - check_signal_message(\@_,1,$_[0],undef,$_[2],$_[3],'privnotices'); - } else { - check_signal_message(\@_,1,$_[0],$_[4],$_[2],$_[3],'pubnotices'); - } - } -}, -# "message join", SERVER_REC, char *channel, char *nick, char *address -{ - 'types' => ['joins'], - 'signal' => 'message join', - 'sub' => sub {check_signal_message(\@_,-1,$_[0],$_[1],$_[2],$_[3],'joins');} -}, -# "message part", SERVER_REC, char *channel, char *nick, char *address, char *reason -{ - 'types' => ['parts'], - 'signal' => 'message part', - 'sub' => sub {check_signal_message(\@_,4,$_[0],$_[1],$_[2],$_[3],'parts');} -}, -# "message quit", SERVER_REC, char *nick, char *address, char *reason -{ - 'types' => ['quits'], - 'signal' => 'message quit', - 'sub' => sub {check_signal_message(\@_,3,$_[0],undef,$_[1],$_[2],'quits');} -}, -# "message kick", SERVER_REC, char *channel, char *nick, char *kicker, char *address, char *reason -{ - 'types' => ['kicks'], - 'signal' => 'message kick', - 'sub' => sub {check_signal_message(\@_,5,$_[0],$_[1],$_[3],$_[4],'kicks',{'other'=>$_[2]});} -}, -# "message topic", SERVER_REC, char *channel, char *topic, char *nick, char *address -{ - 'types' => ['topics'], - 'signal' => 'message topic', - 'sub' => sub {check_signal_message(\@_,2,$_[0],$_[1],$_[3],$_[4],'topics');} -}, -# "message invite", SERVER_REC, char *channel, char *nick, char *address -{ - 'types' => ['invites'], - 'signal' => 'message invite', - 'sub' => sub {check_signal_message(\@_,-1,$_[0],$_[1],$_[2],$_[3],'invites');} -}, -# "message nick", SERVER_REC, char *newnick, char *oldnick, char *address -{ - 'types' => ['nick_changes'], - 'signal' => 'message nick', - 'sub' => sub {check_signal_message(\@_,-1,$_[0],undef,$_[1],$_[3],'nick_changes');} -}, -# "message dcc", DCC_REC *dcc, char *msg -{ - 'types' => ['dcc_msgs'], - 'signal' => 'message dcc', - 'sub' => sub {check_signal_message(\@_,1,$_[0]->{'server'},undef,$_[0]->{'nick'},undef,'dcc_msgs'); - } -}, -# "message dcc action", DCC_REC *dcc, char *msg -{ - 'types' => ['dcc_actions'], - 'signal' => 'message dcc action', - 'sub' => sub {check_signal_message(\@_,1,$_[0]->{'server'},undef,$_[0]->{'nick'},undef,'dcc_actions');} -}, -# "message dcc ctcp", DCC_REC *dcc, char *cmd, char *data -{ - 'types' => ['dcc_ctcps'], - 'signal' => 'message dcc ctcp', - 'sub' => sub {check_signal_message(\@_,1,$_[0]->{'server'},undef,$_[0]->{'nick'},undef,'dcc_ctcps');} -}, -# "server incoming", SERVER_REC, char *data -{ - 'types' => ['rawin'], - 'signal' => 'server incoming', - 'sub' => sub {check_signal_message(\@_,1,$_[0],undef,undef,undef,'rawin');} -}, -# "send command", char *args, SERVER_REC, WI_ITEM_REC -{ - 'types' => ['send_command'], - 'signal' => 'send command', - 'sub' => sub { - sig_send_text_or_command(\@_,1); - } -}, -# "send text", char *line, SERVER_REC, WI_ITEM_REC -{ - 'types' => ['send_text'], - 'signal' => 'send text', - 'sub' => sub { - sig_send_text_or_command(\@_,0); - } -}, -# "beep" -{ - 'types' => ['beep'], - 'signal' => 'beep', - 'sub' => sub {check_signal_message(\@_,-1,undef,undef,undef,undef,'beep');} -}, -# "event "<cmd>, SERVER_REC, char *args, char *sender_nick, char *sender_address -{ - 'types' => ['mode_channel', 'mode_nick'], - 'signal' => 'event mode', - 'sub' => sub { - my ($server, $event_args, $nickname, $address) = @_; - my ($target, $modes, $modeargs) = split(/ /, $event_args, 3); - return if (!$server->ischannel($target)); - my (@modeargs) = split(/ /,$modeargs); - my ($pos, $type, $event_type, $arg) = (0, '+'); - foreach my $char (split(//,$modes)) { - if ($char eq "+" || $char eq "-") { - $type = $char; - } else { - if ($char =~ /[Oovh]/) { # mode_nick - $event_type = 'mode_nick'; - $arg = $modeargs[$pos++]; - } elsif ($char =~ /[beIqdk]/ || ( $char =~ /[lfJ]/ && $type eq '+')) { # chan_mode with arg - $event_type = 'mode_channel'; - $arg = $modeargs[$pos++]; - } else { # chan_mode without arg - $event_type = 'mode_channel'; - $arg = undef; - } - check_signal_message(\@_,-1,$server,$target,$nickname,$address,$event_type,{ - 'mode_type' => $type, - 'mode_char' => $char, - 'mode_arg' => $arg, - 'other' => ($event_type eq 'mode_nick') ? $arg : undef - }); - } - } - } -}, -# "notifylist joined", SERVER_REC, char *nick, char *user, char *host, char *realname, char *awaymsg -{ - 'types' => ['notify_join'], - 'signal' => 'notifylist joined', - 'sub' => sub {check_signal_message(\@_, 5, $_[0], undef, $_[1], $_[2].'@'.$_[3], 'notify_join', {'realname' => $_[4]});} -}, -{ - 'types' => ['notify_part'], - 'signal' => 'notifylist left', - 'sub' => sub {check_signal_message(\@_, 5, $_[0], undef, $_[1], $_[2].'@'.$_[3], 'notify_left', {'realname' => $_[4]});} -}, -{ - 'types' => ['notify_unidle'], - 'signal' => 'notifylist unidle', - 'sub' => sub {check_signal_message(\@_, 5, $_[0], undef, $_[1], $_[2].'@'.$_[3], 'notify_unidle', {'realname' => $_[4]});} -}, -{ - 'types' => ['notify_away', 'notify_unaway'], - 'signal' => 'notifylist away changed', - 'sub' => sub {check_signal_message(\@_, 5, $_[0], undef, $_[1], $_[2].'@'.$_[3], ($_[5] ? 'notify_away' : 'notify_unaway'), {'realname' => $_[4]});} -}, -# "ctcp msg", SERVER_REC, char *args, char *nick, char *addr, char *target -{ - 'types' => ['pubctcps', 'privctcps'], - 'signal' => 'ctcp msg', - 'sub' => sub { - my ($server, $args, $nick, $addr, $target) = @_; - if ($target eq $server->{'nick'}) { - check_signal_message(\@_, 1, $server, undef, $nick, $addr, 'privctcps'); - } else { - check_signal_message(\@_, 1, $server, $target, $nick, $addr, 'pubctcps'); - } - } -}, -# "ctcp reply", SERVER_REC, char *args, char *nick, char *addr, char *target -{ - 'types' => ['pubctcpreplies', 'privctcpreplies'], - 'signal' => 'ctcp reply', - 'sub' => sub { - my ($server, $args, $nick, $addr, $target) = @_; - if ($target eq $server->{'nick'}) { - check_signal_message(\@_, 1, $server, undef, $nick, $addr, 'privctcps'); - } else { - check_signal_message(\@_, 1, $server, $target, $nick, $addr, 'pubctcps'); - } - } -} -); - -sub sig_send_text_or_command { - my ($signal, $iscommand) = @_; - my ($line, $server, $item) = @$signal; - my ($channelname,$nickname,$address) = (undef,undef,undef); - if ($item && (ref($item) eq 'Irssi::Irc::Channel' || ref($item) eq 'Irssi::Silc::Channel')) { - $channelname = $item->{'name'}; - } elsif ($item && ref($item) eq 'Irssi::Irc::Query') { # TODO Silc query ? - $nickname = $item->{'name'}; - $address = $item->{'address'} - } - # TODO pass context also for non-channels (queries and other stuff) - check_signal_message($signal,0,$server,$channelname,$nickname,$address,$iscommand ? 'send_command' : 'send_text'); - -} - -my %filters = ( -'tags' => { - 'types' => \@all_server_types, - 'sub' => sub { - my ($param, $signal,$parammessage,$server,$channelname,$nickname,$address,$condition,$extra) = @_; - - if (!defined($server)) { - return 0; - } - my $matches = 0; - foreach my $tag (split(/ /,$param)) { - if (lc($server->{'tag'}) eq lc($tag)) { - $matches = 1; - last; - } - } - return $matches; - } -}, -'channels' => { - 'types' => \@allchan_types, - 'sub' => sub { - my ($param, $signal,$parammessage,$server,$channelname,$nickname,$address,$condition,$extra) = @_; - - if (!defined($channelname) || !defined($server)) { - return 0; - } - my $matches = 0; - foreach my $trigger_channel (split(/ /,$param)) { - if (lc($channelname) eq lc($trigger_channel) - || lc($server->{'tag'}.'/'.$channelname) eq lc($trigger_channel) - || lc($server->{'tag'}.'/') eq lc($trigger_channel)) { - $matches = 1; - last; # this channel matches, stop checking channels - } - } - return $matches; - } -}, -'masks' => { - 'types' => \@all_types, - 'sub' => sub { - my ($param, $signal,$parammessage,$server,$channelname,$nickname,$address,$condition,$extra) = @_; - return (defined($nickname) && defined($address) && defined($server) && $server->masks_match($param, $nickname, $address)); - } -}, -'other_masks' => { - 'types' => ['kicks', 'mode_nick'], - 'sub' => sub { - my ($param, $signal,$parammessage,$server,$channelname,$nickname,$address,$condition,$extra) = @_; - return 0 unless defined($extra->{'other'}); - my $other_address = get_address($extra->{'other'}, $server, $channelname); - return defined($other_address) && $server->masks_match($param, $extra->{'other'}, $other_address); - } -}, -'hasmode' => { - 'types' => \@all_types, - 'sub' => sub { - my ($param, $signal,$parammessage,$server,$channelname,$nickname,$address,$condition,$extra) = @_; - return hasmode($param, $nickname, $server, $channelname); - } -}, -'other_hasmode' => { - 'types' => ['kicks', 'mode_nick'], - 'sub' => sub { - my ($param,$signal,$parammessage,$server,$channelname,$nickname,$address,$condition,$extra) = @_; - return defined($extra->{'other'}) && hasmode($param, $extra->{'other'}, $server, $channelname); - } -}, -'hasflag' => { - 'types' => \@all_types, - 'sub' => sub { - my ($param, $signal,$parammessage,$server,$channelname,$nickname,$address,$condition,$extra) = @_; - return 0 unless defined($nickname) && defined($address) && defined($server); - my $flags = get_flags ($server->{'chatnet'},$channelname,$nickname,$address); - return defined($flags) && check_modes($flags,$param); - } -}, -'other_hasflag' => { - 'types' => ['kicks', 'mode_nick'], - 'sub' => sub { - my ($param, $signal,$parammessage,$server,$channelname,$nickname,$address,$condition,$extra) = @_; - return 0 unless defined($extra->{'other'}); - my $other_address = get_address($extra->{'other'}, $server, $channelname); - return 0 unless defined($other_address); - my $flags = get_flags ($server->{'chatnet'},$channelname,$extra->{'other'},$other_address); - return defined($flags) && check_modes($flags,$param); - } -}, -'mode_type' => { - 'types' => ['mode_channel', 'mode_nick'], - 'sub' => sub { - my ($param, $signal,$parammessage,$server,$channelname,$nickname,$address,$condition,$extra) = @_; - return (($param) eq $extra->{'mode_type'}); - } -}, -'mode_char' => { - 'types' => ['mode_channel', 'mode_nick'], - 'sub' => sub { - my ($param, $signal,$parammessage,$server,$channelname,$nickname,$address,$condition,$extra) = @_; - return (($param) eq $extra->{'mode_char'}); - } -}, -'mode_arg' => { - 'types' => ['mode_channel', 'mode_nick'], - 'sub' => sub { - my ($param, $signal,$parammessage,$server,$channelname,$nickname,$address,$condition,$extra) = @_; - return (($param) eq $extra->{'mode_arg'}); - } -} -); - -sub get_address { - my ($nick, $server, $channel) = @_; - my $nickrec = get_nickrec($nick, $server, $channel); - return $nickrec ? $nickrec->{'host'} : undef; -} -sub get_nickrec { - my ($nick, $server, $channel) = @_; - return unless defined($server) && defined($channel) && defined($nick); - my $chanrec = $server->channel_find($channel); - return $chanrec ? $chanrec->nick_find($nick) : undef; -} - -sub hasmode { - my ($param, $nickname, $server, $channelname) = @_; - my $nickrec = get_nickrec($nickname, $server, $channelname); - return 0 unless defined $nickrec; - my $modes = - ($nickrec->{'op'} ? 'o' : '') - . ($nickrec->{'voice'} ? 'v' : '') - . ($nickrec->{'halfop'} ? 'h' : '') - ; - return check_modes($modes, $param); -} - -# list of all switches -my @trigger_switches = (@trigger_types, qw(all nocase stop once debug disabled)); -# parameters (with an argument) -my @trigger_params = qw(pattern regexp command replace name); -# list of all options (including switches) for /TRIGGER ADD -my @trigger_add_options = (@trigger_switches, @trigger_params, keys(%filters)); -# same for /TRIGGER CHANGE, this includes the -no<option>'s -my @trigger_options = map(($_,'no'.$_) ,@trigger_add_options); - -# check the triggers on $signal's $parammessage parameter, for triggers with $condition set -# on $server in $channelname, for $nickname!$address -# set $parammessage to -1 if the signal doesn't have a message -# for signal without channel, nick or address, set to undef -sub check_signal_message { - my ($signal, $parammessage, $server, $channelname, $nickname, $address, $condition, $extra) = @_; - my ($changed, $stopped, $context, $need_rebuild); - my $message = ($parammessage == -1) ? '' : $signal->[$parammessage]; - - return if (!$triggers_by_type{$condition}); - - if ($recursion_depth > 10) { - Irssi::print("Trigger error: Maximum recursion depth reached, aborting trigger.", MSGLEVEL_CLIENTERROR); - return; - } - $recursion_depth++; - -TRIGGER: - foreach my $trigger (@{$triggers_by_type{$condition}}) { - # check filters - foreach my $trigfilter (@{$trigger->{'filters'}}) { - if (! ($trigfilter->[2]($trigfilter->[1], $signal,$parammessage,$server,$channelname,$nickname,$address,$condition,$extra))) { - - next TRIGGER; - } - } - - # check regexp (and keep matches in @- and @+, so don't make a this a {block}) - next if ($trigger->{'compregexp'} && ($parammessage == -1 || $message !~ m/$trigger->{'compregexp'}/)); - - # if we got this far, it fully matched, and we need to do the replace/command/stop/once - my $expands = $extra; - $expands->{'M'} = $message,; - $expands->{'T'} = (defined($server)) ? $server->{'tag'} : ''; - $expands->{'C'} = $channelname; - $expands->{'N'} = $nickname; - $expands->{'A'} = $address; - $expands->{'I'} = ((!defined($address)) ? '' : substr($address,0,index($address,'@'))); - $expands->{'H'} = ((!defined($address)) ? '' : substr($address,index($address,'@')+1)); - $expands->{'$'} = '$'; - $expands->{';'} = ';'; - - if (defined($trigger->{'replace'})) { # it's a -replace - $message =~ s/$trigger->{'compregexp'}/do_expands($trigger->{'compreplace'},$expands,$message)/ge; - $changed = 1; - } - - if ($trigger->{'command'}) { # it's a (nonempty) -command - my $command = $trigger->{'command'}; - # $1 = the stuff behind the $ we want to expand: a number, or a character from %expands - $command = do_expands($command, $expands, $message); - - if (defined($server)) { - if (defined($channelname) && $server->channel_find($channelname)) { - $context = $server->channel_find($channelname); - } else { - $context = $server; - } - } else { - $context = undef; - } - - if (defined($context)) { - $context->command("eval $command"); - } else { - Irssi::command("eval $command"); - } - } - - if ($trigger->{'debug'}) { - print("DEBUG: trigger $condition pmesg=$parammessage message=$message server=$server->{tag} channel=$channelname nick=$nickname address=$address " . join(' ',map {$_ . '=' . $extra->{$_}} keys(%$extra))); - } - - if ($trigger->{'stop'}) { - $stopped = 1; - } - - if ($trigger->{'once'}) { - # find this trigger in the real trigger list, and remove it - for (my $realindex=0; $realindex < scalar(@triggers); $realindex++) { - if ($triggers[$realindex] == $trigger) { - splice (@triggers,$realindex,1); - last; - } - } - $need_rebuild = 1; - } - } - - if ($need_rebuild) { - rebuild(); - $changed_since_last_save = 1; - } - if ($stopped) { # stopped with -stop - signal_stop(); - } elsif ($changed) { # changed with -replace - $signal->[$parammessage] = $message; - signal_continue(@$signal); - } - $recursion_depth--; -} - -# used in check_signal_message to expand $'s -# $inthis is a string that can contain $ stuff (like 'foo$1bar$N') -sub do_expands { - my ($inthis, $expands, $from) = @_; - # @+ and @- are copied because there are two s/// nested, and the inner needs the $1 and $2,... of the outer one - my @plus = @+; - my @min = @-; - my $p = \@plus; my $m = \@min; - $inthis =~ s/\$(\\*(\d+|[^0-9x{]|x[0-9a-fA-F][0-9a-fA-F]|{.*?}))/expand_and_escape($1,$expands,$m,$p,$from)/ge; - return $inthis; -} - -# \ $ and ; need extra escaping because we use eval -sub expand_and_escape { - my $retval = expand(@_); - $retval =~ s/([\\\$;])/\\\1/g; - return $retval; -} - -# used in do_expands (via expand_and_escape), to_expand is the part after the $ -sub expand { - my ($to_expand, $expands, $min, $plus, $from) = @_; - if ($to_expand =~ /^\d+$/) { # a number => look up in $vars - # from man perlvar: - # $3 is the same as "substr $var, $-[3], $+[3] - $-[3])" - return ($to_expand > @{$min} ? '' : substr($from,$min->[$to_expand],$plus->[$to_expand]-$min->[$to_expand])); - } elsif ($to_expand =~ s/^\\//) { # begins with \, so strip that from to_expand - my $exp = expand($to_expand,$expands,$min,$plus,$from); # first expand without \ - $exp =~ s/([^a-zA-Z0-9])/\\\1/g; # escape non-word chars - return $exp; - } elsif ($to_expand =~ /^x([0-9a-fA-F]{2})/) { # $xAA - return chr(hex($1)); - } elsif ($to_expand =~ /^{(.*?)}$/) { # ${foo} - return expand($1, $expands, $min, $plus, $from); - } else { # look up in $expands - return $expands->{$to_expand}; - } -} - -sub check_modes { - my ($has_modes, $need_modes) = @_; - my $matches; - my $switch = 1; # if a '-' if found, will be 0 (meaning the modes should not be set) - foreach my $need_mode (split /&/, $need_modes) { - $matches = 0; - foreach my $char (split //, $need_mode) { - if ($char eq '-') { - $switch = 0; - } elsif ($char eq '+') { - $switch = 1; - } elsif ((index($has_modes, $char) != -1) == $switch) { - $matches = 1; - last; - } - } - if (!$matches) { - return 0; - } - } - return 1; -} - -# get someones flags from people.pl or friends(_shasta).pl -sub get_flags { - my ($chatnet, $channel, $nick, $address) = @_; - my $flags; - no strict 'refs'; - if (defined %{ 'Irssi::Script::people::' }) { - if (defined ($channel)) { - $flags = (&{ 'Irssi::Script::people::find_local_flags' }($chatnet,$channel,$nick,$address)); - } else { - $flags = (&{ 'Irssi::Script::people::find_global_flags' }($chatnet,$nick,$address)); - } - $flags = join('',keys(%{$flags})); - } else { - my $shasta; - if (defined %{ 'Irssi::Script::friends_shasta::' }) { - $shasta = 'friends_shasta'; - } elsif (defined &{ 'Irssi::Script::friends::get_idx' }) { - $shasta = 'friends'; - } else { - return undef; - } - my $idx = (&{ 'Irssi::Script::'.$shasta.'::get_idx' }($nick, $address)); - if ($idx == -1) { - return ''; - } - $flags = (&{ 'Irssi::Script::'.$shasta.'::get_friends_flags' }($idx,undef)); - if ($channel) { - $flags .= (&{ 'Irssi::Script::'.$shasta.'::get_friends_flags' }($idx,$channel)); - } - } - return $flags; -} - -######################################################## -### internal stuff called by manage, needed by above ### -######################################################## - -my %mask_to_regexp = (); -foreach my $i (0..255) { - my $ch = chr $i; - $mask_to_regexp{$ch} = "\Q$ch\E"; -} -$mask_to_regexp{'?'} = '(.)'; -$mask_to_regexp{'*'} = '(.*)'; - -sub compile_trigger { - my ($trigger) = @_; - my $regexp; - - if ($trigger->{'regexp'}) { - $regexp = $trigger->{'regexp'}; - } elsif ($trigger->{'pattern'}) { - $regexp = $trigger->{'pattern'}; - $regexp =~ s/(.)/$mask_to_regexp{$1}/g; - } else { - delete $trigger->{'compregexp'}; - return; - } - - if ($trigger->{'nocase'}) { - $regexp = '(?i)' . $regexp; - } - - $trigger->{'compregexp'} = qr/$regexp/; - - if(defined($trigger->{'replace'})) { - (my $replace = $trigger->{'replace'}) =~ s/\$/\$\$/g; - $trigger->{'compreplace'} = Irssi::parse_special($replace); - } -} - -# rebuilds triggers_by_type and updates signal binds -sub rebuild { - %triggers_by_type = (); - foreach my $trigger (@triggers) { - if (!$trigger->{'disabled'}) { - if ($trigger->{'all'}) { - # -all is an alias for all types in @all_types for which the filters can apply -ALLTYPES: - foreach my $type (@all_types) { - # check if all filters can apply to $type - foreach my $filter (@{$trigger->{'filters'}}) { - if (! grep {$_ eq $type} $filters{$filter->[0]}->{'types'}) { - next ALLTYPES; - } - } - push @{$triggers_by_type{$type}}, ($trigger); - } - } - - foreach my $type ($trigger->{'all'} ? @notall_types : @trigger_types) { - if ($trigger->{$type}) { - push @{$triggers_by_type{$type}}, ($trigger); - } - } - } - } - - foreach my $signal (@signals) { - my $should_bind = 0; - foreach my $type (@{$signal->{'types'}}) { - if (defined($triggers_by_type{$type})) { - $should_bind = 1; - } - } - if ($should_bind && !$signal->{'bind'}) { - signal_add_first($signal->{'signal'}, $signal->{'sub'}); - $signal->{'bind'} = 1; - } elsif (!$should_bind && $signal->{'bind'}) { - signal_remove($signal->{'signal'}, $signal->{'sub'}); - $signal->{'bind'} = 0; - } - } -} - -################################ -### manage the triggers-list ### -################################ - -my $trigger_file; # cached setting - -sub sig_setup_changed { - $trigger_file = Irssi::settings_get_str('trigger_file'); -} - -sub autosave { - cmd_save() if ($changed_since_last_save); -} - -# TRIGGER SAVE -sub cmd_save { - my $io = new IO::File $trigger_file, "w"; - if (defined $io) { - $io->print("#Triggers file version $VERSION\n"); - foreach my $trigger (@triggers) { - $io->print(to_string($trigger) . "\n"); - } - $io->close; - } - Irssi::printformat(MSGLEVEL_CLIENTNOTICE, 'trigger_saved', $trigger_file); - $changed_since_last_save = 0; -} - -# save on unload -sub UNLOAD { - cmd_save(); -} - -# TRIGGER LOAD -sub cmd_load { - sig_setup_changed(); # make sure we've read the trigger_file setting - my $converted = 0; - my $io = new IO::File $trigger_file, "r"; - if (not defined $io) { - if (-e $trigger_file) { - Irssi::print("Error opening triggers file", MSGLEVEL_CLIENTERROR); - } - return; - } - if (defined $io) { - @triggers = (); - my $text; - $text = $io->getline; - my $file_version = ''; - if ($text =~ /^#Triggers file version (.*)\n/) { - $file_version = $1; - } - if ($file_version lt '0.6.1+2') { - no strict 'vars'; - $text .= $_ foreach ($io->getlines); - my $rep = eval "$text"; - if (! ref $rep) { - Irssi::print("Error in triggers file"); - return; - } - my @old_triggers = @$rep; - - for (my $index=0;$index < scalar(@old_triggers);$index++) { - my $trigger = $old_triggers[$index]; - - if ($file_version lt '0.6.1') { - # convert old names: notices => pubnotices, actions => pubactions - foreach $oldname ('notices','actions') { - if ($trigger->{$oldname}) { - delete $trigger->{$oldname}; - $trigger->{'pub'.$oldname} = 1; - $converted = 1; - } - } - } - if ($file_version lt '0.6.1+1' && $trigger->{'modifiers'}) { - if ($trigger->{'modifiers'} =~ /i/) { - $trigger->{'nocase'} = 1; - Irssi::print("Trigger: trigger ".($index+1)." had 'i' in it's modifiers, it has been converted to -nocase"); - } - if ($trigger->{'modifiers'} !~ /^[ig]*$/) { - Irssi::print("Trigger: trigger ".($index+1)." had unrecognised modifier '". $trigger->{'modifiers'} ."', which couldn't be converted."); - } - delete $trigger->{'modifiers'}; - $converted = 1; - } - - if (defined($trigger->{'replace'}) && ! $trigger->{'regexp'}) { - Irssi::print("Trigger: trigger ".($index+1)." had -replace but no -regexp, removed it"); - splice (@old_triggers,$index,1); - $index--; # nr of next trigger now is the same as this one was - } - - # convert to text with compat, and then to new trigger hash - $text = to_string($trigger,1); - my @args = &shellwords($text . ' a'); - my $trigger = parse_options({},@args); - if ($trigger) { - push @triggers, $trigger; - } - } - } else { # new format - while ( $text = $io->getline ) { - chop($text); - my @args = &shellwords($text . ' a'); - my $trigger = parse_options({},@args); - if ($trigger) { - push @triggers, $trigger; - } - } - } - } - Irssi::printformat(MSGLEVEL_CLIENTNOTICE, 'trigger_loaded', $trigger_file); - if ($converted) { - Irssi::print("Trigger: Triggers file will be in new format next time it's saved."); - } - rebuild(); -} - -# escape for printing with to_string -# <<abcdef>> => << 'abcdef' >> -# <<abc'def>> => << "abc'def" >> -# <<abc'def\x02>> => << 'abc'\''def\x02' >> -sub param_to_string { - my ($text) = @_; - # avoid ugly escaping if we can use "-quotes without other escaping (no " or \) - if ($text =~ /^[^"\\]*'[^"\\]$/) { - return ' "' . $text . '" '; - } - # "'" signs without a (odd number of) \ in front of them, need be to escaped as '\'' - # this is ugly :( - $text =~ s/(^|[^\\](\\\\)*)'/$1'\\''/g; - return " '$text' "; -} - -# converts a trigger back to "-switch -options 'foo'" form -# if $compat, $trigger is in the old format (used to convert) -sub to_string { - my ($trigger, $compat) = @_; - my $string; - - foreach my $switch (@trigger_switches) { - if ($trigger->{$switch}) { - $string .= '-'.$switch.' '; - } - } - - if ($compat) { - foreach my $filter (keys(%filters)) { - if ($trigger->{$filter}) { - $string .= '-' . $filter . param_to_string($trigger->{$filter}); - } - } - } else { - foreach my $trigfilter (@{$trigger->{'filters'}}) { - $string .= '-' . $trigfilter->[0] . param_to_string($trigfilter->[1]); - } - } - - foreach my $param (@trigger_params) { - if ($trigger->{$param} || ($param eq 'replace' && defined($trigger->{'replace'}))) { - $string .= '-' . $param . param_to_string($trigger->{$param}); - } - } - return $string; -} - -# find a trigger (for REPLACE and DELETE), returns index of trigger, or -1 if not found -sub find_trigger { - my ($data) = @_; - if ($data =~ /^[0-9]*$/ and defined($triggers[$data-1])) { - return $data-1; - } else { - for (my $i=0; $i < scalar(@triggers); $i++) { - if ($triggers[$i]->{'name'} eq $data) { - return $i; - } - } - } - Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'trigger_not_found', $data); - return -1; # not found -} - - -# TRIGGER ADD <options> -sub cmd_add { - my ($data, $server, $item) = @_; - my @args = shellwords($data . ' a'); - - my $trigger = parse_options({}, @args); - if ($trigger) { - push @triggers, $trigger; - Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'trigger_added', scalar(@triggers), to_string($trigger)); - rebuild(); - $changed_since_last_save = 1; - } -} - -# TRIGGER CHANGE <nr> <options> -sub cmd_change { - my ($data, $server, $item) = @_; - my @args = shellwords($data . ' a'); - my $index = find_trigger(shift @args); - if ($index != -1) { - if(parse_options($triggers[$index], @args)) { - Irssi::print("Trigger " . ($index+1) ." changed to: ". to_string($triggers[$index])); - } - rebuild(); - $changed_since_last_save = 1; - } -} - -# parses options for TRIGGER ADD and TRIGGER CHANGE -# if invalid args returns undef, else changes $thetrigger and returns it -sub parse_options { - my ($thetrigger,@args) = @_; - my ($trigger, $option); - - if (pop(@args) ne 'a') { - Irssi::print("Syntax error, probably missing a closing quote", MSGLEVEL_CLIENTERROR); - return undef; - } - - %$trigger = %$thetrigger; # make a copy to prevent changing the given trigger if args doesn't parse -ARGS: for (my $arg = shift @args; $arg; $arg = shift @args) { - # expand abbreviated options, put in $option - $arg =~ s/^-//; - $option = undef; - foreach my $ioption (@trigger_options) { - if (index($ioption, $arg) == 0) { # -$opt starts with $arg - if ($option) { # another already matched - Irssi::print("Ambiguous option: $arg", MSGLEVEL_CLIENTERROR); - return undef; - } - $option = $ioption; - last if ($arg eq $ioption); # exact match is unambiguous - } - } - if (!$option) { - Irssi::print("Unknown option: $arg", MSGLEVEL_CLIENTERROR); - return undef; - } - - # -<param> <value> or -no<param> - foreach my $param (@trigger_params) { - if ($option eq $param) { - $trigger->{$param} = shift @args; - next ARGS; - } - if ($option eq 'no'.$param) { - $trigger->{$param} = undef; - next ARGS; - } - } - - # -[no]<switch> - foreach my $switch (@trigger_switches) { - # -<switch> - if ($option eq $switch) { - $trigger->{$switch} = 1; - next ARGS; - } - # -no<switch> - elsif ($option eq 'no'.$switch) { - $trigger->{$switch} = undef; - next ARGS; - } - } - - # -<filter> <value> - if ($filters{$option}) { - push @{$trigger->{'filters'}}, [$option, shift @args, $filters{$option}->{'sub'}]; - next ARGS; - } - - # -<nofilter> - if ($option =~ /^no(.*)$/ && $filters{$1}) { - my $filter = $1; - # the new filters are the old grepped for everything except ones with name $filter - @{$trigger->{'filters'}} = grep( $_->[0] ne $filter, @{$trigger->{'filters'}} ); - } - } - - if (defined($trigger->{'replace'}) && ! $trigger->{'regexp'} && !$trigger->{'pattern'}) { - Irssi::print("Trigger error: Can't have -replace without -regexp", MSGLEVEL_CLIENTERROR); - return undef; - } - - if ($trigger->{'pattern'} && $trigger->{'regexp'}) { - Irssi::print("Trigger error: Can't have -pattern and -regexp in same trigger", MSGLEVEL_CLIENTERROR); - return undef; - } - - # remove types that are implied by -all - if ($trigger->{'all'}) { - foreach my $type (@all_types) { - delete $trigger->{$type}; - } - } - - # remove types for which the filters don't apply - foreach my $type (@trigger_types) { - if ($trigger->{$type}) { - foreach my $filter (@{$trigger->{'filters'}}) { - if (!grep {$_ eq $type} @{$filters{$filter->[0]}->{'types'}}) { - Irssi::print("Warning: the filter -" . $filter->[0] . " can't apply to an event of type -$type, so I'm removing that type from this trigger."); - delete $trigger->{$type}; - } - } - } - } - - # check if it has at least one type - my $has_a_type; - foreach my $type (@trigger_types) { - if ($trigger->{$type}) { - $has_a_type = 1; - last; - } - } - if (!$has_a_type && !$trigger->{'all'}) { - Irssi::print("Warning: this trigger doesn't trigger on any type of message. you probably want to add -publics or -all"); - } - - compile_trigger($trigger); - %$thetrigger = %$trigger; # copy changes to real trigger - return $thetrigger; -} - -# TRIGGER DELETE <num> -sub cmd_del { - my ($data, $server, $item) = @_; - my @args = shellwords($data); - my $index = find_trigger(shift @args); - if ($index != -1) { - Irssi::print("Deleted ". ($index+1) .": ". to_string($triggers[$index])); - splice (@triggers,$index,1); - rebuild(); - $changed_since_last_save = 1; - } -} - -# TRIGGER MOVE <num> <num> -sub cmd_move { - my ($data, $server, $item) = @_; - my @args = &shellwords($data); - my $index = find_trigger(shift @args); - if ($index != -1) { - my $newindex = shift @args; - if ($newindex < 1 || $newindex > scalar(@triggers)) { - Irssi::print("$newindex is not a valid trigger number"); - return; - } - Irssi::print("Moved from ". ($index+1) ." to $newindex: ". to_string($triggers[$index])); - $newindex -= 1; # array starts counting from 0 - my $trigger = splice (@triggers,$index,1); # remove from old place - splice (@triggers,$newindex,0,($trigger)); # insert at new place - rebuild(); - $changed_since_last_save = 1; - } -} - -# TRIGGER LIST -sub cmd_list { - Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'trigger_header'); - my $i=1; - foreach my $trigger (@triggers) { - Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'trigger_line', $i++, to_string($trigger)); - } -} - -###################### -### initialisation ### -###################### - -command_bind('trigger help',\&cmd_help); -command_bind('help trigger',\&cmd_help); -command_bind('trigger add',\&cmd_add); -command_bind('trigger change',\&cmd_change); -command_bind('trigger move',\&cmd_move); -command_bind('trigger list',\&cmd_list); -command_bind('trigger delete',\&cmd_del); -command_bind('trigger save',\&cmd_save); -command_bind('trigger reload',\&cmd_load); -command_bind 'trigger' => sub { - my ( $data, $server, $item ) = @_; - $data =~ s/\s+$//g; - command_runsub('trigger', $data, $server, $item); -}; - -Irssi::signal_add('setup saved', \&autosave); -Irssi::signal_add('setup changed', \&sig_setup_changed); - -# This makes tab completion work -Irssi::command_set_options('trigger add',join(' ',@trigger_add_options)); -Irssi::command_set_options('trigger change',join(' ',@trigger_options)); - -Irssi::settings_add_str($IRSSI{'name'}, 'trigger_file', Irssi::get_irssi_dir()."/triggers"); - -cmd_load(); diff --git a/protocols/skype/t/livetest-bitlbee.sh b/protocols/skype/t/livetest-bitlbee.sh deleted file mode 100755 index 7cbfbf6e..00000000 --- a/protocols/skype/t/livetest-bitlbee.sh +++ /dev/null @@ -1,116 +0,0 @@ -#!/usr/bin/env bash - -start_skyped() -{ - python ../skyped.py "$@" > skypedtest.pid - while true - do - [ -e skypedtest.pid ] || break - pid=$(sed 's/.*: //' skypedtest.pid) - if [ -n "$(ps -p $pid -o pid=)" ]; then - sleep 5 - else - start_skyped "$@" - break - fi - done -} - -BITLBEE=$1 -typeset -ix PORT=`echo $2 | egrep '^[0-9]{1,5}$'` -SCRIPT=$3 -shift 3 - -[ -n "$SCRIPT" -a -n "$BITLBEE" -a -e "$SCRIPT" -a "$PORT" -ne 0 ] || { echo Syntax: `basename "$0"` bitlbee-executable listening-port test-script test-script-args; exit 1; } - -# Create or empty test dir -mkdir livetest 2>/dev/null || rm livetest/bitlbeetest*.xml bitlbeetest.pid 2>/dev/null - -# Run the bee -echo Running bitlbee... -$VALGRIND $BITLBEE -n -c bitlbee.conf -d livetest/ -D -P bitlbeetest.pid -p $PORT 2>bitlbee.log & -sleep 2 - -# Check if it's really running -kill -0 `cat bitlbeetest.pid 2>/dev/null ` 2>/dev/null || { echo Failed to run bitlbee daemon on port $PORT; exit 1; } - -if [ -z "$TUNNELED_MODE" ]; then - # Set up skyped - - rm -rf etc - mkdir etc - cd etc - cp ../../skyped.cnf . - cp ~/.skyped/skyped.cert.pem . - cp ~/.skyped/skyped.key.pem . - cd .. - echo "[skyped]" > skyped.conf - echo "username = $TEST_SKYPE_ID" >> skyped.conf - SHA1=`which sha1sum` - if [ -z "$SHA1" ]; then - SHA1=`which sha1` - fi - if [ -z "$SHA1" ]; then - echo Test failed - echo "(Can't compute password for skyped.conf)" - exit 77 - fi - echo "password = $(echo -n $TEST_SKYPE_PASSWORD|$SHA1|sed 's/ *-$//')" >> skyped.conf - # we use ~ here to test that resolve that syntax works - echo "cert = $(pwd|sed "s|$HOME|~|")/etc/skyped.cert.pem" >> skyped.conf - echo "key = $(pwd|sed "s|$HOME|~|")/etc/skyped.key.pem" >> skyped.conf - echo "port = 2727" >> skyped.conf - - # Run skyped - start_skyped -c skyped.conf -l skypedtest.log & - sleep 2 -fi - -if [ "$TUNNELED_MODE" = "yes" ]; then - rm -f tunnel.pid - if [ -n "$TUNNEL_SCRIPT" ]; then - $TUNNEL_SCRIPT & - echo $! > tunnel.pid - sleep 5 - fi -fi - -# Run the test -echo Running test script... -"$SCRIPT" $* -RET=$? - -if [ -z "$TUNNELED_MODE" ]; then - # skyped runs on another host: no means to kill it - # Kill skyped - killall -TERM skype - if [ -f skypedtest.pid ]; then - pid=$(sed 's/.*: //' skypedtest.pid) - rm skypedtest.pid - [ -n "$(ps -p $pid -o pid=)" ] && kill -TERM $pid - fi -fi - -if [ "$TUNNELED_MODE" = "yes" ]; then - if [ -n "$TUNNEL_SCRIPT" ]; then - cat tunnel.pid >> /tmp/tunnel.pid - kill `cat tunnel.pid` - rm -f tunnel.pid - fi -fi - -# Kill bee -echo Killing bitlbee... -kill `cat bitlbeetest.pid` - -if [ "$TUNNELED_MODE" = "yes" ]; then - # give the skyped a chance to timeout - sleep 30 -fi - -# Return test result -[ $RET -eq 0 ] && echo Test passed -[ $RET -ne 0 ] && echo Test failed -[ $RET -eq 22 ] && echo '(timed out)' -[ $RET -eq 66 ] && echo '(environment variables missing)' -exit $RET diff --git a/protocols/skype/t/login-bitlbee.mock b/protocols/skype/t/login-bitlbee.mock new file mode 100644 index 00000000..41273a83 --- /dev/null +++ b/protocols/skype/t/login-bitlbee.mock @@ -0,0 +1,7 @@ +>> NOTICE AUTH +<< NICK alice +<< USER alice alice localhost :Alice +>> PRIVMSG &bitlbee +<< PRIVMSG &bitlbee :account add skype alice foo +<< PRIVMSG &bitlbee :account skype on +>> PRIVMSG &bitlbee :skype - Logging in: Logged in diff --git a/protocols/skype/t/login-skyped.mock b/protocols/skype/t/login-skyped.mock new file mode 100644 index 00000000..eacff2e6 --- /dev/null +++ b/protocols/skype/t/login-skyped.mock @@ -0,0 +1,16 @@ +>> SEARCH GROUPS CUSTOM +<< GROUPS 48, 49 +>> SEARCH FRIENDS +<< USERS echo123, bob +>> SET USERSTATUS ONLINE +<< USERSTATUS ONLINE +>> SET USERSTATUS ONLINE +<< USERSTATUS ONLINE +>> GET USER echo123 ONLINESTATUS +<< USER echo123 ONLINESTATUS ONLINE +>> GET USER echo123 FULLNAME +<< USER echo123 FULLNAME Echo / Sound Test Service +>> GET USER bob ONLINESTATUS +<< USER bob ONLINESTATUS ONLINE +>> GET USER bob FULLNAME +<< USER bob FULLNAME Bob diff --git a/protocols/skype/t/msg-bitlbee.mock b/protocols/skype/t/msg-bitlbee.mock new file mode 100644 index 00000000..42cc163d --- /dev/null +++ b/protocols/skype/t/msg-bitlbee.mock @@ -0,0 +1,9 @@ +>> NOTICE AUTH +<< NICK alice +<< USER alice alice localhost :Alice +>> PRIVMSG &bitlbee +<< PRIVMSG &bitlbee :account add skype alice foo +<< PRIVMSG &bitlbee :account skype on +>> :bob!bob@skype.com JOIN :&bitlbee +<< PRIVMSG &bitlbee :bob: foo +>> :bob!bob@skype.com PRIVMSG &bitlbee :alice: bar diff --git a/protocols/skype/t/msg-skyped.mock b/protocols/skype/t/msg-skyped.mock new file mode 100644 index 00000000..03efb6bc --- /dev/null +++ b/protocols/skype/t/msg-skyped.mock @@ -0,0 +1,49 @@ +>> SEARCH GROUPS CUSTOM +<< GROUPS 48, 49 +>> SEARCH FRIENDS +<< USERS echo123, bob +>> SET USERSTATUS ONLINE +<< USERSTATUS ONLINE +>> SET USERSTATUS ONLINE +<< USERSTATUS ONLINE +>> GET USER echo123 ONLINESTATUS +<< USER echo123 ONLINESTATUS ONLINE +>> GET USER echo123 FULLNAME +<< USER echo123 FULLNAME Echo / Sound Test Service +>> GET USER bob ONLINESTATUS +<< USER bob ONLINESTATUS ONLINE +>> GET USER bob FULLNAME +<< USER bob FULLNAME Bob +>> MESSAGE bob foo +<< CHATMESSAGE 290 STATUS SENDING +<< CHAT #alice/$bob;ea753190f0a3e49b NAME #alice/$bob;ea753190f0a3e49b +<< CHAT #alice/$bob;ea753190f0a3e49b STATUS DIALOG +<< CHATMEMBER 287 ROLE USER +<< CHAT #alice/$bob;ea753190f0a3e49b MYROLE USER +<< CHAT #alice/$bob;ea753190f0a3e49b MEMBERS alice bob +<< CHAT #alice/$bob;ea753190f0a3e49b ACTIVEMEMBERS alice +<< CHAT #alice/$bob;ea753190f0a3e49b STATUS DIALOG +<< CHAT #alice/$bob;ea753190f0a3e49b TIMESTAMP 1357987847 +<< CHAT #alice/$bob;ea753190f0a3e49b DIALOG_PARTNER bob +<< CHAT #alice/$bob;ea753190f0a3e49b MEMBERS alice bob +<< CHAT #alice/$bob;ea753190f0a3e49b FRIENDLYNAME bob | foo +<< CHAT #alice/$bob;ea753190f0a3e49b POSTERS alice +<< CHAT #alice/$bob;ea753190f0a3e49b ACTIVITY_TIMESTAMP 1357987847 +<< CHAT #alice/$bob;ea753190f0a3e49b FRIENDLYNAME bob | foo +<< CHATMESSAGE 289 STATUS SENDING +<< CHATMESSAGE 290 STATUS SENDING +<< CHATMESSAGE 289 STATUS SENT +<< CHATMESSAGE 290 STATUS SENT +<< CHATMEMBER 288 IS_ACTIVE TRUE +<< CHAT #alice/$bob;ea753190f0a3e49b ACTIVEMEMBERS alice bob +<< CHAT #alice/$bob;ea753190f0a3e49b POSTERS alice bob +<< CHAT #alice/$bob;ea753190f0a3e49b ACTIVITY_TIMESTAMP 1357987875 +<< CHATMESSAGE 293 STATUS RECEIVED +>> GET CHATMESSAGE 293 FROM_HANDLE +<< CHATMESSAGE 293 FROM_HANDLE bob +>> GET CHATMESSAGE 293 BODY +<< CHATMESSAGE 293 BODY bar +>> GET CHATMESSAGE 293 TYPE +<< CHATMESSAGE 293 TYPE SAID +>> GET CHATMESSAGE 293 CHATNAME +<< CHATMESSAGE 293 CHATNAME #alice/$bob;ea753190f0a3e49b diff --git a/protocols/skype/t/set-mood-text-bitlbee.mock b/protocols/skype/t/set-mood-text-bitlbee.mock new file mode 100644 index 00000000..f017f8bd --- /dev/null +++ b/protocols/skype/t/set-mood-text-bitlbee.mock @@ -0,0 +1,9 @@ +>> NOTICE AUTH +<< NICK alice +<< USER alice alice localhost :Alice +>> PRIVMSG &bitlbee +<< PRIVMSG &bitlbee :account add skype alice foo +<< PRIVMSG &bitlbee :account skype set skypeconsole_receive true +<< PRIVMSG &bitlbee :account skype on +<< PRIVMSG &bitlbee :account skype set mood_text "foo bar" +>> PRIVMSG &bitlbee :alice: PROFILE MOOD_TEXT foo bar diff --git a/protocols/skype/t/set-mood-text-skyped.mock b/protocols/skype/t/set-mood-text-skyped.mock new file mode 100644 index 00000000..566f4234 --- /dev/null +++ b/protocols/skype/t/set-mood-text-skyped.mock @@ -0,0 +1,14 @@ +>> SEARCH GROUPS CUSTOM +<< GROUPS 48, 49 +>> SEARCH FRIENDS +<< USERS echo123 +>> SET USERSTATUS ONLINE +<< USERSTATUS ONLINE +>> SET USERSTATUS ONLINE +<< USERSTATUS ONLINE +>> GET USER echo123 ONLINESTATUS +<< USER echo123 ONLINESTATUS ONLINE +>> GET USER echo123 FULLNAME +<< USER echo123 FULLNAME Echo / Sound Test Service +>> SET PROFILE MOOD_TEXT foo bar +<< PROFILE MOOD_TEXT foo bar diff --git a/protocols/skype/test.py b/protocols/skype/test.py new file mode 100755 index 00000000..63652f76 --- /dev/null +++ b/protocols/skype/test.py @@ -0,0 +1,135 @@ +#!/usr/bin/env python2.7 + +import subprocess +import sys +import pexpect +import unittest +import shutil +import os +import hashlib + +def openssl(args): + with open(os.devnull, "w") as devnull: + proc = subprocess.Popen(['openssl'] + args, stdin=subprocess.PIPE, stderr=devnull) + for i in range(6): + proc.stdin.write("\n") + proc.stdin.close() + proc.communicate() +def setupSkyped(): + try: + shutil.rmtree("t/skyped") + except OSError: + pass + os.makedirs("t/skyped") + cwd = os.getcwd() + os.chdir("t/skyped") + try: + shutil.copyfile("../../skyped.cnf", "skyped.cnf") + openssl(['req', '-new', '-x509', '-days', '365', '-nodes', '-config', 'skyped.cnf', '-out', 'skyped.cert.pem', '-keyout', 'skyped.key.pem']) + with open("skyped.conf", "w") as sock: + sock.write("[skyped]\n") + sock.write("username = alice\n") + sock.write("password = %s\n" % hashlib.sha1("foo").hexdigest()) + sock.write("cert = %s/skyped.cert.pem\n" % os.getcwd()) + sock.write("key = %s/skyped.key.pem\n" % os.getcwd()) + sock.write("port = 2727\n") + finally: + os.chdir(cwd) + +class Test(unittest.TestCase): + def mock(self, name): + with open("t/skyped.log", "w") as skyped_log,\ + open("t/pexpect.log", "w") as pexpect_log: + skyped = subprocess.Popen([sys.executable, "skyped.py", + "-c", "t/skyped/skyped.conf", "-n", "-d", "-m", "t/%s-skyped.mock" % name], + stdout=skyped_log, stderr=subprocess.STDOUT) + try: + bitlbee = pexpect.spawn('../../bitlbee', ['-d', 't/bitlbee'], logfile=pexpect_log) + if os.environ.get('ATTACH_GDB'): + subprocess.Popen(['gdb', '-batch-silent', + '-ex', 'set logging overwrite on', + '-ex', 'set logging file t/gdb-%s.log' % bitlbee.pid, + '-ex', 'set logging on', + '-ex', 'handle all pass nostop noprint', + '-ex', 'handle SIGSEGV pass stop print', + '-ex', 'set pagination 0', + '-ex', 'continue', + '-ex', 'backtrace full', + '-ex', 'info registers', + '-ex', 'thread apply all backtrace', + '-ex', 'quit', + '../../bitlbee', str(bitlbee.pid) ]) + bitlbee_mock = open("t/%s-bitlbee.mock" % name) + for i in bitlbee_mock.readlines(): + line = i.strip() + if line.startswith(">> "): + bitlbee.expect_exact(line[3:], timeout=10) + elif line.startswith("<< "): + bitlbee.sendline(line[3:]) + bitlbee_mock.close() + bitlbee.close() + finally: + skyped.terminate() + skyped.communicate() + + def setUp(self): + try: + shutil.rmtree("t/bitlbee") + except OSError: + pass + os.makedirs("t/bitlbee") + + def testMsg(self): + self.mock("msg") + + def testLogin(self): + self.mock("login") + + def testInfo(self): + self.mock("info") + + def testCall(self): + self.mock("call") + + def testCallFailed(self): + self.mock("call-failed") + + def testAddYes(self): + self.mock("add-yes") + + def testAddedYes(self): + self.mock("added-yes") + + def testAddedNo(self): + self.mock("added-no") + + def testGroupchatInvited(self): + self.mock("groupchat-invited") + + def testGroupchatInvite(self): + self.mock("groupchat-invite") + + def testGroupchatLeave(self): + self.mock("groupchat-leave") + + def testCalledYes(self): + self.mock("called-yes") + + def testCalledNo(self): + self.mock("called-no") + + def testFiletransfer(self): + self.mock("filetransfer") + + def testGroupRead(self): + self.mock("group-read") + + def testCtcpHelp(self): + self.mock("ctcp-help") + + def testSetMoodText(self): + self.mock("set-mood-text") + +if __name__ == '__main__': + setupSkyped() + unittest.main() diff --git a/protocols/twitter/Makefile b/protocols/twitter/Makefile index a1ad2301..ce87090f 100644 --- a/protocols/twitter/Makefile +++ b/protocols/twitter/Makefile @@ -37,7 +37,7 @@ $(objects): ../../Makefile.settings Makefile $(objects): %.o: $(_SRCDIR_)%.c @echo '*' Compiling $< - @$(CC) -c $(CFLAGS) $< -o $@ + @$(CC) -c $(CFLAGS) $(CFLAGS_BITLBEE) $< -o $@ twitter_mod.o: $(objects) @echo '*' Linking twitter_mod.o diff --git a/protocols/twitter/twitter.c b/protocols/twitter/twitter.c index f7e1ec76..db61ba7c 100644 --- a/protocols/twitter/twitter.c +++ b/protocols/twitter/twitter.c @@ -3,7 +3,8 @@ * BitlBee - An IRC to IM gateway * * Simple module to facilitate twitter functionality. * * * -* Copyright 2009 Geert Mulders <g.c.w.m.mulders@gmail.com> * +* Copyright 2009-2010 Geert Mulders <g.c.w.m.mulders@gmail.com> * +* Copyright 2010-2013 Wilmer van der Gaast <wilmer@gaast.net> * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public * @@ -28,17 +29,7 @@ #include "twitter_lib.h" #include "url.h" -#define twitter_msg( ic, fmt... ) \ - do { \ - struct twitter_data *td = ic->proto_data; \ - if( td->timeline_gc ) \ - imcb_chat_log( td->timeline_gc, fmt ); \ - else \ - imcb_log( ic, fmt ); \ - } while( 0 ); - GSList *twitter_connections = NULL; - /** * Main loop function */ @@ -61,15 +52,57 @@ static void twitter_main_loop_start(struct im_connection *ic) { struct twitter_data *td = ic->proto_data; + /* Create the room now that we "logged in". */ + if (td->flags & TWITTER_MODE_CHAT) + twitter_groupchat_init(ic); + imcb_log(ic, "Getting initial statuses"); - // Run this once. After this queue the main loop function. + // Run this once. After this queue the main loop function (or open the + // stream if available). twitter_main_loop(ic, -1, 0); + + if (set_getbool(&ic->acc->set, "stream")) { + /* That fetch was just to get backlog, the stream will give + us the rest. \o/ */ + twitter_open_stream(ic); + + /* Stream sends keepalives (empty lines) or actual data at + least twice a minute. Disconnect if this stops. */ + ic->flags |= OPT_PONGS; + } else { + /* Not using the streaming API, so keep polling the old- + fashioned way. :-( */ + td->main_loop_id = + b_timeout_add(set_getint(&ic->acc->set, "fetch_interval") * 1000, + twitter_main_loop, ic); + } +} + +struct groupchat *twitter_groupchat_init(struct im_connection *ic) +{ + char *name_hint; + struct groupchat *gc; + struct twitter_data *td = ic->proto_data; + GSList *l; + + if (td->timeline_gc) + return td->timeline_gc; + + td->timeline_gc = gc = imcb_chat_new(ic, "twitter/timeline"); + + name_hint = g_strdup_printf("%s_%s", td->prefix, ic->acc->user); + imcb_chat_name_hint(gc, name_hint); + g_free(name_hint); - // Queue the main_loop - // Save the return value, so we can remove the timeout on logout. - td->main_loop_id = - b_timeout_add(set_getint(&ic->acc->set, "fetch_interval") * 1000, twitter_main_loop, ic); + for (l = ic->bee->users; l; l = l->next) { + bee_user_t *bu = l->data; + if (bu->ic == ic) + imcb_chat_add_buddy(gc, bu->handle); + } + imcb_chat_add_buddy(gc, ic->acc->user); + + return gc; } static void twitter_oauth_start(struct im_connection *ic); @@ -82,11 +115,10 @@ void twitter_login_finish(struct im_connection *ic) if (set_getbool(&ic->acc->set, "oauth") && !td->oauth_info) twitter_oauth_start(ic); - else if (g_strcasecmp(set_getstr(&ic->acc->set, "mode"), "one") != 0 && - !(td->flags & TWITTER_HAVE_FRIENDS)) { + else if (!(td->flags & TWITTER_MODE_ONE) && + !(td->flags & TWITTER_HAVE_FRIENDS)) { imcb_log(ic, "Getting contact list"); twitter_get_friends_ids(ic, -1); - //twitter_get_statuses_friends(ic, -1); } else twitter_main_loop_start(ic); } @@ -160,17 +192,18 @@ static gboolean twitter_oauth_callback(struct oauth_info *info) imcb_buddy_msg(ic, name, msg, 0, 0); g_free(msg); } else if (info->stage == OAUTH_ACCESS_TOKEN) { + const char *sn; + if (info->token == NULL || info->token_secret == NULL) { imcb_error(ic, "OAuth error: %s", twitter_parse_error(info->http)); imc_logout(ic, TRUE); return FALSE; - } else { - const char *sn = oauth_params_get(&info->params, "screen_name"); - - if (sn != NULL && ic->acc->prpl->handle_cmp(sn, ic->acc->user) != 0) { + } + + if ((sn = oauth_params_get(&info->params, "screen_name"))) { + if (ic->acc->prpl->handle_cmp(sn, ic->acc->user) != 0) imcb_log(ic, "Warning: You logged in via OAuth as %s " - "instead of %s.", sn, ic->acc->user); - } + "instead of %s.", sn, ic->acc->user); g_free(td->user); td->user = g_strdup(sn); } @@ -186,16 +219,6 @@ static gboolean twitter_oauth_callback(struct oauth_info *info) return TRUE; } - -static char *set_eval_mode(set_t * set, char *value) -{ - if (g_strcasecmp(value, "one") == 0 || - g_strcasecmp(value, "many") == 0 || g_strcasecmp(value, "chat") == 0) - return value; - else - return NULL; -} - int twitter_url_len_diff(gchar *msg, unsigned int target_len) { int url_len_diff = 0; @@ -232,25 +255,39 @@ static gboolean twitter_length_check(struct im_connection *ic, gchar * msg) if (max == 0 || (len = g_utf8_strlen(msg, -1) + url_len_diff) <= max) return TRUE; - imcb_error(ic, "Maximum message length exceeded: %d > %d", len, max); + twitter_log(ic, "Maximum message length exceeded: %d > %d", len, max); return FALSE; } +static char *set_eval_commands(set_t * set, char *value) +{ + if (g_strcasecmp(value, "strict") == 0 ) + return value; + else + return set_eval_bool(set, value); +} + +static char *set_eval_mode(set_t * set, char *value) +{ + if (g_strcasecmp(value, "one") == 0 || + g_strcasecmp(value, "many") == 0 || g_strcasecmp(value, "chat") == 0) + return value; + else + return NULL; +} + static void twitter_init(account_t * acc) { set_t *s; char *def_url; - char *def_oauth; char *def_tul; if (strcmp(acc->prpl->name, "twitter") == 0) { def_url = TWITTER_API_URL; - def_oauth = "true"; def_tul = "20"; } else { /* if( strcmp( acc->prpl->name, "identica" ) == 0 ) */ def_url = IDENTICA_API_URL; - def_oauth = "true"; def_tul = "0"; } @@ -259,7 +296,7 @@ static void twitter_init(account_t * acc) s = set_add(&acc->set, "base_url", def_url, NULL, acc); s->flags |= ACC_SET_OFFLINE_ONLY; - s = set_add(&acc->set, "commands", "true", set_eval_bool, acc); + s = set_add(&acc->set, "commands", "true", set_eval_commands, acc); s = set_add(&acc->set, "fetch_interval", "60", set_eval_int, acc); s->flags |= ACC_SET_OFFLINE_ONLY; @@ -273,18 +310,22 @@ static void twitter_init(account_t * acc) s = set_add(&acc->set, "mode", "chat", set_eval_mode, acc); s->flags |= ACC_SET_OFFLINE_ONLY; - s = set_add(&acc->set, "oauth", def_oauth, set_eval_oauth, acc); + s = set_add(&acc->set, "oauth", "true", set_eval_oauth, acc); s = set_add(&acc->set, "show_ids", "true", set_eval_bool, acc); - s->flags |= ACC_SET_OFFLINE_ONLY; s = set_add(&acc->set, "show_old_mentions", "20", set_eval_int, acc); s = set_add(&acc->set, "strip_newlines", "false", set_eval_bool, acc); + + if (strcmp(acc->prpl->name, "twitter") == 0) { + s = set_add(&acc->set, "stream", "true", set_eval_bool, acc); + s->flags |= ACC_SET_OFFLINE_ONLY; + } } /** - * Login method. Since the twitter API works with seperate HTTP request we + * Login method. Since the twitter API works with separate HTTP request we * only save the user and pass to the twitter_data object. */ static void twitter_login(account_t * acc) @@ -302,6 +343,12 @@ static void twitter_login(account_t * acc) return; } + if (!strstr(url.host, "twitter.com") && + set_getbool(&ic->acc->set, "stream")) { + imcb_error(ic, "Warning: The streaming API is only supported by Twitter, " + "and you seem to be connecting to a different service."); + } + imcb_log(ic, "Connecting"); twitter_connections = g_slist_append(twitter_connections, ic); @@ -342,8 +389,16 @@ static void twitter_login(account_t * acc) imcb_add_buddy(ic, name, NULL); imcb_buddy_status(ic, name, OPT_LOGGED_IN, NULL, NULL); - if (set_getbool(&acc->set, "show_ids")) - td->log = g_new0(struct twitter_log_data, TWITTER_LOG_LENGTH); + td->log = g_new0(struct twitter_log_data, TWITTER_LOG_LENGTH); + td->log_id = -1; + + s = set_getstr(&ic->acc->set, "mode"); + if (g_strcasecmp(s, "one") == 0) + td->flags |= TWITTER_MODE_ONE; + else if (g_strcasecmp(s, "many") == 0) + td->flags |= TWITTER_MODE_MANY; + else + td->flags |= TWITTER_MODE_CHAT; twitter_login_finish(ic); } @@ -365,6 +420,7 @@ static void twitter_logout(struct im_connection *ic) imcb_chat_free(td->timeline_gc); if (td) { + http_close(td->stream); oauth_info_free(td->oauth_info); g_free(td->user); g_free(td->prefix); @@ -413,13 +469,6 @@ static int twitter_buddy_msg(struct im_connection *ic, char *who, char *message, return (0); } -/** - * - */ -static void twitter_set_my_name(struct im_connection *ic, char *info) -{ -} - static void twitter_get_info(struct im_connection *ic, char *who) { } @@ -492,132 +541,131 @@ static void twitter_buddy_data_free(struct bee_user *bu) g_free(bu->data); } +/** Convert the given bitlbee tweet ID, bitlbee username, or twitter tweet ID + * into a twitter tweet ID. + * + * Returns 0 if the user provides garbage. + */ +static guint64 twitter_message_id_from_command_arg(struct im_connection *ic, char *arg, bee_user_t **bu_) { + struct twitter_data *td = ic->proto_data; + struct twitter_user_data *tud; + bee_user_t *bu = NULL; + guint64 id = 0; + + if (bu_) + *bu_ = NULL; + if (!arg || !arg[0]) + return 0; + + if (arg[0] != '#' && (bu = bee_user_by_handle(ic->bee, ic, arg))) { + if ((tud = bu->data)) + id = tud->last_id; + } else { + if (arg[0] == '#') + arg++; + if (sscanf(arg, "%" G_GINT64_MODIFIER "x", &id) == 1 && + id < TWITTER_LOG_LENGTH) { + bu = td->log[id].bu; + id = td->log[id].id; + /* Beware of dangling pointers! */ + if (!g_slist_find(ic->bee->users, bu)) + bu = NULL; + } else if (sscanf(arg, "%" G_GINT64_MODIFIER "d", &id) == 1) { + /* Allow normal tweet IDs as well; not a very useful + feature but it's always been there. Just ignore + very low IDs to avoid accidents. */ + if (id < 1000000) + id = 0; + } + } + if (bu_) + *bu_ = bu; + return id; +} + static void twitter_handle_command(struct im_connection *ic, char *message) { struct twitter_data *td = ic->proto_data; char *cmds, **cmd, *new = NULL; - guint64 in_reply_to = 0; + guint64 in_reply_to = 0, id; + gboolean allow_post = + g_strcasecmp(set_getstr(&ic->acc->set, "commands"), "strict") != 0; + bee_user_t *bu = NULL; cmds = g_strdup(message); cmd = split_command_parts(cmds); if (cmd[0] == NULL) { - g_free(cmds); - return; - } else if (!set_getbool(&ic->acc->set, "commands")) { - /* Not supporting commands. */ + goto eof; + } else if (!set_getbool(&ic->acc->set, "commands") && allow_post) { + /* Not supporting commands if "commands" is set to true/strict. */ } else if (g_strcasecmp(cmd[0], "undo") == 0) { - guint64 id; - if (cmd[1] == NULL) twitter_status_destroy(ic, td->last_status_id); - else if (sscanf(cmd[1], "%" G_GUINT64_FORMAT, &id) == 1) { - if (id < TWITTER_LOG_LENGTH && td->log) - id = td->log[id].id; - + else if ((id = twitter_message_id_from_command_arg(ic, cmd[1], NULL))) twitter_status_destroy(ic, id); - } else - twitter_msg(ic, "Could not undo last action"); + else + twitter_log(ic, "Could not undo last action"); - g_free(cmds); - return; + goto eof; + } else if (g_strcasecmp(cmd[0], "favourite") == 0 && cmd[1]) { + if ((id = twitter_message_id_from_command_arg(ic, cmd[1], NULL))) { + twitter_favourite_tweet(ic, id); + } else { + twitter_log(ic, "Please provide a message ID or username."); + } + goto eof; } else if (g_strcasecmp(cmd[0], "follow") == 0 && cmd[1]) { twitter_add_buddy(ic, cmd[1], NULL); - g_free(cmds); - return; + goto eof; } else if (g_strcasecmp(cmd[0], "unfollow") == 0 && cmd[1]) { twitter_remove_buddy(ic, cmd[1], NULL); - g_free(cmds); - return; + goto eof; } else if ((g_strcasecmp(cmd[0], "report") == 0 || g_strcasecmp(cmd[0], "spam") == 0) && cmd[1]) { - char * screen_name; - guint64 id; - screen_name = cmd[1]; + char *screen_name; + /* Report nominally works on users but look up the user who posted the given ID if the user wants to do it that way */ - if (g_str_has_prefix(cmd[1], "#") && - sscanf(cmd[1] + 1, "%" G_GUINT64_FORMAT, &id) == 1) { - if (id < TWITTER_LOG_LENGTH && td->log) { - if (g_slist_find(ic->bee->users, td->log[id].bu)) { - screen_name = td->log[id].bu->handle; - } - } - } + twitter_message_id_from_command_arg(ic, cmd[1], &bu); + if (bu) + screen_name = bu->handle; + else + screen_name = cmd[1]; + twitter_report_spam(ic, screen_name); - g_free(cmds); - return; + goto eof; } else if (g_strcasecmp(cmd[0], "rt") == 0 && cmd[1]) { - struct twitter_user_data *tud; - bee_user_t *bu; - guint64 id; - - if (g_str_has_prefix(cmd[1], "#") && - sscanf(cmd[1] + 1, "%" G_GUINT64_FORMAT, &id) == 1) { - if (id < TWITTER_LOG_LENGTH && td->log) - id = td->log[id].id; - } else if ((bu = bee_user_by_handle(ic->bee, ic, cmd[1])) && - (tud = bu->data) && tud->last_id) - id = tud->last_id; - else if (sscanf(cmd[1], "%" G_GUINT64_FORMAT, &id) == 1){ - if (id < TWITTER_LOG_LENGTH && td->log) - id = td->log[id].id; - } + id = twitter_message_id_from_command_arg(ic, cmd[1], NULL); td->last_status_id = 0; if (id) twitter_status_retweet(ic, id); else - twitter_msg(ic, "User `%s' does not exist or didn't " + twitter_log(ic, "User `%s' does not exist or didn't " "post any statuses recently", cmd[1]); - g_free(cmds); - return; + goto eof; } else if (g_strcasecmp(cmd[0], "reply") == 0 && cmd[1] && cmd[2]) { - struct twitter_user_data *tud; - bee_user_t *bu = NULL; - guint64 id = 0; - - if (g_str_has_prefix(cmd[1], "#") && - sscanf(cmd[1] + 1, "%" G_GUINT64_FORMAT, &id) == 1 && - (id < TWITTER_LOG_LENGTH) && td->log) { - bu = td->log[id].bu; - if (g_slist_find(ic->bee->users, bu)) - id = td->log[id].id; - else - bu = NULL; - } else if ((bu = bee_user_by_handle(ic->bee, ic, cmd[1])) && - (tud = bu->data) && tud->last_id) { - id = tud->last_id; - } else if (sscanf(cmd[1], "%" G_GUINT64_FORMAT, &id) == 1 && - (id < TWITTER_LOG_LENGTH) && td->log) { - bu = td->log[id].bu; - if (g_slist_find(ic->bee->users, bu)) - id = td->log[id].id; - else - bu = NULL; - } - + id = twitter_message_id_from_command_arg(ic, cmd[1], &bu); if (!id || !bu) { - twitter_msg(ic, "User `%s' does not exist or didn't " + twitter_log(ic, "User `%s' does not exist or didn't " "post any statuses recently", cmd[1]); - return; + goto eof; } message = new = g_strdup_printf("@%s %s", bu->handle, message + (cmd[2] - cmd[0])); in_reply_to = id; + allow_post = TRUE; } else if (g_strcasecmp(cmd[0], "post") == 0) { message += 5; + allow_post = TRUE; } - { + if (allow_post) { char *s; - bee_user_t *bu; - if (!twitter_length_check(ic, message)) { - g_free(new); - g_free(cmds); - return; - } + if (!twitter_length_check(ic, message)) + goto eof; s = cmd[0] + strlen(cmd[0]) - 1; if (!new && s > cmd[0] && (*s == ':' || *s == ',')) { @@ -640,11 +688,33 @@ static void twitter_handle_command(struct im_connection *ic, char *message) this would delete the second-last Tweet. Prevent that. */ td->last_status_id = 0; twitter_post_status(ic, message, in_reply_to); - g_free(new); + } else { + twitter_log(ic, "Unknown command: %s", cmd[0]); } +eof: + g_free(new); g_free(cmds); } +void twitter_log(struct im_connection *ic, char *format, ... ) +{ + struct twitter_data *td = ic->proto_data; + va_list params; + char *text; + + va_start(params, format); + text = g_strdup_vprintf(format, params); + va_end(params); + + if (td->timeline_gc) + imcb_chat_log(td->timeline_gc, "%s", text); + else + imcb_log(ic, "%s", text); + + g_free(text); +} + + void twitter_initmodule() { struct prpl *ret = g_new0(struct prpl, 1); @@ -656,7 +726,6 @@ void twitter_initmodule() ret->logout = twitter_logout; ret->buddy_msg = twitter_buddy_msg; ret->get_info = twitter_get_info; - ret->set_my_name = twitter_set_my_name; ret->add_buddy = twitter_add_buddy; ret->remove_buddy = twitter_remove_buddy; ret->chat_msg = twitter_chat_msg; diff --git a/protocols/twitter/twitter.h b/protocols/twitter/twitter.h index 14e43824..8792b7c9 100644 --- a/protocols/twitter/twitter.h +++ b/protocols/twitter/twitter.h @@ -3,7 +3,8 @@ * BitlBee - An IRC to IM gateway * * Simple module to facilitate twitter functionality. * * * -* Copyright 2009 Geert Mulders <g.c.w.m.mulders@gmail.com> * +* Copyright 2009-2010 Geert Mulders <g.c.w.m.mulders@gmail.com> * +* Copyright 2010-2012 Wilmer van der Gaast <wilmer@gaast.net> * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public * @@ -34,10 +35,13 @@ typedef enum { - TWITTER_HAVE_FRIENDS = 1, + TWITTER_HAVE_FRIENDS = 0x00001, + TWITTER_MODE_ONE = 0x00002, + TWITTER_MODE_MANY = 0x00004, + TWITTER_MODE_CHAT = 0x00008, TWITTER_DOING_TIMELINE = 0x10000, - TWITTER_GOT_TIMELINE = 0x20000, - TWITTER_GOT_MENTIONS = 0x40000, + TWITTER_GOT_TIMELINE = 0x20000, + TWITTER_GOT_MENTIONS = 0x40000, } twitter_flags_t; struct twitter_log_data; @@ -56,6 +60,7 @@ struct twitter_data guint64 last_status_id; /* For undo */ gint main_loop_id; + struct http_request *stream; struct groupchat *timeline_gc; gint http_fails; twitter_flags_t flags; @@ -79,7 +84,7 @@ struct twitter_user_data time_t last_time; }; -#define TWITTER_LOG_LENGTH 100 +#define TWITTER_LOG_LENGTH 256 struct twitter_log_data { guint64 id; @@ -98,4 +103,7 @@ void twitter_login_finish( struct im_connection *ic ); struct http_request; char *twitter_parse_error( struct http_request *req ); +void twitter_log(struct im_connection *ic, char *format, ... ); +struct groupchat *twitter_groupchat_init(struct im_connection *ic); + #endif //_TWITTER_H diff --git a/protocols/twitter/twitter_http.c b/protocols/twitter/twitter_http.c index dbac5461..0f1ab518 100644 --- a/protocols/twitter/twitter_http.c +++ b/protocols/twitter/twitter_http.c @@ -46,14 +46,15 @@ static char *twitter_url_append(char *url, char *key, char *value); * Do a request. * This is actually pretty generic function... Perhaps it should move to the lib/http_client.c */ -void *twitter_http(struct im_connection *ic, char *url_string, http_input_function func, - gpointer data, int is_post, char **arguments, int arguments_len) +struct http_request *twitter_http(struct im_connection *ic, char *url_string, http_input_function func, + gpointer data, int is_post, char **arguments, int arguments_len) { struct twitter_data *td = ic->proto_data; char *tmp; GString *request = g_string_new(""); void *ret; char *url_arguments; + url_t *base_url = NULL; url_arguments = g_strdup(""); @@ -66,20 +67,34 @@ void *twitter_http(struct im_connection *ic, char *url_string, http_input_functi url_arguments = tmp; } } + + if (strstr(url_string, "://")) { + base_url = g_new0(url_t, 1); + if (!url_set(base_url, url_string)) { + g_free(base_url); + return NULL; + } + } + // Make the request. g_string_printf(request, "%s %s%s%s%s HTTP/1.0\r\n" "Host: %s\r\n" "User-Agent: BitlBee " BITLBEE_VERSION " " ARCH "/" CPU "\r\n", is_post ? "POST" : "GET", - td->url_path, url_string, - is_post ? "" : "?", is_post ? "" : url_arguments, td->url_host); + base_url ? base_url->file : td->url_path, + base_url ? "" : url_string, + is_post ? "" : "?", is_post ? "" : url_arguments, + base_url ? base_url->host : td->url_host); // If a pass and user are given we append them to the request. if (td->oauth_info) { char *full_header; char *full_url; - full_url = g_strconcat(set_getstr(&ic->acc->set, "base_url"), url_string, NULL); + if (base_url) + full_url = g_strdup(url_string); + else + full_url = g_strconcat(set_getstr(&ic->acc->set, "base_url"), url_string, NULL); full_header = oauth_http_header(td->oauth_info, is_post ? "POST" : "GET", full_url, url_arguments); @@ -108,10 +123,23 @@ void *twitter_http(struct im_connection *ic, char *url_string, http_input_functi g_string_append(request, "\r\n"); } - ret = http_dorequest(td->url_host, td->url_port, td->url_ssl, request->str, func, data); + if (base_url) + ret = http_dorequest(base_url->host, base_url->port, base_url->proto == PROTO_HTTPS, request->str, func, data); + else + ret = http_dorequest(td->url_host, td->url_port, td->url_ssl, request->str, func, data); g_free(url_arguments); g_string_free(request, TRUE); + g_free(base_url); + return ret; +} + +struct http_request *twitter_http_f(struct im_connection *ic, char *url_string, http_input_function func, + gpointer data, int is_post, char **arguments, int arguments_len, twitter_http_flags_t flags) +{ + struct http_request *ret = twitter_http(ic, url_string, func, data, is_post, arguments, arguments_len); + if (ret) + ret->flags |= flags; return ret; } diff --git a/protocols/twitter/twitter_http.h b/protocols/twitter/twitter_http.h index 393a1c26..09ef350c 100644 --- a/protocols/twitter/twitter_http.h +++ b/protocols/twitter/twitter_http.h @@ -27,10 +27,18 @@ #include "nogaim.h" #include "http_client.h" +typedef enum { + /* With this set, twitter_http_post() will post a generic confirmation + message to the user. */ + TWITTER_HTTP_USER_ACK = 0x1000000, +} twitter_http_flags_t; + struct oauth_info; -void *twitter_http(struct im_connection *ic, char *url_string, http_input_function func, - gpointer data, int is_post, char** arguments, int arguments_len); +struct http_request *twitter_http(struct im_connection *ic, char *url_string, http_input_function func, + gpointer data, int is_post, char** arguments, int arguments_len); +struct http_request *twitter_http_f(struct im_connection *ic, char *url_string, http_input_function func, + gpointer data, int is_post, char** arguments, int arguments_len, twitter_http_flags_t flags); #endif //_TWITTER_HTTP_H diff --git a/protocols/twitter/twitter_lib.c b/protocols/twitter/twitter_lib.c index 20a2708d..05222af2 100644 --- a/protocols/twitter/twitter_lib.c +++ b/protocols/twitter/twitter_lib.c @@ -4,7 +4,7 @@ * Simple module to facilitate twitter functionality. * * * * Copyright 2009-2010 Geert Mulders <g.c.w.m.mulders@gmail.com> * -* Copyright 2010-2011 Wilmer van der Gaast <wilmer@gaast.net> * +* Copyright 2010-2013 Wilmer van der Gaast <wilmer@gaast.net> * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public * @@ -34,8 +34,8 @@ #include "url.h" #include "misc.h" #include "base64.h" -#include "xmltree.h" #include "twitter_lib.h" +#include "json_util.h" #include <ctype.h> #include <errno.h> @@ -58,11 +58,10 @@ struct twitter_xml_status { time_t created_at; char *text; struct twitter_xml_user *user; - guint64 id, reply_to; + guint64 id, rt_id; /* Usually equal, with RTs id == *original* id */ + guint64 reply_to; }; -static void twitter_groupchat_init(struct im_connection *ic); - /** * Frees a twitter_xml_user struct. */ @@ -139,17 +138,16 @@ static void twitter_add_buddy(struct im_connection *ic, char *name, const char * // Check if the buddy is already in the buddy list. if (!bee_user_by_handle(ic->bee, ic, name)) { - char *mode = set_getstr(&ic->acc->set, "mode"); - // The buddy is not in the list, add the buddy and set the status to logged in. imcb_add_buddy(ic, name, NULL); imcb_rename_buddy(ic, name, fullname); - if (g_strcasecmp(mode, "chat") == 0) { + if (td->flags & TWITTER_MODE_CHAT) { /* Necessary so that nicks always get translated to the exact Twitter username. */ imcb_buddy_nick_hint(ic, name, name); - imcb_chat_add_buddy(td->timeline_gc, name); - } else if (g_strcasecmp(mode, "many") == 0) + if (td->timeline_gc) + imcb_chat_add_buddy(td->timeline_gc, name); + } else if (td->flags & TWITTER_MODE_MANY) imcb_buddy_status(ic, name, OPT_LOGGED_IN, NULL, NULL); } } @@ -159,28 +157,75 @@ static void twitter_add_buddy(struct im_connection *ic, char *name, const char * char *twitter_parse_error(struct http_request *req) { static char *ret = NULL; - struct xt_parser *xp = NULL; - struct xt_node *node, *err; + json_value *root, *err; g_free(ret); ret = NULL; if (req->body_size > 0) { - xp = xt_new(NULL, NULL); - xt_feed(xp, req->reply_body, req->body_size); - - for (node = xp->root; node; node = node->next) - if ((err = xt_find_node(node->children, "error")) && err->text_len > 0) { - ret = g_strdup_printf("%s (%s)", req->status_string, err->text); - break; - } - - xt_free(xp); + root = json_parse(req->reply_body); + err = json_o_get(root, "errors"); + if (err && err->type == json_array && (err = err->u.array.values[0]) && + err->type == json_object) { + const char *msg = json_o_str(err, "message"); + if (msg) + ret = g_strdup_printf("%s (%s)", req->status_string, msg); + } + json_value_free(root); } return ret ? ret : req->status_string; } +/* WATCH OUT: This function might or might not destroy your connection. + Sub-optimal indeed, but just be careful when this returns NULL! */ +static json_value *twitter_parse_response(struct im_connection *ic, struct http_request *req) +{ + gboolean logging_in = !(ic->flags & OPT_LOGGED_IN); + gboolean periodic; + struct twitter_data *td = ic->proto_data; + json_value *ret; + char path[64] = "", *s; + + if ((s = strchr(req->request, ' '))) { + path[sizeof(path)-1] = '\0'; + strncpy(path, s + 1, sizeof(path) - 1); + if ((s = strchr(path, '?')) || (s = strchr(path, ' '))) + *s = '\0'; + } + + /* Kinda nasty. :-( Trying to suppress error messages, but only + for periodic (i.e. mentions/timeline) queries. */ + periodic = strstr(path, "timeline") || strstr(path, "mentions"); + + if (req->status_code == 401 && logging_in) { + /* IIRC Twitter once had an outage where they were randomly + throwing 401s so I'll keep treating this one as fatal + only during login. */ + imcb_error(ic, "Authentication failure (%s)", + twitter_parse_error(req)); + imc_logout(ic, FALSE); + return NULL; + } else if (req->status_code != 200) { + // It didn't go well, output the error and return. + if (!periodic || logging_in || ++td->http_fails >= 5) + twitter_log(ic, "Error: Could not retrieve %s: %s", + path, twitter_parse_error(req)); + + if (logging_in) + imc_logout(ic, TRUE); + return NULL; + } else { + td->http_fails = 0; + } + + if ((ret = json_parse(req->reply_body)) == NULL) { + imcb_error(ic, "Could not retrieve %s: %s", + path, "XML parse error"); + } + return ret; +} + static void twitter_http_get_friends_ids(struct http_request *req); /** @@ -198,45 +243,35 @@ void twitter_get_friends_ids(struct im_connection *ic, gint64 next_cursor) } /** - * Function to help fill a list. - */ -static xt_status twitter_xt_next_cursor(struct xt_node *node, struct twitter_xml_list *txl) -{ - char *end = NULL; - - if (node->text) - txl->next_cursor = g_ascii_strtoll(node->text, &end, 10); - if (end == NULL) - txl->next_cursor = -1; - - return XT_HANDLED; -} - -/** * Fill a list of ids. */ -static xt_status twitter_xt_get_friends_id_list(struct xt_node *node, struct twitter_xml_list *txl) +static gboolean twitter_xt_get_friends_id_list(json_value *node, struct twitter_xml_list *txl) { - struct xt_node *child; + json_value *c; + int i; // Set the list type. txl->type = TXL_ID; - // The root <statuses> node should hold the list of statuses <status> - // Walk over the nodes children. - for (child = node->children; child; child = child->next) { - if (g_strcasecmp("ids", child->name) == 0) { - struct xt_node *idc; - for (idc = child->children; idc; idc = idc->next) - if (g_strcasecmp(idc->name, "id") == 0) - txl->list = g_slist_prepend(txl->list, - g_memdup(idc->text, idc->text_len + 1)); - } else if (g_strcasecmp("next_cursor", child->name) == 0) { - twitter_xt_next_cursor(child, txl); - } - } + c = json_o_get(node, "ids"); + if (!c || c->type != json_array) + return FALSE; - return XT_HANDLED; + for (i = 0; i < c->u.array.length; i ++) { + if (c->u.array.values[i]->type != json_integer) + continue; + + txl->list = g_slist_prepend(txl->list, + g_strdup_printf("%lld", c->u.array.values[i]->u.integer)); + } + + c = json_o_get(node, "next_cursor"); + if (c && c->type == json_integer) + txl->next_cursor = c->u.integer; + else + txl->next_cursor = -1; + + return TRUE; } static void twitter_get_users_lookup(struct im_connection *ic); @@ -247,7 +282,7 @@ static void twitter_get_users_lookup(struct im_connection *ic); static void twitter_http_get_friends_ids(struct http_request *req) { struct im_connection *ic; - struct xt_parser *parser; + json_value *parsed; struct twitter_xml_list *txl; struct twitter_data *td; @@ -259,34 +294,15 @@ static void twitter_http_get_friends_ids(struct http_request *req) td = ic->proto_data; - // Check if the HTTP request went well. More strict checks as this is - // the first request we do in a session. - if (req->status_code == 401) { - imcb_error(ic, "Authentication failure"); - imc_logout(ic, FALSE); - return; - } else if (req->status_code != 200) { - // It didn't go well, output the error and return. - imcb_error(ic, "Could not retrieve %s: %s", - TWITTER_FRIENDS_IDS_URL, twitter_parse_error(req)); - imc_logout(ic, TRUE); - return; - } else { - td->http_fails = 0; - } - - /* Create the room now that we "logged in". */ - if (!td->timeline_gc && g_strcasecmp(set_getstr(&ic->acc->set, "mode"), "chat") == 0) - twitter_groupchat_init(ic); - txl = g_new0(struct twitter_xml_list, 1); txl->list = td->follow_ids; // Parse the data. - parser = xt_new(NULL, txl); - xt_feed(parser, req->reply_body, req->body_size); - twitter_xt_get_friends_id_list(parser->root, txl); - xt_free(parser); + if (!(parsed = twitter_parse_response(ic, req))) + return; + + twitter_xt_get_friends_id_list(parsed, txl); + json_value_free(parsed); td->follow_ids = txl->list; if (txl->next_cursor) @@ -301,7 +317,7 @@ static void twitter_http_get_friends_ids(struct http_request *req) txl_free(txl); } -static xt_status twitter_xt_get_users(struct xt_node *node, struct twitter_xml_list *txl); +static gboolean twitter_xt_get_users(json_value *node, struct twitter_xml_list *txl); static void twitter_http_get_users_lookup(struct http_request *req); static void twitter_get_users_lookup(struct im_connection *ic) @@ -342,8 +358,7 @@ static void twitter_get_users_lookup(struct im_connection *ic) static void twitter_http_get_users_lookup(struct http_request *req) { struct im_connection *ic = req->data; - struct twitter_data *td; - struct xt_parser *parser; + json_value *parsed; struct twitter_xml_list *txl; GSList *l = NULL; struct twitter_xml_user *user; @@ -352,28 +367,14 @@ static void twitter_http_get_users_lookup(struct http_request *req) if (!g_slist_find(twitter_connections, ic)) return; - td = ic->proto_data; - - if (req->status_code != 200) { - // It didn't go well, output the error and return. - imcb_error(ic, "Could not retrieve %s: %s", - TWITTER_USERS_LOOKUP_URL, twitter_parse_error(req)); - imc_logout(ic, TRUE); - return; - } else { - td->http_fails = 0; - } - txl = g_new0(struct twitter_xml_list, 1); txl->list = NULL; - // Parse the data. - parser = xt_new(NULL, txl); - xt_feed(parser, req->reply_body, req->body_size); - // Get the user list from the parsed xml feed. - twitter_xt_get_users(parser->root, txl); - xt_free(parser); + if (!(parsed = twitter_parse_response(ic, req))) + return; + twitter_xt_get_users(parsed, txl); + json_value_free(parsed); // Add the users as buddies. for (l = txl->list; l; l = g_slist_next(l)) { @@ -387,25 +388,15 @@ static void twitter_http_get_users_lookup(struct http_request *req) twitter_get_users_lookup(ic); } -/** - * Function to fill a twitter_xml_user struct. - * It sets: - * - the name and - * - the screen_name. - */ -static xt_status twitter_xt_get_user(struct xt_node *node, struct twitter_xml_user *txu) +struct twitter_xml_user *twitter_xt_get_user(const json_value *node) { - struct xt_node *child; - - // Walk over the nodes children. - for (child = node->children; child; child = child->next) { - if (g_strcasecmp("name", child->name) == 0) { - txu->name = g_memdup(child->text, child->text_len + 1); - } else if (g_strcasecmp("screen_name", child->name) == 0) { - txu->screen_name = g_memdup(child->text, child->text_len + 1); - } - } - return XT_HANDLED; + struct twitter_xml_user *txu; + + txu = g_new0(struct twitter_xml_user, 1); + txu->name = g_strdup(json_o_str(node, "name")); + txu->screen_name = g_strdup(json_o_str(node, "screen_name")); + + return txu; } /** @@ -413,26 +404,26 @@ static xt_status twitter_xt_get_user(struct xt_node *node, struct twitter_xml_us * It sets: * - all <user>s from the <users> element. */ -static xt_status twitter_xt_get_users(struct xt_node *node, struct twitter_xml_list *txl) +static gboolean twitter_xt_get_users(json_value *node, struct twitter_xml_list *txl) { struct twitter_xml_user *txu; - struct xt_node *child; + int i; // Set the type of the list. txl->type = TXL_USER; + if (!node || node->type != json_array) + return FALSE; + // The root <users> node should hold the list of users <user> // Walk over the nodes children. - for (child = node->children; child; child = child->next) { - if (g_strcasecmp("user", child->name) == 0) { - txu = g_new0(struct twitter_xml_user, 1); - twitter_xt_get_user(child, txu); - // Put the item in the front of the list. + for (i = 0; i < node->u.array.length; i ++) { + txu = twitter_xt_get_user(node->u.array.values[i]); + if (txu) txl->list = g_slist_prepend(txl->list, txu); - } } - return XT_HANDLED; + return TRUE; } #ifdef __GLIBC__ @@ -441,6 +432,8 @@ static xt_status twitter_xt_get_users(struct xt_node *node, struct twitter_xml_l #define TWITTER_TIME_FORMAT "%a %b %d %H:%M:%S +0000 %Y" #endif +static char* expand_entities(char* text, const json_value *entities); + /** * Function to fill a twitter_xml_status struct. * It sets: @@ -449,77 +442,133 @@ static xt_status twitter_xt_get_users(struct xt_node *node, struct twitter_xml_l * - the status id and * - the user in a twitter_xml_user struct. */ -static xt_status twitter_xt_get_status(struct xt_node *node, struct twitter_xml_status *txs) +static struct twitter_xml_status *twitter_xt_get_status(const json_value *node) { - struct xt_node *child, *rt = NULL; - - // Walk over the nodes children. - for (child = node->children; child; child = child->next) { - if (g_strcasecmp("text", child->name) == 0) { - txs->text = g_memdup(child->text, child->text_len + 1); - } else if (g_strcasecmp("retweeted_status", child->name) == 0) { - rt = child; - } else if (g_strcasecmp("created_at", child->name) == 0) { + struct twitter_xml_status *txs; + const json_value *rt = NULL, *entities = NULL; + + if (node->type != json_object) + return FALSE; + txs = g_new0(struct twitter_xml_status, 1); + + JSON_O_FOREACH (node, k, v) { + if (strcmp("text", k) == 0 && v->type == json_string) { + txs->text = g_memdup(v->u.string.ptr, v->u.string.length + 1); + strip_html(txs->text); + } else if (strcmp("retweeted_status", k) == 0 && v->type == json_object) { + rt = v; + } else if (strcmp("created_at", k) == 0 && v->type == json_string) { struct tm parsed; /* Very sensitive to changes to the formatting of this field. :-( Also assumes the timezone used is UTC since C time handling functions suck. */ - if (strptime(child->text, TWITTER_TIME_FORMAT, &parsed) != NULL) + if (strptime(v->u.string.ptr, TWITTER_TIME_FORMAT, &parsed) != NULL) txs->created_at = mktime_utc(&parsed); - } else if (g_strcasecmp("user", child->name) == 0) { - txs->user = g_new0(struct twitter_xml_user, 1); - twitter_xt_get_user(child, txs->user); - } else if (g_strcasecmp("id", child->name) == 0) { - txs->id = g_ascii_strtoull(child->text, NULL, 10); - } else if (g_strcasecmp("in_reply_to_status_id", child->name) == 0) { - txs->reply_to = g_ascii_strtoull(child->text, NULL, 10); + } else if (strcmp("user", k) == 0 && v->type == json_object) { + txs->user = twitter_xt_get_user(v); + } else if (strcmp("id", k) == 0 && v->type == json_integer) { + txs->rt_id = txs->id = v->u.integer; + } else if (strcmp("in_reply_to_status_id", k) == 0 && v->type == json_integer) { + txs->reply_to = v->u.integer; + } else if (strcmp("entities", k) == 0 && v->type == json_object) { + entities = v; } } /* If it's a (truncated) retweet, get the original. Even if the API claims it wasn't truncated because it may be lying. */ if (rt) { - struct twitter_xml_status *rtxs = g_new0(struct twitter_xml_status, 1); - if (twitter_xt_get_status(rt, rtxs) != XT_HANDLED) { + struct twitter_xml_status *rtxs = twitter_xt_get_status(rt); + if (rtxs) { + g_free(txs->text); + txs->text = g_strdup_printf("RT @%s: %s", rtxs->user->screen_name, rtxs->text); + txs->id = rtxs->id; txs_free(rtxs); - return XT_HANDLED; } + } else if (entities) { + txs->text = expand_entities(txs->text, entities); + } - g_free(txs->text); - txs->text = g_strdup_printf("RT @%s: %s", rtxs->user->screen_name, rtxs->text); - txs_free(rtxs); - } else { - struct xt_node *urls, *url; + if (txs->text && txs->user && txs->id) + return txs; + + txs_free(txs); + return NULL; +} + +/** + * Function to fill a twitter_xml_status struct (DM variant). + */ +static struct twitter_xml_status *twitter_xt_get_dm(const json_value *node) +{ + struct twitter_xml_status *txs; + const json_value *entities = NULL; + + if (node->type != json_object) + return FALSE; + txs = g_new0(struct twitter_xml_status, 1); + + JSON_O_FOREACH (node, k, v) { + if (strcmp("text", k) == 0 && v->type == json_string) { + txs->text = g_memdup(v->u.string.ptr, v->u.string.length + 1); + strip_html(txs->text); + } else if (strcmp("created_at", k) == 0 && v->type == json_string) { + struct tm parsed; + + /* Very sensitive to changes to the formatting of + this field. :-( Also assumes the timezone used + is UTC since C time handling functions suck. */ + if (strptime(v->u.string.ptr, TWITTER_TIME_FORMAT, &parsed) != NULL) + txs->created_at = mktime_utc(&parsed); + } else if (strcmp("sender", k) == 0 && v->type == json_object) { + txs->user = twitter_xt_get_user(v); + } else if (strcmp("id", k) == 0 && v->type == json_integer) { + txs->id = v->u.integer; + } + } + + if (entities) { + txs->text = expand_entities(txs->text, entities); + } + + if (txs->text && txs->user && txs->id) + return txs; + + txs_free(txs); + return NULL; +} + +static char* expand_entities(char* text, const json_value *entities) { + JSON_O_FOREACH (entities, k, v) { + int i; + + if (v->type != json_array) + continue; + if (strcmp(k, "urls") != 0 && strcmp(k, "media") != 0) + continue; - urls = xt_find_path(node, "entities"); - if (urls != NULL) - urls = urls->children; - for (; urls; urls = urls->next) { - if (strcmp(urls->name, "urls") != 0 && strcmp(urls->name, "media") != 0) + for (i = 0; i < v->u.array.length; i ++) { + if (v->u.array.values[i]->type != json_object) continue; - for (url = urls ? urls->children : NULL; url; url = url->next) { - /* "short" is a reserved word. :-P */ - struct xt_node *kort = xt_find_node(url->children, "url"); - struct xt_node *disp = xt_find_node(url->children, "display_url"); - char *pos, *new; - - if (!kort || !kort->text || !disp || !disp->text || - !(pos = strstr(txs->text, kort->text))) - continue; - - *pos = '\0'; - new = g_strdup_printf("%s%s <%s>%s", txs->text, kort->text, - disp->text, pos + strlen(kort->text)); - - g_free(txs->text); - txs->text = new; - } + const char *kort = json_o_str(v->u.array.values[i], "url"); + const char *disp = json_o_str(v->u.array.values[i], "display_url"); + char *pos, *new; + + if (!kort || !disp || !(pos = strstr(text, kort))) + continue; + + *pos = '\0'; + new = g_strdup_printf("%s%s <%s>%s", text, kort, + disp, pos + strlen(kort)); + + g_free(text); + text = new; } } - - return XT_HANDLED; + + return text; } /** @@ -528,198 +577,324 @@ static xt_status twitter_xt_get_status(struct xt_node *node, struct twitter_xml_ * - all <status>es within the <status> element and * - the next_cursor. */ -static xt_status twitter_xt_get_status_list(struct im_connection *ic, struct xt_node *node, - struct twitter_xml_list *txl) +static gboolean twitter_xt_get_status_list(struct im_connection *ic, const json_value *node, + struct twitter_xml_list *txl) { struct twitter_xml_status *txs; - struct xt_node *child; - bee_user_t *bu; + int i; // Set the type of the list. txl->type = TXL_STATUS; + + if (node->type != json_array) + return FALSE; // The root <statuses> node should hold the list of statuses <status> // Walk over the nodes children. - for (child = node->children; child; child = child->next) { - if (g_strcasecmp("status", child->name) == 0) { - txs = g_new0(struct twitter_xml_status, 1); - twitter_xt_get_status(child, txs); - // Put the item in the front of the list. - txl->list = g_slist_prepend(txl->list, txs); - - if (txs->user && txs->user->screen_name && - (bu = bee_user_by_handle(ic->bee, ic, txs->user->screen_name))) { - struct twitter_user_data *tud = bu->data; - - if (txs->id > tud->last_id) { - tud->last_id = txs->id; - tud->last_time = txs->created_at; - } - } - } else if (g_strcasecmp("next_cursor", child->name) == 0) { - twitter_xt_next_cursor(child, txl); - } + for (i = 0; i < node->u.array.length; i ++) { + txs = twitter_xt_get_status(node->u.array.values[i]); + if (!txs) + continue; + + txl->list = g_slist_prepend(txl->list, txs); } - return XT_HANDLED; + return TRUE; } +/* Will log messages either way. Need to keep track of IDs for stream deduping. + Plus, show_ids is on by default and I don't see why anyone would disable it. */ static char *twitter_msg_add_id(struct im_connection *ic, struct twitter_xml_status *txs, const char *prefix) { struct twitter_data *td = ic->proto_data; - char *ret = NULL; - - if (!set_getbool(&ic->acc->set, "show_ids")) { - if (*prefix) - return g_strconcat(prefix, txs->text, NULL); - else - return NULL; - } + int reply_to = -1; + bee_user_t *bu; - td->log[td->log_id].id = txs->id; - td->log[td->log_id].bu = bee_user_by_handle(ic->bee, ic, txs->user->screen_name); if (txs->reply_to) { int i; for (i = 0; i < TWITTER_LOG_LENGTH; i++) if (td->log[i].id == txs->reply_to) { - ret = g_strdup_printf("\002[\002%02d->%02d\002]\002 %s%s", - td->log_id, i, prefix, txs->text); + reply_to = i; break; } } - if (ret == NULL) - ret = g_strdup_printf("\002[\002%02d\002]\002 %s%s", td->log_id, prefix, txs->text); - td->log_id = (td->log_id + 1) % TWITTER_LOG_LENGTH; - return ret; -} + if (txs->user && txs->user->screen_name && + (bu = bee_user_by_handle(ic->bee, ic, txs->user->screen_name))) { + struct twitter_user_data *tud = bu->data; -static void twitter_groupchat_init(struct im_connection *ic) -{ - char *name_hint; - struct groupchat *gc; - struct twitter_data *td = ic->proto_data; - GSList *l; - - td->timeline_gc = gc = imcb_chat_new(ic, "twitter/timeline"); - - name_hint = g_strdup_printf("%s_%s", td->prefix, ic->acc->user); - imcb_chat_name_hint(gc, name_hint); - g_free(name_hint); - - for (l = ic->bee->users; l; l = l->next) { - bee_user_t *bu = l->data; - if (bu->ic == ic) - imcb_chat_add_buddy(td->timeline_gc, bu->handle); + if (txs->id > tud->last_id) { + tud->last_id = txs->id; + tud->last_time = txs->created_at; + } + } + + td->log_id = (td->log_id + 1) % TWITTER_LOG_LENGTH; + td->log[td->log_id].id = txs->id; + td->log[td->log_id].bu = bee_user_by_handle(ic->bee, ic, txs->user->screen_name); + + /* This is all getting hairy. :-( If we RT'ed something ourselves, + remember OUR id instead so undo will work. In other cases, the + original tweet's id should be remembered for deduplicating. */ + if (strcmp(txs->user->screen_name, td->user) == 0) + td->log[td->log_id].id = txs->rt_id; + + if (set_getbool(&ic->acc->set, "show_ids")) { + if (reply_to != -1) + return g_strdup_printf("\002[\002%02x->%02x\002]\002 %s%s", + td->log_id, reply_to, prefix, txs->text); + else + return g_strdup_printf("\002[\002%02x\002]\002 %s%s", + td->log_id, prefix, txs->text); + } else { + if (*prefix) + return g_strconcat(prefix, txs->text, NULL); + else + return NULL; } } /** * Function that is called to see the statuses in a groupchat window. */ -static void twitter_groupchat(struct im_connection *ic, GSList * list) +static void twitter_status_show_chat(struct im_connection *ic, struct twitter_xml_status *status) { struct twitter_data *td = ic->proto_data; - GSList *l = NULL; - struct twitter_xml_status *status; struct groupchat *gc; - guint64 last_id = 0; + gboolean me = g_strcasecmp(td->user, status->user->screen_name) == 0; + char *msg; // Create a new groupchat if it does not exsist. - if (!td->timeline_gc) - twitter_groupchat_init(ic); - - gc = td->timeline_gc; - if (!gc->joined) - imcb_chat_add_buddy(gc, ic->acc->user); - - for (l = list; l; l = g_slist_next(l)) { - char *msg; - - status = l->data; - if (status->user == NULL || status->text == NULL || last_id == status->id) - continue; - - last_id = status->id; - - strip_html(status->text); - - if (set_getbool(&ic->acc->set, "strip_newlines")) - strip_newlines(status->text); - - msg = twitter_msg_add_id(ic, status, ""); - - // Say it! - if (g_strcasecmp(td->user, status->user->screen_name) == 0) { - imcb_chat_log(gc, "You: %s", msg ? msg : status->text); - } else { - twitter_add_buddy(ic, status->user->screen_name, status->user->name); - - imcb_chat_msg(gc, status->user->screen_name, - msg ? msg : status->text, 0, status->created_at); - } - - g_free(msg); + gc = twitter_groupchat_init(ic); - // Update the timeline_id to hold the highest id, so that by the next request - // we won't pick up the updates already in the list. - td->timeline_id = MAX(td->timeline_id, status->id); + if (!me) + /* MUST be done before twitter_msg_add_id() to avoid #872. */ + twitter_add_buddy(ic, status->user->screen_name, status->user->name); + msg = twitter_msg_add_id(ic, status, ""); + + // Say it! + if (me) { + imcb_chat_log(gc, "You: %s", msg ? msg : status->text); + } else { + imcb_chat_msg(gc, status->user->screen_name, + msg ? msg : status->text, 0, status->created_at); } + + g_free(msg); } /** * Function that is called to see statuses as private messages. */ -static void twitter_private_message_chat(struct im_connection *ic, GSList * list) +static void twitter_status_show_msg(struct im_connection *ic, struct twitter_xml_status *status) { struct twitter_data *td = ic->proto_data; - GSList *l = NULL; - struct twitter_xml_status *status; - char from[MAX_STRING]; - gboolean mode_one; - guint64 last_id = 0; - - mode_one = g_strcasecmp(set_getstr(&ic->acc->set, "mode"), "one") == 0; + char from[MAX_STRING] = ""; + char *prefix = NULL, *text = NULL; + gboolean me = g_strcasecmp(td->user, status->user->screen_name) == 0; - if (mode_one) { + if (td->flags & TWITTER_MODE_ONE) { g_snprintf(from, sizeof(from) - 1, "%s_%s", td->prefix, ic->acc->user); from[MAX_STRING - 1] = '\0'; } - for (l = list; l; l = g_slist_next(l)) { - char *prefix = NULL, *text = NULL; + if (td->flags & TWITTER_MODE_ONE) + prefix = g_strdup_printf("\002<\002%s\002>\002 ", + status->user->screen_name); + else if (!me) + twitter_add_buddy(ic, status->user->screen_name, status->user->name); + else + prefix = g_strdup("You: "); - status = l->data; - if (status->user == NULL || status->text == NULL || last_id == status->id) - continue; + text = twitter_msg_add_id(ic, status, prefix ? prefix : ""); - last_id = status->id; + imcb_buddy_msg(ic, + *from ? from : status->user->screen_name, + text ? text : status->text, 0, status->created_at); - strip_html(status->text); - if (mode_one) - prefix = g_strdup_printf("\002<\002%s\002>\002 ", - status->user->screen_name); - else - twitter_add_buddy(ic, status->user->screen_name, status->user->name); + g_free(text); + g_free(prefix); +} - text = twitter_msg_add_id(ic, status, prefix ? prefix : ""); +static void twitter_status_show(struct im_connection *ic, struct twitter_xml_status *status) +{ + struct twitter_data *td = ic->proto_data; + + if (status->user == NULL || status->text == NULL) + return; + + /* Grrrr. Would like to do this during parsing, but can't access + settings from there. */ + if (set_getbool(&ic->acc->set, "strip_newlines")) + strip_newlines(status->text); + + if (td->flags & TWITTER_MODE_CHAT) + twitter_status_show_chat(ic, status); + else + twitter_status_show_msg(ic, status); - imcb_buddy_msg(ic, - mode_one ? from : status->user->screen_name, - text ? text : status->text, 0, status->created_at); + // Update the timeline_id to hold the highest id, so that by the next request + // we won't pick up the updates already in the list. + td->timeline_id = MAX(td->timeline_id, status->rt_id); +} - // Update the timeline_id to hold the highest id, so that by the next request - // we won't pick up the updates already in the list. - td->timeline_id = MAX(td->timeline_id, status->id); +static gboolean twitter_stream_handle_object(struct im_connection *ic, json_value *o); - g_free(text); - g_free(prefix); +static void twitter_http_stream(struct http_request *req) +{ + struct im_connection *ic = req->data; + struct twitter_data *td; + json_value *parsed; + int len = 0; + char c, *nl; + + if (!g_slist_find(twitter_connections, ic)) + return; + + ic->flags |= OPT_PONGED; + td = ic->proto_data; + + if ((req->flags & HTTPC_EOF) || !req->reply_body) { + td->stream = NULL; + imcb_error(ic, "Stream closed (%s)", req->status_string); + imc_logout(ic, TRUE); + return; + } + + /* MUST search for CRLF, not just LF: + https://dev.twitter.com/docs/streaming-apis/processing#Parsing_responses */ + if (!(nl = strstr(req->reply_body, "\r\n"))) + return; + + len = nl - req->reply_body; + if (len > 0) { + c = req->reply_body[len]; + req->reply_body[len] = '\0'; + + if ((parsed = json_parse(req->reply_body))) { + twitter_stream_handle_object(ic, parsed); + } + json_value_free(parsed); + req->reply_body[len] = c; } + + http_flush_bytes(req, len + 2); + + /* One notification might bring multiple events! */ + if (req->body_size > 0) + twitter_http_stream(req); } -static void twitter_http_get_home_timeline(struct http_request *req); -static void twitter_http_get_mentions(struct http_request *req); +static gboolean twitter_stream_handle_event(struct im_connection *ic, json_value *o); +static gboolean twitter_stream_handle_status(struct im_connection *ic, struct twitter_xml_status *txs); + +static gboolean twitter_stream_handle_object(struct im_connection *ic, json_value *o) +{ + struct twitter_data *td = ic->proto_data; + struct twitter_xml_status *txs; + json_value *c; + + if ((txs = twitter_xt_get_status(o))) { + gboolean ret = twitter_stream_handle_status(ic, txs); + txs_free(txs); + return ret; + } else if ((c = json_o_get(o, "direct_message")) && + (txs = twitter_xt_get_dm(c))) { + if (strcmp(txs->user->screen_name, td->user) != 0) + imcb_buddy_msg(ic, txs->user->screen_name, + txs->text, 0, txs->created_at); + txs_free(txs); + return TRUE; + } else if ((c = json_o_get(o, "event")) && c->type == json_string) { + twitter_stream_handle_event(ic, o); + return TRUE; + } else if ((c = json_o_get(o, "disconnect")) && c->type == json_object) { + /* HACK: Because we're inside an event handler, we can't just + disconnect here. Instead, just change the HTTP status string + into a Twitter status string. */ + char *reason = json_o_strdup(c, "reason"); + if (reason) { + g_free(td->stream->status_string); + td->stream->status_string = reason; + } + return TRUE; + } + return FALSE; +} + +static gboolean twitter_stream_handle_status(struct im_connection *ic, struct twitter_xml_status *txs) +{ + struct twitter_data *td = ic->proto_data; + int i; + + for (i = 0; i < TWITTER_LOG_LENGTH; i++) { + if (td->log[i].id == txs->id) { + /* Got a duplicate (RT, probably). Drop it. */ + return TRUE; + } + } + + if (!(strcmp(txs->user->screen_name, td->user) == 0 || + set_getbool(&ic->acc->set, "fetch_mentions") || + bee_user_by_handle(ic->bee, ic, txs->user->screen_name))) { + /* Tweet is from an unknown person and the user does not want + to see @mentions, so drop it. twitter_stream_handle_event() + picks up new follows so this simple filter should be safe. */ + /* TODO: The streaming API seems to do poor @mention matching. + I.e. I'm getting mentions for @WilmerSomething, not just for + @Wilmer. But meh. You want spam, you get spam. */ + return TRUE; + } + + twitter_status_show(ic, txs); + + return TRUE; +} + +static gboolean twitter_stream_handle_event(struct im_connection *ic, json_value *o) +{ + struct twitter_data *td = ic->proto_data; + json_value *source = json_o_get(o, "source"); + json_value *target = json_o_get(o, "target"); + const char *type = json_o_str(o, "event"); + + if (!type || !source || source->type != json_object + || !target || target->type != json_object) { + return FALSE; + } + + if (strcmp(type, "follow") == 0) { + struct twitter_xml_user *us = twitter_xt_get_user(source); + struct twitter_xml_user *ut = twitter_xt_get_user(target); + if (strcmp(us->screen_name, td->user) == 0) { + twitter_add_buddy(ic, ut->screen_name, ut->name); + } + txu_free(us); + txu_free(ut); + } + + return TRUE; +} + +gboolean twitter_open_stream(struct im_connection *ic) +{ + struct twitter_data *td = ic->proto_data; + char *args[2] = {"with", "followings"}; + + if ((td->stream = twitter_http(ic, TWITTER_USER_STREAM_URL, + twitter_http_stream, ic, 0, args, 2))) { + /* This flag must be enabled or we'll get no data until EOF + (which err, kind of, defeats the purpose of a streaming API). */ + td->stream->flags |= HTTPC_STREAMING; + return TRUE; + } + + return FALSE; +} + +static void twitter_get_home_timeline(struct im_connection *ic, gint64 next_cursor); +static void twitter_get_mentions(struct im_connection *ic, gint64 next_cursor); /** * Get the timeline with optionally mentions @@ -730,7 +905,10 @@ void twitter_get_timeline(struct im_connection *ic, gint64 next_cursor) gboolean include_mentions = set_getbool(&ic->acc->set, "fetch_mentions"); if (td->flags & TWITTER_DOING_TIMELINE) { - return; + if (++td->http_fails >= 5) { + imcb_error(ic, "Fetch timeout (%d)", td->flags); + imc_logout(ic, TRUE); + } } td->flags |= TWITTER_DOING_TIMELINE; @@ -753,9 +931,12 @@ void twitter_flush_timeline(struct im_connection *ic) int show_old_mentions = set_getint(&ic->acc->set, "show_old_mentions"); struct twitter_xml_list *home_timeline = td->home_timeline_obj; struct twitter_xml_list *mentions = td->mentions_obj; + guint64 last_id = 0; GSList *output = NULL; GSList *l; + imcb_connected(ic); + if (!(td->flags & TWITTER_GOT_TIMELINE)) { return; } @@ -781,12 +962,13 @@ void twitter_flush_timeline(struct im_connection *ic) } // See if the user wants to see the messages in a groupchat window or as private messages. - if (g_strcasecmp(set_getstr(&ic->acc->set, "mode"), "chat") == 0) - twitter_groupchat(ic, output); - else - twitter_private_message_chat(ic, output); - - g_slist_free(output); + while (output) { + struct twitter_xml_status *txs = output->data; + if (txs->id != last_id) + twitter_status_show(ic, txs); + last_id = txs->id; + output = g_slist_remove(output, txs); + } txl_free(home_timeline); txl_free(mentions); @@ -795,10 +977,13 @@ void twitter_flush_timeline(struct im_connection *ic) td->home_timeline_obj = td->mentions_obj = NULL; } +static void twitter_http_get_home_timeline(struct http_request *req); +static void twitter_http_get_mentions(struct http_request *req); + /** * Get the timeline. */ -void twitter_get_home_timeline(struct im_connection *ic, gint64 next_cursor) +static void twitter_get_home_timeline(struct im_connection *ic, gint64 next_cursor) { struct twitter_data *td = ic->proto_data; @@ -834,7 +1019,7 @@ void twitter_get_home_timeline(struct im_connection *ic, gint64 next_cursor) /** * Get mentions. */ -void twitter_get_mentions(struct im_connection *ic, gint64 next_cursor) +static void twitter_get_mentions(struct im_connection *ic, gint64 next_cursor) { struct twitter_data *td = ic->proto_data; @@ -865,9 +1050,7 @@ void twitter_get_mentions(struct im_connection *ic, gint64 next_cursor) } g_free(args[1]); - if (td->timeline_id) { - g_free(args[5]); - } + g_free(args[5]); } /** @@ -877,7 +1060,7 @@ static void twitter_http_get_home_timeline(struct http_request *req) { struct im_connection *ic = req->data; struct twitter_data *td; - struct xt_parser *parser; + json_value *parsed; struct twitter_xml_list *txl; // Check if the connection is still active. @@ -886,33 +1069,21 @@ static void twitter_http_get_home_timeline(struct http_request *req) td = ic->proto_data; - // Check if the HTTP request went well. - if (req->status_code == 200) { - td->http_fails = 0; - if (!(ic->flags & OPT_LOGGED_IN)) - imcb_connected(ic); - } else { - // It didn't go well, output the error and return. - if (++td->http_fails >= 5) - imcb_error(ic, "Could not retrieve %s: %s", - TWITTER_HOME_TIMELINE_URL, twitter_parse_error(req)); - - goto end; - } - txl = g_new0(struct twitter_xml_list, 1); txl->list = NULL; - // Parse the data. - parser = xt_new(NULL, txl); - xt_feed(parser, req->reply_body, req->body_size); // The root <statuses> node should hold the list of statuses <status> - twitter_xt_get_status_list(ic, parser->root, txl); - xt_free(parser); + if (!(parsed = twitter_parse_response(ic, req))) + goto end; + twitter_xt_get_status_list(ic, parsed, txl); + json_value_free(parsed); td->home_timeline_obj = txl; end: + if (!g_slist_find(twitter_connections, ic)) + return; + td->flags |= TWITTER_GOT_TIMELINE; twitter_flush_timeline(ic); @@ -925,7 +1096,7 @@ static void twitter_http_get_mentions(struct http_request *req) { struct im_connection *ic = req->data; struct twitter_data *td; - struct xt_parser *parser; + json_value *parsed; struct twitter_xml_list *txl; // Check if the connection is still active. @@ -934,33 +1105,21 @@ static void twitter_http_get_mentions(struct http_request *req) td = ic->proto_data; - // Check if the HTTP request went well. - if (req->status_code == 200) { - td->http_fails = 0; - if (!(ic->flags & OPT_LOGGED_IN)) - imcb_connected(ic); - } else { - // It didn't go well, output the error and return. - if (++td->http_fails >= 5) - imcb_error(ic, "Could not retrieve %s: %s", - TWITTER_MENTIONS_URL, twitter_parse_error(req)); - - goto end; - } - txl = g_new0(struct twitter_xml_list, 1); txl->list = NULL; - // Parse the data. - parser = xt_new(NULL, txl); - xt_feed(parser, req->reply_body, req->body_size); // The root <statuses> node should hold the list of statuses <status> - twitter_xt_get_status_list(ic, parser->root, txl); - xt_free(parser); + if (!(parsed = twitter_parse_response(ic, req))) + goto end; + twitter_xt_get_status_list(ic, parsed, txl); + json_value_free(parsed); td->mentions_obj = txl; end: + if (!g_slist_find(twitter_connections, ic)) + return; + td->flags |= TWITTER_GOT_MENTIONS; twitter_flush_timeline(ic); @@ -974,6 +1133,7 @@ static void twitter_http_post(struct http_request *req) { struct im_connection *ic = req->data; struct twitter_data *td; + json_value *parsed, *id; // Check if the connection is still active. if (!g_slist_find(twitter_connections, ic)) @@ -982,26 +1142,17 @@ static void twitter_http_post(struct http_request *req) td = ic->proto_data; td->last_status_id = 0; - // Check if the HTTP request went well. - if (req->status_code != 200) { - // It didn't go well, output the error and return. - imcb_error(ic, "HTTP error: %s", twitter_parse_error(req)); + if (!(parsed = twitter_parse_response(ic, req))) return; + + if ((id = json_o_get(parsed, "id")) && id->type == json_integer) { + td->last_status_id = id->u.integer; } - - if (req->body_size > 0) { - struct xt_parser *xp = NULL; - struct xt_node *node; - - xp = xt_new(NULL, NULL); - xt_feed(xp, req->reply_body, req->body_size); - - if ((node = xt_find_node(xp->root, "status")) && - (node = xt_find_node(node->children, "id")) && node->text) - td->last_status_id = g_ascii_strtoull(node->text, NULL, 10); - - xt_free(xp); - } + + json_value_free(parsed); + + if (req->flags & TWITTER_HTTP_USER_ACK) + twitter_log(ic, "Command processed successfully"); } /** @@ -1047,8 +1198,9 @@ void twitter_status_destroy(struct im_connection *ic, guint64 id) { char *url; url = g_strdup_printf("%s%llu%s", TWITTER_STATUS_DESTROY_URL, - (unsigned long long) id, ".xml"); - twitter_http(ic, url, twitter_http_post, ic, 1, NULL, 0); + (unsigned long long) id, ".json"); + twitter_http_f(ic, url, twitter_http_post, ic, 1, NULL, 0, + TWITTER_HTTP_USER_ACK); g_free(url); } @@ -1056,8 +1208,9 @@ void twitter_status_retweet(struct im_connection *ic, guint64 id) { char *url; url = g_strdup_printf("%s%llu%s", TWITTER_STATUS_RETWEET_URL, - (unsigned long long) id, ".xml"); - twitter_http(ic, url, twitter_http_post, ic, 1, NULL, 0); + (unsigned long long) id, ".json"); + twitter_http_f(ic, url, twitter_http_post, ic, 1, NULL, 0, + TWITTER_HTTP_USER_ACK); g_free(url); } @@ -1071,6 +1224,21 @@ void twitter_report_spam(struct im_connection *ic, char *screen_name) NULL, }; args[1] = screen_name; - twitter_http(ic, TWITTER_REPORT_SPAM_URL, twitter_http_post, - ic, 1, args, 2); + twitter_http_f(ic, TWITTER_REPORT_SPAM_URL, twitter_http_post, + ic, 1, args, 2, TWITTER_HTTP_USER_ACK); +} + +/** + * Favourite a tweet. + */ +void twitter_favourite_tweet(struct im_connection *ic, guint64 id) +{ + char *args[2] = { + "id", + NULL, + }; + args[1] = g_strdup_printf("%llu", (unsigned long long) id); + twitter_http_f(ic, TWITTER_FAVORITE_CREATE_URL, twitter_http_post, + ic, 1, args, 2, TWITTER_HTTP_USER_ACK); + g_free(args[1]); } diff --git a/protocols/twitter/twitter_lib.h b/protocols/twitter/twitter_lib.h index 09b91e5b..f59c81ef 100644 --- a/protocols/twitter/twitter_lib.h +++ b/protocols/twitter/twitter_lib.h @@ -28,60 +28,61 @@ #include "nogaim.h" #include "twitter_http.h" -#define TWITTER_API_URL "http://api.twitter.com/1" +#define TWITTER_API_URL "http://api.twitter.com/1.1" #define IDENTICA_API_URL "https://identi.ca/api" /* Status URLs */ -#define TWITTER_STATUS_UPDATE_URL "/statuses/update.xml" +#define TWITTER_STATUS_UPDATE_URL "/statuses/update.json" #define TWITTER_STATUS_SHOW_URL "/statuses/show/" #define TWITTER_STATUS_DESTROY_URL "/statuses/destroy/" #define TWITTER_STATUS_RETWEET_URL "/statuses/retweet/" /* Timeline URLs */ -#define TWITTER_PUBLIC_TIMELINE_URL "/statuses/public_timeline.xml" -#define TWITTER_FEATURED_USERS_URL "/statuses/featured.xml" -#define TWITTER_FRIENDS_TIMELINE_URL "/statuses/friends_timeline.xml" -#define TWITTER_HOME_TIMELINE_URL "/statuses/home_timeline.xml" -#define TWITTER_MENTIONS_URL "/statuses/mentions.xml" -#define TWITTER_USER_TIMELINE_URL "/statuses/user_timeline.xml" +#define TWITTER_PUBLIC_TIMELINE_URL "/statuses/public_timeline.json" +#define TWITTER_FEATURED_USERS_URL "/statuses/featured.json" +#define TWITTER_FRIENDS_TIMELINE_URL "/statuses/friends_timeline.json" +#define TWITTER_HOME_TIMELINE_URL "/statuses/home_timeline.json" +#define TWITTER_MENTIONS_URL "/statuses/mentions_timeline.json" +#define TWITTER_USER_TIMELINE_URL "/statuses/user_timeline.json" /* Users URLs */ -#define TWITTER_USERS_LOOKUP_URL "/users/lookup.xml" +#define TWITTER_USERS_LOOKUP_URL "/users/lookup.json" /* Direct messages URLs */ -#define TWITTER_DIRECT_MESSAGES_URL "/direct_messages.xml" -#define TWITTER_DIRECT_MESSAGES_NEW_URL "/direct_messages/new.xml" -#define TWITTER_DIRECT_MESSAGES_SENT_URL "/direct_messages/sent.xml" +#define TWITTER_DIRECT_MESSAGES_URL "/direct_messages.json" +#define TWITTER_DIRECT_MESSAGES_NEW_URL "/direct_messages/new.json" +#define TWITTER_DIRECT_MESSAGES_SENT_URL "/direct_messages/sent.json" #define TWITTER_DIRECT_MESSAGES_DESTROY_URL "/direct_messages/destroy/" /* Friendships URLs */ -#define TWITTER_FRIENDSHIPS_CREATE_URL "/friendships/create.xml" -#define TWITTER_FRIENDSHIPS_DESTROY_URL "/friendships/destroy.xml" -#define TWITTER_FRIENDSHIPS_SHOW_URL "/friendships/show.xml" +#define TWITTER_FRIENDSHIPS_CREATE_URL "/friendships/create.json" +#define TWITTER_FRIENDSHIPS_DESTROY_URL "/friendships/destroy.json" +#define TWITTER_FRIENDSHIPS_SHOW_URL "/friendships/show.json" /* Social graphs URLs */ -#define TWITTER_FRIENDS_IDS_URL "/friends/ids.xml" -#define TWITTER_FOLLOWERS_IDS_URL "/followers/ids.xml" +#define TWITTER_FRIENDS_IDS_URL "/friends/ids.json" +#define TWITTER_FOLLOWERS_IDS_URL "/followers/ids.json" /* Account URLs */ -#define TWITTER_ACCOUNT_RATE_LIMIT_URL "/account/rate_limit_status.xml" +#define TWITTER_ACCOUNT_RATE_LIMIT_URL "/account/rate_limit_status.json" /* Favorites URLs */ -#define TWITTER_FAVORITES_GET_URL "/favorites.xml" -#define TWITTER_FAVORITE_CREATE_URL "/favorites/create/" -#define TWITTER_FAVORITE_DESTROY_URL "/favorites/destroy/" +#define TWITTER_FAVORITES_GET_URL "/favorites.json" +#define TWITTER_FAVORITE_CREATE_URL "/favorites/create.json" +#define TWITTER_FAVORITE_DESTROY_URL "/favorites/destroy.json" /* Block URLs */ #define TWITTER_BLOCKS_CREATE_URL "/blocks/create/" #define TWITTER_BLOCKS_DESTROY_URL "/blocks/destroy/" /* Report spam */ -#define TWITTER_REPORT_SPAM_URL "/report_spam.xml" +#define TWITTER_REPORT_SPAM_URL "/users/report_spam.json" +#define TWITTER_USER_STREAM_URL "https://userstream.twitter.com/1.1/user.json" + +gboolean twitter_open_stream(struct im_connection *ic); void twitter_get_timeline(struct im_connection *ic, gint64 next_cursor); void twitter_get_friends_ids(struct im_connection *ic, gint64 next_cursor); -void twitter_get_home_timeline(struct im_connection *ic, gint64 next_cursor); -void twitter_get_mentions(struct im_connection *ic, gint64 next_cursor); void twitter_get_statuses_friends(struct im_connection *ic, gint64 next_cursor); void twitter_post_status(struct im_connection *ic, char *msg, guint64 in_reply_to); @@ -90,6 +91,7 @@ void twitter_friendships_create_destroy(struct im_connection *ic, char *who, int void twitter_status_destroy(struct im_connection *ic, guint64 id); void twitter_status_retweet(struct im_connection *ic, guint64 id); void twitter_report_spam(struct im_connection *ic, char *screen_name); +void twitter_favourite_tweet(struct im_connection *ic, guint64 id); #endif //_TWITTER_LIB_H diff --git a/protocols/yahoo/Makefile b/protocols/yahoo/Makefile index d756d1e7..8ac73e49 100644 --- a/protocols/yahoo/Makefile +++ b/protocols/yahoo/Makefile @@ -12,7 +12,7 @@ _SRCDIR_ := $(_SRCDIR_)protocols/yahoo/ endif # [SH] Program variables -objects = yahoo.o crypt.o libyahoo2.o yahoo_fn.o yahoo_httplib.o yahoo_util.o +objects = yahoo.o libyahoo2.o yahoo_httplib.o yahoo_util.o CFLAGS += -DSTDC_HEADERS -DHAVE_STRING_H -DHAVE_STRCHR -DHAVE_MEMCPY -DHAVE_GLIB LFLAGS += -r @@ -38,7 +38,7 @@ $(objects): ../../Makefile.settings Makefile $(objects): %.o: $(_SRCDIR_)%.c @echo '*' Compiling $< - @$(CC) -c $(CFLAGS) $< -o $@ + @$(CC) -c $(CFLAGS) $(CFLAGS_BITLBEE) $< -o $@ yahoo_mod.o: $(objects) @echo '*' Linking yahoo_mod.o diff --git a/protocols/yahoo/crypt.c b/protocols/yahoo/crypt.c deleted file mode 100644 index 5122e3af..00000000 --- a/protocols/yahoo/crypt.c +++ /dev/null @@ -1,203 +0,0 @@ -/* One way encryption based on MD5 sum. - Copyright (C) 1996, 1997, 1999, 2000 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -/* warmenhoven took this file and made it work with the md5.[ch] we - * already had. isn't that lovely. people should just use linux or - * freebsd, crypt works properly on those systems. i hate solaris */ - -#if HAVE_STRING_H -# include <string.h> -#elif HAVE_STRINGS_H -# include <strings.h> -#endif - -#include <stdlib.h> -#include "yahoo_util.h" - -#include "md5.h" - -/* Define our magic string to mark salt for MD5 "encryption" - replacement. This is meant to be the same as for other MD5 based - encryption implementations. */ -static const char md5_salt_prefix[] = "$1$"; - -/* Table with characters for base64 transformation. */ -static const char b64t[64] = -"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - -char *yahoo_crypt(char *key, char *salt) -{ - char *buffer = NULL; - int buflen = 0; - int needed = 3 + strlen (salt) + 1 + 26 + 1; - - md5_byte_t alt_result[16]; - md5_state_t ctx; - md5_state_t alt_ctx; - size_t salt_len; - size_t key_len; - size_t cnt; - char *cp; - - if (buflen < needed) { - buflen = needed; - if ((buffer = realloc(buffer, buflen)) == NULL) - return NULL; - } - - /* Find beginning of salt string. The prefix should normally always - be present. Just in case it is not. */ - if (strncmp (md5_salt_prefix, salt, sizeof (md5_salt_prefix) - 1) == 0) - /* Skip salt prefix. */ - salt += sizeof (md5_salt_prefix) - 1; - - salt_len = MIN (strcspn (salt, "$"), 8); - key_len = strlen (key); - - /* Prepare for the real work. */ - md5_init(&ctx); - - /* Add the key string. */ - md5_append(&ctx, (md5_byte_t *)key, key_len); - - /* Because the SALT argument need not always have the salt prefix we - add it separately. */ - md5_append(&ctx, (md5_byte_t *)md5_salt_prefix, sizeof (md5_salt_prefix) - 1); - - /* The last part is the salt string. This must be at most 8 - characters and it ends at the first `$' character (for - compatibility which existing solutions). */ - md5_append(&ctx, (md5_byte_t *)salt, salt_len); - - /* Compute alternate MD5 sum with input KEY, SALT, and KEY. The - final result will be added to the first context. */ - md5_init(&alt_ctx); - - /* Add key. */ - md5_append(&alt_ctx, (md5_byte_t *)key, key_len); - - /* Add salt. */ - md5_append(&alt_ctx, (md5_byte_t *)salt, salt_len); - - /* Add key again. */ - md5_append(&alt_ctx, (md5_byte_t *)key, key_len); - - /* Now get result of this (16 bytes) and add it to the other - context. */ - md5_finish(&alt_ctx, alt_result); - - /* Add for any character in the key one byte of the alternate sum. */ - for (cnt = key_len; cnt > 16; cnt -= 16) - md5_append(&ctx, alt_result, 16); - md5_append(&ctx, alt_result, cnt); - - /* For the following code we need a NUL byte. */ - alt_result[0] = '\0'; - - /* The original implementation now does something weird: for every 1 - bit in the key the first 0 is added to the buffer, for every 0 - bit the first character of the key. This does not seem to be - what was intended but we have to follow this to be compatible. */ - for (cnt = key_len; cnt > 0; cnt >>= 1) - md5_append(&ctx, (cnt & 1) != 0 ? alt_result : (md5_byte_t *)key, 1); - - /* Create intermediate result. */ - md5_finish(&ctx, alt_result); - - /* Now comes another weirdness. In fear of password crackers here - comes a quite long loop which just processes the output of the - previous round again. We cannot ignore this here. */ - for (cnt = 0; cnt < 1000; ++cnt) { - /* New context. */ - md5_init(&ctx); - - /* Add key or last result. */ - if ((cnt & 1) != 0) - md5_append(&ctx, (md5_byte_t *)key, key_len); - else - md5_append(&ctx, alt_result, 16); - - /* Add salt for numbers not divisible by 3. */ - if (cnt % 3 != 0) - md5_append(&ctx, (md5_byte_t *)salt, salt_len); - - /* Add key for numbers not divisible by 7. */ - if (cnt % 7 != 0) - md5_append(&ctx, (md5_byte_t *)key, key_len); - - /* Add key or last result. */ - if ((cnt & 1) != 0) - md5_append(&ctx, alt_result, 16); - else - md5_append(&ctx, (md5_byte_t *)key, key_len); - - /* Create intermediate result. */ - md5_finish(&ctx, alt_result); - } - - /* Now we can construct the result string. It consists of three - parts. */ - - strncpy(buffer, md5_salt_prefix, MAX (0, buflen)); - cp = buffer + strlen(buffer); - buflen -= sizeof (md5_salt_prefix); - - strncpy(cp, salt, MIN ((size_t) buflen, salt_len)); - cp = cp + strlen(cp); - buflen -= MIN ((size_t) buflen, salt_len); - - if (buflen > 0) { - *cp++ = '$'; - --buflen; - } - -#define b64_from_24bit(B2, B1, B0, N) \ - do { \ - unsigned int w = ((B2) << 16) | ((B1) << 8) | (B0); \ - int n = (N); \ - while (n-- > 0 && buflen > 0) { \ - *cp++ = b64t[w & 0x3f]; \ - --buflen; \ - w >>= 6; \ - }\ - } while (0) - - b64_from_24bit (alt_result[0], alt_result[6], alt_result[12], 4); - b64_from_24bit (alt_result[1], alt_result[7], alt_result[13], 4); - b64_from_24bit (alt_result[2], alt_result[8], alt_result[14], 4); - b64_from_24bit (alt_result[3], alt_result[9], alt_result[15], 4); - b64_from_24bit (alt_result[4], alt_result[10], alt_result[5], 4); - b64_from_24bit (0, 0, alt_result[11], 2); - if (buflen <= 0) { - FREE(buffer); - } else - *cp = '\0'; /* Terminate the string. */ - - /* Clear the buffer for the intermediate result so that people - attaching to processes or reading core dumps cannot get any - information. We do it in this way to clear correct_words[] - inside the MD5 implementation as well. */ - md5_init(&ctx); - md5_finish(&ctx, alt_result); - memset (&ctx, '\0', sizeof (ctx)); - memset (&alt_ctx, '\0', sizeof (alt_ctx)); - - return buffer; -} diff --git a/protocols/yahoo/libyahoo2.c b/protocols/yahoo/libyahoo2.c index ca2a161e..da427279 100644 --- a/protocols/yahoo/libyahoo2.c +++ b/protocols/yahoo/libyahoo2.c @@ -82,7 +82,6 @@ char *strchr (), *strrchr (); #include "yahoo2.h" #include "yahoo_httplib.h" #include "yahoo_util.h" -#include "yahoo_fn.h" #include "yahoo2_callbacks.h" #include "yahoo_debug.h" @@ -121,11 +120,6 @@ int yahoo_log_message(char *fmt, ...) return YAHOO_CALLBACK(ext_yahoo_log) ("%s", out); } -int yahoo_connect(char *host, int port) -{ - return YAHOO_CALLBACK(ext_yahoo_connect) (host, port); -} - static enum yahoo_log_level log_level = YAHOO_LOG_NONE; enum yahoo_log_level yahoo_get_log_level() @@ -374,6 +368,7 @@ static struct yahoo_input_data * find_input_by_id(int id) } */ +#if 0 static struct yahoo_input_data *find_input_by_id_and_webcam_user(int id, const char *who) { @@ -390,6 +385,7 @@ static struct yahoo_input_data *find_input_by_id_and_webcam_user(int id, } return NULL; } +#endif static struct yahoo_input_data *find_input_by_id_and_type(int id, enum yahoo_connection_type type) @@ -430,8 +426,6 @@ static int count_inputs_with_id(int id) return c; } -extern char *yahoo_crypt(char *, char *); - /* Free a buddy list */ static void yahoo_free_buddies(YList *list) { @@ -2642,6 +2636,7 @@ static struct yahoo_packet *yahoo_getdata(struct yahoo_input_data *yid) return pkt; } +#if 0 static struct yab *yahoo_yab_read(unsigned char *d, int len) { char *st, *en; @@ -2792,6 +2787,7 @@ static struct yab *yahoo_getyab(struct yahoo_input_data *yid) return yab; } +#endif static char *yahoo_getwebcam_master(struct yahoo_input_data *yid) { @@ -3099,6 +3095,7 @@ static void yahoo_process_chatcat_connection(struct yahoo_input_data *yid, } } +#if 0 static void yahoo_process_yab_connection(struct yahoo_input_data *yid, int over) { struct yahoo_data *yd = yid->yd; @@ -3158,6 +3155,7 @@ static void yahoo_process_yab_connection(struct yahoo_input_data *yid, int over) YAHOO_CALLBACK(ext_yahoo_got_buddies) (yd->client_id, yd->buddies); } +#endif static void yahoo_process_search_connection(struct yahoo_input_data *yid, int over) @@ -3413,7 +3411,7 @@ static void yahoo_process_webcam_connection(struct yahoo_input_data *yid, static void (*yahoo_process_connection[]) (struct yahoo_input_data *, int over) = { yahoo_process_pager_connection, yahoo_process_ft_connection, - yahoo_process_yab_connection, + NULL, /*yahoo_process_yab_connection, */ yahoo_process_webcam_master_connection, yahoo_process_webcam_connection, yahoo_process_chatcat_connection, @@ -3577,10 +3575,12 @@ void *yahoo_get_fd(int id) return yid->fd; } +#if 0 void yahoo_send_buzz(int id, const char *from, const char *who) { yahoo_send_im(id, from, who, "<ding>", 1, 0); } +#endif void yahoo_send_im(int id, const char *from, const char *who, const char *what, int utf8, int picture) @@ -3722,6 +3722,7 @@ void yahoo_logoff(int id) } +#if 0 void yahoo_get_list(int id) { struct yahoo_input_data *yid = @@ -3741,6 +3742,7 @@ void yahoo_get_list(int id) yahoo_packet_free(pkt); } } +#endif static void _yahoo_http_connected(int id, void *fd, int error, void *data) { @@ -3757,6 +3759,7 @@ static void _yahoo_http_connected(int id, void *fd, int error, void *data) YAHOO_INPUT_READ, yid); } +#if 0 /* FIXME Get address book from address.yahoo.com instead */ void yahoo_get_yab(int id) { @@ -3897,6 +3900,7 @@ void yahoo_refresh(int id) yahoo_packet_free(pkt); } } +#endif void yahoo_keepalive(int id) { @@ -3914,6 +3918,7 @@ void yahoo_keepalive(int id) yahoo_packet_free(pkt); } +#if 0 void yahoo_chat_keepalive(int id) { struct yahoo_input_data *yid = @@ -3931,6 +3936,7 @@ void yahoo_chat_keepalive(int id) yahoo_send_packet(yid, pkt, 0); yahoo_packet_free(pkt); } +#endif void yahoo_add_buddy(int id, const char *who, const char *group, const char *msg) @@ -4023,6 +4029,7 @@ void yahoo_confirm_buddy(int id, const char *who, int reject, const char *msg) yahoo_packet_free(pkt); } +#if 0 void yahoo_ignore_buddy(int id, const char *who, int unignore) { struct yahoo_input_data *yid = @@ -4069,6 +4076,7 @@ void yahoo_stealth_buddy(int id, const char *who, int unstealth) yahoo_send_packet(yid, pkt, 0); yahoo_packet_free(pkt); } +#endif void yahoo_change_buddy_group(int id, const char *who, const char *old_group, const char *new_group) @@ -4097,6 +4105,7 @@ void yahoo_change_buddy_group(int id, const char *who, const char *old_group, yahoo_packet_free(pkt); } +#if 0 void yahoo_group_rename(int id, const char *old_group, const char *new_group) { struct yahoo_input_data *yid = @@ -4148,6 +4157,7 @@ void yahoo_conference_addinvite(int id, const char *from, const char *who, yahoo_packet_free(pkt); } +#endif void yahoo_conference_invite(int id, const char *from, YList *who, const char *room, const char *msg) @@ -4289,6 +4299,7 @@ void yahoo_conference_message(int id, const char *from, YList *who, yahoo_packet_free(pkt); } +#if 0 void yahoo_get_chatrooms(int id, int chatroomid) { struct yahoo_data *yd = find_conn_by_id(id); @@ -4731,6 +4742,7 @@ void yahoo_send_picture(int id, const char *name, unsigned long size, { /* Not Implemented */ } +#endif /* File Transfer */ static YList *active_file_transfers = NULL; @@ -4758,6 +4770,7 @@ struct send_file_data { void *data; }; +#if 0 static char *yahoo_get_random(void) { int i = 0; @@ -4787,6 +4800,7 @@ static char *yahoo_get_random(void) return strdup(out); } +#endif static int _are_same_id(const void *sfd1, const void *id) { @@ -5167,6 +5181,7 @@ static void yahoo_process_filetransfer(struct yahoo_input_data *yid, } } +#if 0 void yahoo_send_file(int id, const char *who, const char *msg, const char *name, unsigned long size, yahoo_get_fd_callback callback, void *data) @@ -5245,6 +5260,7 @@ void yahoo_send_file_transfer_response(int client_id, int response, char *id, vo if(response == YAHOO_FILE_TRANSFER_REJECT) yahoo_remove_active_transfer(sfd); } +#endif static void yahoo_process_ft_connection(struct yahoo_input_data *yid, int over) { @@ -5358,6 +5374,7 @@ static void yahoo_process_ft_connection(struct yahoo_input_data *yid, int over) /* End File Transfer */ +#if 0 enum yahoo_status yahoo_current_status(int id) { struct yahoo_data *yd = find_conn_by_id(id); @@ -5407,6 +5424,7 @@ const char *yahoo_get_cookie(int id, const char *which) return yd->login_cookie; return NULL; } +#endif const char *yahoo_get_profile_url(void) { diff --git a/protocols/yahoo/yahoo.c b/protocols/yahoo/yahoo.c index 8b3b0c05..a9fb2f34 100644 --- a/protocols/yahoo/yahoo.c +++ b/protocols/yahoo/yahoo.c @@ -1,7 +1,7 @@ /* * libyahoo2 wrapper to BitlBee * - * Mostly Copyright 2004-2010 Wilmer van der Gaast <wilmer@gaast.net> + * Mostly Copyright 2004-2012 Wilmer van der Gaast <wilmer@gaast.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -569,10 +569,6 @@ void ext_yahoo_got_buddies( int id, YList *buds ) } } -void ext_yahoo_got_ignore( int id, YList *igns ) -{ -} - void ext_yahoo_got_identities( int id, YList *ids ) { } @@ -813,13 +809,6 @@ void ext_yahoo_got_buddy_change_group( int id, const char *me, const char *who, imcb_add_buddy( ic, who, new_group ); } -/* Because we don't want asynchronous connects in BitlBee, and because - libyahoo doesn't seem to use this one anyway, this one is now defunct. */ -int ext_yahoo_connect(const char *host, int port) -{ - return -1; -} - static void byahoo_accept_conf( void *data ) { struct byahoo_conf_invitation *inv = data; diff --git a/protocols/yahoo/yahoo2.h b/protocols/yahoo/yahoo2.h index 589aaa5a..b9e6665b 100644 --- a/protocols/yahoo/yahoo2.h +++ b/protocols/yahoo/yahoo2.h @@ -120,7 +120,7 @@ extern "C" { /* utf8 is whether msg is a utf8 string or not. */ void yahoo_send_im(int id, const char *from, const char *who, const char *msg, int utf8, int picture); - void yahoo_send_buzz(int id, const char *from, const char *who); +// void yahoo_send_buzz(int id, const char *from, const char *who); /* if type is true, send typing notice, else send stopped typing notice */ void yahoo_send_typing(int id, const char *from, const char *who, int typ); diff --git a/protocols/yahoo/yahoo2_callbacks.h b/protocols/yahoo/yahoo2_callbacks.h index 0dccf188..0a3aab46 100644 --- a/protocols/yahoo/yahoo2_callbacks.h +++ b/protocols/yahoo/yahoo2_callbacks.h @@ -112,7 +112,7 @@ struct yahoo_callbacks { * id - the id that identifies the server connection * igns - the ignore list */ - void YAHOO_CALLBACK_TYPE(ext_yahoo_got_ignore) (int id, YList *igns); +// void YAHOO_CALLBACK_TYPE(ext_yahoo_got_ignore) (int id, YList *igns); /* * Name: ext_yahoo_got_identities @@ -677,7 +677,7 @@ struct yahoo_callbacks { * Returns: * a unix file descriptor to the socket */ - int YAHOO_CALLBACK_TYPE(ext_yahoo_connect) (const char *host, int port); +// int YAHOO_CALLBACK_TYPE(ext_yahoo_connect) (const char *host, int port); /* * Name: ext_yahoo_connect_async diff --git a/protocols/yahoo/yahoo_fn.c b/protocols/yahoo/yahoo_fn.c deleted file mode 100644 index 9544999d..00000000 --- a/protocols/yahoo/yahoo_fn.c +++ /dev/null @@ -1,4622 +0,0 @@ -/* - * libyahoo2 - originally from gaim patches by Amatus - * - * Copyright (C) 2003-2004 - * - * Some code copyright (C) 1998-1999, Mark Spencer <markster@marko.net> - * libfaim code copyright 1998, 1999 Adam Fritzler <afritz@auk.cx> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include "yahoo_fn.h" - -static const unsigned char table_0[256] = { - 0x5A, 0x41, 0x11, 0x77, 0x29, 0x9C, 0x31, 0xAD, - 0x4A, 0x32, 0x1A, 0x6D, 0x56, 0x9F, 0x39, 0xA6, - 0x0C, 0xE8, 0x49, 0x40, 0xA4, 0x21, 0xE9, 0x01, - 0x91, 0x86, 0x2F, 0xB9, 0xED, 0x80, 0x51, 0xAB, - 0x7F, 0x92, 0xF2, 0x73, 0xCD, 0xD9, 0x75, 0x2A, - 0x70, 0x34, 0x35, 0x8D, 0xA8, 0x72, 0x7D, 0x9B, - 0x2E, 0xC5, 0x2D, 0x76, 0x1E, 0xBB, 0xE7, 0x37, - 0xBA, 0xB7, 0xB2, 0x03, 0x20, 0x17, 0x8A, 0x07, - 0xD6, 0x96, 0x13, 0x95, 0xE5, 0xF1, 0x18, 0x3B, - 0xA5, 0x62, 0x33, 0xC1, 0x44, 0x3D, 0x6C, 0xA7, - 0xBF, 0x1C, 0x60, 0xFF, 0x5B, 0xF5, 0x8E, 0xE6, - 0x5C, 0xCC, 0xF7, 0x69, 0x15, 0x0F, 0x0B, 0xBD, - 0x12, 0x9D, 0xB3, 0x65, 0x53, 0xB1, 0x14, 0xF4, - 0x19, 0x3E, 0xB6, 0x45, 0xCB, 0xA2, 0x7A, 0xD3, - 0xF8, 0xD1, 0x61, 0xEE, 0xBC, 0xC6, 0xB0, 0x5D, - 0x4B, 0x09, 0x26, 0xE1, 0x1D, 0x6E, 0xC3, 0xFB, - 0x68, 0x4C, 0x42, 0x52, 0x5F, 0xDE, 0xFD, 0xEF, - 0x81, 0x04, 0x6F, 0xE0, 0xF0, 0x1F, 0x0D, 0x7C, - 0x58, 0x4F, 0x1B, 0x30, 0xCF, 0x9A, 0x2B, 0x05, - 0xF6, 0x3F, 0x78, 0xAC, 0xD8, 0xEC, 0xE2, 0x25, - 0x93, 0xDA, 0x84, 0x8C, 0x4E, 0xD5, 0x38, 0x0A, - 0x06, 0x7E, 0xD4, 0x59, 0x98, 0xE3, 0x36, 0xC2, - 0xD2, 0xA3, 0x10, 0x79, 0xFA, 0xC9, 0x16, 0x27, - 0x66, 0x89, 0xFE, 0x57, 0xF3, 0x83, 0xB8, 0x28, - 0x3C, 0xC7, 0xCE, 0x71, 0xC8, 0xDB, 0x22, 0xE4, - 0xDD, 0xDF, 0x02, 0x8F, 0x5E, 0xEB, 0x48, 0x2C, - 0x08, 0xC4, 0x43, 0xEA, 0x50, 0x55, 0x90, 0x54, - 0x87, 0xCA, 0x00, 0x24, 0x6B, 0x85, 0x97, 0xD7, - 0xDC, 0x6A, 0x67, 0xD0, 0x88, 0xA1, 0x9E, 0xC0, - 0x46, 0xAE, 0x64, 0x74, 0x4D, 0xA0, 0x99, 0xB5, - 0x0E, 0x8B, 0xAA, 0x3A, 0xB4, 0xFC, 0xA9, 0x94, - 0x7B, 0xBE, 0xF9, 0xAF, 0x82, 0x63, 0x47, 0x23 }; - -static const unsigned char table_1[256] = { - 0x08, 0xCB, 0x54, 0xCF, 0x97, 0x53, 0x59, 0xF1, - 0x66, 0xEC, 0xDB, 0x1B, 0xB1, 0xE2, 0x36, 0xEB, - 0xB3, 0x8F, 0x71, 0xA8, 0x90, 0x7D, 0xDA, 0xDC, - 0x2C, 0x2F, 0xE8, 0x6A, 0x73, 0x37, 0xAE, 0xCC, - 0xA1, 0x16, 0xE6, 0xFC, 0x9C, 0xA9, 0x2A, 0x3F, - 0x58, 0xFD, 0x56, 0x4C, 0xA5, 0xF2, 0x33, 0x99, - 0x1A, 0xB7, 0xFE, 0xA6, 0x1E, 0x32, 0x9E, 0x48, - 0x03, 0x4A, 0x78, 0xEE, 0xCA, 0xC3, 0x88, 0x7A, - 0xAC, 0x23, 0xAA, 0xBD, 0xDE, 0xD3, 0x67, 0x43, - 0xFF, 0x64, 0x8A, 0xF9, 0x04, 0xD0, 0x7B, 0xC2, - 0xBC, 0xF3, 0x89, 0x0E, 0xDD, 0xAB, 0x9D, 0x84, - 0x5A, 0x62, 0x7F, 0x6D, 0x82, 0x68, 0xA3, 0xED, - 0x2E, 0x07, 0x41, 0xEF, 0x2D, 0x70, 0x4F, 0x69, - 0x8E, 0xE7, 0x0F, 0x11, 0x19, 0xAF, 0x31, 0xFB, - 0x8D, 0x4B, 0x5F, 0x96, 0x75, 0x42, 0x6C, 0x46, - 0xE4, 0x55, 0xD6, 0x3B, 0xE1, 0xD1, 0xB0, 0xB5, - 0x45, 0x29, 0xC0, 0x94, 0x9F, 0xD4, 0x15, 0x17, - 0x3C, 0x47, 0xC8, 0xD9, 0xC6, 0x76, 0xB9, 0x02, - 0xE0, 0xC9, 0xB2, 0x01, 0xC1, 0x5D, 0x4E, 0x14, - 0xF4, 0xAD, 0xB6, 0x00, 0x72, 0xF0, 0x49, 0x0D, - 0xD8, 0x5E, 0x6F, 0x2B, 0x8C, 0x51, 0x83, 0xC5, - 0x0A, 0x85, 0xE5, 0x38, 0x7E, 0x26, 0xEA, 0x22, - 0x6B, 0x06, 0xD5, 0x8B, 0xBF, 0xC7, 0x35, 0x1D, - 0xF6, 0x24, 0x28, 0xCE, 0x9B, 0x77, 0x20, 0x60, - 0xF5, 0x87, 0x3D, 0x65, 0x86, 0x0C, 0xDF, 0xBA, - 0x12, 0xA4, 0x3A, 0x34, 0xD7, 0xA0, 0xF8, 0x63, - 0x52, 0x27, 0xB8, 0x18, 0xA7, 0x13, 0x91, 0x09, - 0x93, 0x5C, 0x10, 0x9A, 0xB4, 0xE9, 0x44, 0xC4, - 0x21, 0x57, 0x1C, 0x0B, 0xA2, 0x74, 0x4D, 0xBE, - 0xD2, 0x1F, 0xCD, 0xE3, 0x6E, 0x7C, 0x40, 0x50, - 0x39, 0x80, 0x98, 0xFA, 0x25, 0x92, 0x30, 0x5B, - 0x05, 0x95, 0xBB, 0x79, 0x61, 0x3E, 0x81, 0xF7 }; - -static const unsigned char table_2[32] = { - 0x19, 0x05, 0x09, 0x1C, 0x0B, 0x1A, 0x12, 0x03, - 0x06, 0x04, 0x0D, 0x1D, 0x15, 0x0E, 0x1B, 0x18, - 0x00, 0x07, 0x08, 0x02, 0x13, 0x1F, 0x0C, 0x1E, - 0x16, 0x0A, 0x10, 0x0F, 0x01, 0x14, 0x11, 0x17 }; - -static const unsigned char table_3[256] = { - 0xBC, 0x1B, 0xCC, 0x1E, 0x5B, 0x59, 0x4F, 0xA8, - 0x62, 0xC6, 0xC1, 0xBB, 0x83, 0x2D, 0xA3, 0xA6, - 0x5A, 0xDC, 0xE5, 0x93, 0xFB, 0x5C, 0xD6, 0x2A, - 0x97, 0xC7, 0x1C, 0x73, 0x08, 0x45, 0xD2, 0x89, - 0x4A, 0xD4, 0xCF, 0x0C, 0x1D, 0xD8, 0xCD, 0x26, - 0x8F, 0x11, 0x55, 0x8B, 0xD3, 0x53, 0xCE, 0x00, - 0xB5, 0x3B, 0x2E, 0x39, 0x88, 0x7B, 0x85, 0x46, - 0x54, 0xA5, 0x31, 0x40, 0x3E, 0x0A, 0x4C, 0x68, - 0x70, 0x0F, 0xBA, 0x0E, 0x75, 0x8A, 0xEB, 0x44, - 0x60, 0x6C, 0x05, 0xC9, 0xF0, 0xDD, 0x0D, 0x66, - 0xAB, 0xA1, 0xAD, 0xF2, 0x12, 0x6A, 0xE6, 0x27, - 0xF6, 0x9F, 0xDB, 0xB8, 0xF4, 0x56, 0x5E, 0x2C, - 0xDA, 0xFE, 0x34, 0x86, 0xF5, 0xC2, 0xB0, 0xF1, - 0xCB, 0xF3, 0x78, 0x9B, 0x7F, 0xB4, 0xD7, 0x58, - 0x74, 0x07, 0x72, 0x96, 0x02, 0xCA, 0xAC, 0xE8, - 0x5D, 0xA7, 0x32, 0xBD, 0x81, 0x43, 0x18, 0xF8, - 0x15, 0x0B, 0xE9, 0x76, 0x30, 0xBF, 0x3A, 0x22, - 0x9E, 0xD1, 0x79, 0x37, 0xBE, 0x8C, 0x7A, 0x98, - 0x21, 0x95, 0x10, 0x8D, 0xDF, 0xC0, 0x69, 0xC8, - 0x03, 0x6E, 0x4B, 0x36, 0xFC, 0x6F, 0xA9, 0x48, - 0x63, 0xE1, 0xB9, 0x24, 0x87, 0x13, 0xB2, 0xA4, - 0x84, 0x06, 0x14, 0x61, 0x3D, 0x92, 0xB1, 0x41, - 0xE2, 0x71, 0xAF, 0x16, 0xDE, 0x25, 0x82, 0xD9, - 0x2B, 0x33, 0x51, 0xA2, 0x4E, 0x7D, 0x94, 0xFF, - 0xFD, 0x5F, 0x80, 0xED, 0x64, 0xE7, 0x50, 0x6D, - 0xD0, 0x3C, 0x6B, 0x65, 0x77, 0x17, 0x1A, 0xEC, - 0xD5, 0xAA, 0xF9, 0xC4, 0x9C, 0x35, 0xE3, 0x42, - 0xE4, 0x19, 0x52, 0x67, 0xB7, 0x9D, 0x28, 0xC5, - 0x47, 0x38, 0x91, 0x57, 0xAE, 0x3F, 0x29, 0x9A, - 0x2F, 0xF7, 0x90, 0x04, 0xEE, 0xFA, 0x20, 0xB6, - 0xEA, 0x49, 0x23, 0x4D, 0xB3, 0x8E, 0xC3, 0x1F, - 0x7C, 0xEF, 0xE0, 0x99, 0x09, 0xA0, 0x01, 0x7E }; - -static const unsigned char table_4[32] = { - 0x1F, 0x0B, 0x00, 0x1E, 0x03, 0x0E, 0x15, 0x01, - 0x1A, 0x17, 0x1D, 0x1B, 0x11, 0x0F, 0x0A, 0x12, - 0x13, 0x18, 0x02, 0x04, 0x09, 0x06, 0x0D, 0x07, - 0x08, 0x05, 0x10, 0x19, 0x0C, 0x14, 0x16, 0x1C }; - -static const unsigned char table_5[256] = { - 0x9A, 0xAB, 0x61, 0x28, 0x0A, 0x23, 0xFC, 0xBA, - 0x90, 0x22, 0xB7, 0x62, 0xD9, 0x09, 0x91, 0xF4, - 0x7B, 0x5D, 0x6B, 0x80, 0xAC, 0x9E, 0x21, 0x72, - 0x64, 0x2D, 0xFF, 0x66, 0xEB, 0x5B, 0x05, 0xC8, - 0x1B, 0xD1, 0x55, 0xF5, 0x97, 0x08, 0xAE, 0xC7, - 0x00, 0xDE, 0xE1, 0x78, 0xD8, 0xB6, 0xF0, 0x17, - 0xE4, 0x32, 0xCD, 0x76, 0x07, 0x14, 0x7F, 0x7A, - 0xBF, 0xB4, 0x1D, 0x94, 0x48, 0x75, 0xFA, 0xA7, - 0x99, 0x7E, 0x65, 0x38, 0x29, 0x51, 0xC3, 0x83, - 0x7C, 0x0D, 0xA0, 0xCC, 0xF1, 0xDD, 0xE2, 0x49, - 0xF8, 0xD2, 0x25, 0x54, 0x9B, 0x0E, 0xB9, 0xFE, - 0x67, 0xC4, 0xCE, 0x13, 0xD4, 0xE7, 0xB8, 0x41, - 0x77, 0xDB, 0xA6, 0xB0, 0x11, 0x6A, 0x5E, 0x68, - 0x8D, 0xF9, 0x36, 0xD3, 0xC2, 0x3A, 0xAA, 0x59, - 0x03, 0xE0, 0xE3, 0xF3, 0x42, 0x2C, 0x04, 0x47, - 0xE6, 0x93, 0xCB, 0x6E, 0x20, 0xCA, 0x01, 0xA1, - 0x40, 0x2B, 0x2F, 0x5F, 0x87, 0xD0, 0xEC, 0x88, - 0x27, 0x58, 0xC6, 0x3E, 0xDF, 0x26, 0x5C, 0xE9, - 0x1F, 0x0F, 0x95, 0x1C, 0xFB, 0xA5, 0x12, 0x39, - 0x1E, 0x3C, 0x33, 0x43, 0x56, 0xE8, 0x82, 0xF7, - 0x7D, 0x89, 0xF2, 0xD7, 0x50, 0x92, 0x60, 0x4C, - 0x2A, 0x86, 0x16, 0x6C, 0x37, 0xC0, 0xAD, 0xB3, - 0x24, 0x45, 0xB1, 0xA2, 0x71, 0xA4, 0xA3, 0xED, - 0xC9, 0x5A, 0x4D, 0x84, 0x0C, 0x3F, 0xC5, 0x9D, - 0x63, 0x19, 0x79, 0x57, 0x96, 0x30, 0x74, 0xBB, - 0xDA, 0x1A, 0x9F, 0x44, 0xC1, 0x98, 0xE5, 0x81, - 0xD6, 0x18, 0x8F, 0xFD, 0x8E, 0x06, 0x6F, 0xF6, - 0x2E, 0x3B, 0xB5, 0x85, 0x8A, 0x9C, 0x53, 0x4A, - 0xA9, 0x52, 0x3D, 0x4E, 0xBE, 0xAF, 0xBC, 0xA8, - 0x4F, 0x6D, 0x15, 0x35, 0x8C, 0xBD, 0x34, 0x8B, - 0xDC, 0x0B, 0xCF, 0x31, 0xEA, 0xB2, 0x70, 0x4B, - 0x46, 0x73, 0x69, 0xD5, 0x10, 0xEE, 0x02, 0xEF }; - -static const unsigned char table_6[32] = { - 0x1A, 0x1C, 0x0F, 0x0C, 0x00, 0x02, 0x13, 0x09, - 0x11, 0x05, 0x0D, 0x12, 0x18, 0x0B, 0x04, 0x10, - 0x14, 0x1B, 0x1E, 0x16, 0x07, 0x08, 0x03, 0x17, - 0x19, 0x1F, 0x01, 0x0E, 0x15, 0x06, 0x0A, 0x1D }; - -static const unsigned char table_7[256] = { - 0x52, 0x11, 0x72, 0xD0, 0x76, 0xD7, 0xAE, 0x03, - 0x7F, 0x19, 0xF4, 0xB8, 0xB3, 0x5D, 0xCA, 0x2D, - 0x5C, 0x30, 0x53, 0x1A, 0x57, 0xF6, 0xAD, 0x83, - 0x29, 0x79, 0xD5, 0xF0, 0x0F, 0xC3, 0x8B, 0xD3, - 0x8E, 0x37, 0x01, 0xA6, 0xF1, 0x10, 0x04, 0x71, - 0xCC, 0xC6, 0xE7, 0xC2, 0x85, 0x94, 0xBD, 0x6F, - 0xCB, 0xEA, 0xFC, 0xA1, 0x38, 0x5E, 0x08, 0x2E, - 0x35, 0x42, 0x67, 0xD4, 0x56, 0x6D, 0x7C, 0xE5, - 0x0E, 0x7D, 0x12, 0x65, 0xF5, 0x33, 0x82, 0xC4, - 0x1D, 0xD2, 0x16, 0x58, 0xEC, 0xCD, 0xA8, 0xBF, - 0xAB, 0x07, 0x45, 0x55, 0xB7, 0x6A, 0x70, 0xF2, - 0xBE, 0x05, 0x6B, 0x9D, 0xEB, 0x13, 0x0D, 0x9F, - 0xE8, 0xA7, 0xC8, 0x31, 0x3C, 0xB6, 0x21, 0xC0, - 0x20, 0x60, 0x6C, 0xE2, 0xCE, 0x8C, 0xFD, 0x95, - 0xE3, 0x4A, 0xB5, 0xB2, 0x40, 0xB1, 0xF3, 0x17, - 0xF9, 0x24, 0x06, 0x22, 0x2F, 0x25, 0x93, 0x8A, - 0x2A, 0x7E, 0x28, 0x3D, 0x47, 0xF8, 0x89, 0xA5, - 0x7B, 0x9B, 0xC5, 0x84, 0x59, 0x46, 0x90, 0x74, - 0x69, 0xC7, 0xAA, 0xEE, 0x6E, 0xD6, 0xB0, 0x18, - 0x66, 0xA0, 0x7A, 0x1E, 0xFB, 0xDB, 0x4E, 0x51, - 0x92, 0xE4, 0xE0, 0x3E, 0xB4, 0xD8, 0x23, 0x3B, - 0xC1, 0x5F, 0xFE, 0x98, 0x99, 0x73, 0x09, 0xA9, - 0xA3, 0xDF, 0x14, 0x5A, 0x26, 0x8F, 0x0B, 0xAF, - 0x4C, 0x97, 0x54, 0xE1, 0x63, 0x48, 0xED, 0xBA, - 0xCF, 0xBB, 0x1F, 0xDC, 0xA4, 0xFA, 0x64, 0x75, - 0xDE, 0x81, 0x9A, 0xFF, 0x49, 0x41, 0x27, 0x62, - 0x02, 0x15, 0xD9, 0x86, 0xAC, 0x3F, 0x0C, 0x61, - 0xD1, 0x77, 0x2B, 0x1B, 0x96, 0xDA, 0x68, 0x1C, - 0x44, 0x32, 0xBC, 0xA2, 0x87, 0xF7, 0x91, 0x8D, - 0x80, 0xDD, 0x0A, 0x50, 0x34, 0x4B, 0x00, 0xB9, - 0x36, 0xE6, 0x78, 0x4F, 0xC9, 0xE9, 0x2C, 0x43, - 0x88, 0x9E, 0x9C, 0x5B, 0x4D, 0x3A, 0x39, 0xEF }; - -static const unsigned char table_8[32] = { - 0x13, 0x08, 0x1E, 0x1D, 0x17, 0x16, 0x07, 0x1F, - 0x0E, 0x03, 0x1A, 0x19, 0x01, 0x12, 0x11, 0x10, - 0x09, 0x0C, 0x0F, 0x14, 0x0B, 0x05, 0x00, 0x04, - 0x1C, 0x18, 0x0A, 0x15, 0x02, 0x1B, 0x06, 0x0D }; - -static const unsigned char table_9[256] = { - 0x20, 0x2A, 0xDA, 0xFE, 0x76, 0x0D, 0xED, 0x39, - 0x51, 0x4C, 0x46, 0x9A, 0xF1, 0xB0, 0x10, 0xC7, - 0xD1, 0x6F, 0x18, 0x24, 0xB9, 0x7A, 0x4F, 0x47, - 0xE0, 0x4E, 0x88, 0x09, 0x8A, 0xBA, 0x60, 0xBD, - 0xC2, 0x27, 0x93, 0x7D, 0x94, 0x40, 0xCB, 0x80, - 0xB8, 0x41, 0x84, 0x5D, 0xC1, 0x0F, 0x5E, 0x78, - 0x2B, 0x48, 0x28, 0x29, 0xEE, 0x81, 0x90, 0x86, - 0x50, 0x9C, 0xF3, 0xB2, 0x35, 0x52, 0x0C, 0x9D, - 0xFC, 0x69, 0xD6, 0xA6, 0x06, 0xD7, 0xC6, 0xFF, - 0x1C, 0x14, 0x57, 0x33, 0xE2, 0x1F, 0x83, 0xA8, - 0xF7, 0x99, 0xC5, 0xDC, 0x70, 0x9E, 0xF4, 0x6B, - 0x0A, 0x77, 0x95, 0x4A, 0x2E, 0x53, 0xF2, 0x62, - 0x98, 0xF8, 0x96, 0xDB, 0xE6, 0x32, 0x3C, 0x58, - 0xD5, 0x6D, 0xE7, 0x4B, 0xCE, 0x91, 0x43, 0xD8, - 0xFA, 0xE3, 0x4D, 0xD9, 0x68, 0xDE, 0xEC, 0x01, - 0x08, 0xD3, 0x8F, 0x19, 0xC4, 0xA7, 0x6E, 0x3E, - 0x63, 0x12, 0x72, 0x42, 0x9F, 0xB4, 0x04, 0x1B, - 0x7E, 0x11, 0x17, 0x73, 0xB5, 0x22, 0x56, 0xA1, - 0x89, 0xDD, 0xF5, 0x3F, 0x49, 0x26, 0x8D, 0x15, - 0x85, 0x75, 0x5F, 0x65, 0x82, 0xB6, 0xF6, 0xD2, - 0xA4, 0x55, 0x37, 0xC8, 0xA0, 0xCC, 0x66, 0x5C, - 0xC9, 0x25, 0x36, 0x67, 0x7C, 0xE1, 0xA3, 0xCF, - 0xA9, 0x59, 0x2F, 0xFB, 0xBB, 0x07, 0x87, 0xA2, - 0x44, 0x92, 0x13, 0x00, 0x16, 0x61, 0x38, 0xEB, - 0xAE, 0xD4, 0x1E, 0x64, 0x6A, 0xE4, 0xCA, 0x1D, - 0x6C, 0xDF, 0xAB, 0x5B, 0x03, 0x7B, 0x9B, 0x8C, - 0x5A, 0xFD, 0xC3, 0xB3, 0x0B, 0xAA, 0xAC, 0x8B, - 0xBE, 0xBC, 0x3D, 0x97, 0xCD, 0x05, 0x21, 0x8E, - 0xAD, 0xEA, 0x54, 0x30, 0xAF, 0x02, 0xB1, 0x34, - 0x0E, 0xA5, 0x3B, 0x45, 0x1A, 0x23, 0xE8, 0x7F, - 0xEF, 0xB7, 0x31, 0xD0, 0xBF, 0x3A, 0x79, 0xE5, - 0xF9, 0xF0, 0x2C, 0x74, 0xE9, 0x71, 0xC0, 0x2D }; - -static const unsigned char table_10[32] = { - 0x1D, 0x12, 0x11, 0x0D, 0x1E, 0x19, 0x16, 0x1B, - 0x18, 0x13, 0x07, 0x17, 0x0C, 0x02, 0x00, 0x15, - 0x0E, 0x08, 0x05, 0x01, 0x10, 0x06, 0x04, 0x0F, - 0x1F, 0x1A, 0x0B, 0x09, 0x0A, 0x14, 0x1C, 0x03 }; - -static const unsigned char table_11[256] = { - 0x6B, 0x1D, 0xC6, 0x0A, 0xB7, 0xAC, 0xB2, 0x11, - 0x29, 0xD3, 0xA2, 0x4D, 0xCB, 0x03, 0xEF, 0xA6, - 0xC1, 0x5D, 0x75, 0x48, 0x35, 0x6C, 0xE2, 0x84, - 0xAB, 0xAA, 0xD8, 0x2C, 0x0E, 0x95, 0x25, 0x27, - 0x7D, 0x0B, 0xD0, 0xFB, 0x14, 0xE5, 0xF2, 0x4E, - 0x7F, 0x2A, 0x63, 0x3C, 0xC9, 0xF6, 0xDC, 0x07, - 0x26, 0x55, 0xCF, 0x2B, 0xCD, 0xA7, 0x17, 0xD2, - 0x9A, 0x7B, 0x93, 0x78, 0x9E, 0xE6, 0x2F, 0x49, - 0x1E, 0xFD, 0xF0, 0xFE, 0x7C, 0x33, 0x92, 0xA3, - 0xC8, 0xA0, 0xA9, 0xC4, 0xA1, 0x94, 0x6D, 0x44, - 0x0C, 0x90, 0x3A, 0x8C, 0x8E, 0x85, 0xAF, 0x40, - 0x36, 0xA4, 0xD1, 0xB9, 0x19, 0x6F, 0xF4, 0xBA, - 0x1A, 0x73, 0xD9, 0xB5, 0xB4, 0x7A, 0xF9, 0x83, - 0x58, 0xAD, 0xCE, 0x60, 0x98, 0xDB, 0x1C, 0x1B, - 0x52, 0xB8, 0xF3, 0x96, 0xED, 0xDE, 0xB3, 0xEE, - 0x4F, 0xBD, 0x10, 0xD4, 0x43, 0xEA, 0xE7, 0x37, - 0x12, 0x3D, 0xA8, 0x22, 0x65, 0xEC, 0x5B, 0x08, - 0x9D, 0x0D, 0x5C, 0xB6, 0x8A, 0x79, 0x3F, 0x04, - 0xD6, 0x01, 0xE1, 0xBE, 0xDD, 0x50, 0xFA, 0x41, - 0x13, 0x91, 0xF7, 0xDA, 0x18, 0xB0, 0x45, 0x81, - 0x4C, 0xF5, 0x32, 0x23, 0x56, 0x5A, 0xEB, 0x97, - 0x34, 0x00, 0x77, 0x71, 0x4B, 0x70, 0xD5, 0x31, - 0x72, 0x05, 0xDF, 0xE8, 0x15, 0x3B, 0x54, 0x16, - 0x89, 0xE4, 0xF1, 0xD7, 0x80, 0x82, 0x4A, 0xE3, - 0x39, 0x06, 0x47, 0x28, 0xC2, 0x86, 0x87, 0xB1, - 0x62, 0x74, 0x53, 0x21, 0x67, 0x38, 0x42, 0xCA, - 0x9B, 0xC3, 0x51, 0x99, 0x8B, 0x1F, 0x24, 0x8D, - 0xF8, 0x68, 0x3E, 0x59, 0xBB, 0x61, 0x5F, 0xBC, - 0x09, 0x6E, 0x8F, 0x0F, 0x2D, 0xC0, 0xE0, 0x46, - 0x66, 0x69, 0xA5, 0xE9, 0x30, 0x9C, 0x5E, 0xAE, - 0xBF, 0xC7, 0x20, 0x7E, 0x6A, 0xC5, 0x88, 0xFC, - 0x64, 0x76, 0xFF, 0x9F, 0x2E, 0x02, 0xCC, 0x57 }; - -static const unsigned char table_12[32] = { - 0x14, 0x1B, 0x18, 0x00, 0x1F, 0x15, 0x17, 0x07, - 0x11, 0x1A, 0x0E, 0x13, 0x12, 0x06, 0x01, 0x03, - 0x1C, 0x0C, 0x0B, 0x1D, 0x10, 0x0F, 0x09, 0x19, - 0x0D, 0x1E, 0x04, 0x05, 0x08, 0x16, 0x0A, 0x02 }; - -static const unsigned char table_13[256] = { - 0x37, 0x8A, 0x1B, 0x91, 0xA5, 0x2B, 0x2D, 0x88, - 0x8E, 0xFE, 0x0E, 0xD3, 0xF3, 0xE9, 0x7D, 0xD1, - 0x24, 0xEA, 0xB1, 0x8B, 0x5C, 0xA4, 0x44, 0x7E, - 0x8C, 0x2C, 0x73, 0xD5, 0x50, 0x3E, 0xD7, 0x18, - 0xB9, 0xD6, 0xBA, 0x94, 0x0C, 0xFC, 0xCB, 0xB4, - 0x0D, 0x63, 0x4C, 0xDE, 0x77, 0x16, 0xFD, 0x81, - 0x3C, 0x11, 0x45, 0x36, 0xF6, 0x67, 0x95, 0x6D, - 0x6A, 0x1A, 0xA3, 0xC5, 0x92, 0x10, 0x28, 0x84, - 0x48, 0xA6, 0x23, 0xE3, 0x4B, 0xE1, 0xF5, 0x19, - 0xE0, 0x2E, 0x00, 0x61, 0x74, 0xCC, 0xF7, 0xB0, - 0x68, 0xC8, 0x40, 0x6F, 0x59, 0x52, 0x26, 0x99, - 0xC9, 0xF9, 0xC4, 0x53, 0x9B, 0xEC, 0x03, 0x17, - 0xE2, 0x06, 0x30, 0x7B, 0xBE, 0xCD, 0x1D, 0x3B, - 0xD2, 0x5B, 0x65, 0x21, 0x49, 0xB7, 0x79, 0xCF, - 0x82, 0x86, 0xC7, 0x62, 0xEE, 0x8D, 0xFF, 0xD4, - 0xC3, 0x85, 0xA7, 0xFA, 0xA9, 0x6B, 0xF2, 0x69, - 0x9C, 0x38, 0x78, 0xBD, 0x7F, 0xDD, 0xCE, 0xA1, - 0x33, 0xC2, 0x43, 0xEB, 0xD8, 0xE6, 0x2A, 0xE4, - 0x76, 0x6C, 0xAA, 0x46, 0x05, 0xE7, 0xA0, 0x0A, - 0x71, 0x98, 0x41, 0x5F, 0x0F, 0xEF, 0x51, 0xAD, - 0xF0, 0xED, 0x96, 0x5A, 0x42, 0x3F, 0xBF, 0x6E, - 0xBC, 0x5D, 0xC1, 0x15, 0x70, 0x54, 0x4D, 0x14, - 0xB5, 0xCA, 0x27, 0x80, 0x87, 0x39, 0x60, 0x47, - 0x9D, 0x2F, 0x56, 0x1F, 0xBB, 0x31, 0xF1, 0xE8, - 0xB3, 0x9E, 0x5E, 0x7C, 0xD0, 0xC6, 0xB2, 0x57, - 0x83, 0xAC, 0x09, 0x8F, 0xA2, 0x90, 0x13, 0x25, - 0x01, 0x08, 0x64, 0xB6, 0x02, 0xDB, 0x55, 0x32, - 0xAF, 0x9A, 0xC0, 0x1C, 0x12, 0x29, 0x0B, 0x72, - 0x4F, 0xDA, 0xAB, 0x35, 0xF8, 0x22, 0xD9, 0x4E, - 0x3D, 0x1E, 0xDC, 0x58, 0x20, 0x34, 0xAE, 0x66, - 0x75, 0x93, 0x9F, 0x3A, 0x07, 0xE5, 0x89, 0xDF, - 0x97, 0x4A, 0xB8, 0x7A, 0xF4, 0xFB, 0x04, 0xA8 }; - -static const unsigned char table_14[32] = { - 0x04, 0x14, 0x13, 0x15, 0x1A, 0x1B, 0x0F, 0x16, - 0x02, 0x0D, 0x0C, 0x06, 0x10, 0x17, 0x01, 0x0B, - 0x1E, 0x08, 0x1C, 0x18, 0x19, 0x0A, 0x1F, 0x05, - 0x11, 0x09, 0x1D, 0x07, 0x0E, 0x12, 0x03, 0x00 }; - -static const unsigned char table_15[256] = { - 0x61, 0x48, 0x58, 0x41, 0x7F, 0x88, 0x43, 0x42, - 0xD9, 0x80, 0x81, 0xFE, 0xC6, 0x49, 0xD7, 0x2C, - 0xE6, 0x5B, 0xEE, 0xFF, 0x2A, 0x6F, 0xBF, 0x98, - 0xD6, 0x20, 0xB9, 0xB1, 0x5D, 0x95, 0x72, 0x1E, - 0x82, 0x96, 0xDE, 0xC1, 0x40, 0xD8, 0x70, 0xA3, - 0xD1, 0x1F, 0xF0, 0x9F, 0x2D, 0xDC, 0x3F, 0xF9, - 0x5E, 0x0D, 0x15, 0x2F, 0x67, 0x31, 0x9D, 0x84, - 0x97, 0x0C, 0xF6, 0x79, 0xC2, 0xA7, 0xC0, 0x32, - 0xB3, 0xEB, 0xED, 0x71, 0x30, 0xCC, 0x4B, 0xA0, - 0xF5, 0xC4, 0xCD, 0x27, 0xFA, 0x11, 0x25, 0xDB, - 0x4F, 0xE2, 0x7E, 0xA6, 0xAF, 0x34, 0x69, 0x63, - 0x8F, 0x08, 0x1C, 0x85, 0xF1, 0x57, 0x78, 0xC8, - 0xA2, 0x83, 0xB5, 0x68, 0xF7, 0x64, 0x45, 0x26, - 0x3B, 0x03, 0xAD, 0x3C, 0x50, 0xD5, 0x77, 0xFC, - 0xFB, 0x18, 0xC9, 0xD2, 0x9C, 0xBB, 0xBA, 0x76, - 0x23, 0x55, 0xD3, 0x5A, 0x01, 0xE9, 0x87, 0x07, - 0x19, 0x09, 0x39, 0x8A, 0x91, 0x93, 0x12, 0xDF, - 0x22, 0xA8, 0xCF, 0x4E, 0x4D, 0x65, 0xB0, 0x0F, - 0x13, 0x53, 0x21, 0x8C, 0xE5, 0xB7, 0x0B, 0x0E, - 0x6C, 0x44, 0xCA, 0x7B, 0xC5, 0x6E, 0xCE, 0xE3, - 0x14, 0x29, 0xAC, 0x2E, 0xE7, 0x59, 0xE8, 0x0A, - 0xEA, 0x66, 0x7C, 0x94, 0x6D, 0x05, 0x9E, 0x9A, - 0x2B, 0x38, 0x6A, 0xCB, 0x51, 0xEF, 0x06, 0xDA, - 0xFD, 0x47, 0x92, 0x1D, 0xA5, 0x37, 0x33, 0xEC, - 0xB4, 0x52, 0x56, 0xC3, 0xF4, 0xF8, 0x8B, 0xD0, - 0xA4, 0x5F, 0x28, 0x89, 0x75, 0xC7, 0x04, 0x00, - 0xE4, 0x86, 0x36, 0x3A, 0x99, 0x16, 0x7D, 0xE0, - 0x7A, 0x4C, 0x54, 0x46, 0x73, 0xB2, 0xF3, 0xE1, - 0x62, 0xBE, 0x90, 0x4A, 0x24, 0x6B, 0x3E, 0xAA, - 0x1B, 0xF2, 0x60, 0xD4, 0xA9, 0x9B, 0x1A, 0xB8, - 0xA1, 0x35, 0xAE, 0xB6, 0x10, 0x5C, 0x17, 0xBC, - 0xAB, 0x8D, 0x02, 0x74, 0xBD, 0x3D, 0x8E, 0xDD }; - -static const unsigned char table_16[256] = { - 0x3F, 0x9C, 0x17, 0xC1, 0x59, 0xC6, 0x23, 0x93, - 0x4B, 0xDF, 0xCB, 0x55, 0x2B, 0xDE, 0xCD, 0xAD, - 0xB3, 0xE7, 0x42, 0x2F, 0x02, 0x5A, 0x7B, 0x5C, - 0x8F, 0xD1, 0x11, 0xCE, 0xEC, 0xF6, 0xA4, 0xE6, - 0x58, 0x98, 0x6A, 0x99, 0xFB, 0x9B, 0x53, 0x21, - 0x8A, 0x09, 0x2E, 0x3C, 0x22, 0x38, 0xAC, 0x07, - 0x91, 0x46, 0xA9, 0x95, 0xC3, 0x14, 0x84, 0xDB, - 0x36, 0x68, 0x1D, 0xDD, 0xF9, 0x12, 0xE0, 0x3D, - 0x8D, 0x4D, 0x05, 0x86, 0x69, 0xC0, 0xD3, 0xD5, - 0xA5, 0xC9, 0xE5, 0x67, 0x6D, 0xE2, 0x7F, 0xFE, - 0xB2, 0x0F, 0x62, 0xCF, 0x37, 0x35, 0xF3, 0x28, - 0x16, 0xA6, 0x50, 0x76, 0x80, 0x00, 0x31, 0x97, - 0x39, 0x7C, 0x25, 0x0C, 0x64, 0xF2, 0x52, 0x1A, - 0x92, 0x4F, 0x2A, 0x56, 0x03, 0x4C, 0xBD, 0x10, - 0xB7, 0x2C, 0x8C, 0xAE, 0x73, 0xB9, 0xE9, 0xF7, - 0xA7, 0xE1, 0x75, 0xBC, 0xC5, 0x1C, 0x3A, 0x63, - 0x7A, 0x4A, 0x29, 0xD2, 0x71, 0xE8, 0x08, 0xA1, - 0xD4, 0xFD, 0x13, 0xFA, 0xA0, 0x27, 0x41, 0x72, - 0x82, 0x18, 0x51, 0x60, 0x5E, 0x66, 0x0D, 0xAA, - 0xD8, 0x1F, 0xAF, 0x45, 0xD0, 0xF1, 0x9F, 0x6B, - 0xE4, 0x44, 0x89, 0xEE, 0xC4, 0x0B, 0x6C, 0xCC, - 0x83, 0x77, 0xA2, 0x87, 0x0A, 0xA8, 0xED, 0x90, - 0x74, 0x6E, 0xF5, 0xAB, 0xA3, 0xB6, 0x5F, 0x0E, - 0x04, 0x9A, 0xB4, 0x8E, 0xF0, 0xFF, 0x88, 0xB5, - 0xF8, 0xBF, 0x8B, 0x6F, 0x4E, 0x79, 0x40, 0xCA, - 0x24, 0x26, 0xDC, 0x33, 0xEB, 0x2D, 0x5B, 0x1B, - 0x9D, 0xC7, 0x49, 0x48, 0x54, 0x85, 0xEF, 0xD7, - 0xC2, 0xB8, 0xC8, 0x5D, 0xD9, 0x3B, 0x15, 0xBB, - 0x65, 0xE3, 0xD6, 0x30, 0x3E, 0x1E, 0x32, 0x9E, - 0x57, 0x81, 0x34, 0x06, 0xFC, 0xBA, 0x7D, 0x20, - 0x70, 0xDA, 0x7E, 0x47, 0x94, 0x61, 0xB0, 0x78, - 0xF4, 0xBE, 0xEA, 0x19, 0x43, 0x01, 0xB1, 0x96 }; - -static const unsigned char table_17[256] = { - 0x7E, 0xF1, 0xD3, 0x75, 0x87, 0xA6, 0xED, 0x9E, - 0xA9, 0xD5, 0xC6, 0xBF, 0xE6, 0x6A, 0xEE, 0x4B, - 0x34, 0xDF, 0x4C, 0x7D, 0xDD, 0xFE, 0x3F, 0xAF, - 0x66, 0x2D, 0x74, 0x6F, 0xFC, 0x4F, 0x5F, 0x88, - 0x29, 0x7B, 0xC7, 0x2A, 0x70, 0xE8, 0x1D, 0xDE, - 0xD0, 0x55, 0x71, 0x81, 0xC4, 0x0D, 0x50, 0x4E, - 0x58, 0x00, 0x96, 0x97, 0xBB, 0xD7, 0x53, 0x15, - 0x6C, 0x40, 0x17, 0xC9, 0xFF, 0x8F, 0x94, 0xFB, - 0x19, 0x9A, 0x3E, 0xB5, 0x5A, 0x5E, 0x86, 0x24, - 0xB8, 0x77, 0xBA, 0x85, 0x51, 0x18, 0xBE, 0x59, - 0x79, 0xF3, 0xD4, 0xC3, 0xAB, 0x28, 0xFD, 0x25, - 0x41, 0x91, 0x07, 0x8D, 0xAE, 0x49, 0xF5, 0x80, - 0x35, 0xA1, 0x9C, 0x3C, 0xE2, 0x65, 0xB3, 0xE0, - 0x16, 0xCB, 0x12, 0x6B, 0xF7, 0xB1, 0x93, 0x8A, - 0xCE, 0x54, 0x4D, 0xF8, 0x13, 0xA2, 0x95, 0x46, - 0xEA, 0x61, 0x57, 0x9D, 0x27, 0x8B, 0x3D, 0x60, - 0x36, 0x68, 0x06, 0x56, 0xB6, 0x1B, 0xD2, 0x89, - 0x10, 0xA7, 0xC5, 0x1A, 0x0B, 0x2C, 0xBD, 0x14, - 0x0A, 0xDC, 0x23, 0xA8, 0xE1, 0x04, 0x02, 0xC0, - 0xB2, 0x9B, 0xE3, 0x2E, 0x33, 0x7C, 0x32, 0xAC, - 0x7A, 0x39, 0xB0, 0xF9, 0x98, 0x5B, 0x3A, 0x48, - 0x21, 0x90, 0xB9, 0x20, 0xF0, 0xA0, 0x09, 0x1F, - 0x2F, 0xEF, 0xEB, 0x22, 0x78, 0x82, 0x37, 0xD6, - 0xD1, 0x84, 0x76, 0x01, 0xDB, 0x43, 0xC2, 0xB7, - 0x7F, 0xA4, 0xE5, 0xC1, 0x1C, 0x69, 0x05, 0xEC, - 0xD8, 0x38, 0x67, 0x42, 0x72, 0xBC, 0x73, 0xAD, - 0xA3, 0xE9, 0x4A, 0x8E, 0x47, 0x1E, 0xC8, 0x6E, - 0xDA, 0x5D, 0x2B, 0xF6, 0x30, 0x63, 0xCC, 0xF4, - 0xCD, 0x8C, 0x0F, 0x3B, 0xE7, 0xD9, 0xCF, 0xB4, - 0x03, 0x92, 0x0E, 0x31, 0xE4, 0x08, 0xF2, 0x45, - 0xCA, 0x83, 0x26, 0x5C, 0xA5, 0x44, 0x64, 0x6D, - 0x9F, 0x99, 0x62, 0xAA, 0xFA, 0x11, 0x0C, 0x52 }; - -static const unsigned char table_18[256] = { - 0x0F, 0x42, 0x3D, 0x86, 0x3E, 0x66, 0xFE, 0x5C, - 0x52, 0xE2, 0xA3, 0xB3, 0xCE, 0x16, 0xCC, 0x95, - 0xB0, 0x8B, 0x82, 0x3B, 0x93, 0x7D, 0x62, 0x08, - 0x1C, 0x6E, 0xBB, 0xCB, 0x1D, 0x88, 0x69, 0xD4, - 0xC9, 0x40, 0x1F, 0xBE, 0x27, 0xBC, 0xDB, 0x38, - 0xE5, 0xA1, 0x71, 0xBA, 0x8A, 0x5E, 0xFD, 0x36, - 0x8F, 0x26, 0x6B, 0xE4, 0x20, 0x6D, 0xC5, 0xDE, - 0xE0, 0x83, 0x7C, 0xD5, 0xD9, 0x4D, 0xDC, 0xE3, - 0x0D, 0x32, 0xED, 0x0E, 0x2F, 0x21, 0xA7, 0x79, - 0xA0, 0xD3, 0x8C, 0x14, 0x6F, 0xB7, 0xF8, 0x85, - 0x5D, 0x37, 0x24, 0xD6, 0x25, 0xD2, 0x8E, 0xA5, - 0xB8, 0xCD, 0x5A, 0x9F, 0x05, 0xAD, 0x65, 0x9E, - 0x4F, 0x5B, 0x56, 0xF0, 0xAA, 0xC2, 0x28, 0xA8, - 0x6A, 0x01, 0x99, 0x2E, 0xA6, 0x77, 0x74, 0x64, - 0x76, 0x15, 0x90, 0x75, 0xAF, 0xE8, 0x39, 0x48, - 0x09, 0x11, 0xE1, 0x2D, 0xEC, 0xB5, 0x7A, 0xB1, - 0x94, 0x13, 0x41, 0x4C, 0x02, 0xA9, 0x97, 0xDF, - 0xC3, 0x8D, 0xEA, 0x3A, 0x9C, 0xD1, 0xA2, 0x9A, - 0xD7, 0x59, 0xD8, 0x18, 0xDA, 0x47, 0x89, 0x81, - 0xC7, 0xF5, 0xFC, 0x98, 0xCA, 0x91, 0x06, 0x68, - 0xC8, 0x07, 0x4A, 0x84, 0x0A, 0xE7, 0x33, 0x2C, - 0xEB, 0xDD, 0x5F, 0xAC, 0x23, 0x1A, 0x35, 0x70, - 0x43, 0x80, 0x61, 0xAE, 0xC1, 0xD0, 0x7B, 0x92, - 0x49, 0x51, 0x53, 0xC4, 0x34, 0x30, 0x0C, 0x4B, - 0x00, 0x04, 0x10, 0xFF, 0x63, 0x44, 0xB4, 0x0B, - 0x57, 0x72, 0xF1, 0x9D, 0x19, 0xF6, 0xB2, 0x87, - 0x1B, 0xEE, 0x46, 0x2A, 0xF3, 0xBF, 0x12, 0x96, - 0x58, 0x2B, 0xF9, 0xB6, 0xCF, 0x22, 0x3C, 0xAB, - 0x1E, 0x6C, 0x31, 0xC6, 0xF7, 0x78, 0x45, 0x17, - 0xE9, 0x7E, 0x73, 0xF2, 0x55, 0xFB, 0x3F, 0x9B, - 0xF4, 0xBD, 0xA4, 0x29, 0x60, 0x03, 0xB9, 0x50, - 0xFA, 0x4E, 0xEF, 0x54, 0xE6, 0x7F, 0xC0, 0x67 }; - -static const unsigned char table_19[256] = { - 0xEA, 0xE7, 0x13, 0x14, 0xB9, 0xC0, 0xC4, 0x42, - 0x49, 0x6E, 0x2A, 0xA6, 0x65, 0x3C, 0x6A, 0x40, - 0x07, 0xCD, 0x4F, 0xFE, 0xF2, 0x2D, 0xC8, 0x30, - 0x9D, 0xBE, 0x1B, 0x9B, 0x4A, 0x7E, 0x9F, 0xA7, - 0x78, 0xAB, 0x4D, 0x1D, 0xF1, 0x96, 0x32, 0x84, - 0xFB, 0x80, 0x88, 0xE8, 0x41, 0x97, 0xDC, 0xD0, - 0x4E, 0x33, 0xA4, 0x3B, 0xE0, 0xDD, 0x36, 0xC9, - 0x72, 0x48, 0x8A, 0x2F, 0x35, 0xF0, 0xDF, 0x21, - 0xE1, 0xE5, 0x6C, 0x9A, 0x60, 0x8F, 0xB7, 0x24, - 0xE4, 0x9E, 0x8C, 0x0F, 0x3D, 0x28, 0xBB, 0xD6, - 0x69, 0xA0, 0x66, 0xC7, 0xE3, 0xD8, 0x11, 0x27, - 0xD9, 0x37, 0xF4, 0xF5, 0x8E, 0xD4, 0x76, 0xE2, - 0xDB, 0x15, 0xA2, 0x5C, 0x9C, 0xEE, 0x44, 0xED, - 0x2B, 0xB3, 0x75, 0x74, 0x71, 0x8B, 0x3A, 0x91, - 0x06, 0x19, 0xC1, 0x57, 0x89, 0xCC, 0x82, 0x10, - 0x17, 0xB2, 0x08, 0x70, 0x39, 0xCA, 0xBA, 0xB5, - 0xAA, 0xBF, 0x02, 0xBD, 0x26, 0x58, 0x04, 0x54, - 0x23, 0x4B, 0x90, 0x51, 0x6D, 0x98, 0xD5, 0xB0, - 0xAF, 0x22, 0xDA, 0xB4, 0x87, 0xFC, 0x7D, 0x18, - 0x6F, 0x64, 0x59, 0x09, 0x0C, 0xA5, 0x5D, 0x03, - 0x0A, 0xD3, 0xCE, 0x99, 0x8D, 0xC2, 0xC3, 0x62, - 0xD2, 0x83, 0x1A, 0xAC, 0x7C, 0x93, 0xD7, 0xA9, - 0x16, 0xF7, 0x77, 0xE6, 0x3E, 0x05, 0x73, 0x55, - 0x43, 0x95, 0x7A, 0x6B, 0x38, 0x67, 0x3F, 0xC6, - 0xAD, 0x0E, 0x29, 0x46, 0x45, 0xFA, 0xBC, 0xEC, - 0x5B, 0x7F, 0x0B, 0x1C, 0x01, 0x12, 0x85, 0x50, - 0xF9, 0xEF, 0x25, 0x34, 0x79, 0x2E, 0xEB, 0x00, - 0x5F, 0x86, 0xF8, 0x4C, 0xA8, 0x56, 0xB6, 0x5A, - 0xF3, 0x31, 0x94, 0x92, 0xB1, 0xB8, 0x52, 0xD1, - 0xCF, 0xCB, 0xA1, 0x81, 0x68, 0x47, 0xFF, 0xC5, - 0xFD, 0x1F, 0xDE, 0x53, 0xA3, 0x2C, 0x20, 0xF6, - 0x1E, 0x0D, 0xAE, 0x7B, 0x5E, 0x61, 0xE9, 0x63 }; - -static const unsigned char table_20[32] = { - 0x0D, 0x0B, 0x11, 0x02, 0x05, 0x1B, 0x08, 0x1D, - 0x04, 0x14, 0x01, 0x09, 0x00, 0x19, 0x1E, 0x15, - 0x1F, 0x0A, 0x0F, 0x1C, 0x10, 0x16, 0x0C, 0x07, - 0x13, 0x1A, 0x06, 0x17, 0x0E, 0x12, 0x18, 0x03 }; - -static const unsigned char table_21[256] = { - 0x4C, 0x94, 0xAD, 0x66, 0x9E, 0x69, 0x04, 0xA8, - 0x61, 0xE0, 0xE1, 0x3D, 0xFD, 0x9C, 0xFB, 0x19, - 0x1E, 0x80, 0x8C, 0xA0, 0xFC, 0x27, 0x26, 0x3B, - 0x48, 0x6D, 0x07, 0xE4, 0xEA, 0x17, 0x64, 0x9B, - 0xD0, 0xE2, 0xD1, 0x13, 0x39, 0xF5, 0x73, 0xD3, - 0x0C, 0x3A, 0x6E, 0x77, 0xFA, 0xE3, 0x2F, 0x44, - 0x7E, 0x72, 0x30, 0x43, 0xD4, 0x7F, 0x36, 0xD9, - 0xBD, 0x3E, 0x3F, 0x91, 0xBE, 0x54, 0x79, 0xA6, - 0x7C, 0x0E, 0xC5, 0x7A, 0x70, 0xC4, 0xD7, 0xCE, - 0xDA, 0xAA, 0x68, 0x8F, 0xBC, 0x96, 0x1B, 0x16, - 0xA2, 0xC6, 0x67, 0x09, 0x45, 0x9F, 0xCF, 0x41, - 0xC8, 0x60, 0x74, 0x99, 0x5D, 0x85, 0x5F, 0x50, - 0x33, 0x52, 0x22, 0xA9, 0xB5, 0x2D, 0x98, 0x87, - 0x15, 0x9A, 0xAC, 0x2C, 0xDE, 0xC0, 0xB8, 0x37, - 0x88, 0x1F, 0xC1, 0x4F, 0x65, 0x0F, 0x3C, 0x84, - 0x4B, 0x1A, 0xAB, 0xA4, 0x23, 0xCB, 0xB1, 0xC7, - 0xDB, 0xEF, 0x40, 0x0D, 0x46, 0xE8, 0xF4, 0x71, - 0x38, 0x01, 0x5C, 0x0B, 0x5E, 0xC9, 0xAF, 0xC3, - 0xF6, 0xB6, 0x10, 0x1D, 0xE5, 0x8A, 0x90, 0xA7, - 0xA3, 0x05, 0x4E, 0x14, 0x63, 0x25, 0x34, 0xEC, - 0x6B, 0x95, 0x21, 0x55, 0xF2, 0xF0, 0x47, 0x9D, - 0xF8, 0x8E, 0x02, 0x0A, 0xED, 0x97, 0xAE, 0x00, - 0x2A, 0xEB, 0xB2, 0xA5, 0x32, 0x06, 0x2E, 0xFE, - 0x8D, 0x7B, 0x7D, 0x35, 0x5A, 0xD2, 0xF1, 0xE9, - 0xF9, 0x62, 0xB7, 0xB9, 0x53, 0x75, 0x5B, 0x8B, - 0xCC, 0x6C, 0x18, 0x49, 0x89, 0x31, 0xB0, 0x92, - 0x6F, 0xDF, 0x03, 0x57, 0xF3, 0x58, 0xCA, 0x2B, - 0x93, 0xA1, 0xD6, 0x24, 0x29, 0xCD, 0x59, 0x1C, - 0x83, 0xB3, 0x42, 0xBF, 0x82, 0xB4, 0x11, 0x4A, - 0x08, 0xEE, 0x76, 0x4D, 0x12, 0xDC, 0xE6, 0xC2, - 0x56, 0xBA, 0x86, 0x28, 0x6A, 0x20, 0x51, 0xF7, - 0xFF, 0xD8, 0xE7, 0xDD, 0xBB, 0x78, 0xD5, 0x81 }; - -static const unsigned char table_22[32] = { - 0x0B, 0x15, 0x1C, 0x0C, 0x06, 0x0A, 0x1D, 0x16, - 0x12, 0x0E, 0x04, 0x11, 0x1F, 0x0F, 0x07, 0x02, - 0x17, 0x13, 0x19, 0x18, 0x0D, 0x10, 0x1A, 0x05, - 0x03, 0x00, 0x01, 0x08, 0x09, 0x14, 0x1B, 0x1E }; - -static const unsigned char table_23[256] = { - 0x36, 0x53, 0x2D, 0xD0, 0x7A, 0xF0, 0xD5, 0x1C, - 0x50, 0x61, 0x9A, 0x90, 0x0B, 0x29, 0x20, 0x77, - 0xF1, 0x82, 0xFE, 0xC1, 0xA7, 0xB6, 0x78, 0x87, - 0x02, 0x05, 0xCB, 0x28, 0xAE, 0xD6, 0x17, 0x1A, - 0x91, 0x5D, 0xB9, 0xE2, 0xDE, 0x6A, 0x4E, 0x07, - 0xAC, 0x38, 0x13, 0x3B, 0x46, 0xFD, 0xB7, 0xD1, - 0x79, 0xFB, 0x58, 0x76, 0x08, 0x47, 0x95, 0xA6, - 0x99, 0x9E, 0x12, 0x67, 0xC2, 0xED, 0x9C, 0x1B, - 0x89, 0x71, 0xB5, 0x4A, 0xAA, 0x5F, 0x34, 0x85, - 0x40, 0x2B, 0x9F, 0x37, 0x7C, 0x0F, 0xD4, 0x75, - 0x48, 0x27, 0x2E, 0xC9, 0xEB, 0x06, 0xDF, 0x8C, - 0x14, 0xAF, 0xEE, 0xA2, 0x74, 0x45, 0x8D, 0x70, - 0x6B, 0xD7, 0x56, 0xCF, 0xBC, 0x7B, 0x01, 0xC8, - 0x54, 0xB0, 0x3C, 0x39, 0xFA, 0x81, 0xDC, 0xBB, - 0x0D, 0xB2, 0xAD, 0x93, 0xC7, 0x8A, 0x73, 0x6C, - 0xC3, 0x04, 0x2F, 0xEF, 0x52, 0x33, 0x9D, 0x1E, - 0xC5, 0x65, 0x23, 0xD8, 0xB1, 0xD2, 0xE5, 0x25, - 0x2C, 0xE6, 0x92, 0xB4, 0xF7, 0xF4, 0x8F, 0x6E, - 0xE8, 0x5A, 0x8E, 0x7D, 0x4C, 0xB3, 0xFF, 0x41, - 0x26, 0xE3, 0x30, 0x69, 0xF8, 0x80, 0x57, 0x4F, - 0xA0, 0x7F, 0x66, 0x68, 0xE1, 0x7E, 0x0E, 0x31, - 0xE7, 0xEA, 0x3E, 0x8B, 0x4B, 0x94, 0xE9, 0xCD, - 0x19, 0x35, 0xA3, 0x98, 0xD9, 0x5B, 0x44, 0x2A, - 0xE0, 0x6D, 0xF3, 0xE4, 0x72, 0x18, 0x03, 0x59, - 0x84, 0x09, 0xA1, 0x9B, 0xBD, 0xDA, 0x4D, 0x63, - 0xCC, 0x3A, 0x10, 0xFC, 0x3F, 0x0A, 0x88, 0x24, - 0xF5, 0x21, 0xC4, 0x6F, 0x1F, 0x42, 0x62, 0x64, - 0x51, 0xDD, 0xCA, 0xF9, 0x22, 0xCE, 0xA8, 0x86, - 0xBA, 0xB8, 0x5C, 0xAB, 0x32, 0x00, 0x0C, 0xF2, - 0x83, 0xDB, 0xF6, 0x60, 0x3D, 0x16, 0xEC, 0x11, - 0xA4, 0xBE, 0x96, 0x5E, 0x97, 0xD3, 0xA5, 0x55, - 0x1D, 0x15, 0xC6, 0xBF, 0xA9, 0x43, 0xC0, 0x49 }; - -static const unsigned char table_24[256] = { - 0xDC, 0x5A, 0xE6, 0x59, 0x64, 0xDA, 0x58, 0x40, - 0x95, 0xF8, 0x2A, 0xE0, 0x39, 0x7E, 0x32, 0x89, - 0x09, 0x93, 0xED, 0x55, 0xC3, 0x5B, 0x1A, 0xD1, - 0xA5, 0x8B, 0x0F, 0x13, 0xC9, 0xE1, 0x34, 0xD0, - 0xB6, 0xA2, 0xD9, 0x52, 0x57, 0x83, 0xFD, 0xE9, - 0xAC, 0x73, 0x6E, 0x21, 0xF1, 0x0E, 0x25, 0xCC, - 0x36, 0xFB, 0xF7, 0x92, 0x15, 0x30, 0x54, 0x91, - 0xD6, 0x9E, 0xAA, 0x35, 0x70, 0xB2, 0xC0, 0x27, - 0xFE, 0x04, 0xBC, 0xC7, 0x02, 0xFA, 0x7D, 0xE3, - 0xBE, 0x62, 0x79, 0x2B, 0x31, 0x6A, 0x8F, 0x7F, - 0x56, 0xF0, 0xB4, 0x0C, 0x1F, 0x68, 0xB7, 0xB9, - 0x0B, 0x14, 0x3E, 0xA9, 0x4B, 0x03, 0x10, 0xEE, - 0x2C, 0xAB, 0x8A, 0x77, 0xB1, 0xE7, 0xCA, 0xD4, - 0x98, 0x01, 0xAD, 0x1E, 0x50, 0x26, 0x82, 0x44, - 0xF3, 0xBF, 0xD3, 0x6B, 0x33, 0x0A, 0x3C, 0x5D, - 0xCE, 0x81, 0xC5, 0x78, 0x9F, 0xB8, 0x23, 0xDB, - 0x4E, 0xA1, 0x41, 0x76, 0xAE, 0x51, 0x86, 0x06, - 0x7A, 0x66, 0xA0, 0x5E, 0x29, 0x17, 0x84, 0x4A, - 0xB0, 0x3B, 0x3D, 0x71, 0x07, 0x7B, 0x0D, 0x9A, - 0x6F, 0x9B, 0x5C, 0x88, 0xB3, 0xD7, 0x24, 0xD5, - 0x48, 0xF5, 0xE8, 0xE4, 0xCF, 0x16, 0xA4, 0xC8, - 0xEF, 0x42, 0x22, 0xEC, 0x47, 0x69, 0x90, 0x63, - 0xE2, 0x1B, 0x87, 0x85, 0x3F, 0xDE, 0x8C, 0x60, - 0x99, 0xE5, 0x8E, 0x4F, 0xF4, 0xBA, 0xB5, 0x9C, - 0x37, 0x67, 0xBD, 0xA6, 0x97, 0xDD, 0xCB, 0x43, - 0x45, 0x19, 0x49, 0x1C, 0x75, 0xC1, 0xBB, 0xF2, - 0x46, 0xFC, 0x53, 0x9D, 0xD8, 0xA3, 0xDF, 0x2F, - 0xEB, 0x72, 0x94, 0xA8, 0x6D, 0xC6, 0x28, 0x4C, - 0x00, 0x38, 0xC2, 0x65, 0x05, 0x2E, 0xD2, 0x12, - 0xFF, 0x18, 0x61, 0x6C, 0x7C, 0x11, 0xAF, 0x96, - 0xCD, 0x20, 0x74, 0x08, 0x1D, 0xC4, 0xF9, 0x4D, - 0xEA, 0x8D, 0x2D, 0x5F, 0xF6, 0xA7, 0x80, 0x3A }; - -static const unsigned char table_25[32] = { - 0x0A, 0x11, 0x17, 0x03, 0x05, 0x0B, 0x18, 0x13, - 0x09, 0x02, 0x00, 0x1C, 0x0C, 0x08, 0x1B, 0x14, - 0x06, 0x0E, 0x01, 0x0D, 0x16, 0x1E, 0x1D, 0x19, - 0x0F, 0x1A, 0x10, 0x04, 0x12, 0x15, 0x07, 0x1F }; - -static const unsigned char table_26[32] = { - 0x19, 0x13, 0x1B, 0x01, 0x1C, 0x0D, 0x0C, 0x15, - 0x0B, 0x00, 0x1A, 0x0F, 0x12, 0x16, 0x08, 0x0A, - 0x03, 0x06, 0x14, 0x10, 0x18, 0x04, 0x11, 0x1D, - 0x1F, 0x07, 0x17, 0x05, 0x02, 0x0E, 0x1E, 0x09 }; - -static const unsigned char table_27[256] = { - 0x72, 0xF0, 0x14, 0xCB, 0x61, 0xA5, 0xB2, 0x02, - 0x75, 0x22, 0xC3, 0x9D, 0x5A, 0x63, 0xFA, 0x5F, - 0xD9, 0x55, 0x58, 0x43, 0x24, 0x7D, 0x77, 0x93, - 0xBA, 0x50, 0x1D, 0xF7, 0x49, 0x18, 0xB0, 0x42, - 0xBB, 0xEC, 0x52, 0x38, 0xDC, 0xC8, 0x16, 0x54, - 0x17, 0x19, 0x89, 0x67, 0x33, 0x3C, 0x0A, 0xAD, - 0xC9, 0xDE, 0x81, 0xED, 0xBD, 0x0E, 0x0B, 0x6D, - 0x46, 0x30, 0x35, 0x2B, 0x8C, 0xA0, 0x1C, 0x0D, - 0xFD, 0xA1, 0x70, 0xC6, 0xD8, 0x41, 0xB3, 0xC0, - 0x44, 0xEB, 0x92, 0xBE, 0x6B, 0x98, 0x1A, 0x76, - 0x71, 0xC5, 0x51, 0x56, 0x80, 0xFC, 0x01, 0x53, - 0x4B, 0xD0, 0x8B, 0xD2, 0x7B, 0xE7, 0x15, 0x5D, - 0xE5, 0xA6, 0x8A, 0xD3, 0x9B, 0xF4, 0x69, 0x23, - 0xE8, 0xB6, 0xC7, 0xE2, 0x73, 0x9F, 0x88, 0xDF, - 0xB4, 0x28, 0xEE, 0xC2, 0x94, 0xB8, 0xF9, 0x7F, - 0x4A, 0x57, 0x06, 0xF6, 0xBF, 0xC1, 0xAB, 0xFB, - 0xA4, 0x8E, 0xD1, 0xD7, 0xF5, 0x7C, 0xA3, 0x1E, - 0x3B, 0x32, 0x03, 0xAA, 0x90, 0x5C, 0x48, 0xE0, - 0xE3, 0xCF, 0xD4, 0xEF, 0x59, 0xD5, 0x1B, 0x34, - 0x1F, 0x95, 0xCE, 0x7A, 0x20, 0x26, 0x87, 0xB7, - 0x78, 0x9C, 0x4F, 0xA2, 0x12, 0x97, 0x27, 0x3F, - 0xFF, 0x07, 0x84, 0x96, 0x04, 0xAF, 0xA8, 0xEA, - 0x2C, 0x6C, 0xAE, 0x37, 0x91, 0xA9, 0x10, 0xDB, - 0xCD, 0xDA, 0x08, 0x99, 0xF1, 0x4D, 0xCC, 0x68, - 0x79, 0x2E, 0xB1, 0x39, 0x9E, 0xE9, 0x2F, 0x6A, - 0x3D, 0x0F, 0x85, 0x8D, 0xCA, 0x29, 0x86, 0xD6, - 0xDD, 0x05, 0x25, 0x3A, 0x40, 0x21, 0x45, 0xAC, - 0x11, 0xF3, 0xA7, 0x09, 0x2A, 0x31, 0xE4, 0x0C, - 0xF8, 0x6E, 0x3E, 0xB5, 0x82, 0xFE, 0x74, 0x13, - 0x65, 0xE1, 0x2D, 0x8F, 0xE6, 0xC4, 0x00, 0x5B, - 0x4E, 0xB9, 0x66, 0xF2, 0x62, 0x36, 0x4C, 0x83, - 0x5E, 0x6F, 0x47, 0x64, 0xBC, 0x9A, 0x60, 0x7E }; - -static const unsigned char table_28[32] = { - 0x15, 0x05, 0x08, 0x19, 0x02, 0x18, 0x1E, 0x07, - 0x0D, 0x0C, 0x1A, 0x06, 0x17, 0x03, 0x10, 0x09, - 0x01, 0x11, 0x1C, 0x04, 0x0F, 0x1F, 0x12, 0x0B, - 0x1B, 0x13, 0x0A, 0x16, 0x0E, 0x00, 0x1D, 0x14 }; - -static const unsigned char table_29[256] = { - 0x34, 0x59, 0x05, 0x13, 0x09, 0x1D, 0xDF, 0x77, - 0x11, 0xA5, 0x92, 0x27, 0xCD, 0x7B, 0x5E, 0x80, - 0xF9, 0x50, 0x18, 0x24, 0xD4, 0x70, 0x4A, 0x39, - 0x66, 0xA4, 0xDB, 0xE9, 0xED, 0x48, 0xD9, 0xE7, - 0x32, 0xDA, 0x53, 0x8F, 0x72, 0xE1, 0xF6, 0xFE, - 0xD3, 0xAD, 0xA6, 0x1F, 0xB9, 0xD1, 0x0F, 0x4C, - 0x23, 0x90, 0x68, 0xBC, 0x4B, 0x9B, 0x3D, 0xAB, - 0xF0, 0x94, 0x4F, 0x1C, 0x07, 0x65, 0x7F, 0x01, - 0x5C, 0xD7, 0x21, 0x8C, 0xBF, 0x8E, 0xB8, 0x86, - 0x6C, 0x33, 0x36, 0xC1, 0x06, 0x74, 0x37, 0x84, - 0x41, 0xAE, 0x67, 0x29, 0xB4, 0x85, 0xCE, 0x2A, - 0xCB, 0x1E, 0x61, 0x9E, 0x7A, 0x44, 0x3E, 0x89, - 0x14, 0x20, 0x19, 0xBB, 0xE0, 0xAA, 0xCF, 0x83, - 0xA8, 0x93, 0x43, 0xF2, 0xAC, 0x0E, 0xD2, 0xCC, - 0xDD, 0x47, 0x58, 0xC9, 0xCA, 0x1B, 0x54, 0x6E, - 0x8A, 0x79, 0xF8, 0xC4, 0xFB, 0xD5, 0x91, 0xDE, - 0x12, 0x31, 0x99, 0xFA, 0x6D, 0xC8, 0x57, 0xEC, - 0xB7, 0x28, 0x0C, 0x52, 0xF1, 0x0D, 0xB1, 0x9A, - 0x26, 0x98, 0x16, 0x7D, 0xD0, 0x2E, 0x8B, 0xD8, - 0xE6, 0xE8, 0x30, 0xFD, 0x7C, 0x64, 0x5A, 0xBD, - 0x87, 0xE2, 0xA1, 0x3F, 0xC3, 0x38, 0x96, 0xA3, - 0x2D, 0xF3, 0x3A, 0xEE, 0xC0, 0x10, 0xEA, 0x6F, - 0x8D, 0x03, 0xF4, 0x51, 0x97, 0x7E, 0x56, 0x42, - 0x3C, 0x5D, 0x5F, 0xF5, 0x6A, 0xAF, 0xE4, 0xBE, - 0xBA, 0x78, 0xA0, 0x5B, 0x49, 0xA7, 0xC7, 0x9C, - 0x63, 0x6B, 0x00, 0x17, 0x69, 0x75, 0x3B, 0x40, - 0xEF, 0x45, 0xB5, 0x2B, 0x2F, 0x02, 0xC6, 0x22, - 0x9F, 0xFC, 0x73, 0x08, 0x81, 0xB2, 0x2C, 0x71, - 0x35, 0xA2, 0xE3, 0xB3, 0x9D, 0xC5, 0x0A, 0xC2, - 0x25, 0x82, 0xDC, 0x88, 0xA9, 0xE5, 0xF7, 0xEB, - 0xD6, 0x60, 0x76, 0x55, 0x0B, 0x4E, 0xFF, 0x1A, - 0x46, 0x62, 0xB6, 0xB0, 0x15, 0x04, 0x95, 0x4D }; - -static const unsigned char table_30[32] = { - 0x00, 0x1C, 0x0E, 0x0C, 0x06, 0x16, 0x09, 0x12, - 0x01, 0x13, 0x0B, 0x14, 0x11, 0x08, 0x04, 0x18, - 0x10, 0x1B, 0x15, 0x03, 0x02, 0x19, 0x1A, 0x17, - 0x1E, 0x1F, 0x0F, 0x07, 0x0D, 0x05, 0x1D, 0x0A }; - -static const unsigned char table_31[256] = { - 0xDF, 0xD8, 0x3F, 0xBC, 0x5F, 0xC9, 0x8E, 0x4C, - 0x0B, 0x3C, 0xE5, 0xBF, 0x39, 0xD5, 0x30, 0xDD, - 0x23, 0xC7, 0x72, 0x63, 0x1F, 0xF8, 0x96, 0x31, - 0x70, 0xD6, 0x9E, 0xE8, 0x9D, 0xF5, 0xEF, 0x65, - 0xC2, 0x50, 0x62, 0x77, 0xD3, 0x6C, 0x1A, 0x91, - 0xBB, 0xFF, 0xCD, 0x9B, 0xB6, 0xBA, 0xB8, 0x7A, - 0x14, 0xA7, 0x74, 0x89, 0xD4, 0x6E, 0x19, 0x69, - 0xAB, 0x01, 0x15, 0x0E, 0x87, 0x55, 0x79, 0x1C, - 0x18, 0xBE, 0xA8, 0xDB, 0x52, 0xD2, 0x8F, 0x7E, - 0x81, 0xAF, 0xFD, 0x5C, 0x3E, 0x1B, 0xB9, 0xB2, - 0xB7, 0x51, 0x57, 0x8C, 0xCF, 0x5B, 0xA4, 0x75, - 0xDE, 0x22, 0x8B, 0x10, 0x12, 0xC8, 0x35, 0x2D, - 0x45, 0xB5, 0xF0, 0x47, 0x88, 0x16, 0xEB, 0x67, - 0xD9, 0x0C, 0xF1, 0xC1, 0x34, 0x33, 0xC6, 0x78, - 0xB3, 0x26, 0xE3, 0xBD, 0x5D, 0x4E, 0x66, 0xE4, - 0xD7, 0xC4, 0xE6, 0xA1, 0xB0, 0x95, 0x2B, 0x9A, - 0x4A, 0x3A, 0xCB, 0x40, 0xE1, 0x60, 0x49, 0xCC, - 0x03, 0xAC, 0xF4, 0x97, 0x32, 0x0F, 0x38, 0x17, - 0xF9, 0xE0, 0xD1, 0xFB, 0x04, 0x5E, 0x68, 0x06, - 0xAE, 0xFA, 0xAA, 0xED, 0x24, 0x0D, 0x00, 0x61, - 0x20, 0xA3, 0x7B, 0x6B, 0x76, 0x27, 0xEA, 0xCE, - 0x6A, 0x82, 0x9F, 0x6D, 0x9C, 0x64, 0xA2, 0x11, - 0x37, 0x2A, 0xCA, 0x84, 0x25, 0x7C, 0x2F, 0x8D, - 0x90, 0xE7, 0x09, 0x93, 0xF3, 0x43, 0x71, 0xEC, - 0xA9, 0x7D, 0x94, 0xA6, 0x3D, 0x7F, 0x54, 0x44, - 0x99, 0x80, 0x41, 0xC0, 0xA0, 0x8A, 0x1E, 0xDC, - 0x08, 0xD0, 0x2E, 0x42, 0x05, 0x85, 0x86, 0xFE, - 0x3B, 0x59, 0xC3, 0x58, 0x13, 0xB4, 0x36, 0xA5, - 0x73, 0x28, 0x29, 0xDA, 0x4F, 0x1D, 0xB1, 0x53, - 0x46, 0x2C, 0xF2, 0x4D, 0xAD, 0xFC, 0x83, 0x02, - 0x6F, 0x07, 0xE9, 0xEE, 0x21, 0x98, 0x5A, 0xC5, - 0x92, 0x48, 0xF7, 0x0A, 0xF6, 0xE2, 0x4B, 0x56 }; - -static const unsigned char table_32[256] = { - 0x7B, 0x0F, 0x56, 0x2F, 0x1E, 0x2A, 0x7A, 0xD1, - 0x02, 0x91, 0x4E, 0x37, 0x6C, 0x10, 0xA7, 0xF2, - 0x38, 0xAC, 0x9E, 0x2B, 0x5E, 0x23, 0xE3, 0x19, - 0x9B, 0xF6, 0xB0, 0x59, 0x14, 0xB9, 0xA9, 0x46, - 0x84, 0x1D, 0xC0, 0x98, 0xF3, 0xE1, 0xE8, 0x94, - 0x52, 0x35, 0xBA, 0xD8, 0x07, 0xEF, 0x31, 0xF8, - 0x03, 0x76, 0x9C, 0xD7, 0xE4, 0x8B, 0xAF, 0x60, - 0xDD, 0x51, 0x00, 0xDF, 0x11, 0x7F, 0x1C, 0xED, - 0x49, 0xC9, 0xF4, 0x87, 0x64, 0xFC, 0x5D, 0xAD, - 0x88, 0x85, 0xF7, 0x5A, 0x92, 0xDB, 0x72, 0x1A, - 0x83, 0x15, 0x30, 0x24, 0x9F, 0xFF, 0x5B, 0xF1, - 0xD2, 0xFD, 0xC2, 0xB5, 0x25, 0x22, 0x18, 0x3D, - 0xCD, 0x97, 0x8C, 0xCC, 0x78, 0x90, 0xAA, 0x5F, - 0x0A, 0x57, 0x05, 0x61, 0xD4, 0xA0, 0x3A, 0xDE, - 0x3B, 0xF9, 0x65, 0x68, 0x4F, 0x28, 0xFA, 0xEB, - 0x63, 0x2D, 0x8D, 0xD0, 0xA1, 0xFE, 0x12, 0x96, - 0x3C, 0x42, 0x29, 0xD6, 0xA4, 0x34, 0xBD, 0x70, - 0x89, 0xBE, 0xF5, 0x79, 0xAB, 0x8F, 0x32, 0xB4, - 0xEE, 0xE7, 0x2C, 0x04, 0x4B, 0xD5, 0xB1, 0x54, - 0xF0, 0xDA, 0x16, 0x77, 0xA6, 0x53, 0xB2, 0xE2, - 0x73, 0xBF, 0x17, 0xA8, 0x75, 0x26, 0xE0, 0xBC, - 0x0C, 0x71, 0xFB, 0x6D, 0x7E, 0xC5, 0xEA, 0x21, - 0x9D, 0x95, 0x8E, 0xA5, 0x48, 0xB8, 0x7D, 0xCB, - 0x01, 0x99, 0xE5, 0xBB, 0x82, 0xC4, 0xCA, 0xC1, - 0x58, 0x6E, 0x5C, 0x7C, 0xDC, 0x33, 0xB6, 0xC3, - 0x09, 0xC7, 0x1F, 0x0D, 0x43, 0x6F, 0xE9, 0x86, - 0x27, 0xC8, 0x44, 0xB3, 0xD3, 0xCF, 0x08, 0x66, - 0x1B, 0x20, 0x4D, 0xD9, 0xC6, 0x36, 0x40, 0x74, - 0x62, 0x6A, 0x55, 0xEC, 0x06, 0x2E, 0xE6, 0x80, - 0x13, 0x93, 0x50, 0xCE, 0x69, 0x3E, 0x67, 0x4A, - 0x81, 0x4C, 0x0B, 0x3F, 0xB7, 0x0E, 0x39, 0xAE, - 0x47, 0x6B, 0x8A, 0xA2, 0x9A, 0xA3, 0x45, 0x41 }; - -static const unsigned char table_33[256] = { - 0xDE, 0xD3, 0x79, 0x67, 0x13, 0x5C, 0x04, 0xF2, - 0xD9, 0x9F, 0x65, 0x56, 0xCC, 0x3B, 0xA4, 0x9A, - 0x08, 0xBF, 0x26, 0xB2, 0xA7, 0x5E, 0xAA, 0xCA, - 0xBB, 0x2B, 0x38, 0x3F, 0xD8, 0x87, 0xFA, 0x5D, - 0x73, 0x8E, 0x1E, 0x93, 0x05, 0xAF, 0x3E, 0x4E, - 0x90, 0xDB, 0x0B, 0x33, 0x0D, 0x2F, 0x86, 0x4F, - 0xFD, 0xD0, 0x39, 0xB1, 0x8A, 0x1A, 0x20, 0xE6, - 0xCF, 0xA2, 0x82, 0xDF, 0x42, 0x9C, 0x30, 0x40, - 0xE3, 0xB0, 0x88, 0x5A, 0xEC, 0x25, 0xE2, 0xC4, - 0x12, 0x54, 0x50, 0x97, 0x96, 0x21, 0x23, 0x7B, - 0x1D, 0x61, 0x52, 0x34, 0x7D, 0x69, 0x16, 0xC3, - 0x31, 0xF8, 0x48, 0x19, 0x95, 0x01, 0x29, 0x8C, - 0x15, 0xAC, 0x84, 0x74, 0xAB, 0x70, 0xDA, 0x36, - 0xD6, 0x8F, 0xFE, 0x35, 0xD7, 0x2E, 0x89, 0x07, - 0x62, 0x17, 0xDC, 0x92, 0x45, 0x83, 0xB5, 0xE5, - 0x8B, 0xC0, 0x27, 0x85, 0x7C, 0x9D, 0x55, 0x81, - 0x71, 0xCD, 0xC9, 0x00, 0x02, 0xC1, 0x0A, 0x37, - 0xED, 0xEA, 0xC2, 0x98, 0x49, 0x06, 0x1C, 0x78, - 0x64, 0xCE, 0x9E, 0x4C, 0x7A, 0xB4, 0x43, 0x0F, - 0xE0, 0x7E, 0xBC, 0x5B, 0x51, 0xE7, 0x18, 0xF9, - 0x11, 0xA1, 0xF5, 0xC7, 0xCB, 0x4D, 0x6A, 0x0E, - 0x57, 0xF1, 0xFB, 0xB3, 0x99, 0xF0, 0x32, 0xD5, - 0xA9, 0x4B, 0x6F, 0x6D, 0xA8, 0xC5, 0xDD, 0x7F, - 0xEB, 0xBE, 0xFC, 0x2C, 0x22, 0x58, 0x03, 0x9B, - 0x77, 0xF7, 0xBD, 0xBA, 0xD2, 0x6B, 0xAD, 0x5F, - 0x10, 0x6E, 0x09, 0xD1, 0x1B, 0x24, 0xEF, 0x72, - 0x3D, 0x59, 0x28, 0xE1, 0xB7, 0x44, 0x8D, 0xB8, - 0xAE, 0x2D, 0x60, 0xA6, 0xC8, 0x0C, 0xF4, 0x41, - 0xA3, 0x68, 0x46, 0x6C, 0x76, 0xA0, 0xB6, 0x66, - 0xE4, 0x1F, 0x75, 0x4A, 0xFF, 0x2A, 0x94, 0xD4, - 0xF3, 0xE9, 0x91, 0x63, 0xA5, 0xB9, 0xE8, 0x14, - 0x80, 0x3C, 0xEE, 0x47, 0xC6, 0x3A, 0x53, 0xF6 }; - -static const unsigned char table_34[256] = { - 0xF0, 0xE9, 0x3E, 0xD6, 0x89, 0xC8, 0xC7, 0x23, - 0x75, 0x26, 0x5F, 0x9C, 0x57, 0xB8, 0x2A, 0x29, - 0xE5, 0xB5, 0x68, 0xA4, 0x92, 0x46, 0x40, 0x7F, - 0xF2, 0xBC, 0x6A, 0xE0, 0x8F, 0x0F, 0xE4, 0x3A, - 0xE1, 0x30, 0x84, 0x6E, 0x82, 0x8E, 0x56, 0xC5, - 0x32, 0x85, 0xFB, 0x59, 0x43, 0x41, 0xC2, 0xF6, - 0x67, 0x5A, 0x7C, 0x34, 0xA1, 0xD0, 0x4B, 0xAC, - 0x61, 0x72, 0x6B, 0xAF, 0xC4, 0x20, 0x9A, 0xD4, - 0x74, 0x8D, 0x87, 0x83, 0xE2, 0x62, 0x6D, 0xE6, - 0xE7, 0xF9, 0x76, 0xCB, 0x18, 0x90, 0x4F, 0xFF, - 0xD3, 0x3C, 0x08, 0x79, 0x93, 0x2D, 0x95, 0xA3, - 0xDD, 0x5B, 0xDA, 0x7A, 0x39, 0x4D, 0xC1, 0x2E, - 0xCC, 0x53, 0xE8, 0xA2, 0xCF, 0x15, 0x78, 0x1C, - 0xEB, 0x9B, 0x7B, 0xAD, 0x31, 0x2F, 0xE3, 0xC9, - 0x3B, 0xEC, 0x2C, 0x49, 0x02, 0x52, 0x28, 0xBA, - 0x0C, 0x19, 0x24, 0xF7, 0x97, 0x09, 0xA6, 0xA0, - 0xDF, 0xD1, 0xD2, 0xDC, 0x51, 0xA5, 0x94, 0xFD, - 0x71, 0xF5, 0x50, 0x0A, 0x69, 0x25, 0x88, 0x5C, - 0x91, 0xD5, 0x47, 0x0B, 0x27, 0x13, 0x96, 0xD9, - 0xF1, 0xA9, 0x70, 0xC3, 0xBE, 0x42, 0x4E, 0x4A, - 0xB1, 0x07, 0xA7, 0x54, 0xFE, 0x48, 0x9F, 0x63, - 0x17, 0xAE, 0xB9, 0x58, 0x21, 0x35, 0xED, 0x5D, - 0x9D, 0x3D, 0xB4, 0xFC, 0xEA, 0x8C, 0x80, 0xA8, - 0x1E, 0xB0, 0xDE, 0x0D, 0x11, 0x6F, 0x04, 0x12, - 0xF4, 0x10, 0x64, 0x0E, 0xD7, 0x2B, 0xB3, 0x8B, - 0xB7, 0x01, 0x86, 0xCA, 0xFA, 0x9E, 0xEE, 0x66, - 0x37, 0x65, 0x81, 0x38, 0x1F, 0xAA, 0x73, 0xAB, - 0xBD, 0xDB, 0x14, 0xCD, 0x00, 0xBB, 0x98, 0x44, - 0x45, 0xB6, 0x99, 0x5E, 0xD8, 0x1D, 0x36, 0xF8, - 0x55, 0x6C, 0x16, 0x7E, 0x77, 0x3F, 0x22, 0xEF, - 0xF3, 0x7D, 0xC6, 0xCE, 0x8A, 0xB2, 0x33, 0x4C, - 0x03, 0x05, 0xBF, 0x06, 0x1B, 0xC0, 0x1A, 0x60 }; - -static const unsigned char table_35[256] = { - 0xCC, 0x40, 0xEF, 0x1F, 0xDB, 0xE5, 0x71, 0x51, - 0x3B, 0x0F, 0x7D, 0x9C, 0x83, 0x17, 0x6F, 0x8F, - 0x13, 0xDC, 0x7F, 0xA9, 0xA5, 0xA2, 0x9D, 0xDF, - 0xE7, 0x97, 0x2A, 0x30, 0xF2, 0x73, 0xCF, 0x87, - 0x29, 0xB3, 0x86, 0x43, 0x09, 0xB0, 0x2E, 0x10, - 0x8E, 0xBC, 0x57, 0xBA, 0x68, 0xF5, 0xCB, 0x89, - 0x32, 0xC1, 0x6B, 0x1E, 0xAC, 0xB2, 0x2D, 0x6A, - 0x50, 0xEB, 0x18, 0x06, 0xD8, 0xC7, 0x36, 0x31, - 0xC5, 0xAF, 0x12, 0x15, 0xB7, 0x37, 0x4E, 0x01, - 0x14, 0x21, 0x44, 0x5E, 0xF4, 0xB4, 0xE4, 0x65, - 0xFE, 0x8A, 0xEA, 0x0D, 0xBB, 0x45, 0x8B, 0x25, - 0x80, 0x35, 0x61, 0xA8, 0x4A, 0x47, 0xAB, 0x91, - 0x1B, 0x1C, 0x05, 0x4D, 0x5A, 0xD4, 0xF1, 0x9B, - 0x0E, 0x98, 0xCA, 0x96, 0x42, 0x7E, 0x03, 0x5F, - 0xE2, 0x90, 0xBF, 0x82, 0xC9, 0x3D, 0xE0, 0x5C, - 0xFA, 0x3E, 0x41, 0x11, 0x79, 0x58, 0x24, 0x2C, - 0xC0, 0x28, 0x5D, 0xA3, 0xDE, 0x67, 0xFF, 0xA4, - 0x63, 0xB1, 0x22, 0x04, 0xFD, 0x70, 0x39, 0x46, - 0xAA, 0x0A, 0x34, 0x6C, 0xD7, 0x92, 0xA1, 0x3C, - 0x19, 0xD5, 0xFC, 0xAD, 0x85, 0x07, 0x00, 0x23, - 0xF8, 0x69, 0x56, 0x53, 0x55, 0x7A, 0xB8, 0xC8, - 0xDA, 0xCE, 0xF3, 0x5B, 0x49, 0xE1, 0xBE, 0xEC, - 0x1A, 0x88, 0x02, 0xBD, 0xF7, 0x1D, 0x64, 0xA0, - 0x4F, 0xD9, 0xE3, 0x95, 0xC6, 0x48, 0x2B, 0xED, - 0x9A, 0x9E, 0x26, 0x6E, 0xD1, 0x94, 0xB9, 0x93, - 0xDD, 0xF6, 0xA6, 0xFB, 0xC2, 0xB6, 0x0C, 0xE9, - 0x77, 0xF9, 0xCD, 0x08, 0xEE, 0x3F, 0xE6, 0x75, - 0xD6, 0x84, 0x76, 0x8C, 0xF0, 0xAE, 0xD2, 0x78, - 0x2F, 0x4B, 0x16, 0x4C, 0x27, 0x81, 0x6D, 0x99, - 0x38, 0xD3, 0x54, 0x62, 0x74, 0x20, 0x60, 0xC3, - 0x7C, 0x8D, 0x72, 0x0B, 0x52, 0xE8, 0xA7, 0x3A, - 0x59, 0xC4, 0x9F, 0xD0, 0x66, 0x7B, 0x33, 0xB5 }; - -static const unsigned char table_36[256] = { - 0xDB, 0x6F, 0xFE, 0xB3, 0x5C, 0x1F, 0xB8, 0xBF, - 0xA3, 0x71, 0x11, 0x56, 0x90, 0xE2, 0x63, 0x18, - 0x83, 0x51, 0x21, 0xEB, 0x66, 0x08, 0xA6, 0xA5, - 0x1C, 0xF5, 0x14, 0x24, 0x41, 0x33, 0xA7, 0xB5, - 0xC7, 0x79, 0x57, 0x50, 0x85, 0xE1, 0x6D, 0xF7, - 0x0E, 0xDE, 0x67, 0xAB, 0xA1, 0x0B, 0xD9, 0x4A, - 0xCA, 0x36, 0xEA, 0xDA, 0x16, 0xEF, 0x9F, 0x0A, - 0x09, 0x9A, 0x1D, 0xC5, 0xD7, 0x5F, 0x19, 0xDC, - 0x15, 0x06, 0xE8, 0x94, 0x0C, 0x0D, 0xC9, 0x7C, - 0xD6, 0x62, 0xBB, 0x49, 0xF9, 0x61, 0x07, 0x9B, - 0x28, 0xC3, 0x9E, 0xF4, 0x38, 0x78, 0x20, 0x03, - 0xA2, 0x7F, 0xC2, 0x9D, 0x5E, 0x65, 0x52, 0x17, - 0x2E, 0x1B, 0xB0, 0x42, 0xBC, 0xFD, 0xF1, 0xD2, - 0xF6, 0x60, 0xD3, 0x29, 0x97, 0x3D, 0x0F, 0xB1, - 0x2F, 0x22, 0xDD, 0x80, 0x32, 0xF8, 0xAD, 0x70, - 0xB9, 0x8F, 0x37, 0xCE, 0x46, 0x58, 0xB7, 0x30, - 0xED, 0x7A, 0xE9, 0xC0, 0x7D, 0x13, 0x64, 0x23, - 0x4E, 0xC8, 0xF0, 0xCC, 0x3B, 0x45, 0x68, 0x8D, - 0xBE, 0x8B, 0xD8, 0x43, 0x02, 0x27, 0xE4, 0xAA, - 0x10, 0xF2, 0x59, 0x72, 0x40, 0x26, 0x69, 0xE5, - 0x05, 0x84, 0x4F, 0xE0, 0x6B, 0xC1, 0xAC, 0x4C, - 0xFB, 0x31, 0x77, 0x8E, 0xD4, 0x12, 0xA9, 0xB4, - 0xEC, 0x00, 0x76, 0x1E, 0x25, 0xAE, 0xE7, 0x3C, - 0x35, 0x93, 0x9C, 0xC4, 0xFC, 0x2D, 0x91, 0x04, - 0xAF, 0x53, 0x3F, 0xE6, 0xA4, 0xD0, 0x1A, 0xDF, - 0x3A, 0x55, 0x99, 0x01, 0xCB, 0x6C, 0x82, 0x3E, - 0x5D, 0xA8, 0x88, 0x54, 0x5B, 0x95, 0xCD, 0x8C, - 0x81, 0x34, 0xD1, 0x39, 0xFF, 0xEE, 0xFA, 0x8A, - 0x6E, 0x86, 0x92, 0x89, 0xF3, 0x6A, 0xBA, 0x2C, - 0xD5, 0x44, 0xC6, 0x96, 0xBD, 0xB2, 0x2B, 0x87, - 0x74, 0xA0, 0x73, 0x5A, 0x2A, 0x98, 0x75, 0x47, - 0x4B, 0xB6, 0x7B, 0x4D, 0xCF, 0x7E, 0x48, 0xE3 }; - -static const unsigned char table_37[256] = { - 0x1F, 0xD6, 0xB1, 0xB3, 0x40, 0xAD, 0xDE, 0xB7, - 0x19, 0xB4, 0xE7, 0x0B, 0x9C, 0x2D, 0xE0, 0xF5, - 0xCF, 0x2C, 0x30, 0x65, 0x2F, 0xCD, 0x02, 0x91, - 0xCE, 0x2B, 0xBF, 0x78, 0xE6, 0xFA, 0x51, 0x48, - 0xFB, 0x4D, 0xBE, 0x71, 0x1A, 0x56, 0xFD, 0x81, - 0x33, 0x75, 0x89, 0x96, 0x37, 0x82, 0x9E, 0x93, - 0x41, 0x18, 0x5B, 0x2E, 0x22, 0x0F, 0xAF, 0x4B, - 0xB9, 0xD5, 0xEE, 0x6C, 0xE4, 0x05, 0xCC, 0x99, - 0xE5, 0x3B, 0x62, 0xBD, 0x7B, 0xAA, 0x4A, 0xE2, - 0x34, 0x43, 0xF7, 0x39, 0xFE, 0x14, 0x1D, 0xE3, - 0xF0, 0xA7, 0x77, 0xDF, 0xA0, 0xD3, 0xAC, 0xD9, - 0xEA, 0x76, 0xDD, 0xA4, 0xC5, 0xC9, 0x61, 0xF3, - 0xA8, 0xB0, 0x35, 0xE8, 0x68, 0xD4, 0x15, 0xF9, - 0x97, 0xED, 0x25, 0x0A, 0x88, 0x8F, 0x06, 0xA3, - 0x16, 0x36, 0x32, 0xA2, 0xC6, 0x64, 0xD7, 0x94, - 0xD2, 0x6D, 0x74, 0xFC, 0x44, 0x27, 0x5C, 0xFF, - 0x60, 0x1E, 0x58, 0x8B, 0x5E, 0xC7, 0x90, 0x17, - 0x63, 0xAE, 0xC3, 0x12, 0x13, 0x84, 0xEC, 0x49, - 0xA5, 0x9B, 0x31, 0x8D, 0xE1, 0x79, 0xF1, 0x00, - 0x28, 0x3D, 0xC2, 0x55, 0x20, 0x52, 0x95, 0x7E, - 0x42, 0x1C, 0x66, 0x92, 0x7D, 0xB6, 0xC4, 0xF4, - 0x80, 0xB2, 0x72, 0x6E, 0x11, 0xF6, 0x0D, 0x5A, - 0xEF, 0x9D, 0x69, 0x9A, 0x45, 0x67, 0x3F, 0xDA, - 0x8E, 0x57, 0x09, 0x7C, 0x38, 0xA6, 0x83, 0x87, - 0x7A, 0x08, 0x4C, 0x5F, 0x85, 0x7F, 0xD0, 0x04, - 0x50, 0xCB, 0xB8, 0x07, 0x24, 0x26, 0x29, 0x46, - 0x01, 0x03, 0xC1, 0xD8, 0xDC, 0x0E, 0x3C, 0x4F, - 0x53, 0x4E, 0xB5, 0xF8, 0xC0, 0x8A, 0xF2, 0xBB, - 0xE9, 0x5D, 0x2A, 0xBA, 0x0C, 0x1B, 0x3A, 0xA9, - 0x21, 0x6A, 0x70, 0xBC, 0xEB, 0xA1, 0x54, 0x10, - 0x98, 0x9F, 0x23, 0xD1, 0x6B, 0x59, 0x3E, 0xCA, - 0x73, 0xC8, 0x86, 0x47, 0xDB, 0xAB, 0x6F, 0x8C }; - -static const unsigned char table_38[256] = { - 0xAA, 0x8D, 0x37, 0x94, 0x99, 0xDD, 0x70, 0x77, - 0x78, 0xC9, 0x0F, 0xFA, 0xE2, 0x05, 0xC2, 0x16, - 0x02, 0x4D, 0x44, 0x65, 0xAC, 0xB0, 0x39, 0xF8, - 0x06, 0x60, 0xD8, 0xE1, 0x19, 0xB4, 0x36, 0x20, - 0x59, 0x1D, 0xAD, 0xE4, 0xE8, 0xFF, 0x9D, 0x0D, - 0x51, 0x28, 0xE7, 0x8C, 0x0E, 0x97, 0xE3, 0xAE, - 0x6A, 0x27, 0x98, 0xDB, 0x26, 0xF6, 0xEC, 0xC6, - 0xC0, 0xBD, 0x68, 0x61, 0x83, 0x86, 0xE0, 0x2C, - 0xEE, 0x47, 0xF9, 0x5F, 0x6D, 0xBA, 0xE9, 0x72, - 0x8A, 0xBB, 0x08, 0x29, 0xAF, 0x1C, 0xD3, 0x5D, - 0xF7, 0x87, 0x6F, 0x9A, 0x2F, 0x11, 0xD9, 0x90, - 0x66, 0x8E, 0xEB, 0xB1, 0x2E, 0xEA, 0xA3, 0x55, - 0x2B, 0xCC, 0x4C, 0x4B, 0x48, 0x71, 0x3B, 0xFC, - 0xA4, 0x45, 0x0A, 0x8F, 0x7A, 0x13, 0x01, 0x22, - 0xC1, 0xF1, 0xA2, 0xB8, 0x7C, 0xF4, 0xB3, 0xB7, - 0x5B, 0xE5, 0x07, 0x50, 0x7E, 0x18, 0xEF, 0x91, - 0x5C, 0x15, 0x69, 0xBE, 0x0C, 0x93, 0x56, 0x35, - 0x7B, 0xCF, 0x34, 0x74, 0x3E, 0x5E, 0x31, 0x21, - 0x12, 0x63, 0x7F, 0x2A, 0x9B, 0xD4, 0x6B, 0xBC, - 0x33, 0x62, 0x30, 0x75, 0x17, 0x23, 0xB2, 0xF0, - 0x57, 0x67, 0x95, 0x3D, 0xCD, 0x10, 0xE6, 0xC8, - 0x8B, 0xA9, 0x73, 0xC4, 0x43, 0xBF, 0xA7, 0xCA, - 0xB5, 0xD5, 0xD6, 0x3F, 0x1A, 0x7D, 0x82, 0xA8, - 0x40, 0x64, 0xAB, 0x04, 0xC3, 0x1F, 0xA0, 0x5A, - 0x85, 0xF3, 0xDE, 0xFE, 0xDA, 0x1E, 0x81, 0x92, - 0x9C, 0x2D, 0x9F, 0x32, 0xB9, 0xA1, 0x96, 0xD0, - 0x4F, 0x38, 0x80, 0xCB, 0x6C, 0x14, 0x84, 0x1B, - 0xD7, 0xC5, 0xED, 0xD2, 0x3A, 0x0B, 0x88, 0xFD, - 0xDC, 0x49, 0x9E, 0xF5, 0xF2, 0x52, 0xA6, 0x24, - 0xC7, 0xB6, 0x03, 0x3C, 0xD1, 0x54, 0x41, 0xDF, - 0x89, 0x58, 0x79, 0xFB, 0x6E, 0xA5, 0x42, 0x25, - 0x09, 0x76, 0x00, 0x46, 0x4E, 0x53, 0xCE, 0x4A }; - -static const unsigned char table_39[32] = { - 0x12, 0x18, 0x0E, 0x08, 0x16, 0x05, 0x06, 0x00, - 0x11, 0x17, 0x15, 0x1B, 0x14, 0x01, 0x1F, 0x19, - 0x04, 0x0D, 0x0A, 0x0F, 0x10, 0x07, 0x1D, 0x03, - 0x0B, 0x13, 0x0C, 0x09, 0x1E, 0x02, 0x1A, 0x1C }; - -static const unsigned char table_40[32] = { - 0x16, 0x02, 0x06, 0x0E, 0x0D, 0x1C, 0x08, 0x0A, - 0x0F, 0x13, 0x0B, 0x18, 0x07, 0x04, 0x14, 0x01, - 0x1B, 0x05, 0x17, 0x1E, 0x11, 0x1A, 0x10, 0x1F, - 0x12, 0x19, 0x1D, 0x03, 0x0C, 0x00, 0x09, 0x15 }; - -static const unsigned char table_41[32] = { - 0x13, 0x18, 0x04, 0x1F, 0x1D, 0x11, 0x03, 0x00, - 0x10, 0x12, 0x06, 0x0A, 0x1C, 0x07, 0x15, 0x0E, - 0x08, 0x05, 0x0C, 0x09, 0x01, 0x02, 0x16, 0x0B, - 0x1A, 0x17, 0x14, 0x1E, 0x0D, 0x0F, 0x19, 0x1B }; - -static const unsigned char table_42[32] = { - 0x00, 0x08, 0x15, 0x1D, 0x05, 0x18, 0x06, 0x07, - 0x1F, 0x01, 0x0B, 0x03, 0x19, 0x13, 0x02, 0x1C, - 0x17, 0x11, 0x0E, 0x1E, 0x0C, 0x0F, 0x09, 0x1A, - 0x1B, 0x16, 0x10, 0x0D, 0x0A, 0x14, 0x12, 0x04 }; - -static const unsigned char table_43[256] = { - 0x34, 0xB7, 0x36, 0x85, 0x5F, 0x93, 0x98, 0x70, - 0x1E, 0x59, 0x83, 0x60, 0x6F, 0xBF, 0xF9, 0xD0, - 0xB3, 0x22, 0x12, 0x38, 0xF5, 0x01, 0xC9, 0x5B, - 0xEF, 0x1D, 0x81, 0x64, 0xFA, 0x8F, 0x7F, 0xBC, - 0x05, 0x08, 0xE0, 0x8B, 0xE8, 0x86, 0x95, 0xCB, - 0xCA, 0x5A, 0xEB, 0x10, 0x92, 0xE2, 0x7E, 0x28, - 0xD9, 0xC7, 0x0D, 0x24, 0xA7, 0x02, 0x0B, 0xF1, - 0x7B, 0xD3, 0xFE, 0x2B, 0x89, 0x0E, 0xAE, 0xAD, - 0xC8, 0x82, 0x79, 0x43, 0x96, 0xDE, 0x0C, 0x9A, - 0x57, 0x84, 0xB4, 0x19, 0xF8, 0xF0, 0xAF, 0xBE, - 0x99, 0x9F, 0x46, 0xE4, 0x31, 0xDF, 0x30, 0x51, - 0xD4, 0xE5, 0xFC, 0x32, 0x04, 0x56, 0x7D, 0x33, - 0xF7, 0x18, 0x23, 0x4E, 0xC2, 0x7C, 0x6C, 0xD2, - 0xB1, 0x9B, 0x40, 0xA2, 0x88, 0x00, 0xA1, 0xAB, - 0xC6, 0x5C, 0x87, 0x3B, 0xD7, 0x27, 0x2E, 0x45, - 0xDA, 0x8E, 0x61, 0x5E, 0xFB, 0x09, 0x5D, 0x6B, - 0xA3, 0x29, 0x4F, 0xAC, 0xD1, 0x77, 0x4A, 0xA9, - 0xC4, 0x7A, 0x15, 0xD8, 0xAA, 0x17, 0xB9, 0x2D, - 0xE7, 0xBD, 0x2C, 0x62, 0x2F, 0xB2, 0xED, 0x3F, - 0x48, 0x26, 0x1B, 0x35, 0x20, 0x72, 0x4D, 0xFF, - 0xBB, 0x78, 0x1F, 0xCC, 0xEC, 0xA8, 0x9D, 0x90, - 0x4B, 0x13, 0xE1, 0xBA, 0xF3, 0x3C, 0x42, 0x65, - 0x14, 0xDD, 0x75, 0xE3, 0x4C, 0x74, 0x94, 0xCD, - 0xF2, 0x66, 0x06, 0xE9, 0x49, 0xB8, 0x71, 0x41, - 0xA0, 0x25, 0x55, 0x47, 0x97, 0x9E, 0x11, 0x54, - 0x1A, 0xB0, 0x3E, 0x37, 0x39, 0x1C, 0x8D, 0x03, - 0x6E, 0xF6, 0x80, 0x6D, 0x8C, 0x9C, 0xB6, 0xCF, - 0xC3, 0x91, 0x63, 0xC0, 0x07, 0x67, 0xE6, 0xF4, - 0xCE, 0x3D, 0xDB, 0x16, 0xFD, 0xEA, 0xD6, 0x68, - 0xD5, 0xA6, 0x0F, 0x58, 0x44, 0x52, 0xB5, 0xDC, - 0x0A, 0x69, 0xC5, 0xA5, 0xC1, 0x8A, 0x2A, 0xEE, - 0x73, 0x76, 0x3A, 0x21, 0x53, 0xA4, 0x50, 0x6A }; - -static const unsigned char table_44[32] = { - 0x1A, 0x0E, 0x0A, 0x17, 0x1F, 0x08, 0x10, 0x14, - 0x0C, 0x0F, 0x09, 0x1C, 0x06, 0x18, 0x1E, 0x12, - 0x15, 0x00, 0x11, 0x13, 0x0D, 0x01, 0x0B, 0x03, - 0x16, 0x19, 0x05, 0x1D, 0x02, 0x07, 0x04, 0x1B }; - -static const unsigned char table_45[256] = { - 0x5E, 0xD6, 0xE2, 0x54, 0x35, 0xC2, 0xAC, 0x9D, - 0x92, 0x64, 0x57, 0x65, 0xC8, 0xAE, 0x21, 0xA9, - 0x89, 0x48, 0x12, 0x59, 0xEC, 0xEF, 0x9F, 0xF7, - 0x19, 0x03, 0x83, 0xC0, 0x79, 0x5D, 0x4A, 0x10, - 0x8C, 0xEB, 0xFF, 0xB5, 0x3B, 0x51, 0x2D, 0xD1, - 0x6B, 0xC5, 0x24, 0x5C, 0xE6, 0x11, 0x94, 0x3F, - 0xD0, 0x2F, 0x0E, 0x95, 0x3C, 0xFE, 0x5B, 0x20, - 0x23, 0xE0, 0x91, 0x6F, 0xCA, 0x56, 0x0C, 0x73, - 0xDA, 0x67, 0x37, 0xA3, 0xA5, 0x70, 0x93, 0x1C, - 0x18, 0xD9, 0x42, 0x5F, 0x44, 0xF0, 0xF2, 0x14, - 0x58, 0x8A, 0x1D, 0x40, 0x4E, 0x0B, 0x74, 0x84, - 0x52, 0xCB, 0x60, 0xED, 0xAD, 0x66, 0x43, 0x6C, - 0x81, 0xA1, 0x27, 0xB9, 0xBA, 0x4D, 0xF5, 0x04, - 0xB8, 0x96, 0xA6, 0xA2, 0x7D, 0xD4, 0xEA, 0x45, - 0x4F, 0x55, 0xD3, 0x3E, 0x8E, 0x4C, 0xBF, 0x8B, - 0x9A, 0x06, 0x7A, 0xF4, 0x02, 0x88, 0x80, 0x22, - 0xF3, 0xBD, 0x78, 0xEE, 0xAF, 0xF8, 0x15, 0x09, - 0x0F, 0xB0, 0xDD, 0x99, 0x72, 0xE7, 0x90, 0xE1, - 0x25, 0x62, 0x8D, 0x9C, 0x13, 0x08, 0xC9, 0x28, - 0x2A, 0x47, 0x69, 0xDE, 0x77, 0x87, 0xBB, 0xE9, - 0xAA, 0x33, 0x05, 0x29, 0x34, 0x97, 0xFD, 0xA0, - 0x1E, 0xFC, 0xBE, 0xB1, 0x71, 0x9B, 0x50, 0xDC, - 0xB7, 0x31, 0x63, 0x3A, 0xDF, 0xC3, 0x1B, 0x7C, - 0x0A, 0xD7, 0xF6, 0xDB, 0x49, 0x53, 0x7F, 0xD2, - 0x30, 0xA4, 0xB3, 0x6E, 0xB2, 0x6D, 0xCD, 0x7E, - 0x26, 0xE8, 0x76, 0xCF, 0xE5, 0xCE, 0x16, 0xF1, - 0xC6, 0x68, 0x36, 0x46, 0x1F, 0x38, 0x0D, 0x41, - 0x17, 0xBC, 0x86, 0x9E, 0x6A, 0x7B, 0xB4, 0x01, - 0xCC, 0x2C, 0xE3, 0x5A, 0xB6, 0xFA, 0x00, 0x75, - 0x39, 0xA7, 0xC1, 0xD5, 0x98, 0xAB, 0x1A, 0x85, - 0xD8, 0xE4, 0xC4, 0xA8, 0x4B, 0x61, 0x2E, 0x3D, - 0xF9, 0x2B, 0x32, 0x8F, 0xFB, 0xC7, 0x07, 0x82 }; - -static const unsigned char table_46[256] = { - 0x85, 0x78, 0xFE, 0x6C, 0x61, 0xA0, 0x71, 0xCC, - 0x45, 0x54, 0x7A, 0xE6, 0x82, 0x1D, 0xA6, 0x02, - 0x47, 0xD0, 0x23, 0x55, 0x62, 0xFA, 0x76, 0x3E, - 0xE3, 0x66, 0x74, 0x10, 0x5D, 0x49, 0x69, 0x0B, - 0x75, 0x12, 0x8D, 0x9F, 0xEE, 0x93, 0x50, 0x70, - 0x32, 0xBC, 0x1E, 0xD3, 0xEF, 0x7B, 0xB4, 0x92, - 0xFD, 0x16, 0xC2, 0xD8, 0xDE, 0x68, 0xD1, 0x64, - 0xC3, 0xA3, 0xB3, 0xC9, 0x08, 0xFB, 0x84, 0xC1, - 0x28, 0x53, 0xCF, 0xD2, 0x35, 0xD7, 0x4A, 0x01, - 0x44, 0xA4, 0x07, 0xAC, 0x98, 0xF1, 0xB2, 0x9A, - 0x94, 0x2D, 0xD4, 0x34, 0x27, 0x60, 0x1A, 0xB9, - 0xAF, 0x89, 0xEB, 0x8F, 0x6A, 0x13, 0x05, 0xF0, - 0x77, 0x5F, 0x4F, 0x58, 0x2C, 0xE7, 0xCE, 0xED, - 0xC0, 0x0D, 0x3A, 0xA7, 0xE2, 0x38, 0x5B, 0xE9, - 0x3D, 0xF2, 0xDF, 0x86, 0xE0, 0x72, 0xF7, 0x88, - 0xAD, 0xB7, 0x11, 0xDB, 0x73, 0x87, 0xC5, 0x22, - 0xE1, 0x5C, 0xD6, 0x57, 0x7E, 0x7D, 0xA2, 0xF9, - 0xF5, 0x9C, 0x25, 0x6F, 0x26, 0x51, 0xC8, 0x80, - 0x2B, 0xA8, 0x19, 0xD9, 0x65, 0xCD, 0x97, 0xEA, - 0xFF, 0x5E, 0x24, 0x3B, 0x4D, 0xB1, 0x1C, 0x79, - 0x39, 0x6B, 0xA5, 0x2A, 0x09, 0xCA, 0x04, 0xEC, - 0xBA, 0x18, 0x31, 0x46, 0x20, 0xBE, 0x1F, 0x3C, - 0x6D, 0xAA, 0xF6, 0xDD, 0xF4, 0x96, 0x03, 0x0A, - 0x9E, 0x83, 0xA1, 0x9D, 0xD5, 0xB0, 0x17, 0xBF, - 0x56, 0xAB, 0xAE, 0x1B, 0x52, 0xC6, 0x81, 0x4B, - 0xDC, 0x90, 0x5A, 0x9B, 0xB6, 0x0F, 0xF3, 0x67, - 0x30, 0x63, 0x7C, 0x40, 0x0E, 0x7F, 0x95, 0x36, - 0xC4, 0x4E, 0x43, 0xCB, 0x15, 0xB8, 0x00, 0x91, - 0x8A, 0x4C, 0x8E, 0x14, 0x06, 0x6E, 0xA9, 0x2E, - 0x3F, 0x48, 0x2F, 0x0C, 0xB5, 0x21, 0xBB, 0xDA, - 0x8B, 0x42, 0x29, 0x8C, 0x33, 0x59, 0xE8, 0xF8, - 0xC7, 0xE4, 0x37, 0xE5, 0xFC, 0xBD, 0x99, 0x41 }; - -static const unsigned char table_47[32] = { - 0x18, 0x1D, 0x16, 0x10, 0x11, 0x04, 0x1E, 0x08, - 0x19, 0x0E, 0x0F, 0x02, 0x14, 0x1C, 0x07, 0x17, - 0x0D, 0x09, 0x12, 0x1A, 0x05, 0x01, 0x0B, 0x0A, - 0x13, 0x15, 0x0C, 0x00, 0x06, 0x1F, 0x03, 0x1B }; - -static const unsigned char table_48[32] = { - 0x13, 0x08, 0x15, 0x01, 0x17, 0x10, 0x0F, 0x1F, - 0x1D, 0x0D, 0x12, 0x03, 0x06, 0x0A, 0x1C, 0x19, - 0x1A, 0x04, 0x1B, 0x02, 0x16, 0x1E, 0x11, 0x00, - 0x14, 0x09, 0x0C, 0x18, 0x05, 0x07, 0x0E, 0x0B }; - -static const unsigned char table_49[32] = { - 0x1F, 0x0F, 0x19, 0x07, 0x18, 0x05, 0x1E, 0x1D, - 0x15, 0x08, 0x17, 0x10, 0x0A, 0x0E, 0x0C, 0x1B, - 0x02, 0x13, 0x03, 0x0D, 0x04, 0x1A, 0x06, 0x09, - 0x12, 0x1C, 0x0B, 0x16, 0x14, 0x01, 0x11, 0x00 }; - -static const unsigned char table_50[32] = { - 0x16, 0x18, 0x1C, 0x0E, 0x12, 0x00, 0x04, 0x1B, - 0x1F, 0x13, 0x17, 0x0A, 0x1E, 0x03, 0x0C, 0x01, - 0x0F, 0x10, 0x02, 0x08, 0x14, 0x09, 0x19, 0x15, - 0x06, 0x0D, 0x0B, 0x1D, 0x05, 0x07, 0x11, 0x1A }; - -static const unsigned char table_51[32] = { - 0x1C, 0x0D, 0x1B, 0x07, 0x17, 0x0E, 0x06, 0x01, - 0x12, 0x19, 0x03, 0x0B, 0x10, 0x08, 0x00, 0x1E, - 0x0A, 0x04, 0x1A, 0x1D, 0x0C, 0x18, 0x02, 0x13, - 0x0F, 0x11, 0x05, 0x09, 0x15, 0x16, 0x1F, 0x14 }; - -static const unsigned char table_52[256] = { - 0x34, 0x0B, 0x47, 0xA3, 0x56, 0x30, 0x73, 0xD4, - 0x4B, 0xF6, 0xA6, 0x80, 0x22, 0x95, 0xA5, 0xBB, - 0xFE, 0xCD, 0x27, 0x88, 0x87, 0x18, 0x86, 0x6E, - 0xB9, 0x07, 0x37, 0x52, 0x0A, 0x28, 0x2C, 0xC4, - 0x75, 0xA1, 0x29, 0x54, 0x84, 0x08, 0x72, 0x51, - 0xDD, 0xF1, 0x4E, 0x1A, 0x90, 0x57, 0x20, 0xAD, - 0x68, 0x61, 0xAF, 0x50, 0x6B, 0x1B, 0x71, 0xEB, - 0x63, 0xC9, 0xB0, 0x58, 0x26, 0x40, 0xC7, 0xD9, - 0x70, 0xA2, 0x9A, 0x09, 0x3F, 0x92, 0x0D, 0x8C, - 0xC1, 0x96, 0x9F, 0x77, 0x4D, 0x5A, 0xEA, 0x11, - 0xD7, 0xF3, 0x33, 0x93, 0x10, 0xF2, 0x9D, 0x83, - 0xFF, 0x7E, 0xD2, 0x41, 0x24, 0xB4, 0x8D, 0x5C, - 0xCF, 0xEF, 0xE9, 0x64, 0x76, 0xD1, 0xDE, 0xE4, - 0x91, 0x35, 0x89, 0x19, 0x02, 0x0E, 0xF4, 0x2A, - 0x0F, 0xE1, 0xA8, 0x2D, 0x21, 0x23, 0xAA, 0x7C, - 0x78, 0x45, 0xA9, 0xDC, 0x06, 0xF9, 0xDF, 0xF7, - 0x03, 0xAB, 0xB5, 0x1C, 0x36, 0x7B, 0x97, 0xFA, - 0xE5, 0x3B, 0x2F, 0x1F, 0x9E, 0xED, 0xA7, 0x55, - 0x42, 0x6F, 0x1E, 0xB7, 0xE6, 0xFB, 0x12, 0xD5, - 0x99, 0xC6, 0x66, 0x4A, 0xE8, 0x48, 0x60, 0xB1, - 0x05, 0x53, 0x8A, 0xB6, 0x25, 0x8F, 0xA4, 0xD8, - 0x9C, 0xC0, 0x59, 0x3A, 0xBD, 0xDB, 0x44, 0x5E, - 0xE3, 0xDA, 0x1D, 0x32, 0xF5, 0xBA, 0x43, 0x13, - 0x82, 0x4C, 0xE7, 0x17, 0x15, 0x3E, 0x69, 0x2E, - 0xC3, 0xF0, 0x5F, 0xFD, 0xCE, 0xD3, 0xCA, 0x39, - 0xD6, 0x79, 0x3D, 0xC8, 0x67, 0x8B, 0x31, 0x4F, - 0xB3, 0xBC, 0x65, 0x00, 0x7A, 0x98, 0xC5, 0x6C, - 0x2B, 0x94, 0x6D, 0x74, 0x14, 0xAC, 0xCC, 0xA0, - 0x5B, 0xF8, 0xCB, 0x7F, 0xB2, 0xEC, 0xBF, 0x3C, - 0xE0, 0xAE, 0xFC, 0x62, 0x04, 0x8E, 0x85, 0x49, - 0x9B, 0xC2, 0x38, 0xD0, 0xEE, 0x81, 0x46, 0xE2, - 0x01, 0x0C, 0x5D, 0x7D, 0xB8, 0xBE, 0x6A, 0x16 }; - -static const unsigned char table_53[256] = { - 0xE3, 0xF4, 0x8D, 0x72, 0x45, 0x32, 0x9D, 0xCE, - 0x1F, 0x6B, 0xBC, 0xDC, 0xF1, 0xEC, 0x5A, 0x3B, - 0xA5, 0xA2, 0x2B, 0xDD, 0x8A, 0xA3, 0x76, 0xE4, - 0xAF, 0xE9, 0xE1, 0x21, 0xDB, 0x9F, 0x19, 0xD3, - 0x26, 0x80, 0x15, 0xC2, 0x46, 0xB8, 0x17, 0x56, - 0x99, 0x81, 0x08, 0xD7, 0xEF, 0x8E, 0x04, 0x05, - 0x97, 0x2F, 0x78, 0xAD, 0xA1, 0x52, 0x36, 0x58, - 0x53, 0x68, 0x22, 0x70, 0x0B, 0x79, 0xE6, 0xFA, - 0xC3, 0x91, 0xE2, 0xF7, 0xF6, 0x75, 0x2D, 0x0A, - 0x90, 0xEB, 0xA6, 0x35, 0xA7, 0x10, 0xB5, 0xFB, - 0xE7, 0xAA, 0x1E, 0x43, 0xBB, 0x3C, 0x65, 0x25, - 0x2C, 0x59, 0x62, 0x2A, 0xF9, 0x4B, 0x95, 0x5E, - 0x20, 0x11, 0x42, 0x27, 0x44, 0xE8, 0x14, 0x6F, - 0xD1, 0xD8, 0x00, 0x3A, 0x5B, 0x18, 0x89, 0x02, - 0x61, 0xD6, 0xC5, 0x98, 0xD0, 0x5F, 0x34, 0x29, - 0xFD, 0x31, 0x1A, 0xCD, 0x0F, 0x9E, 0xCA, 0x7B, - 0xEA, 0x93, 0x71, 0x5C, 0x0E, 0x57, 0x33, 0xC4, - 0x37, 0xF5, 0x83, 0xB0, 0xDF, 0x49, 0x74, 0x54, - 0x1D, 0x24, 0xB9, 0x16, 0x1C, 0x28, 0xDE, 0x4A, - 0xF0, 0x01, 0x86, 0x82, 0xCC, 0x12, 0x8C, 0x06, - 0x30, 0xA8, 0x7A, 0x73, 0x66, 0x7C, 0xC6, 0xB6, - 0xF2, 0x13, 0xBF, 0x40, 0x85, 0x77, 0x09, 0x3D, - 0x67, 0x63, 0x3F, 0x7F, 0xF3, 0x87, 0x8F, 0xFF, - 0x92, 0xC7, 0x4C, 0x23, 0xBA, 0xCB, 0xB1, 0xED, - 0x0C, 0x60, 0x47, 0xFE, 0x38, 0x5D, 0xCF, 0x8B, - 0x4D, 0xA9, 0x2E, 0xE5, 0xA4, 0x1B, 0x88, 0x3E, - 0x7D, 0xF8, 0xC0, 0xD5, 0x6D, 0x6C, 0x48, 0xAC, - 0x9B, 0x51, 0x7E, 0x6E, 0x50, 0x0D, 0x9A, 0xB3, - 0xEE, 0x07, 0x4F, 0x69, 0x9C, 0x03, 0xD9, 0xD4, - 0xB4, 0xD2, 0xAE, 0x4E, 0x55, 0xB7, 0xC9, 0x41, - 0x39, 0x6A, 0xC8, 0xA0, 0xB2, 0xC1, 0x84, 0xFC, - 0xAB, 0x64, 0xE0, 0xBE, 0xDA, 0xBD, 0x96, 0x94 }; - -static const unsigned char table_54[32] = { - 0x01, 0x02, 0x1D, 0x10, 0x0E, 0x11, 0x08, 0x14, - 0x12, 0x09, 0x15, 0x17, 0x16, 0x04, 0x06, 0x1B, - 0x07, 0x1A, 0x18, 0x13, 0x0A, 0x1E, 0x1C, 0x1F, - 0x0C, 0x0B, 0x0D, 0x05, 0x0F, 0x00, 0x19, 0x03 }; - -static const unsigned char table_55[32] = { - 0x01, 0x12, 0x13, 0x09, 0x0B, 0x19, 0x03, 0x0E, - 0x02, 0x1F, 0x1D, 0x1B, 0x1E, 0x11, 0x06, 0x05, - 0x00, 0x16, 0x07, 0x0C, 0x15, 0x0D, 0x1A, 0x08, - 0x18, 0x10, 0x0F, 0x17, 0x1C, 0x0A, 0x04, 0x14 }; - -static const unsigned char table_56[256] = { - 0xEF, 0x06, 0x5F, 0x11, 0x4B, 0x60, 0x13, 0xBB, - 0x79, 0xD7, 0xE4, 0x6D, 0x22, 0xB4, 0x15, 0x50, - 0x29, 0x17, 0xD2, 0xE3, 0x37, 0x8C, 0x46, 0x7C, - 0xA2, 0xF5, 0x65, 0x16, 0xCB, 0x04, 0x3E, 0xDF, - 0x8E, 0xDE, 0x53, 0xF1, 0xF4, 0xD1, 0x3B, 0xEE, - 0x9A, 0x09, 0x9B, 0x6C, 0xF6, 0xCC, 0xFB, 0x40, - 0xE0, 0xFD, 0x2B, 0x1D, 0x73, 0x18, 0xCD, 0x31, - 0x3F, 0x9E, 0xAD, 0xC9, 0x43, 0x4E, 0x99, 0x3A, - 0x8F, 0x92, 0x85, 0xFC, 0x12, 0x41, 0x20, 0xE8, - 0x2A, 0xC0, 0x1C, 0x38, 0x74, 0x0B, 0xF3, 0x05, - 0x0D, 0x1F, 0x94, 0x9C, 0xAC, 0x00, 0x59, 0x0C, - 0xB3, 0x8D, 0xA8, 0x75, 0xB7, 0x68, 0x2F, 0x27, - 0x6F, 0x69, 0x76, 0xD8, 0xEC, 0xA5, 0xB2, 0x6A, - 0x19, 0x72, 0x1A, 0xB6, 0xE5, 0x77, 0xC6, 0x44, - 0x9D, 0xCA, 0x82, 0x35, 0x36, 0x5E, 0xA9, 0x25, - 0xFA, 0x5C, 0x24, 0x30, 0x39, 0x0E, 0x2C, 0x7D, - 0xE6, 0x88, 0xA0, 0x63, 0xB8, 0x6B, 0x01, 0xDD, - 0xDA, 0x9F, 0x45, 0x83, 0xE2, 0x7F, 0x1B, 0x56, - 0xAF, 0x14, 0xC3, 0x49, 0xBF, 0x78, 0x70, 0x58, - 0x23, 0xA3, 0xBD, 0x34, 0x47, 0x2D, 0x0A, 0xD4, - 0x33, 0x03, 0x1E, 0xC1, 0x87, 0xAE, 0x3C, 0x95, - 0xB0, 0x42, 0x91, 0xB9, 0x5A, 0x61, 0xAA, 0xCF, - 0xF2, 0x51, 0xA6, 0xF8, 0xDC, 0x71, 0xAB, 0x48, - 0x66, 0x90, 0x97, 0xC4, 0x08, 0xF9, 0xD0, 0x7B, - 0xDB, 0xBA, 0x8B, 0xC2, 0xC5, 0x2E, 0xF7, 0x5B, - 0xFF, 0x21, 0x81, 0x54, 0xD3, 0x62, 0x57, 0x4C, - 0x6E, 0x02, 0x98, 0xFE, 0x7E, 0xE7, 0xBC, 0x07, - 0x28, 0x5D, 0x86, 0xCE, 0xEA, 0x84, 0xF0, 0xE1, - 0x93, 0x80, 0xE9, 0xC7, 0x4A, 0xED, 0xB1, 0x26, - 0x89, 0x3D, 0x4F, 0xA7, 0xA1, 0xD6, 0xB5, 0x4D, - 0x67, 0xA4, 0x55, 0x10, 0x0F, 0xD9, 0x52, 0x32, - 0x96, 0xD5, 0xEB, 0x64, 0x8A, 0xC8, 0x7A, 0xBE }; - -static const unsigned char table_57[256] = { - 0xD1, 0x9B, 0x15, 0x06, 0xB4, 0xF6, 0x97, 0xF0, - 0xC6, 0x5B, 0x88, 0x12, 0x25, 0xFA, 0x7B, 0x79, - 0xD6, 0xAB, 0xDC, 0x47, 0x85, 0x61, 0x67, 0x0B, - 0xF3, 0x20, 0x44, 0x53, 0x2A, 0x3B, 0x2D, 0xE8, - 0x17, 0x71, 0xC3, 0xB7, 0x7F, 0x35, 0xEB, 0x10, - 0x03, 0x0D, 0x60, 0x96, 0x27, 0xBB, 0x39, 0x50, - 0x95, 0x55, 0xCC, 0xD4, 0x2F, 0x51, 0xB3, 0x05, - 0xA5, 0xAD, 0xBC, 0x18, 0xE2, 0xAE, 0x07, 0x87, - 0xC4, 0x8D, 0xBE, 0x77, 0xC2, 0x16, 0xFC, 0x33, - 0x4C, 0x4F, 0xE6, 0xA6, 0x57, 0x9F, 0x37, 0x91, - 0xED, 0x4A, 0xF7, 0xB5, 0x52, 0x7C, 0xBD, 0x30, - 0xA0, 0x2C, 0x8C, 0xB0, 0x0C, 0xDA, 0x6F, 0x9E, - 0xEE, 0x43, 0x40, 0x8F, 0x8B, 0x76, 0xA4, 0x68, - 0xFF, 0x6D, 0x58, 0xC9, 0xF9, 0x6E, 0x3F, 0x56, - 0xCA, 0x49, 0xC8, 0x5D, 0xCD, 0xC7, 0x99, 0xEC, - 0x72, 0x38, 0x0A, 0xA9, 0xC5, 0x04, 0x64, 0xBF, - 0xB6, 0x29, 0x80, 0x2E, 0x19, 0x0E, 0x82, 0x45, - 0xBA, 0xD7, 0x1E, 0x86, 0xA8, 0xD8, 0x24, 0xDB, - 0xCF, 0xE1, 0x54, 0xB2, 0x3E, 0x4D, 0x90, 0x42, - 0x5F, 0x59, 0x0F, 0xCE, 0x8E, 0xA2, 0xA7, 0x1D, - 0x22, 0xFD, 0x81, 0x63, 0xE5, 0x6A, 0xE7, 0x93, - 0x41, 0x46, 0x66, 0x89, 0x13, 0xEA, 0x69, 0x1C, - 0x83, 0xF2, 0x08, 0xB8, 0x01, 0x23, 0x26, 0xFB, - 0x78, 0xAA, 0x31, 0x11, 0x1B, 0x98, 0xDD, 0xAC, - 0xB9, 0xFE, 0x94, 0x74, 0xAF, 0x32, 0xD0, 0x5A, - 0xA1, 0xF4, 0x6B, 0x8A, 0xE3, 0x65, 0xDE, 0xCB, - 0x73, 0x3D, 0xA3, 0x7E, 0xDF, 0xD2, 0x6C, 0x7A, - 0x36, 0xD9, 0x62, 0x4B, 0xEF, 0xC1, 0x1F, 0x00, - 0x34, 0xB1, 0xF8, 0xE4, 0xD5, 0x09, 0x1A, 0x9A, - 0x70, 0x48, 0x9D, 0xF1, 0xE0, 0x9C, 0xD3, 0x5C, - 0x75, 0x02, 0x2B, 0x92, 0x21, 0x7D, 0xF5, 0x5E, - 0x4E, 0x3C, 0x84, 0x14, 0x28, 0x3A, 0xE9, 0xC0 }; - -static const unsigned char table_58[256] = { - 0xE9, 0x81, 0x60, 0xA7, 0x18, 0xA0, 0x0F, 0x55, - 0x2B, 0x52, 0xE0, 0x8B, 0x9D, 0x85, 0xD2, 0xA3, - 0x3F, 0x6E, 0xB1, 0xAF, 0xE3, 0x36, 0xE2, 0x19, - 0x56, 0xB0, 0x09, 0xB5, 0x79, 0x43, 0xE1, 0x06, - 0x45, 0xB6, 0xC0, 0x22, 0xEE, 0x41, 0xEC, 0x01, - 0x66, 0x2D, 0x87, 0x38, 0x16, 0x37, 0xFA, 0x29, - 0x96, 0xA4, 0xC3, 0x23, 0x59, 0x7E, 0x92, 0x78, - 0x10, 0x2A, 0x4C, 0x0E, 0x9B, 0x4A, 0x35, 0xF4, - 0x42, 0x0C, 0xD8, 0xD7, 0x24, 0x2C, 0xDD, 0x8E, - 0x5B, 0xF5, 0x33, 0x48, 0xEF, 0xDE, 0x4B, 0xBC, - 0x51, 0xAB, 0x7C, 0xE4, 0x63, 0x70, 0x9A, 0xAC, - 0x54, 0x1D, 0x25, 0xC5, 0xEA, 0xB3, 0x05, 0xF7, - 0xC1, 0x1F, 0xE8, 0x97, 0xBB, 0x32, 0x6D, 0xC7, - 0x28, 0x61, 0xDB, 0x4D, 0x77, 0x72, 0x65, 0x8C, - 0x80, 0x3A, 0x76, 0x47, 0xA8, 0x03, 0x04, 0x12, - 0xCE, 0xA9, 0x75, 0x3C, 0x49, 0xF8, 0x64, 0xDF, - 0x57, 0xA2, 0x69, 0x44, 0xAD, 0x3E, 0x4F, 0x0B, - 0x74, 0x67, 0xC9, 0x1A, 0x17, 0xAA, 0x02, 0x6F, - 0xDA, 0xF2, 0xC6, 0x27, 0x53, 0xD6, 0xFD, 0xCA, - 0x8D, 0x93, 0x89, 0xD5, 0x6B, 0x4E, 0x90, 0x82, - 0x30, 0xE7, 0xC4, 0xD9, 0x8A, 0x7F, 0xB4, 0xFC, - 0xCF, 0xA1, 0xAE, 0x1C, 0x39, 0x1B, 0x7B, 0x5E, - 0x88, 0x7D, 0xD3, 0x71, 0x2E, 0x98, 0x13, 0x8F, - 0xCC, 0x84, 0x73, 0xCD, 0x21, 0x0D, 0x5C, 0xA5, - 0x3D, 0x9E, 0x99, 0xC2, 0xF3, 0x34, 0x14, 0x62, - 0x46, 0x0A, 0x07, 0x08, 0xFF, 0xFB, 0xB7, 0xBF, - 0x5D, 0x91, 0xB8, 0x83, 0xBE, 0x94, 0xBA, 0xF9, - 0xEB, 0xE5, 0xCB, 0x95, 0x40, 0x31, 0xE6, 0x86, - 0xD4, 0xFE, 0xD0, 0x7A, 0x26, 0xB9, 0xDC, 0x2F, - 0xBD, 0xF0, 0x5F, 0x00, 0x9C, 0x6A, 0x5A, 0x3B, - 0xF1, 0xC8, 0x9F, 0xED, 0x50, 0x20, 0x15, 0x11, - 0x68, 0x1E, 0xF6, 0xA6, 0x6C, 0xB2, 0xD1, 0x58 }; - -static const unsigned char table_59[256] = { - 0x4C, 0x85, 0x2B, 0x14, 0xCC, 0x4D, 0x5F, 0xD7, - 0xCE, 0x28, 0xC5, 0x0B, 0xA1, 0x99, 0x08, 0xDE, - 0x42, 0xD1, 0x82, 0x5C, 0xC9, 0x8F, 0x72, 0x12, - 0xCB, 0x0D, 0x04, 0xFA, 0xCD, 0xE5, 0x9A, 0x6F, - 0xCF, 0x92, 0xB5, 0x88, 0x87, 0xBF, 0x90, 0x7C, - 0xAC, 0xBE, 0x36, 0x21, 0x7D, 0x7F, 0xC7, 0x9F, - 0x75, 0xBB, 0x61, 0x16, 0x17, 0x63, 0xAE, 0xC4, - 0x23, 0x89, 0xE0, 0x37, 0x91, 0x5E, 0xC8, 0xE4, - 0xFD, 0xD5, 0xA2, 0xC6, 0x5A, 0xEF, 0x9B, 0xD6, - 0x27, 0xEE, 0x60, 0x1C, 0xDF, 0xDA, 0xF1, 0xD2, - 0x1E, 0x01, 0x9D, 0x44, 0x03, 0xD8, 0x11, 0x53, - 0x4F, 0x6C, 0x8B, 0xB7, 0x40, 0xF2, 0x79, 0x20, - 0x74, 0x97, 0x3E, 0x3D, 0x05, 0xD4, 0x70, 0x30, - 0x54, 0x59, 0xE7, 0x15, 0xE1, 0xEB, 0x71, 0x83, - 0xFE, 0x66, 0xB1, 0xA6, 0xF7, 0x8E, 0x6A, 0xEA, - 0x65, 0x7E, 0xA3, 0xCA, 0x2D, 0x4B, 0xB8, 0x9C, - 0x35, 0xC3, 0xB6, 0x49, 0x32, 0x25, 0xB3, 0xB0, - 0x76, 0xC0, 0xF5, 0x00, 0x8A, 0xAF, 0x19, 0xDB, - 0xDD, 0x47, 0xDC, 0x07, 0xB2, 0x4A, 0x55, 0xE6, - 0x69, 0xEC, 0xED, 0x06, 0x94, 0xB9, 0xA7, 0x56, - 0x2C, 0xAA, 0xE3, 0x22, 0x3B, 0x98, 0x77, 0x52, - 0x3C, 0x64, 0xF8, 0x13, 0x78, 0xFC, 0xFB, 0xF3, - 0xD3, 0xF9, 0x29, 0x45, 0x51, 0x8C, 0xA0, 0x38, - 0xD9, 0xA5, 0x62, 0x3A, 0x6E, 0xD0, 0xE8, 0x7A, - 0x33, 0x1D, 0xB4, 0x73, 0x02, 0xFF, 0x10, 0x80, - 0x6B, 0xF0, 0xA4, 0xBA, 0xF6, 0xC2, 0x0E, 0xE2, - 0x81, 0x43, 0x84, 0x86, 0x1F, 0x31, 0x2F, 0xA9, - 0x1B, 0x2A, 0x4E, 0xF4, 0x95, 0x5B, 0x3F, 0x34, - 0x39, 0x7B, 0x0A, 0x26, 0x6D, 0x57, 0x50, 0x09, - 0x9E, 0xA8, 0xBC, 0x24, 0x93, 0x67, 0x41, 0x96, - 0x0C, 0x46, 0xBD, 0xE9, 0x68, 0x18, 0xAB, 0x2E, - 0x5D, 0x1A, 0x8D, 0xC1, 0x58, 0x48, 0xAD, 0x0F }; - -static const unsigned char table_60[32] = { - 0x1C, 0x06, 0x1E, 0x10, 0x1D, 0x05, 0x00, 0x0E, - 0x0C, 0x02, 0x11, 0x19, 0x15, 0x18, 0x16, 0x07, - 0x1F, 0x0B, 0x14, 0x01, 0x0F, 0x09, 0x0D, 0x13, - 0x03, 0x08, 0x12, 0x04, 0x1B, 0x0A, 0x17, 0x1A }; - -static const unsigned char table_61[256] = { - 0xC5, 0xA6, 0xF2, 0x6B, 0x4B, 0x58, 0xE0, 0x41, - 0xC6, 0x2F, 0x13, 0xFE, 0xC1, 0x34, 0x3F, 0x24, - 0x10, 0xBF, 0x8B, 0xC9, 0x26, 0x2E, 0x68, 0xBE, - 0x28, 0x54, 0x93, 0x11, 0x21, 0x03, 0xFF, 0x50, - 0x31, 0x71, 0x2C, 0x6C, 0x91, 0x8F, 0x3B, 0x40, - 0x3E, 0xE5, 0xA5, 0x80, 0xEA, 0x7C, 0x9D, 0x18, - 0x84, 0x5A, 0x73, 0x3A, 0x33, 0x43, 0xA1, 0x47, - 0xB1, 0xEE, 0xFB, 0x79, 0x5E, 0xAF, 0xB9, 0x48, - 0x0F, 0x88, 0x65, 0x67, 0x6F, 0xDB, 0x25, 0xE4, - 0xB0, 0x87, 0xD0, 0x46, 0xB5, 0xB7, 0x53, 0xD4, - 0x1E, 0x76, 0xB4, 0x90, 0xDD, 0xA3, 0xF7, 0x57, - 0xD2, 0xCC, 0x5D, 0xE3, 0xB3, 0xD8, 0x5F, 0x2B, - 0x69, 0x4A, 0x9B, 0x39, 0x1A, 0x8D, 0x05, 0x8A, - 0x44, 0x15, 0xAE, 0xF3, 0xA8, 0x92, 0x02, 0xAB, - 0xB8, 0xDA, 0x0A, 0x0C, 0xED, 0xD7, 0x77, 0x98, - 0x3D, 0x19, 0x95, 0x36, 0xE7, 0x7F, 0x66, 0xEF, - 0x86, 0xDC, 0xCB, 0x9C, 0x63, 0xE6, 0x1D, 0x14, - 0x9A, 0x22, 0xBD, 0xD6, 0x89, 0x2D, 0xD1, 0xF9, - 0xA2, 0xDE, 0xF5, 0x5C, 0x8E, 0x2A, 0x29, 0xCA, - 0x7A, 0x8C, 0x38, 0x9F, 0xBB, 0xDF, 0xEC, 0x30, - 0x00, 0xFC, 0xAC, 0x81, 0xB2, 0xE8, 0xC0, 0xA7, - 0x7B, 0x07, 0x52, 0x74, 0x70, 0x0E, 0x51, 0x6A, - 0x62, 0x0D, 0x85, 0x1B, 0x4F, 0x96, 0x55, 0x1C, - 0x32, 0x6E, 0x01, 0xF6, 0x08, 0xFD, 0x17, 0x35, - 0xF0, 0x16, 0xC8, 0x23, 0xE9, 0x59, 0x3C, 0x37, - 0x5B, 0x42, 0xD3, 0x49, 0x7D, 0x83, 0x78, 0xAD, - 0x94, 0x9E, 0x56, 0xB6, 0xF1, 0xC3, 0x75, 0xF8, - 0xFA, 0x09, 0x4C, 0xD9, 0x97, 0xF4, 0x7E, 0x6D, - 0xBC, 0x4D, 0x64, 0xCD, 0x12, 0x99, 0x45, 0xCE, - 0x61, 0x20, 0x0B, 0xA0, 0x82, 0xD5, 0xE1, 0x72, - 0xA9, 0x1F, 0x06, 0x27, 0xC7, 0x04, 0xE2, 0xBA, - 0xCF, 0x60, 0xAA, 0xA4, 0xEB, 0xC4, 0x4E, 0xC2 }; - -static const unsigned char table_62[256] = { - 0x01, 0x59, 0xEC, 0xFC, 0x51, 0xD2, 0xE4, 0x9D, - 0xAA, 0x61, 0xD5, 0xCA, 0x63, 0x5D, 0xCE, 0x36, - 0xB9, 0x49, 0x76, 0xA9, 0x14, 0x4C, 0x90, 0x28, - 0x66, 0x17, 0x4F, 0x1E, 0x1A, 0x47, 0x30, 0xE8, - 0xFD, 0x86, 0x2E, 0x7B, 0x7E, 0xCC, 0x34, 0x13, - 0x94, 0x45, 0x38, 0x74, 0x29, 0xB0, 0x37, 0xC3, - 0x26, 0x6C, 0x39, 0xA3, 0x89, 0xEB, 0xA2, 0x20, - 0x00, 0xE0, 0x73, 0xE7, 0xB5, 0xCB, 0xED, 0x3E, - 0x79, 0x09, 0xFA, 0x32, 0x54, 0xBA, 0x05, 0x96, - 0xDE, 0x23, 0xD0, 0xA1, 0xAB, 0xFE, 0xF2, 0x22, - 0xB2, 0x9B, 0x7D, 0x44, 0x12, 0x3D, 0x40, 0x82, - 0xA0, 0xA8, 0x33, 0xDC, 0xF7, 0xFB, 0xAC, 0x41, - 0x8A, 0x9C, 0x60, 0x11, 0xC8, 0xF0, 0xEA, 0x57, - 0x3A, 0x42, 0xCD, 0x1D, 0x3C, 0xC6, 0x97, 0x62, - 0x55, 0x9F, 0xF3, 0x93, 0x91, 0xDA, 0x6A, 0xE5, - 0x27, 0x8E, 0x4E, 0xFF, 0xA4, 0x80, 0x04, 0xE1, - 0x2B, 0x5E, 0xC0, 0x64, 0xC2, 0xD8, 0x46, 0x8C, - 0xD4, 0x0F, 0xC4, 0x43, 0xD9, 0x9E, 0x4B, 0x5C, - 0x0A, 0x8B, 0xBF, 0xD7, 0x7A, 0x81, 0x3B, 0x4A, - 0x58, 0xB6, 0x21, 0x1F, 0xC1, 0xBD, 0xB1, 0x77, - 0x72, 0x1C, 0x4D, 0xBC, 0xA5, 0x65, 0xC7, 0xF5, - 0xB4, 0x2D, 0x69, 0x71, 0xE6, 0x8F, 0xBB, 0x03, - 0xAF, 0xD6, 0x08, 0x75, 0xB7, 0x31, 0xF4, 0x2A, - 0x48, 0x70, 0x0C, 0x8D, 0xD1, 0x87, 0x2F, 0x16, - 0x5A, 0x5B, 0x98, 0xA6, 0xC5, 0x99, 0x50, 0x07, - 0xDD, 0x92, 0x25, 0x68, 0x0D, 0xBE, 0x78, 0x0B, - 0xAD, 0x84, 0x6B, 0x19, 0x52, 0x7C, 0xF6, 0xB3, - 0x56, 0x83, 0x88, 0xEE, 0x2C, 0x1B, 0x6E, 0x53, - 0x67, 0xE2, 0x6F, 0x15, 0x06, 0x10, 0x18, 0x85, - 0xF1, 0x6D, 0xF9, 0xC9, 0xAE, 0x3F, 0xB8, 0x95, - 0x35, 0xDF, 0xEF, 0xA7, 0x7F, 0x24, 0xF8, 0xE3, - 0xCF, 0xE9, 0xDB, 0xD3, 0x02, 0x9A, 0x0E, 0x5F }; - -static const unsigned char table_63[256] = { - 0x0C, 0x02, 0xEE, 0x94, 0x2D, 0x76, 0x96, 0x75, - 0x21, 0xDC, 0x37, 0x03, 0xC0, 0xF7, 0xDF, 0xEF, - 0xB1, 0x1D, 0xCF, 0x15, 0x5A, 0xB4, 0xCC, 0x81, - 0x89, 0x6B, 0xA5, 0x2E, 0x6D, 0xD4, 0x08, 0x44, - 0x2A, 0x60, 0x50, 0xBF, 0x40, 0x7D, 0x5F, 0x64, - 0x93, 0x70, 0xA4, 0x7F, 0xC9, 0xEB, 0x0A, 0xF8, - 0x9F, 0xA8, 0xBC, 0x25, 0xE5, 0xF3, 0x1B, 0xD7, - 0x29, 0x13, 0x0D, 0x69, 0x20, 0x5C, 0x0F, 0x91, - 0x4F, 0x62, 0x06, 0x26, 0x41, 0xED, 0xDA, 0x53, - 0x65, 0xFF, 0xCD, 0x3F, 0xF6, 0x01, 0xCE, 0xA2, - 0x04, 0xDE, 0x27, 0x87, 0xBA, 0x86, 0x24, 0x78, - 0xAF, 0xE1, 0x3D, 0xD0, 0xC8, 0x1F, 0x4A, 0x2C, - 0x9A, 0xF0, 0xCB, 0xAD, 0x0B, 0x59, 0xC5, 0x58, - 0xEA, 0x8A, 0xA1, 0x45, 0xB7, 0x5D, 0xB5, 0x77, - 0x2B, 0x47, 0x05, 0x00, 0xAC, 0x61, 0xFA, 0x33, - 0x74, 0x31, 0xCA, 0x22, 0x42, 0x8B, 0xFE, 0x09, - 0xB2, 0x6E, 0x1A, 0xBE, 0xAA, 0x7B, 0xEC, 0xF4, - 0x51, 0x66, 0x28, 0x12, 0xFC, 0x5E, 0x67, 0xF5, - 0xB9, 0x82, 0x90, 0x8E, 0x8D, 0x17, 0xE7, 0xE8, - 0xB0, 0xC3, 0x16, 0xA0, 0x4B, 0xB6, 0xFB, 0x7E, - 0xC4, 0x85, 0x4C, 0x1E, 0xC7, 0x39, 0x4E, 0xA9, - 0xE3, 0x4D, 0x32, 0x72, 0x35, 0x80, 0xE0, 0x34, - 0xB8, 0x73, 0x98, 0x49, 0x92, 0x30, 0xD5, 0xD2, - 0xA3, 0x54, 0x7A, 0x84, 0x8F, 0x6C, 0xFD, 0x43, - 0x3A, 0x36, 0x3B, 0xD9, 0x48, 0x6A, 0x14, 0x79, - 0xD1, 0x57, 0x88, 0xDB, 0xE4, 0x9B, 0xF9, 0x99, - 0x10, 0x71, 0xC1, 0x68, 0x9E, 0x11, 0xAB, 0xBD, - 0x7C, 0x3E, 0x3C, 0x18, 0x9D, 0x97, 0xF2, 0xE6, - 0xA6, 0xF1, 0x46, 0xC2, 0x19, 0xBB, 0x52, 0xD8, - 0x95, 0xD3, 0x23, 0xAE, 0x07, 0x2F, 0xE9, 0x63, - 0x1C, 0x55, 0x6F, 0x9C, 0x56, 0x38, 0xC6, 0x5B, - 0x8C, 0xE2, 0x83, 0xA7, 0xD6, 0x0E, 0xB3, 0xDD }; - -static const unsigned char table_64[32] = { - 0x03, 0x05, 0x0D, 0x09, 0x1A, 0x16, 0x08, 0x10, - 0x06, 0x1E, 0x1C, 0x15, 0x02, 0x04, 0x17, 0x0C, - 0x18, 0x0B, 0x19, 0x11, 0x1B, 0x14, 0x13, 0x0A, - 0x0E, 0x00, 0x1D, 0x1F, 0x01, 0x0F, 0x07, 0x12 }; - -static const unsigned char table_65[32] = { - 0x01, 0x0A, 0x1E, 0x14, 0x10, 0x1D, 0x0D, 0x17, - 0x0E, 0x0C, 0x0F, 0x12, 0x04, 0x1A, 0x05, 0x02, - 0x08, 0x1C, 0x09, 0x1F, 0x0B, 0x13, 0x19, 0x1B, - 0x11, 0x00, 0x16, 0x06, 0x03, 0x18, 0x15, 0x07 }; - -static const unsigned char table_66[32] = { - 0x1C, 0x18, 0x0C, 0x09, 0x05, 0x03, 0x15, 0x12, - 0x0D, 0x02, 0x08, 0x0E, 0x19, 0x07, 0x13, 0x17, - 0x1E, 0x1D, 0x1F, 0x11, 0x06, 0x0A, 0x0B, 0x14, - 0x0F, 0x10, 0x01, 0x1B, 0x00, 0x04, 0x1A, 0x16 }; - -static const unsigned char table_67[256] = { - 0x6B, 0x49, 0xC8, 0x86, 0xFF, 0xC0, 0x5D, 0xEF, - 0xF7, 0x06, 0xE0, 0x98, 0xA9, 0x72, 0x71, 0xD5, - 0xBA, 0x7F, 0x10, 0xD1, 0xBE, 0x41, 0x9C, 0x40, - 0x28, 0x8E, 0xE5, 0x74, 0x47, 0x9E, 0x3E, 0x7C, - 0xB5, 0xCD, 0x3F, 0x20, 0xF2, 0xA6, 0xDC, 0x97, - 0x32, 0x6D, 0x52, 0xF5, 0x16, 0x05, 0xFE, 0x04, - 0x3D, 0x53, 0x50, 0x23, 0x39, 0x77, 0x08, 0x60, - 0x75, 0x18, 0x4A, 0xC6, 0xBB, 0xE7, 0xF1, 0xAB, - 0xEB, 0x88, 0xB6, 0x82, 0x6E, 0x91, 0xF3, 0x34, - 0x3A, 0x42, 0x1A, 0xDF, 0xA1, 0xB3, 0x92, 0xBF, - 0xB7, 0x00, 0xD4, 0xDE, 0x31, 0xF0, 0x1C, 0xDA, - 0x4F, 0x61, 0x67, 0x2C, 0x07, 0xF9, 0x15, 0xA4, - 0x7A, 0x26, 0x45, 0x2A, 0x12, 0x9F, 0xF4, 0x14, - 0x8C, 0x90, 0xFC, 0xC5, 0x4B, 0x87, 0xE2, 0xC7, - 0xD0, 0x8A, 0xE8, 0xDD, 0xEE, 0x3C, 0x2F, 0x22, - 0x6A, 0x54, 0x37, 0x9B, 0x84, 0x25, 0x8F, 0xE3, - 0xD7, 0xD8, 0x4E, 0xAD, 0x0F, 0x4C, 0x56, 0xA2, - 0xD3, 0xB0, 0x73, 0x0B, 0xAE, 0xEA, 0x1D, 0x01, - 0x36, 0xB4, 0x2D, 0xC4, 0x19, 0x58, 0x1E, 0x62, - 0xE9, 0xB2, 0x5B, 0x5A, 0xBD, 0xD6, 0x65, 0x94, - 0x9A, 0x55, 0xCC, 0x99, 0x1B, 0x85, 0x2B, 0xBC, - 0x8D, 0x46, 0x81, 0xB8, 0xA3, 0x29, 0x5F, 0x35, - 0x5C, 0xB1, 0x1F, 0x13, 0x17, 0xCB, 0x51, 0x02, - 0x09, 0x7E, 0xA7, 0x69, 0x6F, 0x95, 0x30, 0x7B, - 0xCA, 0x48, 0xAF, 0xAA, 0x0E, 0x44, 0x38, 0xB9, - 0x0D, 0x11, 0xA0, 0xD9, 0x0C, 0xDB, 0xF8, 0x68, - 0x33, 0x79, 0x59, 0x66, 0x4D, 0x03, 0xE1, 0x89, - 0xE4, 0x3B, 0x78, 0xC2, 0x64, 0x6C, 0x27, 0xC9, - 0xCF, 0xAC, 0xED, 0xFA, 0x5E, 0x2E, 0x76, 0x57, - 0x93, 0xEC, 0x80, 0xA8, 0xE6, 0xCE, 0xC1, 0xA5, - 0x9D, 0xD2, 0xC3, 0x0A, 0x7D, 0x70, 0xF6, 0x63, - 0x24, 0x43, 0x21, 0x83, 0xFB, 0xFD, 0x8B, 0x96 }; - -static const unsigned char table_68[256] = { - 0x93, 0xFF, 0x83, 0x70, 0x12, 0x2D, 0x1C, 0xD6, - 0xF9, 0xEE, 0xCF, 0x94, 0x7B, 0xB5, 0xA4, 0x84, - 0x99, 0xF7, 0x67, 0x32, 0xFC, 0x8A, 0xE3, 0xE4, - 0xCE, 0xC6, 0x77, 0x7E, 0xDA, 0x42, 0x85, 0xF0, - 0x7D, 0x48, 0x28, 0x79, 0xDE, 0x5B, 0xE2, 0x0F, - 0x75, 0xC5, 0x2C, 0x4F, 0xF3, 0xEC, 0x14, 0x10, - 0x9C, 0x6E, 0x59, 0x4A, 0x20, 0x34, 0xA3, 0x89, - 0xE0, 0x4E, 0x52, 0x88, 0x81, 0x5F, 0x6F, 0x71, - 0x17, 0x3B, 0x21, 0xB4, 0xCB, 0x9B, 0x18, 0x13, - 0xE8, 0xE1, 0x02, 0x2E, 0xED, 0x00, 0xA7, 0x1B, - 0x06, 0xF4, 0x27, 0xDC, 0x35, 0x2F, 0x08, 0x9D, - 0x7C, 0xC0, 0x36, 0xA6, 0x6B, 0xDF, 0x4C, 0xBC, - 0xFE, 0xDB, 0xA5, 0xA8, 0x8D, 0x73, 0x7F, 0xC7, - 0x8E, 0x60, 0x31, 0x61, 0x4B, 0x29, 0xD7, 0xE9, - 0xBD, 0xAB, 0xCC, 0xFA, 0xD9, 0xEF, 0xC2, 0xD4, - 0x19, 0x11, 0x15, 0xC9, 0xB1, 0xD5, 0x64, 0x97, - 0xE7, 0x8F, 0x05, 0x44, 0xF8, 0xF1, 0x58, 0x47, - 0x2A, 0x03, 0x1F, 0xAF, 0x0D, 0x04, 0x23, 0xB8, - 0x24, 0x51, 0xB2, 0x54, 0x41, 0x53, 0x5C, 0xAE, - 0xB7, 0xB3, 0xB6, 0x3D, 0x37, 0x39, 0x55, 0xBF, - 0x0B, 0x7A, 0x57, 0x3C, 0x0E, 0x40, 0x6A, 0xF5, - 0x72, 0xDD, 0xBB, 0x8B, 0xAA, 0x46, 0xA0, 0x30, - 0x56, 0x78, 0x38, 0xBA, 0x9E, 0x92, 0x87, 0xFB, - 0x66, 0x90, 0x1E, 0xB9, 0x96, 0x65, 0xA2, 0x50, - 0x1D, 0xC3, 0x26, 0x22, 0xD0, 0x0A, 0x43, 0xF2, - 0xB0, 0xEB, 0xAC, 0x62, 0x98, 0x3F, 0xD3, 0x69, - 0xA1, 0x9F, 0x16, 0x95, 0xE6, 0xF6, 0x2B, 0x25, - 0x1A, 0xD2, 0xBE, 0x09, 0x5D, 0x45, 0xC4, 0xFD, - 0x5A, 0x07, 0x0C, 0x82, 0x3E, 0x49, 0x74, 0x6C, - 0x68, 0x5E, 0xCA, 0xEA, 0xCD, 0x9A, 0xAD, 0xD1, - 0x33, 0x86, 0x76, 0x80, 0xE5, 0xC8, 0xD8, 0xA9, - 0x8C, 0x6D, 0x91, 0x63, 0x3A, 0x4D, 0xC1, 0x01 }; - -static const unsigned char table_69[256] = { - 0x21, 0x6B, 0x9B, 0xAE, 0x11, 0x5A, 0x91, 0xC2, - 0x47, 0x8E, 0x87, 0x86, 0x4F, 0xFC, 0x8F, 0x66, - 0x97, 0x2F, 0x61, 0x9C, 0x5B, 0x4C, 0xB3, 0x14, - 0x77, 0x48, 0x62, 0xE1, 0x54, 0x64, 0xDD, 0xCD, - 0x30, 0xB7, 0x2D, 0xD2, 0xC3, 0xC0, 0x0B, 0xD8, - 0x53, 0x98, 0x16, 0x56, 0x7A, 0x35, 0x50, 0xD9, - 0xE8, 0x2C, 0x32, 0x55, 0x17, 0x5D, 0x79, 0xEB, - 0xC8, 0x75, 0x67, 0xE2, 0x4B, 0xBA, 0xFE, 0x57, - 0x10, 0xF4, 0x70, 0x2A, 0xBB, 0xA6, 0x72, 0x36, - 0xAF, 0x8D, 0xAB, 0x90, 0xE3, 0x2B, 0xB2, 0x26, - 0x93, 0x01, 0xBD, 0x71, 0xF9, 0x05, 0xC7, 0x80, - 0x29, 0xCC, 0x3B, 0x22, 0xF2, 0x12, 0x81, 0x34, - 0xF6, 0x1A, 0x8B, 0xDF, 0x28, 0x46, 0x9E, 0x6A, - 0x23, 0x85, 0x74, 0xE7, 0xE6, 0x52, 0xA0, 0x49, - 0xF0, 0x19, 0x25, 0xAC, 0x78, 0x42, 0xD6, 0xA2, - 0x37, 0x65, 0x4D, 0x94, 0x02, 0x6F, 0xB4, 0xC6, - 0x99, 0xD3, 0x9A, 0x33, 0xB8, 0x00, 0xCA, 0xE4, - 0x45, 0xAD, 0x1B, 0x6C, 0x03, 0xA8, 0x07, 0x8A, - 0x60, 0x69, 0xFF, 0xF7, 0xA7, 0x27, 0x95, 0xF5, - 0x82, 0xCB, 0xEC, 0xED, 0x4E, 0xFB, 0xA4, 0x59, - 0xDA, 0xCF, 0x2E, 0x20, 0xFA, 0x31, 0xD1, 0xEA, - 0x4A, 0xE9, 0x5E, 0xA9, 0xA1, 0x08, 0x1C, 0x96, - 0x38, 0xB9, 0xEE, 0x7F, 0xAA, 0xF1, 0x7D, 0x3A, - 0xA5, 0x43, 0xC5, 0xE0, 0x24, 0x39, 0x0D, 0xDE, - 0xB0, 0xF8, 0xBE, 0x58, 0x7E, 0x51, 0xD4, 0x89, - 0x15, 0x40, 0x3E, 0xB1, 0x1F, 0x5F, 0x68, 0x63, - 0x84, 0x3D, 0x88, 0xBC, 0x41, 0xEF, 0xB5, 0xBF, - 0x06, 0x6E, 0x9D, 0x3F, 0x0E, 0x76, 0x5C, 0xDC, - 0x13, 0xF3, 0xE5, 0x8C, 0x7C, 0x04, 0x0A, 0xD5, - 0x18, 0xC4, 0x44, 0x09, 0xC9, 0x1D, 0x9F, 0xFD, - 0xD0, 0x0F, 0x6D, 0xD7, 0x92, 0x7B, 0x0C, 0xA3, - 0x73, 0xDB, 0xB6, 0x83, 0xCE, 0x1E, 0xC1, 0x3C }; - -static const unsigned char table_70[256] = { - 0x54, 0x23, 0xF1, 0x09, 0x9D, 0xEB, 0x26, 0xD9, - 0x6C, 0xC1, 0xBC, 0x3D, 0x6E, 0xB0, 0x5F, 0xE2, - 0x59, 0x4D, 0x95, 0xFA, 0xD8, 0x29, 0xAA, 0x8E, - 0xF5, 0xEF, 0x43, 0x76, 0xFD, 0x0D, 0x4F, 0xAD, - 0xB7, 0xFC, 0xA8, 0x9F, 0x62, 0xC2, 0x7B, 0x10, - 0x0B, 0xF2, 0x73, 0xA9, 0x46, 0x4C, 0x53, 0xD7, - 0x0A, 0x50, 0x89, 0x63, 0x48, 0xD6, 0xA2, 0x44, - 0xE6, 0x8D, 0x69, 0x2C, 0xF9, 0xC0, 0x35, 0x06, - 0x66, 0x21, 0x9E, 0xD2, 0x98, 0xF7, 0x9B, 0xE7, - 0x12, 0xB8, 0xA5, 0xBA, 0xE0, 0x79, 0x71, 0x7E, - 0x8C, 0x24, 0xED, 0x7C, 0x60, 0x81, 0xC3, 0x5C, - 0x2B, 0xE5, 0xEE, 0xB5, 0xA4, 0x05, 0x03, 0x34, - 0x16, 0x2A, 0xA3, 0x2D, 0x3F, 0xDF, 0x07, 0x5B, - 0xAE, 0x47, 0x61, 0x08, 0x18, 0xDB, 0x6D, 0x3C, - 0x96, 0xD5, 0xAB, 0x78, 0x94, 0x45, 0x20, 0x9A, - 0xE4, 0x13, 0x68, 0xDD, 0xDE, 0x31, 0x14, 0x57, - 0x02, 0x52, 0x56, 0x1C, 0x1B, 0xE9, 0xD0, 0xA1, - 0x22, 0x64, 0xB2, 0x7A, 0xCF, 0x5D, 0x00, 0x0F, - 0xF8, 0x5E, 0x36, 0x58, 0x40, 0xAF, 0x19, 0x32, - 0x2E, 0xB3, 0x72, 0xBE, 0xB9, 0xD3, 0xCD, 0x7D, - 0x4A, 0x1D, 0x33, 0x2F, 0xAC, 0x27, 0x41, 0xE8, - 0x55, 0xCB, 0x0E, 0x5A, 0x77, 0xFB, 0x8B, 0x86, - 0x75, 0x8A, 0x51, 0xEC, 0xDA, 0xC6, 0xA6, 0xCC, - 0x91, 0x4B, 0x11, 0xF6, 0xEA, 0xD1, 0xB6, 0x4E, - 0x82, 0x04, 0x92, 0x30, 0xF4, 0x25, 0x88, 0x1E, - 0x9C, 0xA0, 0xC8, 0x6A, 0x93, 0x87, 0x1F, 0xB4, - 0xB1, 0x8F, 0x65, 0xCA, 0xFE, 0xFF, 0x97, 0x15, - 0x99, 0x28, 0x80, 0x42, 0x70, 0x85, 0x0C, 0x3B, - 0xBD, 0xE1, 0xA7, 0x17, 0xC9, 0x3A, 0xBB, 0x6B, - 0x37, 0xF0, 0xC5, 0x39, 0x6F, 0x01, 0x83, 0x67, - 0x74, 0xCE, 0xDC, 0x90, 0x3E, 0xF3, 0x7F, 0xC4, - 0x49, 0x84, 0x38, 0xC7, 0xE3, 0xD4, 0x1A, 0xBF }; - -static const unsigned char table_71[32] = { - 0x17, 0x13, 0x0E, 0x1A, 0x0D, 0x18, 0x19, 0x10, - 0x14, 0x11, 0x16, 0x05, 0x04, 0x00, 0x12, 0x0A, - 0x02, 0x07, 0x03, 0x0B, 0x09, 0x1F, 0x1C, 0x0F, - 0x0C, 0x06, 0x1B, 0x08, 0x1D, 0x01, 0x15, 0x1E }; - -static const unsigned char table_72[256] = { - 0xC9, 0xA7, 0x1B, 0xEC, 0x2B, 0x8B, 0xB0, 0xEB, - 0x7F, 0x39, 0x25, 0xD9, 0x1D, 0xD5, 0x67, 0xA0, - 0xB3, 0xAC, 0x3B, 0xC8, 0x82, 0xC0, 0xE3, 0x9E, - 0x4C, 0x9B, 0xAF, 0xFD, 0x91, 0x86, 0x5F, 0x92, - 0xB4, 0x42, 0x3C, 0x45, 0x12, 0xC4, 0xE2, 0xE1, - 0x6C, 0x1F, 0xC6, 0x40, 0x93, 0x2A, 0xC2, 0x72, - 0x2E, 0x14, 0x51, 0xA5, 0x70, 0xBD, 0xA2, 0xC7, - 0x7D, 0xF1, 0x9F, 0x64, 0xC1, 0xF7, 0x80, 0xFF, - 0x50, 0x49, 0x8C, 0x66, 0x13, 0x48, 0x6A, 0x0A, - 0x26, 0x94, 0x83, 0x1E, 0x84, 0xBB, 0x57, 0x27, - 0x44, 0x5B, 0x62, 0xF6, 0x09, 0x4F, 0x77, 0x76, - 0x2D, 0x7E, 0xCD, 0x0B, 0x24, 0xFE, 0x81, 0xB8, - 0x21, 0x85, 0xCF, 0xA8, 0x75, 0x56, 0x37, 0x17, - 0xAA, 0x23, 0xE5, 0xE8, 0x9A, 0x9D, 0x2F, 0x04, - 0x31, 0x4A, 0x7C, 0xFC, 0xD6, 0xE4, 0x29, 0xC3, - 0xFB, 0x36, 0x1C, 0x0C, 0xCE, 0xEE, 0x0D, 0xF3, - 0x46, 0xF8, 0x41, 0x0E, 0x68, 0xAB, 0x2C, 0x69, - 0x96, 0x90, 0x28, 0xED, 0x02, 0x63, 0x07, 0xAD, - 0xB2, 0xDC, 0x05, 0xE6, 0x78, 0x03, 0xA4, 0x7A, - 0x5C, 0x52, 0x95, 0x5D, 0x88, 0x01, 0xDF, 0x35, - 0x5E, 0xB6, 0x06, 0x4D, 0x15, 0x89, 0x59, 0x3F, - 0xF0, 0xA1, 0xA3, 0x99, 0x19, 0xEA, 0xDB, 0xE0, - 0x6B, 0x71, 0x6E, 0xB7, 0x65, 0x54, 0x9C, 0xBC, - 0x98, 0xDD, 0x4B, 0x60, 0x3D, 0xBF, 0xF5, 0xD1, - 0xD7, 0xF9, 0x55, 0x61, 0xA9, 0xB1, 0x6D, 0xDE, - 0x79, 0xAE, 0x1A, 0x34, 0x3A, 0x4E, 0xCB, 0x38, - 0xBA, 0x97, 0x00, 0x74, 0xEF, 0xD8, 0x18, 0x33, - 0x7B, 0xFA, 0x22, 0x32, 0x20, 0xCA, 0x8A, 0xBE, - 0xA6, 0x43, 0x11, 0x10, 0xD0, 0xD3, 0x87, 0x73, - 0x6F, 0xF4, 0x8D, 0xCC, 0x30, 0x0F, 0x16, 0xDA, - 0xB5, 0xC5, 0xD4, 0x47, 0x8E, 0xE7, 0x58, 0x8F, - 0x08, 0x53, 0xF2, 0xB9, 0x5A, 0x3E, 0xE9, 0xD2 }; - -static const unsigned char table_73[256] = { - 0x36, 0x37, 0xED, 0xD8, 0xBF, 0xD7, 0x12, 0xB7, - 0x40, 0x32, 0x19, 0x4A, 0x44, 0x2A, 0xCE, 0xA5, - 0x29, 0x13, 0x43, 0x51, 0x5C, 0xD0, 0x76, 0x6E, - 0x41, 0xD6, 0xE2, 0x4F, 0xB8, 0x27, 0x2E, 0xCF, - 0xD9, 0xE0, 0x69, 0xC0, 0x59, 0x77, 0x62, 0x6F, - 0x53, 0xE7, 0x93, 0xD4, 0xAD, 0xC8, 0x4C, 0xC2, - 0x2C, 0xBE, 0xAA, 0xA0, 0x22, 0x78, 0x14, 0xB3, - 0xB0, 0xEA, 0xBA, 0x9A, 0x33, 0x1B, 0x31, 0x6C, - 0xFC, 0x0A, 0x0B, 0xA1, 0xE4, 0x75, 0x7C, 0xE3, - 0x65, 0x21, 0xA9, 0xA4, 0x4E, 0x3C, 0x5F, 0x39, - 0x74, 0xA2, 0x9E, 0x03, 0x70, 0xD2, 0xFD, 0x1D, - 0x25, 0x72, 0x73, 0x8E, 0x7B, 0xB2, 0x6A, 0x92, - 0x81, 0xF3, 0xF0, 0x46, 0x08, 0x85, 0xE6, 0x30, - 0x05, 0x7E, 0xEC, 0x0D, 0xDD, 0x42, 0x2F, 0x5B, - 0xB9, 0xCB, 0x84, 0x0C, 0x16, 0xC7, 0x24, 0xFA, - 0xF9, 0x8F, 0x20, 0xAC, 0x10, 0x55, 0xC3, 0x1A, - 0x8B, 0x94, 0x3D, 0xDB, 0xC9, 0x04, 0xB5, 0xCC, - 0xC6, 0x98, 0xB6, 0x8D, 0x0F, 0x3A, 0x06, 0x4B, - 0xEF, 0x35, 0x68, 0x3F, 0xEE, 0xE5, 0x63, 0xC5, - 0x60, 0x88, 0x52, 0x2D, 0x6D, 0xAB, 0xCD, 0xC4, - 0x1F, 0xF4, 0xCA, 0x67, 0x7D, 0x1C, 0xDA, 0x34, - 0xDE, 0x86, 0xAE, 0xF1, 0x61, 0x09, 0xF5, 0xF6, - 0x49, 0xE9, 0xF2, 0x48, 0x1E, 0xD3, 0x56, 0x18, - 0x9B, 0xB1, 0x57, 0x9D, 0xBB, 0x5E, 0xAF, 0x87, - 0x9F, 0x8A, 0xC1, 0x79, 0xA7, 0xA8, 0xFB, 0xDC, - 0x47, 0x3E, 0x97, 0x80, 0x91, 0xA6, 0x7A, 0xA3, - 0x9C, 0x11, 0x02, 0x2B, 0x58, 0xD1, 0xF7, 0x00, - 0x83, 0x01, 0xE8, 0xFE, 0x50, 0x23, 0x66, 0x4D, - 0xD5, 0x82, 0x89, 0x3B, 0xEB, 0xE1, 0xF8, 0x5A, - 0x15, 0x7F, 0x8C, 0x17, 0x96, 0x28, 0x5D, 0x64, - 0x26, 0x38, 0x71, 0x0E, 0x45, 0xDF, 0xB4, 0x99, - 0xFF, 0x90, 0x6B, 0xBC, 0x54, 0x95, 0xBD, 0x07 }; - -static const unsigned char table_74[256] = { - 0xA7, 0xCF, 0x99, 0x1A, 0x13, 0xC7, 0xE9, 0xC4, - 0xB6, 0x0E, 0x15, 0x09, 0xFF, 0xDF, 0xBE, 0x03, - 0xAD, 0xF1, 0xB0, 0x3C, 0x4A, 0x9B, 0xF5, 0x12, - 0xA1, 0x2C, 0xDB, 0x51, 0x5E, 0x6F, 0xE6, 0x49, - 0x27, 0xBB, 0xAE, 0x56, 0xC0, 0x0C, 0x77, 0x60, - 0x5B, 0x69, 0xA2, 0xF0, 0x24, 0x8E, 0xE1, 0xA4, - 0xBC, 0x9F, 0x50, 0xD4, 0x61, 0x19, 0x67, 0x00, - 0x7B, 0xAB, 0xDD, 0x26, 0xCD, 0x6C, 0xE8, 0xA8, - 0x7A, 0x93, 0xEF, 0x20, 0x52, 0x1F, 0x1B, 0x46, - 0x25, 0x3B, 0x1E, 0x65, 0xC2, 0xF9, 0x10, 0xB2, - 0xB3, 0xD9, 0x21, 0xD2, 0x11, 0x94, 0xE2, 0xFC, - 0x38, 0x9E, 0x36, 0x87, 0xAA, 0x53, 0x45, 0x68, - 0x2B, 0xE7, 0x07, 0xFA, 0xD3, 0x8D, 0x3F, 0x17, - 0xC1, 0x06, 0x72, 0x62, 0x8C, 0x55, 0x73, 0x8A, - 0xC9, 0x2E, 0x5A, 0x7D, 0x02, 0x6D, 0xF8, 0x4B, - 0xE4, 0xBF, 0xEC, 0xB7, 0x31, 0xDC, 0xF4, 0xB8, - 0x47, 0x64, 0x0A, 0x33, 0x48, 0xAC, 0xFB, 0x05, - 0x3E, 0x34, 0x1C, 0x97, 0x1D, 0x63, 0x37, 0x2D, - 0xB1, 0x92, 0xED, 0x9D, 0x4C, 0xD5, 0x4E, 0x9A, - 0x0D, 0x79, 0x0F, 0xBD, 0x95, 0xBA, 0x08, 0x2A, - 0xC6, 0x7E, 0x88, 0xCB, 0xA6, 0x29, 0x70, 0x35, - 0x66, 0xCA, 0x89, 0x75, 0x6A, 0x4F, 0xB5, 0x6B, - 0x74, 0xDE, 0x01, 0x04, 0x81, 0x91, 0x90, 0x18, - 0x32, 0x0B, 0x7F, 0x44, 0xB4, 0xAF, 0xF2, 0xEB, - 0x22, 0xFD, 0x14, 0xA0, 0xFE, 0x8B, 0xB9, 0x16, - 0x86, 0xE3, 0xD7, 0xDA, 0xC5, 0x3A, 0x41, 0x83, - 0xD1, 0x28, 0x54, 0x30, 0xE0, 0x40, 0xA5, 0x57, - 0x8F, 0x84, 0xD6, 0x96, 0x39, 0xE5, 0x42, 0x80, - 0xA9, 0x58, 0xCE, 0x5D, 0xEE, 0x5F, 0xA3, 0xD0, - 0xC8, 0x59, 0x43, 0x4D, 0x5C, 0xF7, 0xCC, 0x76, - 0x6E, 0xF3, 0x23, 0x3D, 0x85, 0x82, 0x78, 0xF6, - 0x2F, 0xD8, 0xC3, 0x7C, 0x9C, 0x98, 0xEA, 0x71 }; - -static const unsigned char table_75[256] = { - 0xE7, 0xA5, 0x30, 0xE1, 0x9D, 0x81, 0xBE, 0x83, - 0xB2, 0x1E, 0xE4, 0x69, 0x2F, 0x2B, 0x0D, 0xEB, - 0x7C, 0x59, 0x2D, 0xAA, 0x01, 0x0C, 0xDB, 0xED, - 0xC4, 0xEE, 0x5D, 0x38, 0x72, 0xD8, 0x70, 0xCE, - 0x0B, 0xF6, 0x7F, 0x48, 0x26, 0x9E, 0xA3, 0x44, - 0xD6, 0xCF, 0x0F, 0x6B, 0xFD, 0x23, 0x98, 0xAB, - 0x11, 0xD4, 0x92, 0x91, 0x5E, 0x08, 0x4D, 0xC6, - 0xF0, 0xA8, 0x7E, 0x8A, 0x1D, 0xA1, 0x97, 0x76, - 0x3E, 0x64, 0x07, 0x24, 0xDE, 0x75, 0xA4, 0xCC, - 0x1A, 0x04, 0x4B, 0x6C, 0xFA, 0xB0, 0xC7, 0x35, - 0xE2, 0x56, 0x61, 0xA0, 0xE9, 0x27, 0xDF, 0xC3, - 0xE5, 0xF4, 0x8D, 0xB4, 0xD3, 0x52, 0xD7, 0x49, - 0xCD, 0x31, 0x6E, 0x3F, 0x4E, 0x6A, 0x5B, 0x65, - 0xCA, 0x14, 0x71, 0x53, 0xD9, 0x47, 0x28, 0x7D, - 0x17, 0x06, 0x5C, 0xFE, 0xBA, 0xB8, 0xAC, 0x15, - 0xE8, 0xE0, 0x9A, 0xDD, 0x1F, 0xBC, 0x95, 0x42, - 0xCB, 0x58, 0x00, 0x85, 0xD5, 0x62, 0xC9, 0xB6, - 0x05, 0x80, 0x4C, 0x3C, 0x1C, 0xF5, 0x03, 0xF8, - 0x96, 0x77, 0x02, 0x19, 0xF2, 0xFB, 0x5F, 0xC2, - 0xAE, 0x60, 0x1B, 0xAD, 0x8F, 0xC1, 0x33, 0xA6, - 0x20, 0xBF, 0xA7, 0xC8, 0x74, 0x18, 0x90, 0xE3, - 0x68, 0x09, 0x7A, 0x79, 0xB5, 0xDA, 0xF3, 0x0E, - 0x66, 0x84, 0xB3, 0xBB, 0xE6, 0xF7, 0xB7, 0x7B, - 0x39, 0x4A, 0x12, 0x4F, 0xC5, 0x41, 0x54, 0xD0, - 0xFF, 0x87, 0x63, 0x40, 0x99, 0x21, 0x29, 0xD2, - 0x3D, 0x37, 0x3A, 0x93, 0xFC, 0x25, 0xF1, 0xD1, - 0x2C, 0x6D, 0x8C, 0x5A, 0x8E, 0x9B, 0xBD, 0xAF, - 0x10, 0x55, 0xF9, 0x9F, 0x43, 0x0A, 0x50, 0x16, - 0x57, 0xB1, 0xC0, 0x73, 0x82, 0xEF, 0x88, 0x6F, - 0xEA, 0x2A, 0xEC, 0x2E, 0x86, 0x45, 0x51, 0x22, - 0xA9, 0x34, 0x94, 0x3B, 0xB9, 0x9C, 0xA2, 0x13, - 0x89, 0x46, 0x78, 0xDC, 0x32, 0x8B, 0x67, 0x36 }; - -static const unsigned char table_76[256] = { - 0x3D, 0x66, 0x40, 0xC5, 0x1D, 0xF5, 0xE7, 0xB7, - 0x2C, 0x23, 0x09, 0xC2, 0x68, 0xE6, 0xD3, 0x8D, - 0x35, 0x94, 0x93, 0xF0, 0x43, 0x97, 0x2B, 0x4B, - 0x1A, 0xEB, 0x00, 0x4C, 0x6F, 0xE4, 0x92, 0xEA, - 0xB8, 0xA3, 0xA6, 0xEC, 0x11, 0x5E, 0x61, 0x81, - 0xE1, 0x48, 0xC9, 0xCB, 0xDB, 0x2E, 0x3B, 0xED, - 0x36, 0x52, 0x3A, 0xD2, 0x4F, 0x4E, 0x22, 0x96, - 0x57, 0x2D, 0x62, 0x53, 0xCF, 0xD9, 0x5B, 0x9F, - 0x8E, 0x78, 0xC6, 0x07, 0x7D, 0xA1, 0x02, 0xB4, - 0xF4, 0xB6, 0x34, 0x98, 0xDA, 0xA9, 0xD4, 0x54, - 0x99, 0x82, 0x0A, 0xD8, 0x88, 0x5D, 0x3C, 0xD0, - 0xAB, 0x31, 0xFB, 0x03, 0x17, 0x46, 0xE8, 0xE2, - 0xA4, 0xFF, 0xB0, 0xAA, 0xAD, 0x7C, 0x55, 0x49, - 0x75, 0x6B, 0x10, 0x24, 0xC0, 0x04, 0xB1, 0xBF, - 0x6A, 0xF6, 0x15, 0xEF, 0x5C, 0x60, 0x27, 0x3E, - 0x38, 0x63, 0xC1, 0x76, 0xFD, 0x84, 0xE0, 0xCD, - 0xFE, 0x30, 0xCE, 0xBB, 0xDC, 0x1E, 0x1B, 0xBC, - 0xB5, 0xE9, 0x9E, 0x8F, 0x0D, 0x3F, 0x91, 0x19, - 0x28, 0x37, 0x26, 0x42, 0x08, 0x9A, 0x0C, 0x83, - 0x90, 0x6D, 0x74, 0x65, 0xF2, 0x4A, 0xDE, 0x8B, - 0x67, 0x0E, 0x8C, 0x5F, 0xF9, 0x7F, 0x5A, 0x86, - 0x69, 0x45, 0x44, 0xD5, 0xF7, 0xE5, 0x8A, 0xA8, - 0xC8, 0x7E, 0x05, 0x64, 0xEE, 0x79, 0xBE, 0x7A, - 0x14, 0xD6, 0x50, 0x18, 0x25, 0xBD, 0x85, 0xE3, - 0xA2, 0x70, 0xCC, 0x59, 0x71, 0x77, 0xFA, 0x47, - 0x9B, 0x1F, 0x9D, 0xBA, 0x29, 0x4D, 0xF8, 0xDF, - 0xC4, 0x72, 0x2F, 0xAE, 0x06, 0x51, 0x41, 0xAF, - 0xF3, 0xDD, 0x87, 0xB2, 0x9C, 0xC7, 0x12, 0x16, - 0x20, 0xA7, 0x21, 0x73, 0xF1, 0x58, 0xD7, 0x7B, - 0xB9, 0xB3, 0x32, 0x01, 0x80, 0x1C, 0x39, 0x0B, - 0x13, 0x56, 0x6C, 0x89, 0x33, 0x6E, 0x2A, 0xA5, - 0xD1, 0x95, 0xC3, 0xA0, 0x0F, 0xCA, 0xAC, 0xFC }; - -static const unsigned char table_77[32] = { - 0x1C, 0x0D, 0x1E, 0x01, 0x06, 0x16, 0x18, 0x17, - 0x0B, 0x1F, 0x04, 0x0F, 0x00, 0x19, 0x08, 0x0A, - 0x11, 0x03, 0x05, 0x07, 0x09, 0x0C, 0x15, 0x14, - 0x1A, 0x12, 0x13, 0x0E, 0x1D, 0x10, 0x02, 0x1B }; - -static const unsigned char table_78[32] = { - 0x0E, 0x02, 0x17, 0x12, 0x1E, 0x09, 0x15, 0x03, - 0x01, 0x0B, 0x0F, 0x11, 0x10, 0x0A, 0x16, 0x06, - 0x07, 0x00, 0x1C, 0x1D, 0x1F, 0x0C, 0x18, 0x04, - 0x13, 0x0D, 0x1B, 0x08, 0x19, 0x14, 0x05, 0x1A }; - -static const unsigned char table_79[32] = { - 0x12, 0x0B, 0x11, 0x01, 0x07, 0x0E, 0x1A, 0x0D, - 0x1E, 0x18, 0x14, 0x1F, 0x0A, 0x17, 0x19, 0x1B, - 0x00, 0x10, 0x0C, 0x08, 0x13, 0x02, 0x0F, 0x1D, - 0x09, 0x06, 0x04, 0x16, 0x15, 0x1C, 0x05, 0x03 }; - -static const unsigned char table_80[256] = { - 0x14, 0xE7, 0x31, 0x0F, 0xD1, 0x5F, 0xED, 0x1E, - 0xA6, 0x77, 0x20, 0x57, 0x34, 0x64, 0x33, 0x0B, - 0x5A, 0xB4, 0x83, 0x62, 0xFD, 0x8E, 0xE4, 0xF3, - 0xBD, 0xA5, 0xC8, 0x6D, 0x3E, 0x4F, 0x01, 0x7A, - 0xD3, 0x45, 0x3C, 0xF2, 0x68, 0xFF, 0xE6, 0x84, - 0xC2, 0xC1, 0x53, 0x72, 0x8C, 0xA1, 0xC7, 0x00, - 0x89, 0x97, 0x69, 0xA4, 0xF8, 0xAA, 0xAD, 0x8F, - 0x24, 0xC6, 0x9A, 0xAC, 0xE5, 0xAB, 0x6B, 0x79, - 0x99, 0x60, 0x28, 0x2B, 0x3B, 0xAF, 0x1C, 0x80, - 0xA3, 0x8A, 0x1A, 0xB5, 0xE1, 0x9F, 0xDA, 0x78, - 0xD7, 0xC4, 0x87, 0x5D, 0xE9, 0x27, 0xFB, 0x18, - 0x94, 0x3A, 0xCE, 0x3F, 0xF6, 0x12, 0x75, 0x37, - 0x6E, 0x9E, 0x29, 0x6C, 0xF7, 0x7D, 0x92, 0x08, - 0x42, 0xB2, 0xBF, 0x0C, 0xB6, 0x25, 0xE0, 0x49, - 0x43, 0x91, 0x98, 0xBB, 0xDC, 0x63, 0xEA, 0xA8, - 0x74, 0x38, 0x35, 0xCD, 0x07, 0x70, 0x81, 0x41, - 0xC9, 0x51, 0xBC, 0xA9, 0x59, 0xD4, 0xB8, 0x2C, - 0x7C, 0x2D, 0xB3, 0x6F, 0x11, 0x86, 0x9D, 0x46, - 0xF0, 0x65, 0x76, 0x04, 0x0E, 0xCA, 0xBE, 0x5C, - 0xF9, 0x71, 0x9C, 0x21, 0x4C, 0x02, 0xFE, 0x8D, - 0xD5, 0x26, 0x40, 0xC3, 0x32, 0x9B, 0xB0, 0x5E, - 0x48, 0xC5, 0x85, 0x4B, 0x0A, 0xCC, 0x58, 0x52, - 0x61, 0x13, 0xEF, 0x4A, 0xEE, 0x03, 0xD9, 0xDE, - 0xA7, 0x19, 0x09, 0x7F, 0x5B, 0x96, 0xBA, 0x0D, - 0xCF, 0xD2, 0x06, 0x1F, 0xD8, 0xDB, 0xEC, 0xA0, - 0xDD, 0x66, 0x10, 0xA2, 0xDF, 0x30, 0xF4, 0x88, - 0xCB, 0x36, 0x82, 0xE3, 0x73, 0x17, 0x55, 0x15, - 0xF5, 0xB7, 0x23, 0xB1, 0xD6, 0xE2, 0x47, 0x7E, - 0x67, 0xE8, 0x1D, 0x16, 0x8B, 0xEB, 0xD0, 0x3D, - 0x6A, 0x54, 0x2A, 0x4E, 0x93, 0xFA, 0x44, 0x05, - 0x2F, 0x50, 0x2E, 0x95, 0xAE, 0x1B, 0x56, 0x7B, - 0x39, 0xB9, 0xC0, 0x22, 0xF1, 0x4D, 0x90, 0xFC }; - -static const unsigned char table_81[32] = { - 0x03, 0x02, 0x1D, 0x0E, 0x09, 0x1A, 0x0C, 0x11, - 0x1C, 0x0D, 0x08, 0x12, 0x19, 0x10, 0x04, 0x17, - 0x15, 0x05, 0x0A, 0x00, 0x13, 0x16, 0x1B, 0x18, - 0x1E, 0x0B, 0x0F, 0x01, 0x07, 0x14, 0x1F, 0x06 }; - -static const unsigned char table_82[256] = { - 0x53, 0xD3, 0x64, 0x89, 0x7D, 0xA5, 0x66, 0xA4, - 0x09, 0x46, 0x17, 0x2C, 0xAF, 0x8C, 0x21, 0x5F, - 0x3B, 0x22, 0xE3, 0x05, 0x07, 0x28, 0x2F, 0xAB, - 0xF4, 0x8E, 0x51, 0x31, 0x02, 0xC7, 0x48, 0x13, - 0x24, 0x12, 0xB8, 0xE5, 0xBD, 0xAE, 0x7E, 0xCC, - 0xC9, 0x98, 0x08, 0xEE, 0xDB, 0x1B, 0xE8, 0x3D, - 0x8F, 0xF2, 0xFB, 0x36, 0x4D, 0x94, 0x9C, 0x16, - 0xF7, 0x42, 0x9B, 0x2B, 0xFD, 0x7B, 0x77, 0x3F, - 0xC3, 0xFC, 0x23, 0x93, 0x50, 0x0C, 0x79, 0x18, - 0x47, 0xE1, 0xCB, 0xA7, 0xB6, 0x85, 0xE6, 0x61, - 0x2D, 0xD8, 0x9F, 0x80, 0xE9, 0x14, 0x0B, 0x1C, - 0x40, 0x76, 0x2A, 0x25, 0x0E, 0x99, 0xAC, 0xC4, - 0xEB, 0x29, 0x41, 0x8A, 0x73, 0x06, 0x57, 0xC6, - 0x8D, 0xFA, 0x5A, 0xCD, 0x67, 0xB2, 0xD9, 0x0A, - 0x1E, 0xEF, 0x3E, 0xA0, 0x45, 0x03, 0x27, 0xF1, - 0x38, 0x54, 0xC1, 0x7A, 0xFE, 0x52, 0x75, 0xD4, - 0x74, 0x7C, 0xD2, 0x68, 0xEA, 0x4C, 0x97, 0xF9, - 0xF5, 0x8B, 0x0F, 0x84, 0xA8, 0x6E, 0x9E, 0x11, - 0x6B, 0xBC, 0x4B, 0x6C, 0x9A, 0xF0, 0xA3, 0x1F, - 0x92, 0x19, 0xA2, 0x3A, 0x15, 0x04, 0xC5, 0x62, - 0xD5, 0x96, 0x90, 0x32, 0xAA, 0xD6, 0xCF, 0x35, - 0xB4, 0x81, 0x2E, 0x01, 0x10, 0x49, 0x70, 0xDE, - 0xDD, 0x88, 0xB9, 0x6D, 0x60, 0xBB, 0x44, 0xF8, - 0x3C, 0xEC, 0x34, 0x82, 0x95, 0x72, 0x58, 0x4E, - 0xE4, 0x0D, 0xBE, 0xDA, 0x83, 0x4A, 0x00, 0xBF, - 0xD0, 0xC8, 0x26, 0xB3, 0x65, 0x1A, 0x69, 0xCA, - 0xF3, 0xD7, 0x6F, 0x55, 0xE2, 0xFF, 0x5D, 0xDC, - 0x20, 0xF6, 0x63, 0xED, 0xE0, 0x59, 0x9D, 0xB1, - 0x1D, 0xAD, 0x91, 0xA1, 0xB7, 0xA9, 0xDF, 0xC0, - 0x39, 0xD1, 0x43, 0xCE, 0x4F, 0x5C, 0xE7, 0x37, - 0x5E, 0x33, 0x5B, 0xA6, 0xC2, 0xB0, 0xBA, 0x30, - 0x6A, 0x78, 0xB5, 0x71, 0x56, 0x87, 0x7F, 0x86 }; - -static const unsigned char table_83[32] = { - 0x1B, 0x0A, 0x1F, 0x01, 0x10, 0x08, 0x0E, 0x18, - 0x06, 0x04, 0x00, 0x1C, 0x0C, 0x19, 0x0D, 0x16, - 0x02, 0x03, 0x09, 0x07, 0x13, 0x0F, 0x05, 0x12, - 0x17, 0x1E, 0x1A, 0x1D, 0x0B, 0x11, 0x14, 0x15 }; - -static const unsigned char table_84[32] = { - 0x02, 0x1A, 0x0D, 0x15, 0x01, 0x16, 0x1E, 0x00, - 0x08, 0x1B, 0x04, 0x10, 0x1C, 0x18, 0x19, 0x14, - 0x0C, 0x11, 0x0B, 0x0E, 0x03, 0x0A, 0x07, 0x12, - 0x1D, 0x17, 0x13, 0x06, 0x0F, 0x05, 0x09, 0x1F }; - -static const unsigned char table_85[256] = { - 0xC6, 0x7C, 0xCE, 0xBD, 0x84, 0x3E, 0x0B, 0xD8, - 0xFE, 0xCC, 0x46, 0x50, 0xD1, 0xFB, 0xA0, 0x6D, - 0xEA, 0xE2, 0x40, 0x51, 0x13, 0xB0, 0xD6, 0xB1, - 0xA8, 0xDF, 0x61, 0xA4, 0x80, 0x21, 0xB3, 0x33, - 0x06, 0x6B, 0xE3, 0x8C, 0xA1, 0x18, 0xBA, 0x03, - 0xD7, 0x8D, 0x54, 0x12, 0x4C, 0xEE, 0x9E, 0xCF, - 0x04, 0x2A, 0x08, 0xBB, 0xC2, 0xD4, 0xC3, 0x4A, - 0xD5, 0xFA, 0x36, 0x2F, 0x14, 0x3F, 0xED, 0x05, - 0x17, 0x28, 0x75, 0xFC, 0xA2, 0x1F, 0x4B, 0x6F, - 0x91, 0x7E, 0x4E, 0x96, 0x3B, 0xF3, 0x1D, 0x78, - 0xEB, 0x68, 0xF1, 0xA7, 0x9F, 0xC7, 0x59, 0x6C, - 0x92, 0xE6, 0x66, 0x07, 0x8A, 0x25, 0x26, 0x72, - 0x30, 0x5A, 0x81, 0x2C, 0x58, 0x32, 0xCB, 0xE0, - 0xF9, 0x48, 0x83, 0x9B, 0xA5, 0xE1, 0xA6, 0x64, - 0xFF, 0xC9, 0x8F, 0x53, 0x3D, 0x24, 0xC8, 0xDE, - 0x02, 0x7D, 0x09, 0xB4, 0x0A, 0x95, 0x0F, 0xE4, - 0xDB, 0xB7, 0x71, 0x4D, 0x1C, 0xAC, 0x35, 0xCD, - 0x29, 0xDD, 0xC1, 0xF2, 0xF4, 0xC0, 0x5C, 0x74, - 0xDC, 0x87, 0xFD, 0x4F, 0x11, 0x0E, 0x5D, 0x3C, - 0x01, 0x73, 0xE9, 0xD9, 0x10, 0x9A, 0x5B, 0xC5, - 0x98, 0x34, 0x15, 0xAE, 0xF7, 0xAA, 0x67, 0x23, - 0xBC, 0x8B, 0x7B, 0x65, 0xA9, 0xB6, 0x77, 0x00, - 0x19, 0x0C, 0x5E, 0x99, 0xF0, 0x55, 0x86, 0x97, - 0x69, 0xDA, 0x38, 0x9C, 0x16, 0xE8, 0x27, 0xAF, - 0x2E, 0x47, 0x6A, 0xD0, 0x79, 0x44, 0x45, 0x2B, - 0x5F, 0x85, 0xF5, 0x62, 0x70, 0x22, 0x7F, 0xF6, - 0x88, 0x93, 0x60, 0x42, 0x3A, 0x39, 0x49, 0x6E, - 0x89, 0x52, 0x20, 0xF8, 0xCA, 0xD2, 0x76, 0xB9, - 0xAB, 0x7A, 0x9D, 0xD3, 0xBE, 0x1A, 0xAD, 0x41, - 0x56, 0x31, 0x90, 0xB5, 0xB2, 0xEC, 0xA3, 0xE5, - 0x8E, 0x1B, 0xEF, 0xBF, 0x94, 0xC4, 0x0D, 0xB8, - 0x2D, 0x57, 0xE7, 0x82, 0x1E, 0x37, 0x63, 0x43 }; - -static const unsigned char table_86[32] = { - 0x11, 0x07, 0x0F, 0x0A, 0x19, 0x1D, 0x0B, 0x09, - 0x1C, 0x1E, 0x14, 0x06, 0x0C, 0x16, 0x13, 0x04, - 0x15, 0x18, 0x00, 0x0D, 0x12, 0x05, 0x08, 0x02, - 0x10, 0x1A, 0x1F, 0x01, 0x17, 0x0E, 0x03, 0x1B }; - -static const unsigned char table_87[32] = { - 0x17, 0x0E, 0x1D, 0x13, 0x0B, 0x19, 0x03, 0x06, - 0x09, 0x01, 0x0D, 0x15, 0x1C, 0x16, 0x18, 0x1B, - 0x11, 0x10, 0x00, 0x1E, 0x1F, 0x08, 0x12, 0x0F, - 0x02, 0x04, 0x07, 0x1A, 0x14, 0x0A, 0x0C, 0x05 }; - -static const unsigned char table_88[32] = { - 0x09, 0x08, 0x17, 0x10, 0x0A, 0x07, 0x1C, 0x1F, - 0x04, 0x0E, 0x01, 0x0C, 0x0D, 0x1B, 0x03, 0x15, - 0x02, 0x1E, 0x18, 0x19, 0x0F, 0x06, 0x1A, 0x0B, - 0x05, 0x11, 0x14, 0x00, 0x16, 0x1D, 0x12, 0x13 }; - -static const unsigned char table_89[32] = { - 0x15, 0x1C, 0x1D, 0x14, 0x0F, 0x1A, 0x05, 0x02, - 0x07, 0x09, 0x06, 0x08, 0x1F, 0x00, 0x10, 0x13, - 0x0D, 0x03, 0x0C, 0x18, 0x0E, 0x16, 0x1B, 0x1E, - 0x12, 0x04, 0x11, 0x0A, 0x01, 0x0B, 0x17, 0x19 }; - -static const unsigned char table_90[256] = { - 0x62, 0x36, 0x64, 0x0E, 0x4C, 0x6C, 0xBE, 0xCF, - 0x25, 0x5A, 0x3D, 0x12, 0x54, 0x9F, 0xE7, 0xA5, - 0xDE, 0xD7, 0xB2, 0x60, 0x18, 0x8D, 0x89, 0x70, - 0x48, 0x66, 0x1C, 0xA6, 0x17, 0x9B, 0xDF, 0x9A, - 0x82, 0xB9, 0x2E, 0xFA, 0x83, 0x5B, 0x7A, 0x61, - 0xFC, 0x6B, 0x8B, 0x4E, 0x0F, 0xAD, 0x78, 0xE1, - 0xE8, 0x15, 0x1A, 0xF7, 0xA3, 0x3A, 0x04, 0xE3, - 0x30, 0x8C, 0x06, 0xC4, 0x05, 0x32, 0x1F, 0x6A, - 0xB8, 0x37, 0x58, 0xF5, 0x74, 0x63, 0xD4, 0xAC, - 0xA4, 0xF3, 0xEC, 0xBB, 0x8E, 0x65, 0xA0, 0xEE, - 0x6D, 0x11, 0xDD, 0xEA, 0x68, 0x2B, 0xDA, 0x0B, - 0xEF, 0xC3, 0x8F, 0x03, 0x77, 0x1B, 0xFB, 0x1E, - 0x5C, 0xD9, 0xCB, 0x33, 0x55, 0xF1, 0xA1, 0xF9, - 0x7C, 0x38, 0x95, 0x00, 0x6E, 0x85, 0xC2, 0x7F, - 0xBF, 0x84, 0x2A, 0x13, 0x72, 0x81, 0xE9, 0x59, - 0x41, 0x69, 0x3B, 0x0C, 0x90, 0xB4, 0x51, 0x2F, - 0xA2, 0xFE, 0xF8, 0x49, 0x57, 0xE5, 0x96, 0xFF, - 0xCD, 0xD5, 0xCE, 0xAA, 0x40, 0xB0, 0x4D, 0xBA, - 0xDB, 0xC7, 0x46, 0x86, 0xD1, 0xCA, 0xC0, 0x67, - 0x9C, 0x21, 0xAE, 0xB3, 0x7B, 0x87, 0xE2, 0x71, - 0xE6, 0x39, 0xA8, 0x22, 0x07, 0x2C, 0x44, 0x52, - 0xA7, 0xF0, 0x4A, 0x92, 0x56, 0x28, 0x43, 0x8A, - 0x5E, 0x53, 0x93, 0x47, 0x97, 0x88, 0x76, 0x79, - 0x91, 0x26, 0xC1, 0x3F, 0xB7, 0xF6, 0x3E, 0x80, - 0xA9, 0xC6, 0x01, 0xD2, 0xEB, 0x9E, 0x4B, 0xBC, - 0xC8, 0xB5, 0x02, 0x5F, 0x98, 0x9D, 0x5D, 0x35, - 0xD0, 0x16, 0xB1, 0x23, 0x7D, 0xAF, 0x10, 0x3C, - 0xAB, 0x14, 0x09, 0x2D, 0x0D, 0xC5, 0x1D, 0xD6, - 0x42, 0xF2, 0x34, 0x73, 0xF4, 0xFD, 0xE0, 0x24, - 0x6F, 0xD3, 0x75, 0xD8, 0xCC, 0xB6, 0x99, 0x4F, - 0x29, 0x0A, 0x08, 0xE4, 0x27, 0x19, 0x31, 0xC9, - 0x20, 0x94, 0x45, 0xED, 0xDC, 0xBD, 0x7E, 0x50 }; - -static const unsigned char table_91[32] = { - 0x03, 0x04, 0x0C, 0x18, 0x10, 0x0D, 0x13, 0x1B, - 0x1F, 0x07, 0x11, 0x17, 0x1C, 0x1D, 0x05, 0x06, - 0x0A, 0x12, 0x02, 0x1A, 0x0B, 0x01, 0x0E, 0x08, - 0x14, 0x16, 0x00, 0x15, 0x19, 0x09, 0x0F, 0x1E }; - -static const unsigned char table_92[32] = { - 0x1E, 0x10, 0x01, 0x07, 0x11, 0x16, 0x15, 0x17, - 0x1F, 0x14, 0x0C, 0x1C, 0x06, 0x03, 0x00, 0x18, - 0x08, 0x0E, 0x02, 0x1B, 0x09, 0x0D, 0x19, 0x05, - 0x0F, 0x12, 0x0B, 0x13, 0x0A, 0x04, 0x1D, 0x1A }; - -static const unsigned char table_93[256] = { - 0x76, 0x78, 0xA2, 0x94, 0x0E, 0x7F, 0xDF, 0xC1, - 0xB9, 0xE1, 0x3D, 0x59, 0x6F, 0x1E, 0x53, 0x99, - 0x80, 0xE3, 0x21, 0xF8, 0x65, 0xB8, 0x08, 0xBC, - 0x29, 0x17, 0xFD, 0x33, 0x35, 0xF2, 0x70, 0xC7, - 0x25, 0xD0, 0xCD, 0x7A, 0xB7, 0x9B, 0xA5, 0xC3, - 0x00, 0x90, 0xDC, 0xB1, 0x0C, 0x20, 0x67, 0x8D, - 0x43, 0x49, 0xF3, 0x96, 0x14, 0x1A, 0xC8, 0x19, - 0x72, 0xD7, 0x8A, 0x38, 0x66, 0xDA, 0xDD, 0x2E, - 0xBE, 0xD5, 0x91, 0x7C, 0x3A, 0x92, 0x8E, 0xE7, - 0x51, 0xB5, 0xA8, 0xD9, 0x0B, 0x2A, 0xBA, 0x81, - 0x41, 0x0F, 0xBD, 0x4E, 0x31, 0x23, 0x9C, 0x8B, - 0x2B, 0x1D, 0x04, 0x3E, 0x8C, 0xF0, 0x45, 0xA0, - 0x1C, 0x44, 0x55, 0x5E, 0xF1, 0x98, 0x54, 0x5D, - 0x9D, 0x84, 0xAE, 0x09, 0xA9, 0xC5, 0x83, 0x60, - 0x86, 0x95, 0xB4, 0xFA, 0x6B, 0xA7, 0x9A, 0xCA, - 0x8F, 0x4F, 0x0A, 0x7B, 0xB0, 0x02, 0xEA, 0xA4, - 0x18, 0xDB, 0xD3, 0x64, 0xEB, 0xFC, 0xC4, 0xC9, - 0xF5, 0xD6, 0xCC, 0x75, 0x0D, 0x5C, 0x93, 0x4A, - 0x6D, 0xC0, 0x1F, 0x50, 0xE6, 0x16, 0xEE, 0x07, - 0xFB, 0x74, 0x56, 0x58, 0x52, 0x89, 0x79, 0x68, - 0xB6, 0xFE, 0x01, 0xD4, 0x7E, 0x06, 0xBF, 0xCB, - 0x5B, 0xC2, 0xC6, 0x32, 0xAC, 0x26, 0x22, 0xD2, - 0x82, 0x46, 0x69, 0x15, 0x2C, 0xF7, 0xAD, 0x13, - 0x4D, 0xA3, 0xF6, 0x2D, 0x48, 0x71, 0x57, 0x11, - 0x63, 0x05, 0x5F, 0x9E, 0x4B, 0xAB, 0xA6, 0x61, - 0xBB, 0xA1, 0x3C, 0x97, 0xF9, 0x03, 0x40, 0x12, - 0xCF, 0x37, 0xE4, 0x10, 0x6A, 0xED, 0xFF, 0x62, - 0x42, 0x4C, 0xAF, 0x9F, 0xE5, 0xE8, 0xD8, 0xD1, - 0x28, 0x3F, 0x1B, 0xE9, 0xCE, 0x6C, 0x27, 0x88, - 0xEF, 0x2F, 0xE0, 0x30, 0x87, 0x5A, 0x73, 0xB3, - 0x6E, 0x3B, 0x7D, 0x77, 0x36, 0xAA, 0x39, 0xDE, - 0x24, 0x34, 0xE2, 0xEC, 0x85, 0x47, 0xF4, 0xB2 }; - -static const unsigned char table_94[32] = { - 0x1C, 0x07, 0x05, 0x1A, 0x10, 0x1D, 0x14, 0x12, - 0x08, 0x0F, 0x0C, 0x01, 0x04, 0x1B, 0x16, 0x0A, - 0x11, 0x02, 0x1F, 0x13, 0x0D, 0x1E, 0x17, 0x06, - 0x0E, 0x09, 0x15, 0x19, 0x03, 0x18, 0x00, 0x0B }; - -static const unsigned char table_95[32] = { - 0x12, 0x10, 0x11, 0x15, 0x03, 0x0A, 0x14, 0x05, - 0x1D, 0x07, 0x17, 0x0D, 0x09, 0x08, 0x1B, 0x1F, - 0x0B, 0x06, 0x19, 0x0E, 0x18, 0x04, 0x00, 0x02, - 0x1E, 0x1C, 0x01, 0x0C, 0x1A, 0x0F, 0x13, 0x16 }; - -static const unsigned char table_96[256] = { - 0x1C, 0x6E, 0xCD, 0xB4, 0xB3, 0x93, 0xA8, 0x2E, - 0x4F, 0x09, 0xE3, 0x72, 0x64, 0x13, 0x21, 0xF5, - 0x89, 0xB2, 0xD2, 0x22, 0x5D, 0x63, 0x90, 0xC4, - 0x42, 0x9B, 0x07, 0xCA, 0x16, 0x19, 0x5C, 0x2B, - 0x3D, 0xA0, 0x69, 0x5F, 0x52, 0x41, 0x66, 0xC0, - 0x55, 0xDA, 0x82, 0x40, 0x25, 0x02, 0x3C, 0xDD, - 0xAE, 0xD7, 0xD6, 0xDB, 0x04, 0x78, 0x05, 0x4A, - 0x4C, 0x81, 0x00, 0xBE, 0x45, 0xC5, 0x30, 0xB0, - 0x65, 0x5A, 0xA9, 0x38, 0x75, 0x26, 0x85, 0x4E, - 0xF0, 0xA2, 0x91, 0x8A, 0x54, 0xD0, 0x3E, 0x0D, - 0xFE, 0xF2, 0x0A, 0x23, 0x24, 0x37, 0x32, 0x0B, - 0xCB, 0xB5, 0x28, 0x6A, 0x95, 0x49, 0x53, 0x9A, - 0xEE, 0x2C, 0x9D, 0xD4, 0x1D, 0x46, 0xC9, 0x79, - 0xCC, 0xDF, 0x17, 0xE8, 0x6D, 0x29, 0x0E, 0x80, - 0xE0, 0x62, 0xA1, 0xFA, 0x10, 0xF6, 0x03, 0xC1, - 0x15, 0x14, 0x1F, 0x99, 0x97, 0xD5, 0x9E, 0x3F, - 0x7B, 0x2F, 0xEF, 0x2A, 0x68, 0x83, 0xE2, 0x1B, - 0xC8, 0x87, 0x12, 0x70, 0xC7, 0x36, 0xD3, 0x73, - 0x8B, 0x7D, 0x47, 0x9F, 0xD9, 0xFB, 0x6C, 0x5B, - 0xFC, 0xAA, 0xB9, 0xB1, 0x0C, 0x31, 0x8E, 0xF3, - 0x92, 0xA3, 0x4B, 0xF1, 0xC2, 0x3A, 0x67, 0xEA, - 0x77, 0x11, 0xB6, 0xE4, 0x1A, 0x33, 0xD1, 0xBA, - 0xF9, 0xAC, 0x43, 0xE5, 0xC3, 0xC6, 0xFD, 0xF4, - 0x44, 0x6F, 0xB7, 0x88, 0xA7, 0xF8, 0x34, 0x94, - 0x6B, 0x27, 0xDE, 0x1E, 0xDC, 0x01, 0x61, 0x50, - 0xAD, 0x74, 0x4D, 0x86, 0xF7, 0x8D, 0x9C, 0x0F, - 0x5E, 0xBD, 0x08, 0x84, 0x18, 0xED, 0xA5, 0x39, - 0xAB, 0x98, 0x48, 0xE6, 0x2D, 0x96, 0xCF, 0x7F, - 0xFF, 0xBB, 0x8F, 0xEC, 0xBF, 0xE7, 0x56, 0xA4, - 0x35, 0x76, 0xA6, 0xAF, 0xBC, 0x71, 0xE9, 0xB8, - 0x7E, 0x7C, 0x06, 0x3B, 0xEB, 0x60, 0x7A, 0x8C, - 0x59, 0xCE, 0xE1, 0x57, 0x20, 0x58, 0x51, 0xD8 }; - -static const unsigned char table_97[256] = { - 0x15, 0x2D, 0xAF, 0x36, 0xCF, 0xD3, 0xD0, 0xED, - 0xB2, 0x1B, 0xFE, 0x92, 0xBD, 0xAD, 0x58, 0x0F, - 0x76, 0x3C, 0x47, 0x03, 0x2E, 0x4C, 0x40, 0xF7, - 0x39, 0xA7, 0x72, 0x22, 0x95, 0xF3, 0x8C, 0xE0, - 0x79, 0xB6, 0x75, 0x82, 0x94, 0x8F, 0x44, 0xFC, - 0xB0, 0x05, 0xE9, 0x10, 0x68, 0xE7, 0xF1, 0xA5, - 0xA8, 0xE2, 0x6F, 0xBE, 0xE5, 0x54, 0xA2, 0xC6, - 0xDB, 0x1C, 0x9E, 0x6D, 0x14, 0xA1, 0x26, 0x34, - 0x1E, 0x1A, 0x06, 0x53, 0xEE, 0x67, 0xA9, 0x73, - 0xD5, 0x59, 0x2F, 0x61, 0xE6, 0x74, 0xD6, 0x97, - 0xC0, 0x0C, 0xB1, 0x6E, 0x6C, 0x33, 0xC8, 0x77, - 0x8B, 0x49, 0x43, 0xE3, 0xB5, 0xDE, 0x6A, 0xA0, - 0x78, 0x2A, 0xC9, 0xF9, 0x9A, 0xDC, 0x90, 0x55, - 0xF4, 0x16, 0x5E, 0x3F, 0xC5, 0x7C, 0xFA, 0x09, - 0x8E, 0x87, 0xF2, 0x9D, 0x70, 0x27, 0x9B, 0xC4, - 0xCD, 0x91, 0x4B, 0xB4, 0x18, 0xE1, 0x3D, 0x5D, - 0x7A, 0xEA, 0xF0, 0x65, 0xB9, 0xF6, 0xC3, 0x66, - 0x21, 0x96, 0xD1, 0xB8, 0x56, 0x62, 0x48, 0x28, - 0x3A, 0x86, 0x63, 0xD4, 0xD7, 0x41, 0x8D, 0x20, - 0xC2, 0x98, 0x37, 0xD8, 0x85, 0x42, 0x0D, 0x31, - 0x84, 0x4E, 0x11, 0x46, 0x2B, 0x19, 0xCC, 0xB7, - 0x69, 0x13, 0x6B, 0x29, 0x38, 0x7E, 0x0E, 0xD2, - 0x3B, 0x60, 0x89, 0x7F, 0xEF, 0x07, 0x08, 0xCA, - 0xBF, 0x3E, 0xA3, 0xAA, 0x52, 0x4A, 0x45, 0x00, - 0xC7, 0xF8, 0x57, 0xEB, 0x93, 0x9C, 0x4D, 0x7B, - 0x2C, 0xBB, 0xFB, 0xFF, 0x35, 0x4F, 0x32, 0xA6, - 0x23, 0x8A, 0xDD, 0x12, 0xA4, 0x81, 0x17, 0x1D, - 0x1F, 0xCB, 0x0A, 0x71, 0x02, 0xAC, 0xDF, 0x24, - 0xAB, 0x7D, 0x30, 0x5C, 0x01, 0x5A, 0xBA, 0xEC, - 0x51, 0xF5, 0x0B, 0x64, 0xCE, 0xAE, 0x5B, 0x50, - 0x80, 0x88, 0xE8, 0x5F, 0x04, 0xDA, 0xE4, 0xBC, - 0x83, 0x25, 0x9F, 0xD9, 0x99, 0xC1, 0xFD, 0xB3 }; - -static const unsigned char table_98[256] = { - 0xC8, 0xE6, 0x38, 0x93, 0xE5, 0x03, 0x18, 0x1F, - 0xE9, 0x5A, 0xB6, 0xAF, 0xC3, 0x95, 0x00, 0x51, - 0xC0, 0xFD, 0x32, 0xE8, 0x96, 0x57, 0xF0, 0xAA, - 0xDC, 0x71, 0xF8, 0x01, 0x40, 0x0A, 0x4F, 0xB0, - 0x1B, 0x9D, 0x16, 0x92, 0xF3, 0x5E, 0xA9, 0x3C, - 0xBE, 0x6A, 0xA7, 0xE3, 0x35, 0x0D, 0xAD, 0xDB, - 0x48, 0xE0, 0x7E, 0xC6, 0xB4, 0x6D, 0x17, 0x41, - 0x3E, 0xE2, 0x87, 0x12, 0xE1, 0x53, 0xD9, 0x8A, - 0xAC, 0xA6, 0xD8, 0xFA, 0x36, 0x0B, 0x06, 0xDF, - 0x6C, 0x4E, 0xA4, 0xBC, 0xC9, 0xEE, 0x44, 0x26, - 0xF2, 0xE4, 0x9E, 0x34, 0xEF, 0x05, 0x0F, 0x7F, - 0xD1, 0xCD, 0x67, 0x28, 0xC1, 0x8E, 0x7D, 0x90, - 0x8F, 0x60, 0x1E, 0x19, 0xBD, 0x77, 0xB8, 0xD5, - 0x3D, 0x8C, 0x31, 0x99, 0x08, 0xDD, 0x04, 0x30, - 0x61, 0xFB, 0xEB, 0x98, 0x15, 0xFC, 0x10, 0xDE, - 0x20, 0xBA, 0xA1, 0xB3, 0xD4, 0x91, 0x6F, 0x9F, - 0x94, 0x5B, 0x42, 0xCB, 0x75, 0x1C, 0xBB, 0x5C, - 0x5D, 0xD6, 0x66, 0x50, 0xB9, 0xF1, 0x82, 0x7B, - 0x33, 0x23, 0x4A, 0xA5, 0x55, 0x97, 0xEA, 0x37, - 0xF4, 0x64, 0x6E, 0xBF, 0x8B, 0xB1, 0x07, 0x9A, - 0x43, 0x11, 0x65, 0xC2, 0x02, 0xDA, 0x9B, 0x25, - 0xCA, 0x3B, 0x7A, 0xCE, 0xA8, 0xCF, 0xF7, 0x56, - 0x6B, 0xF9, 0x47, 0x2A, 0x2E, 0x1D, 0x2D, 0xE7, - 0x46, 0xD0, 0x62, 0x4C, 0x80, 0x4B, 0x2B, 0xF5, - 0x69, 0x9C, 0x45, 0xED, 0x83, 0xAB, 0x74, 0x39, - 0xA3, 0x85, 0xD7, 0x5F, 0xB2, 0x86, 0x22, 0x29, - 0x89, 0x49, 0x1A, 0xC4, 0x52, 0xEC, 0x8D, 0x73, - 0xD3, 0x7C, 0x79, 0xD2, 0x14, 0x4D, 0x84, 0xA2, - 0x0E, 0x70, 0x78, 0x72, 0xB7, 0xA0, 0xC5, 0x81, - 0x58, 0x0C, 0x68, 0x27, 0xFF, 0xF6, 0xAE, 0xCC, - 0x88, 0xFE, 0x24, 0x2F, 0x76, 0x3F, 0x59, 0x21, - 0x54, 0x3A, 0x13, 0x09, 0x2C, 0xB5, 0xC7, 0x63 }; - -static const unsigned char table_99[32] = { - 0x19, 0x00, 0x10, 0x18, 0x09, 0x11, 0x13, 0x1D, - 0x08, 0x1A, 0x02, 0x05, 0x03, 0x17, 0x12, 0x01, - 0x1F, 0x14, 0x06, 0x07, 0x15, 0x0D, 0x0F, 0x0B, - 0x0E, 0x16, 0x1E, 0x04, 0x1B, 0x0A, 0x0C, 0x1C }; - -static const unsigned char table_100[256] = { - 0x9B, 0x3A, 0xAE, 0x60, 0x27, 0x67, 0x1E, 0x4E, - 0x91, 0xDA, 0x85, 0x43, 0x5C, 0xCC, 0x89, 0x55, - 0x75, 0x56, 0xF2, 0x86, 0xEB, 0xC4, 0x0D, 0xE6, - 0x63, 0x88, 0x38, 0x59, 0x68, 0xD0, 0x18, 0xF0, - 0xBA, 0x28, 0xF5, 0x80, 0x02, 0x5B, 0xE1, 0xA4, - 0x7A, 0x4B, 0x8E, 0xF7, 0x9E, 0x99, 0x70, 0xEF, - 0x66, 0x50, 0xB1, 0xCD, 0x9A, 0xAF, 0x5F, 0x21, - 0xE5, 0x5D, 0x14, 0xD4, 0x34, 0x22, 0xC3, 0x0F, - 0x44, 0xB6, 0x92, 0xCE, 0xB4, 0x6E, 0xB0, 0x00, - 0xF9, 0xB5, 0x10, 0xEA, 0x45, 0x2F, 0x2B, 0xF4, - 0xF6, 0xFE, 0xCB, 0x0A, 0x42, 0xF8, 0xE7, 0xFD, - 0xC8, 0xC2, 0x6C, 0x9C, 0x57, 0xA1, 0x46, 0x04, - 0xE9, 0x97, 0x40, 0x32, 0x19, 0xFA, 0x51, 0xD1, - 0x6D, 0x4C, 0x2A, 0xD9, 0x95, 0x26, 0x72, 0x1B, - 0x83, 0x93, 0x5A, 0x15, 0x33, 0xC5, 0x77, 0x13, - 0xE0, 0x36, 0x37, 0xDB, 0xA7, 0xC7, 0x81, 0x62, - 0xC1, 0x47, 0x64, 0x74, 0x1D, 0x84, 0x29, 0x39, - 0x41, 0x35, 0x09, 0x90, 0x20, 0x9F, 0x8C, 0x7D, - 0x3E, 0x07, 0xB9, 0x76, 0x06, 0xA3, 0x31, 0x7F, - 0x49, 0x6F, 0x3D, 0xD5, 0x25, 0xAC, 0xDF, 0x0B, - 0x3C, 0x79, 0x01, 0x8F, 0x82, 0x2E, 0xFC, 0x98, - 0xA5, 0x58, 0xA0, 0x4A, 0x7C, 0x24, 0xDD, 0x05, - 0x4D, 0x12, 0xBC, 0xAA, 0xE2, 0xAB, 0xD3, 0xBF, - 0x94, 0x2D, 0x54, 0xBB, 0xAD, 0xB7, 0x6A, 0xE3, - 0xBD, 0x5E, 0x8D, 0x08, 0x3B, 0xB8, 0x73, 0x8A, - 0x16, 0xD2, 0x69, 0xE8, 0xEE, 0x53, 0xD8, 0xDC, - 0x48, 0xCF, 0xC6, 0xA9, 0x1A, 0xCA, 0x17, 0x11, - 0xED, 0xC0, 0xA6, 0x1F, 0x96, 0x8B, 0xFF, 0x78, - 0x03, 0x61, 0x1C, 0xA8, 0x3F, 0x9D, 0x0E, 0xC9, - 0xE4, 0xA2, 0x52, 0xEC, 0x4F, 0xD6, 0xF3, 0x6B, - 0x87, 0xB3, 0x7E, 0xDE, 0xD7, 0x71, 0x65, 0xF1, - 0x30, 0x0C, 0xB2, 0x7B, 0xBE, 0xFB, 0x23, 0x2C }; - -static const unsigned char table_101[32] = { - 0x18, 0x08, 0x14, 0x17, 0x03, 0x10, 0x19, 0x04, - 0x0D, 0x1C, 0x06, 0x1D, 0x1E, 0x12, 0x11, 0x0B, - 0x0F, 0x02, 0x0E, 0x1B, 0x13, 0x05, 0x07, 0x16, - 0x15, 0x0A, 0x0C, 0x1A, 0x00, 0x01, 0x1F, 0x09 }; - -static const unsigned char table_102[32] = { - 0x17, 0x1F, 0x0E, 0x05, 0x13, 0x0C, 0x14, 0x1A, - 0x0F, 0x01, 0x12, 0x1C, 0x00, 0x07, 0x0D, 0x02, - 0x10, 0x16, 0x04, 0x11, 0x1D, 0x03, 0x1E, 0x18, - 0x06, 0x15, 0x0A, 0x19, 0x09, 0x08, 0x1B, 0x0B }; - -static const unsigned char table_103[32] = { - 0x0F, 0x09, 0x1E, 0x11, 0x0D, 0x08, 0x10, 0x00, - 0x01, 0x1F, 0x1D, 0x1C, 0x12, 0x04, 0x07, 0x05, - 0x19, 0x14, 0x1B, 0x02, 0x1A, 0x15, 0x17, 0x16, - 0x18, 0x0B, 0x0A, 0x13, 0x0C, 0x0E, 0x03, 0x06 }; - -static const unsigned char table_104[256] = { - 0xA4, 0x9F, 0x78, 0x39, 0x3D, 0x81, 0x51, 0x24, - 0x46, 0x2A, 0x56, 0xE8, 0xDF, 0x73, 0xA8, 0xA2, - 0x0D, 0xDC, 0xA5, 0x4F, 0xF0, 0x93, 0xC0, 0x76, - 0x38, 0x70, 0xB0, 0x30, 0x98, 0x13, 0x8B, 0x14, - 0x26, 0x45, 0x0F, 0x7D, 0x34, 0x72, 0x6B, 0x89, - 0x43, 0xE2, 0x96, 0x5B, 0xEF, 0x2B, 0xF9, 0xDE, - 0x82, 0xB5, 0x61, 0x4A, 0x17, 0xC2, 0x5A, 0xCB, - 0xB2, 0x8D, 0xE4, 0xEC, 0xD9, 0x80, 0xBC, 0x62, - 0x67, 0x11, 0xA9, 0x3A, 0xE1, 0xC4, 0xEA, 0xD2, - 0x71, 0xD0, 0xDB, 0xE5, 0x7B, 0x08, 0x77, 0xD6, - 0x10, 0x19, 0x48, 0xEB, 0xAA, 0x2C, 0x0C, 0x59, - 0xBE, 0xF6, 0x28, 0x50, 0x90, 0x87, 0xCD, 0x04, - 0x1F, 0x79, 0x99, 0x5C, 0x49, 0x06, 0x8A, 0x3E, - 0x5F, 0x5E, 0x15, 0x23, 0x2D, 0xB6, 0xA6, 0x7A, - 0x03, 0x20, 0xDA, 0xFB, 0x35, 0x75, 0xC7, 0x47, - 0xB9, 0x7C, 0xA1, 0xCE, 0xC5, 0xDD, 0xFD, 0x6C, - 0x05, 0xAC, 0x09, 0xB4, 0x95, 0xD1, 0xB1, 0x63, - 0xFF, 0xAE, 0xD5, 0x25, 0x1E, 0x6E, 0x57, 0x18, - 0x74, 0xE6, 0x2F, 0x9A, 0xE7, 0x42, 0x65, 0xF5, - 0x58, 0x27, 0x33, 0x9C, 0xCF, 0xB7, 0xC3, 0xF1, - 0x12, 0x1D, 0xB8, 0xF4, 0x64, 0x4D, 0xD4, 0xBD, - 0xE3, 0xAB, 0x44, 0x60, 0xAF, 0xCC, 0x0A, 0xFC, - 0xD3, 0x21, 0x0B, 0x1A, 0x6D, 0x83, 0xA7, 0x8E, - 0x3C, 0xC1, 0xED, 0xF3, 0x2E, 0x86, 0xC9, 0x41, - 0x02, 0xF7, 0xC8, 0x40, 0x1B, 0xF8, 0xF2, 0x07, - 0x5D, 0x4E, 0xC6, 0x29, 0xD7, 0x4B, 0x7E, 0x31, - 0x94, 0x32, 0x01, 0x92, 0xE9, 0x36, 0x0E, 0x7F, - 0x85, 0x16, 0xFA, 0x00, 0x88, 0x3F, 0x68, 0x4C, - 0x22, 0x55, 0xBF, 0x9D, 0xE0, 0x6A, 0xAD, 0xBA, - 0x91, 0xCA, 0xA3, 0x1C, 0xEE, 0xD8, 0x3B, 0x66, - 0x69, 0x9B, 0x84, 0xA0, 0xB3, 0x6F, 0xFE, 0x52, - 0x97, 0xBB, 0x37, 0x8C, 0x54, 0x53, 0x9E, 0x8F }; - -static const unsigned char table_105[256] = { - 0x7B, 0x35, 0x11, 0x79, 0x07, 0x2F, 0xF6, 0x82, - 0x8E, 0xB4, 0x6E, 0xD2, 0x6D, 0xC5, 0x8C, 0x1C, - 0xE0, 0xD6, 0x34, 0xF0, 0x4F, 0x25, 0x59, 0xE8, - 0xDF, 0x1D, 0xEB, 0x32, 0x86, 0x51, 0xA4, 0xF2, - 0x5C, 0xD1, 0xC8, 0x41, 0xEC, 0x9D, 0x62, 0xAC, - 0xDD, 0x3E, 0xB8, 0x65, 0x75, 0x89, 0x12, 0x6C, - 0x40, 0x4E, 0xC7, 0x27, 0xE1, 0x37, 0xCF, 0x09, - 0x16, 0x78, 0xAA, 0x58, 0x0D, 0xE6, 0x54, 0xFE, - 0x8F, 0xFD, 0xF9, 0x61, 0x26, 0x3F, 0x2E, 0xCD, - 0x2C, 0x04, 0xB2, 0x80, 0x0F, 0x14, 0x6F, 0xC6, - 0xAB, 0xFB, 0x13, 0xDB, 0x9A, 0x21, 0xB3, 0xC0, - 0xA9, 0x19, 0x70, 0xF3, 0x2B, 0xAE, 0x9B, 0x49, - 0xB7, 0xA8, 0x24, 0x1B, 0x48, 0xEA, 0xED, 0xD9, - 0x47, 0x9E, 0x9C, 0x69, 0x3C, 0x66, 0xBB, 0x06, - 0x46, 0x38, 0x17, 0xB5, 0xCB, 0x05, 0x4A, 0x5E, - 0x15, 0x20, 0xB9, 0xB6, 0x33, 0x4C, 0x7D, 0xA3, - 0xD7, 0xB1, 0x23, 0x72, 0xC3, 0x4B, 0x63, 0xBE, - 0xF7, 0x5B, 0x74, 0x64, 0x77, 0xCC, 0xD3, 0x85, - 0xDE, 0x1A, 0x31, 0x97, 0xA2, 0x8B, 0xFC, 0x10, - 0x5F, 0xDC, 0xD5, 0xB0, 0xBD, 0x55, 0xC1, 0xE7, - 0x0C, 0x50, 0x43, 0x39, 0x71, 0x52, 0xE5, 0xAF, - 0x8A, 0x60, 0x92, 0x2D, 0xD8, 0x03, 0xF5, 0x28, - 0xCA, 0xEF, 0xD0, 0xC2, 0x53, 0x91, 0xA6, 0x73, - 0x56, 0xA5, 0xF1, 0x57, 0x42, 0xF4, 0xD4, 0x36, - 0x8D, 0xBC, 0xE9, 0x7E, 0x02, 0x76, 0x18, 0x0B, - 0x84, 0x5A, 0xE2, 0xBF, 0x68, 0x95, 0x29, 0x98, - 0xAD, 0x88, 0x1F, 0x81, 0x67, 0xA1, 0x3A, 0xA7, - 0x22, 0xF8, 0x01, 0xA0, 0xCE, 0x7A, 0xDA, 0x30, - 0xC4, 0xE4, 0xEE, 0x7C, 0x3B, 0x4D, 0x3D, 0xE3, - 0xFA, 0x6A, 0x7F, 0x99, 0x00, 0x93, 0x0E, 0xFF, - 0x90, 0x0A, 0x2A, 0x5D, 0x96, 0x08, 0x6B, 0x83, - 0xBA, 0x1E, 0x44, 0x87, 0x45, 0x9F, 0xC9, 0x94 }; - -static const unsigned char table_106[32] = { - 0x03, 0x11, 0x07, 0x1B, 0x0F, 0x14, 0x0C, 0x01, - 0x04, 0x02, 0x09, 0x0A, 0x05, 0x12, 0x06, 0x1F, - 0x1C, 0x0E, 0x0D, 0x15, 0x18, 0x08, 0x00, 0x10, - 0x1E, 0x1D, 0x17, 0x19, 0x13, 0x16, 0x0B, 0x1A }; - -static const unsigned char table_107[32] = { - 0x13, 0x1B, 0x06, 0x11, 0x1C, 0x07, 0x08, 0x0E, - 0x10, 0x05, 0x09, 0x18, 0x04, 0x15, 0x1E, 0x0F, - 0x1F, 0x12, 0x02, 0x00, 0x17, 0x19, 0x1A, 0x0D, - 0x03, 0x0C, 0x0A, 0x1D, 0x14, 0x01, 0x16, 0x0B }; - -static const unsigned char table_108[256] = { - 0x99, 0xA3, 0x48, 0xE8, 0x5A, 0x7D, 0x97, 0xCA, - 0x7F, 0x06, 0x9B, 0x04, 0xE0, 0xF3, 0x18, 0xAE, - 0x59, 0xA0, 0x2B, 0x15, 0x85, 0x3E, 0x12, 0x93, - 0x3D, 0x28, 0x32, 0xF5, 0x20, 0x5D, 0x86, 0x00, - 0x1B, 0x2E, 0x36, 0x10, 0x5E, 0x6C, 0xD8, 0x29, - 0xB6, 0x3F, 0x05, 0x1C, 0xCE, 0xC2, 0x34, 0x5F, - 0x5C, 0x79, 0xD1, 0x1F, 0xA2, 0xEE, 0x8A, 0x69, - 0xB5, 0x87, 0x96, 0x6D, 0x4D, 0xC1, 0x61, 0x2C, - 0x11, 0xE7, 0x8E, 0xBF, 0x1E, 0x53, 0xD0, 0x58, - 0x76, 0xA4, 0x60, 0xA9, 0xB0, 0xF9, 0xEA, 0x3C, - 0x52, 0x9A, 0x24, 0xF1, 0x9F, 0xD3, 0x40, 0x0A, - 0x63, 0x78, 0x6A, 0x8B, 0x08, 0x22, 0x16, 0x83, - 0x6B, 0xD2, 0x49, 0x19, 0xBD, 0xFD, 0x62, 0x72, - 0xA8, 0x55, 0xAB, 0x0C, 0xB9, 0x13, 0xD5, 0xF0, - 0xF2, 0x84, 0xAF, 0x2F, 0x7B, 0x2A, 0x21, 0x0F, - 0xDA, 0x30, 0x71, 0xD6, 0x81, 0xE6, 0xEC, 0x41, - 0x90, 0x50, 0x66, 0x0E, 0xA7, 0xB8, 0xF7, 0x3A, - 0xB2, 0xCF, 0x3B, 0xFC, 0x56, 0x6F, 0xC3, 0xA6, - 0xC9, 0xA1, 0x8D, 0xBB, 0x9D, 0x75, 0xF6, 0xAA, - 0x7E, 0xF8, 0x33, 0xEF, 0xBC, 0x7C, 0x23, 0x1A, - 0x92, 0x6E, 0x2D, 0x8F, 0xED, 0xB7, 0xB1, 0x1D, - 0x67, 0x39, 0xAC, 0x0D, 0x74, 0xDB, 0x7A, 0x94, - 0x07, 0x09, 0xC0, 0xD7, 0xAD, 0xFE, 0x54, 0x91, - 0xDE, 0x45, 0xA5, 0x77, 0xCB, 0x37, 0xC6, 0x38, - 0x89, 0x88, 0x17, 0xD9, 0x4F, 0xDF, 0x25, 0xFB, - 0xFA, 0x4C, 0x80, 0x35, 0x82, 0xF4, 0x95, 0xC8, - 0xFF, 0xE9, 0x31, 0x01, 0x14, 0xB3, 0x02, 0x9E, - 0x4E, 0x43, 0x46, 0xC7, 0xEB, 0x51, 0xE5, 0x47, - 0xB4, 0xE3, 0xDC, 0x57, 0xC4, 0x98, 0x03, 0xE1, - 0xBA, 0x68, 0xCD, 0x27, 0xC5, 0x0B, 0xD4, 0x64, - 0x4B, 0x9C, 0x70, 0x65, 0x4A, 0xE4, 0x42, 0xDD, - 0xCC, 0xE2, 0x44, 0x73, 0xBE, 0x26, 0x8C, 0x5B }; - -static const unsigned char table_109[256] = { - 0xE3, 0x95, 0xDB, 0x09, 0x82, 0x0A, 0x8F, 0x9E, - 0xC9, 0xDC, 0x28, 0x35, 0x0F, 0x8B, 0xA8, 0xA5, - 0x7F, 0x3D, 0x8C, 0xD1, 0x93, 0x57, 0x04, 0xAA, - 0x6A, 0x98, 0x81, 0xDD, 0x16, 0x67, 0x2E, 0xDF, - 0xED, 0xF7, 0xB2, 0xBD, 0x14, 0xB6, 0x76, 0xC8, - 0x75, 0x9F, 0x48, 0xAE, 0xBB, 0xB0, 0xF3, 0xE2, - 0xD4, 0x59, 0xD8, 0x9C, 0x64, 0xC1, 0x73, 0x21, - 0x6D, 0x96, 0x7B, 0x62, 0x56, 0x55, 0xCC, 0xFD, - 0xCE, 0x41, 0xA3, 0x43, 0x33, 0xAF, 0x23, 0x9D, - 0x6F, 0x65, 0x19, 0x52, 0xAD, 0xC6, 0xD3, 0x3F, - 0x66, 0xFF, 0xD0, 0x30, 0x6C, 0xC0, 0xEB, 0xCF, - 0x51, 0x88, 0x38, 0x72, 0x69, 0x77, 0x3B, 0xFA, - 0xBA, 0xB7, 0xA1, 0x91, 0xE0, 0x89, 0xAB, 0x44, - 0x1B, 0x05, 0x5B, 0xB9, 0x71, 0x47, 0x7E, 0xFB, - 0x02, 0xC7, 0x99, 0x6E, 0x42, 0x20, 0x90, 0x1F, - 0x4A, 0x85, 0x1A, 0xEA, 0x0C, 0x0D, 0xB3, 0xDA, - 0xE7, 0x13, 0xE6, 0xD7, 0x6B, 0x12, 0x46, 0x53, - 0xB5, 0xF8, 0x1D, 0x83, 0x54, 0x49, 0x8A, 0x26, - 0x4D, 0xDE, 0xF6, 0x03, 0xA2, 0x7D, 0x0E, 0xA0, - 0x68, 0x79, 0xCA, 0x0B, 0x5D, 0x40, 0x4F, 0x80, - 0xC2, 0xD6, 0x87, 0x70, 0xF0, 0xD2, 0x92, 0xEE, - 0xBE, 0x74, 0x5F, 0xBC, 0xA4, 0x4B, 0xFE, 0x37, - 0x60, 0xA9, 0x06, 0xA7, 0xE1, 0xF5, 0x2B, 0x10, - 0xEF, 0x2C, 0x07, 0x86, 0x7A, 0x27, 0xE9, 0xC5, - 0xAC, 0x32, 0x22, 0xF2, 0xE5, 0x8D, 0x31, 0x01, - 0x34, 0xA6, 0xB8, 0xC3, 0x3C, 0xE4, 0x08, 0x94, - 0x15, 0x4E, 0xB4, 0x39, 0x58, 0x00, 0x3E, 0x29, - 0x45, 0x3A, 0x84, 0x36, 0xF1, 0x2A, 0x50, 0x11, - 0xC4, 0x5A, 0xFC, 0xBF, 0xD9, 0xF9, 0x17, 0x9B, - 0x8E, 0x18, 0x63, 0x4C, 0x2F, 0x78, 0x2D, 0x5E, - 0x9A, 0xCD, 0x24, 0xEC, 0x7C, 0x97, 0x61, 0xCB, - 0x1E, 0xF4, 0xD5, 0xB1, 0x5C, 0x25, 0xE8, 0x1C }; - -static const unsigned char table_110[256] = { - 0xC3, 0x06, 0x3C, 0xCB, 0xD2, 0x44, 0x9D, 0x48, - 0x28, 0xAA, 0xA9, 0xD0, 0x64, 0x25, 0x56, 0xCA, - 0xC2, 0xF8, 0x5C, 0xAE, 0x4E, 0x63, 0xB2, 0xE9, - 0x35, 0x11, 0xA8, 0x1A, 0x76, 0x15, 0xE0, 0x26, - 0x97, 0x99, 0xD4, 0x43, 0x80, 0xEE, 0xC1, 0x69, - 0xA6, 0x1E, 0x7A, 0x42, 0x55, 0x38, 0xBF, 0x75, - 0x0E, 0x29, 0xF5, 0xF3, 0x36, 0x7D, 0x51, 0xE8, - 0xE5, 0xEB, 0x68, 0x60, 0x0C, 0x70, 0xFD, 0xCC, - 0xE3, 0x23, 0x09, 0x6D, 0x2D, 0x6C, 0x5E, 0xB6, - 0x98, 0x8B, 0x1F, 0x50, 0x34, 0x8D, 0x10, 0x92, - 0x82, 0x85, 0xD5, 0x79, 0x02, 0xA4, 0x0A, 0xBC, - 0x40, 0xC6, 0xA3, 0x72, 0x8F, 0xC4, 0xA5, 0xE4, - 0x49, 0xD6, 0xCE, 0xA1, 0x12, 0x4F, 0x30, 0x31, - 0xDE, 0x2A, 0xF7, 0x95, 0xB5, 0x96, 0x14, 0x08, - 0xE6, 0x3D, 0x86, 0xF2, 0x47, 0x74, 0xB8, 0x5D, - 0x1D, 0x2B, 0x3A, 0x93, 0x7C, 0x6A, 0x01, 0xA0, - 0x9A, 0x4D, 0xB7, 0x71, 0xA7, 0x41, 0xC5, 0x65, - 0xC8, 0x89, 0xD1, 0x3E, 0x0D, 0xD8, 0xFF, 0x6F, - 0x7F, 0xA2, 0xFE, 0xD9, 0xF0, 0x4A, 0x07, 0x1C, - 0x0F, 0x6E, 0x03, 0x81, 0x1B, 0x05, 0xDF, 0x52, - 0xF1, 0x8A, 0xF9, 0xDD, 0x91, 0x3B, 0xD7, 0xE1, - 0x54, 0xAD, 0x90, 0x5A, 0x7B, 0xC7, 0x32, 0x62, - 0x16, 0x27, 0xB9, 0x66, 0x21, 0x88, 0xBD, 0x18, - 0x77, 0x8E, 0x94, 0x8C, 0x9B, 0x46, 0x9C, 0xB1, - 0xD3, 0x53, 0xB0, 0xBE, 0xAC, 0xAF, 0x73, 0x24, - 0xDA, 0x58, 0xE2, 0xFC, 0x78, 0xEA, 0xCD, 0xFA, - 0x37, 0xED, 0x13, 0x19, 0xC0, 0x59, 0x83, 0xBA, - 0x3F, 0x57, 0x00, 0x7E, 0xC9, 0x2E, 0x17, 0x5B, - 0x84, 0xF6, 0xE7, 0x22, 0xFB, 0x5F, 0x4C, 0x2C, - 0x61, 0x9F, 0x45, 0x39, 0xB3, 0xEC, 0x04, 0x87, - 0x67, 0xDC, 0x0B, 0xF4, 0x20, 0xAB, 0x6B, 0x9E, - 0x4B, 0xCF, 0xB4, 0x2F, 0xBB, 0xEF, 0xDB, 0x33 }; - -static const unsigned char table_111[32] = { - 0x09, 0x0F, 0x00, 0x15, 0x12, 0x17, 0x1A, 0x0D, - 0x1C, 0x0B, 0x01, 0x0A, 0x05, 0x1E, 0x1D, 0x0C, - 0x1B, 0x08, 0x19, 0x18, 0x14, 0x07, 0x0E, 0x03, - 0x10, 0x16, 0x11, 0x1F, 0x04, 0x06, 0x02, 0x13 }; - -static const unsigned char table_112[256] = { - 0xF9, 0x7D, 0xBE, 0xD5, 0x9F, 0xB8, 0x95, 0x43, - 0xDB, 0xAE, 0x7E, 0xEC, 0x5B, 0x58, 0x18, 0x49, - 0x4B, 0x9D, 0x1C, 0x3E, 0x61, 0xD1, 0xF6, 0x2F, - 0x41, 0x82, 0x51, 0x37, 0x72, 0x79, 0x05, 0x2A, - 0xC2, 0xB0, 0xE2, 0xE7, 0xB2, 0xF3, 0x1B, 0x92, - 0x86, 0xBB, 0xDC, 0x90, 0x1A, 0x19, 0xD7, 0xBA, - 0x2C, 0x7B, 0xEF, 0xC7, 0x8A, 0x81, 0xEB, 0xDE, - 0x73, 0x4E, 0xB7, 0x97, 0xCA, 0x29, 0x85, 0xC1, - 0xA5, 0x7F, 0xFE, 0x56, 0xE9, 0x9E, 0x21, 0x76, - 0x3A, 0x88, 0x70, 0xC6, 0xD3, 0x8C, 0x47, 0xC8, - 0x83, 0x48, 0xC3, 0x6A, 0x9C, 0x80, 0x53, 0xBD, - 0xFD, 0x54, 0x09, 0x91, 0x94, 0xAA, 0x7A, 0x59, - 0x71, 0xDD, 0xA8, 0x07, 0xCB, 0x0F, 0xE0, 0x9A, - 0x36, 0x4C, 0x4D, 0x0D, 0xA4, 0x96, 0x6F, 0x14, - 0x22, 0x38, 0xAD, 0x02, 0xF4, 0x0B, 0xEA, 0x93, - 0x20, 0x04, 0xBC, 0xE8, 0x6C, 0xFB, 0x10, 0x6B, - 0x40, 0xB6, 0x24, 0x17, 0x06, 0x31, 0xD9, 0x33, - 0xF5, 0x99, 0x57, 0xCD, 0xAB, 0x67, 0x5C, 0x30, - 0x1E, 0x34, 0xB4, 0x3F, 0x16, 0x42, 0xA2, 0x68, - 0x27, 0xB3, 0x1D, 0xED, 0x5F, 0x52, 0xF7, 0x3C, - 0x65, 0x5D, 0xE5, 0x23, 0x0C, 0x6D, 0x84, 0x6E, - 0xDA, 0x77, 0xF8, 0x15, 0xFA, 0x69, 0xD0, 0xA7, - 0x11, 0xAC, 0xA6, 0xA3, 0x1F, 0x2E, 0xBF, 0x4A, - 0x8F, 0xFC, 0xEE, 0xC9, 0x26, 0x12, 0xC0, 0xB1, - 0x45, 0x0E, 0x3D, 0x7C, 0xCE, 0x13, 0x8E, 0x98, - 0x46, 0x2B, 0xC5, 0x66, 0x28, 0x32, 0xD2, 0x03, - 0xE3, 0xC4, 0x9B, 0x89, 0x5E, 0xF0, 0xCF, 0x3B, - 0x2D, 0x50, 0xB5, 0x00, 0x0A, 0xD6, 0x55, 0xE1, - 0x62, 0x63, 0x64, 0x87, 0xAF, 0x78, 0xB9, 0xF2, - 0x25, 0x44, 0xFF, 0x39, 0xF1, 0x08, 0x4F, 0x74, - 0xA9, 0x8B, 0x75, 0x01, 0xA0, 0xE4, 0x35, 0x8D, - 0xA1, 0xCC, 0xDF, 0x60, 0xD8, 0x5A, 0xE6, 0xD4 }; - -static const unsigned char table_113[256] = { - 0x46, 0x9D, 0x39, 0xB2, 0x8D, 0x3B, 0x59, 0x5A, - 0xD0, 0x9C, 0xE4, 0x04, 0x01, 0xE2, 0xB3, 0xD2, - 0xD7, 0x18, 0x40, 0xD8, 0xF1, 0xEF, 0x3A, 0x1D, - 0x8E, 0xE5, 0xD9, 0xD3, 0xCB, 0x49, 0x4C, 0xCF, - 0xC0, 0xD6, 0xB5, 0x73, 0x77, 0x82, 0x54, 0xA2, - 0xB1, 0xB0, 0x84, 0x5D, 0xC7, 0xDE, 0x31, 0x2F, - 0x50, 0x78, 0xBE, 0x94, 0x64, 0x44, 0x60, 0x7A, - 0x1A, 0x6E, 0x09, 0x6F, 0xBF, 0x76, 0x81, 0x38, - 0x22, 0xC3, 0xEE, 0x8F, 0xFB, 0x32, 0xED, 0x92, - 0xAE, 0xE6, 0x5F, 0xAA, 0xAC, 0x0D, 0xA3, 0x47, - 0x1F, 0x11, 0xC1, 0x29, 0xAF, 0xFD, 0x1C, 0xDB, - 0x00, 0x23, 0xB9, 0xB8, 0x91, 0x41, 0x27, 0x37, - 0x43, 0x02, 0x26, 0xF6, 0x7D, 0x0A, 0x85, 0x93, - 0x97, 0x2E, 0x20, 0x55, 0x13, 0x4B, 0x6C, 0xE7, - 0xFC, 0x25, 0xFA, 0x9E, 0x5B, 0xA1, 0xDF, 0x2C, - 0x3E, 0xBC, 0xEA, 0x42, 0x7C, 0x36, 0x30, 0xEB, - 0xBD, 0x8B, 0x87, 0x16, 0x3D, 0x5C, 0x07, 0xBA, - 0xB4, 0x1B, 0xC2, 0xE3, 0x71, 0x9A, 0x5E, 0x4D, - 0xF2, 0xCC, 0x0E, 0xE1, 0x34, 0x75, 0x58, 0x89, - 0x17, 0xD4, 0x68, 0x80, 0x2B, 0x74, 0x70, 0x8A, - 0x63, 0xE8, 0x56, 0x24, 0xD1, 0x57, 0x35, 0x6D, - 0x3C, 0xA6, 0xC8, 0x7E, 0xA8, 0x4E, 0xC4, 0x33, - 0xA9, 0x62, 0x61, 0x7F, 0x21, 0x98, 0x2A, 0xAD, - 0xB6, 0xA7, 0xF5, 0x3F, 0x15, 0x45, 0xF8, 0xA4, - 0x95, 0x88, 0xDC, 0x96, 0x90, 0x08, 0x9B, 0xF9, - 0x06, 0x14, 0x05, 0xF0, 0xF7, 0xA0, 0xE0, 0x65, - 0xCA, 0xA5, 0x9F, 0x79, 0xCD, 0x4F, 0x72, 0xB7, - 0x4A, 0x0F, 0x66, 0xC5, 0x0C, 0x52, 0xF3, 0x69, - 0x83, 0x03, 0x99, 0x1E, 0x2D, 0xDA, 0x8C, 0x53, - 0x28, 0xDD, 0xE9, 0x0B, 0xC9, 0xF4, 0x48, 0x12, - 0x6A, 0x19, 0xCE, 0xAB, 0x51, 0xD5, 0x6B, 0xBB, - 0xFE, 0x7B, 0x67, 0xFF, 0x10, 0xEC, 0xC6, 0x86 }; - -static const unsigned char table_114[32] = { - 0x11, 0x10, 0x04, 0x1D, 0x08, 0x15, 0x1A, 0x1B, - 0x14, 0x18, 0x0F, 0x17, 0x16, 0x07, 0x1E, 0x0E, - 0x12, 0x0A, 0x13, 0x0B, 0x0C, 0x00, 0x06, 0x02, - 0x1F, 0x19, 0x09, 0x1C, 0x01, 0x0D, 0x03, 0x05 }; - -static const unsigned char table_115[256] = { - 0xB7, 0xBB, 0x63, 0x0D, 0xF0, 0x33, 0x5A, 0x05, - 0xF2, 0x7F, 0x64, 0xDB, 0x51, 0xC9, 0x2C, 0x85, - 0x4F, 0x41, 0xA4, 0x42, 0xCF, 0xA6, 0x52, 0x2F, - 0x26, 0xEF, 0xFB, 0x29, 0x40, 0x16, 0xF7, 0xED, - 0x23, 0x69, 0x8A, 0xDF, 0x77, 0x28, 0x93, 0x14, - 0x82, 0x0C, 0xBE, 0x3D, 0x20, 0xB4, 0x79, 0x94, - 0x54, 0xF8, 0x07, 0xB1, 0xE1, 0x66, 0x73, 0xD3, - 0x19, 0x15, 0xFF, 0x03, 0x6A, 0x9A, 0xDC, 0x1C, - 0xB3, 0x5D, 0x76, 0x68, 0x47, 0x6C, 0xF9, 0xFD, - 0xE9, 0xDD, 0x01, 0x65, 0xBD, 0x80, 0x0E, 0x7A, - 0x8D, 0x99, 0x13, 0x7C, 0xA5, 0xA7, 0x1A, 0xCC, - 0xB8, 0xE6, 0x2B, 0xB2, 0xB6, 0xD0, 0x62, 0x2D, - 0x4D, 0xD2, 0xB9, 0x04, 0x46, 0xAE, 0xAA, 0x44, - 0xDA, 0x92, 0x4B, 0x4E, 0xC4, 0xE2, 0xFE, 0xA2, - 0x75, 0x7B, 0xC3, 0xFA, 0x9F, 0x37, 0x9D, 0x1E, - 0x72, 0xD4, 0x1F, 0x4A, 0x9B, 0xE5, 0x6D, 0xEC, - 0x5C, 0x7D, 0x98, 0xE8, 0xEE, 0x86, 0xD1, 0xC8, - 0xEA, 0x55, 0xBF, 0xAF, 0xDE, 0x32, 0x09, 0x3A, - 0x8F, 0x57, 0x83, 0x43, 0x61, 0xC6, 0x8E, 0x96, - 0x22, 0xA3, 0x97, 0x91, 0x5F, 0x11, 0x3B, 0x5B, - 0x1B, 0x34, 0x49, 0x95, 0xF1, 0x6F, 0x89, 0xA8, - 0xC0, 0x36, 0x0A, 0x3F, 0x60, 0x50, 0xE7, 0x08, - 0xCE, 0x25, 0xC1, 0x71, 0xF6, 0x59, 0x58, 0x56, - 0x4C, 0xAB, 0x27, 0xAC, 0x06, 0xCB, 0x00, 0x30, - 0x84, 0x3E, 0xC2, 0x1D, 0x02, 0xE0, 0xC5, 0xD6, - 0x18, 0x70, 0xA9, 0x88, 0xD9, 0x39, 0x8B, 0x6E, - 0xF4, 0x24, 0xA0, 0x48, 0x45, 0x21, 0x87, 0x78, - 0x38, 0x90, 0xE3, 0xCA, 0xF5, 0xD7, 0x2A, 0x53, - 0x9C, 0xCD, 0x31, 0x35, 0xAD, 0x74, 0xD8, 0x12, - 0xBC, 0x9E, 0x6B, 0x67, 0xB0, 0xBA, 0xE4, 0x10, - 0x5E, 0xFC, 0xC7, 0x0F, 0x2E, 0x81, 0x7E, 0xA1, - 0x8C, 0x17, 0xB5, 0xEB, 0xD5, 0xF3, 0x0B, 0x3C }; - -static const unsigned char table_116[32] = { - 0x00, 0x05, 0x10, 0x1C, 0x0C, 0x1A, 0x04, 0x1B, - 0x0A, 0x0D, 0x14, 0x0B, 0x07, 0x03, 0x12, 0x1E, - 0x06, 0x11, 0x01, 0x08, 0x15, 0x09, 0x1F, 0x0F, - 0x19, 0x18, 0x16, 0x02, 0x13, 0x0E, 0x17, 0x1D }; - -static const unsigned char table_117[256] = { - 0xD0, 0x9A, 0xAB, 0xA8, 0xA7, 0xDF, 0x28, 0xCE, - 0x3E, 0x51, 0xBF, 0x76, 0x03, 0xA0, 0x53, 0x3F, - 0x90, 0x93, 0x87, 0x67, 0x98, 0x3D, 0xEA, 0x8B, - 0x55, 0xCF, 0x10, 0xF3, 0x25, 0xFC, 0x9F, 0x41, - 0x6B, 0x54, 0x6E, 0x0B, 0x83, 0x35, 0x69, 0x7D, - 0xE0, 0x88, 0x4B, 0xE9, 0x1E, 0x96, 0x91, 0x57, - 0xBD, 0x72, 0x21, 0x3C, 0xA6, 0x99, 0x6C, 0xF6, - 0x13, 0xFA, 0x29, 0xED, 0xDB, 0x16, 0x4D, 0x07, - 0x45, 0xA5, 0xE3, 0x0E, 0x31, 0xBC, 0x56, 0x5C, - 0xB2, 0x23, 0xDA, 0x74, 0xFF, 0x02, 0x8F, 0xF4, - 0x2A, 0xC9, 0x89, 0xAA, 0x05, 0xB1, 0xD1, 0x1F, - 0x4F, 0xB0, 0x7A, 0x2C, 0x14, 0xD9, 0xE7, 0x66, - 0x62, 0x1A, 0x4C, 0xC0, 0xC6, 0x63, 0x7F, 0xB4, - 0xF1, 0x43, 0xFE, 0x61, 0xA3, 0xCC, 0xE8, 0x6D, - 0xBA, 0x65, 0x42, 0x2B, 0xCA, 0xD5, 0x52, 0x3A, - 0xCD, 0x1D, 0x24, 0xD7, 0x47, 0xDE, 0x9E, 0x95, - 0x85, 0x48, 0x86, 0xE1, 0xC5, 0xD2, 0x34, 0xAF, - 0x40, 0xFB, 0xE6, 0x4E, 0xC8, 0xF5, 0x7B, 0x5A, - 0xCB, 0xD4, 0x97, 0x6F, 0x0C, 0x79, 0x9C, 0x20, - 0x59, 0x19, 0x68, 0x2E, 0x09, 0x64, 0x73, 0x50, - 0xC2, 0x2F, 0x0D, 0xEF, 0x9D, 0x94, 0x00, 0x81, - 0xE2, 0x46, 0x5F, 0xB8, 0x0A, 0x12, 0x75, 0x1C, - 0x8C, 0xB6, 0x71, 0xAC, 0x04, 0x60, 0xA9, 0x5B, - 0xF8, 0x30, 0x49, 0x44, 0x4A, 0xBE, 0x6A, 0xEB, - 0xD3, 0xD8, 0x36, 0xB3, 0x3B, 0x17, 0x80, 0xA4, - 0xEC, 0x26, 0x82, 0xB5, 0x37, 0x5D, 0x1B, 0x2D, - 0xE5, 0xA2, 0x0F, 0xB7, 0xC4, 0xF2, 0x70, 0x39, - 0xF9, 0xC7, 0xBB, 0x8A, 0x32, 0x78, 0xC3, 0x5E, - 0xD6, 0xE4, 0x22, 0x9B, 0x18, 0x8E, 0xEE, 0x27, - 0x8D, 0x33, 0x11, 0x77, 0x01, 0x06, 0x38, 0xF0, - 0x7E, 0x08, 0x15, 0xB9, 0x7C, 0xAD, 0x84, 0xDD, - 0xC1, 0xFD, 0x92, 0xA1, 0xF7, 0xAE, 0xDC, 0x58 }; - -static const unsigned char table_118[256] = { - 0x38, 0xA0, 0xA6, 0xFC, 0x7C, 0x5A, 0x97, 0x1D, - 0xFD, 0x00, 0x20, 0xA2, 0x72, 0x10, 0x1F, 0x48, - 0x98, 0x7E, 0xDF, 0x2D, 0x80, 0x0A, 0x27, 0xDC, - 0xCF, 0xBF, 0x92, 0x94, 0x53, 0xCC, 0x0E, 0x74, - 0xA7, 0x60, 0x08, 0x15, 0x87, 0x6F, 0xB3, 0xA3, - 0xED, 0x59, 0x09, 0x4F, 0x9E, 0x9A, 0xEE, 0x83, - 0x56, 0x32, 0x34, 0xC7, 0x24, 0xE7, 0x96, 0x4D, - 0xAE, 0xE3, 0xBD, 0xE2, 0x36, 0x4A, 0xB6, 0x8B, - 0xF2, 0xC1, 0xD7, 0x40, 0x31, 0x4B, 0xDA, 0xF1, - 0xB1, 0x70, 0xA8, 0xC3, 0xC6, 0x8A, 0xE6, 0x77, - 0x21, 0x7D, 0xD5, 0x0C, 0x43, 0xC4, 0xF0, 0x1B, - 0x18, 0xA1, 0x85, 0xE1, 0xFF, 0x8D, 0xE5, 0x6E, - 0x9B, 0x51, 0x1C, 0xA4, 0x5C, 0x8E, 0x69, 0x49, - 0x23, 0xCD, 0x52, 0xF8, 0x3E, 0x91, 0x5E, 0x1E, - 0x25, 0xB4, 0x93, 0xCB, 0xE0, 0x47, 0xBC, 0x4E, - 0x33, 0xB7, 0x75, 0x1A, 0x11, 0x9C, 0x3F, 0xEC, - 0xD1, 0x46, 0xDD, 0xAA, 0xB8, 0x99, 0x86, 0x67, - 0x58, 0xF9, 0x16, 0x17, 0x6D, 0x5F, 0x2B, 0xA5, - 0xD3, 0x8F, 0x55, 0x71, 0xD2, 0xBA, 0x5B, 0x3C, - 0x82, 0xB5, 0x41, 0xE4, 0x90, 0x45, 0x6C, 0xF6, - 0xDE, 0xA9, 0x84, 0x62, 0x19, 0x3B, 0xB9, 0xC8, - 0x2C, 0xB0, 0x76, 0x57, 0xD8, 0x26, 0x9D, 0x89, - 0xC9, 0x54, 0xFB, 0x07, 0xCE, 0x22, 0x5D, 0x64, - 0x65, 0xAD, 0x01, 0xDB, 0x14, 0x4C, 0x37, 0x03, - 0x6B, 0xAF, 0xD0, 0x7F, 0x9F, 0xBB, 0xEB, 0xC0, - 0x50, 0x66, 0x68, 0x0B, 0x42, 0x2A, 0xD4, 0xF5, - 0x61, 0x63, 0xF3, 0x39, 0xBE, 0xC5, 0xEF, 0x28, - 0x3A, 0xAB, 0x79, 0x05, 0xE9, 0x12, 0x73, 0x3D, - 0xB2, 0x8C, 0xCA, 0x29, 0x0F, 0xF4, 0x7B, 0x13, - 0x88, 0x44, 0xC2, 0x2E, 0xFA, 0xFE, 0x04, 0x35, - 0xE8, 0x06, 0x7A, 0x78, 0x0D, 0x81, 0xF7, 0xEA, - 0xD9, 0x2F, 0x02, 0xAC, 0x30, 0x6A, 0xD6, 0x95 }; - -static const unsigned char table_119[32] = { - 0x14, 0x0A, 0x1C, 0x00, 0x0C, 0x1F, 0x1E, 0x0B, - 0x12, 0x1D, 0x17, 0x08, 0x07, 0x04, 0x09, 0x10, - 0x03, 0x1B, 0x0E, 0x1A, 0x05, 0x0D, 0x11, 0x15, - 0x18, 0x02, 0x06, 0x01, 0x19, 0x16, 0x13, 0x0F }; - -static const unsigned char table_120[256] = { - 0xCE, 0x89, 0xB2, 0x72, 0x04, 0x77, 0x64, 0xAE, - 0x80, 0x99, 0xB5, 0x00, 0x7B, 0x50, 0x9D, 0xE3, - 0x87, 0x37, 0x6D, 0x3D, 0x32, 0xBA, 0x20, 0xF0, - 0xDC, 0xBD, 0x61, 0x26, 0xD4, 0xA6, 0x70, 0x54, - 0xC1, 0x7D, 0x82, 0xFF, 0x81, 0x83, 0x2F, 0xF5, - 0x3B, 0x42, 0x08, 0x5C, 0x30, 0x59, 0xBB, 0xC2, - 0x33, 0x5D, 0xEE, 0xB7, 0xF7, 0x2B, 0x76, 0xD0, - 0x43, 0x1C, 0x48, 0xFC, 0x01, 0xCD, 0x27, 0x1D, - 0x5A, 0x96, 0x95, 0x03, 0xC6, 0x1F, 0x09, 0xCB, - 0xF6, 0x47, 0xA9, 0x93, 0xA7, 0xD2, 0xDB, 0x51, - 0xB0, 0x7A, 0xE6, 0x62, 0x0F, 0x12, 0x57, 0xF4, - 0x35, 0xFE, 0xA4, 0xDF, 0x5B, 0xF3, 0x67, 0x85, - 0x98, 0xE4, 0xAB, 0x75, 0x4C, 0xE2, 0x25, 0x74, - 0x3A, 0x45, 0xDE, 0xEF, 0x4A, 0x97, 0x86, 0x24, - 0xE9, 0x8F, 0xD8, 0xD7, 0x60, 0xAD, 0x36, 0x8E, - 0x1E, 0xB9, 0x4F, 0x6B, 0x8C, 0x06, 0x23, 0x94, - 0x0E, 0xD3, 0x49, 0x14, 0x90, 0xAF, 0x65, 0xEC, - 0xF9, 0x0D, 0xED, 0x6C, 0xBE, 0x7F, 0xA5, 0xC5, - 0xEA, 0x78, 0x2E, 0xBC, 0xD5, 0xDA, 0x18, 0xE1, - 0x10, 0x2D, 0xB4, 0x16, 0x4B, 0xE8, 0xC4, 0x8D, - 0x19, 0x1B, 0x02, 0x66, 0xB6, 0xE7, 0x9C, 0x7C, - 0xC9, 0xA0, 0x2A, 0x53, 0x13, 0xDD, 0xF8, 0xA8, - 0x0A, 0x6E, 0xCF, 0x6F, 0x7E, 0xE0, 0x3E, 0xE5, - 0x07, 0xCC, 0x38, 0xD1, 0xF2, 0x2C, 0x9A, 0xAC, - 0x88, 0x79, 0xB8, 0xC8, 0xBF, 0x63, 0x71, 0x69, - 0x52, 0x39, 0x9F, 0x22, 0x3F, 0x9E, 0x44, 0xFA, - 0x73, 0x6A, 0x8B, 0xA2, 0xD6, 0x1A, 0x9B, 0xB1, - 0x8A, 0x4D, 0x58, 0xA1, 0x46, 0x5F, 0x55, 0x56, - 0x21, 0x05, 0x15, 0x92, 0xAA, 0xEB, 0x31, 0x68, - 0xFB, 0x41, 0xC3, 0x4E, 0xB3, 0x40, 0x34, 0x17, - 0xD9, 0x29, 0x3C, 0x0C, 0xF1, 0x0B, 0x28, 0x84, - 0x5E, 0xCA, 0xFD, 0x11, 0xA3, 0xC7, 0xC0, 0x91 }; - -static const unsigned char table_121[32] = { - 0x1E, 0x12, 0x06, 0x1D, 0x15, 0x1F, 0x13, 0x0B, - 0x10, 0x0D, 0x1C, 0x01, 0x0A, 0x0E, 0x02, 0x19, - 0x04, 0x1A, 0x03, 0x11, 0x00, 0x16, 0x0C, 0x17, - 0x14, 0x08, 0x18, 0x05, 0x09, 0x0F, 0x1B, 0x07 }; - -static const unsigned char table_122[256] = { - 0x85, 0xDF, 0x7F, 0x7C, 0x56, 0xF0, 0x0C, 0x7D, - 0x76, 0xA8, 0x58, 0x31, 0x25, 0x8A, 0x0D, 0x23, - 0x05, 0x0F, 0x12, 0x64, 0x8E, 0x5D, 0xF4, 0x2C, - 0x18, 0xFA, 0x4B, 0xFE, 0x91, 0xBF, 0x95, 0x0B, - 0xF1, 0x88, 0x10, 0xD8, 0x3E, 0x53, 0x96, 0xB5, - 0x75, 0x24, 0x8F, 0xD6, 0x68, 0x5C, 0x93, 0x1F, - 0x6B, 0xC2, 0xAB, 0xED, 0x1E, 0xC0, 0xBC, 0x47, - 0xE9, 0xD1, 0xDE, 0xCA, 0xF6, 0x62, 0x43, 0xEB, - 0xA2, 0xB4, 0x08, 0xE6, 0x74, 0x0E, 0xA1, 0x72, - 0x66, 0x61, 0x21, 0x2E, 0x32, 0x63, 0x29, 0xD7, - 0x1C, 0x22, 0xAC, 0xE7, 0x54, 0xF3, 0x65, 0x17, - 0x9F, 0x78, 0x79, 0x4C, 0xDD, 0x27, 0x90, 0x36, - 0x19, 0x44, 0x03, 0xD9, 0x4A, 0x5A, 0x34, 0xF9, - 0x97, 0xA6, 0x70, 0x39, 0x28, 0x77, 0x6E, 0xB7, - 0x8C, 0x02, 0x5E, 0x9B, 0x8D, 0x59, 0x6F, 0xA5, - 0x07, 0xE2, 0x41, 0x51, 0xC9, 0x3C, 0xE8, 0xE1, - 0xB3, 0x16, 0x50, 0x04, 0xE3, 0x1D, 0x3B, 0xD2, - 0x4D, 0x35, 0x71, 0xDA, 0x9E, 0xA7, 0xE4, 0xE0, - 0xB6, 0x2B, 0xEA, 0x84, 0x55, 0xF8, 0x57, 0x3D, - 0x73, 0x42, 0xC6, 0x0A, 0x92, 0x6A, 0xAE, 0xF5, - 0xFC, 0xD5, 0x15, 0x52, 0x7E, 0x14, 0x81, 0x13, - 0xE5, 0x49, 0x38, 0x2A, 0x94, 0x5B, 0xA3, 0x11, - 0x8B, 0x80, 0xBB, 0x01, 0x9C, 0xA4, 0xDB, 0xF7, - 0xA9, 0x20, 0xF2, 0x1A, 0xDC, 0x33, 0x3A, 0xEF, - 0xD3, 0xFD, 0x30, 0xB0, 0x1B, 0xC4, 0x06, 0xD4, - 0x6D, 0x87, 0x2F, 0x60, 0x5F, 0xC5, 0x09, 0x37, - 0xAF, 0x00, 0xCB, 0x9D, 0xA0, 0xB9, 0x45, 0x86, - 0x4F, 0x6C, 0x67, 0xFB, 0x40, 0x3F, 0xCC, 0xB8, - 0xC8, 0x82, 0x98, 0x99, 0x7B, 0xB1, 0xCD, 0xD0, - 0xBD, 0x48, 0xAD, 0x26, 0x7A, 0x9A, 0x46, 0xFF, - 0x89, 0xC7, 0xC1, 0xCF, 0xBE, 0xAA, 0xEC, 0xBA, - 0xCE, 0x2D, 0x4E, 0x83, 0xC3, 0x69, 0xEE, 0xB2 }; - -static const unsigned char table_123[256] = { - 0x9D, 0xFB, 0x3C, 0x81, 0xAA, 0x05, 0xB2, 0xBE, - 0xD1, 0x5F, 0x4C, 0xE0, 0xA3, 0xF4, 0xDE, 0x35, - 0xFE, 0x1B, 0x37, 0x99, 0x94, 0x7A, 0x10, 0xAB, - 0xC0, 0xA4, 0xB5, 0xFF, 0x8F, 0x3B, 0xB4, 0x51, - 0x04, 0xE9, 0xB9, 0xC1, 0x98, 0xC5, 0x82, 0x38, - 0x4D, 0x71, 0xFC, 0x33, 0xC4, 0x50, 0x5D, 0x88, - 0xB8, 0x5C, 0x32, 0xE2, 0xBB, 0xCD, 0x60, 0x2C, - 0xD4, 0x7E, 0x27, 0x59, 0x2B, 0x1F, 0x53, 0xF6, - 0x25, 0x86, 0xAE, 0x21, 0xFA, 0x31, 0xD7, 0x0F, - 0x17, 0xDA, 0x7F, 0xC9, 0x46, 0x19, 0x08, 0xA8, - 0xCF, 0x13, 0xCC, 0x03, 0x3F, 0x22, 0x6E, 0xEB, - 0x4A, 0x63, 0x73, 0xBD, 0x36, 0xED, 0x30, 0x57, - 0x65, 0xF8, 0x41, 0x61, 0x1E, 0xA0, 0xC6, 0x45, - 0x3E, 0x75, 0x28, 0x87, 0xCB, 0xD6, 0x16, 0xD8, - 0xDF, 0xEF, 0xEA, 0xA7, 0x58, 0xB0, 0x1D, 0xE6, - 0x47, 0x76, 0xD9, 0x96, 0xE7, 0xDC, 0x00, 0x80, - 0xDD, 0xB7, 0x9A, 0xE1, 0xF5, 0x9C, 0x4B, 0xE3, - 0xBC, 0x8D, 0xF2, 0x2F, 0x9F, 0x6C, 0x93, 0xAF, - 0xA9, 0xC2, 0x5E, 0x24, 0x15, 0xD2, 0x09, 0x0D, - 0xDB, 0x4F, 0x91, 0x0E, 0x64, 0x34, 0x4E, 0xAD, - 0x62, 0x44, 0x23, 0x85, 0xB6, 0xAC, 0xC7, 0xCA, - 0x84, 0xF9, 0x8C, 0xBF, 0x14, 0x7C, 0x8E, 0x92, - 0xF0, 0x0B, 0xCE, 0x90, 0x7D, 0x70, 0x9E, 0x54, - 0x39, 0x5B, 0x6D, 0x52, 0xEE, 0xA2, 0x6F, 0x78, - 0x2D, 0x95, 0x8B, 0x02, 0x3D, 0x7B, 0x69, 0xC3, - 0x49, 0xA5, 0x1A, 0x26, 0xD5, 0x6B, 0xE8, 0xFD, - 0xB3, 0xD3, 0x20, 0x55, 0x18, 0x06, 0xF3, 0xB1, - 0x0C, 0xC8, 0x07, 0x12, 0xF7, 0x01, 0x2E, 0x72, - 0x97, 0xA6, 0x11, 0x89, 0x56, 0x5A, 0x29, 0xBA, - 0x67, 0x42, 0x83, 0x6A, 0x2A, 0xF1, 0xA1, 0x9B, - 0xE5, 0xE4, 0x74, 0x66, 0x1C, 0x68, 0xEC, 0x40, - 0x48, 0x77, 0xD0, 0x0A, 0x8A, 0x3A, 0x43, 0x79 }; - -static const unsigned char table_124[256] = { - 0x6C, 0xC3, 0x28, 0x2F, 0x42, 0x4B, 0x7C, 0x3C, - 0xCE, 0x24, 0xC8, 0x51, 0x25, 0x3F, 0x49, 0x8D, - 0x1E, 0x5C, 0x89, 0x3A, 0x98, 0x47, 0x0B, 0x12, - 0xA9, 0xB1, 0xD7, 0xB6, 0x5D, 0xF9, 0x5A, 0xBC, - 0xFA, 0x06, 0x7D, 0x08, 0xFC, 0x37, 0x54, 0x4F, - 0xD4, 0xCD, 0xA7, 0x5E, 0xE0, 0x92, 0x82, 0x56, - 0xF1, 0x2B, 0xC4, 0xE2, 0x29, 0xEA, 0x35, 0x57, - 0x33, 0x4E, 0x1A, 0x17, 0x8B, 0x85, 0xBF, 0xD5, - 0x18, 0xB3, 0x0D, 0x71, 0x45, 0x81, 0xB4, 0x27, - 0xD1, 0xE1, 0xFF, 0x44, 0x9E, 0xA4, 0x15, 0x9A, - 0x90, 0xC7, 0x79, 0xE3, 0x4C, 0xE9, 0x3D, 0x6B, - 0xF5, 0xF4, 0xEE, 0xAA, 0xDB, 0x07, 0x09, 0xCF, - 0x7B, 0x95, 0xA0, 0x53, 0x8F, 0xA1, 0x9D, 0xBE, - 0x6F, 0xAE, 0x96, 0x46, 0x59, 0x01, 0x84, 0xCC, - 0x3B, 0x8E, 0xF7, 0x4D, 0x6E, 0xDC, 0xE8, 0x36, - 0x7A, 0xE5, 0xBD, 0xE7, 0x9F, 0x2C, 0x52, 0xAB, - 0x55, 0x13, 0x1D, 0xFB, 0x58, 0x9C, 0xDF, 0xC0, - 0x30, 0x73, 0x67, 0x39, 0x74, 0xD3, 0x11, 0xD2, - 0x0E, 0x20, 0xB7, 0x02, 0xB9, 0x1C, 0x86, 0x76, - 0x10, 0x68, 0x9B, 0x63, 0x48, 0x8A, 0xB2, 0xB8, - 0xAF, 0x26, 0x99, 0x04, 0xB0, 0xE4, 0xEF, 0xEB, - 0xEC, 0x6D, 0x61, 0xC1, 0xD0, 0x38, 0xC9, 0x19, - 0x60, 0xA8, 0xA6, 0xF8, 0x80, 0xC5, 0x03, 0x0F, - 0x22, 0x2D, 0x88, 0x32, 0x77, 0x70, 0xFE, 0x0C, - 0x31, 0x40, 0x5F, 0xED, 0xA5, 0x93, 0x43, 0xF0, - 0x8C, 0xE6, 0x34, 0x21, 0xD9, 0xC2, 0xD8, 0xC6, - 0x6A, 0xD6, 0xCB, 0xAC, 0x75, 0xB5, 0x78, 0x0A, - 0xA3, 0x69, 0x16, 0xBA, 0x50, 0x2A, 0x41, 0x83, - 0xF6, 0x64, 0x00, 0x65, 0x7E, 0xDD, 0x5B, 0xDA, - 0x14, 0xFD, 0x3E, 0x7F, 0xCA, 0x66, 0x4A, 0x1F, - 0xA2, 0xAD, 0xF2, 0x23, 0xBB, 0x72, 0xF3, 0x94, - 0x62, 0x1B, 0xDE, 0x91, 0x87, 0x97, 0x05, 0x2E }; - -static const unsigned char table_125[32] = { - 0x1A, 0x18, 0x12, 0x15, 0x00, 0x1C, 0x01, 0x0B, - 0x19, 0x1B, 0x1F, 0x11, 0x07, 0x10, 0x1E, 0x06, - 0x17, 0x04, 0x0A, 0x0E, 0x0D, 0x0C, 0x16, 0x08, - 0x02, 0x03, 0x13, 0x14, 0x09, 0x1D, 0x05, 0x0F }; - -static const unsigned char table_126[32] = { - 0x1C, 0x1D, 0x07, 0x12, 0x18, 0x1A, 0x19, 0x09, - 0x0F, 0x14, 0x1F, 0x0B, 0x13, 0x04, 0x0E, 0x1E, - 0x0C, 0x0D, 0x01, 0x17, 0x1B, 0x16, 0x0A, 0x05, - 0x15, 0x10, 0x11, 0x08, 0x00, 0x03, 0x06, 0x02 }; - -static const unsigned char table_127[256] = { - 0xA0, 0x66, 0xD8, 0x08, 0xEA, 0x39, 0x78, 0xAB, - 0x61, 0x4E, 0xC7, 0xD1, 0xA3, 0x1C, 0x9F, 0xCB, - 0x19, 0x51, 0x15, 0x92, 0x23, 0xFD, 0x7D, 0x1D, - 0x95, 0xAE, 0x0E, 0x8B, 0xE6, 0x7F, 0x86, 0x6D, - 0x06, 0xBD, 0x20, 0x1F, 0x3A, 0xE4, 0x54, 0x91, - 0x69, 0xD3, 0xE3, 0x3D, 0x4D, 0x31, 0x49, 0xA4, - 0x41, 0xF3, 0xE0, 0x11, 0x14, 0x9B, 0x96, 0x5A, - 0xC4, 0x8E, 0x34, 0xDB, 0xBA, 0x83, 0xD9, 0x81, - 0xAF, 0x58, 0x8A, 0x79, 0x13, 0xBC, 0x85, 0x37, - 0x9E, 0x6C, 0x57, 0x71, 0x8D, 0x97, 0x5F, 0x6F, - 0x1E, 0x74, 0x27, 0xFC, 0x5C, 0x7A, 0x64, 0x87, - 0xF5, 0xC6, 0xF2, 0x4F, 0xDE, 0x80, 0xAA, 0x84, - 0x2E, 0xDC, 0xE7, 0x40, 0x75, 0xC5, 0xB3, 0xC8, - 0xCE, 0x21, 0x02, 0x67, 0xB7, 0x10, 0x47, 0x6A, - 0xEE, 0x53, 0x2C, 0x16, 0x05, 0xC0, 0x63, 0x4C, - 0x0D, 0xBB, 0xC3, 0x38, 0x46, 0x68, 0x7E, 0xF9, - 0xB8, 0xB4, 0x3E, 0x36, 0xD5, 0xEC, 0x0B, 0xF6, - 0x33, 0x0A, 0x0F, 0x5B, 0xFB, 0x45, 0xEB, 0xA9, - 0x6E, 0x6B, 0xCF, 0x55, 0x99, 0xAC, 0x22, 0xBE, - 0xB1, 0xA2, 0x3F, 0x25, 0x77, 0x8F, 0x7C, 0xF1, - 0xD4, 0x59, 0xA8, 0xE5, 0xD7, 0xCA, 0xA1, 0x93, - 0xE9, 0xAD, 0xF7, 0x94, 0xEF, 0xED, 0x3C, 0x2A, - 0x88, 0xB5, 0x35, 0x9D, 0x9C, 0x32, 0x5E, 0xB6, - 0x48, 0x9A, 0x7B, 0x26, 0x50, 0x90, 0x04, 0xA7, - 0xDD, 0x09, 0xB9, 0x98, 0xB2, 0xFE, 0xDF, 0x44, - 0x89, 0x29, 0x5D, 0xE2, 0x72, 0xC9, 0x28, 0x03, - 0x43, 0x8C, 0x52, 0x18, 0xC1, 0x56, 0x1B, 0x1A, - 0x01, 0x65, 0xDA, 0xBF, 0x07, 0xFF, 0x76, 0xE8, - 0x30, 0xA5, 0x4A, 0xA6, 0x12, 0x62, 0x24, 0x60, - 0x4B, 0x73, 0x0C, 0xF0, 0xFA, 0x42, 0xF4, 0x00, - 0xD2, 0xD0, 0xD6, 0x3B, 0xC2, 0x2F, 0xE1, 0x2B, - 0x70, 0xF8, 0x17, 0xCD, 0xB0, 0xCC, 0x82, 0x2D }; - -static const unsigned char table_128[32] = { - 0x1A, 0x1C, 0x09, 0x17, 0x1B, 0x0B, 0x16, 0x1E, - 0x14, 0x0C, 0x12, 0x0E, 0x05, 0x03, 0x1F, 0x15, - 0x19, 0x0D, 0x10, 0x13, 0x0A, 0x01, 0x00, 0x11, - 0x02, 0x08, 0x0F, 0x18, 0x07, 0x04, 0x1D, 0x06 }; - -static const unsigned char table_129[256] = { - 0x9D, 0x5F, 0xE8, 0x99, 0x57, 0x07, 0x16, 0xA6, - 0x9F, 0xB6, 0xDE, 0xED, 0x2D, 0xB3, 0xC0, 0x8E, - 0xCC, 0x49, 0xCE, 0xB0, 0x1B, 0xB1, 0x7A, 0xE0, - 0xEB, 0x28, 0xDB, 0x7D, 0x88, 0xC8, 0x06, 0x6C, - 0x02, 0xD0, 0x85, 0x7E, 0xDF, 0xF5, 0x78, 0xE5, - 0xA9, 0x71, 0xD9, 0xDD, 0xDC, 0xEE, 0x8C, 0x54, - 0xA0, 0x86, 0xFE, 0x0E, 0x55, 0xF7, 0x41, 0x47, - 0x1D, 0x15, 0xD6, 0xA4, 0xFF, 0x1F, 0x25, 0xF8, - 0x12, 0xE9, 0x74, 0x7B, 0x04, 0xE6, 0x4C, 0x31, - 0xA2, 0xBE, 0x0C, 0xB9, 0x17, 0xBD, 0x3D, 0xF0, - 0x9E, 0x4D, 0x4E, 0xB2, 0xE7, 0x40, 0xC9, 0x8A, - 0x67, 0x5E, 0x19, 0x0F, 0xB7, 0x22, 0x8D, 0xBA, - 0xFC, 0x93, 0x14, 0xEA, 0xFD, 0x0D, 0xD5, 0x38, - 0xA1, 0x84, 0x1C, 0x35, 0x60, 0x37, 0x43, 0x9C, - 0xCF, 0xEF, 0x3A, 0x72, 0xF2, 0x61, 0x75, 0x6A, - 0x42, 0xAC, 0xD3, 0x48, 0x77, 0xC5, 0x29, 0xF6, - 0x58, 0x79, 0xFA, 0x5D, 0xC7, 0x70, 0x53, 0x9A, - 0x6F, 0xC1, 0x0A, 0x90, 0x8F, 0x3E, 0x3B, 0x8B, - 0xEC, 0xBC, 0x20, 0x27, 0xC3, 0x66, 0x3F, 0x33, - 0xA5, 0x44, 0x2E, 0x32, 0x65, 0x18, 0xFB, 0x59, - 0x52, 0x50, 0xE2, 0x63, 0x2B, 0xCD, 0x64, 0xCB, - 0xD2, 0x68, 0x10, 0xA7, 0xAE, 0x11, 0xA8, 0x96, - 0x69, 0xAF, 0xC2, 0x34, 0x5C, 0x56, 0xE3, 0xF9, - 0xDA, 0x51, 0x81, 0x4A, 0x05, 0x00, 0xB8, 0x7C, - 0x30, 0x2F, 0x46, 0xB4, 0xC6, 0x87, 0x4B, 0x94, - 0x80, 0xF4, 0x7F, 0x3C, 0x26, 0xF1, 0x5B, 0xAB, - 0x91, 0x6E, 0x08, 0x76, 0x98, 0xD1, 0xE1, 0x36, - 0x21, 0xCA, 0xD8, 0x24, 0x9B, 0x39, 0xBB, 0xAD, - 0x13, 0x62, 0x97, 0x1A, 0x6D, 0x2C, 0x5A, 0xC4, - 0xD4, 0xA3, 0x03, 0xBF, 0x1E, 0xE4, 0xF3, 0x95, - 0x23, 0x73, 0x92, 0xB5, 0x01, 0x83, 0x82, 0xAA, - 0x09, 0x45, 0x6B, 0xD7, 0x0B, 0x89, 0x4F, 0x2A }; - -static const unsigned char table_130[32] = { - 0x07, 0x03, 0x15, 0x0B, 0x02, 0x11, 0x17, 0x14, - 0x05, 0x10, 0x0A, 0x0F, 0x01, 0x1C, 0x1D, 0x0E, - 0x12, 0x06, 0x18, 0x16, 0x1A, 0x09, 0x13, 0x19, - 0x1B, 0x00, 0x08, 0x0D, 0x0C, 0x1E, 0x04, 0x1F }; - -static const unsigned char table_131[32] = { - 0x1D, 0x13, 0x1B, 0x10, 0x07, 0x03, 0x0A, 0x02, - 0x00, 0x0C, 0x0E, 0x0B, 0x0D, 0x18, 0x12, 0x1F, - 0x1A, 0x04, 0x15, 0x11, 0x1E, 0x08, 0x1C, 0x14, - 0x19, 0x05, 0x0F, 0x17, 0x06, 0x01, 0x09, 0x16 }; - -static const unsigned char table_132[256] = { - 0x33, 0x8D, 0x45, 0x6F, 0xFF, 0xF5, 0xB6, 0x53, - 0x3B, 0xF3, 0x07, 0xA4, 0x97, 0xEB, 0x6B, 0xA5, - 0xD3, 0xDC, 0x7B, 0x79, 0x93, 0xE7, 0xF7, 0x67, - 0x9C, 0x4F, 0x88, 0xF9, 0x3A, 0x2B, 0x27, 0x48, - 0x47, 0x18, 0xF4, 0xAD, 0xB4, 0x8F, 0x2A, 0x76, - 0x17, 0xE9, 0x1F, 0x40, 0x0C, 0x59, 0xD1, 0x4C, - 0x20, 0x31, 0x73, 0x54, 0xCD, 0x68, 0x08, 0x52, - 0x10, 0x62, 0x3D, 0xD2, 0x77, 0xF2, 0xD7, 0x30, - 0xCA, 0x16, 0x01, 0x50, 0x9F, 0x3F, 0x75, 0xED, - 0x90, 0x6A, 0x34, 0xCE, 0x05, 0x78, 0x5E, 0xD6, - 0x85, 0xCC, 0x29, 0xB8, 0xC1, 0x0D, 0xCB, 0x80, - 0x2E, 0x04, 0x00, 0x44, 0x32, 0x95, 0xBF, 0xFE, - 0x6E, 0x7C, 0xFD, 0xA7, 0x3C, 0x5C, 0xF0, 0xEC, - 0xAC, 0xF8, 0xB9, 0xC0, 0x1B, 0x3E, 0xE8, 0x66, - 0x5D, 0xDE, 0x49, 0x71, 0xAA, 0xAF, 0x21, 0x64, - 0x28, 0x8A, 0x4E, 0x98, 0x58, 0xA2, 0x23, 0xCF, - 0x9E, 0x63, 0x61, 0x91, 0x12, 0xC6, 0x8C, 0x19, - 0xA8, 0xD4, 0xC7, 0xDD, 0xFC, 0xBD, 0x38, 0xDF, - 0xEA, 0x2D, 0x7E, 0x7D, 0xE3, 0xE0, 0xC3, 0xD9, - 0x8B, 0x11, 0xF1, 0x4D, 0xC8, 0xB5, 0x55, 0xAE, - 0xE1, 0x89, 0xE5, 0xB3, 0xBC, 0x69, 0x9D, 0xA6, - 0x09, 0x9A, 0x74, 0x35, 0x1A, 0xFB, 0x24, 0xB7, - 0x13, 0x14, 0x94, 0x0A, 0x86, 0x0F, 0x60, 0x51, - 0xB0, 0x84, 0x22, 0x5B, 0x87, 0x43, 0x57, 0x0B, - 0x2F, 0x5F, 0x02, 0xD0, 0xBB, 0xA3, 0xC9, 0x7A, - 0xBE, 0xC2, 0x26, 0x46, 0xDB, 0x1E, 0x1D, 0x92, - 0xE2, 0xB2, 0x37, 0x6D, 0xD5, 0x4A, 0x0E, 0x4B, - 0x8E, 0xC5, 0x42, 0x99, 0xEE, 0xE4, 0xB1, 0x06, - 0xAB, 0x5A, 0x56, 0x41, 0x65, 0xBA, 0xFA, 0x83, - 0x15, 0xDA, 0x72, 0xA1, 0x81, 0x1C, 0xA9, 0x36, - 0x25, 0x96, 0x6C, 0x39, 0x82, 0xE6, 0x2C, 0x9B, - 0xC4, 0x7F, 0xA0, 0xD8, 0xEF, 0x03, 0x70, 0xF6 }; - -static const unsigned char table_133[256] = { - 0x02, 0xF0, 0xED, 0xC4, 0xE4, 0x67, 0x60, 0x8B, - 0xF3, 0x77, 0x92, 0xE0, 0x85, 0x93, 0x1E, 0x8E, - 0x9A, 0x38, 0x61, 0x20, 0xB7, 0x68, 0xE1, 0x5E, - 0xD5, 0x63, 0xA9, 0xA5, 0xBE, 0x36, 0x12, 0x4D, - 0x86, 0x16, 0xD6, 0xB1, 0x23, 0x64, 0x4F, 0x62, - 0xFC, 0xA3, 0xD3, 0x04, 0x7D, 0x8C, 0xE2, 0xFF, - 0x5D, 0x30, 0xF5, 0x95, 0x1B, 0x5F, 0x73, 0xAA, - 0xE8, 0x07, 0x87, 0xDC, 0x54, 0x7C, 0xEE, 0x00, - 0xB8, 0xDE, 0x55, 0xBA, 0xD0, 0x50, 0xBB, 0x89, - 0x1C, 0xCC, 0x0E, 0xC0, 0x42, 0x11, 0xD8, 0xA2, - 0x2E, 0x33, 0xFE, 0x26, 0xD4, 0x10, 0xDA, 0xC5, - 0xFB, 0xAF, 0x98, 0x78, 0xB5, 0xBD, 0xC8, 0x8D, - 0x46, 0xA0, 0xD1, 0x7B, 0xBC, 0x75, 0xAB, 0x25, - 0xB2, 0x43, 0x57, 0xB6, 0xEC, 0xF4, 0x66, 0x05, - 0x9C, 0x08, 0x53, 0x80, 0xEA, 0x21, 0x2C, 0x6C, - 0x17, 0x71, 0xD2, 0x70, 0x76, 0x9E, 0x6B, 0x7A, - 0x58, 0xA7, 0xBF, 0x29, 0x03, 0x1F, 0x06, 0xC1, - 0xDD, 0x2F, 0x5C, 0x0B, 0x0D, 0x8A, 0x0A, 0xCB, - 0xCA, 0x6F, 0x19, 0x6A, 0xFA, 0xF7, 0xA8, 0xA1, - 0xEB, 0x88, 0x44, 0xAC, 0x01, 0x4E, 0x59, 0x94, - 0x72, 0x2B, 0xE9, 0x0F, 0x22, 0x9B, 0x27, 0x37, - 0x41, 0xF9, 0xF2, 0xE3, 0xEF, 0xB3, 0xD9, 0x2A, - 0x31, 0xC2, 0x0C, 0x15, 0x90, 0x14, 0xF6, 0x83, - 0xFD, 0x96, 0x9D, 0x7F, 0xA4, 0x39, 0xE7, 0x3F, - 0xE6, 0xC7, 0xCD, 0x1A, 0xCF, 0x48, 0x3C, 0x51, - 0x6D, 0x5B, 0x74, 0xC3, 0xC9, 0x09, 0x3D, 0x9F, - 0xDB, 0x32, 0x40, 0x18, 0xD7, 0xCE, 0x69, 0x49, - 0x3A, 0xF1, 0xB9, 0x56, 0x91, 0x99, 0x84, 0x24, - 0x7E, 0x34, 0x4B, 0xA6, 0x47, 0xB4, 0x6E, 0xDF, - 0x65, 0x3B, 0xAD, 0x45, 0x13, 0xC6, 0x81, 0xF8, - 0x4A, 0x2D, 0x8F, 0x4C, 0x97, 0x28, 0x3E, 0xE5, - 0x5A, 0x35, 0xB0, 0xAE, 0x82, 0x79, 0x1D, 0x52 }; - -static const unsigned char table_134[32] = { - 0x09, 0x0F, 0x10, 0x0C, 0x03, 0x15, 0x07, 0x17, - 0x0E, 0x0B, 0x1D, 0x08, 0x19, 0x11, 0x00, 0x0A, - 0x01, 0x06, 0x18, 0x16, 0x0D, 0x13, 0x14, 0x12, - 0x02, 0x1B, 0x1A, 0x04, 0x05, 0x1F, 0x1C, 0x1E }; - -static const unsigned char table_135[256] = { - 0x14, 0x34, 0xEA, 0x02, 0x2B, 0x5A, 0x10, 0x51, - 0xF3, 0x8F, 0x28, 0xB2, 0x50, 0x8B, 0x01, 0xCC, - 0x80, 0x15, 0x29, 0x42, 0xF4, 0x1D, 0xFB, 0xBB, - 0x1F, 0x43, 0x8C, 0x17, 0x1E, 0x81, 0x04, 0x98, - 0x46, 0xD8, 0xD5, 0x65, 0x4C, 0x1C, 0xDB, 0x40, - 0x5F, 0x1A, 0x31, 0x74, 0xF1, 0x64, 0x19, 0x05, - 0xFC, 0xF0, 0x73, 0xB6, 0x23, 0x77, 0x9C, 0xCE, - 0x70, 0xEF, 0xDA, 0xE0, 0xA2, 0x78, 0x84, 0xEB, - 0x9E, 0xC5, 0x95, 0xA3, 0xF6, 0xCA, 0xAD, 0x52, - 0xD0, 0x3F, 0x54, 0xA7, 0x33, 0xA9, 0x09, 0x6A, - 0x89, 0x7E, 0x75, 0xA8, 0xD6, 0x79, 0x9F, 0xAB, - 0x8E, 0x11, 0x0E, 0x3B, 0xAA, 0xE6, 0x85, 0x53, - 0x0A, 0x59, 0xEC, 0x94, 0xD7, 0x41, 0x86, 0x7D, - 0x2F, 0xC7, 0xDE, 0x06, 0xCB, 0x13, 0xBA, 0x58, - 0xC8, 0xC9, 0x07, 0x67, 0x7F, 0xA5, 0xB4, 0x2C, - 0x48, 0x6C, 0xB8, 0xD1, 0x30, 0xD3, 0x35, 0x4F, - 0x88, 0x26, 0x93, 0x32, 0x71, 0x3E, 0x3D, 0xF7, - 0x6D, 0x03, 0xED, 0x8A, 0x36, 0x55, 0x9B, 0x66, - 0x8D, 0x27, 0x7C, 0xF9, 0xA6, 0xC3, 0x20, 0x69, - 0x4A, 0xE3, 0x99, 0x5C, 0xBC, 0x45, 0x16, 0x6B, - 0xB9, 0x49, 0x82, 0xFF, 0xBD, 0xDD, 0xE9, 0x0C, - 0xD4, 0x44, 0xFD, 0x22, 0xE5, 0xAC, 0x61, 0xC4, - 0x90, 0x47, 0x37, 0x72, 0xA4, 0x7A, 0x24, 0x4D, - 0x5B, 0x12, 0x38, 0x92, 0x87, 0x1B, 0xE1, 0xA0, - 0x91, 0x3C, 0xEE, 0x6F, 0xC1, 0x0F, 0x56, 0xC2, - 0x9A, 0xF8, 0x18, 0xE8, 0xD2, 0xDC, 0x4B, 0xCF, - 0x39, 0xF5, 0xFE, 0x2A, 0x2D, 0x9D, 0xA1, 0xFA, - 0xE7, 0xBF, 0x6E, 0xE4, 0x2E, 0xB3, 0xCD, 0xE2, - 0xAF, 0x7B, 0xC0, 0x68, 0x97, 0xB5, 0x5D, 0xB7, - 0x21, 0x57, 0x83, 0x76, 0xB1, 0xAE, 0x5E, 0x0D, - 0x96, 0x4E, 0x08, 0xC6, 0x0B, 0xDF, 0x3A, 0xB0, - 0x00, 0x63, 0xD9, 0xBE, 0xF2, 0x60, 0x25, 0x62 }; - -static const unsigned char table_136[256] = { - 0xD3, 0x1A, 0x00, 0xED, 0x59, 0x24, 0xA3, 0xF2, - 0xBA, 0x58, 0x4C, 0x5C, 0x75, 0x48, 0x98, 0xB0, - 0xCF, 0xC3, 0xF7, 0x88, 0x70, 0xB3, 0x3D, 0x3E, - 0x03, 0xF9, 0xC9, 0xFD, 0x80, 0x44, 0x7F, 0x3B, - 0x95, 0x5F, 0x31, 0x47, 0x15, 0x07, 0xB8, 0x08, - 0xCE, 0xDA, 0x71, 0x9F, 0x83, 0xB1, 0x55, 0x16, - 0xE6, 0xB2, 0xC7, 0xBE, 0x54, 0xE7, 0x2E, 0x8D, - 0x12, 0x21, 0x41, 0x69, 0xFE, 0x28, 0x11, 0x56, - 0x5A, 0xDD, 0xB6, 0x87, 0x78, 0x82, 0x4D, 0x7B, - 0x50, 0x9A, 0x9E, 0x62, 0xF8, 0x0A, 0x64, 0xF1, - 0x4E, 0x33, 0xAD, 0xBB, 0x79, 0x76, 0xD8, 0xCD, - 0x86, 0x34, 0x29, 0xD5, 0x7D, 0x72, 0xC5, 0xC1, - 0xDF, 0x09, 0x4A, 0xB4, 0xD2, 0x7A, 0xF0, 0xCC, - 0x0F, 0xA7, 0xD6, 0x2B, 0x20, 0x26, 0xEF, 0xAB, - 0x74, 0x1E, 0xE3, 0x77, 0xCB, 0x7C, 0x73, 0x5E, - 0x6B, 0x0D, 0x65, 0xA6, 0x30, 0xFB, 0xD0, 0xB7, - 0xAA, 0x94, 0x9D, 0x85, 0x13, 0x18, 0xA8, 0xF3, - 0xE0, 0xBC, 0x45, 0xCA, 0xC8, 0xDC, 0xE2, 0x3C, - 0x23, 0xE5, 0xB9, 0x90, 0x49, 0xA5, 0xE4, 0x36, - 0xFC, 0x53, 0xF6, 0xE8, 0xC6, 0x2C, 0x02, 0x25, - 0xC0, 0x8F, 0x61, 0xA4, 0x39, 0x8C, 0x5D, 0xAE, - 0x22, 0x1C, 0x2F, 0xD4, 0x6C, 0xD1, 0x51, 0xEA, - 0x4F, 0x7E, 0xA0, 0xF5, 0x6A, 0x32, 0xA2, 0x01, - 0xB5, 0x10, 0x2A, 0xAC, 0xA9, 0x06, 0xC4, 0x91, - 0x68, 0xE1, 0xBD, 0x14, 0x38, 0xFA, 0x6E, 0x3F, - 0x37, 0x66, 0xDB, 0x57, 0x43, 0x1B, 0x67, 0xAF, - 0x1F, 0x0B, 0x6D, 0x2D, 0x89, 0x04, 0x4B, 0x52, - 0xC2, 0xBF, 0xA1, 0x92, 0x99, 0x6F, 0x63, 0x81, - 0x27, 0x05, 0x96, 0x3A, 0xEC, 0x0E, 0x97, 0xD9, - 0xDE, 0x46, 0x35, 0x8B, 0x8E, 0x8A, 0xF4, 0xFF, - 0x60, 0xD7, 0xE9, 0x17, 0xEB, 0x9C, 0x84, 0x0C, - 0x93, 0x1D, 0x9B, 0x5B, 0x40, 0xEE, 0x42, 0x19 }; - -static const unsigned char table_137[32] = { - 0x0F, 0x09, 0x02, 0x06, 0x18, 0x0B, 0x1E, 0x05, - 0x11, 0x1D, 0x16, 0x01, 0x13, 0x10, 0x0E, 0x1A, - 0x1B, 0x00, 0x0D, 0x08, 0x15, 0x14, 0x19, 0x17, - 0x03, 0x1F, 0x0A, 0x12, 0x0C, 0x07, 0x04, 0x1C }; - -static const unsigned char table_138[32] = { - 0x0D, 0x1C, 0x1F, 0x15, 0x0F, 0x14, 0x1B, 0x12, - 0x09, 0x0B, 0x19, 0x07, 0x11, 0x16, 0x0C, 0x04, - 0x13, 0x05, 0x1D, 0x03, 0x0E, 0x0A, 0x08, 0x1E, - 0x01, 0x06, 0x18, 0x17, 0x10, 0x1A, 0x02, 0x00 }; - -static const unsigned char table_139[32] = { - 0x05, 0x15, 0x1D, 0x02, 0x0F, 0x03, 0x17, 0x1A, - 0x0A, 0x00, 0x1F, 0x12, 0x0E, 0x11, 0x1B, 0x13, - 0x0B, 0x0D, 0x09, 0x18, 0x1E, 0x08, 0x14, 0x07, - 0x0C, 0x04, 0x16, 0x19, 0x1C, 0x06, 0x10, 0x01 }; - -static const unsigned char table_140[32] = { - 0x06, 0x1E, 0x0C, 0x11, 0x13, 0x08, 0x15, 0x01, - 0x1D, 0x03, 0x0F, 0x19, 0x18, 0x04, 0x00, 0x14, - 0x12, 0x1A, 0x0B, 0x0E, 0x02, 0x1B, 0x07, 0x05, - 0x1F, 0x17, 0x09, 0x0A, 0x0D, 0x16, 0x10, 0x1C }; - -static const unsigned char table_141[256] = { - 0xE1, 0x0A, 0x28, 0xCD, 0x8A, 0x1E, 0x26, 0x10, - 0xC0, 0x6F, 0x06, 0x2C, 0xF8, 0x51, 0x6C, 0x8F, - 0xA8, 0x8C, 0x41, 0xF4, 0xED, 0x36, 0xAC, 0x89, - 0xBD, 0x9D, 0x42, 0x50, 0x95, 0x07, 0x2A, 0x9B, - 0x7E, 0xA3, 0x6B, 0x30, 0x72, 0x4E, 0xBE, 0xD8, - 0x8B, 0x5B, 0x1A, 0x56, 0x05, 0xEF, 0xEE, 0x64, - 0xFF, 0xFD, 0x93, 0xB5, 0xD6, 0x04, 0x57, 0xAE, - 0x4D, 0x6D, 0x2F, 0xBA, 0x40, 0xE0, 0xDB, 0xF2, - 0xCC, 0x08, 0x35, 0x02, 0xC4, 0x65, 0x66, 0x76, - 0xA1, 0x97, 0x9F, 0x6A, 0x90, 0xA7, 0x34, 0x1B, - 0x18, 0xB9, 0xA2, 0xDE, 0x23, 0x1F, 0xCB, 0xE6, - 0xAB, 0xCF, 0xAD, 0x4A, 0xF7, 0x24, 0xD0, 0xE8, - 0x8D, 0x49, 0xEA, 0x0F, 0x94, 0x22, 0xD3, 0x74, - 0x71, 0x0D, 0x21, 0x14, 0x39, 0x4B, 0x16, 0x25, - 0x5A, 0xB7, 0x17, 0x67, 0x59, 0x47, 0x27, 0x4F, - 0x32, 0x3B, 0x63, 0x0C, 0xF0, 0xF3, 0x7B, 0xC7, - 0xCA, 0x3A, 0x9A, 0xE2, 0xD5, 0xFA, 0x91, 0xFC, - 0x86, 0x81, 0x99, 0xB4, 0xBC, 0x7C, 0xC5, 0xBF, - 0xC1, 0xF5, 0x77, 0xA4, 0x79, 0x11, 0x8E, 0x75, - 0x55, 0x3D, 0x78, 0x20, 0x37, 0x3E, 0x85, 0xE4, - 0x2E, 0x82, 0xA9, 0x7A, 0x31, 0xC9, 0xB3, 0xFE, - 0x4C, 0x7D, 0xC3, 0xA0, 0x0E, 0x96, 0x5C, 0xC6, - 0x1C, 0x5F, 0xD7, 0xDD, 0x83, 0xC8, 0x9E, 0xEC, - 0x3F, 0xAF, 0x38, 0x9C, 0xD9, 0xB6, 0xDA, 0xD4, - 0x61, 0x44, 0x43, 0xAA, 0xB1, 0xCE, 0xE7, 0x84, - 0x00, 0x0B, 0xFB, 0x68, 0xC2, 0x3C, 0x58, 0xB2, - 0x69, 0x7F, 0x33, 0x2B, 0x80, 0x03, 0xE9, 0x88, - 0x29, 0x12, 0x01, 0x6E, 0x62, 0xF1, 0xA6, 0xF9, - 0x5D, 0xD2, 0xE3, 0x53, 0x09, 0x2D, 0xBB, 0x15, - 0xEB, 0x13, 0xA5, 0xF6, 0x73, 0x19, 0x60, 0xB0, - 0xD1, 0x48, 0x92, 0x1D, 0x52, 0x5E, 0x45, 0x70, - 0x98, 0x54, 0xB8, 0xDC, 0x46, 0xDF, 0x87, 0xE5 }; - -static const unsigned char table_142[256] = { - 0x90, 0x94, 0xBE, 0x14, 0x99, 0xEB, 0x45, 0x0F, - 0x34, 0x4A, 0xE3, 0x79, 0xD2, 0x64, 0x4D, 0x69, - 0x91, 0xDE, 0xB9, 0x1C, 0x59, 0x20, 0x6C, 0x0B, - 0x16, 0xC7, 0x1D, 0x18, 0x02, 0x7D, 0x13, 0xB2, - 0x7B, 0x81, 0xCF, 0x61, 0xA3, 0x33, 0x00, 0x73, - 0x5A, 0x8A, 0xA1, 0xA8, 0x31, 0xAC, 0xF0, 0x67, - 0xAE, 0xA5, 0x2A, 0x96, 0x58, 0xF4, 0xB7, 0x0E, - 0xE1, 0x54, 0x27, 0x83, 0x09, 0x85, 0xF8, 0x84, - 0xEA, 0xAD, 0x06, 0xED, 0x43, 0xFF, 0xA2, 0x6E, - 0x68, 0x46, 0x74, 0x47, 0x3C, 0xAA, 0xBC, 0x55, - 0xA7, 0xC3, 0x82, 0xDC, 0xBF, 0x38, 0x80, 0x15, - 0xF6, 0xB3, 0x92, 0x7C, 0x93, 0x3F, 0xE9, 0x4C, - 0x35, 0x30, 0x32, 0xF3, 0x88, 0xC0, 0x49, 0x6D, - 0xCE, 0x42, 0xDF, 0xFD, 0x78, 0x6A, 0x24, 0xCA, - 0xB8, 0xFC, 0xA6, 0x5F, 0x29, 0xFE, 0x0C, 0x5C, - 0x0D, 0x23, 0x8B, 0x9D, 0xD4, 0x03, 0x2C, 0x9C, - 0x77, 0xD8, 0x39, 0x8C, 0x57, 0xD5, 0xE0, 0x8F, - 0xC6, 0xB0, 0xCD, 0x48, 0xC9, 0xA0, 0xDA, 0xC8, - 0xD1, 0x5B, 0xAB, 0x37, 0x5D, 0x63, 0xAF, 0xF9, - 0x17, 0x1B, 0xE5, 0xF1, 0x36, 0xC1, 0x04, 0x26, - 0x6F, 0x9E, 0xD9, 0x2F, 0x7F, 0xB5, 0x3A, 0xD6, - 0xE6, 0x40, 0x07, 0xCB, 0x7E, 0x3E, 0xC5, 0x22, - 0xEC, 0xE2, 0xD3, 0x4E, 0x65, 0x2D, 0x70, 0xE7, - 0x10, 0x19, 0xD0, 0xEF, 0xBD, 0xC2, 0x44, 0xB4, - 0xF7, 0xA4, 0x53, 0x9F, 0x86, 0xFA, 0xE8, 0x4B, - 0x28, 0x3D, 0x9B, 0x56, 0x89, 0x6B, 0x25, 0x71, - 0x60, 0x11, 0x9A, 0x5E, 0x1A, 0x52, 0x08, 0x4F, - 0xB1, 0xDD, 0xBB, 0x98, 0xFB, 0x12, 0x3B, 0x0A, - 0x2E, 0xDB, 0x62, 0x8D, 0xC4, 0x75, 0xA9, 0x2B, - 0xE4, 0x97, 0x72, 0xF5, 0xEE, 0xF2, 0xB6, 0x21, - 0xBA, 0x7A, 0x76, 0x41, 0x50, 0x66, 0x05, 0x8E, - 0xCC, 0x1E, 0x87, 0xD7, 0x01, 0x1F, 0x51, 0x95 }; - -static const unsigned char table_143[32] = { - 0x0E, 0x16, 0x18, 0x11, 0x0C, 0x01, 0x12, 0x1F, - 0x08, 0x15, 0x0A, 0x06, 0x1C, 0x1E, 0x02, 0x1A, - 0x17, 0x03, 0x07, 0x13, 0x05, 0x19, 0x10, 0x0F, - 0x0D, 0x14, 0x09, 0x0B, 0x1B, 0x00, 0x1D, 0x04 }; - -static const unsigned char table_144[32] = { - 0x00, 0x1B, 0x17, 0x19, 0x1D, 0x11, 0x0D, 0x1A, - 0x13, 0x03, 0x1E, 0x09, 0x10, 0x0E, 0x15, 0x05, - 0x0B, 0x1C, 0x1F, 0x08, 0x0A, 0x06, 0x01, 0x0F, - 0x16, 0x14, 0x02, 0x04, 0x07, 0x18, 0x12, 0x0C }; - -static const unsigned char table_145[256] = { - 0xF9, 0x2C, 0x38, 0x74, 0xDA, 0x65, 0x85, 0x0E, - 0xBA, 0x64, 0xDB, 0xE3, 0xB6, 0x8B, 0x0B, 0x5E, - 0x01, 0x0F, 0x12, 0x8C, 0xD4, 0xCC, 0xB1, 0x7B, - 0xE7, 0xBC, 0x2E, 0x87, 0x84, 0x3B, 0xF8, 0x4C, - 0x8E, 0x59, 0x2D, 0xAA, 0xCE, 0x28, 0x1B, 0xEE, - 0x7F, 0x5C, 0xFB, 0x62, 0x05, 0xD9, 0xDD, 0x9D, - 0x49, 0x66, 0x82, 0x71, 0xD2, 0xC7, 0xEB, 0xCF, - 0x5B, 0x41, 0x25, 0xC8, 0x6C, 0xFF, 0x78, 0x97, - 0x0C, 0xA2, 0x50, 0x7A, 0xAF, 0x2F, 0xB0, 0x7E, - 0xBB, 0x73, 0xA0, 0x9B, 0x09, 0xDE, 0x35, 0xE9, - 0x5A, 0x70, 0x56, 0xC5, 0x81, 0x19, 0x55, 0xAB, - 0xC1, 0xB4, 0x2A, 0x30, 0x54, 0x6F, 0x3E, 0x46, - 0x5D, 0x37, 0xF5, 0x57, 0x6B, 0x7C, 0x43, 0xE1, - 0x4A, 0x3F, 0xB2, 0x4B, 0x77, 0xB5, 0x44, 0xD6, - 0x91, 0x11, 0x72, 0xE8, 0xBE, 0xA5, 0xA8, 0xD3, - 0x9A, 0x17, 0x86, 0x88, 0x16, 0x3C, 0x36, 0xD8, - 0x6E, 0x07, 0x8D, 0x5F, 0xFA, 0xF1, 0x24, 0x7D, - 0x20, 0x60, 0x0D, 0x89, 0xC9, 0x29, 0xA7, 0x2B, - 0x4E, 0x10, 0x9F, 0xE5, 0x61, 0x32, 0x3A, 0xBF, - 0x93, 0xE6, 0xF3, 0x52, 0x80, 0xC4, 0x02, 0x22, - 0xA4, 0xBD, 0xF0, 0x48, 0x51, 0xF2, 0xD7, 0x33, - 0x00, 0x53, 0x98, 0xEC, 0x47, 0x39, 0xB9, 0x90, - 0x76, 0x4F, 0x68, 0x3D, 0x9C, 0x92, 0xD5, 0xB8, - 0xAE, 0xD0, 0xF4, 0x67, 0x58, 0xC0, 0x06, 0x08, - 0x14, 0x31, 0xDC, 0xA1, 0x15, 0xDF, 0xCA, 0xE2, - 0x23, 0xFE, 0xE4, 0x8F, 0x0A, 0xFC, 0x8A, 0xA3, - 0xC6, 0xCD, 0x6A, 0x75, 0xFD, 0x42, 0xB7, 0x79, - 0x96, 0x1D, 0x63, 0x18, 0xA9, 0x1C, 0x83, 0x6D, - 0xE0, 0x34, 0x04, 0xA6, 0x13, 0xAC, 0xD1, 0xF7, - 0x26, 0xC3, 0x1F, 0x27, 0x45, 0x95, 0xCB, 0x21, - 0xED, 0x1A, 0x9E, 0x99, 0xEA, 0x40, 0x94, 0x4D, - 0x69, 0xF6, 0xEF, 0xC2, 0xAD, 0x03, 0xB3, 0x1E }; - -static const unsigned char table_146[256] = { - 0x1C, 0xF5, 0x16, 0xD2, 0xCC, 0xDC, 0x1E, 0x29, - 0xE3, 0x17, 0x3B, 0x66, 0x6A, 0xF7, 0x03, 0xB2, - 0x92, 0x45, 0x4D, 0xD6, 0x0C, 0x5E, 0xE6, 0x01, - 0xDE, 0xCE, 0x83, 0xFA, 0x35, 0x02, 0x85, 0xC4, - 0x2E, 0x89, 0x8D, 0xE7, 0x30, 0x93, 0xDD, 0x70, - 0x80, 0xD9, 0x6D, 0x81, 0x07, 0x8E, 0xA9, 0xA6, - 0x5F, 0xC9, 0xF3, 0x9D, 0x65, 0xE8, 0x88, 0x0B, - 0x49, 0xAA, 0xB7, 0x6C, 0x11, 0xFC, 0x6F, 0xA3, - 0xF8, 0x52, 0x0E, 0xD4, 0x08, 0x25, 0x27, 0x33, - 0x2F, 0xF0, 0x2B, 0x47, 0xDA, 0x4C, 0x39, 0x54, - 0xB9, 0xC1, 0xEA, 0x7C, 0x44, 0xEB, 0x06, 0xE1, - 0x8C, 0x9B, 0x74, 0x42, 0x4F, 0x0A, 0x69, 0x2A, - 0x2D, 0xA1, 0x19, 0xD5, 0xC3, 0x87, 0x68, 0xFF, - 0xEC, 0xE4, 0x86, 0xCF, 0xF6, 0x79, 0x34, 0xA8, - 0x72, 0xF4, 0x8B, 0xAF, 0xA5, 0x00, 0xBA, 0x5C, - 0x23, 0xB8, 0xC8, 0x59, 0xBF, 0x6E, 0xCB, 0x20, - 0x1F, 0x53, 0x97, 0x4B, 0xD0, 0x55, 0x5B, 0xDF, - 0x8A, 0xED, 0x9A, 0x62, 0xC5, 0xD7, 0x18, 0x82, - 0xC7, 0x12, 0x15, 0x1B, 0xC0, 0x38, 0xCA, 0x26, - 0xDB, 0xAE, 0xF9, 0x90, 0x1A, 0xF2, 0x56, 0x32, - 0x21, 0x3C, 0x43, 0xEE, 0xA4, 0x13, 0x94, 0xA2, - 0x46, 0x77, 0xBC, 0xB6, 0x9C, 0x0D, 0xCD, 0x37, - 0x63, 0x60, 0x6B, 0x3A, 0x3E, 0xA7, 0xD8, 0xFE, - 0xFB, 0xEF, 0x67, 0xFD, 0xAD, 0xF1, 0x09, 0x1D, - 0xE9, 0x51, 0xB4, 0x95, 0x75, 0x0F, 0xB3, 0xD3, - 0xAB, 0x22, 0xBB, 0x61, 0x7F, 0x5A, 0x58, 0x7B, - 0x73, 0xC2, 0x05, 0xE0, 0x14, 0xE2, 0xAC, 0x91, - 0xBE, 0x4E, 0xC6, 0x7A, 0x84, 0x50, 0x28, 0x3F, - 0xB0, 0x04, 0x7E, 0xD1, 0x40, 0xBD, 0xE5, 0x71, - 0xB1, 0x78, 0x41, 0x9E, 0x57, 0x64, 0x8F, 0x24, - 0x4A, 0x9F, 0x3D, 0x31, 0x36, 0x5D, 0xA0, 0x2C, - 0x7D, 0x96, 0x76, 0x99, 0xB5, 0x48, 0x98, 0x10 }; - -static const unsigned char table_147[32] = { - 0x17, 0x07, 0x0D, 0x16, 0x00, 0x1B, 0x1F, 0x09, - 0x10, 0x11, 0x14, 0x0A, 0x02, 0x06, 0x13, 0x0C, - 0x08, 0x1E, 0x0F, 0x12, 0x05, 0x15, 0x19, 0x01, - 0x1C, 0x1A, 0x03, 0x18, 0x04, 0x0B, 0x1D, 0x0E }; - -static const unsigned char table_148[256] = { - 0xFB, 0x23, 0xBC, 0x5A, 0x8C, 0x02, 0x42, 0x3B, - 0x95, 0x0C, 0x21, 0x0E, 0x14, 0xDF, 0x11, 0xC0, - 0xDB, 0x5E, 0xD3, 0xEA, 0xCE, 0xB4, 0x32, 0x12, - 0x70, 0x68, 0xA3, 0x25, 0x5B, 0x4B, 0x47, 0xA5, - 0x84, 0x9B, 0xFA, 0xD1, 0xE1, 0x3C, 0x20, 0x93, - 0x41, 0x26, 0x81, 0x39, 0x17, 0xA4, 0xCF, 0xB9, - 0xC5, 0x5F, 0x1C, 0xB3, 0x88, 0xC2, 0x92, 0x30, - 0x0A, 0xB8, 0xA0, 0xE2, 0x50, 0x2B, 0x48, 0x1E, - 0xD5, 0x13, 0xC7, 0x46, 0x9E, 0x2A, 0xF7, 0x7E, - 0xE8, 0x82, 0x60, 0x7A, 0x36, 0x97, 0x0F, 0x8F, - 0x8B, 0x80, 0xE0, 0xEB, 0xB1, 0xC6, 0x6E, 0xAE, - 0x90, 0x76, 0xA7, 0x31, 0xBE, 0x9C, 0x18, 0x6D, - 0xAB, 0x6C, 0x7B, 0xFE, 0x62, 0x05, 0xE9, 0x66, - 0x2E, 0x38, 0xB5, 0xB2, 0xFD, 0xFC, 0x7F, 0xE3, - 0xA1, 0xF1, 0x99, 0x4D, 0x79, 0x22, 0xD2, 0x37, - 0x29, 0x01, 0x54, 0x00, 0xBD, 0x51, 0x1B, 0x07, - 0x0B, 0x4A, 0xEE, 0x57, 0xDA, 0x1A, 0x06, 0xCA, - 0xCB, 0x9A, 0xC9, 0x7D, 0xE4, 0xDC, 0xE5, 0x8D, - 0x75, 0x4F, 0xF6, 0xA2, 0x65, 0x7C, 0xD9, 0x9D, - 0x03, 0x27, 0x2D, 0x4C, 0x49, 0xD4, 0x5D, 0x3E, - 0xBA, 0x1D, 0xD8, 0x91, 0x74, 0x10, 0xF8, 0xDE, - 0xEF, 0xF0, 0x6A, 0x04, 0x72, 0x08, 0x78, 0x3A, - 0x53, 0xC4, 0x34, 0xF2, 0x64, 0xAF, 0x86, 0xC3, - 0xF3, 0x73, 0x67, 0xCC, 0x58, 0xF4, 0x96, 0xAC, - 0x3D, 0xE7, 0x15, 0x8E, 0x19, 0x61, 0xF9, 0xB6, - 0xCD, 0x87, 0xAA, 0xB0, 0x1F, 0x6F, 0xAD, 0x28, - 0xC8, 0x69, 0x56, 0xC1, 0x71, 0xED, 0xE6, 0x98, - 0x6B, 0x59, 0xB7, 0xF5, 0x2C, 0xEC, 0xA8, 0x94, - 0x89, 0xBB, 0xA9, 0xD7, 0x2F, 0x8A, 0x4E, 0xD6, - 0x33, 0x16, 0x0D, 0x83, 0x5C, 0x52, 0x85, 0xA6, - 0x40, 0x45, 0x9F, 0x44, 0x63, 0x35, 0x77, 0xFF, - 0x09, 0x43, 0xBF, 0xD0, 0x55, 0xDD, 0x3F, 0x24 }; - -static const unsigned char table_149[32] = { - 0x1B, 0x0B, 0x0C, 0x06, 0x1F, 0x17, 0x04, 0x1A, - 0x1E, 0x02, 0x0F, 0x16, 0x0E, 0x09, 0x10, 0x01, - 0x13, 0x19, 0x11, 0x00, 0x0A, 0x05, 0x03, 0x1C, - 0x18, 0x1D, 0x14, 0x0D, 0x07, 0x08, 0x15, 0x12 }; - -static const unsigned char table_150[256] = { - 0x57, 0xBC, 0x9D, 0x46, 0x14, 0xD0, 0x94, 0x95, - 0x1B, 0x12, 0xB8, 0xD4, 0x53, 0x73, 0x83, 0xE6, - 0x75, 0xE1, 0xD1, 0x0D, 0xDF, 0x23, 0x13, 0x40, - 0xF1, 0x0C, 0xA0, 0xC1, 0x22, 0xDA, 0xE8, 0xFB, - 0xE5, 0xC4, 0x16, 0x9C, 0x3F, 0xC3, 0x78, 0x3A, - 0x06, 0xC7, 0xA8, 0x79, 0xA4, 0xB3, 0x55, 0x88, - 0xA9, 0x82, 0xE3, 0x68, 0xFC, 0x3B, 0x26, 0x81, - 0xB4, 0x0A, 0x7D, 0x96, 0xDB, 0x2C, 0xE2, 0xCD, - 0x92, 0x5C, 0xED, 0x0E, 0x42, 0x98, 0xBE, 0xB7, - 0x63, 0x25, 0x7B, 0xD9, 0xEF, 0x11, 0xB9, 0xA3, - 0xFA, 0x00, 0x2A, 0x91, 0x71, 0xBF, 0xB2, 0x3D, - 0x20, 0x4C, 0xB0, 0x8C, 0x3C, 0x27, 0xAF, 0x09, - 0x10, 0x5D, 0x2B, 0x1D, 0xBD, 0x4B, 0x54, 0xD3, - 0xAB, 0x1A, 0xE7, 0xF8, 0x56, 0x65, 0xA5, 0xAD, - 0xEC, 0x17, 0x45, 0x28, 0xCA, 0xEA, 0x01, 0xF5, - 0x34, 0x84, 0x43, 0x8B, 0x03, 0x02, 0x90, 0x6B, - 0x60, 0xCE, 0x19, 0x86, 0x4F, 0x08, 0x35, 0x9A, - 0xAE, 0x07, 0xE0, 0xB6, 0xD6, 0x2D, 0xD2, 0x89, - 0x5F, 0xA6, 0x72, 0x05, 0x36, 0xB5, 0xC0, 0x5A, - 0x4D, 0xD7, 0x30, 0x37, 0x87, 0x50, 0xA2, 0x48, - 0x29, 0xAC, 0xDE, 0x93, 0x24, 0x6E, 0x1E, 0xF7, - 0x52, 0x5E, 0x41, 0xC8, 0xEB, 0x31, 0x7E, 0xE9, - 0x67, 0x7A, 0x47, 0x85, 0x8D, 0x74, 0x9E, 0x64, - 0x38, 0x9B, 0xBA, 0xCC, 0x9F, 0x8E, 0xEE, 0x0F, - 0xB1, 0x7C, 0x6A, 0xBB, 0x2E, 0x58, 0x70, 0x7F, - 0x4E, 0x4A, 0x1C, 0x5B, 0xF0, 0xA1, 0x61, 0xF6, - 0x15, 0x33, 0xE4, 0xF9, 0x2F, 0x62, 0x1F, 0x76, - 0x32, 0xCB, 0x49, 0xFE, 0x8F, 0xD5, 0xDC, 0x66, - 0x0B, 0x3E, 0xC5, 0x21, 0xC6, 0x6C, 0x18, 0xC2, - 0x6D, 0xFF, 0x51, 0x99, 0xCF, 0xFD, 0x59, 0xA7, - 0xAA, 0x8A, 0xF2, 0x69, 0x39, 0x6F, 0x77, 0xDD, - 0x97, 0xC9, 0xF3, 0x04, 0xD8, 0xF4, 0x80, 0x44 }; - -static const unsigned char table_151[256] = { - 0x78, 0x6C, 0xC5, 0x0C, 0x2D, 0xA7, 0x97, 0x9C, - 0x22, 0x76, 0x3E, 0x81, 0x51, 0x47, 0x59, 0x71, - 0xB1, 0xA2, 0x4A, 0x3C, 0xB5, 0x16, 0x06, 0x95, - 0xB9, 0x01, 0xE6, 0x91, 0x96, 0x1C, 0x1B, 0xAD, - 0x61, 0x64, 0xB2, 0xE7, 0x29, 0x19, 0x52, 0x3B, - 0xFA, 0xAF, 0x30, 0xDB, 0xD4, 0x0B, 0xFE, 0x75, - 0x1F, 0xBE, 0xCB, 0xF6, 0xEA, 0x31, 0xF8, 0xD8, - 0xA3, 0x82, 0x73, 0x1D, 0x99, 0xF0, 0xCC, 0xB6, - 0x46, 0x26, 0xAA, 0x8C, 0x87, 0x90, 0x24, 0x8F, - 0x7A, 0x13, 0xEE, 0xD1, 0xA9, 0x05, 0xB3, 0xF7, - 0x02, 0x7C, 0x4C, 0x1E, 0xFF, 0xE5, 0x77, 0xAB, - 0xD6, 0x98, 0x20, 0x4D, 0xC4, 0x23, 0xF4, 0xA4, - 0x85, 0x9A, 0x8E, 0x1A, 0x0E, 0xF5, 0x15, 0x60, - 0x38, 0x72, 0xE9, 0xF1, 0xC3, 0x68, 0xF2, 0x93, - 0xD3, 0x2A, 0x48, 0x74, 0xC2, 0x57, 0xA1, 0x7D, - 0x94, 0x37, 0x92, 0x5C, 0xE1, 0x41, 0x83, 0xD5, - 0x65, 0x14, 0xA6, 0xDC, 0x44, 0x27, 0xEF, 0xD7, - 0x25, 0x10, 0x2C, 0x7F, 0x40, 0xA5, 0x55, 0xBD, - 0x2B, 0x0D, 0xD0, 0xFC, 0xDF, 0xA0, 0x04, 0x00, - 0x62, 0xB4, 0x5A, 0xEB, 0x6B, 0x84, 0x7E, 0x6A, - 0xDE, 0xED, 0x66, 0x03, 0xFB, 0x2E, 0x4F, 0x4E, - 0xBB, 0x36, 0x5B, 0x18, 0xE3, 0x69, 0x3F, 0xEC, - 0xE4, 0xD2, 0x0A, 0x34, 0x63, 0xCF, 0xA8, 0xF9, - 0x9B, 0x7B, 0x6F, 0xE8, 0x49, 0xC1, 0x09, 0x54, - 0xF3, 0x50, 0x67, 0x79, 0xC0, 0x9F, 0x8D, 0x5F, - 0x17, 0x70, 0x11, 0xC8, 0xBC, 0xC6, 0xE0, 0x35, - 0x39, 0xC7, 0x6E, 0x21, 0xBF, 0xDA, 0x6D, 0x28, - 0x0F, 0xDD, 0x33, 0xAC, 0x8A, 0x12, 0xC9, 0xCD, - 0xB8, 0x45, 0xAE, 0x32, 0xCE, 0xE2, 0x56, 0xFD, - 0x42, 0x89, 0x86, 0xCA, 0x4B, 0x3D, 0x5E, 0xBA, - 0x8B, 0x5D, 0xB0, 0xB7, 0xD9, 0x58, 0x2F, 0x08, - 0x43, 0x3A, 0x53, 0x9E, 0x80, 0x88, 0x07, 0x9D }; - -static const unsigned char table_152[32] = { - 0x02, 0x1A, 0x17, 0x1D, 0x01, 0x03, 0x13, 0x1E, - 0x05, 0x18, 0x06, 0x0A, 0x0C, 0x04, 0x1B, 0x00, - 0x1C, 0x09, 0x1F, 0x16, 0x07, 0x0F, 0x0B, 0x0E, - 0x14, 0x12, 0x0D, 0x10, 0x19, 0x11, 0x08, 0x15 }; - -static const unsigned char table_153[32] = { - 0x0E, 0x14, 0x12, 0x1E, 0x1C, 0x02, 0x06, 0x16, - 0x18, 0x0D, 0x17, 0x0C, 0x1D, 0x11, 0x08, 0x19, - 0x07, 0x0F, 0x13, 0x04, 0x03, 0x1B, 0x0B, 0x1F, - 0x1A, 0x0A, 0x05, 0x10, 0x00, 0x01, 0x15, 0x09 }; - -static const unsigned char table_154[256] = { - 0x27, 0x5A, 0x08, 0x5B, 0xF4, 0x39, 0x13, 0x6F, - 0x67, 0xEA, 0x22, 0xCA, 0x5C, 0xCF, 0x18, 0x7C, - 0x05, 0x87, 0x60, 0xCC, 0x40, 0xC6, 0xE8, 0x6D, - 0xF5, 0x2A, 0x2D, 0xA2, 0x8C, 0x82, 0xE9, 0xDC, - 0xD6, 0x65, 0x74, 0x8E, 0x42, 0x4F, 0x3E, 0x55, - 0xFF, 0xC7, 0x9D, 0x0F, 0x81, 0xE2, 0x4C, 0xE6, - 0xEB, 0x4D, 0x70, 0xD1, 0x49, 0x43, 0x3D, 0x69, - 0x0C, 0x45, 0x28, 0x00, 0x99, 0xAE, 0xEC, 0xB8, - 0xC3, 0x17, 0x93, 0x8D, 0x36, 0x3C, 0x46, 0x2B, - 0x29, 0xC5, 0xB4, 0xB1, 0xD0, 0x0D, 0xAD, 0xFE, - 0xE5, 0xA8, 0x3B, 0x1A, 0x2C, 0xDF, 0x07, 0x86, - 0xB0, 0xD3, 0x7A, 0x59, 0x79, 0x8B, 0xC1, 0x9A, - 0x30, 0xDB, 0x24, 0xF3, 0xD8, 0x04, 0x25, 0xC2, - 0xA3, 0x98, 0x96, 0x7B, 0x71, 0x4E, 0x5E, 0x58, - 0xA5, 0x51, 0x88, 0xDA, 0xF8, 0xC0, 0x7D, 0xF6, - 0x31, 0x5F, 0x09, 0x16, 0x21, 0x62, 0x01, 0x64, - 0x9B, 0x3A, 0x2F, 0x61, 0x19, 0xA1, 0xB7, 0xE0, - 0xB9, 0x12, 0xA0, 0xBA, 0x6E, 0x8A, 0xFB, 0xD9, - 0x38, 0x1B, 0xD5, 0xB3, 0x10, 0xED, 0xE4, 0x6A, - 0x32, 0xBD, 0x75, 0xD4, 0x1C, 0xFD, 0x73, 0x77, - 0x54, 0xC8, 0x97, 0x47, 0x35, 0x94, 0xE3, 0xCD, - 0x6B, 0xBB, 0xF9, 0xAC, 0x11, 0x14, 0xAF, 0x78, - 0x3F, 0xCE, 0x26, 0x44, 0xEE, 0xFC, 0x15, 0x66, - 0x4B, 0xA6, 0x20, 0x23, 0xBE, 0x84, 0x1D, 0x7E, - 0x0B, 0x56, 0x92, 0x0A, 0xFA, 0xF7, 0x48, 0x33, - 0x9E, 0x8F, 0xAB, 0x5D, 0x41, 0x50, 0xA4, 0x7F, - 0x80, 0x4A, 0x68, 0x06, 0x2E, 0x6C, 0xC4, 0x02, - 0x0E, 0x63, 0xF0, 0xC9, 0x91, 0xB2, 0xD2, 0x03, - 0x37, 0xEF, 0x9C, 0x90, 0x83, 0x76, 0x1E, 0xA9, - 0x85, 0xB6, 0x57, 0xD7, 0xF2, 0xF1, 0xE7, 0xDE, - 0xCB, 0xAA, 0xBF, 0x89, 0x1F, 0xA7, 0xBC, 0x9F, - 0x53, 0xE1, 0xDD, 0x72, 0x95, 0x52, 0x34, 0xB5 }; - -static const unsigned char table_155[256] = { - 0x75, 0x58, 0xC5, 0xA5, 0x83, 0x16, 0xF3, 0x7F, - 0x94, 0xDE, 0xA0, 0xF6, 0xFD, 0x89, 0xA8, 0x06, - 0x98, 0x01, 0xD9, 0x69, 0xB7, 0x0F, 0xEA, 0x73, - 0x32, 0xF0, 0x49, 0xBF, 0x02, 0xE7, 0x22, 0x3F, - 0xDB, 0x30, 0x5F, 0x20, 0x6A, 0x93, 0x07, 0xBC, - 0x09, 0x0D, 0x37, 0x24, 0x90, 0x15, 0x80, 0xAF, - 0x8F, 0x59, 0x28, 0xFF, 0x6D, 0x1E, 0x52, 0x62, - 0xE2, 0xDD, 0x85, 0x48, 0xB5, 0xAB, 0x68, 0xAC, - 0x7E, 0x26, 0x2C, 0xF9, 0x2A, 0xBE, 0x5B, 0xCE, - 0x87, 0x1D, 0x96, 0xBD, 0xEF, 0x29, 0xA9, 0xC3, - 0x9D, 0x57, 0x79, 0x6B, 0x7A, 0x82, 0x78, 0x0A, - 0x91, 0xF2, 0x7C, 0xC2, 0x25, 0x88, 0xE3, 0x47, - 0x64, 0x46, 0x8D, 0x19, 0xF4, 0xE6, 0xF1, 0x53, - 0x9C, 0x54, 0x23, 0xAD, 0xA3, 0x86, 0x3A, 0x04, - 0x67, 0x1C, 0xF5, 0x43, 0x05, 0x42, 0xD6, 0x4B, - 0xFB, 0xD4, 0x2B, 0x08, 0x45, 0xD8, 0xCD, 0xEB, - 0x31, 0x4A, 0x5A, 0x34, 0x9B, 0xEC, 0x4D, 0xB4, - 0xC6, 0xFE, 0xD5, 0x5E, 0xC1, 0x39, 0x81, 0xCF, - 0x03, 0x6E, 0x95, 0x50, 0xA1, 0x3B, 0xB3, 0xE5, - 0x3D, 0xB1, 0xB2, 0x41, 0x17, 0x2F, 0x2E, 0xE4, - 0x1F, 0xDC, 0xB0, 0xB6, 0x18, 0x6F, 0x44, 0x12, - 0x0B, 0xCC, 0x4E, 0xC0, 0x51, 0x14, 0x76, 0x3C, - 0xB9, 0x9F, 0xA4, 0xD3, 0xA7, 0xE8, 0x13, 0x55, - 0xC8, 0x8C, 0xD2, 0xEE, 0x65, 0xB8, 0xAA, 0x6C, - 0x2D, 0x4F, 0x56, 0xFA, 0x61, 0x4C, 0xE0, 0x5C, - 0xA6, 0x1A, 0xD1, 0x38, 0xD7, 0x72, 0x60, 0x74, - 0xE1, 0xBA, 0x84, 0x3E, 0x40, 0xF8, 0xC7, 0x36, - 0x27, 0x0C, 0x70, 0x97, 0x9A, 0x7D, 0x35, 0x71, - 0xCA, 0x1B, 0x99, 0x8E, 0xAE, 0x66, 0x63, 0xE9, - 0xC9, 0x11, 0x8A, 0x21, 0x92, 0x5D, 0x77, 0x10, - 0xD0, 0xC4, 0xF7, 0x7B, 0x9E, 0xCB, 0xED, 0x0E, - 0x8B, 0x33, 0xFC, 0xBB, 0x00, 0xA2, 0xDF, 0xDA }; - -static const unsigned char table_156[256] = { - 0x31, 0x25, 0xB1, 0xD3, 0xAF, 0xAE, 0x84, 0x2C, - 0x71, 0x5E, 0xD8, 0x80, 0x6F, 0x3E, 0x48, 0x86, - 0xED, 0x54, 0x6A, 0xC3, 0xBC, 0xBF, 0x0E, 0xEA, - 0x10, 0xA2, 0x9D, 0x91, 0x32, 0xE2, 0x7E, 0x1B, - 0x49, 0x27, 0xFF, 0xDD, 0x8A, 0x2F, 0x8D, 0x38, - 0xFA, 0x3C, 0x03, 0x14, 0x0F, 0x89, 0xCC, 0x07, - 0x1A, 0xA0, 0x97, 0x37, 0xA6, 0xD6, 0x63, 0x87, - 0xA1, 0xC2, 0x4B, 0x39, 0xCB, 0xCF, 0x69, 0x4E, - 0xC9, 0x28, 0x1C, 0xBB, 0x42, 0x2B, 0xA9, 0x78, - 0x5B, 0xF6, 0xE0, 0xD0, 0x5F, 0x46, 0x98, 0xCE, - 0x1F, 0x7A, 0x34, 0x8B, 0xFD, 0x9B, 0xEF, 0x74, - 0x05, 0xF2, 0x02, 0xC6, 0xDF, 0x73, 0x5C, 0x8E, - 0xDE, 0x88, 0x57, 0x3B, 0x85, 0xBD, 0xC0, 0x3A, - 0x45, 0x4D, 0x2D, 0x72, 0x0C, 0x60, 0xCA, 0x5D, - 0x06, 0x04, 0x3D, 0x51, 0x15, 0xAD, 0xE8, 0x67, - 0xBA, 0x43, 0x7D, 0xF8, 0xB2, 0xE6, 0xAB, 0xF4, - 0x23, 0x6E, 0xF0, 0x6B, 0x0B, 0x2E, 0xC8, 0xC4, - 0x4F, 0xA8, 0x6D, 0x26, 0xE9, 0x9C, 0x22, 0xB7, - 0x00, 0xB3, 0x0A, 0x7C, 0x44, 0x55, 0x75, 0xD5, - 0xAA, 0x66, 0x56, 0x24, 0x83, 0x90, 0xA4, 0xF5, - 0xCD, 0xEC, 0x18, 0xDC, 0xFE, 0x96, 0xA3, 0xF7, - 0xD2, 0xFB, 0xD1, 0x65, 0xC5, 0x08, 0x7B, 0x70, - 0x16, 0x9A, 0x20, 0x09, 0x29, 0xDA, 0x52, 0x5A, - 0x59, 0xB4, 0x77, 0x62, 0x9E, 0x19, 0x7F, 0x82, - 0x4C, 0xB6, 0x0D, 0x58, 0xEE, 0x1D, 0xB9, 0x93, - 0x50, 0xD9, 0x30, 0xE4, 0x13, 0x01, 0x36, 0x8F, - 0x53, 0x3F, 0x64, 0xA5, 0xB5, 0xD7, 0x81, 0x41, - 0x17, 0xE5, 0x94, 0xE3, 0xF9, 0x61, 0x76, 0xE1, - 0x9F, 0xFC, 0x1E, 0x12, 0xDB, 0x21, 0x79, 0x2A, - 0xAC, 0xF3, 0x6C, 0xC1, 0x95, 0x92, 0xEB, 0xA7, - 0x11, 0xC7, 0xB8, 0x4A, 0x33, 0xB0, 0x99, 0xE7, - 0xF1, 0x68, 0xBE, 0x35, 0x40, 0x8C, 0xD4, 0x47 }; - -static const unsigned char table_157[32] = { - 0x00, 0x0D, 0x03, 0x02, 0x11, 0x04, 0x18, 0x0B, - 0x14, 0x1D, 0x1C, 0x13, 0x1B, 0x17, 0x10, 0x15, - 0x01, 0x19, 0x07, 0x09, 0x1A, 0x16, 0x12, 0x1E, - 0x08, 0x06, 0x0C, 0x0E, 0x1F, 0x0F, 0x0A, 0x05 }; - -static const unsigned char table_158[256] = { - 0x68, 0x26, 0x80, 0x0B, 0xB8, 0xD5, 0x8C, 0xB7, - 0x65, 0xEF, 0xBC, 0x94, 0x28, 0xB9, 0xB2, 0xD2, - 0x92, 0xA4, 0x55, 0x27, 0xE0, 0x40, 0x6C, 0x41, - 0x25, 0xBD, 0xAF, 0xEA, 0xB1, 0x19, 0xA5, 0xC9, - 0x0E, 0xED, 0xB4, 0xF9, 0x8B, 0x6A, 0xAE, 0xD8, - 0x64, 0x83, 0xC1, 0xD3, 0x04, 0xF4, 0xFA, 0xC3, - 0x46, 0x2C, 0xA8, 0xBB, 0x3A, 0x47, 0x33, 0x8F, - 0x52, 0x86, 0x08, 0x9D, 0x1D, 0x59, 0x8E, 0x91, - 0x32, 0xCF, 0x6B, 0x75, 0xB0, 0x7F, 0xC7, 0x24, - 0x05, 0x6F, 0x00, 0x1C, 0x2D, 0xAC, 0xDA, 0x45, - 0x73, 0xB3, 0x3E, 0xD6, 0x54, 0x61, 0x03, 0x77, - 0xF8, 0xD9, 0xE2, 0x4B, 0xFF, 0xF2, 0x0C, 0x4F, - 0x93, 0x71, 0xA7, 0x3D, 0x66, 0x88, 0x98, 0xF1, - 0xB6, 0x7A, 0x2B, 0xCD, 0x44, 0x3C, 0x37, 0x5A, - 0x96, 0x23, 0x9F, 0xBF, 0x7D, 0x5E, 0x2A, 0x35, - 0x72, 0x79, 0xE1, 0xA3, 0x84, 0x99, 0x38, 0x49, - 0xC8, 0xDB, 0x30, 0xDC, 0xAD, 0x3F, 0xF6, 0x09, - 0x69, 0x95, 0xE5, 0x67, 0xA1, 0xFD, 0xF7, 0x1B, - 0xEC, 0x17, 0xD4, 0xEB, 0x29, 0x36, 0x3B, 0x15, - 0xDE, 0x2E, 0xC5, 0x70, 0x6D, 0x53, 0x56, 0xAB, - 0xC0, 0x43, 0xC2, 0xE7, 0x31, 0xE6, 0xA6, 0x78, - 0x5C, 0x7C, 0x48, 0x10, 0x87, 0xCC, 0x9E, 0x7E, - 0x5F, 0xE9, 0x07, 0x5B, 0xF5, 0xEE, 0xB5, 0xCA, - 0x62, 0x18, 0xBE, 0x20, 0x16, 0xDF, 0x13, 0x4E, - 0x7B, 0x02, 0x11, 0x4C, 0x51, 0x85, 0x0D, 0x22, - 0xF3, 0x14, 0x63, 0x76, 0xD0, 0x0F, 0xE4, 0xCB, - 0xCE, 0xA0, 0x82, 0xE3, 0x01, 0xAA, 0x5D, 0x4A, - 0x4D, 0xFB, 0x39, 0x8A, 0x2F, 0xDD, 0xE8, 0x06, - 0x1A, 0x90, 0x81, 0x50, 0x8D, 0x89, 0x97, 0x1E, - 0xFC, 0x60, 0x12, 0x42, 0x9C, 0xF0, 0x34, 0xD7, - 0xD1, 0x1F, 0x0A, 0x21, 0xA9, 0x6E, 0xC4, 0xBA, - 0x9A, 0x57, 0xA2, 0x74, 0xC6, 0xFE, 0x9B, 0x58 }; - -static const unsigned char table_159[256] = { - 0xE5, 0xBF, 0x84, 0x56, 0xD6, 0x43, 0x3E, 0xA5, - 0x64, 0x87, 0x44, 0x63, 0x4A, 0x4C, 0x8D, 0x24, - 0x1C, 0xDA, 0x89, 0x52, 0x80, 0x4F, 0xE4, 0xBC, - 0xC5, 0xF4, 0x27, 0x75, 0x9C, 0xF0, 0xE1, 0x06, - 0x99, 0x48, 0xF2, 0x57, 0x34, 0x9A, 0xA8, 0x62, - 0xC9, 0xD5, 0x16, 0x6D, 0x55, 0xFA, 0x37, 0x5A, - 0x2A, 0xC6, 0x45, 0xDD, 0x1B, 0x76, 0x50, 0xE2, - 0x69, 0x41, 0x6C, 0xC4, 0x3C, 0x47, 0xA9, 0x92, - 0x00, 0x3D, 0x6F, 0xE7, 0x7A, 0x3A, 0x33, 0x53, - 0xF7, 0x03, 0xA7, 0xB1, 0x15, 0x78, 0x0B, 0x67, - 0x2E, 0x21, 0xF1, 0xD4, 0xB3, 0x98, 0x60, 0x58, - 0xBB, 0x82, 0x1E, 0x70, 0x0A, 0xA2, 0x02, 0x17, - 0xFF, 0x9F, 0xD2, 0xAF, 0xC7, 0xDC, 0x68, 0x83, - 0x42, 0xCA, 0x08, 0x39, 0x20, 0xEC, 0x77, 0x96, - 0x5B, 0xAD, 0x09, 0x6B, 0x40, 0xC2, 0x91, 0x51, - 0x10, 0xD9, 0xF9, 0xC1, 0xB5, 0xDF, 0xDB, 0xC0, - 0x7D, 0xAB, 0xAE, 0x54, 0x35, 0xF3, 0xA1, 0xE6, - 0xEA, 0x14, 0xBA, 0xFC, 0xE8, 0xEB, 0xF6, 0xBD, - 0x8C, 0x72, 0x1F, 0xE9, 0xFB, 0x7C, 0xCF, 0x49, - 0xE3, 0xA3, 0x22, 0x9D, 0x46, 0x71, 0x94, 0x31, - 0x2D, 0x65, 0x2B, 0x32, 0x18, 0xB6, 0x90, 0xF8, - 0x11, 0x5F, 0xA0, 0xEF, 0xED, 0x1A, 0x25, 0x2C, - 0x3B, 0xFD, 0x2F, 0x73, 0xB9, 0x7E, 0xDE, 0xB4, - 0x97, 0x0F, 0x7F, 0x86, 0x93, 0x07, 0x19, 0xCE, - 0xE0, 0xB7, 0xEE, 0x26, 0xD1, 0x01, 0x59, 0x5C, - 0xC3, 0x79, 0x8B, 0xD3, 0x4B, 0x04, 0xD0, 0x29, - 0x0D, 0x3F, 0xB2, 0x30, 0xCC, 0x36, 0xFE, 0xB0, - 0xF5, 0x8E, 0xA6, 0x8A, 0xC8, 0xD8, 0x05, 0xB8, - 0x12, 0xBE, 0x81, 0x4D, 0x38, 0xAC, 0x1D, 0x9E, - 0x66, 0x5E, 0x7B, 0x6E, 0x0C, 0xCD, 0x6A, 0x88, - 0xAA, 0x0E, 0x61, 0x5D, 0x95, 0x4E, 0xD7, 0x74, - 0xCB, 0x9B, 0x13, 0x8F, 0xA4, 0x28, 0x23, 0x85 }; - -static const unsigned char table_160[256] = { - 0x35, 0x44, 0x0E, 0x92, 0x75, 0x83, 0x9D, 0x53, - 0xA5, 0x90, 0xF8, 0xF7, 0x54, 0x74, 0xDF, 0x3D, - 0x5A, 0xAA, 0xC6, 0x26, 0x7A, 0xFC, 0x79, 0x6C, - 0x56, 0xB3, 0x32, 0xE3, 0x1C, 0xF9, 0xDC, 0xE6, - 0xA2, 0x93, 0x71, 0xFF, 0x1D, 0xEB, 0xB2, 0x04, - 0x96, 0x46, 0x0C, 0x2B, 0x17, 0xEE, 0x28, 0x25, - 0xD9, 0xAE, 0x11, 0xA7, 0x40, 0x45, 0xFB, 0x80, - 0x18, 0xF1, 0xCB, 0x2E, 0x24, 0xF3, 0xEC, 0x4F, - 0xAB, 0xD7, 0xD4, 0xC4, 0xFD, 0x4B, 0xAD, 0xC9, - 0x4C, 0x08, 0xAC, 0xF4, 0xCD, 0xB7, 0xF2, 0x15, - 0x02, 0x2F, 0x16, 0x34, 0x65, 0x8A, 0x87, 0xCC, - 0x50, 0x0F, 0x9B, 0xC2, 0xC8, 0x7B, 0xEA, 0x8E, - 0xE4, 0xD6, 0x97, 0x30, 0xA8, 0xA0, 0x94, 0xC5, - 0xE8, 0x12, 0x27, 0xCE, 0x84, 0xDD, 0xB1, 0x47, - 0x7E, 0xE7, 0xE1, 0x3A, 0x37, 0x21, 0x2D, 0x3B, - 0x20, 0x60, 0x1E, 0x1B, 0x82, 0xBE, 0xA3, 0x70, - 0x98, 0xBF, 0xA6, 0x4D, 0x76, 0x86, 0x42, 0x9F, - 0xCF, 0xE0, 0x14, 0x4A, 0x0B, 0xB4, 0x36, 0xF5, - 0x85, 0xB8, 0xC0, 0x6A, 0xE9, 0x7D, 0xBD, 0x4E, - 0x8F, 0x51, 0x0D, 0x5B, 0x6B, 0x58, 0x5F, 0x03, - 0x6F, 0xBC, 0x5D, 0x1F, 0x7F, 0xDB, 0x00, 0xC1, - 0x13, 0xF0, 0xD1, 0xFA, 0xDA, 0x05, 0x39, 0xD3, - 0x38, 0xD2, 0x89, 0xE2, 0x88, 0x5E, 0x5C, 0x6D, - 0xCA, 0xB0, 0x01, 0x63, 0x8B, 0x59, 0xA4, 0xD0, - 0x78, 0x19, 0xB5, 0x62, 0x1A, 0x69, 0x8D, 0x9C, - 0x22, 0x3F, 0x9E, 0x33, 0x72, 0x2A, 0x41, 0x29, - 0xFE, 0xF6, 0x64, 0x7C, 0x66, 0xB6, 0xAF, 0x23, - 0x8C, 0x68, 0x6E, 0x49, 0x07, 0x99, 0x77, 0x3E, - 0x9A, 0x73, 0xD8, 0x55, 0x0A, 0x3C, 0xBA, 0xA9, - 0x52, 0xED, 0x91, 0x09, 0x95, 0xC7, 0x43, 0xD5, - 0x57, 0x61, 0x81, 0xEF, 0x06, 0xDE, 0x48, 0x31, - 0xBB, 0x2C, 0xE5, 0xC3, 0x67, 0xA1, 0x10, 0xB9 }; - -static const unsigned char table_161[256] = { - 0x8F, 0x1A, 0x81, 0xA2, 0x2C, 0x56, 0x6D, 0xCD, - 0x4A, 0x33, 0x50, 0xE9, 0xE0, 0x12, 0x5A, 0x43, - 0x2D, 0x4F, 0xEA, 0x95, 0xFD, 0x49, 0xAB, 0xA3, - 0x79, 0x42, 0x0B, 0xB8, 0x89, 0x40, 0x71, 0x14, - 0x80, 0x55, 0xAF, 0xCF, 0x3E, 0x64, 0x8B, 0x74, - 0xBF, 0x9C, 0x24, 0x97, 0xD1, 0xBA, 0x48, 0xD2, - 0x08, 0x1F, 0xDD, 0xA7, 0xDC, 0x92, 0x30, 0x75, - 0x31, 0x37, 0x67, 0x06, 0x68, 0x72, 0x6F, 0x05, - 0x8A, 0x7C, 0x4C, 0x3C, 0x19, 0x28, 0x86, 0x3D, - 0x93, 0xDA, 0xF4, 0xC7, 0x17, 0x85, 0xAC, 0x02, - 0x78, 0x04, 0xAD, 0x03, 0x8D, 0x11, 0xC5, 0x9D, - 0x3A, 0x73, 0x82, 0x59, 0x51, 0x9F, 0x27, 0x47, - 0xE7, 0xED, 0x1E, 0xFF, 0x34, 0x01, 0x5B, 0x4B, - 0xCA, 0x6C, 0x69, 0xBB, 0x3B, 0xC4, 0x5F, 0xDF, - 0x09, 0x6B, 0x7D, 0xC9, 0x88, 0x45, 0x57, 0xD3, - 0x2A, 0x4E, 0xF1, 0xC2, 0xA9, 0xB6, 0x18, 0xD4, - 0xA0, 0x1C, 0x4D, 0x0E, 0xE5, 0xE1, 0xD7, 0xB2, - 0x0C, 0x3F, 0x00, 0x61, 0x16, 0x0D, 0x32, 0x62, - 0x58, 0x63, 0xEE, 0xEF, 0x2F, 0x5D, 0xB0, 0x20, - 0x7A, 0x10, 0xE6, 0xA1, 0xF9, 0xD8, 0x6E, 0xCB, - 0xF0, 0x9B, 0x84, 0x8E, 0xF2, 0xFE, 0xC8, 0x7F, - 0xBD, 0xF8, 0x07, 0xC6, 0x39, 0xBC, 0xCC, 0x22, - 0x54, 0x15, 0x9A, 0xA4, 0xC1, 0x2B, 0x1B, 0x25, - 0xDE, 0x6A, 0xDB, 0x90, 0xEB, 0xB7, 0xD0, 0x44, - 0xA6, 0xB9, 0xB1, 0x23, 0x9E, 0x65, 0x83, 0xFA, - 0x96, 0xB5, 0x0F, 0xF6, 0xD6, 0xE8, 0x53, 0x13, - 0x76, 0xD5, 0x35, 0x87, 0xE3, 0x38, 0xF5, 0xAE, - 0xB3, 0xCE, 0xE2, 0x70, 0xD9, 0x66, 0x5C, 0x26, - 0xC3, 0xFC, 0xF7, 0x94, 0xF3, 0xEC, 0xFB, 0x99, - 0x91, 0x77, 0xB4, 0x46, 0xA5, 0x98, 0x7B, 0x1D, - 0x52, 0x2E, 0xA8, 0x60, 0x5E, 0x29, 0x21, 0x7E, - 0xBE, 0x0A, 0x36, 0x41, 0xC0, 0x8C, 0xE4, 0xAA }; - -static const unsigned char table_162[256] = { - 0xF7, 0x1B, 0xC0, 0x31, 0x5A, 0x23, 0xEA, 0xE9, - 0xFB, 0x14, 0x6A, 0xE8, 0x04, 0x65, 0x5B, 0x2C, - 0x41, 0xD9, 0xEB, 0xE4, 0x8D, 0x1D, 0xCA, 0x8F, - 0x5E, 0x43, 0xAF, 0x46, 0x0A, 0x01, 0x0C, 0xB4, - 0x95, 0x52, 0x92, 0xE0, 0x10, 0x57, 0x0F, 0x71, - 0xB1, 0x26, 0xD8, 0x05, 0x69, 0x3C, 0x54, 0xDF, - 0xFF, 0x9D, 0x51, 0xA0, 0xA1, 0x0B, 0xC1, 0x20, - 0x6D, 0xFA, 0x47, 0x15, 0x09, 0xD3, 0xE1, 0xA9, - 0x66, 0x12, 0x5C, 0x49, 0x1E, 0x3B, 0xD0, 0x8B, - 0x62, 0xBD, 0x06, 0xE5, 0x00, 0x98, 0x4E, 0x32, - 0xB0, 0x2D, 0x2A, 0x7F, 0x03, 0xD5, 0x99, 0x7E, - 0xAB, 0x22, 0xC6, 0xC3, 0x2F, 0x4C, 0x33, 0x45, - 0xE3, 0x3F, 0xF9, 0xB2, 0xFE, 0x36, 0xE7, 0xF8, - 0x55, 0x0D, 0x56, 0x1F, 0x4B, 0xE6, 0x50, 0x81, - 0xCE, 0x80, 0xCD, 0x67, 0x6B, 0xCF, 0x2E, 0x9B, - 0xBC, 0xBE, 0x11, 0x75, 0x4D, 0xAC, 0x59, 0x40, - 0x85, 0x0E, 0xC9, 0x17, 0xA3, 0x60, 0xED, 0x16, - 0xA4, 0xDD, 0xEE, 0x96, 0x77, 0x83, 0x34, 0xD2, - 0xCB, 0xFC, 0x6C, 0x08, 0xEC, 0x35, 0xF2, 0x6F, - 0x3A, 0x7B, 0x21, 0x4A, 0x70, 0xEF, 0xAD, 0xDE, - 0x90, 0x9E, 0x7D, 0x64, 0x2B, 0x79, 0xF5, 0xF3, - 0x13, 0x1C, 0x7A, 0x07, 0x4F, 0x78, 0x89, 0xB6, - 0x97, 0xF1, 0xD7, 0x7C, 0x48, 0xAE, 0x39, 0xA8, - 0xA6, 0x86, 0x3E, 0x27, 0x87, 0x73, 0x82, 0x24, - 0x30, 0x74, 0x5F, 0xD1, 0x9F, 0x9C, 0x1A, 0x8C, - 0x42, 0x6E, 0x28, 0xB9, 0xF0, 0xC4, 0x68, 0x25, - 0xC5, 0xDC, 0xB8, 0x29, 0xD6, 0x84, 0x3D, 0xBB, - 0x88, 0x76, 0xFD, 0x61, 0x94, 0x91, 0xDA, 0xB7, - 0x72, 0xBA, 0xC2, 0xDB, 0xB5, 0xA5, 0xE2, 0x18, - 0xF6, 0xAA, 0x8A, 0x19, 0x63, 0x9A, 0xA7, 0xC8, - 0xD4, 0x02, 0x8E, 0x37, 0xF4, 0xB3, 0xA2, 0x53, - 0x38, 0xCC, 0x58, 0x44, 0xBF, 0x93, 0x5D, 0xC7 }; - -static const unsigned char table_163[32] = { - 0x1B, 0x14, 0x12, 0x15, 0x11, 0x1D, 0x17, 0x19, - 0x10, 0x09, 0x08, 0x06, 0x1A, 0x16, 0x07, 0x13, - 0x1F, 0x0B, 0x1C, 0x05, 0x0E, 0x00, 0x18, 0x0A, - 0x04, 0x01, 0x03, 0x0C, 0x0D, 0x1E, 0x02, 0x0F }; - -static const unsigned char table_164[32] = { - 0x15, 0x00, 0x10, 0x0B, 0x1D, 0x0A, 0x06, 0x1C, - 0x0D, 0x1F, 0x17, 0x0F, 0x03, 0x14, 0x13, 0x12, - 0x1B, 0x18, 0x08, 0x1E, 0x16, 0x09, 0x1A, 0x04, - 0x02, 0x0C, 0x0E, 0x01, 0x07, 0x19, 0x11, 0x05 }; - -static const unsigned char table_165[256] = { - 0x98, 0xF5, 0x1D, 0xFB, 0x13, 0x20, 0x41, 0xA3, - 0xE3, 0x76, 0x49, 0x7E, 0x60, 0xD8, 0x68, 0x30, - 0x88, 0x45, 0xD5, 0x77, 0x00, 0xC3, 0x09, 0x31, - 0x44, 0x18, 0xD4, 0x14, 0xC8, 0x1B, 0x8B, 0x38, - 0x08, 0x52, 0xD1, 0xF3, 0x69, 0x9F, 0xDA, 0x61, - 0x16, 0x1C, 0xE4, 0x7D, 0xEE, 0xD9, 0x5E, 0x4C, - 0xA7, 0xAA, 0xA6, 0xF6, 0xCF, 0xA0, 0xBA, 0x10, - 0xE2, 0xDE, 0x0F, 0xEA, 0xBC, 0x32, 0x63, 0xC0, - 0x54, 0xC5, 0xBE, 0x71, 0x80, 0x56, 0x5C, 0xA4, - 0xAD, 0x15, 0x9D, 0x11, 0x43, 0x67, 0x95, 0xAE, - 0xC6, 0xC4, 0x91, 0x9C, 0xE5, 0x37, 0xE1, 0x7A, - 0xDB, 0xEF, 0x03, 0x65, 0x86, 0x66, 0x2A, 0xB5, - 0xBF, 0xB4, 0x0D, 0xB3, 0xD7, 0x2D, 0x01, 0xEB, - 0x8C, 0xF2, 0x5A, 0x2E, 0x64, 0x25, 0x02, 0xCB, - 0x4A, 0xB0, 0xCE, 0x35, 0xA8, 0x47, 0x85, 0x33, - 0x34, 0x24, 0x23, 0x7B, 0xB6, 0x48, 0x83, 0x40, - 0x87, 0x57, 0x3C, 0xD6, 0xCD, 0x2C, 0x6D, 0xE7, - 0xBB, 0xED, 0x81, 0x5D, 0x55, 0x46, 0xDD, 0xD3, - 0x70, 0xBD, 0xB8, 0x75, 0x53, 0x6E, 0xD0, 0x99, - 0xCA, 0x58, 0xC7, 0x4B, 0x3D, 0xA5, 0x50, 0x7C, - 0x93, 0x51, 0xB7, 0xFD, 0x05, 0x3A, 0xE8, 0x8F, - 0x28, 0x74, 0x39, 0xF0, 0x7F, 0x4F, 0x06, 0x36, - 0xB2, 0x19, 0x2F, 0x1F, 0x8D, 0x0C, 0xB9, 0xFC, - 0x89, 0x21, 0x12, 0xF7, 0x3F, 0x94, 0x6F, 0xDC, - 0x3E, 0x4E, 0x3B, 0xC9, 0x07, 0x9B, 0x17, 0x9A, - 0x73, 0x6A, 0x5B, 0xA1, 0x1E, 0x8A, 0x04, 0x72, - 0x6C, 0xA2, 0xEC, 0x96, 0xFE, 0xF8, 0x84, 0xC1, - 0x79, 0x0E, 0x62, 0x90, 0x8E, 0xF4, 0x42, 0x29, - 0x92, 0x9E, 0xAC, 0x82, 0x4D, 0xAF, 0x2B, 0x6B, - 0xA9, 0xFF, 0x0A, 0xAB, 0x22, 0x5F, 0xDF, 0xD2, - 0x0B, 0x78, 0xF1, 0xE6, 0x59, 0x27, 0xC2, 0xE0, - 0x1A, 0x26, 0xCC, 0xB1, 0xF9, 0xFA, 0x97, 0xE9 }; - -static const unsigned char table_166[256] = { - 0xCB, 0xEA, 0x2A, 0x36, 0x6D, 0x93, 0x4E, 0xD5, - 0xBC, 0x6A, 0xD4, 0x68, 0xF7, 0x18, 0xAB, 0x8B, - 0x66, 0x95, 0x94, 0x64, 0xB7, 0x00, 0x4D, 0x97, - 0x38, 0xB3, 0xFC, 0xE1, 0xBB, 0x63, 0xF3, 0x1F, - 0x6B, 0x2C, 0x2F, 0x5E, 0xA4, 0x7E, 0xFB, 0xF4, - 0xA8, 0x8A, 0x65, 0x53, 0x90, 0x58, 0x40, 0x60, - 0x28, 0x8E, 0x35, 0x49, 0xED, 0xBD, 0x1B, 0x0B, - 0xBA, 0xB8, 0x61, 0x50, 0xE9, 0x39, 0xEF, 0xC3, - 0x74, 0xB6, 0x46, 0x8D, 0xD9, 0x32, 0x92, 0x9A, - 0x30, 0x01, 0xF2, 0x41, 0xB9, 0xE7, 0x3A, 0xB0, - 0x80, 0x15, 0xDE, 0x7D, 0x7F, 0x09, 0xC2, 0x76, - 0xF8, 0x12, 0x59, 0xDD, 0x1D, 0xE6, 0x75, 0xBE, - 0xA3, 0x04, 0xCA, 0x78, 0x7B, 0xAC, 0xD8, 0x70, - 0xD3, 0xC1, 0x25, 0x6F, 0x03, 0x6C, 0x14, 0x45, - 0xE5, 0x2B, 0x87, 0x83, 0xAA, 0x77, 0x5F, 0x4A, - 0x9C, 0x27, 0x0C, 0x10, 0xAE, 0x56, 0x85, 0x0D, - 0xE3, 0xFA, 0x71, 0xEE, 0x9F, 0x21, 0xC0, 0xCD, - 0xFD, 0xDC, 0x5B, 0x11, 0x02, 0x0F, 0x96, 0x3D, - 0x3C, 0x26, 0xEB, 0x08, 0x7A, 0x82, 0xA7, 0x19, - 0xD7, 0xC5, 0xF6, 0x52, 0x57, 0x88, 0xFF, 0x47, - 0x8F, 0xC6, 0x33, 0xB5, 0x2E, 0x8C, 0x81, 0x91, - 0x44, 0xA6, 0x17, 0xF0, 0x4B, 0x9D, 0x34, 0x73, - 0x72, 0x67, 0xD2, 0x0E, 0xA0, 0x99, 0xA5, 0xAF, - 0xFE, 0x9E, 0x6E, 0xDA, 0x3B, 0xE2, 0x23, 0xD6, - 0xD0, 0x13, 0x89, 0x5A, 0x42, 0x98, 0x5C, 0xD1, - 0x86, 0x24, 0xDF, 0x37, 0xF9, 0xCC, 0xF5, 0xA9, - 0x2D, 0xBF, 0x5D, 0xF1, 0x69, 0xE8, 0xA2, 0x06, - 0x48, 0xC7, 0xDB, 0x29, 0xE4, 0xAD, 0x3E, 0xA1, - 0xC9, 0x4C, 0x1A, 0xCE, 0x62, 0x4F, 0x7C, 0xC8, - 0x05, 0xC4, 0xB1, 0x1E, 0x79, 0x55, 0x84, 0xB2, - 0x20, 0x31, 0x9B, 0xEC, 0xB4, 0xCF, 0x54, 0x22, - 0x1C, 0xE0, 0x51, 0x16, 0x43, 0x07, 0x0A, 0x3F }; - -static const unsigned char table_167[256] = { - 0x91, 0xEA, 0x4F, 0x6A, 0x6E, 0x2D, 0x27, 0x22, - 0x44, 0xA5, 0x6D, 0xE3, 0x45, 0x06, 0xE2, 0x87, - 0x9A, 0xC9, 0x2C, 0x4A, 0x93, 0x6F, 0x00, 0xEB, - 0x7C, 0x7F, 0xA2, 0xFE, 0x40, 0x3C, 0x3F, 0xC0, - 0xC7, 0xFB, 0x8B, 0xDF, 0xA3, 0x28, 0x78, 0x48, - 0x46, 0xD5, 0x70, 0x5C, 0x35, 0x4E, 0xD7, 0x3A, - 0x42, 0x47, 0x5B, 0x26, 0x8E, 0xE0, 0x21, 0xB1, - 0x77, 0x1E, 0x53, 0x4B, 0xCC, 0xE5, 0x65, 0xF6, - 0x66, 0x2A, 0xA0, 0x5E, 0x3E, 0xAD, 0xA8, 0x95, - 0x1B, 0x0D, 0x8A, 0x05, 0x68, 0x59, 0x0C, 0x38, - 0x18, 0xC3, 0x81, 0xA4, 0xFD, 0x13, 0x50, 0xCA, - 0xE8, 0xDD, 0xD9, 0x76, 0x8C, 0xC5, 0xF4, 0x17, - 0xB4, 0x3D, 0xEC, 0x0B, 0x67, 0xC6, 0x8D, 0xE1, - 0xBB, 0x7E, 0xCB, 0x10, 0x99, 0xE9, 0x39, 0xF3, - 0x75, 0xFA, 0xAC, 0x16, 0x54, 0x51, 0xBC, 0x24, - 0x58, 0x08, 0xA7, 0x0F, 0x5D, 0xBF, 0xBA, 0xE7, - 0x9D, 0x2B, 0xB5, 0x29, 0xE4, 0xCD, 0x37, 0x30, - 0x55, 0xAE, 0x1D, 0x4D, 0x94, 0x34, 0x92, 0x1C, - 0x6B, 0xBE, 0x52, 0x7B, 0x33, 0xB0, 0x0A, 0x5A, - 0x03, 0x23, 0x41, 0x49, 0x61, 0x64, 0x73, 0x97, - 0xC2, 0x9F, 0x5F, 0x07, 0x04, 0xF8, 0xC1, 0xFC, - 0x74, 0x02, 0x0E, 0x60, 0x9E, 0xD4, 0x85, 0x88, - 0xC4, 0xF5, 0x90, 0x31, 0xF7, 0xEE, 0x9B, 0xB9, - 0x20, 0xE6, 0xA6, 0x63, 0x79, 0x56, 0x62, 0xF0, - 0x2F, 0xD8, 0x4C, 0x83, 0xF9, 0x36, 0x3B, 0x84, - 0xDE, 0x57, 0xB8, 0xB7, 0x11, 0xF2, 0xC8, 0xD3, - 0xD1, 0x96, 0x19, 0x2E, 0x72, 0x9C, 0xDB, 0xB3, - 0xA1, 0xAA, 0xCE, 0x09, 0x98, 0xED, 0xA9, 0xDA, - 0xAF, 0x86, 0xD0, 0x12, 0xFF, 0xDC, 0x1F, 0xD6, - 0x01, 0xF1, 0xD2, 0x80, 0x43, 0x7A, 0x71, 0x82, - 0xB6, 0xAB, 0x89, 0xBD, 0x8F, 0xEF, 0x7D, 0xB2, - 0x14, 0x15, 0x25, 0x32, 0x6C, 0x69, 0x1A, 0xCF }; - -static const unsigned char table_168[256] = { - 0x28, 0xEE, 0xB1, 0xFD, 0xB3, 0xEF, 0x36, 0x8E, - 0x85, 0x5D, 0x1C, 0x53, 0x1E, 0xDA, 0xBA, 0x3C, - 0xA8, 0x90, 0x99, 0x49, 0x45, 0xE0, 0x27, 0x8D, - 0x22, 0xE4, 0x51, 0x3E, 0xAB, 0xE8, 0x70, 0xF5, - 0x81, 0xE6, 0x34, 0x29, 0xF3, 0x11, 0x46, 0x5F, - 0x5C, 0xA0, 0xD1, 0xE3, 0x15, 0x68, 0x3A, 0x01, - 0xE9, 0xD7, 0x24, 0x5A, 0x18, 0x16, 0x88, 0x3B, - 0x64, 0xA1, 0xDB, 0xBF, 0xAA, 0x43, 0xEA, 0x19, - 0xA2, 0xD5, 0x7B, 0xBD, 0x2A, 0x0E, 0x4F, 0xB5, - 0x4B, 0xB7, 0x5B, 0x73, 0xC9, 0xAC, 0x1B, 0x67, - 0xC7, 0xB4, 0x69, 0x00, 0xBC, 0x6D, 0xC1, 0x04, - 0xF4, 0x74, 0xD6, 0xD0, 0x60, 0xAE, 0x17, 0xFE, - 0x63, 0xB6, 0x89, 0x41, 0x7C, 0x44, 0x8B, 0xDC, - 0x50, 0xE5, 0x79, 0x77, 0x47, 0x9F, 0xA6, 0x3D, - 0x09, 0x8A, 0x2F, 0xC0, 0x0F, 0xCD, 0x2B, 0x4D, - 0x0D, 0xC2, 0x5E, 0xB0, 0x57, 0x62, 0xAF, 0x1A, - 0x21, 0x82, 0x48, 0x9E, 0x38, 0xB9, 0xB8, 0xF2, - 0x37, 0x07, 0xCA, 0xC5, 0x84, 0xDF, 0xF9, 0xEC, - 0x42, 0x6B, 0x8F, 0x6C, 0x3F, 0xC4, 0x94, 0xED, - 0x7A, 0x2D, 0xA3, 0x83, 0xD9, 0x55, 0x02, 0x9A, - 0xA9, 0x75, 0x10, 0x2C, 0xCB, 0x95, 0xBB, 0x6E, - 0x23, 0x65, 0x35, 0x97, 0x56, 0xAD, 0xCE, 0xF8, - 0xF0, 0x0C, 0xE2, 0x52, 0x05, 0x91, 0xCC, 0xC8, - 0x78, 0x06, 0x96, 0x4E, 0x03, 0xD3, 0x98, 0xA7, - 0x13, 0x58, 0x93, 0xD4, 0xDD, 0xC6, 0xFC, 0x25, - 0x9C, 0x86, 0x1F, 0xCF, 0x76, 0xA4, 0x6A, 0xFA, - 0x0B, 0x4A, 0x54, 0x40, 0x59, 0xD8, 0x61, 0xFF, - 0x7F, 0x80, 0x6F, 0x7D, 0xF1, 0x8C, 0x92, 0xDE, - 0x9D, 0xC3, 0xB2, 0xE7, 0xFB, 0x20, 0x31, 0x72, - 0x12, 0xBE, 0x1D, 0xF6, 0x9B, 0x14, 0x26, 0x0A, - 0xEB, 0xF7, 0x71, 0x39, 0x30, 0xA5, 0x87, 0xD2, - 0x66, 0x2E, 0x08, 0x32, 0x4C, 0x33, 0x7E, 0xE1 }; - -static const unsigned char table_169[256] = { - 0xA4, 0x31, 0xA9, 0x3F, 0x13, 0x4D, 0x1B, 0x29, - 0x73, 0x43, 0xF1, 0xE7, 0x9C, 0xC2, 0xF6, 0xCD, - 0xA1, 0x94, 0x0D, 0x27, 0xFE, 0x7B, 0x9B, 0x0B, - 0x89, 0xBA, 0x23, 0xEC, 0x76, 0xC3, 0x6C, 0xD8, - 0x8D, 0xF8, 0xF9, 0x7D, 0x68, 0x5B, 0x61, 0x87, - 0x28, 0x14, 0x55, 0x0C, 0xFC, 0xD9, 0x07, 0xE8, - 0x36, 0x88, 0x67, 0x4C, 0xEA, 0xBD, 0xF5, 0x9D, - 0xB6, 0xC6, 0x24, 0x32, 0x93, 0x03, 0x79, 0x8C, - 0x12, 0x84, 0xFF, 0x7E, 0x42, 0xE4, 0x3C, 0xF2, - 0x50, 0xEB, 0x1F, 0x47, 0xB0, 0xA5, 0xB1, 0x71, - 0x30, 0x5F, 0x5C, 0x53, 0xF7, 0x10, 0xC5, 0x6E, - 0xE0, 0xDE, 0xC8, 0x58, 0xB7, 0x90, 0xA6, 0x95, - 0x70, 0x8F, 0xFD, 0xC1, 0x48, 0xB5, 0x19, 0x92, - 0xBC, 0x15, 0x4E, 0xE6, 0x11, 0xDD, 0x81, 0x0E, - 0xBB, 0x75, 0x5D, 0x4A, 0xAB, 0x2D, 0x02, 0x54, - 0x4B, 0x66, 0xD6, 0x2B, 0x2A, 0xE5, 0x26, 0xE1, - 0xEE, 0xE9, 0x8B, 0x6A, 0x7A, 0xF4, 0x51, 0x39, - 0x1C, 0xC9, 0xCF, 0x77, 0x00, 0xF3, 0x25, 0xCC, - 0x08, 0xFB, 0x0F, 0x3E, 0xCE, 0xED, 0x3D, 0x56, - 0xEF, 0x1D, 0x85, 0x96, 0x52, 0xA8, 0xD3, 0xCB, - 0xE3, 0x33, 0x06, 0x7C, 0xAE, 0x72, 0x09, 0x04, - 0x91, 0xC4, 0x5A, 0x69, 0x98, 0xB4, 0x40, 0xDF, - 0x7F, 0x9F, 0xAA, 0x83, 0xE2, 0x78, 0x74, 0x20, - 0xAD, 0x6D, 0xDC, 0xD4, 0xCA, 0x60, 0xF0, 0x35, - 0x37, 0xD0, 0x18, 0x1A, 0x64, 0x3A, 0x99, 0xDB, - 0x62, 0x44, 0x2C, 0x82, 0x8E, 0xD7, 0xD1, 0xFA, - 0x16, 0xD5, 0x46, 0xBF, 0xA7, 0xC0, 0x2E, 0x3B, - 0x01, 0x63, 0xB2, 0x1E, 0x05, 0x21, 0xB8, 0x17, - 0x22, 0x97, 0xAF, 0x4F, 0x86, 0x34, 0xDA, 0xC7, - 0xA3, 0xA0, 0xB3, 0x2F, 0xAC, 0x49, 0xD2, 0x57, - 0x6F, 0x9A, 0x65, 0xB9, 0x41, 0xBE, 0x8A, 0xA2, - 0x6B, 0x0A, 0x59, 0x9E, 0x5E, 0x38, 0x45, 0x80 }; - -static const unsigned char table_170[256] = { - 0xE3, 0x00, 0x99, 0x03, 0xF6, 0xDD, 0xD1, 0x41, - 0x58, 0x7E, 0xD9, 0x46, 0x04, 0xAF, 0x5C, 0x43, - 0xDE, 0x5E, 0xFC, 0x97, 0x3D, 0x68, 0xC8, 0x37, - 0x3C, 0xFB, 0x0F, 0x5A, 0xBE, 0xFA, 0x4C, 0x82, - 0x0C, 0xA0, 0x0A, 0xD4, 0x9D, 0xCE, 0x78, 0xA8, - 0x55, 0x56, 0x60, 0xAA, 0xC9, 0x96, 0x62, 0xEA, - 0x0D, 0xB8, 0xE2, 0x84, 0x17, 0xAE, 0x2B, 0x2C, - 0x91, 0x57, 0x38, 0x01, 0xA9, 0xCD, 0x34, 0xBA, - 0x8D, 0xC0, 0xD6, 0xFF, 0xF2, 0xD3, 0x5F, 0x26, - 0xCA, 0x9B, 0x21, 0x75, 0x4E, 0x49, 0x20, 0x59, - 0x39, 0xBF, 0x90, 0x6C, 0xFE, 0x8F, 0x2F, 0x18, - 0x36, 0xD7, 0xB4, 0xAC, 0xBD, 0xF3, 0x1D, 0x4F, - 0xA3, 0x74, 0x5B, 0x44, 0x05, 0x9C, 0x6D, 0x6B, - 0x1E, 0xE8, 0x25, 0x16, 0x80, 0xCC, 0x29, 0xC7, - 0x94, 0x4A, 0xF5, 0xF4, 0x27, 0x85, 0xBB, 0x24, - 0xDA, 0xB5, 0x76, 0x69, 0xA5, 0x54, 0x23, 0x31, - 0x11, 0xA4, 0x09, 0xE4, 0x64, 0x10, 0xC5, 0xC1, - 0x7D, 0xE7, 0x92, 0xF8, 0x9E, 0x6A, 0x15, 0x8B, - 0x98, 0x42, 0x52, 0x66, 0x0B, 0xA1, 0x35, 0x1A, - 0x14, 0x7C, 0xE1, 0x9F, 0x28, 0xF1, 0x1B, 0xA6, - 0x71, 0x73, 0x81, 0xAB, 0xE6, 0x95, 0x06, 0x1F, - 0xC6, 0xB0, 0x51, 0x0E, 0xEE, 0x77, 0xF0, 0xD8, - 0xC2, 0x89, 0x7B, 0x07, 0xA2, 0xB7, 0x19, 0x67, - 0x2E, 0x8E, 0x47, 0xA7, 0xEF, 0x32, 0xD2, 0x93, - 0xDC, 0x9A, 0xB2, 0xED, 0x45, 0xC4, 0x50, 0x3F, - 0xE5, 0xCF, 0x88, 0x1C, 0x7A, 0x79, 0xEB, 0x70, - 0x2A, 0x7F, 0xBC, 0xDB, 0xD0, 0xB1, 0xCB, 0x08, - 0x86, 0x5D, 0x53, 0x72, 0xB6, 0x4B, 0xB3, 0x22, - 0xC3, 0x6F, 0xB9, 0xD5, 0x3B, 0x13, 0x2D, 0xAD, - 0x33, 0xFD, 0x02, 0x40, 0x8A, 0x3A, 0xF7, 0xE0, - 0x8C, 0x3E, 0x61, 0x6E, 0xE9, 0x63, 0xF9, 0xEC, - 0x48, 0x30, 0x87, 0x83, 0x12, 0x4D, 0x65, 0xDF }; - -static const unsigned char table_171[32] = { - 0x07, 0x06, 0x11, 0x08, 0x0C, 0x1F, 0x19, 0x02, - 0x14, 0x04, 0x0D, 0x18, 0x1A, 0x05, 0x17, 0x13, - 0x1C, 0x1B, 0x15, 0x03, 0x01, 0x0F, 0x16, 0x1E, - 0x1D, 0x10, 0x00, 0x12, 0x0B, 0x0E, 0x09, 0x0A }; - -static const unsigned char table_172[32] = { - 0x11, 0x01, 0x1F, 0x06, 0x1A, 0x04, 0x02, 0x09, - 0x05, 0x0D, 0x0B, 0x18, 0x0E, 0x12, 0x1B, 0x17, - 0x07, 0x08, 0x1D, 0x1E, 0x14, 0x19, 0x16, 0x15, - 0x03, 0x0C, 0x00, 0x10, 0x0A, 0x1C, 0x0F, 0x13 }; - -static const unsigned char table_173[32] = { - 0x1F, 0x0B, 0x13, 0x00, 0x16, 0x15, 0x14, 0x0A, - 0x1D, 0x05, 0x1E, 0x1A, 0x0F, 0x04, 0x0E, 0x01, - 0x19, 0x07, 0x02, 0x12, 0x0C, 0x17, 0x08, 0x09, - 0x03, 0x11, 0x18, 0x10, 0x1C, 0x1B, 0x06, 0x0D }; - -static const unsigned char table_174[32] = { - 0x02, 0x1B, 0x0C, 0x17, 0x1F, 0x05, 0x15, 0x1E, - 0x16, 0x09, 0x1A, 0x12, 0x0F, 0x1C, 0x18, 0x0A, - 0x19, 0x10, 0x0D, 0x13, 0x04, 0x11, 0x08, 0x14, - 0x1D, 0x0E, 0x06, 0x00, 0x01, 0x07, 0x0B, 0x03 }; - -static const unsigned char table_175[32] = { - 0x00, 0x06, 0x0B, 0x08, 0x0C, 0x04, 0x1A, 0x1C, - 0x05, 0x1E, 0x14, 0x03, 0x0A, 0x18, 0x12, 0x1D, - 0x16, 0x1F, 0x07, 0x09, 0x0F, 0x0E, 0x17, 0x13, - 0x11, 0x19, 0x10, 0x0D, 0x1B, 0x02, 0x01, 0x15 }; - -static const unsigned char table_176[32] = { - 0x12, 0x03, 0x1A, 0x15, 0x04, 0x19, 0x0B, 0x1B, - 0x17, 0x1E, 0x0D, 0x05, 0x11, 0x14, 0x1C, 0x00, - 0x18, 0x10, 0x0A, 0x06, 0x0E, 0x08, 0x02, 0x07, - 0x13, 0x09, 0x16, 0x1D, 0x0F, 0x0C, 0x01, 0x1F }; - -static const unsigned char table_177[256] = { - 0x5E, 0x4D, 0x76, 0xFE, 0xB5, 0x50, 0x83, 0x23, - 0x72, 0xDD, 0x93, 0x08, 0x69, 0xAD, 0xEC, 0x3B, - 0x0B, 0x9A, 0x36, 0xC9, 0xCA, 0xBE, 0xF7, 0x30, - 0x19, 0x39, 0x2C, 0xAB, 0xE3, 0x7B, 0xBC, 0x32, - 0xA0, 0xE4, 0xA6, 0xB6, 0xCB, 0xC8, 0x37, 0x07, - 0xD2, 0xA1, 0xD9, 0xF6, 0xBF, 0xF5, 0x88, 0x01, - 0x95, 0x0F, 0x03, 0xFD, 0xE6, 0x68, 0x90, 0x61, - 0x21, 0x6D, 0x3C, 0x62, 0x34, 0x2B, 0x71, 0x4B, - 0x44, 0x64, 0x75, 0xA2, 0x6A, 0xFF, 0x29, 0xBD, - 0x35, 0x15, 0xF9, 0xC1, 0x09, 0x45, 0xB2, 0xF2, - 0x3F, 0xCE, 0xB0, 0xC0, 0xB8, 0x00, 0x05, 0xD7, - 0x11, 0xC6, 0x78, 0x53, 0x9E, 0xB3, 0xED, 0x56, - 0x22, 0x5C, 0x9D, 0x6C, 0x99, 0x43, 0x2F, 0xAE, - 0xEB, 0x40, 0x8C, 0x1F, 0xC2, 0xDF, 0x92, 0x65, - 0x6F, 0x79, 0x5D, 0x5B, 0xAA, 0xDB, 0xF1, 0x96, - 0xD4, 0xF4, 0x8B, 0x51, 0xD5, 0xE2, 0xBB, 0x80, - 0x17, 0x7C, 0x2A, 0x6E, 0xDE, 0xEA, 0x94, 0x31, - 0xA4, 0x2D, 0xC3, 0x8D, 0x55, 0x14, 0x9B, 0x0E, - 0x7D, 0xC4, 0x06, 0x33, 0x73, 0xE9, 0x7A, 0x38, - 0x5F, 0x89, 0x84, 0xD6, 0xA8, 0x13, 0xE8, 0xCF, - 0x46, 0xD0, 0x7F, 0x24, 0x8F, 0xF8, 0x87, 0x1B, - 0x47, 0x02, 0x0C, 0x97, 0x52, 0xFB, 0x8E, 0x20, - 0x70, 0x3E, 0x7E, 0xD1, 0xE5, 0xEE, 0xCC, 0x91, - 0x74, 0xCD, 0x42, 0x04, 0x8A, 0xEF, 0xE1, 0x10, - 0x4F, 0x1C, 0x28, 0x9F, 0xD8, 0x0A, 0x18, 0x49, - 0x9C, 0x16, 0xF3, 0x82, 0x57, 0x1D, 0x26, 0x66, - 0x27, 0x86, 0xE7, 0x59, 0xFA, 0x25, 0x54, 0x0D, - 0x98, 0xDC, 0xF0, 0x3D, 0x63, 0x1E, 0x77, 0x3A, - 0xDA, 0xB7, 0x6B, 0x2E, 0x48, 0x4C, 0xBA, 0xC7, - 0x60, 0xAC, 0x1A, 0xB9, 0xFC, 0xA3, 0xA7, 0xA5, - 0xB4, 0x67, 0xA9, 0x81, 0xB1, 0x12, 0xD3, 0x85, - 0x5A, 0xC5, 0xE0, 0x58, 0x41, 0x4E, 0x4A, 0xAF }; - -static const unsigned char table_178[256] = { - 0x33, 0xBA, 0x98, 0xDA, 0x07, 0x2C, 0x22, 0x9B, - 0xE0, 0xED, 0xB7, 0xA1, 0x93, 0xEB, 0xDC, 0x49, - 0xDF, 0xE1, 0x6C, 0xC2, 0x64, 0x52, 0xD0, 0x8F, - 0xA2, 0x48, 0x26, 0x21, 0x6E, 0x5E, 0x0B, 0x7C, - 0x0D, 0x90, 0xA4, 0xCE, 0xF5, 0x5F, 0xF9, 0x1D, - 0x55, 0x83, 0x8D, 0xFB, 0x38, 0xB3, 0xF2, 0x67, - 0xDE, 0x0A, 0xBE, 0xEC, 0x5B, 0x35, 0x08, 0x50, - 0xE7, 0x56, 0x4A, 0x02, 0xBC, 0x5A, 0xBD, 0x43, - 0x6F, 0x79, 0xB2, 0xF7, 0x60, 0xE9, 0xA0, 0x1B, - 0xC8, 0xDD, 0x9D, 0xA3, 0x5C, 0x61, 0x77, 0x72, - 0x9C, 0x31, 0x0E, 0x05, 0x1E, 0x12, 0xF1, 0xC9, - 0x78, 0x4E, 0x15, 0x7D, 0x54, 0xCB, 0x73, 0xEA, - 0xC5, 0x2B, 0x0F, 0x7E, 0x42, 0x96, 0xC6, 0x74, - 0x09, 0x65, 0x34, 0xE6, 0x63, 0xA6, 0x70, 0xD3, - 0x27, 0x87, 0x3A, 0x16, 0x7B, 0x13, 0x06, 0x40, - 0x46, 0x69, 0xAD, 0x88, 0x81, 0xC0, 0x37, 0x58, - 0xD1, 0x8A, 0x8E, 0x9A, 0x5D, 0x6D, 0xC7, 0xC3, - 0xD2, 0xF4, 0x3F, 0x57, 0x3C, 0x4F, 0xA9, 0x6A, - 0x92, 0xA5, 0x97, 0x0C, 0x2A, 0x36, 0x47, 0xDB, - 0x8C, 0xEE, 0x03, 0x89, 0x7F, 0x91, 0x24, 0x80, - 0x2F, 0x62, 0xE4, 0xAF, 0x17, 0x99, 0xD6, 0xCD, - 0xFE, 0x76, 0x1C, 0xD4, 0x3E, 0xFF, 0xD8, 0xC4, - 0x39, 0x32, 0xCF, 0xE2, 0xE3, 0x53, 0xD7, 0xCC, - 0xD9, 0x11, 0xAA, 0x1F, 0x01, 0x3B, 0x51, 0xB5, - 0x94, 0x4B, 0x28, 0xF0, 0xAC, 0x44, 0x14, 0x4C, - 0xB9, 0xA7, 0xB8, 0x1A, 0xD5, 0xCA, 0xE8, 0x82, - 0x9F, 0x2D, 0xAB, 0x2E, 0x29, 0xFD, 0x68, 0xB1, - 0x66, 0xC1, 0x7A, 0xFA, 0x71, 0x04, 0xA8, 0xB0, - 0x59, 0x18, 0xAE, 0x25, 0x3D, 0xE5, 0xF6, 0x41, - 0x86, 0x75, 0x6B, 0xBB, 0xFC, 0x84, 0x8B, 0x85, - 0x10, 0x23, 0xB6, 0xF3, 0x19, 0x30, 0x20, 0x4D, - 0x95, 0x9E, 0xBF, 0xEF, 0xF8, 0x45, 0x00, 0xB4 }; - -static const unsigned char table_179[256] = { - 0x50, 0x3D, 0x41, 0x42, 0x06, 0x5B, 0xD6, 0x34, - 0x9D, 0x3C, 0x7B, 0x14, 0xE2, 0x9B, 0x80, 0x15, - 0x51, 0x01, 0x6A, 0x30, 0xD7, 0xFC, 0x61, 0x4B, - 0x8A, 0xEC, 0x38, 0x71, 0x70, 0x2E, 0x1C, 0x72, - 0x79, 0x26, 0x4C, 0x48, 0xED, 0xAD, 0x25, 0x53, - 0x03, 0xD9, 0xB5, 0x0D, 0x8E, 0x19, 0xCC, 0xBE, - 0xE1, 0x91, 0x64, 0xA6, 0x21, 0xCE, 0x76, 0xAB, - 0x9F, 0xD1, 0xB6, 0x23, 0x6D, 0xB0, 0x90, 0xBD, - 0x09, 0x3A, 0x5E, 0xD0, 0x73, 0x10, 0x44, 0x08, - 0xFF, 0xB8, 0x24, 0x58, 0xDB, 0x65, 0x95, 0xAA, - 0xE9, 0xC4, 0x32, 0x2B, 0x84, 0xC9, 0xC7, 0xB1, - 0x4F, 0x0C, 0xCB, 0x11, 0x4E, 0x22, 0x4A, 0x16, - 0xDE, 0xBC, 0xEE, 0x68, 0x13, 0xFA, 0xC3, 0x98, - 0xEB, 0x29, 0x43, 0x9A, 0xA1, 0xE0, 0xF0, 0x3F, - 0x2F, 0x1B, 0xC2, 0x66, 0x35, 0xF5, 0xC8, 0xD8, - 0x5A, 0xE5, 0x87, 0x47, 0xD3, 0x7A, 0xE6, 0x39, - 0x77, 0x81, 0xF2, 0x0E, 0x83, 0x7E, 0x17, 0x6C, - 0xB3, 0x5C, 0xE8, 0xD2, 0xC0, 0xA4, 0xF9, 0x86, - 0xCD, 0xFB, 0x54, 0x7C, 0xBF, 0x2D, 0x82, 0xDA, - 0x96, 0x74, 0x97, 0xC5, 0x7D, 0x27, 0x57, 0x56, - 0xDC, 0xBA, 0x69, 0x8C, 0x9C, 0x88, 0xB4, 0x8D, - 0x37, 0xEA, 0x3B, 0x33, 0x2C, 0xB2, 0x45, 0xF7, - 0xC1, 0x1E, 0x46, 0x02, 0x6B, 0x3E, 0xA7, 0xD5, - 0x05, 0x0A, 0xA9, 0x1D, 0xA3, 0x4D, 0xAE, 0x6F, - 0x49, 0xDD, 0x8F, 0xEF, 0xBB, 0x67, 0x0B, 0x40, - 0x9E, 0xF1, 0x78, 0x28, 0xDF, 0x52, 0xF4, 0x92, - 0x94, 0x0F, 0xB9, 0x93, 0xF6, 0x1F, 0xAF, 0xA8, - 0xCA, 0xE4, 0x59, 0x7F, 0x85, 0x75, 0xC6, 0xFD, - 0x00, 0xB7, 0x55, 0xFE, 0x8B, 0x62, 0x5F, 0x12, - 0xF8, 0xD4, 0x89, 0xA0, 0x20, 0xE7, 0xCF, 0x60, - 0x5D, 0xAC, 0x1A, 0x36, 0x63, 0x99, 0x31, 0xF3, - 0x2A, 0x04, 0x18, 0xA5, 0xA2, 0x6E, 0x07, 0xE3 }; - -static const unsigned char table_180[256] = { - 0xDA, 0xCC, 0x72, 0xA6, 0xE7, 0x07, 0xFD, 0x25, - 0x92, 0x39, 0x49, 0x02, 0xD6, 0x09, 0xA8, 0x65, - 0x2E, 0x6C, 0xA1, 0x19, 0xBF, 0x21, 0x11, 0xC7, - 0x3F, 0x9F, 0xF4, 0x51, 0xAF, 0x8C, 0xFE, 0xCD, - 0x7A, 0xEB, 0x5A, 0xF7, 0x18, 0x69, 0xB9, 0xED, - 0x37, 0x45, 0x13, 0xB4, 0xAA, 0x75, 0x47, 0x42, - 0xA3, 0x81, 0x88, 0x70, 0xC1, 0x36, 0x73, 0x1D, - 0x3B, 0x22, 0xB6, 0x35, 0xE9, 0x31, 0x56, 0x23, - 0xE1, 0xF5, 0xAD, 0x46, 0x99, 0x32, 0xE4, 0x40, - 0x00, 0x0F, 0x05, 0xC6, 0x33, 0x84, 0x7B, 0x4D, - 0x4B, 0x7D, 0x91, 0x3D, 0xCE, 0x64, 0x77, 0x55, - 0xD7, 0x2B, 0x2F, 0x2C, 0xB8, 0xD3, 0x85, 0xD1, - 0xB5, 0x6A, 0xF9, 0x41, 0x08, 0xBB, 0x87, 0xEC, - 0x78, 0xE0, 0xEE, 0x8D, 0x01, 0x58, 0x15, 0x8F, - 0x06, 0xF0, 0x8B, 0x27, 0x0D, 0x0B, 0x6D, 0xBD, - 0xCA, 0x2A, 0xA2, 0xE6, 0xDD, 0xBC, 0x4E, 0x5D, - 0x74, 0x04, 0x3A, 0x96, 0x66, 0x12, 0x1E, 0xF2, - 0xF6, 0xC4, 0xAE, 0x3C, 0x0C, 0x90, 0x68, 0xD8, - 0x24, 0x5E, 0x79, 0x10, 0xAC, 0xDF, 0x9B, 0xC5, - 0x44, 0xC3, 0x50, 0x5C, 0xA5, 0x89, 0x60, 0x5F, - 0x48, 0x17, 0x34, 0xA7, 0xE2, 0xF3, 0xD9, 0x3E, - 0x9C, 0xB7, 0x7C, 0x1F, 0xA9, 0xD4, 0xA4, 0x0E, - 0x8E, 0x4C, 0xDC, 0xF8, 0xF1, 0x98, 0xDE, 0x2D, - 0x61, 0xCB, 0xD5, 0x43, 0x86, 0x26, 0xB0, 0x7F, - 0x7E, 0xFF, 0xAB, 0x83, 0x14, 0x9A, 0x80, 0x16, - 0x30, 0xA0, 0x53, 0x97, 0x52, 0x9E, 0xB1, 0x1B, - 0xD0, 0x1A, 0xC8, 0x57, 0xBA, 0x6E, 0xFA, 0x94, - 0xE8, 0x63, 0x5B, 0x29, 0xEF, 0x71, 0x8A, 0x03, - 0xB3, 0x76, 0xC9, 0xD2, 0xBE, 0xE5, 0x82, 0x1C, - 0x95, 0x9D, 0x4A, 0x28, 0xEA, 0x0A, 0xC0, 0xE3, - 0x6F, 0x20, 0x54, 0xFB, 0x93, 0xFC, 0x6B, 0x38, - 0x62, 0x4F, 0xCF, 0xB2, 0xC2, 0x59, 0xDB, 0x67 }; - -static const unsigned char table_181[256] = { - 0x2B, 0xED, 0x14, 0x05, 0x80, 0xCC, 0x5A, 0xF8, - 0x43, 0xB7, 0x86, 0xC6, 0xEE, 0xA6, 0xD7, 0xD6, - 0xA0, 0xC4, 0x21, 0x34, 0xB1, 0x8C, 0xF9, 0xF4, - 0x7C, 0x53, 0x06, 0xD4, 0x6B, 0x3F, 0xE1, 0x12, - 0x6A, 0xCE, 0xCF, 0xBF, 0x74, 0x3E, 0xD5, 0xCB, - 0x97, 0x01, 0xA2, 0x2D, 0xAE, 0xF7, 0x17, 0x29, - 0x47, 0x03, 0x0E, 0xE9, 0x82, 0x46, 0x94, 0xAF, - 0x2A, 0x90, 0xFE, 0x4A, 0x7E, 0x0C, 0x71, 0xB6, - 0xA5, 0xF2, 0x67, 0x41, 0xBA, 0xC2, 0x8A, 0x9D, - 0x36, 0xFF, 0x50, 0x2E, 0xC3, 0x91, 0x9C, 0x37, - 0x66, 0xAD, 0xB2, 0x1F, 0xE4, 0xE3, 0x9F, 0xDD, - 0x87, 0xC0, 0xE6, 0xEF, 0x13, 0x70, 0x5B, 0xDE, - 0x5C, 0x75, 0x7F, 0x4F, 0x44, 0xCA, 0x55, 0x57, - 0xF0, 0x26, 0xA7, 0xC7, 0x10, 0x51, 0x00, 0xB3, - 0x5D, 0x99, 0x81, 0x3B, 0xB9, 0x1C, 0x64, 0x7B, - 0xFB, 0xD9, 0x8D, 0x4E, 0xAC, 0x25, 0xBB, 0x69, - 0xDF, 0x02, 0x9E, 0x2C, 0xAB, 0xF3, 0x65, 0x09, - 0xA3, 0x6C, 0xC1, 0x76, 0x52, 0x30, 0xD8, 0x3A, - 0x40, 0x18, 0x59, 0xD0, 0xE5, 0xB4, 0x5F, 0x33, - 0x68, 0x92, 0x2F, 0xB8, 0x93, 0xD1, 0xEB, 0xA4, - 0xFC, 0x77, 0x19, 0x62, 0xC9, 0x49, 0x84, 0x1A, - 0x9A, 0xE7, 0x31, 0xE8, 0xE2, 0x58, 0xF1, 0x4B, - 0x1E, 0x0B, 0x39, 0xFD, 0x42, 0x7A, 0x89, 0x38, - 0x11, 0x98, 0x63, 0x08, 0xE0, 0xEA, 0xBE, 0xB0, - 0x45, 0x1B, 0x4C, 0x54, 0xC8, 0x27, 0x3D, 0x73, - 0x04, 0x8F, 0x79, 0xBC, 0x6F, 0x0D, 0x0F, 0xA1, - 0x60, 0xDC, 0xC5, 0xFA, 0x8E, 0xDA, 0x15, 0x96, - 0xD3, 0x07, 0xF5, 0x3C, 0x88, 0x72, 0x1D, 0x4D, - 0x8B, 0x61, 0x0A, 0xDB, 0xAA, 0x20, 0x23, 0xEC, - 0x6E, 0x22, 0x48, 0x28, 0xBD, 0xA9, 0x56, 0x5E, - 0x85, 0xA8, 0x95, 0x6D, 0x16, 0x78, 0xB5, 0xF6, - 0x32, 0x24, 0x7D, 0x9B, 0xD2, 0x83, 0x35, 0xCD }; - -static const unsigned char table_182[256] = { - 0x06, 0x7F, 0x66, 0xB5, 0xBA, 0x1E, 0xFD, 0x51, - 0x81, 0x8D, 0x28, 0xA3, 0x15, 0x37, 0xDC, 0x58, - 0xE6, 0x3D, 0xB4, 0xB9, 0x2E, 0xA0, 0x2F, 0xC4, - 0xCB, 0xB1, 0x25, 0xBF, 0xC1, 0x4E, 0x5A, 0xE4, - 0x0F, 0x10, 0x7C, 0x52, 0xA7, 0x29, 0x76, 0x55, - 0xAA, 0x70, 0x62, 0x54, 0x43, 0x93, 0x3A, 0x7D, - 0x5B, 0x56, 0x33, 0x64, 0x74, 0x2A, 0xD9, 0x9B, - 0x88, 0xC0, 0x3C, 0x63, 0xDE, 0xF4, 0x73, 0xDF, - 0x9E, 0xB2, 0xA8, 0x4F, 0x04, 0x57, 0x47, 0x87, - 0x14, 0xFC, 0x27, 0x53, 0x83, 0xDB, 0xD7, 0x20, - 0x96, 0x31, 0xD0, 0xCF, 0x30, 0x19, 0x69, 0x1A, - 0xAE, 0x3B, 0x11, 0x0C, 0xA6, 0x95, 0x8A, 0xF2, - 0x1B, 0xCC, 0x78, 0xEF, 0xB3, 0x71, 0x84, 0xA2, - 0xF1, 0x7A, 0x92, 0x61, 0xCA, 0x90, 0x94, 0x89, - 0x68, 0xEE, 0x97, 0x38, 0x0D, 0xF9, 0x1F, 0x8E, - 0xE9, 0x26, 0xBD, 0xC9, 0xFF, 0x4C, 0x44, 0x1D, - 0x98, 0xE5, 0x86, 0xF3, 0x18, 0xB6, 0x09, 0xD2, - 0x7E, 0xC5, 0xE7, 0x2B, 0x8C, 0x8B, 0x60, 0x3F, - 0x2C, 0x6A, 0x08, 0x0E, 0x50, 0x32, 0x9F, 0xF0, - 0x9A, 0xC2, 0x39, 0xBE, 0xEA, 0x12, 0x16, 0xBB, - 0x5E, 0x67, 0xE3, 0xB8, 0x79, 0x46, 0xDA, 0x00, - 0xD3, 0xBC, 0xCE, 0x1C, 0x80, 0xFA, 0xAB, 0x65, - 0x4A, 0xF8, 0xAC, 0x72, 0x01, 0xC6, 0x35, 0x85, - 0x3E, 0x5C, 0xA1, 0x05, 0xA5, 0xA9, 0xE1, 0x40, - 0xEB, 0xE8, 0x5F, 0xF5, 0xC3, 0xD1, 0x34, 0xFB, - 0xEC, 0xF7, 0x9C, 0xC7, 0xDD, 0x6C, 0x36, 0x9D, - 0x42, 0x59, 0x99, 0x5D, 0xD8, 0x82, 0x07, 0x24, - 0x6D, 0xAD, 0x13, 0x48, 0x6B, 0x6E, 0x75, 0x4D, - 0xD5, 0x02, 0xED, 0xFE, 0x91, 0xCD, 0x77, 0xB0, - 0xF6, 0xC8, 0x6F, 0x23, 0xAF, 0xB7, 0x2D, 0xD6, - 0xA4, 0xE2, 0x45, 0x8F, 0x21, 0xE0, 0x49, 0x22, - 0x7B, 0x17, 0x0B, 0x0A, 0x41, 0x03, 0xD4, 0x4B }; - -static const unsigned char table_183[32] = { - 0x1E, 0x1B, 0x11, 0x07, 0x08, 0x06, 0x18, 0x17, - 0x0D, 0x0F, 0x12, 0x03, 0x1D, 0x04, 0x0A, 0x1A, - 0x0C, 0x13, 0x14, 0x1F, 0x0B, 0x19, 0x10, 0x01, - 0x16, 0x05, 0x1C, 0x0E, 0x02, 0x00, 0x09, 0x15 }; - -static const unsigned char table_184[32] = { - 0x0F, 0x1D, 0x17, 0x16, 0x0D, 0x05, 0x13, 0x1F, - 0x1B, 0x09, 0x1C, 0x1E, 0x15, 0x01, 0x06, 0x08, - 0x0C, 0x10, 0x0B, 0x02, 0x04, 0x0A, 0x07, 0x1A, - 0x18, 0x0E, 0x03, 0x11, 0x12, 0x14, 0x19, 0x00 }; - -static const unsigned char table_185[256] = { - 0xA5, 0xEE, 0x2E, 0x28, 0xA7, 0xAC, 0xD9, 0xB2, - 0x6E, 0x04, 0xB4, 0x03, 0xE8, 0x92, 0x5F, 0x4D, - 0x73, 0x20, 0x71, 0xE0, 0x43, 0x53, 0x3F, 0xF8, - 0x96, 0xA1, 0x24, 0x97, 0xAD, 0x7B, 0xE5, 0xE6, - 0xF2, 0xCE, 0xE3, 0x76, 0x2F, 0xA2, 0x48, 0x0E, - 0x4B, 0x4A, 0x8B, 0x5A, 0x81, 0x2C, 0xBF, 0xD7, - 0xFB, 0x7D, 0x4C, 0x16, 0xF4, 0x00, 0xF5, 0x40, - 0x64, 0x74, 0xA9, 0x37, 0x86, 0xD3, 0x1B, 0xCD, - 0xF1, 0x1A, 0x90, 0x9F, 0x54, 0x79, 0x29, 0xC3, - 0x77, 0x85, 0x02, 0xB1, 0x70, 0xFE, 0x5B, 0xDA, - 0x6B, 0x01, 0x0C, 0x07, 0xB8, 0x58, 0x47, 0x42, - 0x09, 0xE4, 0x27, 0xDD, 0xF3, 0x1E, 0x10, 0x9E, - 0x49, 0x30, 0x05, 0xBE, 0x59, 0xEB, 0xD2, 0xAA, - 0xC8, 0x9D, 0x8C, 0x5E, 0x14, 0x56, 0x8E, 0xF7, - 0x38, 0x55, 0x87, 0xA3, 0x5D, 0x41, 0x4F, 0x1F, - 0xF6, 0x0F, 0x57, 0x91, 0xAE, 0xBA, 0xB3, 0x95, - 0x9B, 0x69, 0xC1, 0x11, 0xD0, 0x25, 0x7F, 0x3B, - 0x62, 0xCF, 0xC0, 0xA0, 0xFC, 0xB6, 0x12, 0x6C, - 0xF0, 0x13, 0x93, 0xAB, 0xC6, 0x78, 0x6D, 0x88, - 0x22, 0x08, 0x2A, 0xE2, 0xB7, 0x65, 0x31, 0x3A, - 0xA6, 0x7C, 0xF9, 0xDC, 0xE7, 0xA4, 0xC9, 0x63, - 0xA8, 0x0B, 0xED, 0x50, 0x36, 0xD8, 0x3E, 0xB0, - 0x6A, 0x5C, 0x45, 0x4E, 0x23, 0x84, 0x34, 0x9A, - 0xCC, 0x3D, 0xB5, 0xEA, 0xDE, 0x75, 0xD6, 0xFF, - 0x6F, 0xC2, 0xDB, 0x8D, 0x7A, 0x1C, 0xE9, 0x61, - 0x0A, 0x1D, 0x32, 0x52, 0x3C, 0x19, 0xFA, 0xD1, - 0xD4, 0x68, 0xC7, 0x0D, 0x99, 0x83, 0xEF, 0x80, - 0x82, 0xBD, 0xD5, 0x7E, 0x39, 0x72, 0x51, 0xAF, - 0x8A, 0x2D, 0xB9, 0x89, 0xC4, 0x67, 0x35, 0xE1, - 0x44, 0x06, 0xEC, 0xCB, 0x8F, 0x17, 0xDF, 0x94, - 0x60, 0xCA, 0x26, 0xFD, 0x33, 0x46, 0x21, 0xBB, - 0x2B, 0xC5, 0x98, 0x18, 0x66, 0x15, 0x9C, 0xBC }; - -static const unsigned char table_186[256] = { - 0xB7, 0xFA, 0x03, 0x7C, 0x76, 0x43, 0xA7, 0x15, - 0x4B, 0x4F, 0x04, 0xAA, 0x4E, 0xD2, 0x52, 0xC8, - 0x79, 0x16, 0xF6, 0x61, 0x01, 0x5D, 0xD6, 0x47, - 0xDE, 0xC5, 0x4D, 0x2F, 0xF5, 0x29, 0x21, 0xE6, - 0x97, 0x35, 0xDC, 0x0E, 0x8B, 0xF4, 0x0F, 0xBE, - 0x30, 0x07, 0x1D, 0x46, 0x75, 0xCE, 0x56, 0x42, - 0x28, 0x93, 0x84, 0x20, 0xA5, 0xC2, 0x87, 0x45, - 0x1C, 0x6B, 0x55, 0x06, 0xEB, 0xB0, 0xF9, 0x14, - 0x23, 0xF1, 0xFC, 0xD7, 0x98, 0xD1, 0xA4, 0xED, - 0x5B, 0xB1, 0x12, 0x7A, 0xD5, 0x5F, 0x53, 0x88, - 0x95, 0x71, 0xE7, 0x5C, 0xF8, 0x83, 0xC7, 0x49, - 0xDD, 0xDA, 0x0B, 0xC1, 0x70, 0xEC, 0x67, 0xE2, - 0xEA, 0x72, 0x4C, 0x92, 0xA6, 0xE5, 0x59, 0xA9, - 0x3C, 0xFE, 0x0A, 0x65, 0x6E, 0xF3, 0xA3, 0x22, - 0x24, 0x81, 0xF2, 0xCC, 0xD3, 0xA0, 0xDF, 0xDB, - 0xAB, 0x09, 0x13, 0x96, 0x36, 0x9C, 0xEE, 0xD4, - 0x33, 0x5E, 0x26, 0xAE, 0x48, 0x38, 0xFF, 0x08, - 0x1F, 0x6D, 0x02, 0xEF, 0x7E, 0x57, 0x2A, 0x8A, - 0xBA, 0x90, 0xAF, 0xA8, 0x37, 0x8E, 0x9B, 0xC0, - 0x69, 0x32, 0x86, 0xBD, 0x73, 0x6C, 0xB9, 0x31, - 0x66, 0xBF, 0x1B, 0x44, 0x9E, 0xB2, 0xD0, 0xE0, - 0xF0, 0x2C, 0x3F, 0xE1, 0x91, 0x18, 0x19, 0x50, - 0xCA, 0x8F, 0x54, 0xB5, 0x8D, 0x0C, 0x17, 0x39, - 0x8C, 0x00, 0x7F, 0x41, 0xE3, 0x2E, 0x1A, 0x9D, - 0x27, 0xA1, 0x10, 0x34, 0x1E, 0x3A, 0x60, 0x77, - 0xBB, 0xB6, 0x0D, 0x4A, 0x3E, 0x6A, 0xB4, 0xA2, - 0xB3, 0xFD, 0xCD, 0x80, 0x51, 0xAD, 0xCF, 0xBC, - 0x40, 0x74, 0x6F, 0x68, 0x2B, 0xC3, 0xF7, 0x63, - 0xB8, 0x25, 0xC4, 0x62, 0xE9, 0xFB, 0x58, 0x85, - 0x78, 0xCB, 0x9A, 0x3D, 0xE4, 0xC9, 0x89, 0x2D, - 0x64, 0x82, 0xC6, 0x05, 0xD8, 0xAC, 0x99, 0x9F, - 0x11, 0x3B, 0x94, 0xE8, 0x7D, 0x7B, 0xD9, 0x5A }; - -static const unsigned char table_187[32] = { - 0x0F, 0x04, 0x1D, 0x1B, 0x15, 0x10, 0x01, 0x0B, - 0x00, 0x17, 0x13, 0x07, 0x1E, 0x1F, 0x08, 0x0A, - 0x19, 0x09, 0x05, 0x06, 0x0C, 0x1A, 0x14, 0x16, - 0x0E, 0x18, 0x03, 0x1C, 0x12, 0x11, 0x0D, 0x02 }; - -static const struct yahoo_fn yahoo_fntable[5][96] = - {{{ IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }, - { IDENT, 0, 0 }}, - {{ MULADD, 0x36056CD7, 0x4387 }, - { LOOKUP, (long)table_0, 0 }, - { LOOKUP, (long)table_1, 0 }, - { BITFLD, (long)table_2, 0 }, - { LOOKUP, (long)table_3, 0 }, - { BITFLD, (long)table_4, 0 }, - { MULADD, 0x4ABB534D, 0x3769 }, - { XOR, 0x1D242DA5, 0 }, - { MULADD, 0x3C23132D, 0x339B }, - { XOR, 0x0191265C, 0 }, - { XOR, 0x3DB979DB, 0 }, - { LOOKUP, (long)table_5, 0 }, - { XOR, 0x1A550E1E, 0 }, - { XOR, 0x2F140A2D, 0 }, - { MULADD, 0x7C466A4B, 0x29BF }, - { XOR, 0x2D3F30D3, 0 }, - { MULADD, 0x7E823B21, 0x6BB3 }, - { BITFLD, (long)table_6, 0 }, - { LOOKUP, (long)table_7, 0 }, - { BITFLD, (long)table_8, 0 }, - { LOOKUP, (long)table_9, 0 }, - { BITFLD, (long)table_10, 0 }, - { LOOKUP, (long)table_11, 0 }, - { BITFLD, (long)table_12, 0 }, - { LOOKUP, (long)table_13, 0 }, - { BITFLD, (long)table_14, 0 }, - { MULADD, 0x5B756AB9, 0x7E9B }, - { LOOKUP, (long)table_15, 0 }, - { XOR, 0x1D1C4911, 0 }, - { LOOKUP, (long)table_16, 0 }, - { LOOKUP, (long)table_17, 0 }, - { XOR, 0x46BD7771, 0 }, - { XOR, 0x51AE2B42, 0 }, - { MULADD, 0x2417591B, 0x177B }, - { MULADD, 0x57F27C5F, 0x2433 }, - { LOOKUP, (long)table_18, 0 }, - { LOOKUP, (long)table_19, 0 }, - { XOR, 0x71422261, 0 }, - { BITFLD, (long)table_20, 0 }, - { MULADD, 0x58E937F9, 0x1075 }, - { LOOKUP, (long)table_21, 0 }, - { BITFLD, (long)table_22, 0 }, - { LOOKUP, (long)table_23, 0 }, - { LOOKUP, (long)table_24, 0 }, - { MULADD, 0x0B4C3D13, 0x1597 }, - { BITFLD, (long)table_25, 0 }, - { XOR, 0x0FE07D38, 0 }, - { MULADD, 0x689B4017, 0x3CFB }, - { BITFLD, (long)table_26, 0 }, - { LOOKUP, (long)table_27, 0 }, - { XOR, 0x35413DF3, 0 }, - { MULADD, 0x05B611AB, 0x570B }, - { MULADD, 0x0DA5334F, 0x3AC7 }, - { XOR, 0x47706008, 0 }, - { BITFLD, (long)table_28, 0 }, - { LOOKUP, (long)table_29, 0 }, - { BITFLD, (long)table_30, 0 }, - { XOR, 0x57611B36, 0 }, - { MULADD, 0x314C2CD1, 0x2B5B }, - { XOR, 0x1EF33946, 0 }, - { MULADD, 0x28EA041F, 0x638F }, - { LOOKUP, (long)table_31, 0 }, - { LOOKUP, (long)table_32, 0 }, - { LOOKUP, (long)table_33, 0 }, - { MULADD, 0x511537CB, 0x7135 }, - { MULADD, 0x1CF71007, 0x5E17 }, - { XOR, 0x583D4BCF, 0 }, - { LOOKUP, (long)table_34, 0 }, - { XOR, 0x373E6856, 0 }, - { MULADD, 0x4D595519, 0x1A7D }, - { LOOKUP, (long)table_35, 0 }, - { LOOKUP, (long)table_36, 0 }, - { XOR, 0x0E2A36A7, 0 }, - { LOOKUP, (long)table_37, 0 }, - { LOOKUP, (long)table_38, 0 }, - { BITFLD, (long)table_39, 0 }, - { BITFLD, (long)table_40, 0 }, - { XOR, 0x53F3604F, 0 }, - { BITFLD, (long)table_41, 0 }, - { BITFLD, (long)table_42, 0 }, - { MULADD, 0x1EDC0BA3, 0x7531 }, - { LOOKUP, (long)table_43, 0 }, - { XOR, 0x10DF1038, 0 }, - { BITFLD, (long)table_44, 0 }, - { LOOKUP, (long)table_45, 0 }, - { XOR, 0x4EDE0CAC, 0 }, - { MULADD, 0x2F076EEB, 0x5BCF }, - { XOR, 0x6D86030F, 0 }, - { XOR, 0x3F331713, 0 }, - { LOOKUP, (long)table_46, 0 }, - { MULADD, 0x41CD726F, 0x3F79 }, - { BITFLD, (long)table_47, 0 }, - { XOR, 0x0ECE0054, 0 }, - { MULADD, 0x19B32B03, 0x4AD1 }, - { BITFLD, (long)table_48, 0 }, - { BITFLD, (long)table_49, 0 }}, - {{ MULADD, 0x39731111, 0x419B }, - { XOR, 0x54F7757A, 0 }, - { BITFLD, (long)table_50, 0 }, - { BITFLD, (long)table_51, 0 }, - { LOOKUP, (long)table_52, 0 }, - { LOOKUP, (long)table_53, 0 }, - { MULADD, 0x3CC0256B, 0x7CE7 }, - { XOR, 0x79991847, 0 }, - { MULADD, 0x228F7FB5, 0x472D }, - { MULADD, 0x32DA290B, 0x7745 }, - { XOR, 0x7A28180D, 0 }, - { BITFLD, (long)table_54, 0 }, - { BITFLD, (long)table_55, 0 }, - { MULADD, 0x5C814F8B, 0x227F }, - { LOOKUP, (long)table_56, 0 }, - { MULADD, 0x0B496F6D, 0x412D }, - { XOR, 0x6F4B62DA, 0 }, - { LOOKUP, (long)table_57, 0 }, - { XOR, 0x64973977, 0 }, - { LOOKUP, (long)table_58, 0 }, - { LOOKUP, (long)table_59, 0 }, - { BITFLD, (long)table_60, 0 }, - { LOOKUP, (long)table_61, 0 }, - { LOOKUP, (long)table_62, 0 }, - { XOR, 0x6DD14C92, 0 }, - { LOOKUP, (long)table_63, 0 }, - { BITFLD, (long)table_64, 0 }, - { BITFLD, (long)table_65, 0 }, - { BITFLD, (long)table_66, 0 }, - { LOOKUP, (long)table_67, 0 }, - { XOR, 0x5E6324D8, 0 }, - { LOOKUP, (long)table_68, 0 }, - { LOOKUP, (long)table_69, 0 }, - { LOOKUP, (long)table_70, 0 }, - { BITFLD, (long)table_71, 0 }, - { XOR, 0x62745ED0, 0 }, - { MULADD, 0x102C215B, 0x0581 }, - { LOOKUP, (long)table_72, 0 }, - { LOOKUP, (long)table_73, 0 }, - { LOOKUP, (long)table_74, 0 }, - { MULADD, 0x19511111, 0x12C1 }, - { LOOKUP, (long)table_75, 0 }, - { MULADD, 0x2A6E2953, 0x6977 }, - { LOOKUP, (long)table_76, 0 }, - { XOR, 0x55CD5445, 0 }, - { BITFLD, (long)table_77, 0 }, - { BITFLD, (long)table_78, 0 }, - { MULADD, 0x646C21EB, 0x43E5 }, - { XOR, 0x71DC4898, 0 }, - { XOR, 0x167519CB, 0 }, - { XOR, 0x6D3158F8, 0 }, - { XOR, 0x7EA95BEA, 0 }, - { BITFLD, (long)table_79, 0 }, - { XOR, 0x47377587, 0 }, - { XOR, 0x2D8B6E8F, 0 }, - { MULADD, 0x5E6105DB, 0x1605 }, - { XOR, 0x65B543C8, 0 }, - { LOOKUP, (long)table_80, 0 }, - { BITFLD, (long)table_81, 0 }, - { MULADD, 0x48AF73CB, 0x0A67 }, - { XOR, 0x4FB96154, 0 }, - { LOOKUP, (long)table_82, 0 }, - { BITFLD, (long)table_83, 0 }, - { XOR, 0x622C4954, 0 }, - { BITFLD, (long)table_84, 0 }, - { XOR, 0x20D220F3, 0 }, - { XOR, 0x361D4F0D, 0 }, - { XOR, 0x2B2000D1, 0 }, - { XOR, 0x6FB8593E, 0 }, - { LOOKUP, (long)table_85, 0 }, - { BITFLD, (long)table_86, 0 }, - { XOR, 0x2B7F7DFC, 0 }, - { MULADD, 0x5FC41A57, 0x0693 }, - { MULADD, 0x17154387, 0x2489 }, - { BITFLD, (long)table_87, 0 }, - { BITFLD, (long)table_88, 0 }, - { BITFLD, (long)table_89, 0 }, - { LOOKUP, (long)table_90, 0 }, - { XOR, 0x7E221470, 0 }, - { XOR, 0x7A600061, 0 }, - { BITFLD, (long)table_91, 0 }, - { BITFLD, (long)table_92, 0 }, - { LOOKUP, (long)table_93, 0 }, - { BITFLD, (long)table_94, 0 }, - { MULADD, 0x00E813A5, 0x2CE5 }, - { MULADD, 0x3D707E25, 0x3827 }, - { MULADD, 0x77A53E07, 0x6A5F }, - { BITFLD, (long)table_95, 0 }, - { LOOKUP, (long)table_96, 0 }, - { LOOKUP, (long)table_97, 0 }, - { XOR, 0x43A73788, 0 }, - { LOOKUP, (long)table_98, 0 }, - { BITFLD, (long)table_99, 0 }, - { LOOKUP, (long)table_100, 0 }, - { XOR, 0x55F4606B, 0 }, - { BITFLD, (long)table_101, 0 }}, - {{ BITFLD, (long)table_102, 0 }, - { MULADD, 0x32CA58E3, 0x04F9 }, - { XOR, 0x11756B30, 0 }, - { MULADD, 0x218B2569, 0x5DB1 }, - { XOR, 0x77D64B90, 0 }, - { BITFLD, (long)table_103, 0 }, - { LOOKUP, (long)table_104, 0 }, - { MULADD, 0x7D1428CB, 0x3D }, - { XOR, 0x6F872C49, 0 }, - { XOR, 0x2E484655, 0 }, - { MULADD, 0x1E3349F7, 0x41F5 }, - { LOOKUP, (long)table_105, 0 }, - { BITFLD, (long)table_106, 0 }, - { XOR, 0x61640311, 0 }, - { BITFLD, (long)table_107, 0 }, - { LOOKUP, (long)table_108, 0 }, - { LOOKUP, (long)table_109, 0 }, - { LOOKUP, (long)table_110, 0 }, - { XOR, 0x007044D3, 0 }, - { BITFLD, (long)table_111, 0 }, - { MULADD, 0x5C221625, 0x576F }, - { LOOKUP, (long)table_112, 0 }, - { LOOKUP, (long)table_113, 0 }, - { XOR, 0x2D406BB1, 0 }, - { MULADD, 0x680B1F17, 0x12CD }, - { BITFLD, (long)table_114, 0 }, - { MULADD, 0x12564D55, 0x32B9 }, - { MULADD, 0x21A67897, 0x6BAB }, - { LOOKUP, (long)table_115, 0 }, - { MULADD, 0x06405119, 0x7143 }, - { XOR, 0x351D01ED, 0 }, - { MULADD, 0x46356F6B, 0x0A49 }, - { MULADD, 0x32C77969, 0x72F3 }, - { BITFLD, (long)table_116, 0 }, - { LOOKUP, (long)table_117, 0 }, - { LOOKUP, (long)table_118, 0 }, - { BITFLD, (long)table_119, 0 }, - { LOOKUP, (long)table_120, 0 }, - { BITFLD, (long)table_121, 0 }, - { MULADD, 0x74D52C55, 0x5F43 }, - { XOR, 0x26201CA8, 0 }, - { XOR, 0x7AEB3255, 0 }, - { LOOKUP, (long)table_122, 0 }, - { MULADD, 0x578F1047, 0x640B }, - { LOOKUP, (long)table_123, 0 }, - { LOOKUP, (long)table_124, 0 }, - { BITFLD, (long)table_125, 0 }, - { BITFLD, (long)table_126, 0 }, - { XOR, 0x4A1352CF, 0 }, - { MULADD, 0x4BFB6EF3, 0x704F }, - { MULADD, 0x1B4C7FE7, 0x5637 }, - { MULADD, 0x04091A3B, 0x4917 }, - { XOR, 0x270C2F52, 0 }, - { LOOKUP, (long)table_127, 0 }, - { BITFLD, (long)table_128, 0 }, - { LOOKUP, (long)table_129, 0 }, - { BITFLD, (long)table_130, 0 }, - { MULADD, 0x127549D5, 0x579B }, - { MULADD, 0x0AB54121, 0x7A47 }, - { BITFLD, (long)table_131, 0 }, - { XOR, 0x751E6E49, 0 }, - { LOOKUP, (long)table_132, 0 }, - { LOOKUP, (long)table_133, 0 }, - { XOR, 0x670C3F74, 0 }, - { MULADD, 0x6B080851, 0x7E8B }, - { XOR, 0x71CD789E, 0 }, - { XOR, 0x3EB20B7B, 0 }, - { BITFLD, (long)table_134, 0 }, - { LOOKUP, (long)table_135, 0 }, - { MULADD, 0x58A67753, 0x272B }, - { MULADD, 0x1AB54AD7, 0x4D33 }, - { MULADD, 0x07D30A45, 0x0569 }, - { MULADD, 0x737616BF, 0x70C7 }, - { LOOKUP, (long)table_136, 0 }, - { MULADD, 0x45C4485D, 0x2063 }, - { BITFLD, (long)table_137, 0 }, - { XOR, 0x2598043D, 0 }, - { MULADD, 0x223A4FE3, 0x49A7 }, - { XOR, 0x1EED619F, 0 }, - { BITFLD, (long)table_138, 0 }, - { XOR, 0x6F477561, 0 }, - { BITFLD, (long)table_139, 0 }, - { BITFLD, (long)table_140, 0 }, - { LOOKUP, (long)table_141, 0 }, - { MULADD, 0x4BC13C4F, 0x45C1 }, - { XOR, 0x3B547BFB, 0 }, - { LOOKUP, (long)table_142, 0 }, - { MULADD, 0x71406AB3, 0x7A5F }, - { XOR, 0x2F1467E9, 0 }, - { MULADD, 0x009366D1, 0x22D1 }, - { MULADD, 0x587D1B75, 0x2CA5 }, - { MULADD, 0x213A4BE7, 0x4499 }, - { MULADD, 0x62653E89, 0x2D5D }, - { BITFLD, (long)table_143, 0 }, - { MULADD, 0x4F5F3257, 0x444F }, - { MULADD, 0x4C0E2B2B, 0x19D3 }}, - {{ MULADD, 0x3F867B35, 0x7B3B }, - { MULADD, 0x32D25CB1, 0x3D6D }, - { BITFLD, (long)table_144, 0 }, - { MULADD, 0x50FA1C51, 0x5F4F }, - { LOOKUP, (long)table_145, 0 }, - { XOR, 0x05FE7AF1, 0 }, - { MULADD, 0x14067C29, 0x10C5 }, - { LOOKUP, (long)table_146, 0 }, - { MULADD, 0x4A5558C5, 0x271F }, - { XOR, 0x3C0861B1, 0 }, - { BITFLD, (long)table_147, 0 }, - { LOOKUP, (long)table_148, 0 }, - { MULADD, 0x18837C9D, 0x6335 }, - { BITFLD, (long)table_149, 0 }, - { XOR, 0x7DAB5033, 0 }, - { LOOKUP, (long)table_150, 0 }, - { MULADD, 0x03B87321, 0x7225 }, - { XOR, 0x7F906745, 0 }, - { LOOKUP, (long)table_151, 0 }, - { BITFLD, (long)table_152, 0 }, - { XOR, 0x21C46C2C, 0 }, - { MULADD, 0x2B36757D, 0x028D }, - { BITFLD, (long)table_153, 0 }, - { LOOKUP, (long)table_154, 0 }, - { XOR, 0x106B4A85, 0 }, - { XOR, 0x17640F11, 0 }, - { LOOKUP, (long)table_155, 0 }, - { XOR, 0x69E60486, 0 }, - { LOOKUP, (long)table_156, 0 }, - { MULADD, 0x3782017D, 0x05BF }, - { BITFLD, (long)table_157, 0 }, - { LOOKUP, (long)table_158, 0 }, - { XOR, 0x6BCA53B0, 0 }, - { LOOKUP, (long)table_159, 0 }, - { LOOKUP, (long)table_160, 0 }, - { LOOKUP, (long)table_161, 0 }, - { LOOKUP, (long)table_162, 0 }, - { XOR, 0x0B8236E3, 0 }, - { BITFLD, (long)table_163, 0 }, - { MULADD, 0x5EE51C43, 0x4553 }, - { BITFLD, (long)table_164, 0 }, - { LOOKUP, (long)table_165, 0 }, - { LOOKUP, (long)table_166, 0 }, - { LOOKUP, (long)table_167, 0 }, - { MULADD, 0x42B14C6F, 0x5531 }, - { XOR, 0x4A2548E8, 0 }, - { MULADD, 0x5C071D85, 0x2437 }, - { LOOKUP, (long)table_168, 0 }, - { MULADD, 0x29195861, 0x108B }, - { XOR, 0x24012258, 0 }, - { LOOKUP, (long)table_169, 0 }, - { XOR, 0x63CC2377, 0 }, - { XOR, 0x08D04B59, 0 }, - { MULADD, 0x3FD30CF5, 0x7027 }, - { XOR, 0x7C3E0478, 0 }, - { MULADD, 0x457776B7, 0x24B3 }, - { XOR, 0x086652BC, 0 }, - { MULADD, 0x302F5B13, 0x371D }, - { LOOKUP, (long)table_170, 0 }, - { MULADD, 0x58692D47, 0x0671 }, - { XOR, 0x6601178E, 0 }, - { MULADD, 0x0F195B9B, 0x1369 }, - { XOR, 0x07BA21D8, 0 }, - { BITFLD, (long)table_171, 0 }, - { BITFLD, (long)table_172, 0 }, - { XOR, 0x13AC3D21, 0 }, - { MULADD, 0x5BCF3275, 0x6E1B }, - { MULADD, 0x62725C5B, 0x16B9 }, - { MULADD, 0x5B950FDF, 0x2D35 }, - { BITFLD, (long)table_173, 0 }, - { BITFLD, (long)table_174, 0 }, - { MULADD, 0x73BA5335, 0x1C13 }, - { BITFLD, (long)table_175, 0 }, - { BITFLD, (long)table_176, 0 }, - { XOR, 0x3E144154, 0 }, - { MULADD, 0x4EED7B27, 0x38AB }, - { LOOKUP, (long)table_177, 0 }, - { MULADD, 0x627C7E0F, 0x7F01 }, - { MULADD, 0x5D7E1F73, 0x2C0F }, - { LOOKUP, (long)table_178, 0 }, - { MULADD, 0x55C9525F, 0x4659 }, - { XOR, 0x3765334C, 0 }, - { MULADD, 0x5DF66DDF, 0x7C25 }, - { LOOKUP, (long)table_179, 0 }, - { LOOKUP, (long)table_180, 0 }, - { XOR, 0x16AE5776, 0 }, - { LOOKUP, (long)table_181, 0 }, - { LOOKUP, (long)table_182, 0 }, - { BITFLD, (long)table_183, 0 }, - { BITFLD, (long)table_184, 0 }, - { LOOKUP, (long)table_185, 0 }, - { MULADD, 0x4392327B, 0x7E0D }, - { LOOKUP, (long)table_186, 0 }, - { MULADD, 0x3D8B0CB5, 0x640D }, - { MULADD, 0x32865601, 0x4D43 }, - { BITFLD, (long)table_187, 0 }}}; - -#define A( x ) (( x ) & 0xFF ) -#define B( x ) (( x ) >> 8 & 0xFF ) -#define C( x ) (( x ) >> 16 & 0xFF ) -#define D( x ) (( x ) >> 24 & 0xFF ) - -int yahoo_xfrm( int table, int depth, int seed ) -{ - const struct yahoo_fn *xfrm; - int i, j, z; - unsigned int n = seed; - unsigned char *arg; - - for( i = 0; i < depth; i++ ) - { - xfrm = &yahoo_fntable[table][n % 96]; - switch( xfrm->type ) - { - case IDENT: - return seed; - case XOR: - seed ^= xfrm->arg1; - break; - case MULADD: - seed = seed * xfrm->arg1 + xfrm->arg2; - break; - case LOOKUP: - arg = (unsigned char *)xfrm->arg1; - seed = arg[A( seed )] | arg[B( seed )] << 8 | arg[C( seed )] << 16 - | arg[D( seed )] << 24; - break; - case BITFLD: - arg = (unsigned char *)xfrm->arg1; - for( j = 0, z = 0; j < 32; j++ ) - z = ((( seed >> j ) & 1 ) << arg[j] ) | ( ~( 1 << arg[j] ) & z ); - seed = z; - break; - } - if( depth - i == 1 ) - return seed; - z = (((((( A( seed ) * 0x9E3779B1 ) ^ B( seed )) * 0x9E3779B1 ) - ^ C( seed )) * 0x9E3779B1 ) ^ D( seed )) * 0x9E3779B1; - n = (((( z ^ ( z >> 8 )) >> 16 ) ^ z ) ^ ( z >> 8 )) & 0xFF; - seed *= 0x00010DCD; - } - return seed; -} diff --git a/protocols/yahoo/yahoo_fn.h b/protocols/yahoo/yahoo_fn.h deleted file mode 100644 index 5400e5d0..00000000 --- a/protocols/yahoo/yahoo_fn.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * libyahoo2 - originally from gaim patches by Amatus - * - * Copyright (C) 2003-2004 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#define IDENT 1 /* identify function */ -#define XOR 2 /* xor with arg1 */ -#define MULADD 3 /* multipy by arg1 then add arg2 */ -#define LOOKUP 4 /* lookup each byte in the table pointed to by arg1 */ -#define BITFLD 5 /* reorder bits according to table pointed to by arg1 */ - -struct yahoo_fn { - int type; - long arg1, arg2; -}; - -int yahoo_xfrm(int table, int depth, int seed); diff --git a/protocols/yahoo/yahoo_httplib.c b/protocols/yahoo/yahoo_httplib.c index 6bb8923d..fd63d507 100644 --- a/protocols/yahoo/yahoo_httplib.c +++ b/protocols/yahoo/yahoo_httplib.c @@ -61,6 +61,7 @@ extern struct yahoo_callbacks *yc; extern enum yahoo_log_level log_level; +#if 0 int yahoo_tcp_readline(char *ptr, int maxlen, void *fd) { int n, rc; @@ -92,6 +93,7 @@ int yahoo_tcp_readline(char *ptr, int maxlen, void *fd) *ptr = 0; return (n); } +#endif static int url_to_host_port_path(const char *url, char *host, int *port, char *path, int *ssl) @@ -182,6 +184,7 @@ char *yahoo_urlencode(const char *instr) return (str); } +#if 0 char *yahoo_urldecode(const char *instr) { int ipos = 0, bpos = 0; @@ -278,6 +281,7 @@ char *yahoo_xmldecode(const char *instr) return (str); } +#endif typedef void (*http_connected) (int id, void *fd, int error); diff --git a/root_commands.c b/root_commands.c index a46e0225..77f40060 100644 --- a/root_commands.c +++ b/root_commands.c @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2010 Wilmer van der Gaast and others * + * Copyright 2002-2013 Wilmer van der Gaast and others * \********************************************************************/ /* User manager (root) commands */ @@ -552,8 +552,7 @@ static void cmd_account( irc_t *irc, char **cmd ) g_strcasecmp( cmd[1], "del" ) == 0 || ( a = account_get( irc->b, cmd[1] ) ) == NULL ) { - irc_rootmsg( irc, "Could not find account `%s'. Note that the syntax " - "of the account command changed, see \x02help account\x02.", cmd[1] ); + irc_rootmsg( irc, "Could not find account `%s'.", cmd[1] ); return; } @@ -680,6 +679,7 @@ static void cmd_add( irc_t *irc, char **cmd ) { account_t *a; int add_on_server = 1; + char *handle = NULL, *s; if( g_strcasecmp( cmd[1], "-tmp" ) == 0 ) { @@ -717,6 +717,18 @@ static void cmd_add( irc_t *irc, char **cmd ) } } + if( ( a->flags & ACC_FLAG_HANDLE_DOMAINS ) && cmd[2][0] != '_' && + ( !( s = strchr( cmd[2], '@' ) ) || s[1] == '\0' ) ) + { + /* If there's no @ or it's the last char, append the user's + domain name now. Exclude handles starting with a _ so + adding _xmlconsole will keep working. */ + if( s ) + *s = '\0'; + if( ( s = strchr( a->user, '@' ) ) ) + cmd[2] = handle = g_strconcat( cmd[2], s, NULL ); + } + if( add_on_server ) { irc_channel_t *ic; @@ -746,6 +758,7 @@ static void cmd_add( irc_t *irc, char **cmd ) "to contact `%s'", iu->nick, cmd[2] ); } + g_free( handle ); } static void cmd_remove( irc_t *irc, char **cmd ) @@ -1291,6 +1304,29 @@ static void cmd_group( irc_t *irc, char **cmd ) } irc_rootmsg( irc, "End of group list" ); } + else if( g_strncasecmp(cmd[1], "info", len ) == 0 ) + { + bee_group_t *bg; + int n = 0; + + MIN_ARGS(2); + bg = bee_group_by_name( irc->b, cmd[2], FALSE ); + + if( bg ) + { + if( strchr(irc->umode, 'b') ) + irc_rootmsg( irc, "Members of %s:", cmd[2] ); + for( l = irc->b->users; l; l = l->next ) + { + bee_user_t *bu = l->data; + if( bu->group == bg ) + irc_rootmsg( irc, "%d. %s", n ++, bu->nick ? : bu->handle ); + } + irc_rootmsg( irc, "End of member list" ); + } + else + irc_rootmsg( irc, "Unknown group: %s. Please use \x02group list\x02 to get a list of available groups.", cmd[2] ); + } else { irc_rootmsg( irc, "Unknown command: %s %s. Please use \x02help commands\x02 to get a list of available commands.", "group", cmd[1] ); @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2005 Wilmer van der Gaast and others * + * Copyright 2002-2013 Wilmer van der Gaast and others * \********************************************************************/ /* Some stuff to register, handle and save user preferences */ @@ -22,6 +22,7 @@ if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + #define BITLBEE_CORE #include "bitlbee.h" @@ -38,9 +39,22 @@ set_t *set_add( set_t **head, const char *key, const char *def, set_eval eval, v { if( ( s = *head ) ) { - while( s->next ) s = s->next; - s->next = g_new0( set_t, 1 ); - s = s->next; + /* Sorted insertion. Special-case insertion at the start. */ + if( strcmp( key, s->key ) < 0 ) + { + s = g_new0( set_t, 1 ); + s->next = *head; + *head = s; + } + else + { + while( s->next && strcmp( key, s->next->key ) > 0 ) + s = s->next; + set_t *last_next = s->next; + s->next = g_new0( set_t, 1 ); + s = s->next; + s->next = last_next; + } } else { diff --git a/storage_xml.c b/storage_xml.c index 3b67edd4..10cb6495 100644 --- a/storage_xml.c +++ b/storage_xml.c @@ -304,7 +304,7 @@ struct xt_node *xml_generate( irc_t *irc ) /* This probably looks pretty strange. g_hash_table_foreach is quite a PITA already (but it can't get much better in - C without using #define, I'm afraid), and since it + C without using #define, I'm afraid), and it doesn't seem to be possible to abort the foreach on write errors, so instead let's use the _find function and return TRUE on write errors. Which means, if we found @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2004 Wilmer van der Gaast and others * + * Copyright 2002-2012 Wilmer van der Gaast and others * \********************************************************************/ /* Main file (Unix specific part) */ |