From eabd4012f4c5704f7362598fc5e94767cf728d70 2012-08-01 11:26:13 From: Vitaly Takmazov Date: 2012-08-01 11:26:13 Subject: [PATCH] Merge branch 'master' of https://github.com/hanzz/libtransport --- diff --git a/CMakeLists.txt b/CMakeLists.txt index c01c3072cb14fe9d38477578ad1c37218e79b2b7..9fac75fc99003f0f82f7a171534ff9b6faf2706e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -79,6 +79,9 @@ set(dbus_DIR "${CMAKE_SOURCE_DIR}/cmake_modules") find_package(dbus) endif() +set(yahoo2_DIR "${CMAKE_SOURCE_DIR}/cmake_modules") +find_package(yahoo2) + find_package(Doxygen) INCLUDE(FindQt4) @@ -191,6 +194,14 @@ else() endif() endif() +# We have our own copy now... +# if(YAHOO2_FOUND) + message("Libyahoo2 plugin : yes") +# include_directories(${YAHOO2_INCLUDE_DIR}) +# else() +# message("Libyahoo2 plugin : no (install libyahoo2-devel)") +# endif() + else() message("Network plugins : no (install libprotobuf-dev)") message("Libpurple plugin : no (install libpurple and libprotobuf-dev)") diff --git a/ChangeLog b/ChangeLog index 9ef83b4825320a212c3561bf2510114f21b2ccf1..94cc0f645c82975e184df0cc1a3b823557ce2477 100644 --- a/ChangeLog +++ b/ChangeLog @@ -13,13 +13,25 @@ Version 2.0.0-beta3 (2012-XX-XX): * Added Munin plugin (Thanks to Askovpen). * Added support for more admin_jid JIDs (Thanks to Askovpen). * Fixed allowed_servers option. + * Show error in server-mode when server port is already used. + * Fixed bug when backend could freeze on exit. + * Options from config file can now be set also using command line like + --service.jid=domain.tld . + * Do not send password in IQ-get registration response. Libpurple: * prpl-gg: Fetch the contact list properly (#252). + * Added support for prpl-novell as it was in spectrum1. Skype: * Log more errors. + Libyahoo2: + * Added new Yahoo backend based on libyahoo2. + + Swiften: + * Added new XMPP backend based on Swiften library. + Backend API: * Added Python NetworkPlugin class, so it is now easier to write backends in Python (Thanks to Sarang). diff --git a/backends/CMakeLists.txt b/backends/CMakeLists.txt index 63de7f0deb73ce89c18164328fc685cebb670fcd..f82ef3efda2375bf85254f919af92aac937d6b7c 100644 --- a/backends/CMakeLists.txt +++ b/backends/CMakeLists.txt @@ -9,6 +9,10 @@ if (PROTOBUF_FOUND) ADD_SUBDIRECTORY(swiften) +# if(YAHOO2_FOUND) + ADD_SUBDIRECTORY(libyahoo2) +# endif() + ADD_SUBDIRECTORY(template) if (NOT WIN32) diff --git a/backends/libcommuni/main.cpp b/backends/libcommuni/main.cpp index 9b717d4ca7ebb2ccea6ee3f165b06905d808d7bc..cab694292061cd3764f04c2d1f5d87777adec8e7 100644 --- a/backends/libcommuni/main.cpp +++ b/backends/libcommuni/main.cpp @@ -78,7 +78,7 @@ int main (int argc, char* argv[]) { Swift::QtEventLoop eventLoop; - if (config.getUnregistered().find("service.irc_server") == config.getUnregistered().end()) { + if (!CONFIG_HAS_KEY(&config, "service.irc_server")) { np = new IRCNetworkPlugin(&config, &eventLoop, host, port); } else { diff --git a/backends/libcommuni/singleircnetworkplugin.cpp b/backends/libcommuni/singleircnetworkplugin.cpp index cce79c7b59a4400627f3a97b2aaa2b46e7c0e19b..276ac5ec831a7a9b5386b2938da82ee30efeecb3 100644 --- a/backends/libcommuni/singleircnetworkplugin.cpp +++ b/backends/libcommuni/singleircnetworkplugin.cpp @@ -10,13 +10,19 @@ DEFINE_LOGGER(logger, "SingleIRCNetworkPlugin"); SingleIRCNetworkPlugin::SingleIRCNetworkPlugin(Config *config, Swift::QtEventLoop *loop, const std::string &host, int port) { this->config = config; - m_server = config->getUnregistered().find("service.irc_server")->second; + if (CONFIG_HAS_KEY(config, "service.irc_server")) { + m_server = CONFIG_STRING(config, "service.irc_server"); + } + else { + LOG4CXX_ERROR(logger, "No [service] irc_server defined, exiting..."); + exit(-1); + } m_socket = new QTcpSocket(); m_socket->connectToHost(FROM_UTF8(host), port); connect(m_socket, SIGNAL(readyRead()), this, SLOT(readData())); - if (config->getUnregistered().find("service.irc_identify") != config->getUnregistered().end()) { - m_identify = config->getUnregistered().find("service.irc_identify")->second; + if (CONFIG_HAS_KEY(config, "service.irc_identify")) { + m_identify = CONFIG_STRING(config, "service.irc_identify"); } else { m_identify = "NickServ identify $name $password"; @@ -52,6 +58,7 @@ void SingleIRCNetworkPlugin::handleLoginRequest(const std::string &user, const s session->setRealName(FROM_UTF8(legacyName)); session->setHost(FROM_UTF8(m_server)); session->setPort(6667); + session->setEncoding( "utf-8" ); if (!password.empty()) { std::string identify = m_identify; diff --git a/backends/libpurple/main.cpp b/backends/libpurple/main.cpp index e06fdb2bb159769b40d46ca58f46947e7cce2785..09b6304996f390e3608cb1b3c89adf3bfe678abc 100644 --- a/backends/libpurple/main.cpp +++ b/backends/libpurple/main.cpp @@ -344,8 +344,13 @@ class SpectrumNetworkPlugin : public NetworkPlugin { } if (purple_accounts_find(name.c_str(), protocol.c_str()) != NULL) { - LOG4CXX_INFO(logger, "Using previously created account with name '" << name.c_str() << "' and protocol '" << protocol << "'"); account = purple_accounts_find(name.c_str(), protocol.c_str()); + if (m_accounts.find(account) != m_accounts.end() && m_accounts[account] != user) { + LOG4CXX_INFO(logger, "Account '" << name << "' is already used by '" << m_accounts[account] << "'"); + np->handleDisconnected(user, 0, "Account '" + name + "' is already used by '" + m_accounts[account] + "'"); + return; + } + LOG4CXX_INFO(logger, "Using previously created account with name '" << name.c_str() << "' and protocol '" << protocol << "'"); } else { LOG4CXX_INFO(logger, "Creating account with name '" << name.c_str() << "' and protocol '" << protocol << "'"); @@ -390,8 +395,6 @@ class SpectrumNetworkPlugin : public NetworkPlugin { purple_account_disconnect(account); purple_account_set_enabled(account, "spectrum", FALSE); - g_free(account->ui_data); - account->ui_data = NULL; m_accounts.erase(account); purple_accounts_delete(account); diff --git a/backends/libyahoo2/CMakeLists.txt b/backends/libyahoo2/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..70ffe5dc7aa0d5b25eb9afa98fad449c6faff543 --- /dev/null +++ b/backends/libyahoo2/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 2.6) + +FILE(GLOB_RECURSE SRC *.c *.cpp) + +ADD_DEFINITIONS(-DHAVE_STDINT_H=1) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/yahoo) + +ADD_EXECUTABLE(spectrum2_libyahoo2_backend ${SRC}) + +target_link_libraries(spectrum2_libyahoo2_backend transport pthread ${Boost_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES}) + +INSTALL(TARGETS spectrum2_libyahoo2_backend RUNTIME DESTINATION bin) + diff --git a/backends/libyahoo2/httpfetch.cpp b/backends/libyahoo2/httpfetch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..90e526208952d1c8904b48fa410120d8d4f5679a --- /dev/null +++ b/backends/libyahoo2/httpfetch.cpp @@ -0,0 +1,159 @@ + +#include "httpfetch.h" +#include "transport/logging.h" + +DEFINE_LOGGER(logger, "HTTPFetch"); + +static int url_to_host_port_path(const char *url, + char *host, int *port, char *path, int *ssl) +{ + char *urlcopy = NULL; + char *slash = NULL; + char *colon = NULL; + + /* + * http://hostname + * http://hostname/ + * http://hostname/path + * http://hostname/path:foo + * http://hostname:port + * http://hostname:port/ + * http://hostname:port/path + * http://hostname:port/path:foo + * and https:// variants of the above + */ + + if (strstr(url, "http://") == url) { + urlcopy = strdup(url + 7); + } else if (strstr(url, "https://") == url) { + urlcopy = strdup(url + 8); + *ssl = 1; + } else { + return 0; + } + + slash = strchr(urlcopy, '/'); + colon = strchr(urlcopy, ':'); + + if (!colon || (slash && slash < colon)) { + if (*ssl) + *port = 443; + else + *port = 80; + } else { + *colon = 0; + *port = atoi(colon + 1); + } + + if (!slash) { + strcpy(path, "/"); + } else { + strcpy(path, slash); + *slash = 0; + } + + strcpy(host, urlcopy); + + free(urlcopy); + + return 1; +} + +HTTPFetch::HTTPFetch(Swift::BoostIOServiceThread *ioService, Swift::ConnectionFactory *factory) : m_ioService(ioService), m_factory(factory) { + m_afterHeader = false; +} + +HTTPFetch::~HTTPFetch() { +} + +void HTTPFetch::_connected(boost::shared_ptr conn, const std::string url, bool error) { + if (error) { + _disconnected(conn); + } + else { + char host[255]; + int port = 80; + char path[255]; + int ssl = 0; + if (!url_to_host_port_path(url.c_str(), host, &port, path, &ssl)) + return; + + static char buff[2048]; + snprintf(buff, sizeof(buff), + "GET %s HTTP/1.1\r\n" + "Host: %s\r\n" + "User-Agent: Mozilla/4.5 [en] (1/1)\r\n" + "Accept: */*\r\n" + "%s" "\r\n", path, host, + "Connection: close\r\n"); + LOG4CXX_INFO(logger, "Sending " << buff << "\n"); + conn->write(Swift::createSafeByteArray(buff)); + } +} + +void HTTPFetch::_disconnected(boost::shared_ptr conn) { + conn->onConnectFinished.disconnect_all_slots(); + conn->onDisconnected.disconnect_all_slots(); + conn->onDataRead.disconnect_all_slots(); + + if (m_buffer.size() == 0) { + onURLFetched(""); + } + else { + std::string img = m_buffer.substr(m_buffer.find("\r\n\r\n") + 4); + onURLFetched(img); + } +} + +void HTTPFetch::_read(boost::shared_ptr conn, boost::shared_ptr data) { + std::string d(data->begin(), data->end()); +// std::cout << d << "\n"; + std::string img = d.substr(d.find("\r\n\r\n") + 4); + if (d.find("Location: ") == std::string::npos) { + m_buffer += d; + } + else { + d = d.substr(d.find("Location: ") + 10); + if (d.find("\r") == std::string::npos) { + d = d.substr(0, d.find("\n")); + } + else { + d = d.substr(0, d.find("\r")); + } + LOG4CXX_INFO(logger, "Next url is '" << d << "'"); + fetchURL(d); + conn->onConnectFinished.disconnect_all_slots(); + conn->onDisconnected.disconnect_all_slots(); + conn->onDataRead.disconnect_all_slots(); + } +} + +bool HTTPFetch::fetchURL(const std::string &url) { + char host[255]; + int port = 80; + char path[255]; + char buff[1024]; + int ssl = 0; + if (!url_to_host_port_path(url.c_str(), host, &port, path, &ssl)) { + LOG4CXX_ERROR(logger, "Invalid URL " << url); + return false; + } + + LOG4CXX_INFO(logger, "Connecting to " << host << ":" << port); + + boost::asio::ip::tcp::resolver resolver(*m_ioService->getIOService()); + boost::asio::ip::tcp::resolver::query query(host, ""); + boost::asio::ip::address address; + for(boost::asio::ip::tcp::resolver::iterator i = resolver.resolve(query); i != boost::asio::ip::tcp::resolver::iterator(); ++i) { + boost::asio::ip::tcp::endpoint end = *i; + address = end.address(); + break; + } + + boost::shared_ptr conn = m_factory->createConnection(); + conn->onConnectFinished.connect(boost::bind(&HTTPFetch::_connected, this, conn, url, _1)); + conn->onDisconnected.connect(boost::bind(&HTTPFetch::_disconnected, this, conn)); + conn->onDataRead.connect(boost::bind(&HTTPFetch::_read, this, conn, _1)); + conn->connect(Swift::HostAddressPort(Swift::HostAddress(address), port)); + return true; +} diff --git a/backends/libyahoo2/httpfetch.h b/backends/libyahoo2/httpfetch.h new file mode 100644 index 0000000000000000000000000000000000000000..1d9a3899e38fc13654516bfae82f9df4cfc172f3 --- /dev/null +++ b/backends/libyahoo2/httpfetch.h @@ -0,0 +1,43 @@ +#pragma once + +// Transport includes +#include "transport/config.h" +#include "transport/networkplugin.h" +#include "transport/logging.h" + +// Swiften +#include "Swiften/Swiften.h" +#include "Swiften/TLS/OpenSSL/OpenSSLContextFactory.h" + +// for signal handler +#include "unistd.h" +#include "signal.h" +#include "sys/wait.h" +#include "sys/signal.h" + +// Boost +#include + +using namespace boost::filesystem; +using namespace boost::program_options; +using namespace Transport; + +class HTTPFetch { + public: + HTTPFetch(Swift::BoostIOServiceThread *ioSerice, Swift::ConnectionFactory *factory); + virtual ~HTTPFetch(); + + bool fetchURL(const std::string &url); + + boost::signal onURLFetched; + + private: + void _connected(boost::shared_ptr conn, const std::string url, bool error); + void _disconnected(boost::shared_ptr conn); + void _read(boost::shared_ptr conn, boost::shared_ptr data); + + Swift::BoostIOServiceThread *m_ioService; + Swift::ConnectionFactory *m_factory; + std::string m_buffer; + bool m_afterHeader; +}; diff --git a/backends/libyahoo2/main.cpp b/backends/libyahoo2/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..eda158b017a00af7cce98fee2af3b31c136685ef --- /dev/null +++ b/backends/libyahoo2/main.cpp @@ -0,0 +1,784 @@ +// Transport includes +#include "transport/config.h" +#include "transport/networkplugin.h" +#include "transport/logging.h" + +// Yahoo2 +#include +#include +#include +#include +#include + +#include "yahoohandler.h" +#include "yahoolocalaccount.h" +#include "httpfetch.h" + +// Swiften +#include "Swiften/Swiften.h" +#include "Swiften/Network/TLSConnectionFactory.h" +#include "Swiften/TLS/OpenSSL/OpenSSLContextFactory.h" + +// for signal handler +#include "unistd.h" +#include "signal.h" +#include "sys/wait.h" +#include "sys/signal.h" + +// Boost +#include +using namespace boost::filesystem; +using namespace boost::program_options; +using namespace Transport; + +class YahooHandler; +class YahooLocalAccount; + +static std::string *currently_read_data; +static YahooLocalAccount *currently_writting_account; + +YahooHandler::YahooHandler(YahooLocalAccount *account, int conn_tag, int handler_tag, void *data, yahoo_input_condition cond) : + handler_tag(handler_tag), conn_tag(conn_tag), data(data), cond(cond), remove_later(false), account(account) {} + +YahooHandler::~YahooHandler() {} + +void YahooHandler::ready(std::string *buffer) { + if (cond == YAHOO_INPUT_WRITE) { + YahooLocalAccount *old = currently_writting_account; + currently_writting_account = account; + yahoo_write_ready(account->id, (void *) conn_tag, data); + currently_writting_account = old; + } + else { + if (!buffer) { + return; + } + // yahoo_read_ready calls ext_yahoo_read(...) in a loop, so we just have to choose proper buffer from which will + // that method read. We do that by static currently_read_data pointer. + currently_read_data = buffer; + // libyahoo2 reads data per 1024 bytes, so if we still have some data after the first ext_yahoo_read call, + // we have to call yahoo_read_ready again... + do { + yahoo_read_ready(account->id, (void *) conn_tag, data); + } while (currently_read_data->size() != 0); + } +} + + +typedef struct { + std::string yahoo_id; + std::string name; + int status; + int away; + std::string msg; + std::string group; +} yahoo_account; + +typedef struct { + int id; + char *label; +} yahoo_idlabel; + +typedef struct { + int id; + char *who; +} yahoo_authorize_data; + +DEFINE_LOGGER(logger, "Yahoo2"); + +// eventloop +Swift::SimpleEventLoop *loop_; + +// Plugin +class YahooPlugin; +YahooPlugin * np = NULL; + +class YahooPlugin : public NetworkPlugin { + public: + Swift::BoostNetworkFactories *m_factories; + Swift::OpenSSLContextFactory *m_sslFactory; + Swift::TLSConnectionFactory *m_tlsFactory; + Swift::BoostIOServiceThread m_boostIOServiceThread; + boost::shared_ptr m_conn; + + YahooPlugin(Config *config, Swift::SimpleEventLoop *loop, const std::string &host, int port) : NetworkPlugin() { + this->config = config; + m_factories = new Swift::BoostNetworkFactories(loop); + m_sslFactory = new Swift::OpenSSLContextFactory(); + m_tlsFactory = new Swift::TLSConnectionFactory(m_sslFactory, m_factories->getConnectionFactory()); + m_conn = m_factories->getConnectionFactory()->createConnection(); + m_conn->onDataRead.connect(boost::bind(&YahooPlugin::_handleDataRead, this, _1)); + m_conn->connect(Swift::HostAddressPort(Swift::HostAddress(host), port)); + + LOG4CXX_INFO(logger, "Starting the plugin."); + } + + // NetworkPlugin uses this method to send the data to networkplugin server + void sendData(const std::string &string) { + m_conn->write(Swift::createSafeByteArray(string)); + } + + // This method has to call handleDataRead with all received data from network plugin server + void _handleDataRead(boost::shared_ptr data) { + std::string d(data->begin(), data->end()); + handleDataRead(d); + } + + void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) { + YahooLocalAccount *account = new YahooLocalAccount(user, legacyName, password); + m_users[user] = account; + m_ids[account->id] = user; + + LOG4CXX_INFO(logger, user << ": Logging in the user as " << legacyName << " with id=" << account->id); + account->login(); + } + + void handleLogoutRequest(const std::string &user, const std::string &legacyName) { + YahooLocalAccount *account = m_users[user]; + if (account) { + yahoo_logoff(account->id); + m_ids.erase(account->id); + m_users.erase(user); + delete account; + } + } + + void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &xhtml = "") { + YahooLocalAccount *account = m_users[user]; + if (account) { + LOG4CXX_INFO(logger, "Sending message from " << user << " to " << legacyName << ": " << message << "."); + yahoo_send_im(account->id, NULL, legacyName.c_str(), message.c_str(), 0, 0); + _yahoo_write_ready(account); + } + } + + void handleBuddyUpdatedRequest(const std::string &user, const std::string &buddyName, const std::string &alias, const std::vector &groups) { + LOG4CXX_INFO(logger, user << ": Added buddy " << buddyName << "."); + handleBuddyChanged(user, buddyName, alias, groups, pbnetwork::STATUS_ONLINE); + } + + void _avatar_fetched(HTTPFetch *fetch, int account_id, unsigned int id, const std::string &img) { + handleVCard(m_ids[account_id], id, "", "", "", img); + delete fetch; + } + + void handleVCardRequest(const std::string &user, const std::string &legacyName, unsigned int id) { + YahooLocalAccount *account = m_users[user]; + if (!account) { + return; + } + + if (account->urls.find(legacyName) == account->urls.end()) { + return; + } + + HTTPFetch *fetch = new HTTPFetch(&m_boostIOServiceThread, m_factories->getConnectionFactory()); + fetch->onURLFetched.connect(boost::bind(&YahooPlugin::_avatar_fetched, this, fetch, account->id, id, _1)); + fetch->fetchURL(account->urls[legacyName]); + } + + void handleBuddyRemovedRequest(const std::string &user, const std::string &buddyName, const std::vector &groups) { + + } + + YahooLocalAccount *getAccount(int id) { + return m_users[m_ids[id]]; + } + + void _yahoo_remove_account(YahooLocalAccount *account) { + m_ids.erase(account->id); + m_users.erase(account->user); + delete account; + } + + void _yahoo_connect_finished(YahooLocalAccount *account, yahoo_connect_callback callback, void *data, int conn_tag, bool error) { + currently_writting_account = account; + if (error) { + LOG4CXX_ERROR(logger, account->user << ": Connection error!"); + callback(NULL, 0, data); +// np->handleDisconnected(user, 0, "Connection error."); + } + else { + LOG4CXX_INFO(logger, account->user << ": Connected"); + // We will have dangling pointer here, but we can't pass boost::shared_ptr here... + callback((void *) conn_tag, 0, data); + } + } + + void _yahoo_write_ready(YahooLocalAccount *account) { + // Find all WRITE handlers and inform that they really can write. + for (std::map::iterator it = account->handlers.begin(); it != account->handlers.end(); it++) { + if (it->second->cond == YAHOO_INPUT_WRITE && !it->second->remove_later) { + it->second->ready(); + } + } + } + + void _yahoo_data_read(YahooLocalAccount *account, int conn_tag, boost::shared_ptr data) { + std::string d(data->begin(), data->end()); + + // Find the handler that handles READing for this conn_tag + for (std::map::iterator it = account->handlers_per_conn[conn_tag].begin(); it != account->handlers_per_conn[conn_tag].end(); it++) { + if (it->second->cond == YAHOO_INPUT_READ && !it->second->remove_later) { + std::string cpy(d); + it->second->ready(&cpy); + + // Look like libyahoo2 needs to be informed it can write to socket after the read + // even we have informed it before... + _yahoo_write_ready(account); + break; + } + } + + account->removeOldHandlers(); + } + + void _yahoo_data_written(YahooLocalAccount *account, int conn_tag) { + LOG4CXX_INFO(logger, "data written"); + for (std::map::iterator it = account->handlers_per_conn[conn_tag].begin(); it != account->handlers_per_conn[conn_tag].end(); it++) { + if (it->second->cond == YAHOO_INPUT_WRITE) { + it->second->ready(); + } + } + + account->removeOldHandlers(); + } + + void _yahoo_disconnected(YahooLocalAccount *account, int conn_tag, const boost::optional &error) { + for (std::map::iterator it = account->handlers_per_conn[conn_tag].begin(); it != account->handlers_per_conn[conn_tag].end(); it++) { + if (it->second->cond == YAHOO_INPUT_READ && !it->second->remove_later) { + std::string cpy; + it->second->ready(&cpy); + _yahoo_write_ready(account); + break; + } + } + + account->removeConn(conn_tag); + } + + int _yahoo_connect_async(int id, const char *host, int port, yahoo_connect_callback callback, void *data, int use_ssl) { + YahooLocalAccount *account = getAccount(id); + if (!account) { + LOG4CXX_ERROR(logger, "Unknown account id=" << id); + return -1; + } + + boost::asio::ip::tcp::resolver resolver(*m_boostIOServiceThread.getIOService()); + boost::asio::ip::tcp::resolver::query query(host, ""); + boost::asio::ip::address address; + for(boost::asio::ip::tcp::resolver::iterator i = resolver.resolve(query); i != boost::asio::ip::tcp::resolver::iterator(); ++i) { + boost::asio::ip::tcp::endpoint end = *i; + address = end.address(); + break; + } + + LOG4CXX_INFO(logger, m_ids[id] << ": Connecting " << host << ":" << port); + int tag = account->conn_tag++; + if (use_ssl) { + account->conns[tag] = m_tlsFactory->createConnection(); + } + else { + account->conns[tag] = m_factories->getConnectionFactory()->createConnection(); + } + account->conns[tag]->onConnectFinished.connect(boost::bind(&YahooPlugin::_yahoo_connect_finished, this, account, callback, data, tag, _1)); + account->conns[tag]->onDisconnected.connect(boost::bind(&YahooPlugin::_yahoo_disconnected, this, account, tag, _1)); + account->conns[tag]->onDataRead.connect(boost::bind(&YahooPlugin::_yahoo_data_read, this, account, tag, _1)); + account->conns[tag]->onDataWritten.connect(boost::bind(&YahooPlugin::_yahoo_data_written, this, account, tag)); + account->conns[tag]->connect(Swift::HostAddressPort(Swift::HostAddress(address), port)); + return tag; + } + + private: + Config *config; + std::map m_users; + std::map m_ids; +}; + +static void spectrum_sigchld_handler(int sig) +{ + int status; + pid_t pid; + + do { + pid = waitpid(-1, &status, WNOHANG); + } while (pid != 0 && pid != (pid_t)-1); + + if ((pid == (pid_t) - 1) && (errno != ECHILD)) { + char errmsg[BUFSIZ]; + snprintf(errmsg, BUFSIZ, "Warning: waitpid() returned %d", pid); + perror(errmsg); + } +} + +static void ext_yahoo_got_conf_invite(int id, const char *me, const char *who, const char *room, const char *msg, YList *members) { +} + +static void ext_yahoo_conf_userdecline(int id, const char *me, const char *who, const char *room, const char *msg) { +} + +static void ext_yahoo_conf_userjoin(int id, const char *me, const char *who, const char *room) { +} + +static void ext_yahoo_conf_userleave(int id, const char *me, const char *who, const char *room) { +} + +static void ext_yahoo_conf_message(int id, const char *me, const char *who, const char *room, const char *msg, int utf8) { +} + +static void ext_yahoo_chat_cat_xml(int id, const char *xml) { +} + +static void ext_yahoo_chat_join(int id, const char *me, const char *room, const char * topic, YList *members, void *fd) { +} + +static void ext_yahoo_chat_userjoin(int id, const char *me, const char *room, struct yahoo_chat_member *who) { +} + +static void ext_yahoo_chat_userleave(int id, const char *me, const char *room, const char *who) { +} + +static void ext_yahoo_chat_message(int id, const char *me, const char *who, const char *room, const char *msg, int msgtype, int utf8) { +} + +static void ext_yahoo_status_changed(int id, const char *who, int stat, const char *msg, int away, int idle, int mobile) { + YahooLocalAccount *account = np->getAccount(id); + if (!account) { + return; + } + + LOG4CXX_INFO(logger, account->user << ": " << who << " status changed"); + + pbnetwork::StatusType status = pbnetwork::STATUS_NONE; + switch (stat) { + case YAHOO_STATUS_AVAILABLE: + status = pbnetwork::STATUS_ONLINE; + break; + case YAHOO_STATUS_NOTATHOME: + case YAHOO_STATUS_NOTATDESK: + case YAHOO_STATUS_NOTINOFFICE: + case YAHOO_STATUS_ONPHONE: + case YAHOO_STATUS_ONVACATION: + case YAHOO_STATUS_OUTTOLUNCH: + case YAHOO_STATUS_STEPPEDOUT: + status = pbnetwork::STATUS_AWAY; + break; + case YAHOO_STATUS_BRB: + status = pbnetwork::STATUS_XA; + break; + case YAHOO_STATUS_BUSY: + status = pbnetwork::STATUS_DND; + break; + case YAHOO_STATUS_OFFLINE: + status = pbnetwork::STATUS_NONE; + break; + default: + status = pbnetwork::STATUS_ONLINE; + break; + } + + yahoo_buddyicon_request(id, who); + np->_yahoo_write_ready(account); + + np->handleBuddyChanged(account->user, who, "", std::vector(), status, msg ? msg : ""); +} + +static void ext_yahoo_got_buddies(int id, YList * buds) { + YahooLocalAccount *account = np->getAccount(id); + if (!account) { + return; + } + + LOG4CXX_INFO(logger, account->user << ": Got buddy list"); + for(; buds; buds = buds->next) { + struct yahoo_buddy *bud = (struct yahoo_buddy *) buds->data; + + std::vector groups; + groups.push_back(bud->group); + np->handleBuddyChanged(account->user, bud->id, bud->real_name ? bud->real_name : "", groups, pbnetwork::STATUS_NONE); + } + +// yahoo_set_away(id, YAHOO_STATUS_AVAILABLE, "", 1); + np->_yahoo_write_ready(account); + np->handleConnected(account->user); +} + +static void ext_yahoo_got_ignore(int id, YList * igns) +{ +} + +static void ext_yahoo_got_buzz(int id, const char *me, const char *who, long tm) { +} + +static void ext_yahoo_got_im(int id, const char *me, const char *who, const char *msg, long tm, int stat, int utf8) { + YahooLocalAccount *account = np->getAccount(id); + if (!account) { + return; + } + + np->handleMessage(account->user, who, msg); +} + +static void ext_yahoo_rejected(int id, const char *who, const char *msg) { +} + +static void ext_yahoo_contact_added(int id, const char *myid, const char *who, const char *msg) { +} + +static void ext_yahoo_typing_notify(int id, const char* me, const char *who, int stat) { +} + +static void ext_yahoo_game_notify(int id, const char *me, const char *who, int stat, const char *msg) +{ +} + +static void ext_yahoo_mail_notify(int id, const char *from, const char *subj, int cnt) { +} + +static void ext_yahoo_got_webcam_image(int id, const char *who, const unsigned char *image, unsigned int image_size, unsigned int real_size, unsigned int timestamp) { +} + +static void ext_yahoo_webcam_viewer(int id, const char *who, int connect) { +} + +static void ext_yahoo_webcam_closed(int id, const char *who, int reason) { +} + +static void ext_yahoo_webcam_data_request(int id, int send) { +} + +static void ext_yahoo_webcam_invite(int id, const char *me, const char *from) { +} + +static void ext_yahoo_webcam_invite_reply(int id, const char *me, const char *from, int accept) { +} + +static void ext_yahoo_system_message(int id, const char *me, const char *who, const char *msg) { +} + +static void ext_yahoo_got_cookies(int id) { +} + +static void ext_yahoo_login_response(int id, int succ, const char *url) { + YahooLocalAccount *account = np->getAccount(id); + if (!account) { + return; + } + + if (succ == YAHOO_LOGIN_OK) { + account->status = yahoo_current_status(id); + // We will fire handleConnected in Got Buddy List. + return; + } + else if (succ == YAHOO_LOGIN_UNAME) { + np->handleDisconnected(account->user, 0, "Could not log into Yahoo service - username not recognised. Please verify that your username is correctly typed."); + } + else if (succ == YAHOO_LOGIN_PASSWD) { + np->handleDisconnected(account->user, 0, "Could not log into Yahoo service - password incorrect. Please verify that your password is correctly typed."); + } + else if (succ == YAHOO_LOGIN_LOCK) { + np->handleDisconnected(account->user, 0, std::string("Could not log into Yahoo service. Your account has been locked. Visit ") + url + " to reactivate it."); + } + else if (succ == YAHOO_LOGIN_DUPL) { + np->handleDisconnected(account->user, 0, "You have been logged out of the yahoo service, possibly due to a duplicate login."); + } + else if (succ == YAHOO_LOGIN_SOCK) { + np->handleDisconnected(account->user, 0, "The server closed the socket."); + } + else { + np->handleDisconnected(account->user, 0, "Could not log in, unknown reason."); + } + + np->handleLogoutRequest(account->user, ""); +} + +static void ext_yahoo_error(int id, const char *_err, int fatal, int num) { + std::string err(_err); + std::string msg("Yahoo Error: "); + msg += err + " - "; + switch(num) { + case E_UNKNOWN: + msg += "unknown error " + err; + break; + case E_CUSTOM: + msg += "custom error " + err; + break; + case E_CONFNOTAVAIL: + msg += err + " is not available for the conference"; + break; + case E_IGNOREDUP: + msg += err + " is already ignored"; + break; + case E_IGNORENONE: + msg += err +" is not in the ignore list"; + break; + case E_IGNORECONF: + msg += err + " is in buddy list - cannot ignore "; + break; + case E_SYSTEM: + msg += "system error " + err; + break; + case E_CONNECTION: + msg += err + "server connection error %s"; + break; + } + LOG4CXX_ERROR(logger, msg); + + YahooLocalAccount *account = np->getAccount(id); + if (!account) { + return; + } + + if(fatal) { + np->handleDisconnected(account->user, 0, msg); + np->handleLogoutRequest(account->user, ""); + } +} + +static int ext_yahoo_connect(const char *host, int port) { + return -1; +} + +static int ext_yahoo_add_handler(int id, void *fd, yahoo_input_condition cond, void *data) { + YahooLocalAccount *account = np->getAccount(id); + if (!account) { + return -1; + } + + int conn_tag = (unsigned long) fd; + YahooHandler *handler = new YahooHandler(account, conn_tag, account->handler_tag++, data, cond); + account->addHandler(handler); + + // We are ready to write right now, so why not... + handler->ready(); + + return handler->handler_tag; +} + +static void ext_yahoo_remove_handler(int id, int tag) { + YahooLocalAccount *account = np->getAccount(id); + if (!account) { + return; + } + + if (account->handlers.find(tag) == account->handlers.end()) { + return; + } + + YahooHandler *handler = account->handlers[tag]; + handler->remove_later = true; +} + +static int ext_yahoo_write(void *fd, char *buf, int len) { + int conn_tag = (unsigned long) fd; + YahooLocalAccount *account = currently_writting_account; + + std::string string(buf, len); + account->conns[conn_tag]->write(Swift::createSafeByteArray(string)); + + return len; +} + +static int ext_yahoo_read(void *fd, char *buf, int len) { + if (currently_read_data->size() < len) { + len = currently_read_data->size(); + } + memcpy(buf, currently_read_data->c_str(), len); + currently_read_data->erase(0, len); + return len; +} + +static void ext_yahoo_close(void *fd) { + // No need to do anything here. We close it properly in _yahoo_disconnected(...); +} + +static int ext_yahoo_connect_async(int id, const char *host, int port, yahoo_connect_callback callback, void *data, int use_ssl) { + return np->_yahoo_connect_async(id, host, port, callback, data, use_ssl); +} + +static void ext_yahoo_got_file(int id, const char *me, const char *who, const char *msg, const char *fname, unsigned long fesize, char *trid) { +} + +static void ext_yahoo_file_transfer_done(int id, int response, void *data) { +} + +static char *ext_yahoo_get_ip_addr(const char *domain) { + return NULL; +} + +static void ext_yahoo_got_ft_data(int id, const unsigned char *in, int count, void *data) { +} + +static void ext_yahoo_got_identities(int id, YList * ids) { +} + +static void ext_yahoo_chat_yahoologout(int id, const char *me) { +} + +static void ext_yahoo_chat_yahooerror(int id, const char *me) { +} + +static void ext_yahoo_got_ping(int id, const char *errormsg){ +} + +static void ext_yahoo_got_search_result(int id, int found, int start, int total, YList *contacts) { +} + +static void ext_yahoo_got_buddyicon_checksum(int id, const char *a, const char *b, int checksum) { + LOG4CXX_INFO(logger, "got buddyicon_checksum"); +} + +static void ext_yahoo_got_buddy_change_group(int id, const char *me, const char *who, const char *old_group, const char *new_group) { +} + +static void ext_yahoo_got_buddyicon(int id, const char *me, const char *who, const char *url, int checksum) { + YahooLocalAccount *account = np->getAccount(id); + if (!account) { + return; + } + + LOG4CXX_INFO(logger, account->user << ": got buddyicon of " << who); + account->urls[who] = url; +} + +static void ext_yahoo_buddyicon_uploaded(int id, const char *url) { +} + +static void ext_yahoo_got_buddyicon_request(int id, const char *me, const char *who) { + LOG4CXX_INFO(logger, "got buddyicon_request"); +} + +static int ext_yahoo_log(const char *fmt,...) +{ + static char log[8192]; + static std::string buffered; + va_list ap; + + va_start(ap, fmt); + + vsnprintf(log, 8191, fmt, ap); + buffered += log; + if (buffered.find('\n') != std::string::npos) { + buffered.erase(buffered.find('\n'), 1); + LOG4CXX_INFO(logger, buffered); + buffered.clear(); + } + fflush(stderr); + va_end(ap); + return 0; +} + +static void register_callbacks() +{ + static struct yahoo_callbacks yc; + + yc.ext_yahoo_login_response = ext_yahoo_login_response; + yc.ext_yahoo_got_buddies = ext_yahoo_got_buddies; + yc.ext_yahoo_got_ignore = ext_yahoo_got_ignore; + yc.ext_yahoo_got_identities = ext_yahoo_got_identities; + yc.ext_yahoo_got_cookies = ext_yahoo_got_cookies; + yc.ext_yahoo_status_changed = ext_yahoo_status_changed; + yc.ext_yahoo_got_im = ext_yahoo_got_im; + yc.ext_yahoo_got_buzz = ext_yahoo_got_buzz; + yc.ext_yahoo_got_conf_invite = ext_yahoo_got_conf_invite; + yc.ext_yahoo_conf_userdecline = ext_yahoo_conf_userdecline; + yc.ext_yahoo_conf_userjoin = ext_yahoo_conf_userjoin; + yc.ext_yahoo_conf_userleave = ext_yahoo_conf_userleave; + yc.ext_yahoo_conf_message = ext_yahoo_conf_message; + yc.ext_yahoo_chat_cat_xml = ext_yahoo_chat_cat_xml; + yc.ext_yahoo_chat_join = ext_yahoo_chat_join; + yc.ext_yahoo_chat_userjoin = ext_yahoo_chat_userjoin; + yc.ext_yahoo_chat_userleave = ext_yahoo_chat_userleave; + yc.ext_yahoo_chat_message = ext_yahoo_chat_message; + yc.ext_yahoo_chat_yahoologout = ext_yahoo_chat_yahoologout; + yc.ext_yahoo_chat_yahooerror = ext_yahoo_chat_yahooerror; + yc.ext_yahoo_got_webcam_image = ext_yahoo_got_webcam_image; + yc.ext_yahoo_webcam_invite = ext_yahoo_webcam_invite; + yc.ext_yahoo_webcam_invite_reply = ext_yahoo_webcam_invite_reply; + yc.ext_yahoo_webcam_closed = ext_yahoo_webcam_closed; + yc.ext_yahoo_webcam_viewer = ext_yahoo_webcam_viewer; + yc.ext_yahoo_webcam_data_request = ext_yahoo_webcam_data_request; + yc.ext_yahoo_got_file = ext_yahoo_got_file; + yc.ext_yahoo_got_ft_data = ext_yahoo_got_ft_data; + yc.ext_yahoo_get_ip_addr = ext_yahoo_get_ip_addr; + yc.ext_yahoo_file_transfer_done = ext_yahoo_file_transfer_done; + yc.ext_yahoo_contact_added = ext_yahoo_contact_added; + yc.ext_yahoo_rejected = ext_yahoo_rejected; + yc.ext_yahoo_typing_notify = ext_yahoo_typing_notify; + yc.ext_yahoo_game_notify = ext_yahoo_game_notify; + yc.ext_yahoo_mail_notify = ext_yahoo_mail_notify; + yc.ext_yahoo_got_search_result = ext_yahoo_got_search_result; + yc.ext_yahoo_system_message = ext_yahoo_system_message; + yc.ext_yahoo_error = ext_yahoo_error; + yc.ext_yahoo_log = ext_yahoo_log; + yc.ext_yahoo_add_handler = ext_yahoo_add_handler; + yc.ext_yahoo_remove_handler = ext_yahoo_remove_handler; + yc.ext_yahoo_connect = ext_yahoo_connect; + yc.ext_yahoo_connect_async = ext_yahoo_connect_async; + yc.ext_yahoo_read = ext_yahoo_read; + yc.ext_yahoo_write = ext_yahoo_write; + yc.ext_yahoo_close = ext_yahoo_close; + yc.ext_yahoo_got_buddyicon = ext_yahoo_got_buddyicon; + yc.ext_yahoo_got_buddyicon_checksum = ext_yahoo_got_buddyicon_checksum; + yc.ext_yahoo_buddyicon_uploaded = ext_yahoo_buddyicon_uploaded; + yc.ext_yahoo_got_buddyicon_request = ext_yahoo_got_buddyicon_request; + yc.ext_yahoo_got_ping = ext_yahoo_got_ping; + yc.ext_yahoo_got_buddy_change_group = ext_yahoo_got_buddy_change_group; + + yahoo_register_callbacks(&yc); +} + +int main (int argc, char* argv[]) { + std::string host; + int port; + + if (signal(SIGCHLD, spectrum_sigchld_handler) == SIG_ERR) { + std::cout << "SIGCHLD handler can't be set\n"; + return -1; + } + + boost::program_options::options_description desc("Usage: spectrum [OPTIONS] \nAllowed options"); + desc.add_options() + ("host,h", value(&host), "host") + ("port,p", value(&port), "port") + ; + try + { + boost::program_options::variables_map vm; + boost::program_options::store(boost::program_options::parse_command_line(argc, argv, desc), vm); + boost::program_options::notify(vm); + } + catch (std::runtime_error& e) + { + std::cout << desc << "\n"; + exit(1); + } + catch (...) + { + std::cout << desc << "\n"; + exit(1); + } + + + if (argc < 5) { + return 1; + } + + Config config; + if (!config.load(argv[5])) { + std::cerr << "Can't open " << argv[1] << " configuration file.\n"; + return 1; + } + + Logging::initBackendLogging(&config); + + register_callbacks(); + yahoo_set_log_level(YAHOO_LOG_DEBUG); + + Swift::SimpleEventLoop eventLoop; + loop_ = &eventLoop; + np = new YahooPlugin(&config, &eventLoop, host, port); + loop_->run(); + + return 0; +} diff --git a/backends/libyahoo2/sample_client.example b/backends/libyahoo2/sample_client.example new file mode 100644 index 0000000000000000000000000000000000000000..78d508ce4946c81396e3749b9696e201d60cf13d --- /dev/null +++ b/backends/libyahoo2/sample_client.example @@ -0,0 +1,1898 @@ +/* + * sample yahoo client based on libyahoo2 + * + * libyahoo2 is available at http://libyahoo2.sourceforge.net/ + * + * $Revision: 373 $ + * $Date: 2010-06-02 13:55:25 -0700 (Wed, 02 Jun 2010) $ + * + * Copyright (C) 2002-2004, Philip S Tellis + * Copyright (C) 2009, Siddhesh Poyarekar + * + * 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 + * + */ + +#if HAVE_CONFIG_H +# include +#endif +#ifndef _WIN32 +#include +#include +#endif +#include +#ifndef _WIN32 +#include +#include +#include + +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if HAVE_UNISTD_H +#include +#endif + +/* Get these from http://libyahoo2.sourceforge.net/ */ +#include +#include +#include "yahoo_util.h" + +#ifndef _WIN32 +int fileno(FILE * stream); +#endif + +#define MAX_PREF_LEN 255 + +static char *local_host = NULL; + +static int do_mail_notify = 0; +static int do_yahoo_debug = 0; +static int ignore_system = 0; +static int do_typing_notify = 1; +static int accept_webcam_viewers = 1; +static int send_webcam_images = 0; +static int webcam_direction = YAHOO_WEBCAM_DOWNLOAD; +static time_t curTime = 0; +static time_t pingTimer = 0; +static time_t webcamTimer = 0; +static double webcamStart = 0; + +/* id of the webcam connection (needed for uploading) */ +static int webcam_id = 0; + +static int poll_loop=1; + +static void register_callbacks(); + +typedef struct { + char yahoo_id[255]; + char password[255]; + int id; + int fd; + int status; + char *msg; +} yahoo_local_account; + +typedef struct { + char yahoo_id[255]; + char name[255]; + int status; + int away; + char *msg; + char group[255]; +} yahoo_account; + +typedef struct { + int id; + char *label; +} yahoo_idlabel; + +typedef struct { + int id; + char *who; +} yahoo_authorize_data; + +yahoo_idlabel yahoo_status_codes[] = { + {YAHOO_STATUS_AVAILABLE, "Available"}, + {YAHOO_STATUS_BRB, "BRB"}, + {YAHOO_STATUS_BUSY, "Busy"}, + {YAHOO_STATUS_NOTATHOME, "Not Home"}, + {YAHOO_STATUS_NOTATDESK, "Not at Desk"}, + {YAHOO_STATUS_NOTINOFFICE, "Not in Office"}, + {YAHOO_STATUS_ONPHONE, "On Phone"}, + {YAHOO_STATUS_ONVACATION, "On Vacation"}, + {YAHOO_STATUS_OUTTOLUNCH, "Out to Lunch"}, + {YAHOO_STATUS_STEPPEDOUT, "Stepped Out"}, + {YAHOO_STATUS_INVISIBLE, "Invisible"}, + {YAHOO_STATUS_IDLE, "Idle"}, + {YAHOO_STATUS_OFFLINE, "Offline"}, + {YAHOO_STATUS_CUSTOM, "[Custom]"}, + {YPACKET_STATUS_NOTIFY, "Notify"}, + {0, NULL} +}; + +static void ext_yahoo_close(void *fd); + +char * yahoo_status_code(enum yahoo_status s) +{ + int i; + for(i=0; yahoo_status_codes[i].label; i++) + if(yahoo_status_codes[i].id == s) + return yahoo_status_codes[i].label; + return "Unknown"; +} + +#define YAHOO_DEBUGLOG ext_yahoo_log + +static int ext_yahoo_log(const char *fmt,...) +{ + va_list ap; + + va_start(ap, fmt); + + vfprintf(stderr, fmt, ap); + fflush(stderr); + va_end(ap); + return 0; +} + +#define LOG(x) if(do_yahoo_debug) { YAHOO_DEBUGLOG("%s:%d: ", __FILE__, __LINE__); \ + YAHOO_DEBUGLOG x; \ + YAHOO_DEBUGLOG("\n"); } + +#define WARNING(x) if(do_yahoo_debug) { YAHOO_DEBUGLOG("%s:%d: warning: ", __FILE__, __LINE__); \ + YAHOO_DEBUGLOG x; \ + YAHOO_DEBUGLOG("\n"); } + +#define print_message(x) { printf x; printf("\n"); } + +static yahoo_local_account * ylad = NULL; +static YList * buddies = NULL; + +static int expired(time_t timer) +{ + if (timer && curTime >= timer) + return 1; + + return 0; +} + +static void rearm(time_t *timer, int seconds) +{ + time(timer); + *timer += seconds; +} + +#ifndef _WIN32 +FILE *popen(const char *command, const char *type); +int pclose(FILE *stream); +int gethostname(char *name, size_t len); +#endif + +static char * get_local_addresses() +{ + static char addresses[1024]; + char buff[1024]; + struct hostent * hn; +#ifndef _WIN32 + char gateway[16]; + char * c; + int i; + FILE * f; + f = popen("netstat -nr", "r"); + if(!f) + goto IP_TEST_2; + while( fgets(buff, sizeof(buff), f) != NULL ) { + c = strtok( buff, " " ); + if( (strstr(c, "default") || strstr(c,"0.0.0.0") ) && + !strstr(c, "127.0.0" ) ) + break; + } + c = strtok( NULL, " " ); + pclose(f); + + strncpy(gateway,c, 16); + + + + for(i = strlen(gateway); gateway[i] != '.'; i-- ) + gateway[i] = 0; + + gateway[i] = 0; + + for(i = strlen(gateway); gateway[i] != '.'; i-- ) + gateway[i] = 0; + + f = popen("/sbin/ifconfig -a", "r"); + if(!f) + goto IP_TEST_2; + + while( fgets(buff, sizeof(buff), f) != NULL ) { + if( strstr(buff, "inet") && strstr(buff,gateway) ) + break; + } + pclose(f); + + c = strtok( buff, " " ); + c = strtok( NULL, " " ); + + strncpy ( addresses, c, sizeof(addresses) ); + c = strtok(addresses, ":" ); + strncpy ( buff, c, sizeof(buff) ); + if((c=strtok(NULL, ":"))) + strncpy( buff, c, sizeof(buff) ); + + strncpy(addresses, buff, sizeof(addresses)); + + return addresses; + + +IP_TEST_2: +#endif /* _WIN32 */ + + gethostname(buff,sizeof(buff)); + + hn = gethostbyname(buff); + if(hn) + strncpy(addresses, inet_ntoa( *((struct in_addr*)hn->h_addr)), sizeof(addresses) ); + else + addresses[0] = 0; + + return addresses; +} + +static double get_time() +{ +#ifndef _WIN32 + struct timeval ct; + gettimeofday(&ct, 0); + + /* return time in milliseconds */ + return (ct.tv_sec * 1E3 + ct.tv_usec / 1E3); +#else + return timeGetTime(); +#endif +} + +static int yahoo_ping_timeout_callback() +{ + print_message(("Sending a keep alive message")); + yahoo_keepalive(ylad->id); + rearm(&pingTimer, 600); + return 1; +} + +static int yahoo_webcam_timeout_callback(int id) +{ + static unsigned image_num = 0; + unsigned char *image = NULL; + unsigned int length = 0; + unsigned int timestamp = get_time() - webcamStart; + char fname[1024]; + FILE *f_image = NULL; + struct stat s_image; + + if (send_webcam_images) + { + sprintf(fname, "images/image_%.3d.jpc", image_num++); + if (image_num > 999) image_num = 0; + if (stat(fname, &s_image) == -1) + return -1; + length = s_image.st_size; + image = y_new0(unsigned char, length); + + if ((f_image = fopen(fname, "r")) != NULL) { + fread(image, length, 1, f_image); + fclose(f_image); + } else { + printf("Error reading from %s\n", fname); + } + } + + print_message(("Sending a webcam image (%d bytes)", length)); + yahoo_webcam_send_image(id, image, length, timestamp); + FREE(image); + rearm(&webcamTimer, 2); + return 1; +} + +YList * conferences = NULL; +typedef struct { + int id; + char * me; + char * room_name; + char * host; + YList * members; + int joined; +} conf_room; + +static const char * get_buddy_name(const char * yid) +{ + YList * b; + for (b = buddies; b; b = b->next) { + yahoo_account * ya = b->data; + if(!strcmp(yid, ya->yahoo_id)) + return ya->name&&*ya->name?ya->name:ya->yahoo_id; + } + + return yid; +} + +static conf_room * find_conf_room_by_name_and_id(int id, const char * me, const char * name) +{ + YList * l; + for(l = conferences; l; l=l->next) { + conf_room * cr = l->data; + if(cr->id == id && !strcmp(name, cr->room_name) && (me == NULL || cr->me == NULL || !strcmp(me, cr->me))) { + return cr; + } + } + + return NULL; +} + +static void ext_yahoo_got_conf_invite(int id, const char *me, const char *who, const char *room, const char *msg, YList *members) +{ + conf_room * cr = y_new0(conf_room, 1); + cr->room_name = strdup(room); + cr->me = strdup(me); + cr->host = strdup(who); + cr->members = members; + cr->id = id; + + conferences = y_list_append(conferences, cr); + + print_message(("%s has invited you [%s] to a conference: %s\n" + "with the message: %s", + who, me, room, msg)); + + for(; members; members=members->next) + print_message(("\t%s", (char *)members->data)); + +} +static void ext_yahoo_conf_userdecline(int id, const char *me, const char *who, const char *room, const char *msg) +{ + YList * l; + /* TODO: probably have to use the me arg to find the room */ + conf_room * cr = find_conf_room_by_name_and_id(id, me, room); + + if(cr) + for(l = cr->members; l; l=l->next) { + char * w = l->data; + if(!strcmp(w, who)) { + FREE(l->data); + cr->members = y_list_remove_link(cr->members, l); + y_list_free_1(l); + break; + } + } + + print_message(("%s declined the invitation from %s to %s\n" + "with the message: %s", who, me, room, msg)); +} + +static void ext_yahoo_conf_userjoin(int id, const char *me, const char *who, const char *room) +{ + conf_room * cr = find_conf_room_by_name_and_id(id, me, room); + if(cr) { + YList * l = NULL; + for(l = cr->members; l; l=l->next) { + char * w = l->data; + if(!strcmp(w, who)) + break; + } + if(!l) + cr->members = y_list_append(cr->members, strdup(who)); + } + + print_message(("%s joined the conference %s [%s]", who, room, me)); + +} + +static void ext_yahoo_conf_userleave(int id, const char *me, const char *who, const char *room) +{ + YList * l; + conf_room * cr = find_conf_room_by_name_and_id(id, me, room); + + if(cr) + for(l = cr->members; l; l=l->next) { + char * w = l->data; + if(!strcmp(w, who)) { + FREE(l->data); + cr->members = y_list_remove_link(cr->members, l); + y_list_free_1(l); + break; + } + } + + print_message(("%s left the conference %s [%s]", who, room, me)); +} + +static void ext_yahoo_conf_message(int id, const char *me, const char *who, const char *room, const char *msg, int utf8) +{ + char * umsg = (char *)msg; + + if(utf8) + umsg = y_utf8_to_str(msg); + + who = get_buddy_name(who); + + print_message(("%s (in %s [%s]): %s", who, room, me, umsg)); + + if(utf8) + FREE(umsg); +} + +static void print_chat_member(struct yahoo_chat_member *ycm) +{ + printf("%s (%s) ", ycm->id, ycm->alias); + printf(" Age: %d Sex: ", ycm->age); + if (ycm->attribs & YAHOO_CHAT_MALE) { + printf("Male"); + } else if (ycm->attribs & YAHOO_CHAT_FEMALE) { + printf("Female"); + } else { + printf("Unknown"); + } + if (ycm->attribs & YAHOO_CHAT_WEBCAM) { + printf(" with webcam"); + } + + printf(" Location: %s", ycm->location); +} + +static void ext_yahoo_chat_cat_xml(int id, const char *xml) +{ + print_message(("%s", xml)); +} + +static void ext_yahoo_chat_join(int id, const char *me, const char *room, const char * topic, YList *members, void *fd) +{ + print_message(("You [%s] have joined the chatroom %s with topic %s", me, room, topic)); + + while(members) { + YList *n = members->next; + + printf("\t"); + print_chat_member(members->data); + printf("\n"); + FREE(((struct yahoo_chat_member *)members->data)->id); + FREE(((struct yahoo_chat_member *)members->data)->alias); + FREE(((struct yahoo_chat_member *)members->data)->location); + FREE(members->data); + FREE(members); + members=n; + } +} + +static void ext_yahoo_chat_userjoin(int id, const char *me, const char *room, struct yahoo_chat_member *who) +{ + print_chat_member(who); + print_message((" joined the chatroom %s [%s]", room, me)); + FREE(who->id); + FREE(who->alias); + FREE(who->location); + FREE(who); +} + +static void ext_yahoo_chat_userleave(int id, const char *me, const char *room, const char *who) +{ + print_message(("%s left the chatroom %s [%s]", who, room, me)); +} + +static void ext_yahoo_chat_message(int id, const char *me, const char *who, const char *room, const char *msg, int msgtype, int utf8) +{ + char * umsg = (char *)msg; + char * charpos; + + if(utf8) + umsg = y_utf8_to_str(msg); + /* Remove escapes */ + charpos = umsg; + while(*charpos) { + if (*charpos == 0x1b) { + *charpos = ' '; + } + charpos++; + } + + if (msgtype == 2) { + print_message(("(in %s [%s]) %s %s", room, me, who, umsg)); + } else { + print_message(("(in %s [%s]) %s: %s", room, me, who, umsg)); + } + + if(utf8) + FREE(umsg); +} + +static void ext_yahoo_status_changed(int id, const char *who, int stat, const char *msg, int away, int idle, int mobile) +{ + yahoo_account * ya=NULL; + YList * b; + char buf[1024]; + + for(b = buddies; b; b = b->next) { + if(!strcmp(((yahoo_account *)b->data)->yahoo_id, who)) { + ya = b->data; + break; + } + } + + if (msg == NULL) { + sprintf(buf, "%s", yahoo_status_code(stat)); + } + else if (stat == YAHOO_STATUS_CUSTOM) { + sprintf(buf, "%s", msg); + } else { + sprintf(buf, "%s: %s", yahoo_status_code(stat), msg); + } + + if (away > 0) { + char away_buf[32]; + sprintf(away_buf, " away[%d]", away); + strcat(buf, away_buf); + } + + if (mobile > 0) { + char mobile_buf[32]; + sprintf(mobile_buf, " mobile[%d]", mobile); + strcat(buf, mobile_buf); + } + + if (idle > 0) { + char time_buf[32]; + sprintf(time_buf, " idle for %d:%02d:%02d", idle/3600, (idle/60)%60, idle%60); + strcat(buf, time_buf); + } + + print_message(("%s (%s) is now %s", ya?ya->name:who, who, buf)) + + if(ya) { + ya->status = stat; + ya->away = away; + if(msg) { + FREE(ya->msg); + ya->msg = strdup(msg); + } + } +} + +static void ext_yahoo_got_buddies(int id, YList * buds) +{ + while(buddies) { + FREE(buddies->data); + buddies = buddies->next; + if(buddies) + FREE(buddies->prev); + } + for(; buds; buds = buds->next) { + yahoo_account *ya = y_new0(yahoo_account, 1); + struct yahoo_buddy *bud = buds->data; + strncpy(ya->yahoo_id, bud->id, 255); + if(bud->real_name) + strncpy(ya->name, bud->real_name, 255); + strncpy(ya->group, bud->group, 255); + ya->status = YAHOO_STATUS_OFFLINE; + buddies = y_list_append(buddies, ya); + +/* print_message(("%s is %s", bud->id, bud->real_name));*/ + } +} + +static void ext_yahoo_got_ignore(int id, YList * igns) +{ +} + +static void ext_yahoo_got_buzz(int id, const char *me, const char *who, long tm) +{ + who = get_buddy_name(who); + + printf("\a"); + if(tm) { + char timestr[255]; + + strncpy(timestr, ctime((time_t *)&tm), sizeof(timestr)); + timestr[strlen(timestr) - 1] = '\0'; + + print_message(("[Offline message at %s to %s from %s]: **DING**", + timestr, me, who)) + } else + print_message(("[%s]%s: **DING**", me, who)) +} + +static void ext_yahoo_got_im(int id, const char *me, const char *who, const char *msg, long tm, int stat, int utf8) +{ + char *umsg = (char *)msg; + + if(stat == 2) { + LOG(("Error sending message from %s to %s", me, who)); + return; + } + + if(!msg) + return; + + if(utf8) + umsg = y_utf8_to_str(msg); + + who = get_buddy_name(who); + + if(tm) { + char timestr[255]; + + strncpy(timestr, ctime((time_t *)&tm), sizeof(timestr)); + timestr[strlen(timestr) - 1] = '\0'; + + print_message(("[Offline message at %s to %s from %s]: %s", + timestr, me, who, umsg)) + } else + print_message(("[%s]%s: %s", me, who, umsg)) + + if(utf8) + FREE(umsg); +} + +static void ext_yahoo_rejected(int id, const char *who, const char *msg) +{ + print_message(("%s has rejected you%s%s", who, + (msg?" with the message:\n":"."), + (msg?msg:""))); +} + +static void ext_yahoo_contact_added(int id, const char *myid, const char *who, const char *msg) +{ + char buff[1024]; + + snprintf(buff, sizeof(buff), "%s, the yahoo user %s has added you to their contact list", myid, who); + if(msg) { + strcat(buff, " with the following message:\n"); + strcat(buff, msg); + strcat(buff, "\n"); + } else { + strcat(buff, ". "); + } + strcat(buff, "Do you want to allow this [Y/N]?"); + +/* print_message((buff)); + scanf("%c", &choice); + if(choice != 'y' && choice != 'Y') + yahoo_reject_buddy(id, who, "Thanks, but no thanks."); +*/ +} + +static void ext_yahoo_typing_notify(int id, const char* me, const char *who, int stat) +{ + if(stat && do_typing_notify) + print_message(("[%s]%s is typing...", me, who)); +} + +static void ext_yahoo_game_notify(int id, const char *me, const char *who, int stat, const char *msg) +{ +} + +static void ext_yahoo_mail_notify(int id, const char *from, const char *subj, int cnt) +{ + char buff[1024] = {0}; + + if(!do_mail_notify) + return; + + if(from && subj) + snprintf(buff, sizeof(buff), + "You have new mail from %s about %s\n", + from, subj); + if(cnt) { + char buff2[100]; + snprintf(buff2, sizeof(buff2), + "You have %d message%s\n", + cnt, cnt==1?"":"s"); + strcat(buff, buff2); + } + + if(buff[0]) + print_message((buff)); +} + +static void ext_yahoo_got_webcam_image(int id, const char *who, + const unsigned char *image, unsigned int image_size, unsigned int real_size, + unsigned int timestamp) +{ + static unsigned char *cur_image = NULL; + static unsigned int cur_image_len = 0; + static unsigned int image_num = 0; + FILE* f_image; + char fname[1024]; + + /* copy image part to cur_image */ + if (real_size) + { + if (!cur_image) cur_image = y_new0(unsigned char, image_size); + memcpy(cur_image + cur_image_len, image, real_size); + cur_image_len += real_size; + } + + if (image_size == cur_image_len) + { + print_message(("Received a image update at %d (%d bytes)", + timestamp, image_size)); + + /* if we recieved an image then write it to file */ + if (image_size) + { + sprintf(fname, "images/%s_%.3d.jpc", who, image_num++); + + if ((f_image = fopen(fname, "w")) != NULL) { + fwrite(cur_image, image_size, 1, f_image); + fclose(f_image); + } else { + printf("Error writing to %s\n", fname); + } + FREE(cur_image); + cur_image_len = 0; + if (image_num > 999) image_num = 0; + } + } +} + +static void ext_yahoo_webcam_viewer(int id, const char *who, int connect) +{ + switch (connect) + { + case 0: + print_message(("%s has stopped viewing your webcam", who)); + break; + case 1: + print_message(("%s has started viewing your webcam", who)); + break; + case 2: + print_message(("%s is trying to view your webcam", who)); + yahoo_webcam_accept_viewer(id, who, accept_webcam_viewers); + break; + } +} + +static void ext_yahoo_webcam_closed(int id, const char *who, int reason) +{ + switch(reason) + { + case 1: + print_message(("%s stopped broadcasting", who)); + break; + case 2: + print_message(("%s cancelled viewing permission", who)); + break; + case 3: + print_message(("%s declines permission to view his/her webcam", who)); + break; + case 4: + print_message(("%s does not have his/her webcam online", who)); + break; + } +} + +static void ext_yahoo_webcam_data_request(int id, int send) +{ + webcam_id = id; + + if (send) { + print_message(("Got request to start sending images")); + if (!webcamTimer) + rearm(&webcamTimer, 2); + } else { + print_message(("Got request to stop sending images")); + } + send_webcam_images = send; +} + +static void ext_yahoo_webcam_invite(int id, const char *me, const char *from) +{ + print_message(("Got a webcam invitation to %s from %s", me, from)); +} + +static void ext_yahoo_webcam_invite_reply(int id, const char *me, const char *from, int accept) +{ + if(accept) { + print_message(("[%s]%s accepted webcam invitation...", me, from)); + } else { + print_message(("[%s]%s declined webcam invitation...", me, from)); + } +} + +static void ext_yahoo_system_message(int id, const char *me, const char *who, const char *msg) +{ + if(ignore_system) + return; + + print_message(("Yahoo System Message: %s", msg)); +} + +void yahoo_logout() +{ + if (ylad->id <= 0) { + return; + } + + pingTimer=0; + + while(conferences) { + YList * n = conferences->next; + conf_room * cr = conferences->data; + if(cr->joined) + yahoo_conference_logoff(ylad->id, NULL, cr->members, cr->room_name); + FREE(cr->me); + FREE(cr->room_name); + FREE(cr->host); + while(cr->members) { + YList *n = cr->members->next; + FREE(cr->members->data); + FREE(cr->members); + cr->members=n; + } + FREE(cr); + FREE(conferences); + conferences = n; + } + + yahoo_logoff(ylad->id); + yahoo_close(ylad->id); + + ylad->status = YAHOO_STATUS_OFFLINE; + ylad->id = 0; + + poll_loop=0; + + print_message(("logged_out")); +} + +static void ext_yahoo_login(yahoo_local_account * ylad, int login_mode) +{ + LOG(("ext_yahoo_login")); + + ylad->id = yahoo_init_with_attributes(ylad->yahoo_id, ylad->password, + "local_host", local_host, + "pager_port", 5050, + NULL); + ylad->status = YAHOO_STATUS_OFFLINE; + yahoo_login(ylad->id, login_mode); + +/* if (ylad->id <= 0) { + print_message(("Could not connect to Yahoo server. Please verify that you are connected to the net and the pager host and port are correctly entered.")); + return; + } +*/ + rearm(&pingTimer, 600); +} + +static void ext_yahoo_got_cookies(int id) +{ + /*yahoo_get_yab(id);*/ +} + +static void ext_yahoo_login_response(int id, int succ, const char *url) +{ + char buff[1024]; + + if(succ == YAHOO_LOGIN_OK) { + ylad->status = yahoo_current_status(id); + print_message(("logged in")); + return; + + } else if(succ == YAHOO_LOGIN_UNAME) { + + snprintf(buff, sizeof(buff), "Could not log into Yahoo service - username not recognised. Please verify that your username is correctly typed."); + } else if(succ == YAHOO_LOGIN_PASSWD) { + + snprintf(buff, sizeof(buff), "Could not log into Yahoo service - password incorrect. Please verify that your password is correctly typed."); + + } else if(succ == YAHOO_LOGIN_LOCK) { + + snprintf(buff, sizeof(buff), "Could not log into Yahoo service. Your account has been locked.\nVisit %s to reactivate it.", url); + + } else if(succ == YAHOO_LOGIN_DUPL) { + + snprintf(buff, sizeof(buff), "You have been logged out of the yahoo service, possibly due to a duplicate login."); + } else if(succ == YAHOO_LOGIN_SOCK) { + + snprintf(buff, sizeof(buff), "The server closed the socket."); + } else { + snprintf(buff, sizeof(buff), "Could not log in, unknown reason: %d.", succ); + } + + ylad->status = YAHOO_STATUS_OFFLINE; + print_message((buff)); + yahoo_logout(); + poll_loop=0; +} + +static void ext_yahoo_error(int id, const char *err, int fatal, int num) +{ + fprintf(stdout, "Yahoo Error: "); + fprintf(stdout, "%s", err); + switch(num) { + case E_UNKNOWN: + fprintf(stdout, "unknown error %s", err); + break; + case E_CUSTOM: + fprintf(stdout, "custom error %s", err); + break; + case E_CONFNOTAVAIL: + fprintf(stdout, "%s is not available for the conference", err); + break; + case E_IGNOREDUP: + fprintf(stdout, "%s is already ignored", err); + break; + case E_IGNORENONE: + fprintf(stdout, "%s is not in the ignore list", err); + break; + case E_IGNORECONF: + fprintf(stdout, "%s is in buddy list - cannot ignore ", err); + break; + case E_SYSTEM: + fprintf(stdout, "system error %s", err); + break; + case E_CONNECTION: + fprintf(stdout, "server connection error %s", err); + break; + } + fprintf(stdout, "\n"); + if(fatal) + yahoo_logout(); +} + +void yahoo_set_current_state(int yahoo_state) +{ + if (ylad->status == YAHOO_STATUS_OFFLINE && yahoo_state != YAHOO_STATUS_OFFLINE) { + ext_yahoo_login(ylad, yahoo_state); + return; + } else if (ylad->status != YAHOO_STATUS_OFFLINE && yahoo_state == YAHOO_STATUS_OFFLINE) { + yahoo_logout(); + return; + } + + ylad->status = yahoo_state; + if(yahoo_state == YAHOO_STATUS_CUSTOM) { + if(ylad->msg) + yahoo_set_away(ylad->id, yahoo_state, ylad->msg, 1); + else + yahoo_set_away(ylad->id, yahoo_state, "delta p * delta x too large", 1); + } else + yahoo_set_away(ylad->id, yahoo_state, NULL, 1); +} + +static int ext_yahoo_connect(const char *host, int port) +{ + WARNING(("This should not be used anymore. File a bug report.")); + return -1; +} + +/************************************* + * Callback handling code starts here + */ +YList *connections = NULL; +struct _conn { + int fd; + SSL *ssl; + int use_ssl; + int remove; +}; + +struct conn_handler { + struct _conn *con; + int id; + int tag; + yahoo_input_condition cond; + int remove; + void *data; +}; + +static int connection_tags=0; + +static int ext_yahoo_add_handler(int id, void *d, yahoo_input_condition cond, void *data) +{ + struct conn_handler *h = y_new0(struct conn_handler, 1); + + h->id = id; + h->tag = ++connection_tags; + h->con = d; + h->cond = cond; + h->data = data; + + LOG(("Add %d(%d) for %d, tag %d", h->con->fd, cond, id, h->tag)); + + connections = y_list_prepend(connections, h); + + return h->tag; +} + +static void ext_yahoo_remove_handler(int id, int tag) +{ + YList *l; + if (!tag) + return; + + for(l = connections; l; l = y_list_next(l)) { + struct conn_handler *c = l->data; + if(c->tag == tag) { + /* don't actually remove it, just mark it for removal */ + /* we'll remove when we start the next poll cycle */ + LOG(("Marking id:%d fd:%p tag:%d for removal", + c->id, c->con, c->tag)); + c->remove = 1; + return; + } + } +} + +static SSL *do_ssl_connect(int fd) +{ + SSL *ssl; + SSL_CTX *ctx; + + LOG(("SSL Handshake")); + + SSL_library_init (); + ctx = SSL_CTX_new(SSLv23_client_method()); + ssl = SSL_new(ctx); + SSL_CTX_free(ctx); + SSL_set_fd(ssl, fd); + + if (SSL_connect(ssl) == 1) + return ssl; + + return NULL; +} + +struct connect_callback_data { + yahoo_connect_callback callback; + void * callback_data; + int id; + int tag; +}; + +static void connect_complete(void *data, struct _conn *source, yahoo_input_condition condition) +{ + struct connect_callback_data *ccd = data; + int error, err_size = sizeof(error); + + ext_yahoo_remove_handler(0, ccd->tag); + getsockopt(source->fd, SOL_SOCKET, SO_ERROR, &error, (socklen_t *)&err_size); + + if(error) + goto err; + + LOG(("Connected fd: %d, error: %d", source->fd, error)); + + if (source->use_ssl) { + source->ssl = do_ssl_connect(source->fd); + + if (!source->ssl) { +err: + LOG(("SSL Handshake Failed!")); + ext_yahoo_close(source); + + ccd->callback(NULL, 0, ccd->callback_data); + FREE(ccd); + return; + } + } + + fcntl(source->fd, F_SETFL, O_NONBLOCK); + + ccd->callback(source, error, ccd->callback_data); + FREE(ccd); +} + +void yahoo_callback(struct conn_handler *c, yahoo_input_condition cond) +{ + int ret=1; + char buff[1024]={0}; + + if(c->id < 0) { + connect_complete(c->data, c->con, cond); + } else { + if(cond & YAHOO_INPUT_READ) + ret = yahoo_read_ready(c->id, c->con, c->data); + if(ret>0 && cond & YAHOO_INPUT_WRITE) + ret = yahoo_write_ready(c->id, c->con, c->data); + + if(ret == -1) + snprintf(buff, sizeof(buff), + "Yahoo read error (%d): %s", errno, strerror(errno)); + else if(ret == 0) + snprintf(buff, sizeof(buff), + "Yahoo read error: Server closed socket"); + + if(buff[0]) + print_message((buff)); + } +} + +static int ext_yahoo_write(void *fd, char *buf, int len) +{ + struct _conn *c = fd; + + if (c->use_ssl) + return SSL_write(c->ssl, buf, len); + else + return write(c->fd, buf, len); +} + +static int ext_yahoo_read(void *fd, char *buf, int len) +{ + struct _conn *c = fd; + + if (c->use_ssl) + return SSL_read(c->ssl, buf, len); + else + return read(c->fd, buf, len); +} + +static void ext_yahoo_close(void *fd) +{ + struct _conn *c = fd; + YList *l; + + if (c->use_ssl) + SSL_free(c->ssl); + + close(c->fd); + c->fd = 0; + + /* Remove all handlers */ + for (l = connections; l; l = y_list_next(l)) { + struct conn_handler *h = l->data; + + if (h->con == c) + h->remove = 1; + } + + c->remove = 1; +} + +static int ext_yahoo_connect_async(int id, const char *host, int port, + yahoo_connect_callback callback, void *data, int use_ssl) +{ + struct sockaddr_in serv_addr; + static struct hostent *server; + int servfd; + struct connect_callback_data * ccd; + int error; + SSL *ssl = NULL; + + struct _conn *c; + + LOG(("Connecting to %s:%d", host, port)); + + if(!(server = gethostbyname(host))) { + errno=h_errno; + return -1; + } + + if((servfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + return -1; + } + + memset(&serv_addr, 0, sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + memcpy(&serv_addr.sin_addr.s_addr, *server->h_addr_list, server->h_length); + serv_addr.sin_port = htons(port); + + c = y_new0(struct _conn, 1); + c->fd = servfd; + c->use_ssl = use_ssl; + + error = connect(servfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)); + + LOG(("Trying to connect: fd:%d error:%d", servfd, error)); + if(!error) { + LOG(("Connected")); + if (use_ssl) { + ssl = do_ssl_connect(servfd); + + if (!ssl) { + LOG(("SSL Handshake Failed!")); + ext_yahoo_close(c); + + callback(NULL, 0, data); + return -1; + } + } + + c->ssl = ssl; + fcntl(c->fd, F_SETFL, O_NONBLOCK); + + callback(c, 0, data); + return 0; + } else if(error == -1 && errno == EINPROGRESS) { + ccd = calloc(1, sizeof(struct connect_callback_data)); + ccd->callback = callback; + ccd->callback_data = data; + ccd->id = id; + + ccd->tag = ext_yahoo_add_handler(-1, c, YAHOO_INPUT_WRITE, ccd); + return ccd->tag; + } else { + if(error == -1) + LOG(("Connection failure: %s", strerror(errno))); + + ext_yahoo_close(c); + + callback(NULL, errno, data); + return -1; + } +} +/* + * Callback handling code ends here + ***********************************/ + +static void process_commands(char *line) +{ + char *cmd, *to, *msg; + + char *tmp, *start; + char *copy = strdup(line); + int yid = 0; + + enum yahoo_status state; + + start = cmd = copy; + tmp = strchr(copy, ' '); + if(tmp) { + *tmp = '\0'; + copy = tmp+1; + } else { + copy = NULL; + } + + if(!strncasecmp(cmd, "MSG", strlen("MSG"))) { + /* send a message */ + to = copy; + tmp = strchr(copy, ' '); + if(tmp) { + *tmp = '\0'; + copy = tmp+1; + } + msg = copy; + if(to && msg) { + if(!strcmp(msg, "\a")) + yahoo_send_im(ylad->id, NULL, to, "", 0,0); + else { + msg = y_str_to_utf8(msg); + yahoo_send_im(ylad->id, NULL, to, msg, 1,0); + FREE(msg) + } + } + } else if(!strncasecmp(cmd, "CMS", strlen("CMS"))) { + /* send a message */ + conf_room * cr; + to = copy; + tmp = strchr(copy, ' '); + if(tmp) { + *tmp = '\0'; + copy = tmp+1; + } + msg = copy; + cr = find_conf_room_by_name_and_id(ylad->id, NULL, to); + if(!cr) { + print_message(("no such room: %s", copy)); + goto end_parse; + } + if(msg) + yahoo_conference_message(ylad->id, NULL, cr->members, to, msg, 0); + } else if(!strncasecmp(cmd, "CLS", strlen("CLS"))) { + YList * l; + if(copy) { + conf_room * cr = find_conf_room_by_name_and_id(ylad->id, NULL, copy); + if(!cr) { + print_message(("no such room: %s", copy)); + goto end_parse; + } + print_message(("Room: %s", copy)); + for(l = cr->members; l; l=l->next) { + print_message(("%s", (char *)l->data)) + } + } else { + print_message(("All Rooms:")); + for(l = conferences; l; l=l->next) { + conf_room * cr = l->data; + print_message(("%s", cr->room_name)); + } + } + + } else if(!strncasecmp(cmd, "CCR", strlen("CCR"))) { + conf_room * cr = y_new0(conf_room, 1); + while((tmp = strchr(copy, ' ')) != NULL) { + *tmp = '\0'; + if(!cr->room_name) + cr->room_name = strdup(copy); + else + cr->members = y_list_append(cr->members, + strdup(copy)); + copy = tmp+1; + } + cr->members = y_list_append(cr->members, strdup(copy)); + + if(!cr->room_name || !cr->members) { + FREE(cr); + } else { + cr->id = ylad->id; + cr->joined = 1; + conferences = y_list_append(conferences, cr); + yahoo_conference_invite(ylad->id, NULL, cr->members, cr->room_name, "Join my conference"); + cr->members = y_list_append(cr->members,strdup(ylad->yahoo_id)); + } + } else if(!strncasecmp(cmd, "CIN", strlen("CIN"))) { + conf_room * cr; + char * room=copy; + YList * l1, *l = NULL; + + while((tmp = strchr(copy, ' ')) != NULL) { + *tmp = '\0'; + copy = tmp+1; + l = y_list_append(l, copy); + } + + cr = find_conf_room_by_name_and_id(ylad->id, NULL, room); + if(!cr) { + print_message(("no such room: %s", room)); + y_list_free(l); + goto end_parse; + } + + for(l1 = l; l1; l1=l1->next) { + char * w = l1->data; + yahoo_conference_addinvite(ylad->id, NULL, w, room, cr->members, "Join my conference"); + cr->members = y_list_append(cr->members, strdup(w)); + } + y_list_free(l); + + } else if(!strncasecmp(cmd, "CLN", strlen("CLN"))) { + conf_room * cr = find_conf_room_by_name_and_id(ylad->id, NULL, copy); + YList * l; + if(!cr) { + print_message(("no such room: %s", copy)); + goto end_parse; + } + + cr->joined = 1; + for(l = cr->members; l; l=l->next) { + char * w = l->data; + if(!strcmp(w, ylad->yahoo_id)) + break; + } + if(!l) + cr->members = y_list_append(cr->members, strdup(ylad->yahoo_id)); + yahoo_conference_logon(ylad->id, NULL, cr->members, copy); + + } else if(!strncasecmp(cmd, "CLF", strlen("CLF"))) { + conf_room * cr = find_conf_room_by_name_and_id(ylad->id, NULL, copy); + + if(!cr) { + print_message(("no such room: %s", copy)); + goto end_parse; + } + + yahoo_conference_logoff(ylad->id, NULL, cr->members, copy); + + conferences = y_list_remove(conferences, cr); + FREE(cr->room_name); + FREE(cr->host); + while(cr->members) { + YList *n = cr->members->next; + FREE(cr->members->data); + FREE(cr->members); + cr->members=n; + } + FREE(cr); + + } else if(!strncasecmp(cmd, "CDC", strlen("CDC"))) { + conf_room * cr; + char * room = copy; + tmp = strchr(copy, ' '); + if(tmp) { + *tmp = '\0'; + copy = tmp+1; + msg = copy; + } else { + msg = "Thanks, but no thanks!"; + } + + cr = find_conf_room_by_name_and_id(ylad->id, NULL, room); + if(!cr) { + print_message(("no such room: %s", room)); + goto end_parse; + } + + yahoo_conference_decline(ylad->id, NULL, cr->members, room,msg); + + conferences = y_list_remove(conferences, cr); + FREE(cr->room_name); + FREE(cr->host); + while(cr->members) { + YList *n = cr->members->next; + FREE(cr->members->data); + FREE(cr->members); + cr->members=n; + } + FREE(cr); + + + } else if(!strncasecmp(cmd, "CHL", strlen("CHL"))) { + int roomid; + roomid = atoi(copy); + yahoo_get_chatrooms(ylad->id, roomid); + } else if(!strncasecmp(cmd, "CHJ", strlen("CHJ"))) { + char *roomid, *roomname; +/* Linux, FreeBSD, Solaris:1 */ +/* 1600326591 */ + roomid = copy; + tmp = strchr(copy, ' '); + if(tmp) { + *tmp = '\0'; + copy = tmp+1; + } + roomname = copy; + if(roomid && roomname) { + yahoo_chat_logon(ylad->id, NULL, roomname, roomid); + } + + } else if(!strncasecmp(cmd, "CHM", strlen("CHM"))) { + char *msg, *roomname; + roomname = copy; + tmp = strstr(copy, " "); + if(tmp) { + *tmp = '\0'; + copy = tmp+2; + } + msg = copy; + if(roomname && msg) { + yahoo_chat_message(ylad->id, NULL, roomname, msg, 1, 0); + } + + } else if(!strncasecmp(cmd, "CHX", strlen("CHX"))) { + yahoo_chat_logoff(ylad->id, NULL); + } else if(!strncasecmp(cmd, "STA", strlen("STA"))) { + if(isdigit(copy[0])) { + state = (enum yahoo_status)atoi(copy); + copy = strchr(copy, ' '); + if(state == 99) { + if(copy) + msg = copy; + else + msg = "delta x * delta p too large"; + } else + msg = NULL; + } else { + state = YAHOO_STATUS_CUSTOM; + msg = copy; + } + + yahoo_set_away(ylad->id, state, msg, 1); + + } else if(!strncasecmp(cmd, "OFF", strlen("OFF"))) { + /* go offline */ + printf("Going offline\n"); + poll_loop=0; + } else if(!strncasecmp(cmd, "IDS", strlen("IDS"))) { + /* print identities */ + const YList * ids = yahoo_get_identities(ylad->id); + printf("Identities: "); + for(; ids; ids = ids->next) + printf("%s, ", (char *)ids->data); + printf("\n"); + } else if(!strncasecmp(cmd, "AID", strlen("AID"))) { + /* activate identity */ + yahoo_set_identity_status(ylad->id, copy, 1); + } else if(!strncasecmp(cmd, "DID", strlen("DID"))) { + /* deactivate identity */ + yahoo_set_identity_status(ylad->id, copy, 0); + } else if(!strncasecmp(cmd, "LST", strlen("LST"))) { + YList * b = buddies; + for(; b; b=b->next) { + yahoo_account * ya = b->data; + if(ya->status == YAHOO_STATUS_OFFLINE) + continue; + if(ya->msg) + print_message(("%s (%s) is now %s", ya->name, ya->yahoo_id, + ya->msg)) + else + print_message(("%s (%s) is now %s", ya->name, ya->yahoo_id, + yahoo_status_code(ya->status))) + } + } else if(!strncasecmp(cmd, "NAM", strlen("NAM"))) { + struct yab * yab; + + to = copy; + tmp = strchr(copy, ' '); + if(tmp) { + *tmp = '\0'; + copy = tmp+1; + } + yid = atoi(copy); + + tmp = strchr(copy, ' '); + if(tmp) { + *tmp = '\0'; + copy = tmp+1; + } + msg = copy; + + if(to && msg) { + yab = y_new0(struct yab, 1); + yab->id = to; + yab->yid = yid; /* Only do this if you have got it from the server */ + yab->nname = msg; + yahoo_set_yab(ylad->id, yab); + FREE(yab); + } + } else if(!strncasecmp(cmd, "WCAM", strlen("WCAM"))) { + if (copy) + { + printf("Viewing webcam (%s)\n", copy); + webcam_direction = YAHOO_WEBCAM_DOWNLOAD; + yahoo_webcam_get_feed(ylad->id, copy); + } else { + printf("Starting webcam\n"); + webcam_direction = YAHOO_WEBCAM_UPLOAD; + yahoo_webcam_get_feed(ylad->id, NULL); + } + } else if(!strncasecmp(cmd, "WINV", strlen("WINV"))) { + printf("Inviting %s to view webcam\n", copy); + yahoo_webcam_invite(ylad->id, copy); + } else { + fprintf(stderr, "Unknown command: %s\n", cmd); + } + +end_parse: + FREE(start); +} + +#ifndef _WIN32 +static void local_input_callback(int source) +{ + char line[1024] = {0}; + int i; + char c; + i=0; c=0; + do { + if(read(source, &c, 1) <= 0) + c='\0'; + if(c == '\r') + continue; + if(c == '\n') + break; + if(c == '\b') { + if(!i) + continue; + c = '\0'; + i--; + } + if(c) { + line[i++] = c; + line[i]='\0'; + } + } while(i<1023 && c != '\n'); + + if(line[0]) + process_commands(line); +} +#else +#include +static void local_input_callback(char c) +{ + static char line[1024] = {0}; + static int line_length = 0; + + if (c == '\b' || (int)c == 127) { + if (line_length > 0) { + _cputs("\b \b"); + line_length--; + } + return; + } + + if (c == '\n' || c == '\r' || c == 3) { + _cputs("\n"); + line[line_length] = 0; + process_commands(line); + line_length = 0; + line[0] = 0; + return; + } + + _putch(c); + line[line_length++] = c; +} +#endif + +int main(int argc, char * argv[]) +{ + int status; + int log_level; + int lfd=0; + + fd_set inp, outp; + struct timeval tv; + +#ifndef _WIN32 + int fd_stdin = fileno(stdin); +#endif + YList *l=connections; + +#ifdef _WIN32 + WSADATA wsa; + if (WSAStartup(MAKEWORD(2,2), &wsa)) + return -1; +#endif + + ylad = y_new0(yahoo_local_account, 1); + + local_host = strdup(get_local_addresses()); + + printf("Yahoo Id: "); + scanf("%s", ylad->yahoo_id); + printf("Password: "); +#ifdef _WIN32 + scanf("%s", ylad->password); +#else + { + tcflag_t oflags; + struct termios term; + tcgetattr(fd_stdin, &term); + oflags = term.c_lflag; + term.c_lflag = oflags & ~(ECHO | ECHOK | ICANON); + term.c_cc[VTIME] = 1; + tcsetattr(fd_stdin, TCSANOW, &term); + + scanf("%s", ylad->password); + + term.c_lflag = oflags; + term.c_cc[VTIME] = 0; + tcsetattr(fd_stdin, TCSANOW, &term); + } + printf("\n"); +#endif + + printf("Initial Status: "); + scanf("%d", &status); + + printf("Log Level: "); + scanf("%d", &log_level); + do_yahoo_debug=log_level; + + register_callbacks(); + yahoo_set_log_level(log_level); + + ext_yahoo_login(ylad, status); + + while(poll_loop) { + FD_ZERO(&inp); + FD_ZERO(&outp); +#ifndef _WIN32 + FD_SET(fd_stdin, &inp); + tv.tv_sec=1; + tv.tv_usec=0; +#else + tv.tv_sec=0; + tv.tv_usec=1E4; +#endif + lfd=0; + + for(l=connections; l; ) { + struct conn_handler *c = l->data; + if(c->remove) { + YList *n = y_list_next(l); + LOG(("Removing id:%d fd:%d", c->id, c->con->fd)); + connections = y_list_remove_link(connections, l); + y_list_free_1(l); + FREE(c); + l=n; + } else { + if(c->cond & YAHOO_INPUT_READ) + FD_SET(c->con->fd, &inp); + if(c->cond & YAHOO_INPUT_WRITE) + FD_SET(c->con->fd, &outp); + if(lfd < c->con->fd) + lfd = c->con->fd; + l = y_list_next(l); + } + } + + select(lfd + 1, &inp, &outp, NULL, &tv); + time(&curTime); + +#ifndef _WIN32 + if(FD_ISSET(fd_stdin, &inp)) local_input_callback(0); +#else + if (_kbhit()) local_input_callback(_getch()); +#endif + + for(l = connections; l; l = y_list_next(l)) { + struct conn_handler *c = l->data; + if(c->con->remove) { + FREE(c->con); + c->con = NULL; + continue; + } + if(c->remove) + continue; + if(FD_ISSET(c->con->fd, &inp)) + yahoo_callback(c, YAHOO_INPUT_READ); + if(FD_ISSET(c->con->fd, &outp)) + yahoo_callback(c, YAHOO_INPUT_WRITE); + } + + if(expired(pingTimer)) yahoo_ping_timeout_callback(); + if(expired(webcamTimer)) yahoo_webcam_timeout_callback(webcam_id); + } + LOG(("Exited loop")); + + while(connections) { + YList *tmp = connections; + struct conn_handler *c = connections->data; + FREE(c); + connections = y_list_remove_link(connections, connections); + y_list_free_1(tmp); + } + + yahoo_logout(); + + FREE(ylad); + +#ifdef _WIN32 + WSACleanup(); +#endif + return 0; +} + +static void ext_yahoo_got_file(int id, const char *me, const char *who, const char *msg, const char *fname, + unsigned long fesize, char *trid) +{ + LOG(("Got a File transfer request (%s, %ld bytes) from %s", fname, fesize, who)); +} + +static void ext_yahoo_file_transfer_done(int id, int response, void *data) +{ +} + +static char *ext_yahoo_get_ip_addr(const char *domain) +{ + return NULL; +} + +static void ext_yahoo_got_ft_data(int id, const unsigned char *in, int count, void *data) +{ +} + +static void ext_yahoo_got_identities(int id, YList * ids) +{ +} + +static void ext_yahoo_chat_yahoologout(int id, const char *me) +{ + LOG(("got chat logout for %s", me)); +} + +static void ext_yahoo_chat_yahooerror(int id, const char *me) +{ + LOG(("got chat error for %s", me)); +} + +static void ext_yahoo_got_ping(int id, const char *errormsg) +{ + LOG(("got ping errormsg %s", errormsg)); +} + +static void ext_yahoo_got_search_result(int id, int found, int start, int total, YList *contacts) +{ + LOG(("got search result")); +} + +static void ext_yahoo_got_buddyicon_checksum(int id, const char *a, const char *b, int checksum) +{ + LOG(("got buddy icon checksum")); +} + +static void ext_yahoo_got_buddy_change_group(int id, const char *me, const char *who, + const char *old_group, const char *new_group) +{ +} + +static void ext_yahoo_got_buddyicon(int id, const char *a, const char *b, const char *c, int checksum) +{ + LOG(("got buddy icon")); +} + +static void ext_yahoo_buddyicon_uploaded(int id, const char *url) +{ + LOG(("buddy icon uploaded")); +} + +static void ext_yahoo_got_buddyicon_request(int id, const char *me, const char *who) +{ + LOG(("got buddy icon request from %s",who)); +} + +static void register_callbacks() +{ + static struct yahoo_callbacks yc; + + yc.ext_yahoo_login_response = ext_yahoo_login_response; + yc.ext_yahoo_got_buddies = ext_yahoo_got_buddies; + yc.ext_yahoo_got_ignore = ext_yahoo_got_ignore; + yc.ext_yahoo_got_identities = ext_yahoo_got_identities; + yc.ext_yahoo_got_cookies = ext_yahoo_got_cookies; + yc.ext_yahoo_status_changed = ext_yahoo_status_changed; + yc.ext_yahoo_got_im = ext_yahoo_got_im; + yc.ext_yahoo_got_buzz = ext_yahoo_got_buzz; + yc.ext_yahoo_got_conf_invite = ext_yahoo_got_conf_invite; + yc.ext_yahoo_conf_userdecline = ext_yahoo_conf_userdecline; + yc.ext_yahoo_conf_userjoin = ext_yahoo_conf_userjoin; + yc.ext_yahoo_conf_userleave = ext_yahoo_conf_userleave; + yc.ext_yahoo_conf_message = ext_yahoo_conf_message; + yc.ext_yahoo_chat_cat_xml = ext_yahoo_chat_cat_xml; + yc.ext_yahoo_chat_join = ext_yahoo_chat_join; + yc.ext_yahoo_chat_userjoin = ext_yahoo_chat_userjoin; + yc.ext_yahoo_chat_userleave = ext_yahoo_chat_userleave; + yc.ext_yahoo_chat_message = ext_yahoo_chat_message; + yc.ext_yahoo_chat_yahoologout = ext_yahoo_chat_yahoologout; + yc.ext_yahoo_chat_yahooerror = ext_yahoo_chat_yahooerror; + yc.ext_yahoo_got_webcam_image = ext_yahoo_got_webcam_image; + yc.ext_yahoo_webcam_invite = ext_yahoo_webcam_invite; + yc.ext_yahoo_webcam_invite_reply = ext_yahoo_webcam_invite_reply; + yc.ext_yahoo_webcam_closed = ext_yahoo_webcam_closed; + yc.ext_yahoo_webcam_viewer = ext_yahoo_webcam_viewer; + yc.ext_yahoo_webcam_data_request = ext_yahoo_webcam_data_request; + yc.ext_yahoo_got_file = ext_yahoo_got_file; + yc.ext_yahoo_got_ft_data = ext_yahoo_got_ft_data; + yc.ext_yahoo_get_ip_addr = ext_yahoo_get_ip_addr; + yc.ext_yahoo_file_transfer_done = ext_yahoo_file_transfer_done; + yc.ext_yahoo_contact_added = ext_yahoo_contact_added; + yc.ext_yahoo_rejected = ext_yahoo_rejected; + yc.ext_yahoo_typing_notify = ext_yahoo_typing_notify; + yc.ext_yahoo_game_notify = ext_yahoo_game_notify; + yc.ext_yahoo_mail_notify = ext_yahoo_mail_notify; + yc.ext_yahoo_got_search_result = ext_yahoo_got_search_result; + yc.ext_yahoo_system_message = ext_yahoo_system_message; + yc.ext_yahoo_error = ext_yahoo_error; + yc.ext_yahoo_log = ext_yahoo_log; + yc.ext_yahoo_add_handler = ext_yahoo_add_handler; + yc.ext_yahoo_remove_handler = ext_yahoo_remove_handler; + yc.ext_yahoo_connect = ext_yahoo_connect; + yc.ext_yahoo_connect_async = ext_yahoo_connect_async; + yc.ext_yahoo_read = ext_yahoo_read; + yc.ext_yahoo_write = ext_yahoo_write; + yc.ext_yahoo_close = ext_yahoo_close; + yc.ext_yahoo_got_buddyicon = ext_yahoo_got_buddyicon; + yc.ext_yahoo_got_buddyicon_checksum = ext_yahoo_got_buddyicon_checksum; + yc.ext_yahoo_buddyicon_uploaded = ext_yahoo_buddyicon_uploaded; + yc.ext_yahoo_got_buddyicon_request = ext_yahoo_got_buddyicon_request; + yc.ext_yahoo_got_ping = ext_yahoo_got_ping; + yc.ext_yahoo_got_buddy_change_group = ext_yahoo_got_buddy_change_group; + + yahoo_register_callbacks(&yc); +} + diff --git a/backends/libyahoo2/yahoo/crypt.c b/backends/libyahoo2/yahoo/crypt.c new file mode 100644 index 0000000000000000000000000000000000000000..9e215d8ae1d61f4ff88455e7bfbe57d04f5cadc6 --- /dev/null +++ b/backends/libyahoo2/yahoo/crypt.c @@ -0,0 +1,208 @@ +/* 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 , 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_CONFIG_H +# include +#endif + +#if HAVE_STRING_H +# include +#elif HAVE_STRINGS_H +# include +#endif + +#include +#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/backends/libyahoo2/yahoo/libyahoo2.c b/backends/libyahoo2/yahoo/libyahoo2.c new file mode 100644 index 0000000000000000000000000000000000000000..f33f1365dd7b99409e8b9f0f06db431cd9c307d0 --- /dev/null +++ b/backends/libyahoo2/yahoo/libyahoo2.c @@ -0,0 +1,5520 @@ +/* + * libyahoo2: libyahoo2.c + * + * Some code copyright (C) 2002-2004, Philip S Tellis + * YMSG16 code copyright (C) 2009, + * Siddhesh Poyarekar + * + * Yahoo Search copyright (C) 2003, Konstantin Klyagin + * + * Much of this code was taken and adapted from the yahoo module for + * gaim released under the GNU GPL. This code is also released under the + * GNU GPL. + * + * This code is derivitive of Gaim + * copyright (C) 1998-1999, Mark Spencer + * 1998-1999, Adam Fritzler + * 1998-2002, Rob Flynn + * 2000-2002, Eric Warmenhoven + * 2001-2002, Brian Macke + * 2001, Anand Biligiri S + * 2001, Valdis Kletnieks + * 2002, Sean Egan + * 2002, Toby Gray + * + * This library also uses code from other libraries, namely: + * Portions from libfaim copyright 1998, 1999 Adam Fritzler + * + * Portions of Sylpheed copyright 2000-2002 Hiroyuki Yamamoto + * + * + * YMSG16 authentication code based mostly on write-up at: + * http://www.carbonize.co.uk/ymsg16.html + * + * 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 + * + */ + +#if HAVE_CONFIG_H +# include +#endif + +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#include + +#if STDC_HEADERS +# include +#else +# if !HAVE_STRCHR +# define strchr index +# define strrchr rindex +# endif +char *strchr(), *strrchr(); +# if !HAVE_MEMCPY +# define memcpy(d, s, n) bcopy ((s), (d), (n)) +# define memmove(d, s, n) bcopy ((s), (d), (n)) +# endif +#endif + +#include + +#include +#include + +#include "sha1.h" +#include "md5.h" +#include "yahoo2.h" +#include "yahoo_httplib.h" +#include "yahoo_util.h" +#include "yahoo_fn.h" + +#include "yahoo2_callbacks.h" +#include "yahoo_debug.h" +#ifdef __MINGW32__ +#define snprintf _snprintf +#define vsnprintf _vsnprintf +#endif + +struct yahoo_callbacks *yc = NULL; + +void yahoo_register_callbacks(struct yahoo_callbacks *tyc) +{ + yc = tyc; +} + +#define YAHOO_CALLBACK(x) yc->x + +static int yahoo_send_data(void *fd, void *data, int len); +static void _yahoo_http_connected(int id, void *fd, int error, void *data); +static void yahoo_connected(void *fd, int error, void *data); + +int yahoo_log_message(char *fmt, ...) +{ + char out[1024]; + va_list ap; + va_start(ap, fmt); + vsnprintf(out, sizeof(out), fmt, ap); + va_end(ap); + 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() +{ + return log_level; +} + +int yahoo_set_log_level(enum yahoo_log_level level) +{ + enum yahoo_log_level l = log_level; + log_level = level; + return l; +} + +/* default values for servers */ +static char *default_pager_hosts[] = { "scs.msg.yahoo.com", + "scsa.msg.yahoo.com", + "scsb.msg.yahoo.com", + "scsc.msg.yahoo.com", + NULL}; + +static int pager_port = 5050; +static int fallback_ports[] = { 23, 25, 80, 20, 119, 8001, 8002, 5050, 0 }; + +static char filetransfer_host[] = "filetransfer.msg.yahoo.com"; +static int filetransfer_port = 80; +static char webcam_host[] = "webcam.yahoo.com"; +static int webcam_port = 5100; +static char webcam_description[] = ""; +static char local_host[] = ""; +static int conn_type = Y_WCM_DSL; + +static char profile_url[] = "http://profiles.yahoo.com/"; + +struct connect_callback_data { + struct yahoo_data *yd; + int tag; + int i; + int server_i; +}; + +struct yahoo_pair { + int key; + char *value; +}; + +struct yahoo_packet { + unsigned short int service; + unsigned int status; + unsigned int id; + YList *hash; +}; + +struct yahoo_search_state { + int lsearch_type; + char *lsearch_text; + int lsearch_gender; + int lsearch_agerange; + int lsearch_photo; + int lsearch_yahoo_only; + int lsearch_nstart; + int lsearch_nfound; + int lsearch_ntotal; +}; + +struct data_queue { + unsigned char *queue; + int len; +}; + +struct yahoo_input_data { + struct yahoo_data *yd; + struct yahoo_webcam *wcm; + struct yahoo_webcam_data *wcd; + struct yahoo_search_state *ys; + + void *fd; + enum yahoo_connection_type type; + + unsigned char *rxqueue; + int rxlen; + int read_tag; + + YList *txqueues; + int write_tag; +}; + +struct yahoo_server_settings { + char *pager_host; + int pager_port; + char *filetransfer_host; + int filetransfer_port; + char *webcam_host; + int webcam_port; + char *webcam_description; + char *local_host; + int conn_type; + char **pager_host_list; +}; + +static void yahoo_process_ft_connection(struct yahoo_input_data *yid, int over); + +static void yahoo_process_filetransfer(struct yahoo_input_data *yid, + struct yahoo_packet *pkt); +static void yahoo_process_filetransferinfo(struct yahoo_input_data *yid, + struct yahoo_packet *pkt); +static void yahoo_process_filetransferaccept(struct yahoo_input_data *yid, + struct yahoo_packet *pkt); + +static void *_yahoo_default_server_settings() +{ + struct yahoo_server_settings *yss = + y_new0(struct yahoo_server_settings, 1); + + /* Give preference to the default host list + * Make sure that only one of the two is set at any time + */ + yss->pager_host = NULL; + yss->pager_host_list = default_pager_hosts; + + yss->pager_port = pager_port; + yss->filetransfer_host = strdup(filetransfer_host); + yss->filetransfer_port = filetransfer_port; + yss->webcam_host = strdup(webcam_host); + yss->webcam_port = webcam_port; + yss->webcam_description = strdup(webcam_description); + yss->local_host = strdup(local_host); + yss->conn_type = conn_type; + + return yss; +} + +static void *_yahoo_assign_server_settings(va_list ap) +{ + struct yahoo_server_settings *yss = _yahoo_default_server_settings(); + char *key; + char *svalue; + int nvalue; + char **pvalue; + + while (1) { + key = va_arg(ap, char *); + if (key == NULL) + break; + + if (!strcmp(key, "pager_host")) { + svalue = va_arg(ap, char *); + free(yss->pager_host); + yss->pager_host = strdup(svalue); + yss->pager_host_list = NULL; + } else if (!strcmp(key, "pager_host_list")) { + pvalue = va_arg(ap, char **); + yss->pager_host_list = pvalue; + free(yss->pager_host); + yss->pager_host = NULL; + } else if (!strcmp(key, "pager_port")) { + nvalue = va_arg(ap, int); + yss->pager_port = nvalue; + } else if (!strcmp(key, "filetransfer_host")) { + svalue = va_arg(ap, char *); + free(yss->filetransfer_host); + yss->filetransfer_host = strdup(svalue); + } else if (!strcmp(key, "filetransfer_port")) { + nvalue = va_arg(ap, int); + yss->filetransfer_port = nvalue; + } else if (!strcmp(key, "webcam_host")) { + svalue = va_arg(ap, char *); + free(yss->webcam_host); + yss->webcam_host = strdup(svalue); + } else if (!strcmp(key, "webcam_port")) { + nvalue = va_arg(ap, int); + yss->webcam_port = nvalue; + } else if (!strcmp(key, "webcam_description")) { + svalue = va_arg(ap, char *); + free(yss->webcam_description); + yss->webcam_description = strdup(svalue); + } else if (!strcmp(key, "local_host")) { + svalue = va_arg(ap, char *); + free(yss->local_host); + yss->local_host = strdup(svalue); + } else if (!strcmp(key, "conn_type")) { + nvalue = va_arg(ap, int); + yss->conn_type = nvalue; + } else { + WARNING(("Unknown key passed to yahoo_init, " + "perhaps you didn't terminate the list " + "with NULL")); + } + } + + return yss; +} + +static void yahoo_free_server_settings(struct yahoo_server_settings *yss) +{ + if (!yss) + return; + + free(yss->pager_host); + free(yss->filetransfer_host); + free(yss->webcam_host); + free(yss->webcam_description); + free(yss->local_host); + + free(yss); +} + +static YList *conns = NULL; +static YList *inputs = NULL; +static int last_id = 0; + +static void add_to_list(struct yahoo_data *yd) +{ + conns = y_list_prepend(conns, yd); +} + +static struct yahoo_data *find_conn_by_id(int id) +{ + YList *l; + for (l = conns; l; l = y_list_next(l)) { + struct yahoo_data *yd = l->data; + if (yd->client_id == id) + return yd; + } + return NULL; +} + +static void del_from_list(struct yahoo_data *yd) +{ + conns = y_list_remove(conns, yd); +} + +/* call repeatedly to get the next one */ +/* +static struct yahoo_input_data * find_input_by_id(int id) +{ + YList *l; + for(l = inputs; l; l = y_list_next(l)) { + struct yahoo_input_data *yid = l->data; + if(yid->yd->client_id == id) + return yid; + } + return NULL; +} +*/ + +static struct yahoo_input_data *find_input_by_id_and_webcam_user(int id, + const char *who) +{ + YList *l; + LOG(("find_input_by_id_and_webcam_user")); + for (l = inputs; l; l = y_list_next(l)) { + struct yahoo_input_data *yid = l->data; + if (yid->type == YAHOO_CONNECTION_WEBCAM + && yid->yd->client_id == id && yid->wcm && ((who + && yid->wcm->user + && !strcmp(who, yid->wcm->user)) + || !(yid->wcm->user && !who))) + return yid; + } + return NULL; +} + +static struct yahoo_input_data *find_input_by_id_and_type(int id, + enum yahoo_connection_type type) +{ + YList *l; + LOG(("find_input_by_id_and_type")); + for (l = inputs; l; l = y_list_next(l)) { + struct yahoo_input_data *yid = l->data; + if (yid->type == type && yid->yd->client_id == id) + return yid; + } + return NULL; +} + +static struct yahoo_input_data *find_input_by_id_and_fd(int id, void *fd) +{ + YList *l; + LOG(("find_input_by_id_and_fd")); + for (l = inputs; l; l = y_list_next(l)) { + struct yahoo_input_data *yid = l->data; + if (yid->fd == fd && yid->yd->client_id == id) + return yid; + } + return NULL; +} + +static int count_inputs_with_id(int id) +{ + int c = 0; + YList *l; + LOG(("counting %d", id)); + for (l = inputs; l; l = y_list_next(l)) { + struct yahoo_input_data *yid = l->data; + if (yid->yd->client_id == id) + c++; + } + LOG(("%d", c)); + return c; +} + +extern char *yahoo_crypt(char *, char *); + +/* Free a buddy list */ +static void yahoo_free_buddies(YList *list) +{ + YList *l; + + for (l = list; l; l = l->next) { + struct yahoo_buddy *bud = l->data; + if (!bud) + continue; + + FREE(bud->group); + FREE(bud->id); + FREE(bud->real_name); + if (bud->yab_entry) { + FREE(bud->yab_entry->fname); + FREE(bud->yab_entry->lname); + FREE(bud->yab_entry->nname); + FREE(bud->yab_entry->id); + FREE(bud->yab_entry->email); + FREE(bud->yab_entry->hphone); + FREE(bud->yab_entry->wphone); + FREE(bud->yab_entry->mphone); + FREE(bud->yab_entry); + } + FREE(bud); + l->data = bud = NULL; + } + + y_list_free(list); +} + +/* Free an identities list */ +static void yahoo_free_identities(YList *list) +{ + while (list) { + YList *n = list; + FREE(list->data); + list = y_list_remove_link(list, list); + y_list_free_1(n); + } +} + +/* Free webcam data */ +static void yahoo_free_webcam(struct yahoo_webcam *wcm) +{ + if (wcm) { + FREE(wcm->user); + FREE(wcm->server); + FREE(wcm->key); + FREE(wcm->description); + FREE(wcm->my_ip); + } + FREE(wcm); +} + +static void yahoo_free_data(struct yahoo_data *yd) +{ + FREE(yd->user); + FREE(yd->password); + FREE(yd->cookie_y); + FREE(yd->cookie_t); + FREE(yd->cookie_b); + FREE(yd->cookie_c); + FREE(yd->login_cookie); + FREE(yd->login_id); + + yahoo_free_buddies(yd->buddies); + yahoo_free_buddies(yd->ignore); + yahoo_free_identities(yd->identities); + + yahoo_free_server_settings(yd->server_settings); + + FREE(yd); +} + +#define YAHOO_PACKET_HDRLEN (4 + 2 + 2 + 2 + 2 + 4 + 4) + +static struct yahoo_packet *yahoo_packet_new(enum yahoo_service service, + enum ypacket_status status, int id) +{ + struct yahoo_packet *pkt = y_new0(struct yahoo_packet, 1); + + pkt->service = service; + pkt->status = status; + pkt->id = id; + + return pkt; +} + +static void yahoo_packet_hash(struct yahoo_packet *pkt, int key, + const char *value) +{ + struct yahoo_pair *pair = y_new0(struct yahoo_pair, 1); + pair->key = key; + pair->value = strdup(value); + pkt->hash = y_list_append(pkt->hash, pair); +} + +static int yahoo_packet_length(struct yahoo_packet *pkt) +{ + YList *l; + + int len = 0; + + for (l = pkt->hash; l; l = l->next) { + struct yahoo_pair *pair = l->data; + int tmp = pair->key; + do { + tmp /= 10; + len++; + } while (tmp); + len += 2; + len += strlen(pair->value); + len += 2; + } + + return len; +} + +#define yahoo_put16(buf, data) ( \ + (*(buf) = (unsigned char)((data)>>8)&0xff), \ + (*((buf)+1) = (unsigned char)(data)&0xff), \ + 2) +#define yahoo_get16(buf) ((((*(buf))&0xff)<<8) + ((*((buf)+1)) & 0xff)) +#define yahoo_put32(buf, data) ( \ + (*((buf)) = (unsigned char)((data)>>24)&0xff), \ + (*((buf)+1) = (unsigned char)((data)>>16)&0xff), \ + (*((buf)+2) = (unsigned char)((data)>>8)&0xff), \ + (*((buf)+3) = (unsigned char)(data)&0xff), \ + 4) +#define yahoo_get32(buf) ((((*(buf) )&0xff)<<24) + \ + (((*((buf)+1))&0xff)<<16) + \ + (((*((buf)+2))&0xff)<< 8) + \ + (((*((buf)+3))&0xff))) + +static void yahoo_packet_read(struct yahoo_packet *pkt, unsigned char *data, + int len) +{ + int pos = 0; + + while (pos + 1 < len) { + char *key, *value = NULL; + int accept; + int x; + + struct yahoo_pair *pair = y_new0(struct yahoo_pair, 1); + + key = malloc(len + 1); + x = 0; + while (pos + 1 < len) { + if (data[pos] == 0xc0 && data[pos + 1] == 0x80) + break; + key[x++] = data[pos++]; + } + key[x] = 0; + pos += 2; + pair->key = strtol(key, NULL, 10); + free(key); + + accept = x; + + if (pos + 1 > len) { + /* Malformed packet! (Truncated--garbage or something) */ + accept = 0; + } + + /* if x is 0 there was no key, so don't accept it */ + if (accept) + value = malloc(len - pos + 1); + x = 0; + while (pos + 1 < len) { + if (data[pos] == 0xc0 && data[pos + 1] == 0x80) + break; + if (accept) + value[x++] = data[pos++]; + } + if (accept) + value[x] = 0; + pos += 2; + if (accept) { + pair->value = strdup(value); + FREE(value); + pkt->hash = y_list_append(pkt->hash, pair); + DEBUG_MSG(("Key: %d \tValue: %s", pair->key, + pair->value)); + } else { + FREE(pair); + } + } +} + +static void yahoo_packet_write(struct yahoo_packet *pkt, unsigned char *data) +{ + YList *l; + int pos = 0; + + for (l = pkt->hash; l; l = l->next) { + struct yahoo_pair *pair = l->data; + unsigned char buf[100]; + + snprintf((char *)buf, sizeof(buf), "%d", pair->key); + strcpy((char *)data + pos, (char *)buf); + pos += strlen((char *)buf); + data[pos++] = 0xc0; + data[pos++] = 0x80; + + strcpy((char *)data + pos, pair->value); + pos += strlen(pair->value); + data[pos++] = 0xc0; + data[pos++] = 0x80; + } +} + +static void yahoo_dump_unhandled(struct yahoo_packet *pkt) +{ + YList *l; + + NOTICE(("Service: 0x%02x\tStatus: %d", pkt->service, pkt->status)); + for (l = pkt->hash; l; l = l->next) { + struct yahoo_pair *pair = l->data; + NOTICE(("\t%d => %s", pair->key, pair->value)); + } +} + +static void yahoo_packet_dump(unsigned char *data, int len) +{ + if (yahoo_get_log_level() >= YAHOO_LOG_DEBUG) { + int i; + for (i = 0; i < len; i++) { + if ((i % 8 == 0) && i) + YAHOO_CALLBACK(ext_yahoo_log) (" "); + if ((i % 16 == 0) && i) + YAHOO_CALLBACK(ext_yahoo_log) ("\n"); + YAHOO_CALLBACK(ext_yahoo_log) ("%02x ", data[i]); + } + YAHOO_CALLBACK(ext_yahoo_log) ("\n"); + for (i = 0; i < len; i++) { + if ((i % 8 == 0) && i) + YAHOO_CALLBACK(ext_yahoo_log) (" "); + if ((i % 16 == 0) && i) + YAHOO_CALLBACK(ext_yahoo_log) ("\n"); + if (isprint(data[i])) + YAHOO_CALLBACK(ext_yahoo_log) (" %c ", data[i]); + else + YAHOO_CALLBACK(ext_yahoo_log) (" . "); + } + YAHOO_CALLBACK(ext_yahoo_log) ("\n"); + } +} + +static const char base64digits[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" "0123456789._"; +static void to_y64(unsigned char *out, const unsigned char *in, int inlen) +/* raw bytes in quasi-big-endian order to base 64 string (NUL-terminated) */ +{ + for (; inlen >= 3; inlen -= 3) { + *out++ = base64digits[in[0] >> 2]; + *out++ = base64digits[((in[0] << 4) & 0x30) | (in[1] >> 4)]; + *out++ = base64digits[((in[1] << 2) & 0x3c) | (in[2] >> 6)]; + *out++ = base64digits[in[2] & 0x3f]; + in += 3; + } + if (inlen > 0) { + unsigned char fragment; + + *out++ = base64digits[in[0] >> 2]; + fragment = (in[0] << 4) & 0x30; + if (inlen > 1) + fragment |= in[1] >> 4; + *out++ = base64digits[fragment]; + *out++ = (inlen < 2) ? '-' : base64digits[(in[1] << 2) & 0x3c]; + *out++ = '-'; + } + *out = '\0'; +} + +static void yahoo_add_to_send_queue(struct yahoo_input_data *yid, void *data, + int length) +{ + struct data_queue *tx = y_new0(struct data_queue, 1); + tx->queue = y_new0(unsigned char, length); + tx->len = length; + memcpy(tx->queue, data, length); + + yid->txqueues = y_list_append(yid->txqueues, tx); + + if (!yid->write_tag) + yid->write_tag = + YAHOO_CALLBACK(ext_yahoo_add_handler) (yid->yd-> + client_id, yid->fd, YAHOO_INPUT_WRITE, yid); +} + +static void yahoo_send_packet(struct yahoo_input_data *yid, + struct yahoo_packet *pkt, int extra_pad) +{ + int pktlen = yahoo_packet_length(pkt); + int len = YAHOO_PACKET_HDRLEN + pktlen; + unsigned char *data; + int pos = 0; + + if (!yid->fd) + return; + + data = y_new0(unsigned char, len + 1); + + memcpy(data + pos, "YMSG", 4); + pos += 4; + pos += yahoo_put16(data + pos, YAHOO_PROTO_VER); /* version [latest 12 0x000c] */ + pos += yahoo_put16(data + pos, 0x0000); /* HIWORD pkt length??? */ + pos += yahoo_put16(data + pos, pktlen + extra_pad); /* LOWORD pkt length? */ + pos += yahoo_put16(data + pos, pkt->service); /* service */ + pos += yahoo_put32(data + pos, pkt->status); /* status [4bytes] */ + pos += yahoo_put32(data + pos, pkt->id); /* session [4bytes] */ + + yahoo_packet_write(pkt, data + pos); + + yahoo_packet_dump(data, len); + + if (yid->type == YAHOO_CONNECTION_FT) + yahoo_send_data(yid->fd, data, len); + else + yahoo_add_to_send_queue(yid, data, len); + FREE(data); +} + +static void yahoo_packet_free(struct yahoo_packet *pkt) +{ + while (pkt->hash) { + struct yahoo_pair *pair = pkt->hash->data; + YList *tmp; + FREE(pair->value); + FREE(pair); + tmp = pkt->hash; + pkt->hash = y_list_remove_link(pkt->hash, pkt->hash); + y_list_free_1(tmp); + } + FREE(pkt); +} + +static int yahoo_send_data(void *fd, void *data, int len) +{ + int ret; + int e; + + if (fd == NULL) + return -1; + + yahoo_packet_dump(data, len); + + do { + ret = YAHOO_CALLBACK(ext_yahoo_write) (fd, data, len); + } while (ret == -1 && errno == EINTR); + e = errno; + + if (ret == -1) { + LOG(("wrote data: ERR %s", strerror(errno))); + } else { + LOG(("wrote data: OK")); + } + + errno = e; + return ret; +} + +void yahoo_close(int id) +{ + struct yahoo_data *yd = find_conn_by_id(id); + if (!yd) + return; + + del_from_list(yd); + + yahoo_free_data(yd); + if (id == last_id) + last_id--; +} + +static void yahoo_input_close(struct yahoo_input_data *yid) +{ + inputs = y_list_remove(inputs, yid); + + LOG(("yahoo_input_close(read)")); + YAHOO_CALLBACK(ext_yahoo_remove_handler) (yid->yd->client_id, + yid->read_tag); + LOG(("yahoo_input_close(write)")); + YAHOO_CALLBACK(ext_yahoo_remove_handler) (yid->yd->client_id, + yid->write_tag); + yid->read_tag = yid->write_tag = 0; + if (yid->fd) + YAHOO_CALLBACK(ext_yahoo_close) (yid->fd); + yid->fd = 0; + FREE(yid->rxqueue); + if (count_inputs_with_id(yid->yd->client_id) == 0) { + LOG(("closing %d", yid->yd->client_id)); + yahoo_close(yid->yd->client_id); + } + yahoo_free_webcam(yid->wcm); + if (yid->wcd) + FREE(yid->wcd); + if (yid->ys) { + FREE(yid->ys->lsearch_text); + FREE(yid->ys); + } + FREE(yid); +} + +static int is_same_bud(const void *a, const void *b) +{ + const struct yahoo_buddy *subject = a; + const struct yahoo_buddy *object = b; + + return strcmp(subject->id, object->id); +} + +static char *getcookie(char *rawcookie) +{ + char *cookie = NULL; + char *tmpcookie; + char *cookieend; + + if (strlen(rawcookie) < 2) + return NULL; + + tmpcookie = strdup(rawcookie + 2); + cookieend = strchr(tmpcookie, ';'); + + if (cookieend) + *cookieend = '\0'; + + cookie = strdup(tmpcookie); + FREE(tmpcookie); + /* cookieend=NULL; not sure why this was there since the value is not preserved in the stack -dd */ + + return cookie; +} + +static char *getlcookie(char *cookie) +{ + char *tmp; + char *tmpend; + char *login_cookie = NULL; + + tmpend = strstr(cookie, "n="); + if (tmpend) { + tmp = strdup(tmpend + 2); + tmpend = strchr(tmp, '&'); + if (tmpend) + *tmpend = '\0'; + login_cookie = strdup(tmp); + FREE(tmp); + } + + return login_cookie; +} + +static void yahoo_process_notify(struct yahoo_input_data *yid, + struct yahoo_packet *pkt) +{ + struct yahoo_data *yd = yid->yd; + char *msg = NULL; + char *from = NULL; + char *to = NULL; + int stat = 0; + int accept = 0; + char *ind = NULL; + YList *l; + for (l = pkt->hash; l; l = l->next) { + struct yahoo_pair *pair = l->data; + if (pair->key == 4) + from = pair->value; + if (pair->key == 5) + to = pair->value; + if (pair->key == 49) + msg = pair->value; + if (pair->key == 13) + stat = atoi(pair->value); + if (pair->key == 14) + ind = pair->value; + if (pair->key == 16) { /* status == -1 */ + NOTICE((pair->value)); + return; + } + + } + + if (!msg) + return; + + if (!strncasecmp(msg, "TYPING", strlen("TYPING"))) + YAHOO_CALLBACK(ext_yahoo_typing_notify) (yd->client_id, to, + from, stat); + else if (!strncasecmp(msg, "GAME", strlen("GAME"))) + YAHOO_CALLBACK(ext_yahoo_game_notify) (yd->client_id, to, from, + stat, ind); + else if (!strncasecmp(msg, "WEBCAMINVITE", strlen("WEBCAMINVITE"))) { + if (!strcmp(ind, " ")) { + YAHOO_CALLBACK(ext_yahoo_webcam_invite) (yd->client_id, + to, from); + } else { + accept = atoi(ind); + /* accept the invitation (-1 = deny 1 = accept) */ + if (accept < 0) + accept = 0; + YAHOO_CALLBACK(ext_yahoo_webcam_invite_reply) (yd-> + client_id, to, from, accept); + } + } else + LOG(("Got unknown notification: %s", msg)); +} + +static void yahoo_process_conference(struct yahoo_input_data *yid, + struct yahoo_packet *pkt) +{ + struct yahoo_data *yd = yid->yd; + char *msg = NULL; + char *host = NULL; + char *who = NULL; + char *room = NULL; + char *id = NULL; + int utf8 = 0; + YList *members = NULL; + YList *l; + + for (l = pkt->hash; l; l = l->next) { + struct yahoo_pair *pair = l->data; + if (pair->key == 50) + host = pair->value; + + if (pair->key == 52) { /* invite */ + members = y_list_append(members, strdup(pair->value)); + } + if (pair->key == 53) /* logon */ + who = pair->value; + if (pair->key == 54) /* decline */ + who = pair->value; + if (pair->key == 55) /* unavailable (status == 2) */ + who = pair->value; + if (pair->key == 56) /* logoff */ + who = pair->value; + + if (pair->key == 57) + room = pair->value; + + if (pair->key == 58) /* join message */ + msg = pair->value; + if (pair->key == 14) /* decline/conf message */ + msg = pair->value; + + if (pair->key == 13) ; + if (pair->key == 16) /* error */ + msg = pair->value; + + if (pair->key == 1) /* my id */ + id = pair->value; + if (pair->key == 3) /* message sender */ + who = pair->value; + + if (pair->key == 97) + utf8 = atoi(pair->value); + } + + if (!room) + return; + + if (host) { + for (l = members; l; l = l->next) { + char *w = l->data; + if (!strcmp(w, host)) + break; + } + if (!l) + members = y_list_append(members, strdup(host)); + } + /* invite, decline, join, left, message -> status == 1 */ + + switch (pkt->service) { + case YAHOO_SERVICE_CONFINVITE: + if (pkt->status == 2) ; + else if (members) + YAHOO_CALLBACK(ext_yahoo_got_conf_invite) (yd-> + client_id, id, host, room, msg, members); + else if (msg) + YAHOO_CALLBACK(ext_yahoo_error) (yd->client_id, msg, 0, + E_CONFNOTAVAIL); + break; + case YAHOO_SERVICE_CONFADDINVITE: + if (pkt->status == 1) + YAHOO_CALLBACK(ext_yahoo_got_conf_invite) (yd-> + client_id, id, host, room, msg, members); + break; + case YAHOO_SERVICE_CONFDECLINE: + if (who) + YAHOO_CALLBACK(ext_yahoo_conf_userdecline) (yd-> + client_id, id, who, room, msg); + break; + case YAHOO_SERVICE_CONFLOGON: + if (who) + YAHOO_CALLBACK(ext_yahoo_conf_userjoin) (yd->client_id, + id, who, room); + break; + case YAHOO_SERVICE_CONFLOGOFF: + if (who) + YAHOO_CALLBACK(ext_yahoo_conf_userleave) (yd->client_id, + id, who, room); + break; + case YAHOO_SERVICE_CONFMSG: + if (who) + YAHOO_CALLBACK(ext_yahoo_conf_message) (yd->client_id, + id, who, room, msg, utf8); + break; + } +} + +static void yahoo_process_chat(struct yahoo_input_data *yid, + struct yahoo_packet *pkt) +{ + char *msg = NULL; + char *id = NULL; + char *who = NULL; + char *room = NULL; + char *topic = NULL; + YList *members = NULL; + struct yahoo_chat_member *currentmember = NULL; + int msgtype = 1; + int utf8 = 0; + int firstjoin = 0; + int membercount = 0; + int chaterr = 0; + YList *l; + + yahoo_dump_unhandled(pkt); + for (l = pkt->hash; l; l = l->next) { + struct yahoo_pair *pair = l->data; + + if (pair->key == 1) { + /* My identity */ + id = pair->value; + } + + if (pair->key == 104) { + /* Room name */ + room = pair->value; + } + + if (pair->key == 105) { + /* Room topic */ + topic = pair->value; + } + + if (pair->key == 108) { + /* Number of members in this packet */ + membercount = atoi(pair->value); + } + + if (pair->key == 109) { + /* message sender */ + who = pair->value; + + if (pkt->service == YAHOO_SERVICE_CHATJOIN) { + currentmember = + y_new0(struct yahoo_chat_member, 1); + currentmember->id = strdup(pair->value); + members = y_list_append(members, currentmember); + } + } + + if (pair->key == 110) { + /* age */ + if (pkt->service == YAHOO_SERVICE_CHATJOIN) + currentmember->age = atoi(pair->value); + } + + if (pair->key == 113) { + /* attribs */ + if (pkt->service == YAHOO_SERVICE_CHATJOIN) + currentmember->attribs = atoi(pair->value); + } + + if (pair->key == 141) { + /* alias */ + if (pkt->service == YAHOO_SERVICE_CHATJOIN) + currentmember->alias = strdup(pair->value); + } + + if (pair->key == 142) { + /* location */ + if (pkt->service == YAHOO_SERVICE_CHATJOIN) + currentmember->location = strdup(pair->value); + } + + if (pair->key == 130) { + /* first join */ + firstjoin = 1; + } + + if (pair->key == 117) { + /* message */ + msg = pair->value; + } + + if (pair->key == 124) { + /* Message type */ + msgtype = atoi(pair->value); + } + if (pair->key == 114) { + /* message error not sure what all the pair values mean */ + /* but -1 means no session in room */ + chaterr = atoi(pair->value); + } + } + + if (!room) { + if (pkt->service == YAHOO_SERVICE_CHATLOGOUT) { /* yahoo originated chat logout */ + YAHOO_CALLBACK(ext_yahoo_chat_yahoologout) (yid->yd-> + client_id, id); + return; + } + if (pkt->service == YAHOO_SERVICE_COMMENT && chaterr) { + YAHOO_CALLBACK(ext_yahoo_chat_yahooerror) (yid->yd-> + client_id, id); + return; + } + + WARNING(("We didn't get a room name, ignoring packet")); + return; + } + + switch (pkt->service) { + case YAHOO_SERVICE_CHATJOIN: + if (y_list_length(members) != membercount) { + WARNING(("Count of members doesn't match No. of members we got")); + } + if (firstjoin && members) { + YAHOO_CALLBACK(ext_yahoo_chat_join) (yid->yd->client_id, + id, room, topic, members, yid->fd); + } else if (who) { + if (y_list_length(members) != 1) { + WARNING(("Got more than 1 member on a normal join")); + } + /* this should only ever have one, but just in case */ + while (members) { + YList *n = members->next; + currentmember = members->data; + YAHOO_CALLBACK(ext_yahoo_chat_userjoin) (yid-> + yd->client_id, id, room, currentmember); + y_list_free_1(members); + members = n; + } + } + break; + case YAHOO_SERVICE_CHATEXIT: + if (who) { + YAHOO_CALLBACK(ext_yahoo_chat_userleave) (yid->yd-> + client_id, id, room, who); + } + break; + case YAHOO_SERVICE_COMMENT: + if (who) { + YAHOO_CALLBACK(ext_yahoo_chat_message) (yid->yd-> + client_id, id, who, room, msg, msgtype, utf8); + } + break; + } +} + +static void yahoo_process_message(struct yahoo_input_data *yid, + struct yahoo_packet *pkt) +{ + struct yahoo_data *yd = yid->yd; + YList *l; + YList *messages = NULL; + + struct m { + int i_31; + int i_32; + char *to; + char *from; + long tm; + char *msg; + int utf8; + char *gunk; + } *message = y_new0(struct m, 1); + + for (l = pkt->hash; l; l = l->next) { + struct yahoo_pair *pair = l->data; + if (pair->key == 1 || pair->key == 4) { + if (!message->from) + message->from = pair->value; + } else if (pair->key == 5) + message->to = pair->value; + else if (pair->key == 15) + message->tm = strtol(pair->value, NULL, 10); + else if (pair->key == 97) + message->utf8 = atoi(pair->value); + /* This comes when the official client sends us a message */ + else if (pair->key == 429) + message->gunk = pair->value; + /* user message *//* sys message */ + else if (pair->key == 14 || pair->key == 16) + message->msg = pair->value; + else if (pair->key == 31) { + if (message->i_31) { + messages = y_list_append(messages, message); + message = y_new0(struct m, 1); + } + message->i_31 = atoi(pair->value); + } else if (pair->key == 32) + message->i_32 = atoi(pair->value); + else + LOG(("yahoo_process_message: status: %d, key: %d, value: %s", pkt->status, pair->key, pair->value)); + } + + messages = y_list_append(messages, message); + + for (l = messages; l; l = l->next) { + message = l->data; + if (pkt->service == YAHOO_SERVICE_SYSMESSAGE) { + YAHOO_CALLBACK(ext_yahoo_system_message) (yd->client_id, + message->to, message->from, message->msg); + } else if (pkt->status <= 2 || pkt->status == 5) { + /* Confirm message receipt if we got the gunk */ + if(message->gunk) { + struct yahoo_packet *outpkt; + + outpkt = yahoo_packet_new(YAHOO_SERVICE_MESSAGE_CONFIRM, + YPACKET_STATUS_DEFAULT, 0); + yahoo_packet_hash(outpkt, 1, yd->user); + yahoo_packet_hash(outpkt, 5, message->from); + yahoo_packet_hash(outpkt, 302, "430"); + yahoo_packet_hash(outpkt, 430, message->gunk); + yahoo_packet_hash(outpkt, 303, "430"); + yahoo_packet_hash(outpkt, 450, "0"); + yahoo_send_packet(yid, outpkt, 0); + + yahoo_packet_free(outpkt); + } + + if (!strcmp(message->msg, "")) + YAHOO_CALLBACK(ext_yahoo_got_buzz) (yd->client_id, + message->to, message->from, message->tm); + else + YAHOO_CALLBACK(ext_yahoo_got_im) (yd->client_id, + message->to, message->from, message->msg, + message->tm, pkt->status, message->utf8); + } else if (pkt->status == 0xffffffff) { + YAHOO_CALLBACK(ext_yahoo_error) (yd->client_id, + message->msg, 0, E_SYSTEM); + } + FREE(message); + } + + y_list_free(messages); +} + +/* + * Here's what multi-level packets look like. Data in brackets is the value. + * + * 3 level: + * ======= + * + * 302 (318) - Beginning level 1 + * 300 (318) - Begin level 2 + * 302 (319) - End level 2 header + * 300 (319) - Begin level 3 + * 301 (319) - End level 3 + * 303 (319) - End level 2 + * 303 (318) - End level 1 + * + * 2 level: + * ======= + * + * 302 (315) - Beginning level 1 + * 300 (315) - Begin level 2 + * 301 (315) - End level 2 + * 303 (315) - End level 1 + * + */ +static void yahoo_process_status(struct yahoo_input_data *yid, + struct yahoo_packet *pkt) +{ + YList *l; + struct yahoo_data *yd = yid->yd; + + struct yahoo_process_status_entry *u; + + YList *users = 0; + + if (pkt->service == YAHOO_SERVICE_LOGOFF && pkt->status == -1) { + YAHOO_CALLBACK(ext_yahoo_login_response) (yd->client_id, + YAHOO_LOGIN_DUPL, NULL); + return; + } + + /* + * Status updates may be spread accross multiple packets and not + * even on buddy boundaries, so keeping some state is important. + * So, continue where we left off, and only add a user entry to + * the list once it's complete (301-315 End buddy). + */ + u = yd->half_user; + + for (l = pkt->hash; l; l = l->next) { + struct yahoo_pair *pair = l->data; + + switch (pair->key) { + case 300: /* Begin buddy */ + if (!strcmp(pair->value, "315") && !u) { + u = yd->half_user = y_new0(struct yahoo_process_status_entry, 1); + } + break; + case 301: /* End buddy */ + if (!strcmp(pair->value, "315") && u) { + users = y_list_prepend(users, u); + u = yd->half_user = NULL; + } + break; + case 0: /* we won't actually do anything with this */ + NOTICE(("key %d:%s", pair->key, pair->value)); + break; + case 1: /* we don't get the full buddy list here. */ + if (!yd->logged_in) { + yd->logged_in = 1; + if (yd->current_status < 0) + yd->current_status = yd->initial_status; + YAHOO_CALLBACK(ext_yahoo_login_response) (yd-> + client_id, YAHOO_LOGIN_OK, NULL); + } + break; + case 8: /* how many online buddies we have */ + NOTICE(("key %d:%s", pair->key, pair->value)); + break; + case 7: /* the current buddy */ + if (!u) { + /* This will only happen in case of a single level message */ + u = y_new0(struct yahoo_process_status_entry, 1); + users = y_list_prepend(users, u); + } + u->name = pair->value; + break; + case 10: /* state */ + u->state = strtol(pair->value, NULL, 10); + break; + case 19: /* custom status message */ + u->msg = pair->value; + break; + case 47: /* is it an away message or not. Not applicable for YMSG16 anymore */ + u->away = atoi(pair->value); + break; + case 137: /* seconds idle */ + u->idle = atoi(pair->value); + break; + case 11: /* this is the buddy's session id */ + u->buddy_session = atoi(pair->value); + break; + case 17: /* in chat? */ + u->f17 = atoi(pair->value); + break; + case 13: /* bitmask, bit 0 = pager, bit 1 = chat, bit 2 = game */ + u->flags = atoi(pair->value); + break; + case 60: /* SMS -> 1 MOBILE USER */ + /* sometimes going offline makes this 2, but invisible never sends it */ + u->mobile = atoi(pair->value); + break; + case 138: + u->f138 = atoi(pair->value); + break; + case 184: + u->f184 = pair->value; + break; + case 192: + u->f192 = atoi(pair->value); + break; + case 10001: + u->f10001 = atoi(pair->value); + break; + case 10002: + u->f10002 = atoi(pair->value); + break; + case 198: + u->f198 = atoi(pair->value); + break; + case 197: + u->f197 = pair->value; + break; + case 205: + u->f205 = pair->value; + break; + case 213: + u->f213 = atoi(pair->value); + break; + case 16: /* Custom error message */ + YAHOO_CALLBACK(ext_yahoo_error) (yd->client_id, + pair->value, 0, E_CUSTOM); + break; + default: + WARNING(("unknown status key %d:%s", pair->key, + pair->value)); + break; + } + } + + while (users) { + YList *t = users; + struct yahoo_process_status_entry *u = users->data; + + if (u->name != NULL) { + if (pkt->service == + YAHOO_SERVICE_LOGOFF + /*|| u->flags == 0 No flags for YMSG16 */ ) { + YAHOO_CALLBACK(ext_yahoo_status_changed) (yd-> + client_id, u->name, + YAHOO_STATUS_OFFLINE, NULL, 1, 0, 0); + } else { + /* Key 47 always seems to be 1 for YMSG16 */ + if (!u->state) + u->away = 0; + else + u->away = 1; + + YAHOO_CALLBACK(ext_yahoo_status_changed) (yd-> + client_id, u->name, u->state, u->msg, + u->away, u->idle, u->mobile); + } + } + + users = y_list_remove_link(users, users); + y_list_free_1(t); + FREE(u); + } +} + +static void yahoo_process_buddy_list(struct yahoo_input_data *yid, + struct yahoo_packet *pkt) +{ + struct yahoo_data *yd = yid->yd; + YList *l; + int last_packet = 0; + char *cur_group = NULL; + struct yahoo_buddy *newbud = NULL; + + /* we could be getting multiple packets here */ + for (l = pkt->hash; l; l = l->next) { + struct yahoo_pair *pair = l->data; + + switch (pair->key) { + case 300: + case 301: + case 302: + break; /* Separators. Our logic does not need them */ + case 303: + if (318 == atoi(pair->value)) + last_packet = 1; + break; + case 65: + cur_group = strdup(pair->value); + break; + case 7: + newbud = y_new0(struct yahoo_buddy, 1); + newbud->id = strdup(pair->value); + if (cur_group) + newbud->group = strdup(cur_group); + else if (yd->buddies) { + struct yahoo_buddy *lastbud = + (struct yahoo_buddy *)y_list_nth(yd-> + buddies, + y_list_length(yd->buddies) - 1)->data; + newbud->group = strdup(lastbud->group); + } else + newbud->group = strdup("Buddies"); + + yd->buddies = y_list_append(yd->buddies, newbud); + + break; + } + } + + /* we could be getting multiple packets here */ + if (pkt->hash && !last_packet) + return; + + /* Logged in */ + if (!yd->logged_in) { + yd->logged_in = 1; + if (yd->current_status < 0) + yd->current_status = yd->initial_status; + YAHOO_CALLBACK(ext_yahoo_login_response) (yd->client_id, + YAHOO_LOGIN_OK, NULL); + + yahoo_set_away(yd->client_id, yd->initial_status, NULL, + (yd->initial_status == YAHOO_STATUS_AVAILABLE) ? 0 : 1); + + yahoo_get_yab(yd->client_id); + } + + YAHOO_CALLBACK(ext_yahoo_got_buddies) (yd->client_id, yd->buddies); + +} + +static void yahoo_process_list(struct yahoo_input_data *yid, + struct yahoo_packet *pkt) +{ + struct yahoo_data *yd = yid->yd; + YList *l; + + /* we could be getting multiple packets here */ + for (l = pkt->hash; l; l = l->next) { + struct yahoo_pair *pair = l->data; + + switch (pair->key) { + case 89: /* identities */ + { + char **identities = + y_strsplit(pair->value, ",", -1); + int i; + for (i = 0; identities[i]; i++) + yd->identities = + y_list_append(yd->identities, + strdup(identities[i])); + y_strfreev(identities); + } + YAHOO_CALLBACK(ext_yahoo_got_identities) (yd->client_id, + yd->identities); + break; + case 59: /* cookies */ + if (pair->value[0] == 'Y') { + FREE(yd->cookie_y); + FREE(yd->login_cookie); + + yd->cookie_y = getcookie(pair->value); + yd->login_cookie = getlcookie(yd->cookie_y); + + } else if (pair->value[0] == 'T') { + FREE(yd->cookie_t); + yd->cookie_t = getcookie(pair->value); + + } else if (pair->value[0] == 'C') { + FREE(yd->cookie_c); + yd->cookie_c = getcookie(pair->value); + } + + break; + case 3: /* my id */ + case 90: /* 1 */ + case 100: /* 0 */ + case 101: /* NULL */ + case 102: /* NULL */ + case 93: /* 86400/1440 */ + break; + } + } + + if (yd->cookie_y && yd->cookie_t) /* We don't get cookie_c anymore */ + YAHOO_CALLBACK(ext_yahoo_got_cookies) (yd->client_id); +} + +static void yahoo_process_verify(struct yahoo_input_data *yid, + struct yahoo_packet *pkt) +{ + struct yahoo_data *yd = yid->yd; + + if (pkt->status != 0x01) { + DEBUG_MSG(("expected status: 0x01, got: %d", pkt->status)); + YAHOO_CALLBACK(ext_yahoo_login_response) (yd->client_id, + YAHOO_LOGIN_LOCK, ""); + return; + } + + pkt = yahoo_packet_new(YAHOO_SERVICE_AUTH, YPACKET_STATUS_DEFAULT, + yd->session_id); + + yahoo_packet_hash(pkt, 1, yd->user); + yahoo_send_packet(yid, pkt, 0); + + yahoo_packet_free(pkt); + +} + +static void yahoo_process_picture_checksum(struct yahoo_input_data *yid, + struct yahoo_packet *pkt) +{ + struct yahoo_data *yd = yid->yd; + char *from; + char *to; + int checksum = 0; + YList *l; + + for (l = pkt->hash; l; l = l->next) { + struct yahoo_pair *pair = l->data; + + switch (pair->key) { + case 1: + case 4: + from = pair->value; + case 5: + to = pair->value; + break; + case 212: + break; + case 192: + checksum = atoi(pair->value); + break; + } + } + + YAHOO_CALLBACK(ext_yahoo_got_buddyicon_checksum) (yd->client_id, to, + from, checksum); +} + +static void yahoo_process_picture(struct yahoo_input_data *yid, + struct yahoo_packet *pkt) +{ + struct yahoo_data *yd = yid->yd; + char *url; + char *from; + char *to; + int status = 0; + int checksum = 0; + YList *l; + + for (l = pkt->hash; l; l = l->next) { + struct yahoo_pair *pair = l->data; + + switch (pair->key) { + case 1: + case 4: /* sender */ + from = pair->value; + break; + case 5: /* we */ + to = pair->value; + break; + case 13: /* request / sending */ + status = atoi(pair->value); + break; + case 20: /* url */ + url = pair->value; + break; + case 192: /*checksum */ + checksum = atoi(pair->value); + break; + } + } + + switch (status) { + case 1: /* this is a request, ignore for now */ + YAHOO_CALLBACK(ext_yahoo_got_buddyicon_request) (yd->client_id, + to, from); + break; + case 2: /* this is cool - we get a picture :) */ + YAHOO_CALLBACK(ext_yahoo_got_buddyicon) (yd->client_id, to, + from, url, checksum); + break; + } +} + +static void yahoo_process_picture_upload(struct yahoo_input_data *yid, + struct yahoo_packet *pkt) +{ + struct yahoo_data *yd = yid->yd; + YList *l; + char *url; + + if (pkt->status != 1) + return; /* something went wrong */ + + for (l = pkt->hash; l; l = l->next) { + struct yahoo_pair *pair = l->data; + + switch (pair->key) { + case 5: /* we */ + break; + case 20: /* url */ + url = pair->value; + break; + case 27: /* local filename */ + break; + case 38: /* time */ + break; + } + } + + YAHOO_CALLBACK(ext_yahoo_buddyicon_uploaded) (yd->client_id, url); +} + +void yahoo_login(int id, int initial) +{ + struct yahoo_data *yd = find_conn_by_id(id); + struct connect_callback_data *ccd; + struct yahoo_server_settings *yss; + int tag; + + char *host; + + struct yahoo_input_data *yid = y_new0(struct yahoo_input_data, 1); + yid->yd = yd; + yid->type = YAHOO_CONNECTION_PAGER; + inputs = y_list_prepend(inputs, yid); + + yd->initial_status = initial; + yss = yd->server_settings; + + ccd = y_new0(struct connect_callback_data, 1); + ccd->yd = yd; + + host = yss->pager_host; + + if (!host) + host = yss->pager_host_list[0]; + + tag = YAHOO_CALLBACK(ext_yahoo_connect_async) (yd->client_id, + host, yss->pager_port, yahoo_connected, ccd, 0); + + /* + * if tag <= 0, then callback has already been called + * so ccd will have been freed + */ + if (tag > 0) + ccd->tag = tag; + else if (tag < 0) + YAHOO_CALLBACK(ext_yahoo_login_response) (yd->client_id, + YAHOO_LOGIN_SOCK, NULL); +} + +static void yahoo_auth_https(struct yahoo_data *yd) +{ + char url[256]; + char *user_encoded, *pass_encoded, *seed_encoded; + + struct yahoo_input_data *yid = y_new0(struct yahoo_input_data, 1); + + yid->yd = yd; + yid->type = YAHOO_CONNECTION_AUTH; + + inputs = y_list_prepend(inputs, yid); + + user_encoded = yahoo_urlencode(yid->yd->user); + pass_encoded = yahoo_urlencode(yid->yd->password); + seed_encoded = yahoo_urlencode(yid->yd->seed); + + snprintf(url, sizeof(url), + "https://login.yahoo.com/config/pwtoken_get?src=ymsgr&ts=" + "&login=%s&passwd=%s&chal=%s", user_encoded, pass_encoded, + seed_encoded); + + yahoo_http_get(yid->yd->client_id, url, NULL, 1, 0, + _yahoo_http_connected, yid); + + FREE(user_encoded); + FREE(pass_encoded); + FREE(seed_encoded); +} + +static void yahoo_process_auth(struct yahoo_input_data *yid, + struct yahoo_packet *pkt) +{ + char *seed = NULL; + char *sn = NULL; + YList *l = pkt->hash; + int m = 0; + struct yahoo_data *yd = yid->yd; + + while (l) { + struct yahoo_pair *pair = l->data; + + switch (pair->key) { + case 94: + seed = pair->value; + break; + case 1: + sn = pair->value; + break; + case 13: + m = atoi(pair->value); + break; + } + l = l->next; + } + + if (!seed) + return; + + yd->seed = strdup(seed); + + if (m==2) + yahoo_auth_https(yd); + else { + /* call error */ + WARNING(("unknown auth type %d", m)); + YAHOO_CALLBACK(ext_yahoo_login_response) (yd->client_id, + YAHOO_LOGIN_UNKNOWN, NULL); + } +} + +static void yahoo_send_auth(struct yahoo_data *yd) +{ + + struct yahoo_packet *packet; + + unsigned char crypt_hash[25]; + + md5_byte_t result[16]; + md5_state_t ctx; + + struct yahoo_input_data *yid = + find_input_by_id_and_type(yd->client_id, + YAHOO_CONNECTION_PAGER); + + /* HTTPS */ + md5_init(&ctx); + md5_append(&ctx, (md5_byte_t *)yd->crumb, strlen(yd->crumb)); + md5_append(&ctx, (md5_byte_t *)yd->seed, strlen(yd->seed)); + md5_finish(&ctx, result); + + to_y64(crypt_hash, result, 16); + + packet = yahoo_packet_new(YAHOO_SERVICE_AUTHRESP, + yd->initial_status, yd->session_id); + yahoo_packet_hash(packet, 1, yd->user); + yahoo_packet_hash(packet, 0, yd->user); + yahoo_packet_hash(packet, 277, yd->cookie_y); + yahoo_packet_hash(packet, 278, yd->cookie_t); + yahoo_packet_hash(packet, 307, (char *)crypt_hash); + yahoo_packet_hash(packet, 244, "4194239"); /* Rekkanoryo says this is the build number */ + yahoo_packet_hash(packet, 2, yd->user); + yahoo_packet_hash(packet, 2, "1"); + yahoo_packet_hash(packet, 59, yd->cookie_b); + yahoo_packet_hash(packet, 98, "us"); /* TODO Put country code */ + yahoo_packet_hash(packet, 135, "9.0.0.2152"); + + yahoo_send_packet(yid, packet, 0); + + yahoo_packet_free(packet); +} + +static void yahoo_process_auth_resp(struct yahoo_input_data *yid, + struct yahoo_packet *pkt) +{ + struct yahoo_data *yd = yid->yd; + char *login_id; + char *handle; + char *url = NULL; + int login_status = -1; + + YList *l; + + for (l = pkt->hash; l; l = l->next) { + struct yahoo_pair *pair = l->data; + if (pair->key == 0) + login_id = pair->value; + else if (pair->key == 1) + handle = pair->value; + else if (pair->key == 20) + url = pair->value; + else if (pair->key == 66) + login_status = atoi(pair->value); + } + + if (pkt->status == YPACKET_STATUS_DISCONNECTED) { + YAHOO_CALLBACK(ext_yahoo_login_response) (yd->client_id, + login_status, url); + /* yahoo_logoff(yd->client_id); */ + } +} + +static void yahoo_process_mail(struct yahoo_input_data *yid, + struct yahoo_packet *pkt) +{ + struct yahoo_data *yd = yid->yd; + char *who = NULL; + char *email = NULL; + char *subj = NULL; + int count = 0; + YList *l; + + for (l = pkt->hash; l; l = l->next) { + struct yahoo_pair *pair = l->data; + if (pair->key == 9) + count = strtol(pair->value, NULL, 10); + else if (pair->key == 43) + who = pair->value; + else if (pair->key == 42) + email = pair->value; + else if (pair->key == 18) + subj = pair->value; + else + LOG(("key: %d => value: %s", pair->key, pair->value)); + } + + if (who && email && subj) { + char from[1024]; + snprintf(from, sizeof(from), "%s (%s)", who, email); + YAHOO_CALLBACK(ext_yahoo_mail_notify) (yd->client_id, from, + subj, count); + } else if (count > 0) + YAHOO_CALLBACK(ext_yahoo_mail_notify) (yd->client_id, NULL, + NULL, count); +} + +static void yahoo_process_new_contact(struct yahoo_input_data *yid, + struct yahoo_packet *pkt) +{ + struct yahoo_data *yd = yid->yd; + char *me = NULL; + char *who = NULL; + char *msg = NULL; + int online = -1; + + YList *l; + + for (l = pkt->hash; l; l = l->next) { + struct yahoo_pair *pair = l->data; + if (pair->key == 4) + who = pair->value; + else if (pair->key == 5) + me = pair->value; + else if (pair->key == 14) + msg = pair->value; + else if (pair->key == 13) + online = strtol(pair->value, NULL, 10); + } + + if (who && online < 0) + YAHOO_CALLBACK(ext_yahoo_contact_added) (yd->client_id, me, who, + msg); + else if (online == 2) + YAHOO_CALLBACK(ext_yahoo_rejected) (yd->client_id, who, msg); +} + +/* UNUSED? */ +static void yahoo_process_contact(struct yahoo_input_data *yid, + struct yahoo_packet *pkt) +{ + struct yahoo_data *yd = yid->yd; + char *id = NULL; + char *who = NULL; + char *msg = NULL; + char *name = NULL; + long tm = 0L; + int state = YAHOO_STATUS_AVAILABLE; + int online = 0; + int away = 0; + int idle = 0; + int mobile = 0; + + YList *l; + + for (l = pkt->hash; l; l = l->next) { + struct yahoo_pair *pair = l->data; + if (pair->key == 1) + id = pair->value; + else if (pair->key == 3) + who = pair->value; + else if (pair->key == 14) + msg = pair->value; + else if (pair->key == 7) + name = pair->value; + else if (pair->key == 10) + state = strtol(pair->value, NULL, 10); + else if (pair->key == 15) + tm = strtol(pair->value, NULL, 10); + else if (pair->key == 13) + online = strtol(pair->value, NULL, 10); + else if (pair->key == 47) + away = strtol(pair->value, NULL, 10); + else if (pair->key == 137) + idle = strtol(pair->value, NULL, 10); + else if (pair->key == 60) + mobile = strtol(pair->value, NULL, 10); + + } + + if (id) + YAHOO_CALLBACK(ext_yahoo_contact_added) (yd->client_id, id, who, + msg); + else if (name) + YAHOO_CALLBACK(ext_yahoo_status_changed) (yd->client_id, name, + state, msg, away, idle, mobile); + else if (pkt->status == 0x07) + YAHOO_CALLBACK(ext_yahoo_rejected) (yd->client_id, who, msg); +} + +static void yahoo_process_buddyadd(struct yahoo_input_data *yid, + struct yahoo_packet *pkt) +{ + struct yahoo_data *yd = yid->yd; + char *who = NULL; + char *where = NULL; + int status = 0; + char *me = NULL; + + struct yahoo_buddy *bud = NULL; + + YList *l; + for (l = pkt->hash; l; l = l->next) { + struct yahoo_pair *pair = l->data; + if (pair->key == 1) + me = pair->value; + if (pair->key == 7) + who = pair->value; + if (pair->key == 65) + where = pair->value; + if (pair->key == 66) + status = strtol(pair->value, NULL, 10); + } + + if (!who) + return; + if (!where) + where = "Unknown"; + + bud = y_new0(struct yahoo_buddy, 1); + bud->id = strdup(who); + bud->group = strdup(where); + bud->real_name = NULL; + + yd->buddies = y_list_append(yd->buddies, bud); + + /* A non-zero status (i've seen 2) seems to mean the buddy is already + * added and is online */ + if (status) { + LOG(("Setting online see packet for info")); + yahoo_dump_unhandled(pkt); + YAHOO_CALLBACK(ext_yahoo_status_changed) (yd->client_id, who, + YAHOO_STATUS_AVAILABLE, NULL, 0, 0, 0); + } +} + +static void yahoo_process_buddydel(struct yahoo_input_data *yid, + struct yahoo_packet *pkt) +{ + struct yahoo_data *yd = yid->yd; + char *who = NULL; + char *where = NULL; + int unk_66 = 0; + char *me = NULL; + struct yahoo_buddy *bud; + + YList *buddy; + + YList *l; + for (l = pkt->hash; l; l = l->next) { + struct yahoo_pair *pair = l->data; + if (pair->key == 1) + me = pair->value; + else if (pair->key == 7) + who = pair->value; + else if (pair->key == 65) + where = pair->value; + else if (pair->key == 66) + unk_66 = strtol(pair->value, NULL, 10); + else + DEBUG_MSG(("unknown key: %d = %s", pair->key, + pair->value)); + } + + if (!who || !where) + return; + + bud = y_new0(struct yahoo_buddy, 1); + bud->id = strdup(who); + bud->group = strdup(where); + + buddy = y_list_find_custom(yd->buddies, bud, is_same_bud); + + FREE(bud->id); + FREE(bud->group); + FREE(bud); + + if (buddy) { + bud = buddy->data; + yd->buddies = y_list_remove_link(yd->buddies, buddy); + y_list_free_1(buddy); + + FREE(bud->id); + FREE(bud->group); + FREE(bud->real_name); + FREE(bud); + + bud = NULL; + } +} + +static void yahoo_process_ignore(struct yahoo_input_data *yid, + struct yahoo_packet *pkt) +{ + char *who = NULL; + int status = 0; + char *me = NULL; + int un_ignore = 0; + + YList *l; + for (l = pkt->hash; l; l = l->next) { + struct yahoo_pair *pair = l->data; + if (pair->key == 0) + who = pair->value; + if (pair->key == 1) + me = pair->value; + if (pair->key == 13) /* 1 == ignore, 2 == unignore */ + un_ignore = strtol(pair->value, NULL, 10); + if (pair->key == 66) + status = strtol(pair->value, NULL, 10); + } + + /* + * status + * 0 - ok + * 2 - already in ignore list, could not add + * 3 - not in ignore list, could not delete + * 12 - is a buddy, could not add + */ + +/* if(status) + YAHOO_CALLBACK(ext_yahoo_error)(yd->client_id, who, 0, status); +*/ +} + +static void yahoo_process_voicechat(struct yahoo_input_data *yid, + struct yahoo_packet *pkt) +{ + char *who = NULL; + char *me = NULL; + char *room = NULL; + char *voice_room = NULL; + + YList *l; + for (l = pkt->hash; l; l = l->next) { + struct yahoo_pair *pair = l->data; + if (pair->key == 4) + who = pair->value; + if (pair->key == 5) + me = pair->value; + if (pair->key == 13) + voice_room = pair->value; + if (pair->key == 57) + room = pair->value; + } + + NOTICE(("got voice chat invite from %s in %s to identity %s", who, room, + me)); + /* + * send: s:0 1:me 5:who 57:room 13:1 + * ???? s:4 5:who 10:99 19:-1615114531 + * gotr: s:4 5:who 10:99 19:-1615114615 + * ???? s:1 5:me 4:who 57:room 13:3room + * got: s:1 5:me 4:who 57:room 13:1room + * rej: s:0 1:me 5:who 57:room 13:3 + * rejr: s:4 5:who 10:99 19:-1617114599 + */ +} + +static void yahoo_process_ping(struct yahoo_input_data *yid, + struct yahoo_packet *pkt) +{ + char *errormsg = NULL; + + YList *l; + for (l = pkt->hash; l; l = l->next) { + struct yahoo_pair *pair = l->data; + if (pair->key == 16) + errormsg = pair->value; + } + + NOTICE(("got ping packet")); + YAHOO_CALLBACK(ext_yahoo_got_ping) (yid->yd->client_id, errormsg); +} + +static void yahoo_process_buddy_change_group(struct yahoo_input_data *yid, + struct yahoo_packet *pkt) +{ + YList *l; + char *me = NULL; + char *who = NULL; + char *old_group = NULL; + char *new_group = NULL; + + for (l = pkt->hash; l; l = l->next) { + struct yahoo_pair *pair = l->data; + if (pair->key == 1) + me = pair->value; + if (pair->key == 7) + who = pair->value; + if (pair->key == 224) + old_group = pair->value; + if (pair->key == 264) + new_group = pair->value; + } + + YAHOO_CALLBACK(ext_yahoo_got_buddy_change_group) (yid->yd->client_id, + me, who, old_group, new_group); +} + +static void _yahoo_webcam_get_server_connected(void *fd, int error, void *d) +{ + struct yahoo_input_data *yid = d; + char *who = yid->wcm->user; + char *data = NULL; + char *packet = NULL; + unsigned char magic_nr[] = { 0, 1, 0 }; + unsigned char header_len = 8; + unsigned int len = 0; + unsigned int pos = 0; + + if (error || !fd) { + FREE(who); + FREE(yid); + return; + } + + yid->fd = fd; + inputs = y_list_prepend(inputs, yid); + + /* send initial packet */ + if (who) + data = strdup(""); + else + data = strdup(""); + yahoo_add_to_send_queue(yid, data, strlen(data)); + FREE(data); + + /* send data */ + if (who) { + data = strdup("g="); + data = y_string_append(data, who); + data = y_string_append(data, "\r\n"); + } else { + data = strdup("f=1\r\n"); + } + len = strlen(data); + packet = y_new0(char, header_len + len); + packet[pos++] = header_len; + memcpy(packet + pos, magic_nr, sizeof(magic_nr)); + pos += sizeof(magic_nr); + pos += yahoo_put32(packet + pos, len); + memcpy(packet + pos, data, len); + pos += len; + yahoo_add_to_send_queue(yid, packet, pos); + FREE(packet); + FREE(data); + + yid->read_tag = + YAHOO_CALLBACK(ext_yahoo_add_handler) (yid->yd->client_id, fd, + YAHOO_INPUT_READ, yid); +} + +static void yahoo_webcam_get_server(struct yahoo_input_data *y, char *who, + char *key) +{ + struct yahoo_input_data *yid = y_new0(struct yahoo_input_data, 1); + struct yahoo_server_settings *yss = y->yd->server_settings; + + yid->type = YAHOO_CONNECTION_WEBCAM_MASTER; + yid->yd = y->yd; + yid->wcm = y_new0(struct yahoo_webcam, 1); + yid->wcm->user = who ? strdup(who) : NULL; + yid->wcm->direction = who ? YAHOO_WEBCAM_DOWNLOAD : YAHOO_WEBCAM_UPLOAD; + yid->wcm->key = strdup(key); + + YAHOO_CALLBACK(ext_yahoo_connect_async) (yid->yd->client_id, + yss->webcam_host, yss->webcam_port, + _yahoo_webcam_get_server_connected, yid, 0); + +} + +static YList *webcam_queue = NULL; +static void yahoo_process_webcam_key(struct yahoo_input_data *yid, + struct yahoo_packet *pkt) +{ + char *me = NULL; + char *key = NULL; + char *who = NULL; + + YList *l; + yahoo_dump_unhandled(pkt); + for (l = pkt->hash; l; l = l->next) { + struct yahoo_pair *pair = l->data; + if (pair->key == 5) + me = pair->value; + if (pair->key == 61) + key = pair->value; + } + + l = webcam_queue; + if (!l) + return; + who = l->data; + webcam_queue = y_list_remove_link(webcam_queue, webcam_queue); + y_list_free_1(l); + yahoo_webcam_get_server(yid, who, key); + FREE(who); +} + +static void yahoo_packet_process(struct yahoo_input_data *yid, + struct yahoo_packet *pkt) +{ + DEBUG_MSG(("yahoo_packet_process: 0x%02x", pkt->service)); + switch (pkt->service) { + case YAHOO_SERVICE_USERSTAT: + case YAHOO_SERVICE_LOGON: + case YAHOO_SERVICE_LOGOFF: + case YAHOO_SERVICE_ISAWAY: + case YAHOO_SERVICE_ISBACK: + case YAHOO_SERVICE_GAMELOGON: + case YAHOO_SERVICE_GAMELOGOFF: + case YAHOO_SERVICE_IDACT: + case YAHOO_SERVICE_IDDEACT: + case YAHOO_SERVICE_Y6_STATUS_UPDATE: + case YAHOO_SERVICE_Y8_STATUS: + yahoo_process_status(yid, pkt); + break; + case YAHOO_SERVICE_NOTIFY: + yahoo_process_notify(yid, pkt); + break; + case YAHOO_SERVICE_MESSAGE: + case YAHOO_SERVICE_GAMEMSG: + case YAHOO_SERVICE_SYSMESSAGE: + yahoo_process_message(yid, pkt); + break; + case YAHOO_SERVICE_NEWMAIL: + yahoo_process_mail(yid, pkt); + break; + case YAHOO_SERVICE_Y7_AUTHORIZATION: + yahoo_process_new_contact(yid, pkt); + break; + case YAHOO_SERVICE_NEWCONTACT: + yahoo_process_contact(yid, pkt); + break; + case YAHOO_SERVICE_LIST: + yahoo_process_list(yid, pkt); + break; + case YAHOO_SERVICE_VERIFY: + yahoo_process_verify(yid, pkt); + break; + case YAHOO_SERVICE_AUTH: + yahoo_process_auth(yid, pkt); + break; + case YAHOO_SERVICE_AUTHRESP: + yahoo_process_auth_resp(yid, pkt); + break; + case YAHOO_SERVICE_CONFINVITE: + case YAHOO_SERVICE_CONFADDINVITE: + case YAHOO_SERVICE_CONFDECLINE: + case YAHOO_SERVICE_CONFLOGON: + case YAHOO_SERVICE_CONFLOGOFF: + case YAHOO_SERVICE_CONFMSG: + yahoo_process_conference(yid, pkt); + break; + case YAHOO_SERVICE_CHATONLINE: + case YAHOO_SERVICE_CHATGOTO: + case YAHOO_SERVICE_CHATJOIN: + case YAHOO_SERVICE_CHATLEAVE: + case YAHOO_SERVICE_CHATEXIT: + case YAHOO_SERVICE_CHATLOGOUT: + case YAHOO_SERVICE_CHATPING: + case YAHOO_SERVICE_COMMENT: + yahoo_process_chat(yid, pkt); + break; + case YAHOO_SERVICE_P2PFILEXFER: + case YAHOO_SERVICE_Y7_FILETRANSFER: + yahoo_process_filetransfer(yid, pkt); + break; + case YAHOO_SERVICE_Y7_FILETRANSFERINFO: + yahoo_process_filetransferinfo(yid, pkt); + break; + case YAHOO_SERVICE_Y7_FILETRANSFERACCEPT: + yahoo_process_filetransferaccept(yid, pkt); + break; + case YAHOO_SERVICE_ADDBUDDY: + yahoo_process_buddyadd(yid, pkt); + break; + case YAHOO_SERVICE_REMBUDDY: + yahoo_process_buddydel(yid, pkt); + break; + case YAHOO_SERVICE_IGNORECONTACT: + yahoo_process_ignore(yid, pkt); + break; + case YAHOO_SERVICE_VOICECHAT: + yahoo_process_voicechat(yid, pkt); + break; + case YAHOO_SERVICE_WEBCAM: + yahoo_process_webcam_key(yid, pkt); + break; + case YAHOO_SERVICE_PING: + yahoo_process_ping(yid, pkt); + break; + case YAHOO_SERVICE_Y7_CHANGE_GROUP: + yahoo_process_buddy_change_group(yid, pkt); + break; + case YAHOO_SERVICE_IDLE: + case YAHOO_SERVICE_MAILSTAT: + case YAHOO_SERVICE_CHATINVITE: + case YAHOO_SERVICE_CALENDAR: + case YAHOO_SERVICE_NEWPERSONALMAIL: + case YAHOO_SERVICE_ADDIDENT: + case YAHOO_SERVICE_ADDIGNORE: + case YAHOO_SERVICE_GOTGROUPRENAME: + case YAHOO_SERVICE_GROUPRENAME: + case YAHOO_SERVICE_PASSTHROUGH2: + case YAHOO_SERVICE_CHATLOGON: + case YAHOO_SERVICE_CHATLOGOFF: + case YAHOO_SERVICE_CHATMSG: + case YAHOO_SERVICE_REJECTCONTACT: + case YAHOO_SERVICE_PEERTOPEER: + WARNING(("unhandled service 0x%02x", pkt->service)); + yahoo_dump_unhandled(pkt); + break; + case YAHOO_SERVICE_PICTURE: + yahoo_process_picture(yid, pkt); + break; + case YAHOO_SERVICE_PICTURE_CHECKSUM: + yahoo_process_picture_checksum(yid, pkt); + break; + case YAHOO_SERVICE_PICTURE_UPLOAD: + yahoo_process_picture_upload(yid, pkt); + break; + case YAHOO_SERVICE_Y8_LIST: /* Buddy List */ + yahoo_process_buddy_list(yid, pkt); + break; + default: + WARNING(("unknown service 0x%02x", pkt->service)); + yahoo_dump_unhandled(pkt); + break; + } +} + +static struct yahoo_packet *yahoo_getdata(struct yahoo_input_data *yid) +{ + struct yahoo_packet *pkt; + struct yahoo_data *yd = yid->yd; + int pos = 0; + int pktlen; + + if (!yd) + return NULL; + + DEBUG_MSG(("rxlen is %d", yid->rxlen)); + if (yid->rxlen < YAHOO_PACKET_HDRLEN) { + DEBUG_MSG(("len < YAHOO_PACKET_HDRLEN")); + return NULL; + } + + pos += 4; /* YMSG */ + pos += 2; + pos += 2; + + pktlen = yahoo_get16(yid->rxqueue + pos); + pos += 2; + DEBUG_MSG(("%d bytes to read, rxlen is %d", pktlen, yid->rxlen)); + + if (yid->rxlen < (YAHOO_PACKET_HDRLEN + pktlen)) { + DEBUG_MSG(("len < YAHOO_PACKET_HDRLEN + pktlen")); + return NULL; + } + + LOG(("reading packet")); + yahoo_packet_dump(yid->rxqueue, YAHOO_PACKET_HDRLEN + pktlen); + + pkt = yahoo_packet_new(0, 0, 0); + + pkt->service = yahoo_get16(yid->rxqueue + pos); + pos += 2; + pkt->status = yahoo_get32(yid->rxqueue + pos); + pos += 4; + DEBUG_MSG(("Yahoo Service: 0x%02x Status: %d", pkt->service, + pkt->status)); + pkt->id = yahoo_get32(yid->rxqueue + pos); + pos += 4; + + yd->session_id = pkt->id; + + yahoo_packet_read(pkt, yid->rxqueue + pos, pktlen); + + yid->rxlen -= YAHOO_PACKET_HDRLEN + pktlen; + DEBUG_MSG(("rxlen == %d, rxqueue == %p", yid->rxlen, yid->rxqueue)); + if (yid->rxlen > 0) { + unsigned char *tmp = y_memdup(yid->rxqueue + YAHOO_PACKET_HDRLEN + + pktlen, yid->rxlen); + FREE(yid->rxqueue); + yid->rxqueue = tmp; + DEBUG_MSG(("new rxlen == %d, rxqueue == %p", yid->rxlen, + yid->rxqueue)); + } else { + DEBUG_MSG(("freed rxqueue == %p", yid->rxqueue)); + FREE(yid->rxqueue); + } + + return pkt; +} + +static struct yab *yahoo_yab_read(unsigned char *d, int len) +{ + char *st, *en; + char *data = (char *)d; + struct yab *yab = NULL; + + data[len] = '\0'; + + DEBUG_MSG(("Got yab: %s", data)); + st = en = strstr(data, "e0=\""); + if (st) { + yab = y_new0(struct yab, 1); + + st += strlen("e0=\""); + en = strchr(st, '"'); + *en++ = '\0'; + yab->email = yahoo_xmldecode(st); + } + + if (!en) + return NULL; + + st = strstr(en, "id=\""); + if (st) { + st += strlen("id=\""); + en = strchr(st, '"'); + *en++ = '\0'; + yab->yid = atoi(yahoo_xmldecode(st)); + } + + st = strstr(en, "fn=\""); + if (st) { + st += strlen("fn=\""); + en = strchr(st, '"'); + *en++ = '\0'; + yab->fname = yahoo_xmldecode(st); + } + + st = strstr(en, "ln=\""); + if (st) { + st += strlen("ln=\""); + en = strchr(st, '"'); + *en++ = '\0'; + yab->lname = yahoo_xmldecode(st); + } + + st = strstr(en, "nn=\""); + if (st) { + st += strlen("nn=\""); + en = strchr(st, '"'); + *en++ = '\0'; + yab->nname = yahoo_xmldecode(st); + } + + st = strstr(en, "yi=\""); + if (st) { + st += strlen("yi=\""); + en = strchr(st, '"'); + *en++ = '\0'; + yab->id = yahoo_xmldecode(st); + } + + st = strstr(en, "hphone=\""); + if (st) { + st += strlen("hphone=\""); + en = strchr(st, '"'); + *en++ = '\0'; + yab->hphone = yahoo_xmldecode(st); + } + + st = strstr(en, "wphone=\""); + if (st) { + st += strlen("wphone=\""); + en = strchr(st, '"'); + *en++ = '\0'; + yab->wphone = yahoo_xmldecode(st); + } + + st = strstr(en, "mphone=\""); + if (st) { + st += strlen("mphone=\""); + en = strchr(st, '"'); + *en++ = '\0'; + yab->mphone = yahoo_xmldecode(st); + } + + st = strstr(en, "dbid=\""); + if (st) { + st += strlen("dbid=\""); + en = strchr(st, '"'); + *en++ = '\0'; + yab->dbid = atoi(st); + } + + return yab; +} + +static struct yab *yahoo_getyab(struct yahoo_input_data *yid) +{ + struct yab *yab = NULL; + int pos = 0, end = 0; + struct yahoo_data *yd = yid->yd; + + if (!yd) + return NULL; + + do { + DEBUG_MSG(("rxlen is %d", yid->rxlen)); + + if (yid->rxlen <= strlen("rxlen - strlen("rxqueue + pos, "= yid->rxlen - 1) + return NULL; + + end = pos + 2; + /* end with > */ + while (end < yid->rxlen - strlen(">") + && memcmp(yid->rxqueue + end, ">", strlen(">"))) + end++; + + if (end >= yid->rxlen - 1) + return NULL; + + yab = yahoo_yab_read(yid->rxqueue + pos, end + 2 - pos); + + yid->rxlen -= end + 1; + DEBUG_MSG(("rxlen == %d, rxqueue == %p", yid->rxlen, + yid->rxqueue)); + if (yid->rxlen > 0) { + unsigned char *tmp = + y_memdup(yid->rxqueue + end + 1, yid->rxlen); + FREE(yid->rxqueue); + yid->rxqueue = tmp; + DEBUG_MSG(("new rxlen == %d, rxqueue == %p", yid->rxlen, + yid->rxqueue)); + } else { + DEBUG_MSG(("freed rxqueue == %p", yid->rxqueue)); + FREE(yid->rxqueue); + } + + } while (!yab && end < yid->rxlen - 1); + + return yab; +} + +static char *yahoo_getwebcam_master(struct yahoo_input_data *yid) +{ + unsigned int pos = 0; + unsigned int len = 0; + unsigned int status = 0; + char *server = NULL; + struct yahoo_data *yd = yid->yd; + + if (!yid || !yd) + return NULL; + + DEBUG_MSG(("rxlen is %d", yid->rxlen)); + + len = yid->rxqueue[pos++]; + if (yid->rxlen < len) + return NULL; + + /* extract status (0 = ok, 6 = webcam not online) */ + status = yid->rxqueue[pos++]; + + if (status == 0) { + pos += 2; /* skip next 2 bytes */ + server = y_memdup(yid->rxqueue + pos, 16); + pos += 16; + } else if (status == 6) { + YAHOO_CALLBACK(ext_yahoo_webcam_closed) + (yd->client_id, yid->wcm->user, 4); + } + + /* skip rest of the data */ + + yid->rxlen -= len; + DEBUG_MSG(("rxlen == %d, rxqueue == %p", yid->rxlen, yid->rxqueue)); + if (yid->rxlen > 0) { + unsigned char *tmp = y_memdup(yid->rxqueue + pos, yid->rxlen); + FREE(yid->rxqueue); + yid->rxqueue = tmp; + DEBUG_MSG(("new rxlen == %d, rxqueue == %p", yid->rxlen, + yid->rxqueue)); + } else { + DEBUG_MSG(("freed rxqueue == %p", yid->rxqueue)); + FREE(yid->rxqueue); + } + + return server; +} + +static int yahoo_get_webcam_data(struct yahoo_input_data *yid) +{ + unsigned char reason = 0; + unsigned int pos = 0; + unsigned int begin = 0; + unsigned int end = 0; + unsigned int closed = 0; + unsigned char header_len = 0; + char *who; + int connect = 0; + struct yahoo_data *yd = yid->yd; + + if (!yd) + return -1; + + if (!yid->wcm || !yid->wcd || !yid->rxlen) + return -1; + + DEBUG_MSG(("rxlen is %d", yid->rxlen)); + + /* if we are not reading part of image then read header */ + if (!yid->wcd->to_read) { + header_len = yid->rxqueue[pos++]; + yid->wcd->packet_type = 0; + + if (yid->rxlen < header_len) + return 0; + + if (header_len >= 8) { + reason = yid->rxqueue[pos++]; + /* next 2 bytes should always be 05 00 */ + pos += 2; + yid->wcd->data_size = yahoo_get32(yid->rxqueue + pos); + pos += 4; + yid->wcd->to_read = yid->wcd->data_size; + } + if (header_len >= 13) { + yid->wcd->packet_type = yid->rxqueue[pos++]; + yid->wcd->timestamp = yahoo_get32(yid->rxqueue + pos); + pos += 4; + } + + /* skip rest of header */ + pos = header_len; + } + + begin = pos; + pos += yid->wcd->to_read; + if (pos > yid->rxlen) + pos = yid->rxlen; + + /* if it is not an image then make sure we have the whole packet */ + if (yid->wcd->packet_type != 0x02) { + if ((pos - begin) != yid->wcd->data_size) { + yid->wcd->to_read = 0; + return 0; + } else { + yahoo_packet_dump(yid->rxqueue + begin, pos - begin); + } + } + + DEBUG_MSG(("packet type %.2X, data length %d", yid->wcd->packet_type, + yid->wcd->data_size)); + + /* find out what kind of packet we got */ + switch (yid->wcd->packet_type) { + case 0x00: + /* user requests to view webcam (uploading) */ + if (yid->wcd->data_size && + yid->wcm->direction == YAHOO_WEBCAM_UPLOAD) { + end = begin; + while (end <= yid->rxlen && yid->rxqueue[end++] != 13) ; + if (end > begin) { + who = y_memdup(yid->rxqueue + begin, + end - begin); + who[end - begin - 1] = 0; + YAHOO_CALLBACK(ext_yahoo_webcam_viewer) (yd-> + client_id, who + 2, 2); + FREE(who); + } + } + + if (yid->wcm->direction == YAHOO_WEBCAM_DOWNLOAD) { + /* timestamp/status field */ + /* 0 = declined viewing permission */ + /* 1 = accepted viewing permission */ + if (yid->wcd->timestamp == 0) { + YAHOO_CALLBACK(ext_yahoo_webcam_closed) (yd-> + client_id, yid->wcm->user, 3); + } + } + break; + case 0x01: /* status packets?? */ + /* timestamp contains status info */ + /* 00 00 00 01 = we have data?? */ + break; + case 0x02: /* image data */ + YAHOO_CALLBACK(ext_yahoo_got_webcam_image) (yd->client_id, + yid->wcm->user, yid->rxqueue + begin, + yid->wcd->data_size, pos - begin, yid->wcd->timestamp); + break; + case 0x05: /* response packets when uploading */ + if (!yid->wcd->data_size) { + YAHOO_CALLBACK(ext_yahoo_webcam_data_request) (yd-> + client_id, yid->wcd->timestamp); + } + break; + case 0x07: /* connection is closing */ + switch (reason) { + case 0x01: /* user closed connection */ + closed = 1; + break; + case 0x0F: /* user cancelled permission */ + closed = 2; + break; + } + YAHOO_CALLBACK(ext_yahoo_webcam_closed) (yd->client_id, + yid->wcm->user, closed); + break; + case 0x0C: /* user connected */ + case 0x0D: /* user disconnected */ + if (yid->wcd->data_size) { + who = y_memdup(yid->rxqueue + begin, pos - begin + 1); + who[pos - begin] = 0; + if (yid->wcd->packet_type == 0x0C) + connect = 1; + else + connect = 0; + YAHOO_CALLBACK(ext_yahoo_webcam_viewer) (yd->client_id, + who, connect); + FREE(who); + } + break; + case 0x13: /* user data */ + /* i=user_ip (ip of the user we are viewing) */ + /* j=user_ext_ip (external ip of the user we */ + /* are viewing) */ + break; + case 0x17: /* ?? */ + break; + } + yid->wcd->to_read -= pos - begin; + + yid->rxlen -= pos; + DEBUG_MSG(("rxlen == %d, rxqueue == %p", yid->rxlen, yid->rxqueue)); + if (yid->rxlen > 0) { + unsigned char *tmp = y_memdup(yid->rxqueue + pos, yid->rxlen); + FREE(yid->rxqueue); + yid->rxqueue = tmp; + DEBUG_MSG(("new rxlen == %d, rxqueue == %p", yid->rxlen, + yid->rxqueue)); + } else { + DEBUG_MSG(("freed rxqueue == %p", yid->rxqueue)); + FREE(yid->rxqueue); + } + + /* If we read a complete packet return success */ + if (!yid->wcd->to_read) + return 1; + + return 0; +} + +int yahoo_write_ready(int id, void *fd, void *data) +{ + struct yahoo_input_data *yid = data; + int len; + struct data_queue *tx; + + LOG(("write callback: id=%d fd=%p data=%p", id, fd, data)); + if (!yid || !yid->txqueues) + return -2; + + tx = yid->txqueues->data; + LOG(("writing %d bytes", tx->len)); + len = yahoo_send_data(fd, tx->queue, MIN(1024, tx->len)); + + if (len == -1 && errno == EAGAIN) + return 1; + + if (len <= 0) { + int e = errno; + DEBUG_MSG(("len == %d (<= 0)", len)); + while (yid->txqueues) { + YList *l = yid->txqueues; + tx = l->data; + free(tx->queue); + free(tx); + yid->txqueues = + y_list_remove_link(yid->txqueues, + yid->txqueues); + y_list_free_1(l); + } + LOG(("yahoo_write_ready(%d, %p) len < 0", id, fd)); + YAHOO_CALLBACK(ext_yahoo_remove_handler) (id, yid->write_tag); + yid->write_tag = 0; + errno = e; + return 0; + } + + tx->len -= len; + if (tx->len > 0) { + unsigned char *tmp = y_memdup(tx->queue + len, tx->len); + FREE(tx->queue); + tx->queue = tmp; + } else { + YList *l = yid->txqueues; + free(tx->queue); + free(tx); + yid->txqueues = + y_list_remove_link(yid->txqueues, yid->txqueues); + y_list_free_1(l); + /* + if(!yid->txqueues) + LOG(("yahoo_write_ready(%d, %d) !yxqueues", id, fd)); + */ + if (!yid->txqueues) { + LOG(("yahoo_write_ready(%d, %p) !txqueues", id, fd)); + YAHOO_CALLBACK(ext_yahoo_remove_handler) (id, + yid->write_tag); + yid->write_tag = 0; + } + } + + return 1; +} + +static void yahoo_process_pager_connection(struct yahoo_input_data *yid, + int over) +{ + struct yahoo_packet *pkt; + struct yahoo_data *yd = yid->yd; + int id = yd->client_id; + + if (over) + return; + + while (find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER) + && (pkt = yahoo_getdata(yid)) != NULL) { + + yahoo_packet_process(yid, pkt); + + yahoo_packet_free(pkt); + } +} + +static void yahoo_process_chatcat_connection(struct yahoo_input_data *yid, + int over) +{ + if (over) + return; + + if (strstr((char *)yid->rxqueue + (yid->rxlen - 20), "")) { + YAHOO_CALLBACK(ext_yahoo_chat_cat_xml) (yid->yd->client_id, + (char *)yid->rxqueue); + } +} + +static void yahoo_process_yab_connection(struct yahoo_input_data *yid, int over) +{ + struct yahoo_data *yd = yid->yd; + struct yab *yab; + YList *buds; + int changed = 0; + int id = yd->client_id; + int yab_used = 0; + + LOG(("Got data for YAB")); + + if (over) + return; + + while (find_input_by_id_and_type(id, YAHOO_CONNECTION_YAB) + && (yab = yahoo_getyab(yid)) != NULL) { + if (!yab->id) + continue; + + changed = 1; + yab_used = 0; + for (buds = yd->buddies; buds; buds = buds->next) { + struct yahoo_buddy *bud = buds->data; + if (!strcmp(bud->id, yab->id)) { + yab_used = 1; + bud->yab_entry = yab; + if (yab->nname) { + bud->real_name = strdup(yab->nname); + } else if (yab->fname && yab->lname) { + bud->real_name = y_new0(char, + strlen(yab->fname) + + strlen(yab->lname) + 2); + sprintf(bud->real_name, "%s %s", + yab->fname, yab->lname); + } else if (yab->fname) { + bud->real_name = strdup(yab->fname); + } + break; /* for */ + } + } + + if (!yab_used) { + FREE(yab->fname); + FREE(yab->lname); + FREE(yab->nname); + FREE(yab->id); + FREE(yab->email); + FREE(yab->hphone); + FREE(yab->wphone); + FREE(yab->mphone); + FREE(yab); + } + + } + + if (changed) + YAHOO_CALLBACK(ext_yahoo_got_buddies) (yd->client_id, + yd->buddies); +} + +static void yahoo_process_search_connection(struct yahoo_input_data *yid, + int over) +{ + struct yahoo_found_contact *yct = NULL; + char *p = (char *)yid->rxqueue, *np, *cp; + int k, n; + int start = 0, found = 0, total = 0; + YList *contacts = NULL; + struct yahoo_input_data *pyid = + find_input_by_id_and_type(yid->yd->client_id, + YAHOO_CONNECTION_PAGER); + + if (!over || !pyid) + return; + + if (p && (p = strstr(p, "\r\n\r\n"))) { + p += 4; + + for (k = 0; (p = strchr(p, 4)) && (k < 4); k++) { + p++; + n = atoi(p); + switch (k) { + case 0: + found = pyid->ys->lsearch_nfound = n; + break; + case 2: + start = pyid->ys->lsearch_nstart = n; + break; + case 3: + total = pyid->ys->lsearch_ntotal = n; + break; + } + } + + if (p) + p++; + + k = 0; + while (p && *p) { + cp = p; + np = strchr(p, 4); + + if (!np) + break; + *np = 0; + p = np + 1; + + switch (k++) { + case 1: + if (strlen(cp) > 2 + && y_list_length(contacts) < total) { + yct = y_new0(struct yahoo_found_contact, + 1); + contacts = y_list_append(contacts, yct); + yct->id = cp + 2; + } else { + *p = 0; + } + break; + case 2: + yct->online = !strcmp(cp, "2") ? 1 : 0; + break; + case 3: + yct->gender = cp; + break; + case 4: + yct->age = atoi(cp); + break; + case 5: + /* not worth the context switch for strcmp */ + if (cp[0] != '\005' || cp[1] != '\000') + yct->location = cp; + k = 0; + break; + } + } + } + + YAHOO_CALLBACK(ext_yahoo_got_search_result) (yid->yd->client_id, found, + start, total, contacts); + + while (contacts) { + YList *node = contacts; + contacts = y_list_remove_link(contacts, node); + free(node->data); + y_list_free_1(node); + } +} + +static void _yahoo_webcam_connected(void *fd, int error, void *d) +{ + struct yahoo_input_data *yid = d; + struct yahoo_webcam *wcm = yid->wcm; + struct yahoo_data *yd = yid->yd; + char conn_type[100]; + char *data = NULL; + char *packet = NULL; + unsigned char magic_nr[] = { 1, 0, 0, 0, 1 }; + unsigned header_len = 0; + unsigned int len = 0; + unsigned int pos = 0; + + if (error || !fd) { + FREE(yid); + return; + } + + yid->fd = fd; + inputs = y_list_prepend(inputs, yid); + + LOG(("Connected")); + /* send initial packet */ + switch (wcm->direction) { + case YAHOO_WEBCAM_DOWNLOAD: + data = strdup(""); + break; + case YAHOO_WEBCAM_UPLOAD: + data = strdup(""); + break; + default: + return; + } + yahoo_add_to_send_queue(yid, data, strlen(data)); + FREE(data); + + /* send data */ + switch (wcm->direction) { + case YAHOO_WEBCAM_DOWNLOAD: + header_len = 8; + data = strdup("a=2\r\nc=us\r\ne=21\r\nu="); + data = y_string_append(data, yd->user); + data = y_string_append(data, "\r\nt="); + data = y_string_append(data, wcm->key); + data = y_string_append(data, "\r\ni="); + data = y_string_append(data, wcm->my_ip); + data = y_string_append(data, "\r\ng="); + data = y_string_append(data, wcm->user); + data = y_string_append(data, "\r\no=w-2-5-1\r\np="); + snprintf(conn_type, sizeof(conn_type), "%d", wcm->conn_type); + data = y_string_append(data, conn_type); + data = y_string_append(data, "\r\n"); + break; + case YAHOO_WEBCAM_UPLOAD: + header_len = 13; + data = strdup("a=2\r\nc=us\r\nu="); + data = y_string_append(data, yd->user); + data = y_string_append(data, "\r\nt="); + data = y_string_append(data, wcm->key); + data = y_string_append(data, "\r\ni="); + data = y_string_append(data, wcm->my_ip); + data = y_string_append(data, "\r\no=w-2-5-1\r\np="); + snprintf(conn_type, sizeof(conn_type), "%d", wcm->conn_type); + data = y_string_append(data, conn_type); + data = y_string_append(data, "\r\nb="); + data = y_string_append(data, wcm->description); + data = y_string_append(data, "\r\n"); + break; + } + + len = strlen(data); + packet = y_new0(char, header_len + len); + packet[pos++] = header_len; + packet[pos++] = 0; + switch (wcm->direction) { + case YAHOO_WEBCAM_DOWNLOAD: + packet[pos++] = 1; + packet[pos++] = 0; + break; + case YAHOO_WEBCAM_UPLOAD: + packet[pos++] = 5; + packet[pos++] = 0; + break; + } + + pos += yahoo_put32(packet + pos, len); + if (wcm->direction == YAHOO_WEBCAM_UPLOAD) { + memcpy(packet + pos, magic_nr, sizeof(magic_nr)); + pos += sizeof(magic_nr); + } + memcpy(packet + pos, data, len); + yahoo_add_to_send_queue(yid, packet, header_len + len); + FREE(packet); + FREE(data); + + yid->read_tag = + YAHOO_CALLBACK(ext_yahoo_add_handler) (yid->yd->client_id, + yid->fd, YAHOO_INPUT_READ, yid); +} + +static void yahoo_webcam_connect(struct yahoo_input_data *y) +{ + struct yahoo_webcam *wcm = y->wcm; + struct yahoo_input_data *yid; + struct yahoo_server_settings *yss; + + if (!wcm || !wcm->server || !wcm->key) + return; + + yid = y_new0(struct yahoo_input_data, 1); + yid->type = YAHOO_CONNECTION_WEBCAM; + yid->yd = y->yd; + + /* copy webcam data to new connection */ + yid->wcm = y->wcm; + y->wcm = NULL; + + yss = y->yd->server_settings; + + yid->wcd = y_new0(struct yahoo_webcam_data, 1); + + LOG(("Connecting to: %s:%d", wcm->server, wcm->port)); + YAHOO_CALLBACK(ext_yahoo_connect_async) (y->yd->client_id, wcm->server, + wcm->port, _yahoo_webcam_connected, yid, 0); + +} + +static void yahoo_process_webcam_master_connection(struct yahoo_input_data *yid, + int over) +{ + char *server; + struct yahoo_server_settings *yss; + + if (over) + return; + + server = yahoo_getwebcam_master(yid); + + if (server) { + yss = yid->yd->server_settings; + yid->wcm->server = strdup(server); + yid->wcm->port = yss->webcam_port; + yid->wcm->conn_type = yss->conn_type; + yid->wcm->my_ip = strdup(yss->local_host); + if (yid->wcm->direction == YAHOO_WEBCAM_UPLOAD) + yid->wcm->description = strdup(yss->webcam_description); + yahoo_webcam_connect(yid); + FREE(server); + } +} + +static void yahoo_process_webcam_connection(struct yahoo_input_data *yid, + int over) +{ + int id = yid->yd->client_id; + void *fd = yid->fd; + + if (over) + return; + + /* as long as we still have packets available keep processing them */ + while (find_input_by_id_and_fd(id, fd) + && yahoo_get_webcam_data(yid) == 1) ; +} + +static void yahoo_process_auth_connection(struct yahoo_input_data *yid, + int over) +{ + char *line_end; + char *token; + char *cookie; + + int error_code = 0; + int is_ymsgr = 0; + + /* Wait till we get everything */ + if (!over) + return; + + if (!yid->rxqueue) { + LOG(("Whoops! Closed it just like that??\n")); + YAHOO_CALLBACK(ext_yahoo_login_response) (yid->yd->client_id, + YAHOO_LOGIN_UNKNOWN, NULL); + return; + } + + token = strstr((char *)yid->rxqueue, "\r\n\r\n"); + + if (!token) { + LOG(("Could not find anything after the HTTP headers? huh?\n")); + YAHOO_CALLBACK(ext_yahoo_login_response) (yid->yd->client_id, + YAHOO_LOGIN_UNKNOWN, NULL); + return; + } + + *token = '\0'; + token += 4; + + /* Skip the first number */ + token = strstr(token, "\r\n"); + + if (!token) { + LOG(("Well I tried to skip the first number and found... nothing\n")); + YAHOO_CALLBACK(ext_yahoo_login_response) (yid->yd->client_id, + YAHOO_LOGIN_UNKNOWN, NULL); + return; + } + + token += 2; + + line_end = strstr(token, "\r\n"); + + if (line_end) { + *line_end = '\0'; + + line_end += 2; + } + + error_code = atoi((char *)token); + + switch (error_code) { + case 0: + /* successful */ + break; + case 1212: + /* Incorrect ID or password */ + LOG(("Incorrect ID or password\n")); + YAHOO_CALLBACK(ext_yahoo_login_response) (yid->yd->client_id, + YAHOO_LOGIN_PASSWD, NULL); + + return; + case 1213: + /* Security lock from too many failed login attempts */ + LOG(("Security lock from too many failed login attempts\n")); + YAHOO_CALLBACK(ext_yahoo_login_response) (yid->yd->client_id, + YAHOO_LOGIN_LOCK, ""); + + return; + + case 1214: + /* Security lock */ + LOG(("Security lock\n")); + YAHOO_CALLBACK(ext_yahoo_login_response) (yid->yd->client_id, + YAHOO_LOGIN_LOCK, ""); + + return; + + case 1235: + /* User ID not taken yet */ + LOG(("User ID not taken yet\n")); + YAHOO_CALLBACK(ext_yahoo_login_response) (yid->yd->client_id, + YAHOO_LOGIN_UNAME, NULL); + + return; + + case 1216: + /* Seems to be a lock, but shows the same generic User ID/Password failure */ + LOG(("Seems to be a lock, but shows the same generic User ID/Password failure\n")); + YAHOO_CALLBACK(ext_yahoo_login_response) (yid->yd->client_id, + YAHOO_LOGIN_PASSWD, NULL); + + return; + case 100: + /* Username and password cannot be blank */ + LOG(("Username and password cannot be blank\n")); + YAHOO_CALLBACK(ext_yahoo_login_response) (yid->yd->client_id, + YAHOO_LOGIN_PASSWD, NULL); + + return; + default: + /* Unknown error code */ + LOG(("Unknown Error\n")); + YAHOO_CALLBACK(ext_yahoo_login_response) (yid->yd->client_id, + YAHOO_LOGIN_UNKNOWN, NULL); + + return; + } + + if (line_end && !strncmp(line_end, "ymsgr=", 6)) { + is_ymsgr = 1; + } else if (strncmp(line_end, "crumb=", 6)) { + LOG(("Oops! There was no ymsgr=. Where do I get my token from now :(")); + LOG(("I got this:\n\n%s\n", line_end)); + YAHOO_CALLBACK(ext_yahoo_login_response) (yid->yd->client_id, + YAHOO_LOGIN_UNKNOWN, NULL); + return; + /* Error */ + } + + token = line_end + 6; + + line_end = strstr(token, "\r\n"); + + if (line_end) { + *line_end = '\0'; + line_end += 2; + } + + /* Go for the crumb */ + if (is_ymsgr) { + char url[256]; + char *token_enc; + struct yahoo_input_data *crumb_yid = + y_new0(struct yahoo_input_data, 1); + + crumb_yid->yd = yid->yd; + crumb_yid->type = YAHOO_CONNECTION_AUTH; + + inputs = y_list_prepend(inputs, crumb_yid); + + token_enc = yahoo_urlencode(token); + + snprintf(url, sizeof(url), + "https://login.yahoo.com/config/pwtoken_login?src=ymsgr&ts=" + "&token=%s", token_enc); + + yahoo_http_get(crumb_yid->yd->client_id, url, NULL, 1, 0, + _yahoo_http_connected, crumb_yid); + + FREE(token_enc); + + return; + } + + /* token is actually crumb */ + + if (!line_end) { + /* We did not get our cookies. Cry. */ + LOG(("NO Cookies!")); + YAHOO_CALLBACK(ext_yahoo_login_response) (yid->yd->client_id, + YAHOO_LOGIN_UNKNOWN, NULL); + return; + } + + cookie = strstr((char *)yid->rxqueue, "Set-Cookie: Y="); + + if (!cookie) { + /* Cry. */ + LOG(("NO Y Cookie!")); + YAHOO_CALLBACK(ext_yahoo_login_response) (yid->yd->client_id, + YAHOO_LOGIN_UNKNOWN, NULL); + return; + } + + cookie += 14; + + line_end = strstr(cookie, "\r\n"); + *line_end = '\0'; + + yid->yd->cookie_y = strdup(cookie); + *line_end = ';'; + + cookie = strstr((char *)yid->rxqueue, "Set-Cookie: T="); + if (!cookie) { + /* Cry. */ + LOG(("NO T Cookie!")); + YAHOO_CALLBACK(ext_yahoo_login_response) (yid->yd->client_id, + YAHOO_LOGIN_UNKNOWN, NULL); + return; + } + + cookie += 14; + + line_end = strstr(cookie, "\r\n"); + *line_end = '\0'; + + yid->yd->cookie_t = strdup(cookie); + *line_end = ';'; + + cookie = strstr((char *)yid->rxqueue, "Set-Cookie: B="); + if (!cookie) { + /* Cry. */ + LOG(("NO B Cookie!")); + YAHOO_CALLBACK(ext_yahoo_login_response) (yid->yd->client_id, + YAHOO_LOGIN_UNKNOWN, NULL); + return; + } + + cookie += 14; + + line_end = strstr(cookie, "\r\n"); + *line_end = '\0'; + + yid->yd->cookie_b = strdup(cookie); + + yid->yd->crumb = strdup(token); + + yahoo_send_auth(yid->yd); +} + +static void (*yahoo_process_connection[]) (struct yahoo_input_data *, + int over) = { +yahoo_process_pager_connection, yahoo_process_ft_connection, + yahoo_process_yab_connection, + yahoo_process_webcam_master_connection, + yahoo_process_webcam_connection, + yahoo_process_chatcat_connection, + yahoo_process_search_connection, yahoo_process_auth_connection}; + +int yahoo_read_ready(int id, void *fd, void *data) +{ + struct yahoo_input_data *yid = data; + char buf[1024]; + int len; + + LOG(("read callback: id=%d fd=%p data=%p", id, fd, data)); + if (!yid) + return -2; + + do { + len = YAHOO_CALLBACK(ext_yahoo_read) (fd, buf, sizeof(buf)); + } while (len == -1 && errno == EINTR); + + if (len == -1 && (errno == EAGAIN || errno == EINTR)) /* we'll try again later */ + return 1; + + if (len <= 0) { + int e = errno; + DEBUG_MSG(("len == %d (<= 0)", len)); + + if (yid->type == YAHOO_CONNECTION_PAGER) { + YAHOO_CALLBACK(ext_yahoo_login_response) (yid->yd-> + client_id, YAHOO_LOGIN_SOCK, NULL); + } + + yahoo_process_connection[yid->type] (yid, 1); + yahoo_input_close(yid); + + /* no need to return an error, because we've already fixed it */ + if (len == 0) + return 1; + + errno = e; + LOG(("read error: %s", strerror(errno))); + return -1; + } + + yid->rxqueue = + y_renew(unsigned char, yid->rxqueue, len + yid->rxlen + 1); + memcpy(yid->rxqueue + yid->rxlen, buf, len); + yid->rxlen += len; + yid->rxqueue[yid->rxlen] = 0; + + yahoo_process_connection[yid->type] (yid, 0); + + return len; +} + +int yahoo_init_with_attributes(const char *username, const char *password, ...) +{ + va_list ap; + struct yahoo_data *yd; + + yd = y_new0(struct yahoo_data, 1); + + if (!yd) + return 0; + + yd->user = strdup(username); + yd->password = strdup(password); + + yd->initial_status = -1; + yd->current_status = -1; + + yd->client_id = ++last_id; + + add_to_list(yd); + + va_start(ap, password); + yd->server_settings = _yahoo_assign_server_settings(ap); + va_end(ap); + + return yd->client_id; +} + +int yahoo_init(const char *username, const char *password) +{ + return yahoo_init_with_attributes(username, password, NULL); +} + +static void yahoo_connected(void *fd, int error, void *data) +{ + struct connect_callback_data *ccd = data; + struct yahoo_data *yd = ccd->yd; + struct yahoo_packet *pkt; + struct yahoo_input_data *yid; + struct yahoo_server_settings *yss = yd->server_settings; + + if (error) { + int tag; + if (fallback_ports[ccd->i]) { + char *host = yss->pager_host; + + if (!host) + host = yss->pager_host_list[ccd->server_i]; + + yss->pager_port = fallback_ports[ccd->i++]; + tag = YAHOO_CALLBACK(ext_yahoo_connect_async) (yd-> + client_id, host, yss->pager_port, + yahoo_connected, ccd, 0); + + if (tag > 0) + ccd->tag = tag; + } else if (yss->pager_host_list + && yss->pager_host_list[ccd->server_i]) { + + /* Get back to the default port */ + yss->pager_port = pager_port; + ccd->server_i++; + LOG(("Fallback: Connecting to %s:%d", yss->pager_host_list[ccd->server_i], yss->pager_port)); + + ccd->i = 0; + tag = YAHOO_CALLBACK(ext_yahoo_connect_async) (yd->client_id, + yss->pager_host_list[ccd->server_i], yss->pager_port, + yahoo_connected, ccd, 0); + } else { + FREE(ccd); + YAHOO_CALLBACK(ext_yahoo_login_response) (yd->client_id, + YAHOO_LOGIN_SOCK, NULL); + } + return; + } + + FREE(ccd); + + /* fd == NULL && error == 0 means connect was cancelled */ + if (!fd) + return; + + pkt = yahoo_packet_new(YAHOO_SERVICE_AUTH, YPACKET_STATUS_DEFAULT, + yd->session_id); + NOTICE(("Sending initial packet")); + + yahoo_packet_hash(pkt, 1, yd->user); + + yid = find_input_by_id_and_type(yd->client_id, YAHOO_CONNECTION_PAGER); + yid->fd = fd; + + yahoo_send_packet(yid, pkt, 0); + + yahoo_packet_free(pkt); + + yid->read_tag = + YAHOO_CALLBACK(ext_yahoo_add_handler) (yid->yd->client_id, + yid->fd, YAHOO_INPUT_READ, yid); +} + +void *yahoo_get_fd(int id) +{ + struct yahoo_input_data *yid = + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + if (!yid) + return 0; + else + return yid->fd; +} + +void yahoo_send_buzz(int id, const char *from, const char *who) +{ + yahoo_send_im(id, from, who, "", 1, 0); +} + +void yahoo_send_im(int id, const char *from, const char *who, const char *what, + int utf8, int picture) +{ + struct yahoo_input_data *yid = + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + struct yahoo_packet *pkt = NULL; + struct yahoo_data *yd; + char pic_str[10]; + + if (!yid) + return; + + yd = yid->yd; + + pkt = yahoo_packet_new(YAHOO_SERVICE_MESSAGE, YAHOO_STATUS_OFFLINE, + yd->session_id); + + snprintf(pic_str, sizeof(pic_str), "%d", picture); + + if (from && strcmp(from, yd->user)) + yahoo_packet_hash(pkt, 0, yd->user); + yahoo_packet_hash(pkt, 1, from ? from : yd->user); + yahoo_packet_hash(pkt, 5, who); + yahoo_packet_hash(pkt, 14, what); + + if (utf8) + yahoo_packet_hash(pkt, 97, "1"); + + yahoo_packet_hash(pkt, 63, ";0"); /* imvironment name; or ;0 */ + yahoo_packet_hash(pkt, 64, "0"); + yahoo_packet_hash(pkt, 206, pic_str); + + yahoo_send_packet(yid, pkt, 0); + + yahoo_packet_free(pkt); +} + +void yahoo_send_typing(int id, const char *from, const char *who, int typ) +{ + struct yahoo_input_data *yid = + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + struct yahoo_data *yd; + struct yahoo_packet *pkt = NULL; + if (!yid) + return; + + yd = yid->yd; + pkt = yahoo_packet_new(YAHOO_SERVICE_NOTIFY, YPACKET_STATUS_NOTIFY, + yd->session_id); + + yahoo_packet_hash(pkt, 5, who); + yahoo_packet_hash(pkt, 1, from ? from : yd->user); + yahoo_packet_hash(pkt, 14, " "); + yahoo_packet_hash(pkt, 13, typ ? "1" : "0"); + yahoo_packet_hash(pkt, 49, "TYPING"); + + yahoo_send_packet(yid, pkt, 0); + + yahoo_packet_free(pkt); +} + +void yahoo_set_away(int id, enum yahoo_status state, const char *msg, int away) +{ + struct yahoo_input_data *yid = + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + struct yahoo_data *yd; + struct yahoo_packet *pkt = NULL; + int old_status; + char s[4]; + + if (!yid) + return; + + yd = yid->yd; + + old_status = yd->current_status; + + if (msg) { + yd->current_status = YAHOO_STATUS_CUSTOM; + } else { + yd->current_status = state; + } + + /* Thank you libpurple :) */ + if (yd->current_status == YAHOO_STATUS_INVISIBLE) { + pkt = yahoo_packet_new(YAHOO_SERVICE_Y6_VISIBLE_TOGGLE, + YAHOO_STATUS_AVAILABLE, 0); + yahoo_packet_hash(pkt, 13, "2"); + yahoo_send_packet(yid, pkt, 0); + yahoo_packet_free(pkt); + + return; + } + + pkt = yahoo_packet_new(YAHOO_SERVICE_Y6_STATUS_UPDATE, + yd->current_status, yd->session_id); + snprintf(s, sizeof(s), "%d", yd->current_status); + yahoo_packet_hash(pkt, 10, s); + + if (yd->current_status == YAHOO_STATUS_CUSTOM) { + yahoo_packet_hash(pkt, 19, msg); + } else { + yahoo_packet_hash(pkt, 19, ""); + } + + yahoo_packet_hash(pkt, 47, (away == 2) ? "2" : (away) ? "1" : "0"); + + yahoo_send_packet(yid, pkt, 0); + yahoo_packet_free(pkt); + + if (old_status == YAHOO_STATUS_INVISIBLE) { + pkt = yahoo_packet_new(YAHOO_SERVICE_Y6_VISIBLE_TOGGLE, + YAHOO_STATUS_AVAILABLE, 0); + yahoo_packet_hash(pkt, 13, "1"); + yahoo_send_packet(yid, pkt, 0); + yahoo_packet_free(pkt); + } +} + +void yahoo_logoff(int id) +{ + struct yahoo_input_data *yid = + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + struct yahoo_data *yd; + struct yahoo_packet *pkt = NULL; + + if (!yid) + return; + yd = yid->yd; + + LOG(("yahoo_logoff: current status: %d", yd->current_status)); + + if (yd->current_status != -1) { + pkt = yahoo_packet_new(YAHOO_SERVICE_LOGOFF, + YPACKET_STATUS_DEFAULT, yd->session_id); + yd->current_status = -1; + + if (pkt) { + yahoo_send_packet(yid, pkt, 0); + yahoo_packet_free(pkt); + } + } + +/* do { + yahoo_input_close(yid); + } while((yid = find_input_by_id(id)));*/ + +} + +void yahoo_get_list(int id) +{ + struct yahoo_input_data *yid = + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + struct yahoo_data *yd; + struct yahoo_packet *pkt = NULL; + + if (!yid) + return; + yd = yid->yd; + + pkt = yahoo_packet_new(YAHOO_SERVICE_LIST, YPACKET_STATUS_DEFAULT, + yd->session_id); + yahoo_packet_hash(pkt, 1, yd->user); + if (pkt) { + yahoo_send_packet(yid, pkt, 0); + yahoo_packet_free(pkt); + } +} + +static void _yahoo_http_connected(int id, void *fd, int error, void *data) +{ + struct yahoo_input_data *yid = data; + if (fd == NULL || error) { + inputs = y_list_remove(inputs, yid); + FREE(yid); + return; + } + + yid->fd = fd; + yid->read_tag = + YAHOO_CALLBACK(ext_yahoo_add_handler) (yid->yd->client_id, fd, + YAHOO_INPUT_READ, yid); +} + +/* FIXME Get address book from address.yahoo.com instead */ +void yahoo_get_yab(int id) +{ + struct yahoo_data *yd = find_conn_by_id(id); + struct yahoo_input_data *yid; + char url[1024]; + char buff[2048]; + + if (!yd) + return; + + yid = y_new0(struct yahoo_input_data, 1); + yid->yd = yd; + yid->type = YAHOO_CONNECTION_YAB; + + LOG(("Sending request for Address Book")); + + snprintf(url, 1024, + "http://address.yahoo.com/yab/us?v=XM&prog=ymsgr&.intl=us" + "&diffs=1&t=0&tags=short&rt=0&prog-ver=8.1.0.249&useutf8=1&legenc=codepage-1252"); + + snprintf(buff, sizeof(buff), "Y=%s; T=%s", yd->cookie_y, yd->cookie_t); + + inputs = y_list_prepend(inputs, yid); + + yahoo_http_get(yid->yd->client_id, url, buff, 0, 0, + _yahoo_http_connected, yid); +} + +struct yahoo_post_data { + struct yahoo_input_data *yid; + char *data; +}; + +static void _yahoo_http_post_connected(int id, void *fd, int error, void *data) +{ + struct yahoo_post_data *yad = data; + struct yahoo_input_data *yid = yad->yid; + char *buff = yad->data; + + if (!fd) { + inputs = y_list_remove(inputs, yid); + FREE(yid); + return; + } + + YAHOO_CALLBACK(ext_yahoo_write) (fd, buff, strlen(buff)); + + yid->fd = fd; + yid->read_tag = + YAHOO_CALLBACK(ext_yahoo_add_handler) (yid->yd->client_id, fd, + YAHOO_INPUT_READ, yid); + + FREE(buff); + FREE(yad); +} + +/* FIXME This is also likely affected */ +void yahoo_set_yab(int id, struct yab *yab) +{ + struct yahoo_post_data *yad = y_new0(struct yahoo_post_data, 1); + struct yahoo_data *yd = find_conn_by_id(id); + struct yahoo_input_data *yid; + char url[1024]; + char buff[1024]; + char post[1024]; + int size = 0; + + if (!yd) + return; + + yid = y_new0(struct yahoo_input_data, 1); + yid->type = YAHOO_CONNECTION_YAB; + yid->yd = yd; + + if(yab->yid) + size = snprintf(post, sizeof(post), "" + "" + "" + "", yd->user, 9, yab->yid, /* Don't know why */ + yab->id, yab->nname?yab->nname:""); + else + size = snprintf(post, sizeof(post), "" + "" + "" + "", yd->user, 1, /* Don't know why */ + yab->id, yab->nname?yab->nname:""); + + yad->yid = yid; + yad->data = strdup(post); + + strcpy(url, "http://address.yahoo.com/yab/us?v=XM&prog=ymsgr&.intl=us" + "&sync=1&tags=short&noclear=1&useutf8=1&legenc=codepage-1252"); + + snprintf(buff, sizeof(buff), "Y=%s; T=%s", yd->cookie_y, yd->cookie_t); + + inputs = y_list_prepend(inputs, yid); + + yahoo_http_post(yid->yd->client_id, url, buff, size, + _yahoo_http_post_connected, yad); +} + +void yahoo_set_identity_status(int id, const char *identity, int active) +{ + struct yahoo_input_data *yid = + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + struct yahoo_data *yd; + struct yahoo_packet *pkt = NULL; + + if (!yid) + return; + yd = yid->yd; + + pkt = yahoo_packet_new(active ? YAHOO_SERVICE_IDACT : + YAHOO_SERVICE_IDDEACT, YPACKET_STATUS_DEFAULT, yd->session_id); + yahoo_packet_hash(pkt, 3, identity); + if (pkt) { + yahoo_send_packet(yid, pkt, 0); + yahoo_packet_free(pkt); + } +} + +void yahoo_refresh(int id) +{ + struct yahoo_input_data *yid = + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + struct yahoo_data *yd; + struct yahoo_packet *pkt = NULL; + + if (!yid) + return; + yd = yid->yd; + + pkt = yahoo_packet_new(YAHOO_SERVICE_USERSTAT, YPACKET_STATUS_DEFAULT, + yd->session_id); + if (pkt) { + yahoo_send_packet(yid, pkt, 0); + yahoo_packet_free(pkt); + } +} + +void yahoo_keepalive(int id) +{ + struct yahoo_input_data *yid = + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + struct yahoo_data *yd; + struct yahoo_packet *pkt = NULL; + if (!yid) + return; + yd = yid->yd; + + pkt = yahoo_packet_new(YAHOO_SERVICE_PING, YPACKET_STATUS_DEFAULT, + yd->session_id); + yahoo_send_packet(yid, pkt, 0); + yahoo_packet_free(pkt); +} + +void yahoo_chat_keepalive(int id) +{ + struct yahoo_input_data *yid = + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + struct yahoo_data *yd; + struct yahoo_packet *pkt = NULL; + + if (!yid) + return; + + yd = yid->yd; + + pkt = yahoo_packet_new(YAHOO_SERVICE_CHATPING, YPACKET_STATUS_DEFAULT, + yd->session_id); + yahoo_send_packet(yid, pkt, 0); + yahoo_packet_free(pkt); +} + +void yahoo_add_buddy(int id, const char *who, const char *group, + const char *msg) +{ + struct yahoo_input_data *yid = + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + struct yahoo_data *yd; + struct yahoo_packet *pkt; + + if (!yid) + return; + yd = yid->yd; + + if (!yd->logged_in) + return; + + pkt = yahoo_packet_new(YAHOO_SERVICE_ADDBUDDY, YPACKET_STATUS_DEFAULT, + yd->session_id); + if (msg != NULL) /* add message/request "it's me add me" */ + yahoo_packet_hash(pkt, 14, msg); + else + yahoo_packet_hash(pkt, 14, ""); + yahoo_packet_hash(pkt, 65, group); + yahoo_packet_hash(pkt, 97, "1"); + yahoo_packet_hash(pkt, 1, yd->user); + yahoo_packet_hash(pkt, 302, "319"); + yahoo_packet_hash(pkt, 300, "319"); + yahoo_packet_hash(pkt, 7, who); + yahoo_packet_hash(pkt, 334, "0"); + yahoo_packet_hash(pkt, 301, "319"); + yahoo_packet_hash(pkt, 303, "319"); + yahoo_send_packet(yid, pkt, 0); + yahoo_packet_free(pkt); +} + +void yahoo_remove_buddy(int id, const char *who, const char *group) +{ + struct yahoo_input_data *yid = + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + struct yahoo_data *yd; + struct yahoo_packet *pkt = NULL; + + if (!yid) + return; + yd = yid->yd; + + pkt = yahoo_packet_new(YAHOO_SERVICE_REMBUDDY, YPACKET_STATUS_DEFAULT, + yd->session_id); + + yahoo_packet_hash(pkt, 1, yd->user); + yahoo_packet_hash(pkt, 7, who); + yahoo_packet_hash(pkt, 65, group); + yahoo_send_packet(yid, pkt, 0); + yahoo_packet_free(pkt); +} + +void yahoo_confirm_buddy(int id, const char *who, int reject, const char *msg) +{ + struct yahoo_input_data *yid = + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + struct yahoo_data *yd; + struct yahoo_packet *pkt; + + if (!yid) + return; + yd = yid->yd; + + if (!yd->logged_in) + return; + + pkt = yahoo_packet_new(YAHOO_SERVICE_Y7_AUTHORIZATION, + YPACKET_STATUS_DEFAULT, yd->session_id); + yahoo_packet_hash(pkt, 1, yd->user); + yahoo_packet_hash(pkt, 5, who); + if (reject) + yahoo_packet_hash(pkt, 13, "2"); + else { + yahoo_packet_hash(pkt, 241, "0"); + yahoo_packet_hash(pkt, 13, "1"); + } + + yahoo_packet_hash(pkt, 334, "0"); + + if (reject) { + yahoo_packet_hash(pkt, 14, msg ? msg : ""); + yahoo_packet_hash(pkt, 97, "1"); + } + + yahoo_send_packet(yid, pkt, 0); + yahoo_packet_free(pkt); +} + +void yahoo_ignore_buddy(int id, const char *who, int unignore) +{ + struct yahoo_input_data *yid = + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + struct yahoo_data *yd; + struct yahoo_packet *pkt; + + if (!yid) + return; + yd = yid->yd; + + if (!yd->logged_in) + return; + + pkt = yahoo_packet_new(YAHOO_SERVICE_IGNORECONTACT, + YPACKET_STATUS_DEFAULT, yd->session_id); + yahoo_packet_hash(pkt, 1, yd->user); + yahoo_packet_hash(pkt, 7, who); + yahoo_packet_hash(pkt, 13, unignore ? "2" : "1"); + yahoo_send_packet(yid, pkt, 0); + yahoo_packet_free(pkt); +} + +void yahoo_stealth_buddy(int id, const char *who, int unstealth) +{ + struct yahoo_input_data *yid = + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + struct yahoo_data *yd; + struct yahoo_packet *pkt; + + if (!yid) + return; + yd = yid->yd; + + if (!yd->logged_in) + return; + + pkt = yahoo_packet_new(YAHOO_SERVICE_STEALTH_PERM, + YPACKET_STATUS_DEFAULT, yd->session_id); + yahoo_packet_hash(pkt, 1, yd->user); + yahoo_packet_hash(pkt, 7, who); + yahoo_packet_hash(pkt, 31, unstealth ? "2" : "1"); + yahoo_packet_hash(pkt, 13, "2"); + yahoo_send_packet(yid, pkt, 0); + yahoo_packet_free(pkt); +} + +void yahoo_change_buddy_group(int id, const char *who, const char *old_group, + const char *new_group) +{ + struct yahoo_input_data *yid = + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + struct yahoo_data *yd; + struct yahoo_packet *pkt = NULL; + + if (!yid) + return; + yd = yid->yd; + + pkt = yahoo_packet_new(YAHOO_SERVICE_Y7_CHANGE_GROUP, + YPACKET_STATUS_DEFAULT, yd->session_id); + yahoo_packet_hash(pkt, 1, yd->user); + yahoo_packet_hash(pkt, 302, "240"); + yahoo_packet_hash(pkt, 300, "240"); + yahoo_packet_hash(pkt, 7, who); + yahoo_packet_hash(pkt, 224, old_group); + yahoo_packet_hash(pkt, 264, new_group); + yahoo_packet_hash(pkt, 301, "240"); + yahoo_packet_hash(pkt, 303, "240"); + + yahoo_send_packet(yid, pkt, 0); + yahoo_packet_free(pkt); +} + +void yahoo_group_rename(int id, const char *old_group, const char *new_group) +{ + struct yahoo_input_data *yid = + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + struct yahoo_data *yd; + struct yahoo_packet *pkt = NULL; + + if (!yid) + return; + yd = yid->yd; + + pkt = yahoo_packet_new(YAHOO_SERVICE_GROUPRENAME, + YPACKET_STATUS_DEFAULT, yd->session_id); + yahoo_packet_hash(pkt, 1, yd->user); + yahoo_packet_hash(pkt, 65, old_group); + yahoo_packet_hash(pkt, 67, new_group); + + yahoo_send_packet(yid, pkt, 0); + yahoo_packet_free(pkt); +} + +void yahoo_conference_addinvite(int id, const char *from, const char *who, + const char *room, const YList *members, const char *msg) +{ + struct yahoo_input_data *yid = + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + struct yahoo_data *yd; + struct yahoo_packet *pkt; + + if (!yid) + return; + yd = yid->yd; + + pkt = yahoo_packet_new(YAHOO_SERVICE_CONFADDINVITE, + YPACKET_STATUS_DEFAULT, yd->session_id); + + yahoo_packet_hash(pkt, 1, (from ? from : yd->user)); + yahoo_packet_hash(pkt, 51, who); + yahoo_packet_hash(pkt, 57, room); + yahoo_packet_hash(pkt, 58, msg); + yahoo_packet_hash(pkt, 13, "0"); + for (; members; members = members->next) { + yahoo_packet_hash(pkt, 52, (char *)members->data); + yahoo_packet_hash(pkt, 53, (char *)members->data); + } + /* 52, 53 -> other members? */ + + yahoo_send_packet(yid, pkt, 0); + + yahoo_packet_free(pkt); +} + +void yahoo_conference_invite(int id, const char *from, YList *who, + const char *room, const char *msg) +{ + struct yahoo_input_data *yid = + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + struct yahoo_data *yd; + struct yahoo_packet *pkt; + + if (!yid) + return; + yd = yid->yd; + + pkt = yahoo_packet_new(YAHOO_SERVICE_CONFINVITE, YPACKET_STATUS_DEFAULT, + yd->session_id); + + yahoo_packet_hash(pkt, 1, (from ? from : yd->user)); + yahoo_packet_hash(pkt, 50, yd->user); + for (; who; who = who->next) { + yahoo_packet_hash(pkt, 52, (char *)who->data); + } + yahoo_packet_hash(pkt, 57, room); + yahoo_packet_hash(pkt, 58, msg); + yahoo_packet_hash(pkt, 13, "0"); + + yahoo_send_packet(yid, pkt, 0); + + yahoo_packet_free(pkt); +} + +void yahoo_conference_logon(int id, const char *from, YList *who, + const char *room) +{ + struct yahoo_input_data *yid = + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + struct yahoo_data *yd; + struct yahoo_packet *pkt; + + if (!yid) + return; + yd = yid->yd; + + pkt = yahoo_packet_new(YAHOO_SERVICE_CONFLOGON, YPACKET_STATUS_DEFAULT, + yd->session_id); + + yahoo_packet_hash(pkt, 1, (from ? from : yd->user)); + yahoo_packet_hash(pkt, 3, (from ? from : yd->user)); + yahoo_packet_hash(pkt, 57, room); + for (; who; who = who->next) + yahoo_packet_hash(pkt, 3, (char *)who->data); + + yahoo_send_packet(yid, pkt, 0); + + yahoo_packet_free(pkt); +} + +void yahoo_conference_decline(int id, const char *from, YList *who, + const char *room, const char *msg) +{ + struct yahoo_input_data *yid = + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + struct yahoo_data *yd; + struct yahoo_packet *pkt; + + if (!yid) + return; + yd = yid->yd; + + pkt = yahoo_packet_new(YAHOO_SERVICE_CONFDECLINE, + YPACKET_STATUS_DEFAULT, yd->session_id); + + yahoo_packet_hash(pkt, 1, (from ? from : yd->user)); + yahoo_packet_hash(pkt, 3, (from ? from : yd->user)); + for (; who; who = who->next) + yahoo_packet_hash(pkt, 3, (char *)who->data); + yahoo_packet_hash(pkt, 57, room); + yahoo_packet_hash(pkt, 14, msg); + + yahoo_send_packet(yid, pkt, 0); + + yahoo_packet_free(pkt); +} + +void yahoo_conference_logoff(int id, const char *from, YList *who, + const char *room) +{ + struct yahoo_input_data *yid = + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + struct yahoo_data *yd; + struct yahoo_packet *pkt; + + if (!yid) + return; + yd = yid->yd; + + pkt = yahoo_packet_new(YAHOO_SERVICE_CONFLOGOFF, YPACKET_STATUS_DEFAULT, + yd->session_id); + + yahoo_packet_hash(pkt, 1, (from ? from : yd->user)); + yahoo_packet_hash(pkt, 3, (from ? from : yd->user)); + for (; who; who = who->next) + yahoo_packet_hash(pkt, 3, (char *)who->data); + + yahoo_packet_hash(pkt, 57, room); + + yahoo_send_packet(yid, pkt, 0); + + yahoo_packet_free(pkt); +} + +void yahoo_conference_message(int id, const char *from, YList *who, + const char *room, const char *msg, int utf8) +{ + struct yahoo_input_data *yid = + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + struct yahoo_data *yd; + struct yahoo_packet *pkt; + + if (!yid) + return; + yd = yid->yd; + + pkt = yahoo_packet_new(YAHOO_SERVICE_CONFMSG, YPACKET_STATUS_DEFAULT, + yd->session_id); + + yahoo_packet_hash(pkt, 1, (from ? from : yd->user)); + yahoo_packet_hash(pkt, 53, (from ? from : yd->user)); + for (; who; who = who->next) + yahoo_packet_hash(pkt, 53, (char *)who->data); + + yahoo_packet_hash(pkt, 57, room); + yahoo_packet_hash(pkt, 14, msg); + + if (utf8) + yahoo_packet_hash(pkt, 97, "1"); + + yahoo_send_packet(yid, pkt, 0); + + yahoo_packet_free(pkt); +} + +void yahoo_get_chatrooms(int id, int chatroomid) +{ + struct yahoo_data *yd = find_conn_by_id(id); + struct yahoo_input_data *yid; + char url[1024]; + char buff[1024]; + + if (!yd) + return; + + yid = y_new0(struct yahoo_input_data, 1); + yid->yd = yd; + yid->type = YAHOO_CONNECTION_CHATCAT; + + if (chatroomid == 0) { + snprintf(url, 1024, + "http://insider.msg.yahoo.com/ycontent/?chatcat=0"); + } else { + snprintf(url, 1024, + "http://insider.msg.yahoo.com/ycontent/?chatroom_%d=0", + chatroomid); + } + + snprintf(buff, sizeof(buff), "Y=%s; T=%s", yd->cookie_y, yd->cookie_t); + + inputs = y_list_prepend(inputs, yid); + + yahoo_http_get(yid->yd->client_id, url, buff, 0, 0, + _yahoo_http_connected, yid); +} + +void yahoo_chat_logon(int id, const char *from, const char *room, + const char *roomid) +{ + struct yahoo_input_data *yid = + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + struct yahoo_data *yd; + struct yahoo_packet *pkt; + + if (!yid) + return; + + yd = yid->yd; + + pkt = yahoo_packet_new(YAHOO_SERVICE_CHATONLINE, YPACKET_STATUS_DEFAULT, + yd->session_id); + + yahoo_packet_hash(pkt, 1, (from ? from : yd->user)); + yahoo_packet_hash(pkt, 109, yd->user); + yahoo_packet_hash(pkt, 6, "abcde"); + + yahoo_send_packet(yid, pkt, 0); + + yahoo_packet_free(pkt); + + pkt = yahoo_packet_new(YAHOO_SERVICE_CHATJOIN, YPACKET_STATUS_DEFAULT, + yd->session_id); + + yahoo_packet_hash(pkt, 1, (from ? from : yd->user)); + yahoo_packet_hash(pkt, 104, room); + yahoo_packet_hash(pkt, 129, roomid); + yahoo_packet_hash(pkt, 62, "2"); /* ??? */ + + yahoo_send_packet(yid, pkt, 0); + + yahoo_packet_free(pkt); +} + +void yahoo_chat_message(int id, const char *from, const char *room, + const char *msg, const int msgtype, const int utf8) +{ + struct yahoo_input_data *yid = + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + struct yahoo_data *yd; + struct yahoo_packet *pkt; + char buf[2]; + + if (!yid) + return; + + yd = yid->yd; + + pkt = yahoo_packet_new(YAHOO_SERVICE_COMMENT, YPACKET_STATUS_DEFAULT, + yd->session_id); + + yahoo_packet_hash(pkt, 1, (from ? from : yd->user)); + yahoo_packet_hash(pkt, 104, room); + yahoo_packet_hash(pkt, 117, msg); + + snprintf(buf, sizeof(buf), "%d", msgtype); + yahoo_packet_hash(pkt, 124, buf); + + if (utf8) + yahoo_packet_hash(pkt, 97, "1"); + + yahoo_send_packet(yid, pkt, 0); + + yahoo_packet_free(pkt); +} + +void yahoo_chat_logoff(int id, const char *from) +{ + struct yahoo_input_data *yid = + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + struct yahoo_data *yd; + struct yahoo_packet *pkt; + + if (!yid) + return; + + yd = yid->yd; + + pkt = yahoo_packet_new(YAHOO_SERVICE_CHATLOGOUT, YPACKET_STATUS_DEFAULT, + yd->session_id); + + yahoo_packet_hash(pkt, 1, (from ? from : yd->user)); + + yahoo_send_packet(yid, pkt, 0); + + yahoo_packet_free(pkt); +} + +void yahoo_buddyicon_request(int id, const char *who) +{ + struct yahoo_input_data *yid = + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + struct yahoo_data *yd; + struct yahoo_packet *pkt; + + if (!yid) + return; + + yd = yid->yd; + + pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE, YPACKET_STATUS_DEFAULT, + yd->session_id); + yahoo_packet_hash(pkt, 1, yd->user); + yahoo_packet_hash(pkt, 5, who); + yahoo_packet_hash(pkt, 13, "1"); + yahoo_send_packet(yid, pkt, 0); + + yahoo_packet_free(pkt); +} + +void yahoo_send_picture_info(int id, const char *who, const char *url, + int checksum) +{ + struct yahoo_input_data *yid = + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + struct yahoo_data *yd; + struct yahoo_packet *pkt; + char checksum_str[10]; + + if (!yid) + return; + + yd = yid->yd; + + snprintf(checksum_str, sizeof(checksum_str), "%d", checksum); + + pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE, YPACKET_STATUS_DEFAULT, + 0); + yahoo_packet_hash(pkt, 1, yd->user); + yahoo_packet_hash(pkt, 4, yd->user); + yahoo_packet_hash(pkt, 5, who); + yahoo_packet_hash(pkt, 13, "2"); + yahoo_packet_hash(pkt, 20, url); + yahoo_packet_hash(pkt, 192, checksum_str); + yahoo_send_packet(yid, pkt, 0); + + yahoo_packet_free(pkt); +} + +void yahoo_send_picture_update(int id, const char *who, int type) +{ + struct yahoo_input_data *yid = + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + struct yahoo_data *yd; + struct yahoo_packet *pkt; + char type_str[10]; + + if (!yid) + return; + + yd = yid->yd; + + snprintf(type_str, sizeof(type_str), "%d", type); + + pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE_UPDATE, + YPACKET_STATUS_DEFAULT, 0); + yahoo_packet_hash(pkt, 1, yd->user); + yahoo_packet_hash(pkt, 5, who); + yahoo_packet_hash(pkt, 206, type_str); + yahoo_send_packet(yid, pkt, 0); + + yahoo_packet_free(pkt); +} + +void yahoo_send_picture_checksum(int id, const char *who, int checksum) +{ + struct yahoo_input_data *yid = + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + struct yahoo_data *yd; + struct yahoo_packet *pkt; + char checksum_str[10]; + + if (!yid) + return; + + yd = yid->yd; + + snprintf(checksum_str, sizeof(checksum_str), "%d", checksum); + + pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE_CHECKSUM, + YPACKET_STATUS_DEFAULT, 0); + yahoo_packet_hash(pkt, 1, yd->user); + if (who != 0) + yahoo_packet_hash(pkt, 5, who); + yahoo_packet_hash(pkt, 192, checksum_str); + yahoo_packet_hash(pkt, 212, "1"); + yahoo_send_packet(yid, pkt, 0); + + yahoo_packet_free(pkt); +} + +void yahoo_webcam_close_feed(int id, const char *who) +{ + struct yahoo_input_data *yid = + find_input_by_id_and_webcam_user(id, who); + + if (yid) + yahoo_input_close(yid); +} + +void yahoo_webcam_get_feed(int id, const char *who) +{ + struct yahoo_input_data *yid = + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + struct yahoo_data *yd; + struct yahoo_packet *pkt; + + if (!yid) + return; + + /* + * add the user to the queue. this is a dirty hack, since + * the yahoo server doesn't tell us who's key it's returning, + * we have to just hope that it sends back keys in the same + * order that we request them. + * The queue is popped in yahoo_process_webcam_key + */ + webcam_queue = y_list_append(webcam_queue, who ? strdup(who) : NULL); + + yd = yid->yd; + + pkt = yahoo_packet_new(YAHOO_SERVICE_WEBCAM, YPACKET_STATUS_DEFAULT, + yd->session_id); + + yahoo_packet_hash(pkt, 1, yd->user); + if (who != NULL) + yahoo_packet_hash(pkt, 5, who); + yahoo_send_packet(yid, pkt, 0); + + yahoo_packet_free(pkt); +} + +void yahoo_webcam_send_image(int id, unsigned char *image, unsigned int length, + unsigned int timestamp) +{ + struct yahoo_input_data *yid = + find_input_by_id_and_type(id, YAHOO_CONNECTION_WEBCAM); + unsigned char *packet; + unsigned char header_len = 13; + unsigned int pos = 0; + + if (!yid) + return; + + packet = y_new0(unsigned char, header_len); + + packet[pos++] = header_len; + packet[pos++] = 0; + packet[pos++] = 5; /* version byte?? */ + packet[pos++] = 0; + pos += yahoo_put32(packet + pos, length); + packet[pos++] = 2; /* packet type, image */ + pos += yahoo_put32(packet + pos, timestamp); + yahoo_add_to_send_queue(yid, packet, header_len); + FREE(packet); + + if (length) + yahoo_add_to_send_queue(yid, image, length); +} + +void yahoo_webcam_accept_viewer(int id, const char *who, int accept) +{ + struct yahoo_input_data *yid = + find_input_by_id_and_type(id, YAHOO_CONNECTION_WEBCAM); + char *packet = NULL; + char *data = NULL; + unsigned char header_len = 13; + unsigned int pos = 0; + unsigned int len = 0; + + if (!yid) + return; + + data = strdup("u="); + data = y_string_append(data, (char *)who); + data = y_string_append(data, "\r\n"); + len = strlen(data); + + packet = y_new0(char, header_len + len); + packet[pos++] = header_len; + packet[pos++] = 0; + packet[pos++] = 5; /* version byte?? */ + packet[pos++] = 0; + pos += yahoo_put32(packet + pos, len); + packet[pos++] = 0; /* packet type */ + pos += yahoo_put32(packet + pos, accept); + memcpy(packet + pos, data, len); + FREE(data); + yahoo_add_to_send_queue(yid, packet, header_len + len); + FREE(packet); +} + +void yahoo_webcam_invite(int id, const char *who) +{ + struct yahoo_input_data *yid = + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + struct yahoo_packet *pkt; + + if (!yid) + return; + + pkt = yahoo_packet_new(YAHOO_SERVICE_NOTIFY, YPACKET_STATUS_NOTIFY, + yid->yd->session_id); + + yahoo_packet_hash(pkt, 49, "WEBCAMINVITE"); + yahoo_packet_hash(pkt, 14, " "); + yahoo_packet_hash(pkt, 13, "0"); + yahoo_packet_hash(pkt, 1, yid->yd->user); + yahoo_packet_hash(pkt, 5, who); + yahoo_send_packet(yid, pkt, 0); + + yahoo_packet_free(pkt); +} + +static void yahoo_search_internal(int id, int t, const char *text, int g, + int ar, int photo, int yahoo_only, int startpos, int total) +{ + struct yahoo_data *yd = find_conn_by_id(id); + struct yahoo_input_data *yid; + char url[1024]; + char buff[1024]; + char *ctext, *p; + + if (!yd) + return; + + yid = y_new0(struct yahoo_input_data, 1); + yid->yd = yd; + yid->type = YAHOO_CONNECTION_SEARCH; + + /* + age range + .ar=1 - 13-18, 2 - 18-25, 3 - 25-35, 4 - 35-50, 5 - 50-70, 6 - 70+ + */ + + snprintf(buff, sizeof(buff), "&.sq=%%20&.tt=%d&.ss=%d", total, + startpos); + + ctext = strdup(text); + while ((p = strchr(ctext, ' '))) + *p = '+'; + + snprintf(url, 1024, + "http://members.yahoo.com/interests?.oc=m&.kw=%s&.sb=%d&.g=%d&.ar=0%s%s%s", + ctext, t, g, photo ? "&.p=y" : "", yahoo_only ? "&.pg=y" : "", + startpos ? buff : ""); + + FREE(ctext); + + snprintf(buff, sizeof(buff), "Y=%s; T=%s", yd->cookie_y, yd->cookie_t); + + inputs = y_list_prepend(inputs, yid); + yahoo_http_get(yid->yd->client_id, url, buff, 0, 0, + _yahoo_http_connected, yid); +} + +void yahoo_search(int id, enum yahoo_search_type t, const char *text, + enum yahoo_search_gender g, enum yahoo_search_agerange ar, int photo, + int yahoo_only) +{ + struct yahoo_input_data *yid = + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + struct yahoo_search_state *yss; + + if (!yid) + return; + + if (!yid->ys) + yid->ys = y_new0(struct yahoo_search_state, 1); + + yss = yid->ys; + + FREE(yss->lsearch_text); + yss->lsearch_type = t; + yss->lsearch_text = strdup(text); + yss->lsearch_gender = g; + yss->lsearch_agerange = ar; + yss->lsearch_photo = photo; + yss->lsearch_yahoo_only = yahoo_only; + + yahoo_search_internal(id, t, text, g, ar, photo, yahoo_only, 0, 0); +} + +void yahoo_search_again(int id, int start) +{ + struct yahoo_input_data *yid = + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + struct yahoo_search_state *yss; + + if (!yid || !yid->ys) + return; + + yss = yid->ys; + + if (start == -1) + start = yss->lsearch_nstart + yss->lsearch_nfound; + + yahoo_search_internal(id, yss->lsearch_type, yss->lsearch_text, + yss->lsearch_gender, yss->lsearch_agerange, + yss->lsearch_photo, yss->lsearch_yahoo_only, + start, yss->lsearch_ntotal); +} + +void yahoo_send_picture(int id, const char *name, unsigned long size, + yahoo_get_fd_callback callback, void *data) +{ + /* Not Implemented */ +} + +/* File Transfer */ +static YList *active_file_transfers = NULL; + +enum { + FT_STATE_HEAD = 1, + FT_STATE_RECV, + FT_STATE_RECV_START, + FT_STATE_SEND +}; + +struct send_file_data { + int client_id; + char *id; + char *who; + char *filename; + char *ip_addr; + char *token; + int size; + + struct yahoo_input_data *yid; + int state; + + yahoo_get_fd_callback callback; + void *data; +}; + +static char *yahoo_get_random(void) +{ + int i = 0; + int r = 0; + int c = 0; + char out[25]; + + out[24] = '\0'; + out[23] = '$'; + out[22] = '$'; + + for (i = 0; i < 22; i++) { + if(r == 0) + r = rand(); + + c = r%61; + + if(c<26) + out[i] = c + 'a'; + else if (c<52) + out[i] = c - 26 + 'A'; + else + out[i] = c - 52 + '0'; + + r /= 61; + } + + return strdup(out); +} + +static int _are_same_id(const void *sfd1, const void *id) +{ + return strcmp(((struct send_file_data *)sfd1)->id, (char *)id); +} + +static int _are_same_yid(const void *sfd1, const void *yid) +{ + if(((struct send_file_data *)sfd1)->yid == yid) + return 0; + else + return 1; +} + +static struct send_file_data *yahoo_get_active_transfer(char *id) +{ + YList *l = y_list_find_custom(active_file_transfers, id, + _are_same_id); + + if(l) + return (struct send_file_data *)l->data; + + return NULL; +} + +static struct send_file_data *yahoo_get_active_transfer_with_yid(void *yid) +{ + YList *l = y_list_find_custom(active_file_transfers, yid, + _are_same_yid); + + if(l) + return (struct send_file_data *)l->data; + + return NULL; +} + +static void yahoo_add_active_transfer(struct send_file_data *sfd) +{ + active_file_transfers = y_list_prepend(active_file_transfers, sfd); +} + +static void yahoo_remove_active_transfer(struct send_file_data *sfd) +{ + active_file_transfers = y_list_remove(active_file_transfers, sfd); + free(sfd->id); + free(sfd->who); + free(sfd->filename); + free(sfd->ip_addr); + FREE(sfd); +} + +static void _yahoo_ft_upload_connected(int id, void *fd, int error, void *data) +{ + struct send_file_data *sfd = data; + struct yahoo_input_data *yid = sfd->yid; + + if (!fd) { + inputs = y_list_remove(inputs, yid); + FREE(yid); + return; + } + + sfd->callback(id, fd, error, sfd->data); + + yid->fd = fd; + yid->read_tag = + YAHOO_CALLBACK(ext_yahoo_add_handler) (yid->yd->client_id, fd, + YAHOO_INPUT_READ, yid); +} + +static void yahoo_file_transfer_upload(struct yahoo_data *yd, + struct send_file_data *sfd) +{ + char url[256]; + char buff[4096]; + char *sender_enc = NULL, *recv_enc = NULL, *token_enc = NULL; + + struct yahoo_input_data *yid = y_new0(struct yahoo_input_data, 1); + + yid->yd = yd; + yid->type = YAHOO_CONNECTION_FT; + + inputs = y_list_prepend(inputs, yid); + sfd->yid = yid; + sfd->state = FT_STATE_SEND; + + token_enc = yahoo_urlencode(sfd->token); + sender_enc = yahoo_urlencode(yd->user); + recv_enc = yahoo_urlencode(sfd->who); + + snprintf(url, sizeof(url), + "http://%s/relay?token=%s&sender=%s&recver=%s", sfd->ip_addr, + token_enc, sender_enc, recv_enc); + + snprintf(buff, sizeof(buff), "T=%s; Y=%s", yd->cookie_t, yd->cookie_y); + + yahoo_http_post(yd->client_id, url, buff, sfd->size, + _yahoo_ft_upload_connected, sfd); + + FREE(token_enc); + FREE(sender_enc); + FREE(recv_enc); +} + +static void yahoo_init_ft_recv(struct yahoo_data *yd, + struct send_file_data *sfd) +{ + char url[256]; + char buff[1024]; + char *sender_enc = NULL, *recv_enc = NULL, *token_enc = NULL; + + struct yahoo_input_data *yid = y_new0(struct yahoo_input_data, 1); + + yid->yd = yd; + yid->type = YAHOO_CONNECTION_FT; + + inputs = y_list_prepend(inputs, yid); + sfd->yid = yid; + sfd->state = FT_STATE_HEAD; + + token_enc = yahoo_urlencode(sfd->token); + sender_enc = yahoo_urlencode(sfd->who); + recv_enc = yahoo_urlencode(yd->user); + + snprintf(url, sizeof(url), + "http://%s/relay?token=%s&sender=%s&recver=%s", sfd->ip_addr, + token_enc, sender_enc, recv_enc); + + snprintf(buff, sizeof(buff), "Y=%s; T=%s", yd->cookie_y, yd->cookie_t); + + yahoo_http_head(yid->yd->client_id, url, buff, 0, NULL, + _yahoo_http_connected, yid); + + FREE(token_enc); + FREE(sender_enc); + FREE(recv_enc); +} + +static void yahoo_file_transfer_accept(struct yahoo_input_data *yid, + struct send_file_data *sfd) +{ + struct yahoo_packet *pkt; + + pkt = yahoo_packet_new(YAHOO_SERVICE_Y7_FILETRANSFERACCEPT, + YPACKET_STATUS_DEFAULT, yid->yd->session_id); + + yahoo_packet_hash(pkt, 1, yid->yd->user); + yahoo_packet_hash(pkt, 5, sfd->who); + yahoo_packet_hash(pkt, 265, sfd->id); + yahoo_packet_hash(pkt, 27, sfd->filename); + yahoo_packet_hash(pkt, 249, "3"); + yahoo_packet_hash(pkt, 251, sfd->token); + + yahoo_send_packet(yid, pkt, 0); + + yahoo_packet_free(pkt); + + yahoo_init_ft_recv(yid->yd, sfd); +} + +static void yahoo_process_filetransferaccept(struct yahoo_input_data *yid, + struct yahoo_packet *pkt) +{ + YList *l; + struct send_file_data *sfd; + char *who = NULL; + char *filename = NULL; + char *id = NULL; + char *token = NULL; + + for (l = pkt->hash; l; l = l->next) { + struct yahoo_pair *pair = l->data; + switch (pair->key) { + case 4: + who = pair->value; + break; + case 5: + /* Me... don't care */ + break; + case 249: + break; + case 265: + id = pair->value; + break; + case 251: + token = pair->value; + break; + case 27: + filename = pair->value; + break; + } + } + + sfd = yahoo_get_active_transfer(id); + + if (sfd) { + sfd->token = strdup(token); + + yahoo_file_transfer_upload(yid->yd, sfd); + } + else { + YAHOO_CALLBACK(ext_yahoo_file_transfer_done) + (yid->yd->client_id, YAHOO_FILE_TRANSFER_UNKNOWN, + sfd->data); + + yahoo_remove_active_transfer(sfd); + } +} + +static void yahoo_process_filetransferinfo(struct yahoo_input_data *yid, + struct yahoo_packet *pkt) +{ + YList *l; + char *who = NULL; + char *filename = NULL; + char *id = NULL; + char *token = NULL; + char *ip_addr = NULL; + + struct send_file_data *sfd; + + for (l = pkt->hash; l; l = l->next) { + struct yahoo_pair *pair = l->data; + switch (pair->key) { + case 1: + case 4: + who = pair->value; + break; + case 5: + /* Me... don't care */ + break; + case 249: + break; + case 265: + id = pair->value; + break; + case 250: + ip_addr = pair->value; + break; + case 251: + token = pair->value; + break; + case 27: + filename = pair->value; + break; + } + } + + sfd = yahoo_get_active_transfer(id); + + if (sfd) { + sfd->token = strdup(token); + sfd->ip_addr = strdup(ip_addr); + + yahoo_file_transfer_accept(yid, sfd); + } + else { + YAHOO_CALLBACK(ext_yahoo_file_transfer_done) + (yid->yd->client_id, YAHOO_FILE_TRANSFER_UNKNOWN, + sfd->data); + + yahoo_remove_active_transfer(sfd); + } +} + +static void yahoo_send_filetransferinfo(struct yahoo_data *yd, + struct send_file_data *sfd) +{ + struct yahoo_input_data *yid; + struct yahoo_packet *pkt; + + yid = find_input_by_id_and_type(yd->client_id, YAHOO_CONNECTION_PAGER); + sfd->ip_addr = YAHOO_CALLBACK(ext_yahoo_get_ip_addr)("relay.yahoo.com"); + + if (!sfd->ip_addr) { + YAHOO_CALLBACK(ext_yahoo_file_transfer_done) + (yd->client_id, YAHOO_FILE_TRANSFER_RELAY, sfd->data); + + yahoo_remove_active_transfer(sfd); + + return; + } + + pkt = yahoo_packet_new(YAHOO_SERVICE_Y7_FILETRANSFERINFO, + YPACKET_STATUS_DEFAULT, yd->session_id); + + yahoo_packet_hash(pkt, 1, yd->user); + yahoo_packet_hash(pkt, 5, sfd->who); + yahoo_packet_hash(pkt, 265, sfd->id); + yahoo_packet_hash(pkt, 27, sfd->filename); + yahoo_packet_hash(pkt, 249, "3"); + yahoo_packet_hash(pkt, 250, sfd->ip_addr); + + yahoo_send_packet(yid, pkt, 0); + + yahoo_packet_free(pkt); +} + +static void yahoo_process_filetransfer(struct yahoo_input_data *yid, + struct yahoo_packet *pkt) +{ + YList *l; + char *who = NULL; + char *filename = NULL; + char *msg = NULL; + char *id = NULL; + int action = 0; + int size = 0; + struct yahoo_data *yd = yid->yd; + + struct send_file_data *sfd; + + for (l = pkt->hash; l; l = l->next) { + struct yahoo_pair *pair = l->data; + switch (pair->key) { + case 4: + who = pair->value; + break; + case 5: + /* Me... don't care */ + break; + case 222: + action = atoi(pair->value); + break; + case 265: + id = pair->value; + break; + case 266: /* Don't know */ + break; + case 302: /* Start Data? */ + break; + case 300: + break; + case 27: + filename = pair->value; + break; + case 28: + size = atoi(pair->value); + break; + case 14: + msg = pair->value; + case 301: /* End Data? */ + break; + case 303: + break; + + } + } + + if (action == YAHOO_FILE_TRANSFER_INIT) { + /* Received a FT request from buddy */ + sfd = y_new0(struct send_file_data, 1); + + sfd->client_id = yd->client_id; + sfd->id = strdup(id); + sfd->who = strdup(who); + sfd->filename = strdup(filename); + sfd->size = size; + + yahoo_add_active_transfer(sfd); + + YAHOO_CALLBACK(ext_yahoo_got_file) (yd->client_id, yd->user, + who, msg, filename, size, sfd->id); + } + else { + /* Response to our request */ + sfd = yahoo_get_active_transfer(id); + + if (sfd && action == YAHOO_FILE_TRANSFER_ACCEPT) { + yahoo_send_filetransferinfo(yd, sfd); + } + else if (!sfd || action == YAHOO_FILE_TRANSFER_REJECT) { + YAHOO_CALLBACK(ext_yahoo_file_transfer_done) + (yd->client_id, YAHOO_FILE_TRANSFER_REJECT, + sfd->data); + + yahoo_remove_active_transfer(sfd); + } + } +} + +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) +{ + struct yahoo_packet *pkt = NULL; + char size_str[10]; + struct yahoo_input_data *yid; + struct yahoo_data *yd; + struct send_file_data *sfd; + + yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + yd = find_conn_by_id(id); + sfd = y_new0(struct send_file_data, 1); + + sfd->client_id = id; + sfd->id = yahoo_get_random(); + sfd->who = strdup(who); + sfd->filename = strdup(name); + sfd->size = size; + sfd->callback = callback; + sfd->data = data; + + yahoo_add_active_transfer(sfd); + + if (!yd) + return; + + pkt = yahoo_packet_new(YAHOO_SERVICE_Y7_FILETRANSFER, + YPACKET_STATUS_DEFAULT, yd->session_id); + + snprintf(size_str, sizeof(size_str), "%ld", size); + + yahoo_packet_hash(pkt, 1, yd->user); + yahoo_packet_hash(pkt, 5, who); + yahoo_packet_hash(pkt, 265, sfd->id); + yahoo_packet_hash(pkt, 222, "1"); + yahoo_packet_hash(pkt, 266, "1"); + yahoo_packet_hash(pkt, 302, "268"); + yahoo_packet_hash(pkt, 300, "268"); + yahoo_packet_hash(pkt, 27, name); + yahoo_packet_hash(pkt, 28, size_str); + yahoo_packet_hash(pkt, 301, "268"); + yahoo_packet_hash(pkt, 303, "268"); + + yahoo_send_packet(yid, pkt, 0); + + yahoo_packet_free(pkt); +} + +void yahoo_send_file_transfer_response(int client_id, int response, char *id, void *data) +{ + struct yahoo_packet *pkt = NULL; + char resp[2]; + struct yahoo_input_data *yid; + + struct send_file_data *sfd = yahoo_get_active_transfer(id); + + sfd->data = data; + + yid = find_input_by_id_and_type(client_id, YAHOO_CONNECTION_PAGER); + + pkt = yahoo_packet_new(YAHOO_SERVICE_Y7_FILETRANSFER, + YPACKET_STATUS_DEFAULT, yid->yd->session_id); + + snprintf(resp, sizeof(resp), "%d", response); + + yahoo_packet_hash(pkt, 1, yid->yd->user); + yahoo_packet_hash(pkt, 5, sfd->who); + yahoo_packet_hash(pkt, 265, sfd->id); + yahoo_packet_hash(pkt, 222, resp); + + yahoo_send_packet(yid, pkt, 0); + + yahoo_packet_free(pkt); + + if(response == YAHOO_FILE_TRANSFER_REJECT) + yahoo_remove_active_transfer(sfd); +} + +static void yahoo_process_ft_connection(struct yahoo_input_data *yid, int over) +{ + struct send_file_data *sfd; + struct yahoo_data *yd = yid->yd; + + sfd = yahoo_get_active_transfer_with_yid(yid); + + if (!sfd) { + LOG(("Something funny happened. yid %p has no sfd.\n", yid)); + return; + } + + /* + * We want to handle only the complete data with HEAD since we don't + * want a situation where both the GET and HEAD are active. + * With SEND, we really can't do much with partial response + */ + if ((sfd->state == FT_STATE_HEAD || sfd->state == FT_STATE_SEND) + && !over) + return; + + if (sfd->state == FT_STATE_HEAD) { + /* Do a GET */ + char url[256]; + char buff[1024]; + char *sender_enc = NULL, *recv_enc = NULL, *token_enc = NULL; + + struct yahoo_input_data *yid_ft = + y_new0(struct yahoo_input_data, 1); + + yid_ft->yd = yid->yd; + yid_ft->type = YAHOO_CONNECTION_FT; + + inputs = y_list_prepend(inputs, yid_ft); + sfd->yid = yid_ft; + sfd->state = FT_STATE_RECV; + + token_enc = yahoo_urlencode(sfd->token); + sender_enc = yahoo_urlencode(sfd->who); + recv_enc = yahoo_urlencode(yd->user); + + snprintf(url, sizeof(url), + "http://%s/relay?token=%s&sender=%s&recver=%s", sfd->ip_addr, + token_enc, sender_enc, recv_enc); + + snprintf(buff, sizeof(buff), "Y=%s; T=%s", yd->cookie_y, + yd->cookie_t); + + + yahoo_http_get(yd->client_id, url, buff, 1, 1, + _yahoo_http_connected, yid_ft); + + FREE(token_enc); + FREE(sender_enc); + FREE(recv_enc); + } + else if (sfd->state == FT_STATE_RECV || + sfd->state == FT_STATE_RECV_START) { + + unsigned char *data_begin = NULL; + + if (yid->rxlen == 0) + yahoo_remove_active_transfer(sfd); + + if (sfd->state != FT_STATE_RECV_START && + (data_begin = + (unsigned char *)strstr((char *)yid->rxqueue, + "\r\n\r\n"))) { + + sfd->state = FT_STATE_RECV_START; + + yid->rxlen -= 4+(data_begin-yid->rxqueue)/sizeof(char); + data_begin += 4; + + if (yid->rxlen > 0) + YAHOO_CALLBACK(ext_yahoo_got_ft_data) + (yd->client_id, data_begin, + yid->rxlen, sfd->data); + } + else if (sfd->state == FT_STATE_RECV_START) + YAHOO_CALLBACK(ext_yahoo_got_ft_data) (yd->client_id, + yid->rxqueue, yid->rxlen, sfd->data); + + FREE(yid->rxqueue); + yid->rxqueue = NULL; + yid->rxlen = 0; + } + else if (sfd->state == FT_STATE_SEND) { + /* Sent file completed */ + int len = 0; + char *off = strstr((char *)yid->rxqueue, "Content-Length: "); + + if (off) { + off += 16; + len = atoi(off); + } + + if (len < sfd->size) + YAHOO_CALLBACK(ext_yahoo_file_transfer_done) + (yd->client_id, + YAHOO_FILE_TRANSFER_FAILED, sfd->data); + else + YAHOO_CALLBACK(ext_yahoo_file_transfer_done) + (yd->client_id, + YAHOO_FILE_TRANSFER_DONE, sfd->data); + + yahoo_remove_active_transfer(sfd); + } +} + +/* End File Transfer */ + +enum yahoo_status yahoo_current_status(int id) +{ + struct yahoo_data *yd = find_conn_by_id(id); + if (!yd) + return YAHOO_STATUS_OFFLINE; + return yd->current_status; +} + +const YList *yahoo_get_buddylist(int id) +{ + struct yahoo_data *yd = find_conn_by_id(id); + if (!yd) + return NULL; + return yd->buddies; +} + +const YList *yahoo_get_ignorelist(int id) +{ + struct yahoo_data *yd = find_conn_by_id(id); + if (!yd) + return NULL; + return yd->ignore; +} + +const YList *yahoo_get_identities(int id) +{ + struct yahoo_data *yd = find_conn_by_id(id); + if (!yd) + return NULL; + return yd->identities; +} + +const char *yahoo_get_cookie(int id, const char *which) +{ + struct yahoo_data *yd = find_conn_by_id(id); + if (!yd) + return NULL; + if (!strncasecmp(which, "y", 1)) + return yd->cookie_y; + if (!strncasecmp(which, "b", 1)) + return yd->cookie_b; + if (!strncasecmp(which, "t", 1)) + return yd->cookie_t; + if (!strncasecmp(which, "c", 1)) + return yd->cookie_c; + if (!strncasecmp(which, "login", 5)) + return yd->login_cookie; + return NULL; +} + +const char *yahoo_get_profile_url(void) +{ + return profile_url; +} diff --git a/backends/libyahoo2/yahoo/md5.c b/backends/libyahoo2/yahoo/md5.c new file mode 100644 index 0000000000000000000000000000000000000000..cfd06ea4fd2117689bc17db27ed11a91642bd940 --- /dev/null +++ b/backends/libyahoo2/yahoo/md5.c @@ -0,0 +1,405 @@ +/* + Copyright (C) 1999 Aladdin Enterprises. All rights reserved. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + L. Peter Deutsch + ghost@aladdin.com + + */ +/* + Independent implementation of MD5 (RFC 1321). + + This code implements the MD5 Algorithm defined in RFC 1321. + It is derived directly from the text of the RFC and not from the + reference implementation. + + The original and principal author of md5.c is L. Peter Deutsch + . Other authors are noted in the change history + that follows (in reverse chronological order): + + 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. + 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). + 1999-05-03 lpd Original version. + */ + +#if HAVE_CONFIG_H +# include +#endif + +#include "md5.h" + +#if STDC_HEADERS +# include +#else +# if !HAVE_STRCHR +# define strchr index +# define strrchr rindex +# endif +char *strchr(), *strrchr(); +# if !HAVE_MEMCPY +# define memcpy(d, s, n) bcopy ((s), (d), (n)) +# define memmove(d, s, n) bcopy ((s), (d), (n)) +# endif +#endif + +#ifdef TEST +/* + * Compile with -DTEST to create a self-contained executable test program. + * The test program should print out the same values as given in section + * A.5 of RFC 1321, reproduced below. + */ +main() +{ + static const char *const test[7] = { + "", /*d41d8cd98f00b204e9800998ecf8427e */ + "945399884.61923487334tuvga", /*0cc175b9c0f1b6a831c399e269772661 */ + "abc", /*900150983cd24fb0d6963f7d28e17f72 */ + "message digest", /*f96b697d7cb7938d525a2f31aaf161d0 */ + "abcdefghijklmnopqrstuvwxyz", /*c3fcd3d76192e4007dfb496cca67e13b */ + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + /*d174ab98d277d9f5a5611c2c9f419d9f */ + "12345678901234567890123456789012345678901234567890123456789012345678901234567890" /*57edf4a22be3c955ac49da2e2107b67a */ + }; + int i; + + for (i = 0; i < 7; ++i) { + md5_state_t state; + md5_byte_t digest[16]; + int di; + + md5_init(&state); + md5_append(&state, (const md5_byte_t *)test[i], + strlen(test[i])); + md5_finish(&state, digest); + printf("MD5 (\"%s\") = ", test[i]); + for (di = 0; di < 16; ++di) + printf("%02x", digest[di]); + printf("\n"); + } + return 0; +} +#endif /* TEST */ + +/* + * For reference, here is the program that computed the T values. + */ +#if 0 +#include +main() +{ + int i; + for (i = 1; i <= 64; ++i) { + unsigned long v = + (unsigned long)(4294967296.0 * fabs(sin((double)i))); + printf("#define T%d 0x%08lx\n", i, v); + } + return 0; +} +#endif +/* + * End of T computation program. + */ +#define T1 0xd76aa478 +#define T2 0xe8c7b756 +#define T3 0x242070db +#define T4 0xc1bdceee +#define T5 0xf57c0faf +#define T6 0x4787c62a +#define T7 0xa8304613 +#define T8 0xfd469501 +#define T9 0x698098d8 +#define T10 0x8b44f7af +#define T11 0xffff5bb1 +#define T12 0x895cd7be +#define T13 0x6b901122 +#define T14 0xfd987193 +#define T15 0xa679438e +#define T16 0x49b40821 +#define T17 0xf61e2562 +#define T18 0xc040b340 +#define T19 0x265e5a51 +#define T20 0xe9b6c7aa +#define T21 0xd62f105d +#define T22 0x02441453 +#define T23 0xd8a1e681 +#define T24 0xe7d3fbc8 +#define T25 0x21e1cde6 +#define T26 0xc33707d6 +#define T27 0xf4d50d87 +#define T28 0x455a14ed +#define T29 0xa9e3e905 +#define T30 0xfcefa3f8 +#define T31 0x676f02d9 +#define T32 0x8d2a4c8a +#define T33 0xfffa3942 +#define T34 0x8771f681 +#define T35 0x6d9d6122 +#define T36 0xfde5380c +#define T37 0xa4beea44 +#define T38 0x4bdecfa9 +#define T39 0xf6bb4b60 +#define T40 0xbebfbc70 +#define T41 0x289b7ec6 +#define T42 0xeaa127fa +#define T43 0xd4ef3085 +#define T44 0x04881d05 +#define T45 0xd9d4d039 +#define T46 0xe6db99e5 +#define T47 0x1fa27cf8 +#define T48 0xc4ac5665 +#define T49 0xf4292244 +#define T50 0x432aff97 +#define T51 0xab9423a7 +#define T52 0xfc93a039 +#define T53 0x655b59c3 +#define T54 0x8f0ccc92 +#define T55 0xffeff47d +#define T56 0x85845dd1 +#define T57 0x6fa87e4f +#define T58 0xfe2ce6e0 +#define T59 0xa3014314 +#define T60 0x4e0811a1 +#define T61 0xf7537e82 +#define T62 0xbd3af235 +#define T63 0x2ad7d2bb +#define T64 0xeb86d391 + +static void md5_process(md5_state_t *pms, const md5_byte_t *data /*[64] */ ) +{ + md5_word_t + a = pms->abcd[0], b = pms->abcd[1], + c = pms->abcd[2], d = pms->abcd[3]; + md5_word_t t; + +#ifndef ARCH_IS_BIG_ENDIAN +# define ARCH_IS_BIG_ENDIAN 1 /* slower, default implementation */ +#endif +#if ARCH_IS_BIG_ENDIAN + + /* + * On big-endian machines, we must arrange the bytes in the right + * order. (This also works on machines of unknown byte order.) + */ + md5_word_t X[16]; + const md5_byte_t *xp = data; + int i; + + for (i = 0; i < 16; ++i, xp += 4) + X[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); + +#else /* !ARCH_IS_BIG_ENDIAN */ + + /* + * On little-endian machines, we can process properly aligned data + * without copying it. + */ + md5_word_t xbuf[16]; + const md5_word_t *X; + + if (!((data - (const md5_byte_t *)0) & 3)) { + /* data are properly aligned */ + X = (const md5_word_t *)data; + } else { + /* not aligned */ + memcpy(xbuf, data, 64); + X = xbuf; + } +#endif + +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) + + /* Round 1. */ + /* Let [abcd k s i] denote the operation + a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ +#define F(x, y, z) (((x) & (y)) | (~(x) & (z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + F(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 0, 7, T1); + SET(d, a, b, c, 1, 12, T2); + SET(c, d, a, b, 2, 17, T3); + SET(b, c, d, a, 3, 22, T4); + SET(a, b, c, d, 4, 7, T5); + SET(d, a, b, c, 5, 12, T6); + SET(c, d, a, b, 6, 17, T7); + SET(b, c, d, a, 7, 22, T8); + SET(a, b, c, d, 8, 7, T9); + SET(d, a, b, c, 9, 12, T10); + SET(c, d, a, b, 10, 17, T11); + SET(b, c, d, a, 11, 22, T12); + SET(a, b, c, d, 12, 7, T13); + SET(d, a, b, c, 13, 12, T14); + SET(c, d, a, b, 14, 17, T15); + SET(b, c, d, a, 15, 22, T16); +#undef SET + + /* Round 2. */ + /* Let [abcd k s i] denote the operation + a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ +#define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + G(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 1, 5, T17); + SET(d, a, b, c, 6, 9, T18); + SET(c, d, a, b, 11, 14, T19); + SET(b, c, d, a, 0, 20, T20); + SET(a, b, c, d, 5, 5, T21); + SET(d, a, b, c, 10, 9, T22); + SET(c, d, a, b, 15, 14, T23); + SET(b, c, d, a, 4, 20, T24); + SET(a, b, c, d, 9, 5, T25); + SET(d, a, b, c, 14, 9, T26); + SET(c, d, a, b, 3, 14, T27); + SET(b, c, d, a, 8, 20, T28); + SET(a, b, c, d, 13, 5, T29); + SET(d, a, b, c, 2, 9, T30); + SET(c, d, a, b, 7, 14, T31); + SET(b, c, d, a, 12, 20, T32); +#undef SET + + /* Round 3. */ + /* Let [abcd k s t] denote the operation + a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + H(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 5, 4, T33); + SET(d, a, b, c, 8, 11, T34); + SET(c, d, a, b, 11, 16, T35); + SET(b, c, d, a, 14, 23, T36); + SET(a, b, c, d, 1, 4, T37); + SET(d, a, b, c, 4, 11, T38); + SET(c, d, a, b, 7, 16, T39); + SET(b, c, d, a, 10, 23, T40); + SET(a, b, c, d, 13, 4, T41); + SET(d, a, b, c, 0, 11, T42); + SET(c, d, a, b, 3, 16, T43); + SET(b, c, d, a, 6, 23, T44); + SET(a, b, c, d, 9, 4, T45); + SET(d, a, b, c, 12, 11, T46); + SET(c, d, a, b, 15, 16, T47); + SET(b, c, d, a, 2, 23, T48); +#undef SET + + /* Round 4. */ + /* Let [abcd k s t] denote the operation + a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ +#define I(x, y, z) ((y) ^ ((x) | ~(z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + I(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 0, 6, T49); + SET(d, a, b, c, 7, 10, T50); + SET(c, d, a, b, 14, 15, T51); + SET(b, c, d, a, 5, 21, T52); + SET(a, b, c, d, 12, 6, T53); + SET(d, a, b, c, 3, 10, T54); + SET(c, d, a, b, 10, 15, T55); + SET(b, c, d, a, 1, 21, T56); + SET(a, b, c, d, 8, 6, T57); + SET(d, a, b, c, 15, 10, T58); + SET(c, d, a, b, 6, 15, T59); + SET(b, c, d, a, 13, 21, T60); + SET(a, b, c, d, 4, 6, T61); + SET(d, a, b, c, 11, 10, T62); + SET(c, d, a, b, 2, 15, T63); + SET(b, c, d, a, 9, 21, T64); +#undef SET + + /* Then perform the following additions. (That is increment each + of the four registers by the value it had before this block + was started.) */ + pms->abcd[0] += a; + pms->abcd[1] += b; + pms->abcd[2] += c; + pms->abcd[3] += d; +} + +void md5_init(md5_state_t *pms) +{ + pms->count[0] = pms->count[1] = 0; + pms->abcd[0] = 0x67452301; + pms->abcd[1] = 0xefcdab89; + pms->abcd[2] = 0x98badcfe; + pms->abcd[3] = 0x10325476; +} + +void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes) +{ + const md5_byte_t *p = data; + int left = nbytes; + int offset = (pms->count[0] >> 3) & 63; + md5_word_t nbits = (md5_word_t) (nbytes << 3); + + if (nbytes <= 0) + return; + + /* Update the message length. */ + pms->count[1] += nbytes >> 29; + pms->count[0] += nbits; + if (pms->count[0] < nbits) + pms->count[1]++; + + /* Process an initial partial block. */ + if (offset) { + int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); + + memcpy(pms->buf + offset, p, copy); + if (offset + copy < 64) + return; + p += copy; + left -= copy; + md5_process(pms, pms->buf); + } + + /* Process full blocks. */ + for (; left >= 64; p += 64, left -= 64) + md5_process(pms, p); + + /* Process a final partial block. */ + if (left) + memcpy(pms->buf, p, left); +} + +void md5_finish(md5_state_t *pms, md5_byte_t digest[16]) +{ + static const md5_byte_t pad[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + md5_byte_t data[8]; + int i; + + /* Save the length before padding. */ + for (i = 0; i < 8; ++i) + data[i] = (md5_byte_t) (pms->count[i >> 2] >> ((i & 3) << 3)); + /* Pad to 56 bytes mod 64. */ + md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); + /* Append the length. */ + md5_append(pms, data, 8); + for (i = 0; i < 16; ++i) + digest[i] = (md5_byte_t) (pms->abcd[i >> 2] >> ((i & 3) << 3)); +} diff --git a/backends/libyahoo2/yahoo/md5.h b/backends/libyahoo2/yahoo/md5.h new file mode 100644 index 0000000000000000000000000000000000000000..6c75aa6a59ffd761cb8835c7da83634e440cbb46 --- /dev/null +++ b/backends/libyahoo2/yahoo/md5.h @@ -0,0 +1,92 @@ +/* + Copyright (C) 1999 Aladdin Enterprises. All rights reserved. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + L. Peter Deutsch + ghost@aladdin.com + + */ +/* + Independent implementation of MD5 (RFC 1321). + + This code implements the MD5 Algorithm defined in RFC 1321. + It is derived directly from the text of the RFC and not from the + reference implementation. + + The original and principal author of md5.h is L. Peter Deutsch + . Other authors are noted in the change history + that follows (in reverse chronological order): + + 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. + 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); + added conditionalization for C++ compilation from Martin + Purschke . + 1999-05-03 lpd Original version. + */ + +#ifndef md5_INCLUDED +# define md5_INCLUDED + +/* + * This code has some adaptations for the Ghostscript environment, but it + * will compile and run correctly in any environment with 8-bit chars and + * 32-bit ints. Specifically, it assumes that if the following are + * defined, they have the same meaning as in Ghostscript: P1, P2, P3, + * ARCH_IS_BIG_ENDIAN. + */ + +typedef unsigned char md5_byte_t; /* 8-bit byte */ +typedef unsigned int md5_word_t; /* 32-bit word */ + +/* Define the state of the MD5 Algorithm. */ +typedef struct md5_state_s { + md5_word_t count[2]; /* message length in bits, lsw first */ + md5_word_t abcd[4]; /* digest buffer */ + md5_byte_t buf[64]; /* accumulate block */ +} md5_state_t; + +#ifdef __cplusplus +extern "C" { +#endif + +/* Initialize the algorithm. */ +#ifdef P1 + void md5_init(P1(md5_state_t *pms)); +#else + void md5_init(md5_state_t *pms); +#endif + +/* Append a string to the message. */ +#ifdef P3 + void md5_append(P3(md5_state_t *pms, const md5_byte_t *data, + int nbytes)); +#else + void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); +#endif + +/* Finish the message and return the digest. */ +#ifdef P2 + void md5_finish(P2(md5_state_t *pms, md5_byte_t digest[16])); +#else + void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); +#endif + +#ifdef __cplusplus +} /* end extern "C" */ +#endif +#endif /* md5_INCLUDED */ diff --git a/backends/libyahoo2/yahoo/sha1.c b/backends/libyahoo2/yahoo/sha1.c new file mode 100644 index 0000000000000000000000000000000000000000..d90b17bae9f5ff32e38a260852824030bdd7af22 --- /dev/null +++ b/backends/libyahoo2/yahoo/sha1.c @@ -0,0 +1,613 @@ +/*- + * Copyright (c) 2001-2003 Allan Saddi + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY ALLAN SADDI AND HIS 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 ALLAN SADDI OR HIS 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. + */ + +/* + * Define WORDS_BIGENDIAN if compiling on a big-endian architecture. + * + * Define SHA1_TEST to test the implementation using the NIST's + * sample messages. The output should be: + * + * a9993e36 4706816a ba3e2571 7850c26c 9cd0d89d + * 84983e44 1c3bd26e baae4aa1 f95129e5 e54670f1 + * 34aa973c d4c4daa4 f61eeb2b dbad2731 6534016f + */ + +#ifdef HAVE_CONFIG_H +#include +#endif /* HAVE_CONFIG_H */ + +#if HAVE_INTTYPES_H +# include +#else +# if HAVE_STDINT_H +# include +# endif +#endif + +#include + +#include "sha1.h" + +#define ROTL(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) +#define ROTR(x, n) (((x) >> (n)) | ((x) << (32 - (n)))) + +#define F_0_19(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) +#define F_20_39(x, y, z) ((x) ^ (y) ^ (z)) +#define F_40_59(x, y, z) (((x) & ((y) | (z))) | ((y) & (z))) +#define F_60_79(x, y, z) ((x) ^ (y) ^ (z)) + +#define DO_ROUND(F, K) { \ + temp = ROTL(a, 5) + F(b, c, d) + e + *(W++) + K; \ + e = d; \ + d = c; \ + c = ROTL(b, 30); \ + b = a; \ + a = temp; \ +} + +#define K_0_19 0x5a827999L +#define K_20_39 0x6ed9eba1L +#define K_40_59 0x8f1bbcdcL +#define K_60_79 0xca62c1d6L + +#ifndef RUNTIME_ENDIAN + +#ifdef WORDS_BIGENDIAN + +#define BYTESWAP(x) (x) +#define BYTESWAP64(x) (x) + +#else /* WORDS_BIGENDIAN */ + +#define BYTESWAP(x) ((ROTR((x), 8) & 0xff00ff00L) | (ROTL((x), 8) & 0x00ff00ffL)) + +static uint64_t _byteswap64(uint64_t x) +{ + uint32_t a = x >> 32; + uint32_t b = (uint32_t) x; + return ((uint64_t) BYTESWAP(b) << 32) | (uint64_t) BYTESWAP(a); +} + +#define BYTESWAP64(x) _byteswap64(x) + +#endif /* WORDS_BIGENDIAN */ + +#else /* !RUNTIME_ENDIAN */ + +#define BYTESWAP(x) _byteswap(sc->littleEndian, x) +#define BYTESWAP64(x) _byteswap64(sc->littleEndian, x) + +#define _BYTESWAP(x) ((ROTR((x), 8) & 0xff00ff00L) | \ + (ROTL((x), 8) & 0x00ff00ffL)) +#define _BYTESWAP64(x) __byteswap64(x) + +static uint64_t __byteswap64(uint64_t x) +{ + uint32_t a = x >> 32; + uint32_t b = (uint32_t) x; + return ((uint64_t) _BYTESWAP(b) << 32) | (uint64_t) _BYTESWAP(a); +} + +static uint32_t _byteswap(int littleEndian, uint32_t x) +{ + if (!littleEndian) + return x; + else + return _BYTESWAP(x); +} + +static uint64_t _byteswap64(int littleEndian, uint64_t x) +{ + if (!littleEndian) + return x; + else + return _BYTESWAP64(x); +} + +static void setEndian(int *littleEndianp) +{ + union { + uint32_t w; + uint8_t b[4]; + } endian; + + endian.w = 1L; + *littleEndianp = endian.b[0] != 0; +} + +#endif /* !RUNTIME_ENDIAN */ + +static const uint8_t padding[64] = { + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +void SHA1Init(SHA1Context *sc) +{ +#ifdef RUNTIME_ENDIAN + setEndian(&sc->littleEndian); +#endif /* RUNTIME_ENDIAN */ + + sc->totalLength = 0LL; + sc->hash[0] = 0x67452301L; + sc->hash[1] = 0xefcdab89L; + sc->hash[2] = 0x98badcfeL; + sc->hash[3] = 0x10325476L; + sc->hash[4] = 0xc3d2e1f0L; + sc->bufferLength = 0L; +} + +static void burnStack(int size) +{ + char buf[128]; + + memset(buf, 0, sizeof(buf)); + size -= sizeof(buf); + if (size > 0) + burnStack(size); +} + +static void SHA1Guts(SHA1Context *sc, const uint32_t *cbuf) +{ + uint32_t buf[80]; + uint32_t *W, *W3, *W8, *W14, *W16; + uint32_t a, b, c, d, e, temp; + int i; + + W = buf; + + for (i = 15; i >= 0; i--) { + *(W++) = BYTESWAP(*cbuf); + cbuf++; + } + + W16 = &buf[0]; + W14 = &buf[2]; + W8 = &buf[8]; + W3 = &buf[13]; + + for (i = 63; i >= 0; i--) { + *W = *(W3++) ^ *(W8++) ^ *(W14++) ^ *(W16++); + *W = ROTL(*W, 1); + W++; + } + + a = sc->hash[0]; + b = sc->hash[1]; + c = sc->hash[2]; + d = sc->hash[3]; + e = sc->hash[4]; + + W = buf; + +#ifndef SHA1_UNROLL +#define SHA1_UNROLL 20 +#endif /* !SHA1_UNROLL */ + +#if SHA1_UNROLL == 1 + for (i = 19; i >= 0; i--) + DO_ROUND(F_0_19, K_0_19); + + for (i = 19; i >= 0; i--) + DO_ROUND(F_20_39, K_20_39); + + for (i = 19; i >= 0; i--) + DO_ROUND(F_40_59, K_40_59); + + for (i = 19; i >= 0; i--) + DO_ROUND(F_60_79, K_60_79); +#elif SHA1_UNROLL == 2 + for (i = 9; i >= 0; i--) { + DO_ROUND(F_0_19, K_0_19); + DO_ROUND(F_0_19, K_0_19); + } + + for (i = 9; i >= 0; i--) { + DO_ROUND(F_20_39, K_20_39); + DO_ROUND(F_20_39, K_20_39); + } + + for (i = 9; i >= 0; i--) { + DO_ROUND(F_40_59, K_40_59); + DO_ROUND(F_40_59, K_40_59); + } + + for (i = 9; i >= 0; i--) { + DO_ROUND(F_60_79, K_60_79); + DO_ROUND(F_60_79, K_60_79); + } +#elif SHA1_UNROLL == 4 + for (i = 4; i >= 0; i--) { + DO_ROUND(F_0_19, K_0_19); + DO_ROUND(F_0_19, K_0_19); + DO_ROUND(F_0_19, K_0_19); + DO_ROUND(F_0_19, K_0_19); + } + + for (i = 4; i >= 0; i--) { + DO_ROUND(F_20_39, K_20_39); + DO_ROUND(F_20_39, K_20_39); + DO_ROUND(F_20_39, K_20_39); + DO_ROUND(F_20_39, K_20_39); + } + + for (i = 4; i >= 0; i--) { + DO_ROUND(F_40_59, K_40_59); + DO_ROUND(F_40_59, K_40_59); + DO_ROUND(F_40_59, K_40_59); + DO_ROUND(F_40_59, K_40_59); + } + + for (i = 4; i >= 0; i--) { + DO_ROUND(F_60_79, K_60_79); + DO_ROUND(F_60_79, K_60_79); + DO_ROUND(F_60_79, K_60_79); + DO_ROUND(F_60_79, K_60_79); + } +#elif SHA1_UNROLL == 5 + for (i = 3; i >= 0; i--) { + DO_ROUND(F_0_19, K_0_19); + DO_ROUND(F_0_19, K_0_19); + DO_ROUND(F_0_19, K_0_19); + DO_ROUND(F_0_19, K_0_19); + DO_ROUND(F_0_19, K_0_19); + } + + for (i = 3; i >= 0; i--) { + DO_ROUND(F_20_39, K_20_39); + DO_ROUND(F_20_39, K_20_39); + DO_ROUND(F_20_39, K_20_39); + DO_ROUND(F_20_39, K_20_39); + DO_ROUND(F_20_39, K_20_39); + } + + for (i = 3; i >= 0; i--) { + DO_ROUND(F_40_59, K_40_59); + DO_ROUND(F_40_59, K_40_59); + DO_ROUND(F_40_59, K_40_59); + DO_ROUND(F_40_59, K_40_59); + DO_ROUND(F_40_59, K_40_59); + } + + for (i = 3; i >= 0; i--) { + DO_ROUND(F_60_79, K_60_79); + DO_ROUND(F_60_79, K_60_79); + DO_ROUND(F_60_79, K_60_79); + DO_ROUND(F_60_79, K_60_79); + DO_ROUND(F_60_79, K_60_79); + } +#elif SHA1_UNROLL == 10 + for (i = 1; i >= 0; i--) { + DO_ROUND(F_0_19, K_0_19); + DO_ROUND(F_0_19, K_0_19); + DO_ROUND(F_0_19, K_0_19); + DO_ROUND(F_0_19, K_0_19); + DO_ROUND(F_0_19, K_0_19); + DO_ROUND(F_0_19, K_0_19); + DO_ROUND(F_0_19, K_0_19); + DO_ROUND(F_0_19, K_0_19); + DO_ROUND(F_0_19, K_0_19); + DO_ROUND(F_0_19, K_0_19); + } + + for (i = 1; i >= 0; i--) { + DO_ROUND(F_20_39, K_20_39); + DO_ROUND(F_20_39, K_20_39); + DO_ROUND(F_20_39, K_20_39); + DO_ROUND(F_20_39, K_20_39); + DO_ROUND(F_20_39, K_20_39); + DO_ROUND(F_20_39, K_20_39); + DO_ROUND(F_20_39, K_20_39); + DO_ROUND(F_20_39, K_20_39); + DO_ROUND(F_20_39, K_20_39); + DO_ROUND(F_20_39, K_20_39); + } + + for (i = 1; i >= 0; i--) { + DO_ROUND(F_40_59, K_40_59); + DO_ROUND(F_40_59, K_40_59); + DO_ROUND(F_40_59, K_40_59); + DO_ROUND(F_40_59, K_40_59); + DO_ROUND(F_40_59, K_40_59); + DO_ROUND(F_40_59, K_40_59); + DO_ROUND(F_40_59, K_40_59); + DO_ROUND(F_40_59, K_40_59); + DO_ROUND(F_40_59, K_40_59); + DO_ROUND(F_40_59, K_40_59); + } + + for (i = 1; i >= 0; i--) { + DO_ROUND(F_60_79, K_60_79); + DO_ROUND(F_60_79, K_60_79); + DO_ROUND(F_60_79, K_60_79); + DO_ROUND(F_60_79, K_60_79); + DO_ROUND(F_60_79, K_60_79); + DO_ROUND(F_60_79, K_60_79); + DO_ROUND(F_60_79, K_60_79); + DO_ROUND(F_60_79, K_60_79); + DO_ROUND(F_60_79, K_60_79); + DO_ROUND(F_60_79, K_60_79); + } +#elif SHA1_UNROLL == 20 + DO_ROUND(F_0_19, K_0_19); + DO_ROUND(F_0_19, K_0_19); + DO_ROUND(F_0_19, K_0_19); + DO_ROUND(F_0_19, K_0_19); + DO_ROUND(F_0_19, K_0_19); + DO_ROUND(F_0_19, K_0_19); + DO_ROUND(F_0_19, K_0_19); + DO_ROUND(F_0_19, K_0_19); + DO_ROUND(F_0_19, K_0_19); + DO_ROUND(F_0_19, K_0_19); + DO_ROUND(F_0_19, K_0_19); + DO_ROUND(F_0_19, K_0_19); + DO_ROUND(F_0_19, K_0_19); + DO_ROUND(F_0_19, K_0_19); + DO_ROUND(F_0_19, K_0_19); + DO_ROUND(F_0_19, K_0_19); + DO_ROUND(F_0_19, K_0_19); + DO_ROUND(F_0_19, K_0_19); + DO_ROUND(F_0_19, K_0_19); + DO_ROUND(F_0_19, K_0_19); + + DO_ROUND(F_20_39, K_20_39); + DO_ROUND(F_20_39, K_20_39); + DO_ROUND(F_20_39, K_20_39); + DO_ROUND(F_20_39, K_20_39); + DO_ROUND(F_20_39, K_20_39); + DO_ROUND(F_20_39, K_20_39); + DO_ROUND(F_20_39, K_20_39); + DO_ROUND(F_20_39, K_20_39); + DO_ROUND(F_20_39, K_20_39); + DO_ROUND(F_20_39, K_20_39); + DO_ROUND(F_20_39, K_20_39); + DO_ROUND(F_20_39, K_20_39); + DO_ROUND(F_20_39, K_20_39); + DO_ROUND(F_20_39, K_20_39); + DO_ROUND(F_20_39, K_20_39); + DO_ROUND(F_20_39, K_20_39); + DO_ROUND(F_20_39, K_20_39); + DO_ROUND(F_20_39, K_20_39); + DO_ROUND(F_20_39, K_20_39); + DO_ROUND(F_20_39, K_20_39); + + DO_ROUND(F_40_59, K_40_59); + DO_ROUND(F_40_59, K_40_59); + DO_ROUND(F_40_59, K_40_59); + DO_ROUND(F_40_59, K_40_59); + DO_ROUND(F_40_59, K_40_59); + DO_ROUND(F_40_59, K_40_59); + DO_ROUND(F_40_59, K_40_59); + DO_ROUND(F_40_59, K_40_59); + DO_ROUND(F_40_59, K_40_59); + DO_ROUND(F_40_59, K_40_59); + DO_ROUND(F_40_59, K_40_59); + DO_ROUND(F_40_59, K_40_59); + DO_ROUND(F_40_59, K_40_59); + DO_ROUND(F_40_59, K_40_59); + DO_ROUND(F_40_59, K_40_59); + DO_ROUND(F_40_59, K_40_59); + DO_ROUND(F_40_59, K_40_59); + DO_ROUND(F_40_59, K_40_59); + DO_ROUND(F_40_59, K_40_59); + DO_ROUND(F_40_59, K_40_59); + + DO_ROUND(F_60_79, K_60_79); + DO_ROUND(F_60_79, K_60_79); + DO_ROUND(F_60_79, K_60_79); + DO_ROUND(F_60_79, K_60_79); + DO_ROUND(F_60_79, K_60_79); + DO_ROUND(F_60_79, K_60_79); + DO_ROUND(F_60_79, K_60_79); + DO_ROUND(F_60_79, K_60_79); + DO_ROUND(F_60_79, K_60_79); + DO_ROUND(F_60_79, K_60_79); + DO_ROUND(F_60_79, K_60_79); + DO_ROUND(F_60_79, K_60_79); + DO_ROUND(F_60_79, K_60_79); + DO_ROUND(F_60_79, K_60_79); + DO_ROUND(F_60_79, K_60_79); + DO_ROUND(F_60_79, K_60_79); + DO_ROUND(F_60_79, K_60_79); + DO_ROUND(F_60_79, K_60_79); + DO_ROUND(F_60_79, K_60_79); + DO_ROUND(F_60_79, K_60_79); +#else /* SHA1_UNROLL */ +#error SHA1_UNROLL must be 1, 2, 4, 5, 10 or 20! +#endif + + sc->hash[0] += a; + sc->hash[1] += b; + sc->hash[2] += c; + sc->hash[3] += d; + sc->hash[4] += e; +} + +void SHA1Update(SHA1Context *sc, const void *vdata, uint32_t len) +{ + const uint8_t *data = vdata; + uint32_t bufferBytesLeft; + uint32_t bytesToCopy; + int needBurn = 0; + +#ifdef SHA1_FAST_COPY + if (sc->bufferLength) { + bufferBytesLeft = 64L - sc->bufferLength; + + bytesToCopy = bufferBytesLeft; + if (bytesToCopy > len) + bytesToCopy = len; + + memcpy(&sc->buffer.bytes[sc->bufferLength], data, bytesToCopy); + + sc->totalLength += bytesToCopy * 8L; + + sc->bufferLength += bytesToCopy; + data += bytesToCopy; + len -= bytesToCopy; + + if (sc->bufferLength == 64L) { + SHA1Guts(sc, sc->buffer.words); + needBurn = 1; + sc->bufferLength = 0L; + } + } + + while (len > 63) { + sc->totalLength += 512L; + + SHA1Guts(sc, data); + needBurn = 1; + + data += 64L; + len -= 64L; + } + + if (len) { + memcpy(&sc->buffer.bytes[sc->bufferLength], data, len); + + sc->totalLength += len * 8L; + + sc->bufferLength += len; + } +#else /* SHA1_FAST_COPY */ + while (len) { + bufferBytesLeft = 64L - sc->bufferLength; + + bytesToCopy = bufferBytesLeft; + if (bytesToCopy > len) + bytesToCopy = len; + + memcpy(&sc->buffer.bytes[sc->bufferLength], data, bytesToCopy); + + sc->totalLength += bytesToCopy * 8L; + + sc->bufferLength += bytesToCopy; + data += bytesToCopy; + len -= bytesToCopy; + + if (sc->bufferLength == 64L) { + SHA1Guts(sc, sc->buffer.words); + needBurn = 1; + sc->bufferLength = 0L; + } + } +#endif /* SHA1_FAST_COPY */ + + if (needBurn) + burnStack(sizeof(uint32_t[86]) + sizeof(uint32_t *[5]) + + sizeof(int)); +} + +void SHA1Final(SHA1Context *sc, uint8_t hash[SHA1_HASH_SIZE]) +{ + uint32_t bytesToPad; + uint64_t lengthPad; + int i; + + bytesToPad = 120L - sc->bufferLength; + if (bytesToPad > 64L) + bytesToPad -= 64L; + + lengthPad = BYTESWAP64(sc->totalLength); + + SHA1Update(sc, padding, bytesToPad); + SHA1Update(sc, &lengthPad, 8L); + + if (hash) { + for (i = 0; i < SHA1_HASH_WORDS; i++) { +#ifdef SHA1_FAST_COPY + *((uint32_t *)hash) = BYTESWAP(sc->hash[i]); +#else /* SHA1_FAST_COPY */ + hash[0] = (uint8_t) (sc->hash[i] >> 24); + hash[1] = (uint8_t) (sc->hash[i] >> 16); + hash[2] = (uint8_t) (sc->hash[i] >> 8); + hash[3] = (uint8_t) sc->hash[i]; +#endif /* SHA1_FAST_COPY */ + hash += 4; + } + } +} + +#ifdef SHA1_TEST + +#include +#include +#include + +int main(int argc, char *argv[]) +{ + SHA1Context foo; + uint8_t hash[SHA1_HASH_SIZE]; + char buf[1000]; + int i; + + SHA1Init(&foo); + SHA1Update(&foo, "abc", 3); + SHA1Final(&foo, hash); + + for (i = 0; i < SHA1_HASH_SIZE;) { + printf("%02x", hash[i++]); + if (!(i % 4)) + printf(" "); + } + printf("\n"); + + SHA1Init(&foo); + SHA1Update(&foo, + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56); + SHA1Final(&foo, hash); + + for (i = 0; i < SHA1_HASH_SIZE;) { + printf("%02x", hash[i++]); + if (!(i % 4)) + printf(" "); + } + printf("\n"); + + SHA1Init(&foo); + memset(buf, 'a', sizeof(buf)); + for (i = 0; i < 1000; i++) + SHA1Update(&foo, buf, sizeof(buf)); + SHA1Final(&foo, hash); + + for (i = 0; i < SHA1_HASH_SIZE;) { + printf("%02x", hash[i++]); + if (!(i % 4)) + printf(" "); + } + printf("\n"); + + exit(0); +} + +#endif /* SHA1_TEST */ diff --git a/backends/libyahoo2/yahoo/sha1.h b/backends/libyahoo2/yahoo/sha1.h new file mode 100644 index 0000000000000000000000000000000000000000..b42d61300a15c8ba14296cf7af227c20b95b5fcb --- /dev/null +++ b/backends/libyahoo2/yahoo/sha1.h @@ -0,0 +1,69 @@ +/*- + * Copyright (c) 2001-2003 Allan Saddi + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY ALLAN SADDI AND HIS 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 ALLAN SADDI OR HIS 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 _SHA1_H +#define _SHA1_H + +#if HAVE_INTTYPES_H +# include +#else +# if HAVE_STDINT_H +# include +# endif +#endif + +#define SHA1_HASH_SIZE 20 + +/* Hash size in 32-bit words */ +#define SHA1_HASH_WORDS 5 + +struct _SHA1Context { + uint64_t totalLength; + uint32_t hash[SHA1_HASH_WORDS]; + uint32_t bufferLength; + union { + uint32_t words[16]; + uint8_t bytes[64]; + } buffer; +#ifdef RUNTIME_ENDIAN + int littleEndian; +#endif /* RUNTIME_ENDIAN */ +}; + +typedef struct _SHA1Context SHA1Context; + +#ifdef __cplusplus +extern "C" { +#endif + + void SHA1Init(SHA1Context *sc); + void SHA1Update(SHA1Context *sc, const void *data, uint32_t len); + void SHA1Final(SHA1Context *sc, uint8_t hash[SHA1_HASH_SIZE]); + +#ifdef __cplusplus +} +#endif +#endif /* _SHA1_H */ diff --git a/backends/libyahoo2/yahoo/yahoo2.h b/backends/libyahoo2/yahoo/yahoo2.h new file mode 100644 index 0000000000000000000000000000000000000000..9a4dc7d2cec9e9636e21286fa5202a054c41d5e4 --- /dev/null +++ b/backends/libyahoo2/yahoo/yahoo2.h @@ -0,0 +1,225 @@ +/* + * libyahoo2: yahoo2.h + * + * Copyright (C) 2002-2004, Philip S Tellis + * + * 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 YAHOO2_H +#define YAHOO2_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "yahoo2_types.h" + +/* returns the socket descriptor object for a given pager connection. shouldn't be needed */ + void *yahoo_get_fd(int id); + +/* says how much logging to do */ +/* see yahoo2_types.h for the different values */ + int yahoo_set_log_level(enum yahoo_log_level level); + enum yahoo_log_level yahoo_get_log_level(void); + +/* these functions should be self explanatory */ +/* who always means the buddy you're acting on */ +/* id is the successful value returned by yahoo_init */ + +/* init returns a connection id used to identify the connection hereon */ +/* or 0 on failure */ +/* you must call init before calling any other function */ +/* + * The optional parameters to init are key/value pairs that specify + * server settings to use. This list must be NULL terminated - even + * if the list is empty. If a parameter isn't set, a default value + * will be used. Parameter keys are strings, parameter values are + * either strings or ints, depending on the key. Values passed in + * are copied, so you can use const/auto/static/pointers/whatever + * you want. Parameters are: + * NAME TYPE DEFAULT + * pager_host char * scs.msg.yahoo.com + * pager_port int 5050 + * filetransfer_host char * filetransfer.msg.yahoo.com + * filetransfer_port int 80 + * webcam_host char * webcam.yahoo.com + * webcam_port int 5100 + * webcam_description char * "" + * local_host char * "" + * conn_type int Y_WCM_DSL + * + * You should set at least local_host if you intend to use webcams + */ + int yahoo_init_with_attributes(const char *username, + const char *password, ...); + +/* yahoo_init does the same as yahoo_init_with_attributes, assuming defaults + * for all attributes */ + int yahoo_init(const char *username, const char *password); + +/* release all resources held by this session */ +/* you need to call yahoo_close for a session only if + * yahoo_logoff is never called for it (ie, it was never logged in) */ + void yahoo_close(int id); +/* login logs in to the server */ +/* initial is of type enum yahoo_status. see yahoo2_types.h */ + void yahoo_login(int id, int initial); + void yahoo_logoff(int id); +/* reloads status of all buddies */ + void yahoo_refresh(int id); +/* activates/deactivates an identity */ + void yahoo_set_identity_status(int id, const char *identity, + int active); +/* regets the entire buddy list from the server */ + void yahoo_get_list(int id); +/* download buddy contact information from your yahoo addressbook */ + void yahoo_get_yab(int id); +/* add/modify an address book entry. if yab->dbid is set, it will */ +/* modify that entry else it creates a new entry */ + void yahoo_set_yab(int id, struct yab *yab); + void yahoo_keepalive(int id); + void yahoo_chat_keepalive(int id); + +/* from is the identity you're sending from. if NULL, the default is used */ +/* 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); +/* 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); + +/* used to set away/back status. */ +/* away says whether the custom message is an away message or a sig */ + void yahoo_set_away(int id, enum yahoo_status state, const char *msg, + int away); + + void yahoo_add_buddy(int id, const char *who, const char *group, + const char *msg); + void yahoo_remove_buddy(int id, const char *who, const char *group); + void yahoo_confirm_buddy(int id, const char *who, int reject, + const char *msg); + void yahoo_stealth_buddy(int id, const char *who, int unstealth); +/* if unignore is true, unignore, else ignore */ + void yahoo_ignore_buddy(int id, const char *who, int unignore); + void yahoo_change_buddy_group(int id, const char *who, + const char *old_group, const char *new_group); + void yahoo_group_rename(int id, const char *old_group, + const char *new_group); + + void yahoo_conference_invite(int id, const char *from, YList *who, + const char *room, const char *msg); + void yahoo_conference_addinvite(int id, const char *from, + const char *who, const char *room, const YList *members, + const char *msg); + void yahoo_conference_decline(int id, const char *from, YList *who, + const char *room, const char *msg); + void yahoo_conference_message(int id, const char *from, YList *who, + const char *room, const char *msg, int utf8); + void yahoo_conference_logon(int id, const char *from, YList *who, + const char *room); + void yahoo_conference_logoff(int id, const char *from, YList *who, + const char *room); + +/* Get a list of chatrooms */ + void yahoo_get_chatrooms(int id, int chatroomid); +/* join room with specified roomname and roomid */ + void yahoo_chat_logon(int id, const char *from, const char *room, + const char *roomid); +/* Send message "msg" to room with specified roomname, msgtype is 1-normal message or 2-/me mesage */ + void yahoo_chat_message(int id, const char *from, const char *room, + const char *msg, const int msgtype, const int utf8); +/* Log off chat */ + void yahoo_chat_logoff(int id, const char *from); + +/* requests a webcam feed */ +/* who is the person who's webcam you would like to view */ +/* if who is null, then you're the broadcaster */ + void yahoo_webcam_get_feed(int id, const char *who); + void yahoo_webcam_close_feed(int id, const char *who); + +/* sends an image when uploading */ +/* image points to a JPEG-2000 image, length is the length of the image */ +/* in bytes. The timestamp is the time in milliseconds since we started the */ +/* webcam. */ + void yahoo_webcam_send_image(int id, unsigned char *image, + unsigned int length, unsigned int timestamp); + +/* this function should be called if we want to allow a user to watch the */ +/* webcam. Who is the user we want to accept. */ +/* Accept user (accept = 1), decline user (accept = 0) */ + void yahoo_webcam_accept_viewer(int id, const char *who, int accept); + +/* send an invitation to a user to view your webcam */ + void yahoo_webcam_invite(int id, const char *who); + +/* will set up a connection and initiate file transfer. + * callback will be called with the fd that you should write + * the file data to + */ + 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); + +/* + * Respond to a file transfer request. Be sure to provide the callback data + * since that is your only chance to recognize future callbacks + */ + void yahoo_send_file_transfer_response(int client_id, int response, + char *id, void *data); + + +/* send a search request + */ + void yahoo_search(int id, enum yahoo_search_type t, const char *text, + enum yahoo_search_gender g, enum yahoo_search_agerange ar, + int photo, int yahoo_only); + +/* continue last search + * should be called if only (start+found >= total) + * + * where the above three are passed to ext_yahoo_got_search_result + */ + void yahoo_search_again(int id, int start); + +/* these should be called when input is available on a fd */ +/* registered by ext_yahoo_add_handler */ +/* if these return negative values, errno may be set */ + int yahoo_read_ready(int id, void *fd, void *data); + int yahoo_write_ready(int id, void *fd, void *data); + +/* utility functions. these do not hit the server */ + enum yahoo_status yahoo_current_status(int id); + const YList *yahoo_get_buddylist(int id); + const YList *yahoo_get_ignorelist(int id); + const YList *yahoo_get_identities(int id); +/* 'which' could be y, t, c or login. This may change in later versions. */ + const char *yahoo_get_cookie(int id, const char *which); + +/* returns the url used to get user profiles - you must append the user id */ +/* as of now this is http://profiles.yahoo.com/ */ +/* You'll have to do urlencoding yourself, but see yahoo_httplib.h first */ + const char *yahoo_get_profile_url(void); + + void yahoo_buddyicon_request(int id, const char *who); + +#include "yahoo_httplib.h" + +#ifdef __cplusplus +} +#endif +#endif diff --git a/backends/libyahoo2/yahoo/yahoo2_callbacks.h b/backends/libyahoo2/yahoo/yahoo2_callbacks.h new file mode 100644 index 0000000000000000000000000000000000000000..ca65b513fa36df9862aa5adba1223b251092d1df --- /dev/null +++ b/backends/libyahoo2/yahoo/yahoo2_callbacks.h @@ -0,0 +1,776 @@ +/* + * libyahoo2: yahoo2_callbacks.h + * + * Copyright (C) 2002-2004, Philip S Tellis + * + * 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 + * + */ + +/* + * The functions in this file *must* be defined in your client program + * If you want to use a callback structure instead of direct functions, + * then you must define USE_STRUCT_CALLBACKS in all files that #include + * this one. + * + * Register the callback structure by calling yahoo_register_callbacks - + * declared in this file and defined in libyahoo2.c + */ + +#ifndef YAHOO2_CALLBACKS_H +#define YAHOO2_CALLBACKS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "yahoo2_types.h" + +/* + * yahoo2_callbacks.h + * + * Callback interface for libyahoo2 + */ + + typedef enum { + YAHOO_INPUT_READ = 1 << 0, + YAHOO_INPUT_WRITE = 1 << 1, + YAHOO_INPUT_EXCEPTION = 1 << 2 + } yahoo_input_condition; + +/* + * A callback function called when an asynchronous connect completes. + * + * Params: + * fd - The file descriptor object that has been connected, or NULL on + * error + * error - The value of errno set by the call to connect or 0 if no error + * Set both fd and error to 0 if the connect was cancelled by the + * user + * callback_data - the callback_data passed to the ext_yahoo_connect_async + * function + */ + typedef void (*yahoo_connect_callback) (void *fd, int error, + void *callback_data); + +/* + * The following functions need to be implemented in the client + * interface. They will be called by the library when each + * event occurs. + */ + +/* + * should we use a callback structure or directly call functions + * if you want the structure, you *must* define USE_STRUCT_CALLBACKS + * both when you compile the library, and when you compile your code + * that uses the library + */ + +#define YAHOO_CALLBACK_TYPE(x) (*x) + struct yahoo_callbacks { + +/* + * Name: ext_yahoo_login_response + * Called when the login process is complete + * Params: + * id - the id that identifies the server connection + * succ - enum yahoo_login_status + * url - url to reactivate account if locked + */ + void YAHOO_CALLBACK_TYPE(ext_yahoo_login_response) (int id, int succ, + const char *url); + +/* + * Name: ext_yahoo_got_buddies + * Called when the contact list is got from the server + * Params: + * id - the id that identifies the server connection + * buds - the buddy list + */ + void YAHOO_CALLBACK_TYPE(ext_yahoo_got_buddies) (int id, YList *buds); + +/* + * Name: ext_yahoo_got_ignore + * Called when the ignore list is got from the server + * Params: + * id - the id that identifies the server connection + * igns - the ignore list + */ + void YAHOO_CALLBACK_TYPE(ext_yahoo_got_ignore) (int id, YList *igns); + +/* + * Name: ext_yahoo_got_identities + * Called when the contact list is got from the server + * Params: + * id - the id that identifies the server connection + * ids - the identity list + */ + void YAHOO_CALLBACK_TYPE(ext_yahoo_got_identities) (int id, YList *ids); + +/* + * Name: ext_yahoo_got_cookies + * Called when the cookie list is got from the server + * Params: + * id - the id that identifies the server connection + */ + void YAHOO_CALLBACK_TYPE(ext_yahoo_got_cookies) (int id); + +/* + * Name: ext_yahoo_got_ping + * Called when the ping packet is received from the server + * Params: + * id - the id that identifies the server connection + * errormsg - optional error message + */ + void YAHOO_CALLBACK_TYPE(ext_yahoo_got_ping) (int id, + const char *errormsg); + +/* + * Name: ext_yahoo_status_changed + * Called when remote user's status changes. + * Params: + * id - the id that identifies the server connection + * who - the handle of the remote user + * stat - status code (enum yahoo_status) + * msg - the message if stat == YAHOO_STATUS_CUSTOM + * away - whether the contact is away or not (YAHOO_STATUS_CUSTOM) + * idle - this is the number of seconds he is idle [if he is idle] + * mobile - this is set for mobile users/buddies + * TODO: add support for pager, chat, and game states + */ + void YAHOO_CALLBACK_TYPE(ext_yahoo_status_changed) (int id, + const char *who, int stat, const char *msg, int away, int idle, + int mobile); + +/* + * Name: ext_yahoo_got_buzz + * Called when remote user sends you a buzz. + * Params: + * id - the id that identifies the server connection + * me - the identity the message was sent to + * who - the handle of the remote user + * tm - timestamp of message if offline + */ + void YAHOO_CALLBACK_TYPE(ext_yahoo_got_buzz) (int id, const char *me, + const char *who, long tm); + +/* + * Name: ext_yahoo_got_im + * Called when remote user sends you a message. + * Params: + * id - the id that identifies the server connection + * me - the identity the message was sent to + * who - the handle of the remote user + * msg - the message - NULL if stat == 2 + * tm - timestamp of message if offline + * stat - message status - 0 + * 1 + * 2 == error sending message + * 5 + * utf8 - whether the message is encoded as utf8 or not + */ + void YAHOO_CALLBACK_TYPE(ext_yahoo_got_im) (int id, const char *me, + const char *who, const char *msg, long tm, int stat, int utf8); + +/* + * Name: ext_yahoo_got_conf_invite + * Called when remote user sends you a conference invitation. + * Params: + * id - the id that identifies the server connection + * me - the identity the invitation was sent to + * who - the user inviting you + * room - the room to join + * msg - the message + * members - the initial members of the conference (null terminated list) + */ + void YAHOO_CALLBACK_TYPE(ext_yahoo_got_conf_invite) (int id, + const char *me, const char *who, const char *room, + const char *msg, YList *members); + +/* + * Name: ext_yahoo_conf_userdecline + * Called when someone declines to join the conference. + * Params: + * id - the id that identifies the server connection + * me - the identity in the conference + * who - the user who has declined + * room - the room + * msg - the declining message + */ + void YAHOO_CALLBACK_TYPE(ext_yahoo_conf_userdecline) (int id, + const char *me, const char *who, const char *room, + const char *msg); + +/* + * Name: ext_yahoo_conf_userjoin + * Called when someone joins the conference. + * Params: + * id - the id that identifies the server connection + * me - the identity in the conference + * who - the user who has joined + * room - the room joined + */ + void YAHOO_CALLBACK_TYPE(ext_yahoo_conf_userjoin) (int id, + const char *me, const char *who, const char *room); + +/* + * Name: ext_yahoo_conf_userleave + * Called when someone leaves the conference. + * Params: + * id - the id that identifies the server connection + * me - the identity in the conference + * who - the user who has left + * room - the room left + */ + void YAHOO_CALLBACK_TYPE(ext_yahoo_conf_userleave) (int id, + const char *me, const char *who, const char *room); + +/* + * Name: ext_yahoo_chat_cat_xml + * Called when ? + * Params: + * id - the id that identifies the server connection + * xml - ? + */ + void YAHOO_CALLBACK_TYPE(ext_yahoo_chat_cat_xml) (int id, + const char *xml); + +/* + * Name: ext_yahoo_chat_join + * Called when joining the chatroom. + * Params: + * id - the id that identifies the server connection + * me - the identity in the chatroom + * room - the room joined, used in all other chat calls, freed by + * library after call + * topic - the topic of the room, freed by library after call + * members - the initial members of the chatroom (null terminated YList + * of yahoo_chat_member's) Must be freed by the client + * fd - the object where the connection is coming from (for tracking) + */ + void YAHOO_CALLBACK_TYPE(ext_yahoo_chat_join) (int id, const char *me, + const char *room, const char *topic, YList *members, void *fd); + +/* + * Name: ext_yahoo_chat_userjoin + * Called when someone joins the chatroom. + * Params: + * id - the id that identifies the server connection + * me - the identity in the chatroom + * room - the room joined + * who - the user who has joined, Must be freed by the client + */ + void YAHOO_CALLBACK_TYPE(ext_yahoo_chat_userjoin) (int id, + const char *me, const char *room, + struct yahoo_chat_member *who); + +/* + * Name: ext_yahoo_chat_userleave + * Called when someone leaves the chatroom. + * Params: + * id - the id that identifies the server connection + * me - the identity in the chatroom + * room - the room left + * who - the user who has left (Just the User ID) + */ + void YAHOO_CALLBACK_TYPE(ext_yahoo_chat_userleave) (int id, + const char *me, const char *room, const char *who); + +/* + * Name: ext_yahoo_chat_message + * Called when someone messages in the chatroom. + * Params: + * id - the id that identifies the server connection + * me - the identity in the chatroom + * room - the room + * who - the user who messaged (Just the user id) + * msg - the message + * msgtype - 1 = Normal message + * 2 = /me type message + * utf8 - whether the message is utf8 encoded or not + */ + void YAHOO_CALLBACK_TYPE(ext_yahoo_chat_message) (int id, + const char *me, const char *who, const char *room, + const char *msg, int msgtype, int utf8); + +/* + * + * Name: ext_yahoo_chat_yahoologout + * called when yahoo disconnects your chat session + * Note this is called whenver a disconnect happens, client or server + * requested. Care should be taken to make sure you know the origin + * of the disconnect request before doing anything here (auto-join's etc) + * Params: + * id - the id that identifies this connection + * me - the identity in the chatroom + * Returns: + * nothing. + */ + void YAHOO_CALLBACK_TYPE(ext_yahoo_chat_yahoologout) (int id, + const char *me); + +/* + * + * Name: ext_yahoo_chat_yahooerror + * called when yahoo sends back an error to you + * Note this is called whenver chat message is sent into a room + * in error (fd not connected, room doesn't exists etc) + * Care should be taken to make sure you know the origin + * of the error before doing anything about it. + * Params: + * id - the id that identifies this connection + * me - the identity in the chatroom + * Returns: + * nothing. + */ + void YAHOO_CALLBACK_TYPE(ext_yahoo_chat_yahooerror) (int id, + const char *me); + +/* + * Name: ext_yahoo_conf_message + * Called when someone messages in the conference. + * Params: + * id - the id that identifies the server connection + * me - the identity the conf message was sent to + * who - the user who messaged + * room - the room + * msg - the message + * utf8 - whether the message is utf8 encoded or not + */ + void YAHOO_CALLBACK_TYPE(ext_yahoo_conf_message) (int id, + const char *me, const char *who, const char *room, + const char *msg, int utf8); + +/* + * Name: ext_yahoo_got_file + * Called when someone sends you a file + * Params: + * id - the id that identifies the server connection + * me - the identity the file was sent to + * who - the user who sent the file + * msg - the message + * fname- the file name if direct transfer + * fsize- the file size if direct transfer + * trid - transfer id. Unique for this transfer + * + * NOTE: Subsequent callbacks for file transfer do not send all of this + * information again since it is wasteful. Implementations are expected to + * save this information and supply it as callback data when the file or + * confirmation is sent + */ + void YAHOO_CALLBACK_TYPE(ext_yahoo_got_file) (int id, const char *me, + const char *who, const char *msg, const char *fname, + unsigned long fesize, char *trid); + +/* + * Name: ext_yahoo_got_ft_data + * Called multiple times when parts of the file are received + * Params: + * id - the id that identifies the server connection + * in - The data + * len - Length of the data + * data - callback data + */ + void YAHOO_CALLBACK_TYPE(ext_yahoo_got_ft_data) (int id, + const unsigned char *in, int len, void *data); + +/* + * Name: ext_yahoo_file_transfer_done + * File transfer is done + * Params: + * id - the id that identifies the server connection + * result - To notify if it finished successfully or with a failure + * data - callback data + */ + void YAHOO_CALLBACK_TYPE(ext_yahoo_file_transfer_done) (int id, + int result, void *data); + +/* + * Name: ext_yahoo_contact_added + * Called when a contact is added to your list + * Params: + * id - the id that identifies the server connection + * myid - the identity he was added to + * who - who was added + * msg - any message sent + */ + void YAHOO_CALLBACK_TYPE(ext_yahoo_contact_added) (int id, + const char *myid, const char *who, const char *msg); + +/* + * Name: ext_yahoo_rejected + * Called when a contact rejects your add + * Params: + * id - the id that identifies the server connection + * who - who rejected you + * msg - any message sent + */ + void YAHOO_CALLBACK_TYPE(ext_yahoo_rejected) (int id, const char *who, + const char *msg); + +/* + * Name: ext_yahoo_typing_notify + * Called when remote user starts or stops typing. + * Params: + * id - the id that identifies the server connection + * me - the handle of the identity the notification is sent to + * who - the handle of the remote user + * stat - 1 if typing, 0 if stopped typing + */ + void YAHOO_CALLBACK_TYPE(ext_yahoo_typing_notify) (int id, + const char *me, const char *who, int stat); + +/* + * Name: ext_yahoo_game_notify + * Called when remote user starts or stops a game. + * Params: + * id - the id that identifies the server connection + * me - the handle of the identity the notification is sent to + * who - the handle of the remote user + * stat - 1 if game, 0 if stopped gaming + * msg - game description and/or other text + */ + void YAHOO_CALLBACK_TYPE(ext_yahoo_game_notify) (int id, const char *me, + const char *who, int stat, const char *msg); + +/* + * Name: ext_yahoo_mail_notify + * Called when you receive mail, or with number of messages + * Params: + * id - the id that identifies the server connection + * from - who the mail is from - NULL if only mail count + * subj - the subject of the mail - NULL if only mail count + * cnt - mail count - 0 if new mail notification + */ + void YAHOO_CALLBACK_TYPE(ext_yahoo_mail_notify) (int id, + const char *from, const char *subj, int cnt); + +/* + * Name: ext_yahoo_system_message + * System message + * Params: + * id - the id that identifies the server connection + * me - the handle of the identity the notification is sent to + * who - the source of the system message (there are different types) + * msg - the message + */ + void YAHOO_CALLBACK_TYPE(ext_yahoo_system_message) (int id, + const char *me, const char *who, const char *msg); + +/* + * Name: ext_yahoo_got_buddyicon + * Buddy icon received + * Params: + * id - the id that identifies the server connection + * me - the handle of the identity the notification is sent to + * who - the person the buddy icon is for + * url - the url to use to load the icon + * checksum - the checksum of the icon content + */ + void YAHOO_CALLBACK_TYPE(ext_yahoo_got_buddyicon) (int id, + const char *me, const char *who, const char *url, int checksum); + +/* + * Name: ext_yahoo_got_buddyicon_checksum + * Buddy icon checksum received + * Params: + * id - the id that identifies the server connection + * me - the handle of the identity the notification is sent to + * who - the yahoo id of the buddy icon checksum is for + * checksum - the checksum of the icon content + */ + void YAHOO_CALLBACK_TYPE(ext_yahoo_got_buddyicon_checksum) (int id, + const char *me, const char *who, int checksum); + +/* + * Name: ext_yahoo_got_buddyicon_request + * Buddy icon request received + * Params: + * id - the id that identifies the server connection + * me - the handle of the identity the notification is sent to + * who - the yahoo id of the buddy that requested the buddy icon + */ + void YAHOO_CALLBACK_TYPE(ext_yahoo_got_buddyicon_request) (int id, + const char *me, const char *who); + +/* + * Name: ext_yahoo_got_buddyicon_request + * Buddy icon request received + * Params: + * id - the id that identifies the server connection + * url - remote url, the uploaded buddy icon can be fetched from + */ + void YAHOO_CALLBACK_TYPE(ext_yahoo_buddyicon_uploaded) (int id, + const char *url); + +/* + * Name: ext_yahoo_got_webcam_image + * Called when you get a webcam update + * An update can either be receiving an image, a part of an image or + * just an update with a timestamp + * Params: + * id - the id that identifies the server connection + * who - the user who's webcam we're viewing + * image - image data + * image_size - length of the image in bytes + * real_size - actual length of image data + * timestamp - milliseconds since the webcam started + * + * If the real_size is smaller then the image_size then only part of + * the image has been read. This function will keep being called till + * the total amount of bytes in image_size has been read. The image + * received is in JPEG-2000 Code Stream Syntax (ISO/IEC 15444-1). + * The size of the image will be either 160x120 or 320x240. + * Each webcam image contains a timestamp. This timestamp should be + * used to keep the image in sync since some images can take longer + * to transport then others. When image_size is 0 we can still receive + * a timestamp to stay in sync + */ + void YAHOO_CALLBACK_TYPE(ext_yahoo_got_webcam_image) (int id, + const char *who, const unsigned char *image, + unsigned int image_size, unsigned int real_size, + unsigned int timestamp); + +/* + * Name: ext_yahoo_webcam_invite + * Called when you get a webcam invitation + * Params: + * id - the id that identifies the server connection + * me - identity the invitation is to + * from - who the invitation is from + */ + void YAHOO_CALLBACK_TYPE(ext_yahoo_webcam_invite) (int id, + const char *me, const char *from); + +/* + * Name: ext_yahoo_webcam_invite_reply + * Called when you get a response to a webcam invitation + * Params: + * id - the id that identifies the server connection + * me - identity the invitation response is to + * from - who the invitation response is from + * accept - 0 (decline), 1 (accept) + */ + void YAHOO_CALLBACK_TYPE(ext_yahoo_webcam_invite_reply) (int id, + const char *me, const char *from, int accept); + +/* + * Name: ext_yahoo_webcam_closed + * Called when the webcam connection closed + * Params: + * id - the id that identifies the server connection + * who - the user who we where connected to + * reason - reason why the connection closed + * 1 = user stopped broadcasting + * 2 = user cancelled viewing permission + * 3 = user declines permission + * 4 = user does not have webcam online + */ + void YAHOO_CALLBACK_TYPE(ext_yahoo_webcam_closed) (int id, + const char *who, int reason); + +/* + * Name: ext_yahoo_got_search_result + * Called when the search result received from server + * Params: + * id - the id that identifies the server connection + * found - total number of results returned in the current result set + * start - offset from where the current result set starts + * total - total number of results available (start + found <= total) + * contacts - the list of results as a YList of yahoo_found_contact + * these will be freed after this function returns, so + * if you need to use the information, make a copy + */ + void YAHOO_CALLBACK_TYPE(ext_yahoo_got_search_result) (int id, + int found, int start, int total, YList *contacts); + +/* + * Name: ext_yahoo_error + * Called on error. + * Params: + * id - the id that identifies the server connection + * err - the error message + * fatal- whether this error is fatal to the connection or not + * num - Which error is this + */ + void YAHOO_CALLBACK_TYPE(ext_yahoo_error) (int id, const char *err, + int fatal, int num); + +/* + * Name: ext_yahoo_webcam_viewer + * Called when a viewer disconnects/connects/requests to connect + * Params: + * id - the id that identifies the server connection + * who - the viewer + * connect - 0=disconnect 1=connect 2=request + */ + void YAHOO_CALLBACK_TYPE(ext_yahoo_webcam_viewer) (int id, + const char *who, int connect); + +/* + * Name: ext_yahoo_webcam_data_request + * Called when you get a request for webcam images + * Params: + * id - the id that identifies the server connection + * send - whether to send images or not + */ + void YAHOO_CALLBACK_TYPE(ext_yahoo_webcam_data_request) (int id, + int send); + +/* + * Name: ext_yahoo_log + * Called to log a message. + * Params: + * fmt - the printf formatted message + * Returns: + * 0 + */ + int YAHOO_CALLBACK_TYPE(ext_yahoo_log) (const char *fmt, ...); + +/* + * Name: ext_yahoo_add_handler + * Add a listener for the fd. Must call yahoo_read_ready + * when a YAHOO_INPUT_READ fd is ready and yahoo_write_ready + * when a YAHOO_INPUT_WRITE fd is ready. + * Params: + * id - the id that identifies the server connection + * fd - the fd object on which to listen + * cond - the condition on which to call the callback + * data - callback data to pass to yahoo_*_ready + * + * Returns: a tag to be used when removing the handler + */ + int YAHOO_CALLBACK_TYPE(ext_yahoo_add_handler) (int id, void *fd, + yahoo_input_condition cond, void *data); + +/* + * Name: ext_yahoo_remove_handler + * Remove the listener for the fd. + * Params: + * id - the id that identifies the connection + * tag - the handler tag to remove + */ + void YAHOO_CALLBACK_TYPE(ext_yahoo_remove_handler) (int id, int tag); + +/* + * Name: ext_yahoo_connect + * Connect to a host:port + * Params: + * host - the host to connect to + * port - the port to connect on + * Returns: + * a unix file descriptor to the socket + */ + int YAHOO_CALLBACK_TYPE(ext_yahoo_connect) (const char *host, int port); + +/* + * Name: ext_yahoo_connect_async + * Connect to a host:port asynchronously. This function should return + * immediately returing a tag used to identify the connection handler, + * or a pre-connect error (eg: host name lookup failure). + * Once the connect completes (successfully or unsuccessfully), callback + * should be called (see the signature for yahoo_connect_callback). + * The callback may safely be called before this function returns, but + * it should not be called twice. + * Params: + * id - the id that identifies this connection + * host - the host to connect to + * port - the port to connect on + * callback - function to call when connect completes + * callback_data - data to pass to the callback function + * use_ssl - Whether we need an SSL connection + * Returns: + * a tag signifying the connection attempt + */ + int YAHOO_CALLBACK_TYPE(ext_yahoo_connect_async) (int id, + const char *host, int port, yahoo_connect_callback callback, + void *callback_data, int use_ssl); + +/* + * Name: ext_yahoo_get_ip_addr + * get IP Address for a domain name + * Params: + * domain - Domain name + * Returns: + * Newly allocated string containing the IP Address in IPv4 notation + */ + char *YAHOO_CALLBACK_TYPE(ext_yahoo_get_ip_addr) (const char *domain); + +/* + * Name: ext_yahoo_write + * Write data from the buffer into the socket for the specified connection + * Params: + * fd - the file descriptor object that identifies this connection + * buf - Buffer to write the data from + * len - Length of the data + * Returns: + * Number of bytes written or -1 for error + */ + int YAHOO_CALLBACK_TYPE(ext_yahoo_write) (void *fd, char *buf, int len); + +/* + * Name: ext_yahoo_read + * Read data into a buffer from socket for the specified connection + * Params: + * fd - the file descriptor object that identifies this connection + * buf - Buffer to read the data into + * len - Max length to read + * Returns: + * Number of bytes read or -1 for error + */ + int YAHOO_CALLBACK_TYPE(ext_yahoo_read) (void *fd, char *buf, int len); + +/* + * Name: ext_yahoo_close + * Close the file descriptor object and free its resources. Libyahoo2 will not + * use this object again. + * Params: + * fd - the file descriptor object that identifies this connection + * Returns: + * Nothing + */ + void YAHOO_CALLBACK_TYPE(ext_yahoo_close) (void *fd); + +/* + * Name: ext_yahoo_got_buddy_change_group + * Acknowledgement of buddy changing group + * Params: + * id: client id + * me: The user + * who: Buddy name + * old_group: Old group name + * new_group: New group name + * Returns: + * Nothing + */ + void YAHOO_CALLBACK_TYPE(ext_yahoo_got_buddy_change_group) (int id, + const char *me, const char *who, const char *old_group, + const char *new_group); + +}; + +/* + * if using a callback structure, call yahoo_register_callbacks + * before doing anything else + */ +void yahoo_register_callbacks(struct yahoo_callbacks *tyc); + +#undef YAHOO_CALLBACK_TYPE + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/backends/libyahoo2/yahoo/yahoo2_types.h b/backends/libyahoo2/yahoo/yahoo2_types.h new file mode 100644 index 0000000000000000000000000000000000000000..bbade5d8730312242ed3487afd42ed7722b17a3b --- /dev/null +++ b/backends/libyahoo2/yahoo/yahoo2_types.h @@ -0,0 +1,396 @@ +/* + * libyahoo2: yahoo2_types.h + * + * Copyright (C) 2002-2004, Philip S Tellis + * + * 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 YAHOO2_TYPES_H +#define YAHOO2_TYPES_H + +#include "yahoo_list.h" + +#ifdef __cplusplus +extern "C" { +#endif + + enum yahoo_service { /* these are easier to see in hex */ + YAHOO_SERVICE_LOGON = 1, + YAHOO_SERVICE_LOGOFF, + YAHOO_SERVICE_ISAWAY, + YAHOO_SERVICE_ISBACK, + YAHOO_SERVICE_IDLE, /* 5 (placemarker) */ + YAHOO_SERVICE_MESSAGE, + YAHOO_SERVICE_IDACT, + YAHOO_SERVICE_IDDEACT, + YAHOO_SERVICE_MAILSTAT, + YAHOO_SERVICE_USERSTAT, /* 0xa */ + YAHOO_SERVICE_NEWMAIL, + YAHOO_SERVICE_CHATINVITE, + YAHOO_SERVICE_CALENDAR, + YAHOO_SERVICE_NEWPERSONALMAIL, + YAHOO_SERVICE_NEWCONTACT, + YAHOO_SERVICE_ADDIDENT, /* 0x10 */ + YAHOO_SERVICE_ADDIGNORE, + YAHOO_SERVICE_PING, + YAHOO_SERVICE_GOTGROUPRENAME, /* < 1, 36(old), 37(new) */ + YAHOO_SERVICE_SYSMESSAGE = 0x14, + YAHOO_SERVICE_SKINNAME = 0x15, + YAHOO_SERVICE_PASSTHROUGH2 = 0x16, + YAHOO_SERVICE_CONFINVITE = 0x18, + YAHOO_SERVICE_CONFLOGON, + YAHOO_SERVICE_CONFDECLINE, + YAHOO_SERVICE_CONFLOGOFF, + YAHOO_SERVICE_CONFADDINVITE, + YAHOO_SERVICE_CONFMSG, + YAHOO_SERVICE_CHATLOGON, + YAHOO_SERVICE_CHATLOGOFF, + YAHOO_SERVICE_CHATMSG = 0x20, + YAHOO_SERVICE_GAMELOGON = 0x28, + YAHOO_SERVICE_GAMELOGOFF, + YAHOO_SERVICE_GAMEMSG = 0x2a, + YAHOO_SERVICE_FILETRANSFER = 0x46, + YAHOO_SERVICE_VOICECHAT = 0x4A, + YAHOO_SERVICE_NOTIFY, + YAHOO_SERVICE_VERIFY, + YAHOO_SERVICE_P2PFILEXFER, + YAHOO_SERVICE_PEERTOPEER = 0x4F, /* Checks if P2P possible */ + YAHOO_SERVICE_WEBCAM, + YAHOO_SERVICE_AUTHRESP = 0x54, + YAHOO_SERVICE_LIST, + YAHOO_SERVICE_AUTH = 0x57, + YAHOO_SERVICE_AUTHBUDDY = 0x6d, + YAHOO_SERVICE_ADDBUDDY = 0x83, + YAHOO_SERVICE_REMBUDDY, + YAHOO_SERVICE_IGNORECONTACT, /* > 1, 7, 13 < 1, 66, 13, 0 */ + YAHOO_SERVICE_REJECTCONTACT, + YAHOO_SERVICE_GROUPRENAME = 0x89, /* > 1, 65(new), 66(0), 67(old) */ + YAHOO_SERVICE_Y7_PING = 0x8A, + YAHOO_SERVICE_CHATONLINE = 0x96, /* > 109(id), 1, 6(abcde) < 0,1 */ + YAHOO_SERVICE_CHATGOTO, + YAHOO_SERVICE_CHATJOIN, /* > 1 104-room 129-1600326591 62-2 */ + YAHOO_SERVICE_CHATLEAVE, + YAHOO_SERVICE_CHATEXIT = 0x9b, + YAHOO_SERVICE_CHATADDINVITE = 0x9d, + YAHOO_SERVICE_CHATLOGOUT = 0xa0, + YAHOO_SERVICE_CHATPING, + YAHOO_SERVICE_COMMENT = 0xa8, + YAHOO_SERVICE_GAME_INVITE = 0xb7, + YAHOO_SERVICE_STEALTH_PERM = 0xb9, + YAHOO_SERVICE_STEALTH_SESSION = 0xba, + YAHOO_SERVICE_AVATAR = 0xbc, + YAHOO_SERVICE_PICTURE_CHECKSUM = 0xbd, + YAHOO_SERVICE_PICTURE = 0xbe, + YAHOO_SERVICE_PICTURE_UPDATE = 0xc1, + YAHOO_SERVICE_PICTURE_UPLOAD = 0xc2, + YAHOO_SERVICE_YAB_UPDATE = 0xc4, + YAHOO_SERVICE_Y6_VISIBLE_TOGGLE = 0xc5, /* YMSG13, key 13: 2 = invisible, 1 = visible */ + YAHOO_SERVICE_Y6_STATUS_UPDATE = 0xc6, /* YMSG13 */ + YAHOO_SERVICE_PICTURE_STATUS = 0xc7, /* YMSG13, key 213: 0 = none, 1 = avatar, 2 = picture */ + YAHOO_SERVICE_VERIFY_ID_EXISTS = 0xc8, + YAHOO_SERVICE_AUDIBLE = 0xd0, + YAHOO_SERVICE_Y7_PHOTO_SHARING = 0xd2, + YAHOO_SERVICE_Y7_CONTACT_DETAILS = 0xd3, /* YMSG13 */ + YAHOO_SERVICE_Y7_CHAT_SESSION = 0xd4, + YAHOO_SERVICE_Y7_AUTHORIZATION = 0xd6, /* YMSG13 */ + YAHOO_SERVICE_Y7_FILETRANSFER = 0xdc, /* YMSG13 */ + YAHOO_SERVICE_Y7_FILETRANSFERINFO, /* YMSG13 */ + YAHOO_SERVICE_Y7_FILETRANSFERACCEPT, /* YMSG13 */ + YAHOO_SERVICE_Y7_MINGLE = 0xe1, /* YMSG13 */ + YAHOO_SERVICE_Y7_CHANGE_GROUP = 0xe7, /* YMSG13 */ + YAHOO_SERVICE_MYSTERY = 0xef, /* Don't know what this is for */ + YAHOO_SERVICE_Y8_STATUS = 0xf0, /* YMSG15 */ + YAHOO_SERVICE_Y8_LIST = 0Xf1, /* YMSG15 */ + YAHOO_SERVICE_MESSAGE_CONFIRM = 0xfb, + YAHOO_SERVICE_WEBLOGIN = 0x0226, + YAHOO_SERVICE_SMS_MSG = 0x02ea + }; + + enum yahoo_status { + YAHOO_STATUS_AVAILABLE = 0, + YAHOO_STATUS_BRB, + YAHOO_STATUS_BUSY, + YAHOO_STATUS_NOTATHOME, + YAHOO_STATUS_NOTATDESK, + YAHOO_STATUS_NOTINOFFICE, + YAHOO_STATUS_ONPHONE, + YAHOO_STATUS_ONVACATION, + YAHOO_STATUS_OUTTOLUNCH, + YAHOO_STATUS_STEPPEDOUT, + YAHOO_STATUS_INVISIBLE = 12, + YAHOO_STATUS_CUSTOM = 99, + YAHOO_STATUS_IDLE = 999, + YAHOO_STATUS_OFFLINE = 0x5a55aa56 /* don't ask */ + }; + + enum ypacket_status { + YPACKET_STATUS_DISCONNECTED = -1, + YPACKET_STATUS_DEFAULT = 0, + YPACKET_STATUS_SERVERACK = 1, + YPACKET_STATUS_GAME = 0x2, + YPACKET_STATUS_AWAY = 0x4, + YPACKET_STATUS_CONTINUED = 0x5, + YPACKET_STATUS_INVISIBLE = 12, + YPACKET_STATUS_NOTIFY = 0x16, /* TYPING */ + YPACKET_STATUS_WEBLOGIN = 0x5a55aa55, + YPACKET_STATUS_OFFLINE = 0x5a55aa56 + }; + +#define YAHOO_STATUS_GAME 0x2 /* Games don't fit into the regular status model */ + + enum yahoo_login_status { + YAHOO_LOGIN_OK = 0, + YAHOO_LOGIN_LOGOFF = 1, + YAHOO_LOGIN_UNAME = 3, + YAHOO_LOGIN_PASSWD = 13, + YAHOO_LOGIN_LOCK = 14, + YAHOO_LOGIN_DUPL = 99, + YAHOO_LOGIN_SOCK = -1, + YAHOO_LOGIN_UNKNOWN = 999 + }; + + enum yahoo_error { + E_UNKNOWN = -1, + E_CONNECTION = -2, + E_SYSTEM = -3, + E_CUSTOM = 0, + + /* responses from ignore buddy */ + E_IGNOREDUP = 2, + E_IGNORENONE = 3, + E_IGNORECONF = 12, + + /* conference */ + E_CONFNOTAVAIL = 20 + }; + + enum yahoo_log_level { + YAHOO_LOG_NONE = 0, + YAHOO_LOG_FATAL, + YAHOO_LOG_ERR, + YAHOO_LOG_WARNING, + YAHOO_LOG_NOTICE, + YAHOO_LOG_INFO, + YAHOO_LOG_DEBUG + }; + + enum yahoo_file_transfer { + YAHOO_FILE_TRANSFER_INIT = 1, + YAHOO_FILE_TRANSFER_ACCEPT = 3, + YAHOO_FILE_TRANSFER_REJECT = 4, + YAHOO_FILE_TRANSFER_DONE = 5, + YAHOO_FILE_TRANSFER_RELAY, + YAHOO_FILE_TRANSFER_FAILED, + YAHOO_FILE_TRANSFER_UNKNOWN + }; + +#define YAHOO_PROTO_VER 0x0010 + +/* Yahoo style/color directives */ +#define YAHOO_COLOR_BLACK "\033[30m" +#define YAHOO_COLOR_BLUE "\033[31m" +#define YAHOO_COLOR_LIGHTBLUE "\033[32m" +#define YAHOO_COLOR_GRAY "\033[33m" +#define YAHOO_COLOR_GREEN "\033[34m" +#define YAHOO_COLOR_PINK "\033[35m" +#define YAHOO_COLOR_PURPLE "\033[36m" +#define YAHOO_COLOR_ORANGE "\033[37m" +#define YAHOO_COLOR_RED "\033[38m" +#define YAHOO_COLOR_OLIVE "\033[39m" +#define YAHOO_COLOR_ANY "\033[#" +#define YAHOO_STYLE_ITALICON "\033[2m" +#define YAHOO_STYLE_ITALICOFF "\033[x2m" +#define YAHOO_STYLE_BOLDON "\033[1m" +#define YAHOO_STYLE_BOLDOFF "\033[x1m" +#define YAHOO_STYLE_UNDERLINEON "\033[4m" +#define YAHOO_STYLE_UNDERLINEOFF "\033[x4m" +#define YAHOO_STYLE_URLON "\033[lm" +#define YAHOO_STYLE_URLOFF "\033[xlm" + + enum yahoo_connection_type { + YAHOO_CONNECTION_PAGER = 0, + YAHOO_CONNECTION_FT, + YAHOO_CONNECTION_YAB, + YAHOO_CONNECTION_WEBCAM_MASTER, + YAHOO_CONNECTION_WEBCAM, + YAHOO_CONNECTION_CHATCAT, + YAHOO_CONNECTION_SEARCH, + YAHOO_CONNECTION_AUTH + }; + + enum yahoo_webcam_direction_type { + YAHOO_WEBCAM_DOWNLOAD = 0, + YAHOO_WEBCAM_UPLOAD + }; + + enum yahoo_stealth_visibility_type { + YAHOO_STEALTH_DEFAULT = 0, + YAHOO_STEALTH_ONLINE, + YAHOO_STEALTH_PERM_OFFLINE + }; + +/* chat member attribs */ +#define YAHOO_CHAT_MALE 0x8000 +#define YAHOO_CHAT_FEMALE 0x10000 +#define YAHOO_CHAT_FEMALE 0x10000 +#define YAHOO_CHAT_DUNNO 0x400 +#define YAHOO_CHAT_WEBCAM 0x10 + + enum yahoo_webcam_conn_type { Y_WCM_DIALUP, Y_WCM_DSL, Y_WCM_T1 }; + + struct yahoo_webcam { + int direction; /* Uploading or downloading */ + int conn_type; /* 0=Dialup, 1=DSL/Cable, 2=T1/Lan */ + + char *user; /* user we are viewing */ + char *server; /* webcam server to connect to */ + int port; /* webcam port to connect on */ + char *key; /* key to connect to the server with */ + char *description; /* webcam description */ + char *my_ip; /* own ip number */ + }; + + struct yahoo_webcam_data { + unsigned int data_size; + unsigned int to_read; + unsigned int timestamp; + unsigned char packet_type; + }; + + struct yahoo_data { + char *user; + char *password; + + char *cookie_y; + char *cookie_t; + char *cookie_c; + char *cookie_b; + char *login_cookie; + char *crumb; + char *seed; + + YList *buddies; + YList *ignore; + YList *identities; + char *login_id; + + int current_status; + int initial_status; + int logged_in; + + int session_id; + + int client_id; + + char *rawbuddylist; + char *ignorelist; + + void *server_settings; + + struct yahoo_process_status_entry *half_user; + }; + + struct yab { + int yid; + char *id; + char *fname; + char *lname; + char *nname; + char *email; + char *hphone; + char *wphone; + char *mphone; + int dbid; + }; + + struct yahoo_buddy { + char *group; + char *id; + char *real_name; + struct yab *yab_entry; + }; + + enum yahoo_search_type { + YAHOO_SEARCH_KEYWORD = 0, + YAHOO_SEARCH_YID, + YAHOO_SEARCH_NAME + }; + + enum yahoo_search_gender { + YAHOO_GENDER_NONE = 0, + YAHOO_GENDER_MALE, + YAHOO_GENDER_FEMALE + }; + + enum yahoo_search_agerange { + YAHOO_AGERANGE_NONE = 0 + }; + + struct yahoo_found_contact { + char *id; + char *gender; + char *location; + int age; + int online; + }; + +/* + * Function pointer to be passed to http get/post and send file + */ + typedef void (*yahoo_get_fd_callback) (int id, void *fd, int error, + void *data); + +/* + * Function pointer to be passed to yahoo_get_url_handle + */ + typedef void (*yahoo_get_url_handle_callback) (int id, void *fd, + int error, const char *filename, unsigned long size, + void *data); + + struct yahoo_chat_member { + char *id; + int age; + int attribs; + char *alias; + char *location; + }; + + struct yahoo_process_status_entry { + char *name; /* 7 name */ + int state; /* 10 state */ + int flags; /* 13 flags, bit 0 = pager, bit 1 = chat, bit 2 = game */ + int mobile; /* 60 mobile */ + char *msg; /* 19 custom status message */ + int away; /* 47 away (or invisible) */ + int buddy_session; /* 11 state */ + int f17; /* 17 in chat? then what about flags? */ + int idle; /* 137 seconds idle */ + int f138; /* 138 state */ + char *f184; /* 184 state */ + int f192; /* 192 state */ + int f10001; /* 10001 state */ + int f10002; /* 10002 state */ + int f198; /* 198 state */ + char *f197; /* 197 state */ + char *f205; /* 205 state */ + int f213; /* 213 state */ + }; + +#ifdef __cplusplus +} +#endif +#endif diff --git a/backends/libyahoo2/yahoo/yahoo_debug.h b/backends/libyahoo2/yahoo/yahoo_debug.h new file mode 100644 index 0000000000000000000000000000000000000000..8b8dd6e85bd4ee197e938a738cc38837347a8890 --- /dev/null +++ b/backends/libyahoo2/yahoo/yahoo_debug.h @@ -0,0 +1,36 @@ +/* + * libyahoo2: yahoo_debug.h + * + * Copyright (C) 2002-2004, Philip S Tellis + * + * 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 + * + */ + +extern int yahoo_log_message(char *fmt, ...); + +#define NOTICE(x) if(yahoo_get_log_level() >= YAHOO_LOG_NOTICE) { yahoo_log_message x; yahoo_log_message("\n"); } + +#define LOG(x) if(yahoo_get_log_level() >= YAHOO_LOG_INFO) { yahoo_log_message("%s:%d: ", __FILE__, __LINE__); \ + yahoo_log_message x; \ + yahoo_log_message("\n"); } + +#define WARNING(x) if(yahoo_get_log_level() >= YAHOO_LOG_WARNING) { yahoo_log_message("%s:%d: warning: ", __FILE__, __LINE__); \ + yahoo_log_message x; \ + yahoo_log_message("\n"); } + +#define DEBUG_MSG(x) if(yahoo_get_log_level() >= YAHOO_LOG_DEBUG) { yahoo_log_message("%s:%d: debug: ", __FILE__, __LINE__); \ + yahoo_log_message x; \ + yahoo_log_message("\n"); } diff --git a/backends/libyahoo2/yahoo/yahoo_fn.c b/backends/libyahoo2/yahoo/yahoo_fn.c new file mode 100644 index 0000000000000000000000000000000000000000..dcbeb47c4c022a217827568ce479c57a5f71dc18 --- /dev/null +++ b/backends/libyahoo2/yahoo/yahoo_fn.c @@ -0,0 +1,4810 @@ +/* + * libyahoo2 - originally from gaim patches by Amatus + * + * Copyright (C) 2003-2004 + * + * Some code copyright (C) 1998-1999, Mark Spencer + * libfaim code copyright 1998, 1999 Adam Fritzler + * + * 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" + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +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) +{ + 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/backends/libyahoo2/yahoo/yahoo_fn.h b/backends/libyahoo2/yahoo/yahoo_fn.h new file mode 100644 index 0000000000000000000000000000000000000000..5400e5d0cf90e74b92c04fce6fb79fecdd4abe02 --- /dev/null +++ b/backends/libyahoo2/yahoo/yahoo_fn.h @@ -0,0 +1,32 @@ +/* + * 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/backends/libyahoo2/yahoo/yahoo_httplib.c b/backends/libyahoo2/yahoo/yahoo_httplib.c new file mode 100644 index 0000000000000000000000000000000000000000..60f1f984afaaf1ed294dabf73d5999332ea8b7b4 --- /dev/null +++ b/backends/libyahoo2/yahoo/yahoo_httplib.c @@ -0,0 +1,404 @@ +/* + * libyahoo2: yahoo_httplib.c + * + * Copyright (C) 2002-2004, Philip S Tellis + * + * 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 + * + */ + +#if HAVE_CONFIG_H +# include +#endif + +#include +#include + +#if STDC_HEADERS +# include +#else +# if !HAVE_STRCHR +# define strchr index +# define strrchr rindex +# endif +char *strchr(), *strrchr(); +# if !HAVE_MEMCPY +# define memcpy(d, s, n) bcopy ((s), (d), (n)) +# define memmove(d, s, n) bcopy ((s), (d), (n)) +# endif +#endif + +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include "yahoo2.h" +#include "yahoo2_callbacks.h" +#include "yahoo_httplib.h" +#include "yahoo_util.h" + +#include "yahoo_debug.h" +#ifdef __MINGW32__ +# include +# define snprintf _snprintf +#endif + +extern struct yahoo_callbacks *yc; +#define YAHOO_CALLBACK(x) yc->x + +extern enum yahoo_log_level log_level; + +int yahoo_tcp_readline(char *ptr, int maxlen, void *fd) +{ + int n, rc; + char c; + + for (n = 1; n < maxlen; n++) { + + do { + rc = YAHOO_CALLBACK(ext_yahoo_read) (fd, &c, 1); + } while (rc == -1 && (errno == EINTR || errno == EAGAIN)); /* this is bad - it should be done asynchronously */ + + if (rc == 1) { + if (c == '\r') /* get rid of \r */ + continue; + *ptr = c; + if (c == '\n') + break; + ptr++; + } else if (rc == 0) { + if (n == 1) + return (0); /* EOF, no data */ + else + break; /* EOF, w/ data */ + } else { + return -1; + } + } + + *ptr = 0; + return (n); +} + +static int url_to_host_port_path(const char *url, + char *host, int *port, char *path, int *ssl) +{ + char *urlcopy = NULL; + char *slash = NULL; + char *colon = NULL; + + /* + * http://hostname + * http://hostname/ + * http://hostname/path + * http://hostname/path:foo + * http://hostname:port + * http://hostname:port/ + * http://hostname:port/path + * http://hostname:port/path:foo + * and https:// variants of the above + */ + + if (strstr(url, "http://") == url) { + urlcopy = strdup(url + 7); + } else if (strstr(url, "https://") == url) { + urlcopy = strdup(url + 8); + *ssl = 1; + } else { + WARNING(("Weird url - unknown protocol: %s", url)); + return 0; + } + + slash = strchr(urlcopy, '/'); + colon = strchr(urlcopy, ':'); + + if (!colon || (slash && slash < colon)) { + if (*ssl) + *port = 443; + else + *port = 80; + } else { + *colon = 0; + *port = atoi(colon + 1); + } + + if (!slash) { + strcpy(path, "/"); + } else { + strcpy(path, slash); + *slash = 0; + } + + strcpy(host, urlcopy); + + FREE(urlcopy); + + return 1; +} + +static int isurlchar(unsigned char c) +{ + return (isalnum(c)); +} + +char *yahoo_urlencode(const char *instr) +{ + int ipos = 0, bpos = 0; + char *str = NULL; + int len = strlen(instr); + + if (!(str = y_new(char, 3 *len + 1))) + return ""; + + while (instr[ipos]) { + while (isurlchar(instr[ipos])) + str[bpos++] = instr[ipos++]; + if (!instr[ipos]) + break; + + snprintf(&str[bpos], 4, "%%%02x", instr[ipos] & 0xff); + bpos += 3; + ipos++; + } + str[bpos] = '\0'; + + /* free extra alloc'ed mem. */ + len = strlen(str); + str = y_renew(char, str, len + 1); + + return (str); +} + +char *yahoo_urldecode(const char *instr) +{ + int ipos = 0, bpos = 0; + char *str = NULL; + char entity[3] = { 0, 0, 0 }; + unsigned dec; + int len = strlen(instr); + + if (!(str = y_new(char, len + 1))) + return ""; + + while (instr[ipos]) { + while (instr[ipos] && instr[ipos] != '%') + if (instr[ipos] == '+') { + str[bpos++] = ' '; + ipos++; + } else + str[bpos++] = instr[ipos++]; + if (!instr[ipos]) + break; + + if (instr[ipos + 1] && instr[ipos + 2]) { + ipos++; + entity[0] = instr[ipos++]; + entity[1] = instr[ipos++]; + sscanf(entity, "%2x", &dec); + str[bpos++] = (char)dec; + } else { + str[bpos++] = instr[ipos++]; + } + } + str[bpos] = '\0'; + + /* free extra alloc'ed mem. */ + len = strlen(str); + str = y_renew(char, str, len + 1); + + return (str); +} + +char *yahoo_xmldecode(const char *instr) +{ + int ipos = 0, bpos = 0, epos = 0; + char *str = NULL; + char entity[4] = { 0, 0, 0, 0 }; + char *entitymap[5][2] = { + {"amp;", "&"}, + {"quot;", "\""}, + {"lt;", "<"}, + {"gt;", "<"}, + {"nbsp;", " "} + }; + unsigned dec; + int len = strlen(instr); + + if (!(str = y_new(char, len + 1))) + return ""; + + while (instr[ipos]) { + while (instr[ipos] && instr[ipos] != '&') + if (instr[ipos] == '+') { + str[bpos++] = ' '; + ipos++; + } else + str[bpos++] = instr[ipos++]; + if (!instr[ipos] || !instr[ipos + 1]) + break; + ipos++; + + if (instr[ipos] == '#') { + ipos++; + epos = 0; + while (instr[ipos] != ';') + entity[epos++] = instr[ipos++]; + sscanf(entity, "%u", &dec); + str[bpos++] = (char)dec; + ipos++; + } else { + int i; + for (i = 0; i < 5; i++) + if (!strncmp(instr + ipos, entitymap[i][0], + strlen(entitymap[i][0]))) { + str[bpos++] = entitymap[i][1][0]; + ipos += strlen(entitymap[i][0]); + break; + } + } + } + str[bpos] = '\0'; + + /* free extra alloc'ed mem. */ + len = strlen(str); + str = y_renew(char, str, len + 1); + + return (str); +} + +typedef void (*http_connected) (int id, void *fd, int error); + +struct callback_data { + int id; + yahoo_get_fd_callback callback; + char *request; + void *user_data; +}; + +static void connect_complete(void *fd, int error, void *data) +{ + struct callback_data *ccd = data; + if (error == 0) + YAHOO_CALLBACK(ext_yahoo_write) (fd, ccd->request, + strlen(ccd->request)); + free(ccd->request); + ccd->callback(ccd->id, fd, error, ccd->user_data); + FREE(ccd); +} + +static void yahoo_send_http_request(int id, char *host, int port, char *request, + yahoo_get_fd_callback callback, void *data, int use_ssl) +{ + struct callback_data *ccd = y_new0(struct callback_data, 1); + ccd->callback = callback; + ccd->id = id; + ccd->request = strdup(request); + ccd->user_data = data; + + YAHOO_CALLBACK(ext_yahoo_connect_async) (id, host, port, + connect_complete, ccd, use_ssl); +} + +void yahoo_http_post(int id, const char *url, const char *cookies, + long content_length, yahoo_get_fd_callback callback, void *data) +{ + char host[255]; + int port = 80; + char path[255]; + char buff[1024]; + int ssl = 0; + + if (!url_to_host_port_path(url, host, &port, path, &ssl)) + return; + + /* thanks to kopete dumpcap */ + snprintf(buff, sizeof(buff), + "POST %s HTTP/1.1\r\n" + "Cookie: %s\r\n" + "User-Agent: Mozilla/5.0\r\n" + "Host: %s\r\n" + "Content-Length: %ld\r\n" + "Cache-Control: no-cache\r\n" + "\r\n", path, cookies, host, content_length); + + yahoo_send_http_request(id, host, port, buff, callback, data, ssl); +} + +void yahoo_http_get(int id, const char *url, const char *cookies, int http11, + int keepalive, yahoo_get_fd_callback callback, void *data) +{ + char host[255]; + int port = 80; + char path[255]; + char buff[2048]; + char cookiebuff[1024]; + int ssl = 0; + + if (!url_to_host_port_path(url, host, &port, path, &ssl)) + return; + + /* Allow cases when we don't need to send a cookie */ + if (cookies) + snprintf(cookiebuff, sizeof(cookiebuff), "Cookie: %s\r\n", + cookies); + else + cookiebuff[0] = '\0'; + + snprintf(buff, sizeof(buff), + "GET %s HTTP/1.%s\r\n" + "%sHost: %s\r\n" + "User-Agent: Mozilla/4.5 [en] (" "1" "/" "1" ")\r\n" + "Accept: */*\r\n" + "%s" "\r\n", path, http11?"1":"0", cookiebuff, host, + keepalive? "Connection: Keep-Alive\r\n":"Connection: close\r\n"); + + yahoo_send_http_request(id, host, port, buff, callback, data, ssl); +} + +void yahoo_http_head(int id, const char *url, const char *cookies, int len, + char *payload, yahoo_get_fd_callback callback, void *data) +{ + char host[255]; + int port = 80; + char path[255]; + char buff[2048]; + char cookiebuff[1024]; + int ssl = 0; + + if (!url_to_host_port_path(url, host, &port, path, &ssl)) + return; + + /* Allow cases when we don't need to send a cookie */ + if (cookies) + snprintf(cookiebuff, sizeof(cookiebuff), "Cookie: %s\r\n", + cookies); + else + cookiebuff[0] = '\0'; + + snprintf(buff, sizeof(buff), + "HEAD %s HTTP/1.0\r\n" + "Accept: */*\r\n" + "Host: %s:%d\r\n" + "User-Agent: Mozilla/4.5 [en] (" "1" "/" "1" ")\r\n" + "%s" + "Content-Length: %d\r\n" + "Cache-Control: no-cache\r\n" + "\r\n%s", path, host, port, cookiebuff, len, + payload?payload:""); + + yahoo_send_http_request(id, host, port, buff, callback, data, ssl); +} + diff --git a/backends/libyahoo2/yahoo/yahoo_httplib.h b/backends/libyahoo2/yahoo/yahoo_httplib.h new file mode 100644 index 0000000000000000000000000000000000000000..ab699b20be6239a3b95b69ce76fa0b9c339866b9 --- /dev/null +++ b/backends/libyahoo2/yahoo/yahoo_httplib.h @@ -0,0 +1,48 @@ +/* + * libyahoo2: yahoo_httplib.h + * + * Copyright (C) 2002-2004, Philip S Tellis + * + * 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 YAHOO_HTTPLIB_H +#define YAHOO_HTTPLIB_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "yahoo2_types.h" + + char *yahoo_urlencode(const char *instr); + char *yahoo_urldecode(const char *instr); + char *yahoo_xmldecode(const char *instr); + + int yahoo_tcp_readline(char *ptr, int maxlen, void *fd); + void yahoo_http_post(int id, const char *url, const char *cookies, + long size, yahoo_get_fd_callback callback, void *data); + void yahoo_http_get(int id, const char *url, const char *cookies, + int http11, int keepalive, yahoo_get_fd_callback callback, + void *data); + void yahoo_http_head(int id, const char *url, const char *cookies, + int size, char *payload, yahoo_get_fd_callback callback, + void *data); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/backends/libyahoo2/yahoo/yahoo_list.c b/backends/libyahoo2/yahoo/yahoo_list.c new file mode 100644 index 0000000000000000000000000000000000000000..2335f9c543ef13d9099b6bd94079b34177c2e3fb --- /dev/null +++ b/backends/libyahoo2/yahoo/yahoo_list.c @@ -0,0 +1,233 @@ +/* + * yahoo_list.c: linked list routines + * + * Some code copyright (C) 2002-2004, Philip S Tellis + * Other code copyright Meredydd Luff + * + * 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 + * + * Some of this code was borrowed from elist.c in the eb-lite sources + * + */ + +#include + +#include "yahoo_list.h" + +YList *y_list_append(YList *list, void *data) +{ + YList *n; + YList *new_list = malloc(sizeof(YList)); + YList *attach_to = NULL; + + new_list->next = NULL; + new_list->data = data; + + for (n = list; n != NULL; n = n->next) { + attach_to = n; + } + + if (attach_to == NULL) { + new_list->prev = NULL; + return new_list; + } else { + new_list->prev = attach_to; + attach_to->next = new_list; + return list; + } +} + +YList *y_list_prepend(YList *list, void *data) +{ + YList *n = malloc(sizeof(YList)); + + n->next = list; + n->prev = NULL; + n->data = data; + if (list) + list->prev = n; + + return n; +} + +YList *y_list_concat(YList *list, YList *add) +{ + YList *l; + + if (!list) + return add; + + if (!add) + return list; + + for (l = list; l->next; l = l->next) ; + + l->next = add; + add->prev = l; + + return list; +} + +YList *y_list_remove(YList *list, void *data) +{ + YList *n; + + for (n = list; n != NULL; n = n->next) { + if (n->data == data) { + list = y_list_remove_link(list, n); + y_list_free_1(n); + break; + } + } + + return list; +} + +/* Warning */ +/* link MUST be part of list */ +/* caller must free link using y_list_free_1 */ +YList *y_list_remove_link(YList *list, const YList *link) +{ + if (!link) + return list; + + if (link->next) + link->next->prev = link->prev; + if (link->prev) + link->prev->next = link->next; + + if (link == list) + list = link->next; + + return list; +} + +int y_list_length(const YList *list) +{ + int retval = 0; + const YList *n = list; + + for (n = list; n != NULL; n = n->next) { + retval++; + } + + return retval; +} + +/* well, you could just check for list == NULL, but that would be + * implementation dependent + */ +int y_list_empty(const YList *list) +{ + if (!list) + return 1; + else + return 0; +} + +int y_list_singleton(const YList *list) +{ + if (!list || list->next) + return 0; + return 1; +} + +YList *y_list_copy(YList *list) +{ + YList *n; + YList *copy = NULL; + + for (n = list; n != NULL; n = n->next) { + copy = y_list_append(copy, n->data); + } + + return copy; +} + +void y_list_free_1(YList *list) +{ + free(list); +} + +void y_list_free(YList *list) +{ + YList *n = list; + + while (n != NULL) { + YList *next = n->next; + free(n); + n = next; + } +} + +YList *y_list_find(YList *list, const void *data) +{ + YList *l; + for (l = list; l && l->data != data; l = l->next) ; + + return l; +} + +void y_list_foreach(YList *list, YListFunc fn, void *user_data) +{ + for (; list; list = list->next) + fn(list->data, user_data); +} + +YList *y_list_find_custom(YList *list, const void *data, YListCompFunc comp) +{ + YList *l; + for (l = list; l; l = l->next) + if (comp(l->data, data) == 0) + return l; + + return NULL; +} + +YList *y_list_nth(YList *list, int n) +{ + int i = n; + for (; list && i; list = list->next, i--) ; + + return list; +} + +YList *y_list_insert_sorted(YList *list, void *data, YListCompFunc comp) +{ + YList *l, *n, *prev = NULL; + if (!list) + return y_list_append(list, data); + + n = malloc(sizeof(YList)); + n->data = data; + for (l = list; l && comp(l->data, n->data) <= 0; l = l->next) + prev = l; + + if (l) { + n->prev = l->prev; + l->prev = n; + } else + n->prev = prev; + + n->next = l; + + if (n->prev) { + n->prev->next = n; + return list; + } else { + return n; + } + +} diff --git a/backends/libyahoo2/yahoo/yahoo_list.h b/backends/libyahoo2/yahoo/yahoo_list.h new file mode 100644 index 0000000000000000000000000000000000000000..bdec139bf40b4c8ba61567c1b24591969b78cd67 --- /dev/null +++ b/backends/libyahoo2/yahoo/yahoo_list.h @@ -0,0 +1,76 @@ +/* + * yahoo_list.h: linked list routines + * + * Some code copyright (C) 2002-2004, Philip S Tellis + * Other code copyright Meredydd Luff + * + * 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 + * + */ + +/* + * This is a replacement for the GList. It only provides functions that + * we use in Ayttm. Thanks to Meredyyd from everybuddy dev for doing + * most of it. + */ + +#ifndef __YLIST_H__ +#define __YLIST_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + typedef struct _YList { + struct _YList *next; + struct _YList *prev; + void *data; + } YList; + + typedef int (*YListCompFunc) (const void *, const void *); + typedef void (*YListFunc) (void *, void *); + + YList *y_list_append(YList *list, void *data); + YList *y_list_prepend(YList *list, void *data); + YList *y_list_remove_link(YList *list, const YList *link); + YList *y_list_remove(YList *list, void *data); + + YList *y_list_insert_sorted(YList *list, void *data, + YListCompFunc comp); + + YList *y_list_copy(YList *list); + + YList *y_list_concat(YList *list, YList *add); + + YList *y_list_find(YList *list, const void *data); + YList *y_list_find_custom(YList *list, const void *data, + YListCompFunc comp); + + YList *y_list_nth(YList *list, int n); + + void y_list_foreach(YList *list, YListFunc fn, void *user_data); + + void y_list_free_1(YList *list); + void y_list_free(YList *list); + int y_list_length(const YList *list); + int y_list_empty(const YList *list); + int y_list_singleton(const YList *list); + +#define y_list_next(list) list->next + +#ifdef __cplusplus +} +#endif +#endif diff --git a/backends/libyahoo2/yahoo/yahoo_util.c b/backends/libyahoo2/yahoo/yahoo_util.c new file mode 100644 index 0000000000000000000000000000000000000000..add6d81abc65ec933c3df466a1f99192a5c3107d --- /dev/null +++ b/backends/libyahoo2/yahoo/yahoo_util.c @@ -0,0 +1,162 @@ +/* + * libyahoo2: yahoo_util.c + * + * Copyright (C) 2002-2004, Philip S Tellis + * + * 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 + * + */ + +#if HAVE_CONFIG_H +# include +#endif + +#if STDC_HEADERS +# include +#else +# if !HAVE_STRCHR +# define strchr index +# define strrchr rindex +# endif +char *strchr(), *strrchr(); +# if !HAVE_MEMCPY +# define memcpy(d, s, n) bcopy ((s), (d), (n)) +# define memmove(d, s, n) bcopy ((s), (d), (n)) +# endif +#endif + +#include "yahoo_util.h" + +char *y_string_append(char *string, char *append) +{ + int size = strlen(string) + strlen(append) + 1; + char *new_string = y_renew(char, string, size); + + if (new_string == NULL) { + new_string = y_new(char, size); + strcpy(new_string, string); + FREE(string); + } + + strcat(new_string, append); + + return new_string; +} + +char *y_str_to_utf8(const char *in) +{ + unsigned int n, i = 0; + char *result = NULL; + + if (in == NULL || *in == '\0') + return strdup(""); + + result = y_new(char, strlen(in) * 2 + 1); + + /* convert a string to UTF-8 Format */ + for (n = 0; n < strlen(in); n++) { + unsigned char c = (unsigned char)in[n]; + + if (c < 128) { + result[i++] = (char)c; + } else { + result[i++] = (char)((c >> 6) | 192); + result[i++] = (char)((c & 63) | 128); + } + } + result[i] = '\0'; + return result; +} + +char *y_utf8_to_str(const char *in) +{ + int i = 0; + unsigned int n; + char *result = NULL; + + if (in == NULL || *in == '\0') + return strdup(""); + + result = y_new(char, strlen(in) + 1); + + /* convert a string from UTF-8 Format */ + for (n = 0; n < strlen(in); n++) { + unsigned char c = in[n]; + + if (c < 128) { + result[i++] = (char)c; + } else { + result[i++] = (c << 6) | (in[++n] & 63); + } + } + result[i] = '\0'; + return result; +} + +#if !HAVE_GLIB + +void y_strfreev(char **vector) +{ + char **v; + for (v = vector; *v; v++) { + FREE(*v); + } + FREE(vector); +} + +char **y_strsplit(char *str, char *sep, int nelem) +{ + char **vector; + char *s, *p; + int i = 0; + int l = strlen(sep); + if (nelem <= 0) { + char *s; + nelem = 0; + if (*str) { + for (s = strstr(str, sep); s; + s = strstr(s + l, sep), nelem++) ; + if (strcmp(str + strlen(str) - l, sep)) + nelem++; + } + } + + vector = y_new(char *, nelem + 1); + + for (p = str, s = strstr(p, sep); i < nelem && s; + p = s + l, s = strstr(p, sep), i++) { + int len = s - p; + vector[i] = y_new(char, len + 1); + strncpy(vector[i], p, len); + vector[i][len] = '\0'; + } + + if (i < nelem && *str) /* str didn't end with sep, and str isn't empty */ + vector[i++] = strdup(p); + + vector[i] = NULL; + + return vector; +} + +void *y_memdup(const void *addr, int n) +{ + void *new_chunk = malloc(n); + if (new_chunk) + memcpy(new_chunk, addr, n); + return new_chunk; +} + +#endif diff --git a/backends/libyahoo2/yahoo/yahoo_util.h b/backends/libyahoo2/yahoo/yahoo_util.h new file mode 100644 index 0000000000000000000000000000000000000000..cc92486740b1613be47ffe566d7a6bdb802c4a6a --- /dev/null +++ b/backends/libyahoo2/yahoo/yahoo_util.h @@ -0,0 +1,103 @@ +/* + * libyahoo2: yahoo_util.h + * + * Copyright (C) 2002-2004, Philip S Tellis + * + * 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 __YAHOO_UTIL_H__ +#define __YAHOO_UTIL_H__ + +#if HAVE_CONFIG_H +# include +#endif + +#if HAVE_GLIB +# include + +# define FREE(x) if(x) {g_free(x); x=NULL;} + +# define y_new g_new +# define y_new0 g_new0 +# define y_renew g_renew + +# define y_memdup g_memdup +# define y_strsplit g_strsplit +# define y_strfreev g_strfreev +# ifndef strdup +# define strdup g_strdup +# endif +# ifndef strncasecmp +# define strncasecmp g_strncasecmp +# define strcasecmp g_strcasecmp +# endif + +# define snprintf g_snprintf +# define vsnprintf g_vsnprintf + +#else + +# include +# include + +# define FREE(x) if(x) {free(x); x=NULL;} + +# define y_new(type, n) (type *)malloc(sizeof(type) * (n)) +# define y_new0(type, n) (type *)calloc((n), sizeof(type)) +# define y_renew(type, mem, n) (type *)realloc(mem, n) + +void *y_memdup(const void *addr, int n); +char **y_strsplit(char *str, char *sep, int nelem); +void y_strfreev(char **vector); + +#ifndef _WIN32 +int strncasecmp(const char *s1, const char *s2, size_t n); +int strcasecmp(const char *s1, const char *s2); + +char *strdup(const char *s); + +int snprintf(char *str, size_t size, const char *format, ...); +int vsnprintf(char *str, size_t size, const char *format, va_list ap); +#endif + +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef MIN +#define MIN(x,y) ((x)<(y)?(x):(y)) +#endif + +#ifndef MAX +#define MAX(x,y) ((x)>(y)?(x):(y)) +#endif + +/* + * The following three functions return newly allocated memory. + * You must free it yourself + */ +char *y_string_append(char *str, char *append); +char *y_str_to_utf8(const char *in); +char *y_utf8_to_str(const char *in); + +#endif diff --git a/backends/libyahoo2/yahoohandler.h b/backends/libyahoo2/yahoohandler.h new file mode 100644 index 0000000000000000000000000000000000000000..94a07eb54066927f1338b6cbe38f5c2f9e3b96ac --- /dev/null +++ b/backends/libyahoo2/yahoohandler.h @@ -0,0 +1,48 @@ +#pragma once + +// Transport includes +#include "transport/config.h" +#include "transport/networkplugin.h" +#include "transport/logging.h" + +// Yahoo2 +#include +#include +#include +#include +#include + +// Swiften +#include "Swiften/Swiften.h" +#include "Swiften/TLS/OpenSSL/OpenSSLContextFactory.h" + +// for signal handler +#include "unistd.h" +#include "signal.h" +#include "sys/wait.h" +#include "sys/signal.h" + +// Boost +#include + +using namespace boost::filesystem; +using namespace boost::program_options; +using namespace Transport; + +class YahooLocalAccount; + +class YahooHandler { + public: + YahooHandler(YahooLocalAccount *account, int conn_tag, int handler_tag, void *data, yahoo_input_condition cond); + virtual ~YahooHandler(); + + void ready(std::string *buffer = NULL); + + int handler_tag; + int conn_tag; + void *data; + yahoo_input_condition cond; + bool remove_later; + YahooLocalAccount *account; +}; + diff --git a/backends/libyahoo2/yahoolocalaccount.cpp b/backends/libyahoo2/yahoolocalaccount.cpp new file mode 100644 index 0000000000000000000000000000000000000000..49b88c9422664d0121c72d7a76c3ec7923b84b65 --- /dev/null +++ b/backends/libyahoo2/yahoolocalaccount.cpp @@ -0,0 +1,60 @@ + +#include "yahoolocalaccount.h" +#include "yahoohandler.h" + +YahooLocalAccount::YahooLocalAccount(const std::string &user, const std::string &legacyName, const std::string &password) : user(user), id(0), conn_tag(1), handler_tag(1), status(YAHOO_STATUS_OFFLINE), msg(""), buffer("") { + id = yahoo_init_with_attributes(legacyName.c_str(), password.c_str(), + "local_host", "", + "pager_port", 5050, + NULL); +} + +YahooLocalAccount::~YahooLocalAccount() { + // remove handlers + for (std::map::iterator it = handlers.begin(); it != handlers.end(); it++) { + delete it->second; + } + + // remove conns + for (std::map >::iterator it = conns.begin(); it != conns.end(); it++) { + it->second->onConnectFinished.disconnect_all_slots(); + it->second->onDisconnected.disconnect_all_slots(); + it->second->onDataRead.disconnect_all_slots(); + it->second->onDataWritten.disconnect_all_slots(); + } +} + +void YahooLocalAccount::login() { + yahoo_login(id, YAHOO_STATUS_AVAILABLE); +} + +void YahooLocalAccount::addHandler(YahooHandler *handler) { + handlers[handler->handler_tag] = handler; + handlers_per_conn[handler->conn_tag][handler->handler_tag] = handler; +} + +void YahooLocalAccount::removeOldHandlers() { + std::vector handlers_to_remove; + for (std::map::iterator it = handlers.begin(); it != handlers.end(); it++) { + if (it->second->remove_later) { + handlers_to_remove.push_back(it->first); + } + } + + BOOST_FOREACH(int tag, handlers_to_remove) { + YahooHandler *handler = handlers[tag]; + handlers.erase(tag); + handlers_per_conn[handler->conn_tag].erase(tag); + delete handler; + } +} + +void YahooLocalAccount::removeConn(int conn_tag) { + for (std::map::iterator it = handlers_per_conn[conn_tag].begin(); it != handlers_per_conn[conn_tag].end(); it++) { + it->second->remove_later = true; + } + + removeOldHandlers(); + + conns.erase(conn_tag); +} diff --git a/backends/libyahoo2/yahoolocalaccount.h b/backends/libyahoo2/yahoolocalaccount.h new file mode 100644 index 0000000000000000000000000000000000000000..19eb42c86655e7e735e2f7c1f63886775c6e858b --- /dev/null +++ b/backends/libyahoo2/yahoolocalaccount.h @@ -0,0 +1,56 @@ +#pragma once + +// Transport includes +#include "transport/config.h" +#include "transport/networkplugin.h" +#include "transport/logging.h" + +// Yahoo2 +#include +#include +#include +#include +#include + +// Swiften +#include "Swiften/Swiften.h" +#include "Swiften/TLS/OpenSSL/OpenSSLContextFactory.h" + +// for signal handler +#include "unistd.h" +#include "signal.h" +#include "sys/wait.h" +#include "sys/signal.h" + +// Boost +#include + +using namespace boost::filesystem; +using namespace boost::program_options; +using namespace Transport; + +class YahooHandler; + +class YahooLocalAccount { + public: + YahooLocalAccount(const std::string &user, const std::string &legacyName, const std::string &password); + virtual ~YahooLocalAccount(); + + void login(); + + void addHandler(YahooHandler *handler); + void removeOldHandlers(); + void removeConn(int conn_tag); + + std::string user; + int id; + std::map > conns; + int conn_tag; + std::map handlers; + std::map > handlers_per_conn; + std::map urls; + int handler_tag; + int status; + std::string msg; + std::string buffer; +}; diff --git a/backends/smstools3/main.cpp b/backends/smstools3/main.cpp index 2e61868c60f906925a1c0fd76452f62271e1697a..32799348701277e61ca81f5cd56aca4f6fc609dd 100644 --- a/backends/smstools3/main.cpp +++ b/backends/smstools3/main.cpp @@ -124,8 +124,8 @@ class SMSNetworkPlugin : public NetworkPlugin { void handleSMSDir() { std::string dir = "/var/spool/sms/incoming/"; - if (config->getUnregistered().find("backend.incoming_dir") != config->getUnregistered().end()) { - dir = config->getUnregistered().find("backend.incoming_dir")->second; + if (CONFIG_HAS_KEY(config, "backend.incoming_dir")) { + dir = CONFIG_STRING(config, "backend.incoming_dir"); } LOG4CXX_INFO(logger, "Checking directory " << dir << " for incoming SMS."); diff --git a/backends/swiften/main.cpp b/backends/swiften/main.cpp index a9a240705bcc97223792536082aec39eeb8244be..a9e3bf362972600fe143fcaaa024cc8f17b88028 100644 --- a/backends/swiften/main.cpp +++ b/backends/swiften/main.cpp @@ -112,6 +112,7 @@ class SwiftenPlugin : public NetworkPlugin { } void handleSwiftConnected(const std::string &user) { + LOG4CXX_INFO(logger, user << ": Connected to XMPP server."); handleConnected(user); m_users[user]->requestRoster(); Swift::Presence::ref response = Swift::Presence::create(); diff --git a/cmake_modules/BoostConfig.cmake b/cmake_modules/BoostConfig.cmake index 20e2e60b7548b159695a15e68adf40f8e227b1e4..408f3aff3b223aac5ee60e642f57bd6531b93a45 100644 --- a/cmake_modules/BoostConfig.cmake +++ b/cmake_modules/BoostConfig.cmake @@ -637,14 +637,14 @@ ELSE (_boost_IN_CACHE) endif(Boost_COMPILER) - if(${Boost_MINOR_VERSION} GREATER 41 AND NOT WIN32 AND NOT APPLE) - set (_boost_MULTITHREADED "") - else() +# if(${Boost_MINOR_VERSION} GREATER 41 AND NOT WIN32 AND NOT APPLE) +# set (_boost_MULTITHREADED "") +# else() SET (_boost_MULTITHREADED "-mt") if( NOT Boost_USE_MULTITHREADED ) set (_boost_MULTITHREADED "") endif() - endif() +# endif() if(Boost_DEBUG) message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " diff --git a/cmake_modules/yahoo2Config.cmake b/cmake_modules/yahoo2Config.cmake new file mode 100644 index 0000000000000000000000000000000000000000..bbd958f914e6948b92c2f0011a6ca5c0aa4a6194 --- /dev/null +++ b/cmake_modules/yahoo2Config.cmake @@ -0,0 +1,12 @@ +FIND_PATH(YAHOO2_INCLUDE_DIR yahoo2.h PATH_SUFFIXES libyahoo2) +MARK_AS_ADVANCED(YAHOO2_INCLUDE_DIR) + +FIND_LIBRARY(YAHOO2_LIBRARY yahoo2 ) +MARK_AS_ADVANCED(YAHOO2_LIBRARY) + +if(YAHOO2_LIBRARY AND YAHOO2_INCLUDE_DIR) + set( YAHOO2_FOUND 1 ) + message(STATUS "Found libyahoo2: ${YAHOO2_LIBRARY}, ${YAHOO2_INCLUDE_DIR}") +else() + message(STATUS "Could NOT find libyahoo2 library") +endif() diff --git a/include/Swiften/Parser/StringTreeParser.cpp b/include/Swiften/Parser/StringTreeParser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..92412d14a429d831e93f94289fd0e3b5c369ba5a --- /dev/null +++ b/include/Swiften/Parser/StringTreeParser.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2011 Jan Kaluza + * Licensed under the Simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include +#include +#include +#include + +namespace Swift { + +class DefaultStringTreeParser : public StringTreeParser { + public: + void handleTree(ParserElement::ref root) { + root_ = root; + } + + ParserElement::ref getRoot() { + return root_; + } + + private: + ParserElement::ref root_; +}; + +ParserElement::ref StringTreeParser::parse(const std::string &xml) { + PlatformXMLParserFactory factory; + DefaultStringTreeParser client; + XMLParser *parser = factory.createXMLParser(&client); + + parser->parse(xml); + ParserElement::ref root = client.getRoot(); + delete parser; + return root; +} + +} diff --git a/include/Swiften/Parser/StringTreeParser.h b/include/Swiften/Parser/StringTreeParser.h new file mode 100644 index 0000000000000000000000000000000000000000..06089a7d872a211249eed70ec680a36464d6579f --- /dev/null +++ b/include/Swiften/Parser/StringTreeParser.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2011 Jan Kaluza + * Licensed under the Simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include + +#include +#include + +#include +#include + +namespace Swift { + /** + * Generics parser offering something a bit like a DOM to work with. + */ + class StringTreeParser : public XMLParserClient { + public: + StringTreeParser() : XMLParserClient() {} + + virtual void handleStartElement(const std::string& element, const std::string& xmlns, const AttributeMap& attributes) { + if (!root_) { + root_ = boost::make_shared(element, xmlns, attributes); + elementStack_.push_back(root_); + } + else { + ParserElement::ref current = *elementStack_.rbegin(); + elementStack_.push_back(current->addChild(element, xmlns, attributes)); + } + } + + virtual void handleEndElement(const std::string& /*element*/, const std::string&) { + elementStack_.pop_back(); + if (elementStack_.empty()) { + handleTree(root_); + } + } + + virtual void handleCharacterData(const std::string& data) { + ParserElement::ref current = *elementStack_.rbegin(); + current->appendCharacterData(data); + } + + virtual void handleTree(ParserElement::ref root) = 0; + + static ParserElement::ref parse(const std::string &xml); + + private: + std::deque elementStack_; + ParserElement::ref root_; + }; +} diff --git a/include/Swiften/Server/ServerStanzaChannel.h b/include/Swiften/Server/ServerStanzaChannel.h index 356dab95aa34262c7062f3deeb04bf931931e746..cc7a2754cf6e3077a991942532d02b38bedf84b7 100644 --- a/include/Swiften/Server/ServerStanzaChannel.h +++ b/include/Swiften/Server/ServerStanzaChannel.h @@ -14,6 +14,7 @@ #include "Swiften/Elements/Message.h" #include "Swiften/Elements/IQ.h" #include "Swiften/Elements/Presence.h" +#include "Swiften/TLS/Certificate.h" namespace Swift { class Error; @@ -36,6 +37,10 @@ namespace Swift { bool isAvailable() const { return true; } + + std::vector getPeerCertificateChain() const { + return std::vector(); + } private: std::string getNewIQID(); diff --git a/include/transport/adhoccommand.h b/include/transport/adhoccommand.h new file mode 100644 index 0000000000000000000000000000000000000000..03bc21b832ae5180ffe88134fff1cd55794eac1d --- /dev/null +++ b/include/transport/adhoccommand.h @@ -0,0 +1,72 @@ +/** + * XMPP - libpurple transport + * + * Copyright (C) 2009, Jan Kaluza + * + * 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 Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#pragma once + +#include +#include +#include +#include "Swiften/Swiften.h" + +namespace Transport { + +class Component; + +class AdHocCommand { + public: + /// Creates new AdHocManager. + + /// \param component Transport instance associated with this AdHocManager. + AdHocCommand(Component *component, const Swift::JID &initiator, const Swift::JID &to); + + /// Destructor. + virtual ~AdHocCommand(); + + virtual boost::shared_ptr handleRequest(boost::shared_ptr payload) = 0; + + void addFormField(Swift::FormField::ref field); + + const std::string &getId() { + return m_id; + } + + void refreshLastActivity() { + m_lastActivity = time(NULL); + } + + time_t getLastActivity() { + return m_lastActivity; + } + + protected: + Component *m_component; + Swift::JID m_initiator; + Swift::JID m_to; + std::vector m_fields; + std::string m_id; + + private: + // This is used to remove AdHocCommand after long inactivity to prevent memory leaks + // caused by users which disconnect before they finish the command. + // AdHocManager uses this to garbage collect old AdHocCommands. + time_t m_lastActivity; +}; + +} diff --git a/include/transport/adhoccommandfactory.h b/include/transport/adhoccommandfactory.h new file mode 100644 index 0000000000000000000000000000000000000000..a0430d0fb3620a6369a94e8ebacb7eb83ff26a45 --- /dev/null +++ b/include/transport/adhoccommandfactory.h @@ -0,0 +1,47 @@ +/** + * XMPP - libpurple transport + * + * Copyright (C) 2009, Jan Kaluza + * + * 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 Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#pragma once + +#include +#include +#include +#include "transport/adhoccommand.h" +#include "Swiften/Swiften.h" + +namespace Transport { + +class Component; + +class AdHocCommandFactory { + public: + AdHocCommandFactory() {} + + /// Destructor. + virtual ~AdHocCommandFactory() {} + + virtual AdHocCommand *createAdHocCommand(Component *component, const Swift::JID &initiator, const Swift::JID &to) = 0; + + virtual std::string getNode() = 0; + + virtual std::string getName() = 0; +}; + +} diff --git a/include/transport/adhocmanager.h b/include/transport/adhocmanager.h new file mode 100644 index 0000000000000000000000000000000000000000..ca19979efdc41b272831f8a827e6a2cf4c03d44a --- /dev/null +++ b/include/transport/adhocmanager.h @@ -0,0 +1,75 @@ +/** + * XMPP - libpurple transport + * + * Copyright (C) 2009, Jan Kaluza + * + * 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 Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#pragma once + +#include +#include +#include +#include "Swiften/Swiften.h" + +namespace Transport { + +class Conversation; +class User; +class Component; +class DiscoItemsResponder; +class AdHocCommandFactory; +class AdHocCommand; + +/// Listens for AdHoc commands and manages all AdHoc commands sessions +class AdHocManager : public Swift::Responder { + public: + typedef std::map CommandsMap; + typedef std::map SessionsMap; + /// Creates new AdHocManager. + + /// \param component Transport instance associated with this AdHocManager. + AdHocManager(Component *component, DiscoItemsResponder *discoItemsResponder); + + /// Destructor. + virtual ~AdHocManager(); + + /// Starts handling AdHoc commands payloads. + void start(); + + /// Stops handling AdHoc commands payloads and destroys all existing + /// AdHoc commands sessions. + void stop(); + + /// Adds factory to create new AdHoc commands sessions of particular type. + void addAdHocCommand(AdHocCommandFactory *factory); + + /// Remove sessions older than N seconds. + void removeOldSessions(); + + + private: + virtual bool handleGetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr payload); + virtual bool handleSetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr payload); + + Component *m_component; + DiscoItemsResponder *m_discoItemsResponder; + std::map m_factories; + SessionsMap m_sessions; + Swift::Timer::ref m_collectTimer; +}; + +} diff --git a/include/transport/admininterface.h b/include/transport/admininterface.h index 393394ebdbd6e7e03b82066afe05e3f18b245e7e..48f85dc17911cb3e4fa58d0067d5abf0ef173b87 100644 --- a/include/transport/admininterface.h +++ b/include/transport/admininterface.h @@ -30,13 +30,16 @@ class Component; class StorageBackend; class UserManager; class NetworkPluginServer; +class UserRegistration; class AdminInterface { public: - AdminInterface(Component *component, UserManager *userManager, NetworkPluginServer *server = NULL, StorageBackend *storageBackend = NULL); + AdminInterface(Component *component, UserManager *userManager, NetworkPluginServer *server = NULL, StorageBackend *storageBackend = NULL, UserRegistration *userRegistration = NULL); ~AdminInterface(); + void handleQuery(Swift::Message::ref message); + private: void handleMessageReceived(Swift::Message::ref message); @@ -44,6 +47,8 @@ class AdminInterface { StorageBackend *m_storageBackend; UserManager *m_userManager; NetworkPluginServer *m_server; + UserRegistration *m_userRegistration; + time_t m_start; }; } diff --git a/include/transport/config.h b/include/transport/config.h index 903480e953056b23a3106b3d4ee2ca7abb89a56c..4ced7c987d1a66bccc3504c77c7e636bc76a2e84 100644 --- a/include/transport/config.h +++ b/include/transport/config.h @@ -77,7 +77,7 @@ class Config { bool reload(); bool hasKey(const std::string &key) { - return m_variables.find(key) != m_variables.end(); + return m_variables.find(key) != m_variables.end() || m_unregistered.find(key) != m_unregistered.end(); } /// Returns value of variable defined by key. @@ -85,16 +85,15 @@ class Config { /// For variables in sections you can use "section.variable" key format. /// \param key config variable name const boost::program_options::variable_value &operator[] (const std::string &key) { - return m_variables[key]; + if (m_variables.find(key) != m_variables.end()) { + return m_variables[key]; + } + return m_unregistered[key]; } /// Returns path to config file from which data were loaded. const std::string &getConfigFile() { return m_file; } - const std::map &getUnregistered() { - return m_unregistered; - } - /// This signal is emitted when config is loaded/reloaded. boost::signal onConfigReloaded; @@ -102,7 +101,7 @@ class Config { int m_argc; char **m_argv; Variables m_variables; - std::map m_unregistered; + std::map m_unregistered; std::string m_file; }; diff --git a/src/discoitemsresponder.h b/include/transport/discoitemsresponder.h similarity index 82% rename from src/discoitemsresponder.h rename to include/transport/discoitemsresponder.h index 4361ebe12caa9f608f614c8f69616936480ac8a8..44bdc364ee98f6ab07c9068d88fccae65f274f16 100644 --- a/src/discoitemsresponder.h +++ b/include/transport/discoitemsresponder.h @@ -27,14 +27,22 @@ namespace Transport { +class Component; + class DiscoItemsResponder : public Swift::GetResponder { public: - DiscoItemsResponder(Swift::IQRouter *router); + DiscoItemsResponder(Component *component); ~DiscoItemsResponder(); + void addAdHocCommand(const std::string &node, const std::string &name); +// void removeAdHocCommand(const std::string &node); + private: virtual bool handleGetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr payload); + + Component *m_component; + boost::shared_ptr m_commands; }; } \ No newline at end of file diff --git a/include/transport/mysqlbackend.h b/include/transport/mysqlbackend.h index 47c8757bf085be8b55f55071eebabcde30937105..7b1de13bff1f498df635c9ca212141c46f32d751 100644 --- a/include/transport/mysqlbackend.h +++ b/include/transport/mysqlbackend.h @@ -89,6 +89,9 @@ class MySQLBackend : public StorageBackend void updateBuddy(long userId, const BuddyInfo &buddyInfo); void removeBuddy(long id) {} + void getBuddySetting(long userId, long buddyId, const std::string &variable, int &type, std::string &value) {} + void updateBuddySetting(long userId, long buddyId, const std::string &variable, int type, const std::string &value) {} + void getUserSetting(long userId, const std::string &variable, int &type, std::string &value); void updateUserSetting(long userId, const std::string &variable, const std::string &value); diff --git a/include/transport/networkplugin.h b/include/transport/networkplugin.h index 9f440152a6111e2e6ceb61ccd1d6a6508b0a1590..f54269a0a233cbffd57f77f35f3a053afad71a3e 100644 --- a/include/transport/networkplugin.h +++ b/include/transport/networkplugin.h @@ -75,6 +75,11 @@ class NetworkPlugin { bool blocked = false ); + /// Call this method when buddy is removed from legacy network contact list. + /// \param user XMPP JID of user for which this event occurs. You can get it from NetworkPlugin::handleLoginRequest(). (eg. "user%gmail.com@xmpp.domain.tld") + /// \param buddyName Name of legacy network buddy. (eg. "user2@gmail.com") + void handleBuddyRemoved(const std::string &user, const std::string &buddyName); + /// Call this function when participant in room changed. /// \param user XMPP JID of user for which this event occurs. You can get it from NetworkPlugin::handleLoginRequest(). (eg. "user%gmail.com@xmpp.domain.tld") /// \param nickname Nickname of participant. If participant renamed, this is old name of participant. (eg. "HanzZ") diff --git a/include/transport/networkpluginserver.h b/include/transport/networkpluginserver.h index 5572780a90eda0687baf7d7087a3b0747c246aae..eff5a9876d4ecebdafef2a18caf5eedfb7f2eae0 100644 --- a/include/transport/networkpluginserver.h +++ b/include/transport/networkpluginserver.h @@ -42,6 +42,7 @@ class VCardResponder; class RosterResponder; class BlockResponder; class DummyReadBytestream; +class AdminInterface; class NetworkPluginServer { public: @@ -63,6 +64,10 @@ class NetworkPluginServer { virtual ~NetworkPluginServer(); + void setAdminInterface(AdminInterface *adminInterface) { + m_adminInterface = adminInterface; + } + int getBackendCount() { return m_clients.size(); } @@ -84,11 +89,13 @@ class NetworkPluginServer { private: void handleNewClientConnection(boost::shared_ptr c); void handleSessionFinished(Backend *c); + void handlePongReceived(Backend *c); void handleDataRead(Backend *c, boost::shared_ptr data); void handleConnectedPayload(const std::string &payload); void handleDisconnectedPayload(const std::string &payload); void handleBuddyChangedPayload(const std::string &payload); + void handleBuddyRemovedPayload(const std::string &payload); void handleConvMessagePayload(const std::string &payload, bool subject = false); void handleParticipantChangedPayload(const std::string &payload); void handleRoomChangedPayload(const std::string &payload); @@ -99,7 +106,8 @@ class NetworkPluginServer { void handleStatsPayload(Backend *c, const std::string &payload); void handleFTStartPayload(const std::string &payload); void handleFTFinishPayload(const std::string &payload); - void handleFTDataPayload(Backend *b ,const std::string &payload); + void handleFTDataPayload(Backend *b, const std::string &payload); + void handleQueryPayload(Backend *b, const std::string &payload); void handleUserCreated(User *user); void handleRoomJoined(User *user, const Swift::JID &who, const std::string &room, const std::string &nickname, const std::string &password); @@ -143,6 +151,8 @@ class NetworkPluginServer { std::map m_filetransfers; FileTransferManager *m_ftManager; std::vector m_crashedBackends; + AdminInterface *m_adminInterface; + bool m_startingBackend; }; } diff --git a/include/transport/pqxxbackend.h b/include/transport/pqxxbackend.h index f571433b340f931bef990b7d5be5a1b0b0d8e3d6..bf5abf25d9b9fd8ea8e5fbfa38a1c0c1a83cdd15 100644 --- a/include/transport/pqxxbackend.h +++ b/include/transport/pqxxbackend.h @@ -89,6 +89,9 @@ class PQXXBackend : public StorageBackend void updateBuddy(long userId, const BuddyInfo &buddyInfo); void removeBuddy(long id) {} + void getBuddySetting(long userId, long buddyId, const std::string &variable, int &type, std::string &value) {} + void updateBuddySetting(long userId, long buddyId, const std::string &variable, int type, const std::string &value) {} + void getUserSetting(long userId, const std::string &variable, int &type, std::string &value); void updateUserSetting(long userId, const std::string &variable, const std::string &value); diff --git a/include/transport/protocol.proto b/include/transport/protocol.proto index 8dddaf7e7a03b8195bbfbd08aa33b030bc17b5f3..929c02b79056edac6765ec74f2d5d78975c4b25a 100644 --- a/include/transport/protocol.proto +++ b/include/transport/protocol.proto @@ -158,6 +158,7 @@ message WrapperMessage { TYPE_FT_CONTINUE = 28; TYPE_EXIT = 29; TYPE_BACKEND_CONFIG = 30; + TYPE_QUERY = 31; } required Type type = 1; optional bytes payload = 2; diff --git a/include/transport/rostermanager.h b/include/transport/rostermanager.h index 64f05fa70f63d9a7b642547f617c952813fed9df..fd649b57df89e3466fc310edceb26d4ee1c9c5c4 100644 --- a/include/transport/rostermanager.h +++ b/include/transport/rostermanager.h @@ -69,6 +69,10 @@ class RosterManager { /// \param buddy Buddy. void unsetBuddy(Buddy *buddy); + /// Removes buddy from this roster, sends proper XML to XMPP side and deletes it. + /// \param name Buddy name. + void removeBuddy(const std::string &name); + Buddy *getBuddy(const std::string &name); void setStorageBackend(StorageBackend *storageBackend); @@ -107,7 +111,11 @@ class RosterManager { void sendBuddyRosterPush(Buddy *buddy); + void sendBuddyRosterRemove(Buddy *buddy); + void sendBuddySubscribePresence(Buddy *buddy); + + void sendBuddyUnsubscribePresence(Buddy *buddy); void sendCurrentPresences(const Swift::JID &to); diff --git a/include/transport/rosterstorage.h b/include/transport/rosterstorage.h index bd5cc7dbe76930bdaf682c4e6862e3df481d4627..726425c4b9df6b0f156392dcf8d82f02b81e7041 100644 --- a/include/transport/rosterstorage.h +++ b/include/transport/rosterstorage.h @@ -40,6 +40,8 @@ class RosterStorage { // will happen if buddy is already added. void storeBuddy(Buddy *buddy); + void removeBuddy(Buddy *buddy); + // Store all buddies from queue immediately. Returns true // if some buddies were stored. bool storeBuddies(); diff --git a/include/transport/settingsadhoccommand.h b/include/transport/settingsadhoccommand.h new file mode 100644 index 0000000000000000000000000000000000000000..b34a78040e8038521b2a78ba691dcebe622a6e24 --- /dev/null +++ b/include/transport/settingsadhoccommand.h @@ -0,0 +1,70 @@ +/** + * XMPP - libpurple transport + * + * Copyright (C) 2009, Jan Kaluza + * + * 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 Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#pragma once + +#include +#include +#include +#include "Swiften/Swiften.h" +#include "transport/adhoccommand.h" +#include "transport/adhoccommandfactory.h" + + +namespace Transport { + +class Component; + +class SettingsAdHocCommand : public AdHocCommand { + public: + typedef enum { Init, WaitingForResponse } State; + + SettingsAdHocCommand(Component *component, const Swift::JID &initiator, const Swift::JID &to); + + /// Destructor. + virtual ~SettingsAdHocCommand(); + + virtual boost::shared_ptr handleRequest(boost::shared_ptr payload); + + private: + boost::shared_ptr getForm(); + boost::shared_ptr handleResponse(boost::shared_ptr payload); + State m_state; +}; + +class SettingsAdHocCommandFactory : public AdHocCommandFactory { + public: + SettingsAdHocCommandFactory() {} + virtual ~SettingsAdHocCommandFactory() {} + + AdHocCommand *createAdHocCommand(Component *component, const Swift::JID &initiator, const Swift::JID &to) { + return new SettingsAdHocCommand(component, initiator, to); + } + + std::string getNode() { + return "settings"; + } + + std::string getName() { + return "Transport settings"; + } +}; + +} diff --git a/include/transport/sqlite3backend.h b/include/transport/sqlite3backend.h index 5d7372bf5753e68af63d70f4dd77b00d8d815bdd..d654ffa6b58528de3f0d696da1f2e3ee0cf90c78 100644 --- a/include/transport/sqlite3backend.h +++ b/include/transport/sqlite3backend.h @@ -86,7 +86,10 @@ class SQLite3Backend : public StorageBackend long addBuddy(long userId, const BuddyInfo &buddyInfo); void updateBuddy(long userId, const BuddyInfo &buddyInfo); - void removeBuddy(long id) {} + void removeBuddy(long id); + + void getBuddySetting(long userId, long buddyId, const std::string &variable, int &type, std::string &value); + void updateBuddySetting(long userId, long buddyId, const std::string &variable, int type, const std::string &value); void getUserSetting(long userId, const std::string &variable, int &type, std::string &value); void updateUserSetting(long userId, const std::string &variable, const std::string &value); @@ -111,9 +114,12 @@ class SQLite3Backend : public StorageBackend sqlite3_stmt *m_removeUserBuddies; sqlite3_stmt *m_removeUserSettings; sqlite3_stmt *m_removeUserBuddiesSettings; + sqlite3_stmt *m_removeBuddy; + sqlite3_stmt *m_removeBuddySettings; sqlite3_stmt *m_addBuddy; sqlite3_stmt *m_updateBuddy; sqlite3_stmt *m_updateBuddySetting; + sqlite3_stmt *m_getBuddySetting; sqlite3_stmt *m_getBuddies; sqlite3_stmt *m_getBuddiesSettings; sqlite3_stmt *m_setUserOnline; diff --git a/include/transport/storagebackend.h b/include/transport/storagebackend.h index f0a13df5b0f9a7dbade28d1b004a7dc84381c4da..5289010447dea048ab47ae4fb6b00abc1f934bc6 100644 --- a/include/transport/storagebackend.h +++ b/include/transport/storagebackend.h @@ -119,6 +119,9 @@ class StorageBackend virtual void updateBuddy(long userId, const BuddyInfo &buddyInfo) = 0; virtual void removeBuddy(long id) = 0; + virtual void getBuddySetting(long userId, long buddyId, const std::string &variable, int &type, std::string &value) = 0; + virtual void updateBuddySetting(long userId, long buddyId, const std::string &variable, int type, const std::string &value) = 0; + virtual void getUserSetting(long userId, const std::string &variable, int &type, std::string &value) = 0; virtual void updateUserSetting(long userId, const std::string &variable, const std::string &value) = 0; diff --git a/include/transport/transport.h b/include/transport/transport.h index 3d81307fff0a6e34aab2a13c50794e739da78694..e6f0610d3dd0fc7660fe7db00009efcd8b8bb2a7 100644 --- a/include/transport/transport.h +++ b/include/transport/transport.h @@ -48,7 +48,6 @@ namespace Transport { // class StorageBackend; class DiscoInfoResponder; - class DiscoItemsResponder; class Factory; class UserRegistry; @@ -188,7 +187,6 @@ namespace Transport { Transport::UserRegistry *m_userRegistry; StorageBackend *m_storageBackend; DiscoInfoResponder *m_discoInfoResponder; - DiscoItemsResponder *m_discoItemsResponder; int m_reconnectCount; Config* m_config; std::string m_protocol; diff --git a/munin/spectrum2_ b/munin/spectrum2_ index 5f13e46f9ee0a6fb3a519a36f9e75ae28c9ded60..5b81afddec20de5784017f269f8ea012b282fc0f 100755 --- a/munin/spectrum2_ +++ b/munin/spectrum2_ @@ -1,166 +1,240 @@ -#!/usr/bin/perl - -# config: -# [spectrum2_*] -# env.admin_jid tradmin@host.org -# env.password jid_password -# env.transports icq.host.org xmpp.host.org +#!/usr/bin/python -Wignore::DeprecationWarning +# -*- coding: utf-8 -*- +# +# Wildcard-plugin to monitor spectrum transport usage through an XMPP-connection +# sending Statistics Gathering (XEP-0039 [1]) packets. Depending on the suffix, +# the plugin monitors one specific characteristic of one or more spectrum +# instances. +# +# Current suffixes are: +# spectrum_uptime (monitor uptime of transports) +# spectrum_registered (how many users are registered to the transport) +# spectrum_online (how many users are online) +# spectarm_contacts_registered +# spectrum_contacts_online (same as above, only for the legacy network) +# spectrum_messages (how many messages have been sent over this transport) +# spectrum_memory (how much memory the transport consumes) +# +# Configuration: +# You need to configure this plugin (just like any other plugin) in +# plugin-conf.d/munin-node. +# You have to configure the plugin to run as user and group "spectrum". +# +# By default, the plugin monitors all instances configured in a config-file +# in /etc/spectrum. If you use a different directory, you can specify the +# environment-variable "base". If you do not want to monitor all instances, +# you can give an explicit listing of the corresponding configuration files +# with the environment variable "cfgs". +# +# Here is an example of a configuration. Note again that you can ommit both +# env.cfgs and env.base: +# +# [spectrum_*] +# user spectrum +# group spectrum +# env.cfgs xmpp.example.com.cfg,irc.example.com.cfg +# env.base /etc/spectrum +# +# Author: +# Mathias Ertl +# +# Changelog: +# 2.0: Port to config_interface local socket +# 1.1: Suffixes that aggregate multiple values no longer show the individual +# values by default. This can be overridden by setting the "verbose" +# env-variable to any non-empty string. +# 1.0: Initial version # -# symlinks: -# spectrum2_backends spectrum2_memory spectrum2_users spectrum2_messages spectrum2_messages_sec +# [1] http://xmpp.org/extensions/xep-0039.html # +# Copyright (c) 2009 Mathias Ertl. # -use AnyEvent; -use AnyEvent::XMPP::Client; -use AnyEvent::XMPP::Component; -use AnyEvent::XMPP::Ext::Disco; -use AnyEvent::XMPP::Ext::Version; -use AnyEvent::XMPP::Namespaces qw/xmpp_ns/; -use AnyEvent::XMPP::Util qw/simxml/; -use XML::Simple; -use Time::HiRes qw ( setitimer ITIMER_REAL time ); -use strict; -$|=1; - -$SIG{ALRM} = sub { exit; }; -setitimer(ITIMER_REAL, 30, 1); - - -my %config=( - users => { - title=>'Buddies online', - vlabel=>'users', - info=>'Number of users that currently use the spectrum transports.', - command=>'online_users_count', - base=>'--base 1000', - x=>'1', - }, - backends => { - title=>'Backends running', - vlabel=>'backends', - info=>'Number of backends that currently running.', - command=>'backends_count', - base=>'--base 1000', - x=>'1', - }, - memory => { - title=>'Memory usage of transports', - vlabel=>'megabytes', - info=>'Memory usage of spectrum transports.', - command=>'used_memory', - base=>'--base 1024', - x=>'1024', - }, - messages => { - title=>'Messages send over transport', - vlabel=>'messages', - info=>'Messages send over spectrum transports.', - command=>'', - base=>'--base 1000', - x=>'1', - }, - messages_sec => { - title=>'Messages send over transport', - vlabel=>'messages/sec', - info=>'Messages send per second over spectrum transports.', - command=>'', - base=>'--base 1000', - x=>'1', - }, -); -my @queue=('_out','_in'); -$0 =~ /spectrum2_(.+)*$/; -my $func = $1; -exit 2 unless defined $func; -my %tr; -my $count=0; - foreach (split(' ',$ENV{'transports'})){ - if ($func=~/messages/) - { - $tr{$_."_in"}=$count; - $count++; - $tr{$_."_out"}=$count; - $count++; - } - else - { - $tr{$_}=$count; - $count++; - } - } - -if (exists $ARGV[0] and $ARGV[0] eq "config") -{ - print "graph_title ".$config{$func}->{'title'}."\n"; - print "graph_vlabel ".$config{$func}->{'vlabel'}."\n"; - print "graph_category spectrum2\n"; - foreach (keys (%tr)){ - print "r".$tr{$_}.".label ".$_."\n"; - if ($func eq 'messages_sec') - { - print "r".$tr{$_}.".type DERIVE\n"; - print "r".$tr{$_}.".min 0\n"; - } - } - print "graph_args ".$config{$func}->{'base'}."\n"; - print "graph_info ".$config{$func}->{'info'}."\n"; - exit 0; -} - -binmode( STDOUT); -my $xs=new XML::Simple; -my $cl=AnyEvent::XMPP::Client->new(debug=>0); -my $j=AnyEvent->condvar; -$cl->add_account($ENV{'admin_jid'}.'/'.time,$ENV{'password'}); -$cl->reg_cb( - session_ready => \&cl_sess, - disconnect => \&cl_disc, - message => \&cl_msg, -); -$cl->start; -$j->wait; - - -sub cl_disc -{ -my ($cl,$acc,$h,$p,$reas)=@_; - print "disc ($h:$p) $reas\n"; -} -sub cl_sess -{ - my($cl,$acc)=@_; - foreach (keys (%tr)){ - if ($func=~/messages/) - { - if (s/_in$//) - { - $cl->send_message("messages_from_xmpp",$_,undef,'chat'); - }; - if (s/_out$//) - { - $cl->send_message("messages_to_xmpp",$_,undef,'chat'); - } - } - else - { - $cl->send_message($config{$func}->{'command'},$_,undef,'chat'); - } - } -} -sub cl_msg -{ - my ($cl,$acc,$msg)=@_; - if ($func=~/messages/) - { - print "r".$tr{$msg->from.$queue[-1]}.".value ".int($msg->any_body/$config{$func}->{'x'})."\n"; - delete( $tr{$msg->from.$queue[-1]}); - pop(@queue); - if ($#queue==-1){@queue=("_out","_in");} - } - else - { - print "r".$tr{$msg->from}.".value ".int($msg->any_body/$config{$func}->{'x'})."\n"; - delete( $tr{$msg->from}); - } - exit if (scalar(keys %tr)==0); -} +# Permission to use, copy, and modify this software with or without fee +# is hereby granted, provided that this entire notice is included in +# all source code copies of any software which is or includes a copy or +# modification of this software. +# +# THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR +# IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY +# REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE +# MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR +# PURPOSE. +# +# Magic markers +#%# family=auto +#%# capabilities=autoconf suggest + +import sys +from subprocess import * + +# autoconf and suggest handling: +if len( sys.argv ) > 1: + if sys.argv[1] == 'autoconf': + print( 'yes' ) + sys.exit( 0 ) + elif sys.argv[1] == 'suggest': + print( """uptime +registered +online +contacts_total +contacts_online +messages +messages_sec +memory""" ) + sys.exit(0) + +import os, re + +# filter forbidden characters for munin fieldnames +def handle_field( string ): + for regexp in [ '^[^A-Za-z_]', '[^A-Za-z0-9_]' ]: + string = re.compile( regexp ).sub( '_', string ) + return string + +# get runtime variables +suffix = sys.argv[0].partition('_')[2] +verbose = os.environ.get( 'verbose' ) +proc = Popen(['spectrum2_manager', 'list'], stdout=PIPE, stderr=PIPE) +out, err = proc.communicate() +jids = out.split('\n')[:-1] + +# set variables based on wildcard +if suffix == 'uptime': + stat = { 'uptime': None } + title = "Uptime" + vlabel = "days" + info = '' + transformer = lambda value: float(value)/60.0/60.0/24.0 +elif suffix == 'backends_count': + stat = { "backends_count": None } + title = "Backends count" + vlabel = "backends" + info = 'Total number of backends.' +elif suffix == 'online': + stat = { 'online_users_count': None } + title = "Online users" + vlabel = "users" + info = 'Number of users that currently use the spectrum transports.' +elif suffix == 'messages': + stat = { 'messages_from_xmpp': 'from_xmpp', 'messages_to_xmpp': 'to_xmpp' } + title = "Messages send over transport" + vlabel = "messages" + info = 'Total messages send over spectrum since the last restart.' +elif suffix == 'messages_sec': + stat = { 'messages_from_xmpp': 'from_xmpp', 'messages_to_xmpp': 'to_xmpp' } + title = "Messages send over transport per second" + vlabel = "messages/sec" + info = 'Messages send per second over spectrum transports.' +elif suffix == 'memory': + stat = { 'used_memory': None } + title = "Memory usage of transports" + vlabel = "megabytes" + transformer = lambda value: float(value)/1024.0 + info = 'Memory usage of spectrum transports.' +elif suffix == 'average_memory_per_user': + stat = { 'average_memory_per_user': None } + title = "Average memory usage per user" + vlabel = "kilobytes" + #transformer = lambda value: float(value)/1024.0 + info = 'Memory usage of spectrum transports.' + +# handle config +if len( sys.argv ) > 1 and sys.argv[1] == 'config': + print( """graph_title %s +graph_args --base 1000 -l 0 +graph_scale no +graph_vlabel %s +graph_category spectrum2 +graph_info %s""" %(title, vlabel, info) ) + for jid in jids: + if len(stat) > 1: + # plugin monitors more than one field + label = jid + ' total' + fieldname = handle_field( label ) + print( '%s.label %s' %(fieldname, label) ) + if suffix == 'messages_sec': + print( '%s.type DERIVE' %(fieldname) ) + print( '%s.min 0' %(fieldname) ) + + # to not print individual fields if verbose is not set: + if not verbose: + continue + + for name, field_suffix in stat.iteritems(): + label = jid + if field_suffix: + label += ' ' + field_suffix + fieldname = handle_field( label ) + print( '%s.label %s' %(fieldname, label) ) + if suffix == 'messages_sec': + print( '%s.type DERIVE' %(fieldname) ) + print( '%s.min 0' %(fieldname) ) + sys.exit(0) + +# callback to handle incoming packets +def handler_fetch( packet ): + jid = str( packet.getFrom() ) + total = None + + for child in packet.getChildren()[0].getChildren(): + label = jid + value = child.getAttr( 'value' ) + if len( stat ) > 1: + if total == None: + total = int( value ) + else: + total += int( value ) + if not verbose: + continue + + field_suffix = stat[ child.getAttr( 'name' ) ] + if field_suffix: + label += ' ' + field_suffix + fieldname = handle_field( label ) + if 'transformer' in globals(): + value = transformer(value) + + print( '%s.value %s' %(fieldname, value) ) + + if total != None: + fieldname = handle_field( jid + ' total' ) + if 'transformer' in globals(): + total = transformer( total ) + print( '%s.value %s' %(fieldname, total) ) + +for jid in jids: + total = None + label = jid + for name in stat.keys(): + proc = Popen(['spectrum2_manager', jid, name], stdout=PIPE, stderr=PIPE) + out, err = proc.communicate() + out = out.replace('\n', '') + value = 0 + try: + value = int(out) + except: + print( "Error: %s" % (value)) + continue + + if len( stat ) > 1: + if total == None: + total = int( value ) + else: + total += int( value ) + if not verbose: + continue + + field_suffix = stat[ name ] + if field_suffix: + label += ' ' + field_suffix + fieldname = handle_field( label ) + if 'transformer' in globals(): + value = transformer(value) + + print( '%s.value %s' %(fieldname, value) ) + + if total != None: + fieldname = handle_field( jid + ' total' ) + if 'transformer' in globals(): + total = transformer( total ) + print( '%s.value %s' %(fieldname, total) ) diff --git a/plugin/cpp/networkplugin.cpp b/plugin/cpp/networkplugin.cpp index 43d82653731d0f0810c56af488c11fb75aaa3ee9..4455c37ed8629caf0a055920b492246dfd4ec49a 100644 --- a/plugin/cpp/networkplugin.cpp +++ b/plugin/cpp/networkplugin.cpp @@ -165,6 +165,19 @@ void NetworkPlugin::handleBuddyChanged(const std::string &user, const std::strin send(message); } +void NetworkPlugin::handleBuddyRemoved(const std::string &user, const std::string &buddyName) { + pbnetwork::Buddy buddy; + buddy.set_username(user); + buddy.set_buddyname(buddyName); + + std::string message; + buddy.SerializeToString(&message); + + WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_BUDDY_REMOVED); + + send(message); +} + void NetworkPlugin::handleBuddyTyping(const std::string &user, const std::string &buddyName) { pbnetwork::Buddy buddy; buddy.set_username(user); diff --git a/spectrum/src/main.cpp b/spectrum/src/main.cpp index 6ac952ed44173c89171e20393690a65d8a051327..14abb292b8f215a5052a42189314fadbf65a4bed 100644 --- a/spectrum/src/main.cpp +++ b/spectrum/src/main.cpp @@ -14,6 +14,9 @@ #include "transport/util.h" #include "transport/gatewayresponder.h" #include "transport/logging.h" +#include "transport/discoitemsresponder.h" +#include "transport/adhocmanager.h" +#include "transport/settingsadhoccommand.h" #include "Swiften/EventLoop/SimpleEventLoop.h" #include #include @@ -122,7 +125,8 @@ int main(int argc, char **argv) bool no_daemon = false; std::string config_file; std::string jid; - + + setlocale(LC_ALL, ""); #ifndef WIN32 if (signal(SIGINT, spectrum_sigint_handler) == SIG_ERR) { @@ -251,6 +255,16 @@ int main(int argc, char **argv) std::cerr << "Can't create service.working_dir directory " << CONFIG_STRING(&config, "service.working_dir") << ".\n"; return 1; } + // create directories + try { + boost::filesystem::create_directories( + boost::filesystem::path(CONFIG_STRING(&config, "service.portfile")).parent_path().string() + ); + } + catch (...) { + std::cerr << "Can't create service.portfile directory " << CONFIG_STRING(&config, "service.portfile") << ".\n"; + return 1; + } #ifndef WIN32 if (!CONFIG_STRING(&config, "service.group").empty() ||!CONFIG_STRING(&config, "service.user").empty() ) { @@ -267,6 +281,20 @@ int main(int argc, char **argv) chown(CONFIG_STRING(&config, "service.working_dir").c_str(), pw->pw_uid, gr->gr_gid); } + char backendport[20]; + FILE* port_file_f; + port_file_f = fopen(CONFIG_STRING(&config, "service.portfile").c_str(), "w+"); + if (port_file_f == NULL) { + std::cerr << "Cannot create port_file file " << CONFIG_STRING(&config, "service.portfile").c_str() << ". Exiting\n"; + exit(1); + } + sprintf(backendport,"%s\n",CONFIG_STRING(&config, "service.backend_port").c_str()); + if (fwrite(backendport,1,strlen(backendport),port_file_f) < strlen(backendport)) { + std::cerr << "Cannot write to port file " << CONFIG_STRING(&config, "service.portfile") << ". Exiting\n"; + exit(1); + } + fclose(port_file_f); + if (!no_daemon) { // daemonize daemonize(CONFIG_STRING(&config, "service.working_dir").c_str(), CONFIG_STRING(&config, "service.pidfile").c_str()); @@ -353,13 +381,24 @@ int main(int argc, char **argv) NetworkPluginServer plugin(&transport, &config, &userManager, &ftManager); - AdminInterface adminInterface(&transport, &userManager, &plugin, storageBackend); + AdminInterface adminInterface(&transport, &userManager, &plugin, storageBackend, userRegistration); + plugin.setAdminInterface(&adminInterface); + StatsResponder statsResponder(&transport, &userManager, &plugin, storageBackend); statsResponder.start(); GatewayResponder gatewayResponder(transport.getIQRouter(), &userManager); gatewayResponder.start(); + DiscoItemsResponder discoItemsResponder(&transport); + discoItemsResponder.start(); + + AdHocManager adhocmanager(&transport, &discoItemsResponder); + adhocmanager.start(); + + SettingsAdHocCommandFactory settings; + adhocmanager.addAdHocCommand(&settings); + eventLoop_ = &eventLoop; eventLoop.run(); diff --git a/spectrum/src/sample.cfg b/spectrum/src/sample.cfg index 4409be640ca1093f577eb86b35438e984ff675c4..1b4f17b9ed7255b6866bbc5b8222e7dd6245d6a8 100644 --- a/spectrum/src/sample.cfg +++ b/spectrum/src/sample.cfg @@ -13,13 +13,14 @@ admin_password=test #cert=server.pfx #patch to PKCS#12 certificate #cert_password=test #password to that certificate if any users_per_backend=10 -backend=../..//backends/swiften/spectrum2_swiften_backend +backend=../..//backends/libyahoo2/spectrum2_libyahoo2_backend #backend=../../backends/template/template_backend.py #protocol=prpl-jabber protocol=prpl-msn #protocol=any #protocol=prpl-icq working_dir=./ +portfile=$jid.port [backend] #default_avatar=catmelonhead.jpg diff --git a/spectrum_manager/src/CMakeLists.txt b/spectrum_manager/src/CMakeLists.txt index 5f93dd9c75076185a976b78758c327d28fb21f10..d4ba187497e6e761edbb6f4ba29aaca83b0e386a 100644 --- a/spectrum_manager/src/CMakeLists.txt +++ b/spectrum_manager/src/CMakeLists.txt @@ -1,9 +1,12 @@ cmake_minimum_required(VERSION 2.6) FILE(GLOB SRC *.cpp) -ADD_EXECUTABLE(spectrum2_manager ${SRC} ../../src/config.cpp ../../src/util.cpp) - -target_link_libraries(spectrum2_manager ${SWIFTEN_LIBRARY}) +ADD_EXECUTABLE(spectrum2_manager ${SRC} ../../src/config.cpp ../../src/util.cpp ${CMAKE_CURRENT_SOURCE_DIR}/../../include/transport/protocol.pb.cc) + +ADD_DEPENDENCIES(spectrum2_manager pb) +SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_SOURCE_DIR}/../../include/transport/protocol.pb.cc PROPERTIES GENERATED 1) + +target_link_libraries(spectrum2_manager ${SWIFTEN_LIBRARY} ${PROTOBUF_LIBRARIES}) INSTALL(TARGETS spectrum2_manager RUNTIME DESTINATION bin) diff --git a/spectrum_manager/src/main.cpp b/spectrum_manager/src/main.cpp index 0ab409801ef99b67c5e517f6373b9d8411de3e0d..32b542f0a0d8fc57f8656e9ad8c89135d21b84d4 100644 --- a/spectrum_manager/src/main.cpp +++ b/spectrum_manager/src/main.cpp @@ -1,5 +1,6 @@ #include "managerconfig.h" #include "transport/config.h" +#include "transport/protocol.pb.h" #include "Swiften/Swiften.h" #include "Swiften/EventLoop/SimpleEventLoop.h" @@ -12,6 +13,11 @@ #include "signal.h" #include "sys/wait.h" +#define WRAP(MESSAGE, TYPE) pbnetwork::WrapperMessage wrap; \ + wrap.set_type(TYPE); \ + wrap.set_payload(MESSAGE); \ + wrap.SerializeToString(&MESSAGE); + using namespace Transport; @@ -19,33 +25,7 @@ using namespace boost::filesystem; using namespace boost; -static int finished; -static std::string *m; - -static void handleDisconnected(Swift::Client *client, const boost::optional &, const std::string &server) { - std::cout << "[ DISCONNECTED ] " << server << "\n"; - if (--finished == 0) { - exit(0); - } -} - -static void handleConnected(Swift::Client *client, const std::string &server) { - boost::shared_ptr message(new Swift::Message()); - message->setTo(server); - message->setFrom(client->getJID()); - message->setBody(*m); - - client->sendMessage(message); -} - -static void handleMessageReceived(Swift::Client *client, Swift::Message::ref message, const std::string &server) { - std::string body = message->getBody(); - boost::replace_all(body, "\n", "\n[ OK ] " + server + ": "); - std::cout << "[ OK ] " << server << ": " << body << "\n"; - if (--finished == 0) { - exit(0); - } -} +std::string _data; static std::string searchForBinary(const std::string &binary) { std::vector path_list; @@ -103,6 +83,22 @@ static unsigned long exec_(std::string path, std::string config, std::string jid return (unsigned long) pid; } +static int getPort(const std::string &portfile) { + path p(portfile); + if (!exists(p) || is_directory(p)) { + return 0; + } + + std::ifstream f(p.string().c_str(), std::ios_base::in); + std::string port; + f >> port; + + if (port.empty()) + return 0; + + return boost::lexical_cast(port); +} + static int isRunning(const std::string &pidfile) { path p(pidfile); if (!exists(p) || is_directory(p)) { @@ -288,7 +284,75 @@ static int show_status(ManagerConfig *config) { return ret; } -static void ask_local_servers(ManagerConfig *config, Swift::BoostNetworkFactories &networkFactories, const std::string &message) { +static void handleDataRead(boost::shared_ptr m_conn, boost::shared_ptr data) { + _data += std::string(data->begin(), data->end()); + + // Parse data while there are some + while (_data.size() != 0) { + // expected_size of wrapper message + unsigned int expected_size; + + // if data is >= 4, we have whole header and we can + // read expected_size. + if (_data.size() >= 4) { + expected_size = *((unsigned int*) &_data[0]); + expected_size = ntohl(expected_size); + // If we don't have whole wrapper message, wait for next + // handleDataRead call. + if (_data.size() - 4 < expected_size) + return; + } + else { + return; + } + + // Parse wrapper message and erase it from buffer. + pbnetwork::WrapperMessage wrapper; + if (wrapper.ParseFromArray(&_data[4], expected_size) == false) { + std::cout << "PARSING ERROR " << expected_size << "\n"; + _data.erase(_data.begin(), _data.begin() + 4 + expected_size); + continue; + } + _data.erase(_data.begin(), _data.begin() + 4 + expected_size); + + if (wrapper.type() == pbnetwork::WrapperMessage_Type_TYPE_QUERY) { + pbnetwork::BackendConfig payload; + if (payload.ParseFromString(wrapper.payload()) == false) { + std::cout << "PARSING ERROR\n"; + // TODO: ERROR + continue; + } + + std::cout << payload.config() << "\n"; + exit(0); + } + } +} + +static void handleConnected(boost::shared_ptr m_conn, const std::string &msg, bool error) { + if (error) { + std::cerr << "Can't connect the server\n"; + exit(50); + } + else { + pbnetwork::BackendConfig m; + m.set_config(msg); + + std::string message; + m.SerializeToString(&message); + + WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_QUERY); + + uint32_t size = htonl(message.size()); + char *header = (char *) &size; + + + // send header together with wrapper message + m_conn->write(Swift::createSafeByteArray(std::string(header, 4) + message)); + } +} + +static void ask_local_server(ManagerConfig *config, Swift::BoostNetworkFactories &networkFactories, const std::string &jid, const std::string &message) { path p(CONFIG_STRING(config, "service.config_directory")); try { @@ -302,6 +366,7 @@ static void ask_local_servers(ManagerConfig *config, Swift::BoostNetworkFactorie exit(7); } + bool found = false; directory_iterator end_itr; for (directory_iterator itr(p); itr != end_itr; ++itr) { if (is_regular(itr->path()) && extension(itr->path()) == ".cfg") { @@ -311,20 +376,66 @@ static void ask_local_servers(ManagerConfig *config, Swift::BoostNetworkFactorie continue; } - if (CONFIG_VECTOR(&cfg, "service.admin_jid").empty() || CONFIG_STRING(&cfg, "service.admin_password").empty()) { - std::cerr << itr->path().string() << ": service.admin_jid or service.admin_password empty. This server can't be queried over XMPP.\n"; + if (CONFIG_STRING(&cfg, "service.jid") != jid) { continue; } - finished++; - Swift::Client *client = new Swift::Client(CONFIG_VECTOR(&cfg, "service.admin_jid")[0], CONFIG_STRING(&cfg, "service.admin_password"), &networkFactories); - client->setAlwaysTrustCertificates(); - client->onConnected.connect(boost::bind(&handleConnected, client, CONFIG_STRING(&cfg, "service.jid"))); - client->onDisconnected.connect(bind(&handleDisconnected, client, _1, CONFIG_STRING(&cfg, "service.jid"))); - client->onMessageReceived.connect(bind(&handleMessageReceived, client, _1, CONFIG_STRING(&cfg, "service.jid"))); - Swift::ClientOptions opt; - opt.allowPLAINWithoutTLS = true; - client->connect(opt); + found = true; + + boost::shared_ptr m_conn; + m_conn = networkFactories.getConnectionFactory()->createConnection(); + m_conn->onDataRead.connect(boost::bind(&handleDataRead, m_conn, _1)); + m_conn->onConnectFinished.connect(boost::bind(&handleConnected, m_conn, message, _1)); + m_conn->connect(Swift::HostAddressPort(Swift::HostAddress(CONFIG_STRING(&cfg, "service.backend_host")), getPort(CONFIG_STRING(&cfg, "service.portfile")))); + +// finished++; +// Swift::Client *client = new Swift::Client(CONFIG_VECTOR(&cfg, "service.admin_jid")[0], CONFIG_STRING(&cfg, "service.admin_password"), &networkFactories); +// client->setAlwaysTrustCertificates(); +// client->onConnected.connect(boost::bind(&handleConnected, client, CONFIG_STRING(&cfg, "service.jid"))); +// client->onDisconnected.connect(bind(&handleDisconnected, client, _1, CONFIG_STRING(&cfg, "service.jid"))); +// client->onMessageReceived.connect(bind(&handleMessageReceived, client, _1, CONFIG_STRING(&cfg, "service.jid"))); +// Swift::ClientOptions opt; +// opt.allowPLAINWithoutTLS = true; +// client->connect(opt); + } + } + + if (!found) { + std::cerr << "Config file for Spectrum instance with this JID was not found\n"; + exit(20); + } + } + catch (const filesystem_error& ex) { + std::cerr << "boost filesystem error\n"; + exit(5); + } +} + +static void show_list(ManagerConfig *config) { + path p(CONFIG_STRING(config, "service.config_directory")); + + try { + if (!exists(p)) { + std::cerr << "Config directory " << CONFIG_STRING(config, "service.config_directory") << " does not exist\n"; + exit(6); + } + + if (!is_directory(p)) { + std::cerr << "Config directory " << CONFIG_STRING(config, "service.config_directory") << " does not exist\n"; + exit(7); + } + + bool found = false; + directory_iterator end_itr; + for (directory_iterator itr(p); itr != end_itr; ++itr) { + if (is_regular(itr->path()) && extension(itr->path()) == ".cfg") { + Config cfg; + if (cfg.load(itr->path().string()) == false) { + std::cerr << "Can't load config file " << itr->path().string() << ". Skipping...\n"; + continue; + } + + std::cout << CONFIG_STRING(&cfg, "service.jid") << "\n"; } } } @@ -334,24 +445,71 @@ static void ask_local_servers(ManagerConfig *config, Swift::BoostNetworkFactorie } } +// static void ask_local_servers(ManagerConfig *config, Swift::BoostNetworkFactories &networkFactories, const std::string &message) { +// path p(CONFIG_STRING(config, "service.config_directory")); +// +// try { +// if (!exists(p)) { +// std::cerr << "Config directory " << CONFIG_STRING(config, "service.config_directory") << " does not exist\n"; +// exit(6); +// } +// +// if (!is_directory(p)) { +// std::cerr << "Config directory " << CONFIG_STRING(config, "service.config_directory") << " does not exist\n"; +// exit(7); +// } +// +// directory_iterator end_itr; +// for (directory_iterator itr(p); itr != end_itr; ++itr) { +// if (is_regular(itr->path()) && extension(itr->path()) == ".cfg") { +// Config cfg; +// if (cfg.load(itr->path().string()) == false) { +// std::cerr << "Can't load config file " << itr->path().string() << ". Skipping...\n"; +// continue; +// } +// +// if (CONFIG_VECTOR(&cfg, "service.admin_jid").empty() || CONFIG_STRING(&cfg, "service.admin_password").empty()) { +// std::cerr << itr->path().string() << ": service.admin_jid or service.admin_password empty. This server can't be queried over XMPP.\n"; +// continue; +// } +// +// finished++; +// Swift::Client *client = new Swift::Client(CONFIG_VECTOR(&cfg, "service.admin_jid")[0], CONFIG_STRING(&cfg, "service.admin_password"), &networkFactories); +// client->setAlwaysTrustCertificates(); +// client->onConnected.connect(boost::bind(&handleConnected, client, CONFIG_STRING(&cfg, "service.jid"))); +// client->onDisconnected.connect(bind(&handleDisconnected, client, _1, CONFIG_STRING(&cfg, "service.jid"))); +// client->onMessageReceived.connect(bind(&handleMessageReceived, client, _1, CONFIG_STRING(&cfg, "service.jid"))); +// Swift::ClientOptions opt; +// opt.allowPLAINWithoutTLS = true; +// client->connect(opt); +// } +// } +// } +// catch (const filesystem_error& ex) { +// std::cerr << "boost filesystem error\n"; +// exit(5); +// } +// } + int main(int argc, char **argv) { ManagerConfig config; std::string config_file; - std::string command; + std::vector command; boost::program_options::variables_map vm; - boost::program_options::options_description desc("Usage: spectrum [OPTIONS] \nCommands:\n" + boost::program_options::options_description desc("Usage: spectrum [OPTIONS] \n" + " spectrum [OPTIONS] \nCommands:\n" " start - start all local Spectrum2 instances\n" - " stop - stop all local Spectrum2 instances\n" + " stop - stop all local Spectrum2 instances\n" " status - status of local Spectrum2 instances\n" - " - send command to all local + remote Spectrum2 instances and print output\n" + " - send command to local Spectrum2 instance and print output\n" "Allowed options"); desc.add_options() ("help,h", "Show help output") ("config,c", boost::program_options::value(&config_file)->default_value("/etc/spectrum2/spectrum_manager.cfg"), "Spectrum manager config file") - ("command", boost::program_options::value(&command)->default_value(""), "Command") + ("command", boost::program_options::value >(&command), "Command") ; try { @@ -388,37 +546,35 @@ int main(int argc, char **argv) return 1; } - if (command == "start") { + if (command[0] == "start") { start_all_instances(&config); } - else if (command == "stop") { + else if (command[0] == "stop") { stop_all_instances(&config); } - else if (command == "status") { + else if (command[0] == "status") { return show_status(&config); } + else if (command[0] == "list") { + show_list(&config); + } else { + if (command.size() < 2) { + std::cout << desc << "\n"; + return 11; + } Swift::SimpleEventLoop eventLoop; Swift::BoostNetworkFactories networkFactories(&eventLoop); - std::string message = command; - m = &message; - - ask_local_servers(&config, networkFactories, message); - - std::vector servers = CONFIG_VECTOR(&config, "servers.server"); - for (std::vector::const_iterator it = servers.begin(); it != servers.end(); it++) { - finished++; - Swift::Client *client = new Swift::Client(CONFIG_STRING(&config, "service.admin_username") + "@" + *it, CONFIG_STRING(&config, "service.admin_password"), &networkFactories); - client->setAlwaysTrustCertificates(); - client->onConnected.connect(boost::bind(&handleConnected, client, *it)); - client->onDisconnected.connect(bind(&handleDisconnected, client, _1, *it)); - client->onMessageReceived.connect(bind(&handleMessageReceived, client, _1, *it)); - Swift::ClientOptions opt; - opt.allowPLAINWithoutTLS = true; - client->connect(opt); - // std::cout << *it << "\n"; - } + std::string jid = command[0]; + command.erase(command.begin()); + std::string cmd = boost::algorithm::join(command, " "); + + ask_local_server(&config, networkFactories, jid, cmd); +// std::string message = command; +// m = &message; + +// ask_local_server(&config, networkFactories, message); eventLoop.run(); } diff --git a/src/adhoccommand.cpp b/src/adhoccommand.cpp new file mode 100644 index 0000000000000000000000000000000000000000..badc5dc21d4d90e2be9b3aa33c1fe07c7f7fa94d --- /dev/null +++ b/src/adhoccommand.cpp @@ -0,0 +1,52 @@ +/** + * XMPP - libpurple transport + * + * Copyright (C) 2012, Jan Kaluza + * + * 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 Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#include "transport/adhoccommand.h" +#include "transport/adhoccommandfactory.h" +#include "transport/conversation.h" +#include "transport/usermanager.h" +#include "transport/buddy.h" +#include "transport/factory.h" +#include "transport/user.h" +#include "transport/logging.h" + +namespace Transport { + +DEFINE_LOGGER(logger, "AdHocCommand"); + +AdHocCommand::AdHocCommand(Component *component, const Swift::JID &initiator, const Swift::JID &to) { + m_component = component; + m_initiator = initiator; + m_to = to; + + std::string bucket = "abcdefghijklmnopqrstuvwxyz"; + for (int i = 0; i < 32; i++) { + m_id += bucket[rand() % bucket.size()]; + } +} + +AdHocCommand::~AdHocCommand() { +} + +void AdHocCommand::addFormField(Swift::FormField::ref field) { + m_fields.push_back(field); +} + +} diff --git a/src/adhocmanager.cpp b/src/adhocmanager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..664b421ed327479000f5a06b9e66f07c1b5596f0 --- /dev/null +++ b/src/adhocmanager.cpp @@ -0,0 +1,163 @@ +/** + * XMPP - libpurple transport + * + * Copyright (C) 2012, Jan Kaluza + * + * 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 Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#include "transport/adhocmanager.h" +#include "transport/adhoccommandfactory.h" +#include "transport/discoitemsresponder.h" +#include "transport/conversation.h" +#include "transport/usermanager.h" +#include "transport/buddy.h" +#include "transport/factory.h" +#include "transport/user.h" +#include "transport/logging.h" + +namespace Transport { + +DEFINE_LOGGER(logger, "AdHocManager"); + +AdHocManager::AdHocManager(Component *component, DiscoItemsResponder *discoItemsResponder) : Swift::Responder(component->getIQRouter()){ + m_component = component; + m_discoItemsResponder = discoItemsResponder; + + m_collectTimer = m_component->getNetworkFactories()->getTimerFactory()->createTimer(20); + m_collectTimer->onTick.connect(boost::bind(&AdHocManager::removeOldSessions, this)); + m_collectTimer->start(); +} + +AdHocManager::~AdHocManager() { + m_collectTimer->stop(); + stop(); +} + +void AdHocManager::start() { + Swift::Responder::start(); +} + +void AdHocManager::stop() { + Swift::Responder::stop(); + + for (SessionsMap::iterator it = m_sessions.begin(); it != m_sessions.end(); it++) { + std::vector candidates; + for (CommandsMap::iterator ct = it->second.begin(); ct != it->second.end(); ct++) { + delete ct->second; + } + } + + m_sessions.clear(); +} + +void AdHocManager::addAdHocCommand(AdHocCommandFactory *factory) { + if (m_factories.find(factory->getNode()) != m_factories.end()) { + LOG4CXX_ERROR(logger, "Command with node " << factory->getNode() << " is already registered. Ignoring this attempt."); + return; + } + + m_factories[factory->getNode()] = factory; + m_discoItemsResponder->addAdHocCommand(factory->getNode(), factory->getName()); +} + +void AdHocManager::removeOldSessions() { + unsigned long removedCommands = 0; + time_t now = time(NULL); + + std::vector toRemove; + for (SessionsMap::iterator it = m_sessions.begin(); it != m_sessions.end(); it++) { + std::vector candidates; + for (CommandsMap::iterator ct = it->second.begin(); ct != it->second.end(); ct++) { + if (now - ct->second->getLastActivity() > 15*60) { + candidates.push_back(it->first); + delete ct->second; + removedCommands++; + } + } + + BOOST_FOREACH(std::string &key, candidates) { + it->second.erase(key); + } + + if (it->second.empty()) { + toRemove.push_back(it->first); + } + } + + BOOST_FOREACH(std::string &key, toRemove) { + m_sessions.erase(key); + } + + if (removedCommands > 0) { + LOG4CXX_INFO(logger, "Removed " << removedCommands << " old commands sessions."); + } +} + +bool AdHocManager::handleGetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr payload) { + return false; +} + +bool AdHocManager::handleSetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr payload) { + AdHocCommand *command = NULL; + // Try to find AdHocCommand according to 'from' and session_id + if (m_sessions.find(from) != m_sessions.end() && m_sessions[from].find(payload->getSessionID()) != m_sessions[from].end()) { + command = m_sessions[from][payload->getSessionID()]; + } + // Check if we can create command with this node + else if (m_factories.find(payload->getNode()) != m_factories.end()) { + command = m_factories[payload->getNode()]->createAdHocCommand(m_component, from, to); + m_sessions[from][command->getId()] = command; + LOG4CXX_INFO(logger, from.toString() << ": Started new AdHoc command session with node " << payload->getNode()); + } + else { + LOG4CXX_INFO(logger, from.toString() << ": Unknown node " << payload->getNode() << ". Can't start AdHoc command session."); + sendError(from, id, Swift::ErrorPayload::BadRequest, Swift::ErrorPayload::Modify); + return true; + } + + if (!command) { + LOG4CXX_ERROR(logger, from.toString() << ": createAdHocCommand for node " << payload->getNode() << " returned NULL pointer"); + sendError(from, id, Swift::ErrorPayload::BadRequest, Swift::ErrorPayload::Modify); + return true; + } + + boost::shared_ptr response = command->handleRequest(payload); + if (!response) { + LOG4CXX_ERROR(logger, from.toString() << ": handleRequest for node " << payload->getNode() << " returned NULL pointer"); + sendError(from, id, Swift::ErrorPayload::BadRequest, Swift::ErrorPayload::Modify); + return true; + } + + response->setSessionID(command->getId()); + + sendResponse(from, id, response); + + command->refreshLastActivity(); + + // Command completed, so we can remove it now + if (response->getStatus() == Swift::Command::Completed) { + m_sessions[from].erase(command->getId()); + if (m_sessions[from].empty()) { + m_sessions.erase(from); + } + delete command; + } + + + return true; +} + +} diff --git a/src/admininterface.cpp b/src/admininterface.cpp index db3c53a6478c19da6ef85a225fceedd162a80ad1..3b8a40d1791165437fdb6e3303e58252d2583fe2 100644 --- a/src/admininterface.cpp +++ b/src/admininterface.cpp @@ -27,6 +27,7 @@ #include "transport/usermanager.h" #include "transport/networkpluginserver.h" #include "transport/logging.h" +#include "transport/userregistration.h" #include "storageresponder.h" #include "transport/memoryusage.h" #include @@ -43,11 +44,13 @@ static std::string getArg(const std::string &body) { return body.substr(body.find(" ") + 1); } -AdminInterface::AdminInterface(Component *component, UserManager *userManager, NetworkPluginServer *server, StorageBackend *storageBackend) { +AdminInterface::AdminInterface(Component *component, UserManager *userManager, NetworkPluginServer *server, StorageBackend *storageBackend, UserRegistration *userRegistration) { m_component = component; m_storageBackend = storageBackend; m_userManager = userManager; m_server = server; + m_userRegistration = userRegistration; + m_start = time(NULL); m_component->getStanzaChannel()->onMessageReceived.connect(bind(&AdminInterface::handleMessageReceived, this, _1)); } @@ -55,23 +58,8 @@ AdminInterface::AdminInterface(Component *component, UserManager *userManager, N AdminInterface::~AdminInterface() { } -void AdminInterface::handleMessageReceived(Swift::Message::ref message) { - if (!message->getTo().getNode().empty()) - return; - - std::vector const &x = CONFIG_VECTOR(m_component->getConfig(),"service.admin_jid"); - if (std::find(x.begin(), x.end(), message->getFrom().toBare().toString()) == x.end()) { - LOG4CXX_WARN(logger, "Message not from admin user, but from " << message->getFrom().toBare().toString()); - return; - - } - - // Ignore empty messages - if (message->getBody().empty()) { - return; - } - - LOG4CXX_INFO(logger, "Message from admin received"); +void AdminInterface::handleQuery(Swift::Message::ref message) { + LOG4CXX_INFO(logger, "Message from admin received: '" << message->getBody() << "'"); message->setTo(message->getFrom()); message->setFrom(m_component->getJID()); @@ -80,6 +68,9 @@ void AdminInterface::handleMessageReceived(Swift::Message::ref message) { int backends = m_server->getBackendCount(); message->setBody("Running (" + boost::lexical_cast(users) + " users connected using " + boost::lexical_cast(backends) + " backends)"); } + else if (message->getBody() == "uptime") { + message->setBody(boost::lexical_cast(time(0) - m_start)); + } else if (message->getBody() == "online_users") { std::string lst; const std::map &users = m_userManager->getUsers(); @@ -259,6 +250,9 @@ void AdminInterface::handleMessageReceived(Swift::Message::ref message) { } message->setBody(lst); } + else if (message->getBody() == "crashed_backends_count") { + message->setBody(boost::lexical_cast(m_server->getCrashedBackends().size())); + } else if (message->getBody() == "messages_from_xmpp") { int msgCount = m_userManager->getMessagesToBackend(); message->setBody(boost::lexical_cast(msgCount)); @@ -267,22 +261,68 @@ void AdminInterface::handleMessageReceived(Swift::Message::ref message) { int msgCount = m_userManager->getMessagesToXMPP(); message->setBody(boost::lexical_cast(msgCount)); } + else if (message->getBody().find("register ") == 0 && m_userRegistration) { + std::string body = message->getBody(); + std::vector args; + boost::split(args, body, boost::is_any_of(" ")); + if (args.size() == 4) { + UserInfo res; + res.jid = args[1]; + res.uin = args[2]; + res.password = args[3]; + res.language = "en"; + res.encoding = "utf-8"; + res.vip = 0; + + if (m_userRegistration->registerUser(res)) { + message->setBody("User registered."); + } + else { + message->setBody("Registration failed: User is already registered"); + } + } + else { + message->setBody("Bad argument count. See 'help'."); + } + } + else if (message->getBody().find("unregister ") == 0 && m_userRegistration) { + std::string body = message->getBody(); + std::vector args; + boost::split(args, body, boost::is_any_of(" ")); + if (args.size() == 2) { + if (m_userRegistration->unregisterUser(args[1])) { + message->setBody("User '" + args[1] + "' unregistered."); + } + else { + message->setBody("Unregistration failed: User '" + args[1] + "' is not registered"); + } + } + else { + message->setBody("Bad argument count. See 'help'."); + } + } else if (message->getBody().find("help") == 0) { std::string help; help += "General:\n"; help += " status - shows instance status\n"; help += " reload - Reloads config file\n"; + help += " uptime - returns ptime in seconds\n"; help += "Users:\n"; help += " online_users - returns list of all online users\n"; help += " online_users_count - number of online users\n"; help += " online_users_per_backend - shows online users per backends\n"; help += " has_online_user - returns 1 if user is online\n"; + if (m_userRegistration) { + help += " register - registers the new user\n"; + help += " unregister - unregisters existing user\n"; + } help += "Messages:\n"; help += " messages_from_xmpp - get number of messages received from XMPP users\n"; help += " messages_to_xmpp - get number of messages sent to XMPP users\n"; help += "Backends:\n"; help += " backends_count - number of active backends\n"; help += " crashed_backends - returns IDs of crashed backends\n"; + help += " crashed_backends_count - returns number of crashed backends\n"; help += "Memory:\n"; help += " res_memory - Total RESident memory spectrum2 and its backends use in KB\n"; help += " shr_memory - Total SHaRed memory spectrum2 backends share together in KB\n"; @@ -299,6 +339,25 @@ void AdminInterface::handleMessageReceived(Swift::Message::ref message) { else { message->setBody("Unknown command. Try \"help\""); } +} + +void AdminInterface::handleMessageReceived(Swift::Message::ref message) { + if (!message->getTo().getNode().empty()) + return; + + std::vector const &x = CONFIG_VECTOR(m_component->getConfig(),"service.admin_jid"); + if (std::find(x.begin(), x.end(), message->getFrom().toBare().toString()) == x.end()) { + LOG4CXX_WARN(logger, "Message not from admin user, but from " << message->getFrom().toBare().toString()); + return; + + } + + // Ignore empty messages + if (message->getBody().empty()) { + return; + } + + handleQuery(message); m_component->getStanzaChannel()->sendMessage(message); } diff --git a/src/config.cpp b/src/config.cpp index f9b2a1031dbc36035842925ee66a0ba7d976e2a3..986a00fa58a1e0eea89794781988daa38fc3e720 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -78,6 +78,7 @@ bool Config::load(std::istream &ifs, boost::program_options::options_description ("service.backend", value()->default_value("libpurple_backend"), "Backend") ("service.protocol", value()->default_value(""), "Protocol") ("service.pidfile", value()->default_value("/var/run/spectrum2/$jid.pid"), "Full path to pid file") + ("service.portfile", value()->default_value("/var/run/spectrum2/$jid.port"), "File to store backend_port to. It's used by spectrum2_manager.") ("service.working_dir", value()->default_value("/var/lib/spectrum2/$jid"), "Working dir") ("service.allowed_servers", value >()->multitoken(), "Only users from these servers can connect") ("service.server_mode", value()->default_value(false), "True if Spectrum should behave as server") @@ -93,6 +94,7 @@ bool Config::load(std::istream &ifs, boost::program_options::options_description ("service.memory_collector_time", value()->default_value(0), "Time in seconds after which backend with most memory is set to die.") ("service.more_resources", value()->default_value(false), "Allow more resources to be connected in server mode at the same time.") ("service.enable_privacy_lists", value()->default_value(true), "") + ("service.enable_xhtml", value()->default_value(true), "") ("vhosts.vhost", value >()->multitoken(), "") ("identity.name", value()->default_value("Spectrum 2 Transport"), "Name showed in service discovery.") ("identity.category", value()->default_value("gateway"), "Disco#info identity category. 'gateway' by default.") @@ -136,6 +138,7 @@ bool Config::load(std::istream &ifs, boost::program_options::options_description bool found_working = false; bool found_pidfile = false; + bool found_portfile = false; bool found_backend_port = false; bool found_database = false; std::string jid = ""; @@ -161,6 +164,9 @@ bool Config::load(std::istream &ifs, boost::program_options::options_description else if (opt.string_key == "service.pidfile") { found_pidfile = true; } + else if (opt.string_key == "service.portfile") { + found_portfile = true; + } else if (opt.string_key == "database.database") { found_database = true; } @@ -176,6 +182,11 @@ bool Config::load(std::istream &ifs, boost::program_options::options_description value.push_back("/var/run/spectrum2/$jid.pid"); parsed.options.push_back(boost::program_options::basic_option("service.pidfile", value)); } + if (!found_portfile) { + std::vector value; + value.push_back("/var/run/spectrum2/$jid.port"); + parsed.options.push_back(boost::program_options::basic_option("service.portfile", value)); + } if (!found_backend_port) { std::vector value; std::string p = boost::lexical_cast(getRandomPort(_jid.empty() ? jid : _jid)); @@ -190,7 +201,7 @@ bool Config::load(std::istream &ifs, boost::program_options::options_description BOOST_FOREACH(option &opt, parsed.options) { if (opt.unregistered) { - m_unregistered[opt.string_key] = opt.value[0]; + m_unregistered[opt.string_key] = variable_value(opt.value[0], false); } else if (opt.value[0].find("$jid") != std::string::npos) { boost::replace_all(opt.value[0], "$jid", jid); diff --git a/src/conversation.cpp b/src/conversation.cpp index 571a4cde4b3c3a804b3603d8deb007fe57dd2100..f599c8523e174dfc4c67934db22b8b791ee62acc 100644 --- a/src/conversation.cpp +++ b/src/conversation.cpp @@ -84,8 +84,13 @@ void Conversation::handleMessage(boost::shared_ptr &message, con if (legacyName.find_last_of("@") != std::string::npos) { legacyName.replace(legacyName.find_last_of("@"), 1, "%"); // OK } + + std::string n = nickname; + if (n.empty()) { + n = " "; + } message->setTo(m_jid); - message->setFrom(Swift::JID(legacyName, m_conversationManager->getComponent()->getJID().toBare(), nickname)); + message->setFrom(Swift::JID(legacyName, m_conversationManager->getComponent()->getJID().toBare(), n)); m_conversationManager->getComponent()->getStanzaChannel()->sendMessage(message); } } diff --git a/src/discoitemsresponder.cpp b/src/discoitemsresponder.cpp index 58940a20a746ee62194cd8f59f33b97fb053f6af..2365b27e7e0b7e47437c369ebe1c100eb272b5a8 100644 --- a/src/discoitemsresponder.cpp +++ b/src/discoitemsresponder.cpp @@ -18,32 +18,45 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ -#include "discoitemsresponder.h" +#include "transport/discoitemsresponder.h" #include #include #include "Swiften/Queries/IQRouter.h" -#include "Swiften/Elements/DiscoItems.h" #include "Swiften/Swiften.h" +#include "transport/transport.h" +#include "transport/logging.h" using namespace Swift; using namespace boost; namespace Transport { -DiscoItemsResponder::DiscoItemsResponder(Swift::IQRouter *router) : Swift::GetResponder(router) { +DEFINE_LOGGER(logger, "DiscoItemsResponder"); + +DiscoItemsResponder::DiscoItemsResponder(Component *component) : Swift::GetResponder(component->getIQRouter()) { + m_component = component; + m_commands = boost::shared_ptr(new DiscoItems()); + m_commands->setNode("http://jabber.org/protocol/commands"); } DiscoItemsResponder::~DiscoItemsResponder() { } +void DiscoItemsResponder::addAdHocCommand(const std::string &node, const std::string &name) { + m_commands->addItem(DiscoItems::Item(name, m_component->getJID(), node)); +} + + bool DiscoItemsResponder::handleGetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr info) { - // presence for transport - if (to.getNode().empty()) { + LOG4CXX_INFO(logger, "get request received with node " << info->getNode()); + if (info->getNode() == "http://jabber.org/protocol/commands") { + sendResponse(from, id, m_commands); + } + else if (to.getNode().empty()) { sendResponse(from, id, boost::shared_ptr(new DiscoItems())); } - // presence for buddy else { sendResponse(from, id, boost::shared_ptr(new DiscoItems())); } diff --git a/src/mysqlbackend.cpp b/src/mysqlbackend.cpp index 9bb5eaef76679f4d90feaec5b7c6ce8a40ed46d0..fd810c748cf90e5b7c3855bf39c4e2bd78f43f38 100644 --- a/src/mysqlbackend.cpp +++ b/src/mysqlbackend.cpp @@ -205,7 +205,6 @@ int MySQLBackend::Statement::execute() { m_offset = 0; m_resultOffset = 0; int ret; - if ((ret = mysql_stmt_execute(m_stmt)) != 0) { LOG4CXX_ERROR(logger, m_string << " " << mysql_stmt_error(m_stmt) << "; " << mysql_error(m_conn)); return mysql_stmt_errno(m_stmt); @@ -317,6 +316,10 @@ bool MySQLBackend::connect() { return false; } + if (!mysql_set_character_set(&m_conn, "utf8")) { + LOG4CXX_INFO(logger, "New client character set: " << mysql_character_set_name(&m_conn)); + } + createDatabase(); m_setUser = new Statement(&m_conn, "sssssbss", "INSERT INTO " + m_prefix + "users (jid, uin, password, language, encoding, last_login, vip) VALUES (?, ?, ?, ?, ?, NOW(), ?) ON DUPLICATE KEY UPDATE uin=?, password=?"); @@ -608,11 +611,11 @@ void MySQLBackend::updateUserSetting(long id, const std::string &variable, const } void MySQLBackend::beginTransaction() { - //exec("START TRANSACTION;"); + exec("START TRANSACTION;"); } void MySQLBackend::commitTransaction() { - //exec("COMMIT;"); + exec("COMMIT;"); } } diff --git a/src/networkpluginserver.cpp b/src/networkpluginserver.cpp index fdd68e68430889248a9671c73f3d25e7388c0c69..95d3f334fc94fba0e8e1c7673f0dd7d91baf4b09 100644 --- a/src/networkpluginserver.cpp +++ b/src/networkpluginserver.cpp @@ -32,6 +32,7 @@ #include "transport/rosterresponder.h" #include "transport/memoryreadbytestream.h" #include "transport/logging.h" +#include "transport/admininterface.h" #include "blockresponder.h" #include "Swiften/Swiften.h" #include "Swiften/Server/ServerStanzaChannel.h" @@ -204,7 +205,6 @@ static void handleBuddyPayload(LocalBuddy *buddy, const pbnetwork::Buddy &payloa // Set alias only if it's not empty. Backends are allowed to send empty alias if it has // not changed. if (!payload.alias().empty()) { - LOG4CXX_INFO(logger, "Setting alias to " << payload.alias() << " " << buddy->getAlias()); buddy->setAlias(payload.alias()); } @@ -228,6 +228,8 @@ NetworkPluginServer::NetworkPluginServer(Component *component, Config *config, U m_config = config; m_component = component; m_isNextLongRun = false; + m_adminInterface = NULL; + m_startingBackend = false; m_component->m_factory = new NetworkFactory(this); m_userManager->onUserCreated.connect(boost::bind(&NetworkPluginServer::handleUserCreated, this, _1)); m_userManager->onUserDestroyed.connect(boost::bind(&NetworkPluginServer::handleUserDestroyed, this, _1)); @@ -264,6 +266,7 @@ NetworkPluginServer::NetworkPluginServer(Component *component, Config *config, U LOG4CXX_INFO(logger, "Listening on host " << CONFIG_STRING(m_config, "service.backend_host") << " port " << CONFIG_STRING(m_config, "service.backend_port")); unsigned long pid = exec_(CONFIG_STRING(m_config, "service.backend"), CONFIG_STRING(m_config, "service.backend_host").c_str(), CONFIG_STRING(m_config, "service.backend_port").c_str(), m_config->getConfigFile().c_str()); + LOG4CXX_INFO(logger, "Tried to spawn first backend with pid " << pid); LOG4CXX_INFO(logger, "Backend should now connect to Spectrum2 instance. Spectrum2 won't accept any connection before backend connects"); #ifndef _WIN32 @@ -317,17 +320,15 @@ void NetworkPluginServer::handleNewClientConnection(boost::shared_ptrres = 0; client->init_res = 0; client->shared = 0; - client->willDie = 0; + // Until we receive first PONG from backend, backend is in willDie state. + client->willDie = true; // Backend does not accept new clients automatically if it's long-running client->acceptUsers = !m_isNextLongRun; client->longRun = m_isNextLongRun; - LOG4CXX_INFO(logger, "New" + (client->longRun ? std::string(" long-running") : "") + " backend " << client << " connected. Current backend count=" << (m_clients.size() + 1)); + m_startingBackend = false; - if (m_clients.size() == 0) { - // first backend connected, start the server, we're ready. - m_component->start(); - } + LOG4CXX_INFO(logger, "New" + (client->longRun ? std::string(" long-running") : "") + " backend " << client << " connected. Current backend count=" << (m_clients.size() + 1)); m_clients.push_front(client); @@ -339,28 +340,6 @@ void NetworkPluginServer::handleNewClientConnection(boost::shared_ptrpongReceived = -1; - - // some users are in queue waiting for this backend - while(!m_waitingUsers.empty()) { - // There's no new backend, so stop associating users and wait for new backend, - // which has been already spawned in getFreeClient() call. - if (getFreeClient() == NULL) - break; - - User *u = m_waitingUsers.front(); - m_waitingUsers.pop_front(); - - LOG4CXX_INFO(logger, "Associating " << u->getJID().toString() << " with this backend"); - - // associate backend with user - handleUserCreated(u); - - // connect user if it's ready - if (u->isReadyToConnect()) { - handleUserReadyToConnect(u); - } - - } } void NetworkPluginServer::handleSessionFinished(Backend *c) { @@ -509,8 +488,6 @@ void NetworkPluginServer::handleBuddyChangedPayload(const std::string &data) { if (!user) return; - LOG4CXX_INFO(logger, "HANDLE BUDDY CHANGED " << payload.buddyname() << "-" << payload.alias()); - LocalBuddy *buddy = (LocalBuddy *) user->getRosterManager()->getBuddy(payload.buddyname()); if (buddy) { handleBuddyPayload(buddy, payload); @@ -524,6 +501,20 @@ void NetworkPluginServer::handleBuddyChangedPayload(const std::string &data) { } } +void NetworkPluginServer::handleBuddyRemovedPayload(const std::string &data) { + pbnetwork::Buddy payload; + if (payload.ParseFromString(data) == false) { + // TODO: ERROR + return; + } + + User *user = m_userManager->getUser(payload.username()); + if (!user) + return; + + user->getRosterManager()->removeBuddy(payload.buddyname()); +} + void NetworkPluginServer::handleParticipantChangedPayload(const std::string &data) { pbnetwork::Participant payload; if (payload.ParseFromString(data) == false) { @@ -586,7 +577,7 @@ void NetworkPluginServer::handleConvMessagePayload(const std::string &data, bool } // Add xhtml-im payload. - if (!payload.xhtml().empty()) { + if (CONFIG_BOOL(m_config, "service.enable_xhtml") && !payload.xhtml().empty()) { msg->addPayload(boost::make_shared(payload.xhtml())); } @@ -740,6 +731,68 @@ void NetworkPluginServer::handleFTDataNeeded(Backend *b, unsigned long ftid) { send(b->connection, message); } +void NetworkPluginServer::handlePongReceived(Backend *c) { + // This could be first PONG from the backend + if (c->pongReceived == -1) { + // Backend is fully ready to handle requests + c->willDie = false; + + if (m_clients.size() == 1) { + // first backend connected, start the server, we're ready. + m_component->start(); + } + + // some users are in queue waiting for this backend + while(!m_waitingUsers.empty()) { + // There's no new backend, so stop associating users and wait for new backend, + // which has been already spawned in getFreeClient() call. + if (getFreeClient() == NULL) + break; + + User *u = m_waitingUsers.front(); + m_waitingUsers.pop_front(); + + LOG4CXX_INFO(logger, "Associating " << u->getJID().toString() << " with this backend"); + + // associate backend with user + handleUserCreated(u); + + // connect user if it's ready + if (u->isReadyToConnect()) { + handleUserReadyToConnect(u); + } + } + } + + c->pongReceived = true; +} + +void NetworkPluginServer::handleQueryPayload(Backend *b, const std::string &data) { + pbnetwork::BackendConfig payload; + if (payload.ParseFromString(data) == false) { + // TODO: ERROR + return; + } + + if (!m_adminInterface) { + return; + } + + boost::shared_ptr msg(new Swift::Message()); + msg->setBody(payload.config()); + m_adminInterface->handleQuery(msg); + + pbnetwork::BackendConfig vcard; + vcard.set_config(msg->getBody()); + + std::string message; + vcard.SerializeToString(&message); + + WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_QUERY); + + send(b->connection, message); +} + void NetworkPluginServer::handleDataRead(Backend *c, boost::shared_ptr data) { // Append data to buffer c->data.insert(c->data.end(), data->begin(), data->end()); @@ -790,7 +843,7 @@ void NetworkPluginServer::handleDataRead(Backend *c, boost::shared_ptrpongReceived = true; + handlePongReceived(c); break; case pbnetwork::WrapperMessage_Type_TYPE_PARTICIPANT_CHANGED: handleParticipantChangedPayload(wrapper.payload()); @@ -828,6 +881,12 @@ void NetworkPluginServer::handleDataRead(Backend *c, boost::shared_ptr toRemove; @@ -881,11 +943,26 @@ void NetworkPluginServer::pingTimeout() { // pong has been received OR backend just connected and did not have time to answer the ping // request. if ((*it)->pongReceived || (*it)->pongReceived == -1) { - sendPing((*it)); + // Don't send another ping if pongReceived == -1, because we've already sent one + // when registering backend. + if ((*it)->pongReceived) { + sendPing((*it)); + } } else { LOG4CXX_INFO(logger, "Disconnecting backend " << (*it) << " (ID=" << (*it)->id << "). PING response not received."); toRemove.push_back(*it); + +#ifndef WIN32 + // generate coredump for this backend to find out why it wasn't able to respond to PING + std::string pid = (*it)->id; + if (!pid.empty()) { + try { + kill(boost::lexical_cast(pid), SIGABRT); + } + catch (...) { } + } +#endif } if ((*it)->users.size() == 0) { @@ -1234,7 +1311,6 @@ void NetworkPluginServer::handleBuddyUpdated(Buddy *b, const Swift::RosterItemPa dynamic_cast(b)->setAlias(item.getName()); dynamic_cast(b)->setGroups(item.getGroups()); - user->getRosterManager()->storeBuddy(b); pbnetwork::Buddy buddy; buddy.set_username(user->getJID().toBare()); @@ -1412,8 +1488,9 @@ NetworkPluginServer::Backend *NetworkPluginServer::getFreeClient(bool acceptUser } // there's no free backend, so spawn one. - if (c == NULL) { + if (c == NULL && !m_startingBackend) { m_isNextLongRun = longRun; + m_startingBackend = true; exec_(CONFIG_STRING(m_config, "service.backend"), CONFIG_STRING(m_config, "service.backend_host").c_str(), CONFIG_STRING(m_config, "service.backend_port").c_str(), m_config->getConfigFile().c_str()); } diff --git a/src/rostermanager.cpp b/src/rostermanager.cpp index cdb13dbc6f73cd0d43c78a7a662ed73c069886e8..3d7534abf0942abeca77e5d01a5fc3fbdaa32925 100644 --- a/src/rostermanager.cpp +++ b/src/rostermanager.cpp @@ -99,6 +99,49 @@ void RosterManager::setBuddy(Buddy *buddy) { setBuddyCallback(buddy); } +void RosterManager::removeBuddy(const std::string &name) { + Buddy *buddy = getBuddy(name); + if (!buddy) { + LOG4CXX_WARN(logger, m_user->getJID().toString() << ": Tried to remove unknown buddy " << name); + return; + } + + if (m_component->inServerMode() || m_remoteRosterRequest) { + sendBuddyRosterRemove(buddy); + } + else { + sendBuddyUnsubscribePresence(buddy); + } + + if (m_rosterStorage) + m_rosterStorage->removeBuddy(buddy); + + unsetBuddy(buddy); + delete buddy; +} + +void RosterManager::sendBuddyRosterRemove(Buddy *buddy) { + Swift::RosterPayload::ref p = Swift::RosterPayload::ref(new Swift::RosterPayload()); + Swift::RosterItemPayload item; + item.setJID(buddy->getJID().toBare()); + item.setSubscription(Swift::RosterItemPayload::Remove); + + p->addItem(item); + + // In server mode we have to send pushes to all resources, but in gateway-mode we send it only to bare JID + if (m_component->inServerMode()) { + std::vector presences = m_component->getPresenceOracle()->getAllPresence(m_user->getJID().toBare()); + BOOST_FOREACH(Swift::Presence::ref presence, presences) { + Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(p, presence->getFrom(), m_component->getIQRouter()); + request->send(); + } + } + else { + Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(p, m_user->getJID().toBare(), m_component->getIQRouter()); + request->send(); + } +} + void RosterManager::sendBuddyRosterPush(Buddy *buddy) { // user can't receive anything in server mode if he's not logged in. // He will ask for roster later (handled in rosterreponsder.cpp) @@ -142,6 +185,20 @@ void RosterManager::sendBuddyRosterPush(Buddy *buddy) { } } +void RosterManager::sendBuddyUnsubscribePresence(Buddy *buddy) { + Swift::Presence::ref response = Swift::Presence::create(); + response->setTo(m_user->getJID()); + response->setFrom(buddy->getJID()); + response->setType(Swift::Presence::Unsubscribe); + m_component->getStanzaChannel()->sendPresence(response); + + response = Swift::Presence::create(); + response->setTo(m_user->getJID()); + response->setFrom(buddy->getJID()); + response->setType(Swift::Presence::Unsubscribed); + m_component->getStanzaChannel()->sendPresence(response); +} + void RosterManager::sendBuddySubscribePresence(Buddy *buddy) { Swift::Presence::ref response = Swift::Presence::create(); response->setTo(m_user->getJID()); @@ -458,7 +515,7 @@ void RosterManager::setStorageBackend(StorageBackend *storageBackend) { if (m_rosterStorage || !storageBackend) { return; } - m_rosterStorage = new RosterStorage(m_user, storageBackend); + RosterStorage *storage = new RosterStorage(m_user, storageBackend); std::list roster; storageBackend->getBuddies(m_user->getUserInfo().id, roster); @@ -469,6 +526,8 @@ void RosterManager::setStorageBackend(StorageBackend *storageBackend) { m_buddies[buddy->getName()] = buddy; onBuddySet(buddy); } + + m_rosterStorage = storage; } Swift::RosterPayload::ref RosterManager::generateRosterPayload() { diff --git a/src/rosterstorage.cpp b/src/rosterstorage.cpp index 30679cb9f5edf8b6730ce2677f408c364be46a8b..34a40b3a2bb4541f2161a96c39e7f5c1b94f8dc5 100644 --- a/src/rosterstorage.cpp +++ b/src/rosterstorage.cpp @@ -22,6 +22,9 @@ #include "transport/buddy.h" #include "transport/user.h" #include "transport/storagebackend.h" +#include "transport/logging.h" + +DEFINE_LOGGER(logger, "RosterStorage"); namespace Transport { @@ -85,7 +88,20 @@ RosterStorage::~RosterStorage() { m_storageTimer->stop(); } +void RosterStorage::removeBuddy(Buddy *buddy) { + if (buddy->getID() != -1) { + m_storageBackend->removeBuddy(buddy->getID()); + } +} + void RosterStorage::storeBuddy(Buddy *buddy) { + if (!buddy) { + return; + } + if (buddy->getName().empty()) { + return; + } + m_buddies[buddy->getName()] = buddy; m_storageTimer->start(); } @@ -129,6 +145,7 @@ bool RosterStorage::storeBuddies() { // } } + m_buddies.clear(); m_storageBackend->commitTransaction(); return true; } diff --git a/src/settingsadhoccommand.cpp b/src/settingsadhoccommand.cpp new file mode 100644 index 0000000000000000000000000000000000000000..00aacece68095a389c86cd22b7317e1b9131e47a --- /dev/null +++ b/src/settingsadhoccommand.cpp @@ -0,0 +1,79 @@ +/** + * XMPP - libpurple transport + * + * Copyright (C) 2012, Jan Kaluza + * + * 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 Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#include "transport/settingsadhoccommand.h" +#include "transport/conversation.h" +#include "transport/usermanager.h" +#include "transport/buddy.h" +#include "transport/factory.h" +#include "transport/user.h" +#include "transport/logging.h" + +namespace Transport { + +DEFINE_LOGGER(logger, "SettingsAdHocCommand"); + +SettingsAdHocCommand::SettingsAdHocCommand(Component *component, const Swift::JID &initiator, const Swift::JID &to) : AdHocCommand(component, initiator, to) { + m_state = Init; +} + +SettingsAdHocCommand::~SettingsAdHocCommand() { +} + +boost::shared_ptr SettingsAdHocCommand::getForm() { + boost::shared_ptr response(new Swift::Command("settings", m_id, Swift::Command::Executing)); + boost::shared_ptr form(new Swift::Form()); + + BOOST_FOREACH(Swift::FormField::ref field, m_fields) { + form->addField(field); + } + + response->setForm(form); + return response; +} + +boost::shared_ptr SettingsAdHocCommand::handleResponse(boost::shared_ptr payload) { + + + + boost::shared_ptr response; + response->setStatus(Swift::Command::Completed); + return response; +} + +boost::shared_ptr SettingsAdHocCommand::handleRequest(boost::shared_ptr payload) { + boost::shared_ptr response; + + switch (m_state) { + case Init: + response = getForm(); + m_state = WaitingForResponse; + break; + case WaitingForResponse: + response = handleResponse(payload); + break; + default: + break; + } + + return response; +} + +} diff --git a/src/sqlite3backend.cpp b/src/sqlite3backend.cpp index e9a11dac8b0251d4374288a34379169f5556e810..3de7371b0bddf798f3d93a765af1adecdd86ed23 100644 --- a/src/sqlite3backend.cpp +++ b/src/sqlite3backend.cpp @@ -88,6 +88,8 @@ SQLite3Backend::~SQLite3Backend(){ FINALIZE_STMT(m_removeUserBuddies); FINALIZE_STMT(m_removeUserSettings); FINALIZE_STMT(m_removeUserBuddiesSettings); + FINALIZE_STMT(m_removeBuddy); + FINALIZE_STMT(m_removeBuddySettings); FINALIZE_STMT(m_addBuddy); FINALIZE_STMT(m_updateBuddy); FINALIZE_STMT(m_getBuddies); @@ -96,6 +98,7 @@ SQLite3Backend::~SQLite3Backend(){ FINALIZE_STMT(m_setUserSetting); FINALIZE_STMT(m_updateUserSetting); FINALIZE_STMT(m_updateBuddySetting); + FINALIZE_STMT(m_getBuddySetting); FINALIZE_STMT(m_setUserOnline); FINALIZE_STMT(m_getOnlineUsers); sqlite3_close(m_db); @@ -122,11 +125,15 @@ bool SQLite3Backend::connect() { PREP_STMT(m_removeUserSettings, "DELETE FROM " + m_prefix + "users_settings WHERE user_id=?"); PREP_STMT(m_removeUserBuddiesSettings, "DELETE FROM " + m_prefix + "buddies_settings WHERE user_id=?"); + PREP_STMT(m_removeBuddy, "DELETE FROM " + m_prefix + "buddies WHERE id=?"); + PREP_STMT(m_removeBuddySettings, "DELETE FROM " + m_prefix + "buddies_settings WHERE buddy_id=?"); + PREP_STMT(m_addBuddy, "INSERT INTO " + m_prefix + "buddies (user_id, uin, subscription, groups, nickname, flags) VALUES (?, ?, ?, ?, ?, ?)"); PREP_STMT(m_updateBuddy, "UPDATE " + m_prefix + "buddies SET groups=?, nickname=?, flags=?, subscription=? WHERE user_id=? AND uin=?"); PREP_STMT(m_getBuddies, "SELECT id, uin, subscription, nickname, groups, flags FROM " + m_prefix + "buddies WHERE user_id=? ORDER BY id ASC"); PREP_STMT(m_getBuddiesSettings, "SELECT buddy_id, type, var, value FROM " + m_prefix + "buddies_settings WHERE user_id=? ORDER BY buddy_id ASC"); PREP_STMT(m_updateBuddySetting, "INSERT OR REPLACE INTO " + m_prefix + "buddies_settings (user_id, buddy_id, var, type, value) VALUES (?, ?, ?, ?, ?)"); + PREP_STMT(m_getBuddySetting, "SELECT type, value FROM " + m_prefix + "buddies_settings WHERE user_id=? AND buddy_id=? AND var=?"); PREP_STMT(m_getUserSetting, "SELECT type, value FROM " + m_prefix + "users_settings WHERE user_id=? AND var=?"); PREP_STMT(m_setUserSetting, "INSERT INTO " + m_prefix + "users_settings (user_id, var, type, value) VALUES (?,?,?,?)"); @@ -199,7 +206,11 @@ bool SQLite3Backend::exec(const std::string &query) { char *errMsg = 0; int rc = sqlite3_exec(m_db, query.c_str(), NULL, 0, &errMsg); if (rc != SQLITE_OK) { - LOG4CXX_ERROR(logger, errMsg << " during statement " << query); + // This error is OK, because we try to create buddies table every time + // to detect if DB is created properly. + if (errMsg != "table buddies already exists") { + LOG4CXX_ERROR(logger, errMsg << " during statement " << query); + } sqlite3_free(errMsg); return false; } @@ -401,6 +412,22 @@ bool SQLite3Backend::getBuddies(long id, std::list &roster) { return true; } +void SQLite3Backend::removeBuddy(long id) { + sqlite3_reset(m_removeBuddy); + sqlite3_bind_int(m_removeBuddy, 1, id); + if(sqlite3_step(m_removeBuddy) != SQLITE_DONE) { + LOG4CXX_ERROR(logger, "removeBuddy query"<< (sqlite3_errmsg(m_db) == NULL ? "" : sqlite3_errmsg(m_db))); + return; + } + + sqlite3_reset(m_removeBuddySettings); + sqlite3_bind_int(m_removeBuddySettings, 1, id); + if(sqlite3_step(m_removeBuddySettings) != SQLITE_DONE) { + LOG4CXX_ERROR(logger, "removeBuddySettings query"<< (sqlite3_errmsg(m_db) == NULL ? "" : sqlite3_errmsg(m_db))); + return; + } +} + bool SQLite3Backend::removeUser(long id) { sqlite3_reset(m_removeUser); sqlite3_bind_int(m_removeUser, 1, id); @@ -463,6 +490,31 @@ void SQLite3Backend::updateUserSetting(long id, const std::string &variable, con EXECUTE_STATEMENT(m_updateUserSetting, "m_updateUserSetting"); } +void SQLite3Backend::getBuddySetting(long userId, long buddyId, const std::string &variable, int &type, std::string &value) { + BEGIN(m_getBuddySetting); + BIND_INT(m_getBuddySetting, userId); + BIND_INT(m_getBuddySetting, buddyId); + BIND_STR(m_getBuddySetting, variable); + if(sqlite3_step(m_getBuddySetting) == SQLITE_ROW) { + type = GET_INT(m_getBuddySetting); + value = GET_STR(m_getBuddySetting); + } + + int ret; + while((ret = sqlite3_step(m_getBuddySetting)) == SQLITE_ROW) { + } +} + +void SQLite3Backend::updateBuddySetting(long userId, long buddyId, const std::string &variable, int type, const std::string &value) { + BEGIN(m_updateBuddySetting); + BIND_INT(m_updateBuddySetting, userId); + BIND_INT(m_updateBuddySetting, buddyId); + BIND_STR(m_updateBuddySetting, variable); + BIND_INT(m_updateBuddySetting, type); + BIND_STR(m_updateBuddySetting, value); + EXECUTE_STATEMENT(m_updateBuddySetting, "m_updateBuddySetting"); +} + void SQLite3Backend::beginTransaction() { exec("BEGIN TRANSACTION;"); } diff --git a/src/transport.cpp b/src/transport.cpp index 363e94c261141ff0bc3cad5a0393f717d0574643..f633b3648f536e01ffd189dbbf1bcbeec3d9f17b 100644 --- a/src/transport.cpp +++ b/src/transport.cpp @@ -27,7 +27,6 @@ #include "transport/userregistry.h" #include "transport/logging.h" #include "discoinforesponder.h" -#include "discoitemsresponder.h" #include "storageparser.h" #ifdef _MSC_VER #include @@ -162,9 +161,6 @@ Component::Component(Swift::EventLoop *loop, Swift::NetworkFactories *factories, m_discoInfoResponder = new DiscoInfoResponder(m_iqRouter, m_config); m_discoInfoResponder->start(); - m_discoItemsResponder = new DiscoItemsResponder(m_iqRouter); - m_discoItemsResponder->start(); - // // m_registerHandler = new SpectrumRegisterHandler(m_component); // m_registerHandler->start(); @@ -176,7 +172,6 @@ Component::~Component() { delete m_capsManager; delete m_capsMemoryStorage; delete m_discoInfoResponder; - delete m_discoItemsResponder; if (m_component) delete m_component; if (m_server) { @@ -209,6 +204,9 @@ void Component::setBuddyFeatures(std::list &features) { void Component::start() { if (m_component && !m_component->isAvailable()) { LOG4CXX_INFO(logger, "Connecting XMPP server " << CONFIG_STRING(m_config, "service.server") << " port " << CONFIG_INT(m_config, "service.port")); + if (CONFIG_INT(m_config, "service.port") == 5222) { + LOG4CXX_WARN(logger, "Port 5222 is usually used for client connections, not for component connections! Are you sure you are using right port?"); + } m_reconnectCount++; m_component->connect(CONFIG_STRING(m_config, "service.server"), CONFIG_INT(m_config, "service.port")); m_reconnectTimer->stop(); @@ -242,6 +240,7 @@ void Component::stop() { void Component::handleConnected() { onConnected(); m_reconnectCount = 0; + m_reconnectTimer->stop(); } void Component::handleServerStopped(boost::optional e) { diff --git a/src/usermanager.cpp b/src/usermanager.cpp index ee46277bd4f56a2f97623b94803a4f7f86f2d372..ff4bb6ddf941cfb1093737f3ba54feda7134dc3c 100644 --- a/src/usermanager.cpp +++ b/src/usermanager.cpp @@ -308,8 +308,16 @@ void UserManager::handleRemoveTimeout(const std::string jid, User *u, bool recon } void UserManager::handleMessageReceived(Swift::Message::ref message) { + if (message->getType() == Swift::Message::Error) { + return; + } + + if (message->getBody().empty()) { + return; + } + User *user = getUser(message->getFrom().toBare().toString()); - if (!user ){ + if (!user){ return; }