diff --git a/CMakeLists.txt b/CMakeLists.txt index fc4f75de469d8df170392bbf32562e56a2365f05..6ce72640b3dc89ca61c70089d9c484706398691c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,6 +43,7 @@ INCLUDE(FindQt4) FIND_PACKAGE(Qt4 COMPONENTS QtCore) # ADD_DEFINITIONS(${SWIFTEN_CFLAGS}) +ADD_DEFINITIONS(-DSUPPORT_LEGACY_CAPS) message(" Supported features") message("-----------------------") diff --git a/include/transport/transport.h b/include/transport/transport.h index 010e2fbf783e0f1f334560ee3303a82ed1691dad..79cb254671af988a3d466e712ec57a100c5e747b 100644 --- a/include/transport/transport.h +++ b/include/transport/transport.h @@ -157,6 +157,8 @@ namespace Transport { /// \param presence presence data boost::signal onUserPresenceReceived; + boost::signal info)> onUserDiscoInfoReceived; + // boost::signal info, Swift::ErrorPayload::ref error, const Swift::JID& jid)> onDiscoInfoResponse; private: @@ -166,7 +168,7 @@ namespace Transport { void handleDataRead(const Swift::SafeByteArray &data); void handleDataWritten(const Swift::SafeByteArray &data); -// void handleDiscoInfoResponse(boost::shared_ptr info, Swift::ErrorPayload::ref error, const Swift::JID& jid); + void handleDiscoInfoResponse(boost::shared_ptr info, Swift::ErrorPayload::ref error, const Swift::JID& jid); void handleCapsChanged(const Swift::JID& jid); Swift::NetworkFactories *m_factories; diff --git a/include/transport/user.h b/include/transport/user.h index dcf9a9fe4a03b4b6c3cee0a5a95bc43e32c6fded..0ad6693a55abd1101eeced9b784e6a2c7735e960 100644 --- a/include/transport/user.h +++ b/include/transport/user.h @@ -75,6 +75,8 @@ class User { void handleSubscription(Swift::Presence::ref presence); + void handleDiscoInfo(const Swift::JID& jid, boost::shared_ptr info); + time_t &getLastActivity() { return m_lastActivity; } @@ -127,6 +129,7 @@ class User { Swift::Timer::ref m_reconnectTimer; boost::shared_ptr connection; time_t m_lastActivity; + std::map m_legacyCaps; }; } diff --git a/include/transport/usermanager.h b/include/transport/usermanager.h index 839c612f7bacfb0e3fe2e85ef01d173a7a979a31..0c23b245a3ab9c372aba21fff83590ac5a5fa399 100644 --- a/include/transport/usermanager.h +++ b/include/transport/usermanager.h @@ -117,7 +117,7 @@ class UserManager { void handleProbePresence(Swift::Presence::ref presence); void handleSubscription(Swift::Presence::ref presence); void handleRemoveTimeout(const std::string jid, User *user, bool reconnect); -// void handleDiscoInfoResponse(boost::shared_ptr info, Swift::ErrorPayload::ref error, const Swift::JID& jid); + void handleDiscoInfo(const Swift::JID& jid, boost::shared_ptr info); void addUser(User *user); long m_onlineBuddies; diff --git a/src/mysqlbackend.cpp b/src/mysqlbackend.cpp index 0cfdd59a02b8efa93bbb7feeb59b4fb2e7938af5..d2f4d2fd6e3a6a3fef68a077ec093e2efa583294 100644 --- a/src/mysqlbackend.cpp +++ b/src/mysqlbackend.cpp @@ -296,7 +296,7 @@ bool MySQLBackend::connect() { createDatabase(); - m_setUser = new Statement(&m_conn, "sssssb", "INSERT INTO " + m_prefix + "users (jid, uin, password, language, encoding, last_login, vip) VALUES (?, ?, ?, ?, ?, NOW(), ?)"); + m_setUser = new Statement(&m_conn, "sssssbs", "INSERT INTO " + m_prefix + "users (jid, uin, password, language, encoding, last_login, vip) VALUES (?, ?, ?, ?, ?, NOW(), ?) ON DUPLICATE KEY UPDATE password=?"); m_getUser = new Statement(&m_conn, "s|isssssb", "SELECT id, jid, uin, password, encoding, language, vip FROM " + m_prefix + "users WHERE jid=?"); m_removeUser = new Statement(&m_conn, "i", "DELETE FROM " + m_prefix + "users WHERE id=?"); @@ -386,7 +386,7 @@ bool MySQLBackend::exec(const std::string &query) { } void MySQLBackend::setUser(const UserInfo &user) { - *m_setUser << user.jid << user.uin << user.password << user.language << user.encoding << user.vip; + *m_setUser << user.jid << user.uin << user.password << user.language << user.encoding << user.vip << user.password; m_setUser->execute(); } diff --git a/src/rostermanager.cpp b/src/rostermanager.cpp index 5f397ba8dea43150d32d1397cac7d45208b00ad8..d0f28d8502eff9648dc802c03dd698c8eec84a0c 100644 --- a/src/rostermanager.cpp +++ b/src/rostermanager.cpp @@ -198,7 +198,7 @@ void RosterManager::handleRemoteRosterResponse(boost::shared_ptrgetJID().toString() << ": This server supports remote roster protoXEP"); - m_supportRemoteRoster = true; +// m_supportRemoteRoster = true; return; BOOST_FOREACH(const Swift::RosterItemPayload &item, payload->getItems()) { diff --git a/src/sqlite3backend.cpp b/src/sqlite3backend.cpp index f79ce9fb0450dfd80a428247e2d163ef9325d612..7a4f444b3b1df440fd66544e50bb59060babf251 100644 --- a/src/sqlite3backend.cpp +++ b/src/sqlite3backend.cpp @@ -112,7 +112,7 @@ bool SQLite3Backend::connect() { if (createDatabase() == false) return false; - PREP_STMT(m_setUser, "INSERT INTO " + m_prefix + "users (jid, uin, password, language, encoding, last_login, vip) VALUES (?, ?, ?, ?, ?, DATETIME('NOW'), ?)"); + PREP_STMT(m_setUser, "INSERT OR REPLACE INTO " + m_prefix + "users (jid, uin, password, language, encoding, last_login, vip) VALUES (?, ?, ?, ?, ?, DATETIME('NOW'), ?)"); PREP_STMT(m_getUser, "SELECT id, jid, uin, password, encoding, language, vip FROM " + m_prefix + "users WHERE jid=?"); PREP_STMT(m_removeUser, "DELETE FROM " + m_prefix + "users WHERE id=?"); diff --git a/src/transport.cpp b/src/transport.cpp index f451a818e62be3143d9067406f69928876d041cf..612b51bcc4833b975826ea4e0e2bc0c9312934d2 100644 --- a/src/transport.cpp +++ b/src/transport.cpp @@ -245,18 +245,26 @@ void Component::handlePresence(Swift::Presence::ref presence) { if (capsInfo && capsInfo->getHash() == "sha-1") { /*haveFeatures = */m_entityCapsManager->getCaps(presence->getFrom()) != DiscoInfo::ref(); } -// else { -// GetDiscoInfoRequest::ref discoInfoRequest = GetDiscoInfoRequest::create(presence->getFrom(), m_iqRouter); -// discoInfoRequest->onResponse.connect(boost::bind(&Component::handleDiscoInfoResponse, this, _1, _2, presence->getFrom())); -// discoInfoRequest->send(); -// } +#ifdef SUPPORT_LEGACY_CAPS + else { + GetDiscoInfoRequest::ref discoInfoRequest = GetDiscoInfoRequest::create(presence->getFrom(), m_iqRouter); + discoInfoRequest->onResponse.connect(boost::bind(&Component::handleDiscoInfoResponse, this, _1, _2, presence->getFrom())); + discoInfoRequest->send(); + } +#endif } onUserPresenceReceived(presence); } +void Component::handleDiscoInfoResponse(boost::shared_ptr info, Swift::ErrorPayload::ref error, const Swift::JID& jid) { +#ifdef SUPPORT_LEGACY_CAPS + onUserDiscoInfoReceived(jid, info); +#endif +} + void Component::handleCapsChanged(const Swift::JID& jid) { - m_entityCapsManager->getCaps(jid) != DiscoInfo::ref(); + onUserDiscoInfoReceived(jid, m_entityCapsManager->getCaps(jid)); } } diff --git a/src/user.cpp b/src/user.cpp index 5adc59ce078314b01645331d28f2e53e0fa5c140..7b3ba23730ca9f8324dd33294f594d138a11416e 100644 --- a/src/user.cpp +++ b/src/user.cpp @@ -88,8 +88,18 @@ Swift::JID User::getJIDWithFeature(const std::string &feature) { continue; Swift::DiscoInfo::ref discoInfo = m_entityCapsManager->getCaps(presence->getFrom()); - if (!discoInfo) + if (!discoInfo) { +#ifdef SUPPORT_LEGACY_CAPS + if (m_legacyCaps.find(presence->getFrom()) != m_legacyCaps.end()) { + discoInfo = m_legacyCaps[presence->getFrom()]; + } + else { + continue; + } +#else continue; +#endif + } if (discoInfo->hasFeature(feature)) { LOG4CXX_INFO(logger, m_jid.toString() << ": Found JID with " << feature << " feature: " << presence->getFrom().toString()); @@ -97,7 +107,7 @@ Swift::JID User::getJIDWithFeature(const std::string &feature) { } } - LOG4CXX_INFO(logger, m_jid.toString() << ": No JID with " << feature << " feature"); + LOG4CXX_INFO(logger, m_jid.toString() << ": No JID with " << feature << " feature " << m_legacyCaps.size()); return jid; } @@ -189,21 +199,24 @@ void User::handlePresence(Swift::Presence::ref presence) { sendCurrentPresence(); + // Change legacy network presence - Swift::Presence::ref highest = m_presenceOracle->getHighestPriorityPresence(m_jid.toBare()); - if (highest) { - Swift::Presence::ref response = Swift::Presence::create(highest); - response->setTo(m_jid); - response->setFrom(m_component->getJID()); - LOG4CXX_INFO(logger, m_jid.toString() << ": Changing legacy network presence to " << response->getType()); - onPresenceChanged(highest); - } - else { - Swift::Presence::ref response = Swift::Presence::create(); - response->setTo(m_jid.toBare()); - response->setFrom(m_component->getJID()); - response->setType(Swift::Presence::Unavailable); - onPresenceChanged(response); + if (m_readyForConnect) { + Swift::Presence::ref highest = m_presenceOracle->getHighestPriorityPresence(m_jid.toBare()); + if (highest) { + Swift::Presence::ref response = Swift::Presence::create(highest); + response->setTo(m_jid); + response->setFrom(m_component->getJID()); + LOG4CXX_INFO(logger, m_jid.toString() << ": Changing legacy network presence to " << response->getType()); + onPresenceChanged(highest); + } + else { + Swift::Presence::ref response = Swift::Presence::create(); + response->setTo(m_jid.toBare()); + response->setFrom(m_component->getJID()); + response->setType(Swift::Presence::Unavailable); + onPresenceChanged(response); + } } } @@ -211,12 +224,33 @@ void User::handleSubscription(Swift::Presence::ref presence) { m_rosterManager->handleSubscription(presence); } +void User::handleDiscoInfo(const Swift::JID& jid, boost::shared_ptr info) { + LOG4CXX_INFO(logger, jid.toString() << ": got disco#info"); +#ifdef SUPPORT_LEGACY_CAPS + Swift::DiscoInfo::ref discoInfo = m_entityCapsManager->getCaps(jid); + // This is old legacy cap which is not stored in entityCapsManager, + // we have to store it in our user class. + if (!discoInfo) { + LOG4CXX_INFO(logger, jid.toString() << ": LEGACY"); + m_legacyCaps[jid] = info; + } +#endif + + onConnectingTimeout(); +} + void User::onConnectingTimeout() { if (m_connected || m_readyForConnect) return; m_reconnectTimer->stop(); m_readyForConnect = true; onReadyToConnect(); + + Swift::Presence::ref highest = m_presenceOracle->getHighestPriorityPresence(m_jid.toBare()); + if (highest) { + LOG4CXX_INFO(logger, m_jid.toString() << ": Changing legacy network presence to " << highest->getType()); + onPresenceChanged(highest); + } } void User::setIgnoreDisconnect(bool ignoreDisconnect) { diff --git a/src/usermanager.cpp b/src/usermanager.cpp index 69c6ef681b253da0ccd9f9b35d7b9b2051389c63..b42eef41853cec65fbfedf229576b6e274ecfdd6 100644 --- a/src/usermanager.cpp +++ b/src/usermanager.cpp @@ -53,12 +53,12 @@ UserManager::UserManager(Component *component, UserRegistry *userRegistry, Stora } component->onUserPresenceReceived.connect(bind(&UserManager::handlePresence, this, _1)); + component->onUserDiscoInfoReceived.connect(bind(&UserManager::handleDiscoInfo, this, _1, _2)); m_component->getStanzaChannel()->onMessageReceived.connect(bind(&UserManager::handleMessageReceived, this, _1)); m_component->getStanzaChannel()->onPresenceReceived.connect(bind(&UserManager::handleGeneralPresenceReceived, this, _1)); m_userRegistry->onConnectUser.connect(bind(&UserManager::connectUser, this, _1)); m_userRegistry->onDisconnectUser.connect(bind(&UserManager::disconnectUser, this, _1)); -// component->onDiscoInfoResponse.connect(bind(&UserManager::handleDiscoInfoResponse, this, _1, _2, _3)); m_removeTimer = m_component->getNetworkFactories()->getTimerFactory()->createTimer(1); } @@ -122,6 +122,15 @@ int UserManager::getUserCount() { return m_users.size(); } +void UserManager::handleDiscoInfo(const Swift::JID& jid, boost::shared_ptr info) { + User *user = getUser(jid.toBare().toString()); + if (!user) { + return; + } + + user->handleDiscoInfo(jid, info); +} + void UserManager::handlePresence(Swift::Presence::ref presence) { std::string barejid = presence->getTo().toBare().toString(); std::string userkey = presence->getFrom().toBare().toString(); diff --git a/src/userregistration.cpp b/src/userregistration.cpp index bb4bc89a67b3f9307eee6a2591e35d255d8c882c..7b05216fc65579e2ba5c2a02ad84bc3b71637639 100644 --- a/src/userregistration.cpp +++ b/src/userregistration.cpp @@ -388,6 +388,7 @@ bool UserRegistration::handleSetRequest(const Swift::JID& from, const Swift::JID } else { res.jid = barejid; + res.uin = username; res.password = *payload->getPassword(); res.language = language; res.encoding = encoding;