diff options
author | Vitaly Takmazov <vitalyster@gmail.com> | 2022-02-22 20:56:43 +0300 |
---|---|---|
committer | vitalyster <vitalyster@gmail.com> | 2022-02-23 14:02:31 +0300 |
commit | ee892031f8ec801f02e3ddf3005295e663d49f53 (patch) | |
tree | 19ca7c9a4a60c95fefc4008afa81d2d8b7984e3e | |
parent | b5a2a6c2f12ed6723fa716d7473b9da3096f1b88 (diff) |
libpurple: do not delete accounts.xml
* Do not delete accounts.xml, this will allow to simplify plugin a lot: no need in storage backend,
no need to save/restore settings on backend side
* Read old saved settings on the frontend side and push to backend on login to be backward compatible
26 files changed, 108 insertions, 177 deletions
diff --git a/backends/frotz/main.cpp b/backends/frotz/main.cpp index a7546c5a..05e50b21 100644 --- a/backends/frotz/main.cpp +++ b/backends/frotz/main.cpp @@ -169,7 +169,7 @@ class FrotzNetworkPlugin : public NetworkPlugin { handleDataRead(d); } - void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) { + void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password, const std::map<std::string, std::string> &settings) { np->handleConnected(user); std::vector<std::string> groups; groups.push_back("ZCode"); diff --git a/backends/libcommuni/ircnetworkplugin.cpp b/backends/libcommuni/ircnetworkplugin.cpp index 18bb3e00..9241d0a2 100644 --- a/backends/libcommuni/ircnetworkplugin.cpp +++ b/backends/libcommuni/ircnetworkplugin.cpp @@ -126,7 +126,7 @@ MyIrcSession *IRCNetworkPlugin::createSession(const std::string &user, const std return session; } -void IRCNetworkPlugin::handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) { +void IRCNetworkPlugin::handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password, const std::map<std::string, std::string> &settings) { if (!m_servers.empty()) { // legacy name is user's nickname if (m_sessions[user] != NULL) { diff --git a/backends/libcommuni/ircnetworkplugin.h b/backends/libcommuni/ircnetworkplugin.h index ddb9e53f..aafa05a6 100644 --- a/backends/libcommuni/ircnetworkplugin.h +++ b/backends/libcommuni/ircnetworkplugin.h @@ -35,7 +35,7 @@ class IRCNetworkPlugin : public QObject, public NetworkPlugin { public: IRCNetworkPlugin(Config *config, Swift::QtEventLoop *loop, const std::string &host, int port); - void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password); + void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password, const std::map<std::string, std::string> &settings); void handleLogoutRequest(const std::string &user, const std::string &legacyName); diff --git a/backends/libpurple/CMakeLists.txt b/backends/libpurple/CMakeLists.txt index c62f4978..88722113 100644 --- a/backends/libpurple/CMakeLists.txt +++ b/backends/libpurple/CMakeLists.txt @@ -2,14 +2,6 @@ file(GLOB SRC *.cpp) add_executable(spectrum2_libpurple_backend ${SRC}) -if(MSVC) - target_link_libraries(spectrum2_libpurple_backend transport ${PURPLE_LIBRARY} ${GLIB2_LIBRARIES} ${LIBXML2_LIBRARIES} ${EVENT_LIBRARIES} transport-plugin) -else() - if(NOT WIN32) - target_link_libraries(spectrum2_libpurple_backend transport ${PURPLE_LIBRARY} ${GLIB2_LIBRARIES} ${EVENT_LIBRARIES} transport-plugin pthread) - else() - target_link_libraries(spectrum2_libpurple_backend transport ${PURPLE_LIBRARY} ${GLIB2_LIBRARIES} ${EVENT_LIBRARIES} transport-plugin) - endif() -endif() +target_link_libraries(spectrum2_libpurple_backend transport-plugin ${PURPLE_LIBRARY} ${GLIB2_LIBRARIES} ${EVENT_LIBRARIES}) install(TARGETS spectrum2_libpurple_backend RUNTIME DESTINATION bin) diff --git a/backends/libpurple/main.cpp b/backends/libpurple/main.cpp index 70aafd1a..4b376417 100644 --- a/backends/libpurple/main.cpp +++ b/backends/libpurple/main.cpp @@ -16,7 +16,6 @@ #include "transport/NetworkPlugin.h" #include "transport/Logging.h" #include "transport/Config.h" -#include "transport/StorageBackend.h" #include "geventloop.h" // #include "valgrind/memcheck.h" @@ -78,7 +77,6 @@ class SpectrumNetworkPlugin; std::shared_ptr<Config> config; SpectrumNetworkPlugin *np; -StorageBackend *storagebackend; static std::string host; static int port = 10000; @@ -216,38 +214,6 @@ static std::string getAlias(PurpleBuddy *m_buddy) { return alias; } -static boost::mutex dblock; -static std::string OAUTH_TOKEN = "hangouts_oauth_token"; -static std::string STEAM_ACCESS_TOKEN = "steammobile_access_token"; -static std::string DISCORD_ACCESS_TOKEN = "discord_access_token"; -static std::string WHATSMEOW_ACCESS_TOKEN = "credentials"; - -static bool getUserToken(const std::string user, const std::string token_name, std::string &token_value) -{ - boost::mutex::scoped_lock lock(dblock); - UserInfo info; - if (storagebackend->getUser(user, info) == false) { - LOG4CXX_ERROR(logger, "Didn't find entry for " << user << " in the database!"); - return false; - } - token_value = ""; - int type = TYPE_STRING; - storagebackend->getUserSetting((long)info.id, token_name, type, token_value); - return true; -} - -static bool storeUserToken(const std::string user, const std::string token_name, const std::string token_value) -{ - boost::mutex::scoped_lock lock(dblock); - UserInfo info; - if (storagebackend->getUser(user, info) == false) { - LOG4CXX_ERROR(logger, "Didn't find entry for " << user << " in the database!"); - return false; - } - storagebackend->updateUserSetting((long)info.id, token_name, token_value); - return true; -} - class SpectrumNetworkPlugin : public NetworkPlugin { public: SpectrumNetworkPlugin() : NetworkPlugin() { @@ -389,7 +355,7 @@ class SpectrumNetworkPlugin : public NetworkPlugin { } } - void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) { + void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password, const std::map<std::string, std::string> &settings) { PurpleAccount *account = NULL; std::string name; @@ -447,32 +413,11 @@ class SpectrumNetworkPlugin : public NetworkPlugin { purple_account_set_bool_wrapped(account, "custom_smileys", FALSE); purple_account_set_bool_wrapped(account, "direct_connect", FALSE); purple_account_set_bool_wrapped(account, "compat-verification", TRUE); - if (protocol == "prpl-hangouts") { - std::string token; - if (getUserToken(user, OAUTH_TOKEN, token)) { - purple_account_set_password_wrapped(account, token.c_str()); - } - } - else if (protocol == "prpl-steam-mobile") { - std::string token; - getUserToken(user, STEAM_ACCESS_TOKEN, token); - if (!token.empty()) { - purple_account_set_string_wrapped(account, "access_token", token.c_str()); - } - } - else if (protocol == "prpl-eionrobb-discord") { - std::string token; - getUserToken(user, DISCORD_ACCESS_TOKEN, token); - if (!token.empty()) { - purple_account_set_string_wrapped(account, "token", token.c_str()); - } - } - else if (protocol == "prpl-hehoe-whatsmeow") { - std::string token; - getUserToken(user, WHATSMEOW_ACCESS_TOKEN, token); - if (!token.empty()) { - purple_account_set_string_wrapped(account, "credentials", token.c_str()); - } + + + // Stored user settings + for (const auto& item: settings) { + purple_account_set_string_wrapped(account, item.first.c_str(), item.second.c_str()); } setDefaultAccountOptions(account); @@ -517,8 +462,6 @@ class SpectrumNetworkPlugin : public NetworkPlugin { purple_account_set_enabled_wrapped(account, "spectrum", FALSE); m_accounts.erase(account); - - purple_accounts_delete_wrapped(account); #ifndef WIN32 #if !defined(__FreeBSD__) && !defined(__APPLE__) && defined (__GLIBC__) malloc_trim(0); @@ -1150,69 +1093,6 @@ static PurpleBlistUiOps blistUiOps = static void conv_write_im(PurpleConversation *conv, const char *who, const char *msg, PurpleMessageFlags flags, time_t mtime); -static void conv_write(PurpleConversation *conv, const char *who, const char *alias, const char *msg, PurpleMessageFlags flags, time_t mtime) { - LOG4CXX_INFO(logger, "conv_write()"); - - if (flags & PURPLE_MESSAGE_SYSTEM && CONFIG_STRING(config, "service.protocol") == "prpl-telegram") { - PurpleAccount *account = purple_conversation_get_account_wrapped(conv); - - // char *striped = purple_markup_strip_html_wrapped(message); - // std::string msg = striped; - // g_free(striped); - - - // Escape HTML characters. - char *newline = purple_strdup_withhtml_wrapped(msg); - char *strip, *xhtml; - purple_markup_html_to_xhtml_wrapped(newline, &xhtml, &strip); - // xhtml_linkified = spectrum_markup_linkify(xhtml); - std::string message_(strip); - - std::string xhtml_(xhtml); - g_free(newline); - g_free(xhtml); - // g_free(xhtml_linkified); - g_free(strip); - - // AIM and XMPP adds <body>...</body> here... - if (xhtml_.find("<body>") == 0) { - xhtml_ = xhtml_.substr(6); - if (xhtml_.find("</body>") != std::string::npos) { - xhtml_ = xhtml_.substr(0, xhtml_.find("</body>")); - } - } - - if (xhtml_ == message_) { - xhtml_ = ""; - } - - std::string timestamp; - if (mtime && (unsigned long) time(NULL)-10 > (unsigned long) mtime/* && (unsigned long) time(NULL) - 31536000 < (unsigned long) mtime*/) { - char buf[80]; - strftime(buf, sizeof(buf), "%Y%m%dT%H%M%S", gmtime(&mtime)); - timestamp = buf; - } - - if (purple_conversation_get_type_wrapped(conv) == PURPLE_CONV_TYPE_IM) { - std::string w = purple_normalize_wrapped(account, who); - size_t pos = w.find("/"); - if (pos != std::string::npos) - w.erase((int) pos, w.length() - (int) pos); - LOG4CXX_TRACE(logger, "Received message body='" << message_ << "' xhtml='" << xhtml_ << "' name='" << w << "'"); - np->handleMessage(np->m_accounts[account], w, message_, "", xhtml_, timestamp); - } - else { - std::string conversationName = purple_conversation_get_name_wrapped(conv); - LOG4CXX_TRACE(logger, "Received message body='" << message_ << "' name='" << conversationName << "' " << who); - np->handleMessage(np->m_accounts[account], np->NameToLegacyName(account, conversationName), message_, who, xhtml_, timestamp); - } - } - else { - //Handle all non-special cases by just passing them to conv_write_im - conv_write_im(conv, who, msg, flags, mtime); - } -} - static char *calculate_data_hash(guchar *data, size_t len, const gchar *hash_algo) { @@ -1487,6 +1367,11 @@ static void conv_write_im(PurpleConversation *conv, const char *who, const char } } +static void conv_write(PurpleConversation *conv, const char *who, const char *alias, const char *msg, PurpleMessageFlags flags, time_t mtime) { + //Handle all non-special cases by just passing them to conv_write_im + conv_write_im(conv, who, msg, flags, mtime); +} + static void conv_chat_add_users(PurpleConversation *conv, GList *cbuddies, gboolean new_arrivals) { PurpleAccount *account = purple_conversation_get_account_wrapped(conv); @@ -2181,18 +2066,6 @@ static void signed_on(PurpleConnection *gc, gpointer unused) { // For prpl-gg execute_purple_plugin_action(gc, "Download buddylist from Server"); - if (CONFIG_STRING(config, "service.protocol") == "prpl-hangouts") { - storeUserToken(np->m_accounts[account], OAUTH_TOKEN, purple_account_get_password_wrapped(account)); - } - else if (CONFIG_STRING(config, "service.protocol") == "prpl-steam-mobile") { - storeUserToken(np->m_accounts[account], STEAM_ACCESS_TOKEN, purple_account_get_string_wrapped(account, "access_token", NULL)); - } - else if (CONFIG_STRING(config, "service.protocol") == "prpl-eionrobb-discord") { - storeUserToken(np->m_accounts[account], DISCORD_ACCESS_TOKEN, purple_account_get_string_wrapped(account, "token", NULL)); - } - else if (CONFIG_STRING(config, "service.protocol") == "prpl-hehoe-whatsmeow") { - storeUserToken(np->m_accounts[account], WHATSMEOW_ACCESS_TOKEN, purple_account_get_string_wrapped(account, "credentials", NULL)); - } } static void printDebug(PurpleDebugLevel level, const char *category, const char *arg_s) { @@ -2276,8 +2149,6 @@ static bool initPurple() { LOG4CXX_INFO(logger, "Setting libpurple user directory to: " << userDir); purple_util_set_user_dir_wrapped(userDir.c_str()); - remove("./accounts.xml"); - remove("./blist.xml"); purple_debug_set_ui_ops_wrapped(&debugUiOps); // purple_debug_set_verbose_wrapped(true); @@ -2430,20 +2301,6 @@ int main(int argc, char **argv) { config = std::shared_ptr<Config>(cfg); Logging::initBackendLogging(config.get()); - if (CONFIG_STRING(config, "service.protocol") == "prpl-hangouts" || CONFIG_STRING(config, "service.protocol") == "prpl-steam-mobile" - || CONFIG_STRING(config, "service.protocol") == "prpl-eionrobb-discord" || CONFIG_STRING(config, "service.protocol") == "prpl-hehoe-whatsmeow") - { - storagebackend = StorageBackend::createBackend(config.get(), error); - if (storagebackend == NULL) { - LOG4CXX_ERROR(logger, "Error creating StorageBackend! " << error); - LOG4CXX_ERROR(logger, "Selected libpurple protocol need storage backend configured to work! " << error); - return NetworkPlugin::StorageBackendNeeded; - } - else if (!storagebackend->connect()) { - LOG4CXX_ERROR(logger, "Can't connect to database!"); - return -1; - } - } initPurple(); diff --git a/backends/smstools3/main.cpp b/backends/smstools3/main.cpp index 66438c6b..52ac2823 100644 --- a/backends/smstools3/main.cpp +++ b/backends/smstools3/main.cpp @@ -174,7 +174,7 @@ class SMSNetworkPlugin : public NetworkPlugin { handleDataRead(d); } - void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) { + void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password, const std::map<std::string, std::string> &settings) { UserInfo info; if (!storageBackend->getUser(user, info)) { handleDisconnected(user, 0, "Not registered user."); diff --git a/backends/swiften/main.cpp b/backends/swiften/main.cpp index 4d89170c..9d6dc4b8 100644 --- a/backends/swiften/main.cpp +++ b/backends/swiften/main.cpp @@ -294,7 +294,7 @@ class SwiftenPlugin : public NetworkPlugin, Swift::XMPPParserClient { LOG4CXX_INFO(logger_xml, "XML OUT " << safeByteArrayToString(data)); } - void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) { + void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password, const std::map<std::string, std::string> &settings) { LOG4CXX_INFO(logger, user << ": connecting as " << legacyName); Swift::JID jid(legacyName); if (legacyName.find("/") == std::string::npos) { diff --git a/backends/template/plugin.cpp b/backends/template/plugin.cpp index 45ca5256..57b82848 100644 --- a/backends/template/plugin.cpp +++ b/backends/template/plugin.cpp @@ -36,7 +36,7 @@ void Plugin::_handleDataRead(std::shared_ptr<Swift::SafeByteArray> data) { handleDataRead(d); } -void Plugin::handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) { +void Plugin::handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password, const std::map<std::string, std::string> &settings) { handleConnected(user); LOG4CXX_INFO(logger, user << ": Added buddy - Echo."); handleBuddyChanged(user, "echo", "Echo", std::vector<std::string>(), pbnetwork::STATUS_ONLINE); diff --git a/backends/template/plugin.h b/backends/template/plugin.h index 0b4d86a5..be2d876d 100644 --- a/backends/template/plugin.h +++ b/backends/template/plugin.h @@ -12,7 +12,7 @@ class Plugin : public Transport::NetworkPlugin { // NetworkPlugin uses this method to send the data to networkplugin server void sendData(const std::string &string); - void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password); + void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password, const std::map<std::string, std::string> &settings); void handleLogoutRequest(const std::string &user, const std::string &legacyName); diff --git a/backends/twitter/TwitterPlugin.cpp b/backends/twitter/TwitterPlugin.cpp index ab9bc5bf..9e510263 100644 --- a/backends/twitter/TwitterPlugin.cpp +++ b/backends/twitter/TwitterPlugin.cpp @@ -121,7 +121,7 @@ void TwitterPlugin::_handleDataRead(std::shared_ptr<Swift::SafeByteArray> data) } // User trying to login into his twitter account -void TwitterPlugin::handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) +void TwitterPlugin::handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password, const std::map<std::string, std::string> &settings) { if(userdb.count(user) && (userdb[user].connectionState == NEW || userdb[user].connectionState == CONNECTED || diff --git a/backends/twitter/TwitterPlugin.h b/backends/twitter/TwitterPlugin.h index aec182f1..967df7fc 100644 --- a/backends/twitter/TwitterPlugin.h +++ b/backends/twitter/TwitterPlugin.h @@ -63,7 +63,7 @@ class TwitterPlugin : public NetworkPlugin { void _handleDataRead(std::shared_ptr<Swift::SafeByteArray> data); // User trying to login into his twitter account - void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password); + void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password, const std::map<std::string, std::string> &settings); // User logging out void handleLogoutRequest(const std::string &user, const std::string &legacyName); diff --git a/include/transport/MySQLBackend.h b/include/transport/MySQLBackend.h index 7256e6f6..72196b26 100644 --- a/include/transport/MySQLBackend.h +++ b/include/transport/MySQLBackend.h @@ -96,6 +96,8 @@ class MySQLBackend : public StorageBackend 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 getAllSettings(long userId, std::map<std::string, std::string> &userSettings); + 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); @@ -144,6 +146,7 @@ class MySQLBackend : public StorageBackend // MYSQL_STMT *m_setUser; Statement *m_setUser; Statement *m_getUser; + Statement *m_getUserSettings; Statement *m_getUserSetting; Statement *m_setUserSetting; Statement *m_updateUserSetting; diff --git a/include/transport/NetworkPlugin.h b/include/transport/NetworkPlugin.h index 8be3ad13..eecf9497 100644 --- a/include/transport/NetworkPlugin.h +++ b/include/transport/NetworkPlugin.h @@ -197,6 +197,7 @@ class NetworkPlugin { /// \param user XMPP JID of user for which this event occurs. /// \param legacyName Legacy network name of this user used for login. /// \param password Legacy network password of this user. + /// \param settings User settings /** \msc NetworkPlugin,YourNetworkPlugin,LegacyNetwork; @@ -210,7 +211,7 @@ class NetworkPlugin { YourNetworkPlugin->NetworkPlugin [label="handleDisconnected()", URL="\ref NetworkPlugin::handleDisconnected()"]; \endmsc */ - virtual void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) = 0; + virtual void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password, const std::map<std::string, std::string> &settings = {}) = 0; /// Called when XMPP user wants to disconnect legacy network. /// You should disconnect him from legacy network. diff --git a/include/transport/PQXXBackend.h b/include/transport/PQXXBackend.h index 8ce96eee..587f3027 100644 --- a/include/transport/PQXXBackend.h +++ b/include/transport/PQXXBackend.h @@ -95,6 +95,8 @@ class PQXXBackend : public StorageBackend 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 getAllSettings(long userId, std::map<std::string, std::string> &userSettings); + 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/SQLite3Backend.h b/include/transport/SQLite3Backend.h index 7a88a45a..fa2f6d08 100644 --- a/include/transport/SQLite3Backend.h +++ b/include/transport/SQLite3Backend.h @@ -95,6 +95,8 @@ class SQLite3Backend : public StorageBackend 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 getAllSettings(long userId, std::map<std::string, std::string> &userSettings); + 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,6 +113,7 @@ class SQLite3Backend : public StorageBackend // statements sqlite3_stmt *m_setUser; sqlite3_stmt *m_getUser; + sqlite3_stmt *m_getUserSettings; sqlite3_stmt *m_getUserSetting; sqlite3_stmt *m_setUserSetting; sqlite3_stmt *m_updateUserSetting; diff --git a/include/transport/StorageBackend.h b/include/transport/StorageBackend.h index e497588e..8bbab168 100644 --- a/include/transport/StorageBackend.h +++ b/include/transport/StorageBackend.h @@ -37,6 +37,7 @@ struct UserInfo { std::string password; ///< password for legacy network std::string language; ///< user's preferred language std::string encoding; ///< user's preferred encoding + std::map<std::string, std::string> settings; bool vip; ///< true if user is VIP }; @@ -134,6 +135,8 @@ class StorageBackend 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 getAllSettings(long userId, std::map<std::string, std::string> &userSettings) = 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/User.h b/include/transport/User.h index f688a36d..dc21f82c 100644 --- a/include/transport/User.h +++ b/include/transport/User.h @@ -126,11 +126,11 @@ class User { } void addUserSetting(const std::string &key, const std::string &value) { - m_settings[key] = value; + m_userInfo.settings[key] = value; } const std::string &getUserSetting(const std::string &key) { - return m_settings[key]; + return m_userInfo.settings[key]; } void setCacheMessages(bool cacheMessages); @@ -177,7 +177,6 @@ class User { int m_resources; int m_reconnectCounter; std::list<Swift::Presence::ref> m_joinedRooms; - std::map<std::string, std::string> m_settings; bool m_cacheMessages; int m_reconnectLimit; StorageBackend *m_storageBackend; diff --git a/include/transport/protocol.proto b/include/transport/protocol.proto index 749c7e7a..adf97b90 100644 --- a/include/transport/protocol.proto +++ b/include/transport/protocol.proto @@ -48,6 +48,10 @@ message Login { required string legacyName = 2; required string password = 3; repeated string extraFields = 4; + message UserSettings { + map<string, string> value = 1; + } + optional UserSettings settings = 5; } message Logout { diff --git a/libtransport/MySQLBackend.cpp b/libtransport/MySQLBackend.cpp index 97d781d6..cf39c75a 100644 --- a/libtransport/MySQLBackend.cpp +++ b/libtransport/MySQLBackend.cpp @@ -248,6 +248,7 @@ void MySQLBackend::disconnect() { delete m_updateBuddy; delete m_getBuddies; delete m_getBuddiesSettings; + delete m_getUserSettings; delete m_getUserSetting; delete m_setUserSetting; delete m_updateUserSetting; @@ -297,6 +298,8 @@ bool MySQLBackend::connect() { m_updateBuddySetting = new Statement(&m_conn, "iisiss", "INSERT INTO " + m_prefix + "buddies_settings (user_id, buddy_id, var, type, value) VALUES (?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE value=?"); m_getBuddySetting = new Statement(&m_conn, "iss|is", "SELECT type, value FROM " + m_prefix + "buddies_settings WHERE user_id=? AND buddy_id=? AND var=?"); + m_getUserSettings = new Statement(&m_conn, "i|sis", "SELECT var, type, value FROM " + m_prefix + "users_settings WHERE user_id=?"); + m_getUserSetting = new Statement(&m_conn, "is|is", "SELECT type, value FROM " + m_prefix + "users_settings WHERE user_id=? AND var=?"); m_setUserSetting = new Statement(&m_conn, "isis", "INSERT INTO " + m_prefix + "users_settings (user_id, var, type, value) VALUES (?,?,?,?)"); m_updateUserSetting = new Statement(&m_conn, "sis", "UPDATE " + m_prefix + "users_settings SET value=? WHERE user_id=? AND var=?"); @@ -383,6 +386,19 @@ void MySQLBackend::setUser(const UserInfo &user) { EXEC(m_setUser, setUser(user)); } +void MySQLBackend::getAllSettings(long userId, std::map<std::string, std::string> &userSettings) { + *m_getUserSettings << userId; + EXEC(m_getUserSettings, getAllSettings(userId, userSettings)); + while (m_getUserSettings->fetch() == 0) { + std::string var; + int type; + std::string val; + SettingVariableInfo value; + *m_getUserSettings >> var >> type >> val; + userSettings[var] = val; + } +} + bool MySQLBackend::getUser(const std::string &barejid, UserInfo &user) { *m_getUser << barejid; EXEC(m_getUser, getUser(barejid, user)); diff --git a/libtransport/NetworkPluginServer.cpp b/libtransport/NetworkPluginServer.cpp index 59be6df2..e11cca7c 100644 --- a/libtransport/NetworkPluginServer.cpp +++ b/libtransport/NetworkPluginServer.cpp @@ -1369,6 +1369,11 @@ void NetworkPluginServer::handleUserReadyToConnect(User *user) { login.set_user(user->getJID().toBare()); login.set_legacyname(userInfo.uin); login.set_password(userInfo.password); + pbnetwork::Login_UserSettings *settings = login.mutable_settings(); + auto value = settings->mutable_value(); + for (const auto& item : userInfo.settings) { + (*value)[item.first] = item.second; + } std::string message; login.SerializeToString(&message); diff --git a/libtransport/PQXXBackend.cpp b/libtransport/PQXXBackend.cpp index df148fac..eafcda5a 100644 --- a/libtransport/PQXXBackend.cpp +++ b/libtransport/PQXXBackend.cpp @@ -399,6 +399,25 @@ bool PQXXBackend::removeUser(long id) { return false; } +void PQXXBackend::getAllSettings(long userId, std::map<std::string, std::string> &userSettings) { + try + { + pqxx::nontransaction settings_txn(*m_conn); + pqxx::result settings_r = settings_txn.exec("SELECT var, type, value FROM " + m_prefix + "users_settings WHERE user_id=" + pqxx::to_string(userId)); + for (pqxx::result::const_iterator it = settings_r.begin(); it != settings_r.end(); it++) + { + std::string var = (*it)[0].as<std::string>(); + //int type = (*it)[1].as<long>(); + std::string val = (*it)[2].as<std::string>(); + userSettings[var] = val; + } + } + catch (std::exception &e) + { + LOG4CXX_ERROR(pxxLogger, e.what()); + } +} + void PQXXBackend::getUserSetting(long id, const std::string &variable, int &type, std::string &value) { try { pqxx::nontransaction txn(*m_conn); diff --git a/libtransport/SQLite3Backend.cpp b/libtransport/SQLite3Backend.cpp index 678310af..07aa161d 100644 --- a/libtransport/SQLite3Backend.cpp +++ b/libtransport/SQLite3Backend.cpp @@ -94,6 +94,7 @@ SQLite3Backend::~SQLite3Backend(){ FINALIZE_STMT(m_updateBuddy); FINALIZE_STMT(m_getBuddies); FINALIZE_STMT(m_getBuddiesSettings); + FINALIZE_STMT(m_getUserSettings); FINALIZE_STMT(m_getUserSetting); FINALIZE_STMT(m_setUserSetting); FINALIZE_STMT(m_updateUserSetting); @@ -137,6 +138,8 @@ bool SQLite3Backend::connect() { 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_getUserSettings, "SELECT var, type, value FROM " + m_prefix + "users_settings WHERE user_id=?"); + 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 (?,?,?,?)"); PREP_STMT(m_updateUserSetting, "UPDATE " + m_prefix + "users_settings SET value=? WHERE user_id=? AND var=?"); @@ -513,6 +516,20 @@ bool SQLite3Backend::removeUser(long id) { return true; } +void SQLite3Backend::getAllSettings(long userId, std::map<std::string, std::string> &userSettings) { + BEGIN(m_getUserSettings); + BIND_INT(m_getUserSettings, userId); + int ret2; + while ((ret2 = sqlite3_step(m_getUserSettings)) == SQLITE_ROW) + { + RESET_GET_COUNTER(m_getUserSettings); + std::string var = GET_STR(m_getUserSettings); + int type = GET_INT(m_getUserSettings); + std::string val = GET_STR(m_getUserSettings); + userSettings[var] = val; + } +} + void SQLite3Backend::getUserSetting(long id, const std::string &variable, int &type, std::string &value) { BEGIN(m_getUserSetting); BIND_INT(m_getUserSetting, id); diff --git a/libtransport/UserManager.cpp b/libtransport/UserManager.cpp index 83eabfb4..6abd9fe6 100644 --- a/libtransport/UserManager.cpp +++ b/libtransport/UserManager.cpp @@ -85,6 +85,9 @@ User *UserManager::getUser(const std::string &barejid){ if (m_users.find(barejid) != m_users.end()) { User *user = m_users[barejid]; m_cachedUser = user; + if (m_storageBackend) { + m_storageBackend->getAllSettings(user->getUserInfo().id, user->getUserInfo().settings); + } return user; } return NULL; diff --git a/plugin/cpp/networkplugin.cpp b/plugin/cpp/networkplugin.cpp index 74e1ff60..e1c2f66b 100644 --- a/plugin/cpp/networkplugin.cpp +++ b/plugin/cpp/networkplugin.cpp @@ -350,7 +350,7 @@ void NetworkPlugin::handleLoginPayload(const std::string &data) { // TODO: ERROR return; } - handleLoginRequest(payload.user(), payload.legacyname(), payload.password()); + handleLoginRequest(payload.user(), payload.legacyname(), payload.password(), { payload.settings().value().begin(), payload.settings().value().end() }); } void NetworkPlugin::handleLogoutPayload(const std::string &data) { diff --git a/tests/libtransport/basictest.h b/tests/libtransport/basictest.h index 3b3fe08c..d855fe00 100644 --- a/tests/libtransport/basictest.h +++ b/tests/libtransport/basictest.h @@ -197,6 +197,12 @@ class TestingStorageBackend : public StorageBackend { virtual void getBuddySetting(long userId, long buddyId, const std::string &variable, int &type, std::string &value) {} virtual void updateBuddySetting(long userId, long buddyId, const std::string &variable, int type, const std::string &value) {} + virtual void getAllSettings(long userId, std::map<std::string, std::string> &userSettings) { + for (const auto& it : settings[userId]) { + userSettings[it.first] = it.second; + } + } + virtual void getUserSetting(long userId, const std::string &variable, int &type, std::string &value) { if (settings[userId].find(variable) == settings[userId].end()) { settings[userId][variable] = value; diff --git a/tests/libtransport/settingsadhoccommand.cpp b/tests/libtransport/settingsadhoccommand.cpp index 7733b557..d57e3029 100644 --- a/tests/libtransport/settingsadhoccommand.cpp +++ b/tests/libtransport/settingsadhoccommand.cpp @@ -359,6 +359,7 @@ class SettingsAdHocCommandTest : public CPPUNIT_NS :: TestFixture, public BasicT connectUser(); User *user = userManager->getUser("user@localhost"); CPPUNIT_ASSERT_EQUAL(std::string("1"), user->getUserSetting("send_headlines")); + CPPUNIT_ASSERT_EQUAL(3, (int) user->getUserInfo().settings.size()); std::shared_ptr<Swift::Command> payload(new Swift::Command("settings")); std::shared_ptr<Swift::IQ> iq = Swift::IQ::createRequest(Swift::IQ::Set, Swift::JID("localhost"), "id", payload); iq->setFrom("user@localhost"); |