diff --git a/include/transport/rostermanager.h b/include/transport/rostermanager.h index 29c460ca7cfd013809a7ab9de963dd1875e3da75..2e67532afa4549591537648619c93d7b50ccc6ae 100644 --- a/include/transport/rostermanager.h +++ b/include/transport/rostermanager.h @@ -36,6 +36,16 @@ class Component; class StorageBackend; class RosterStorage; +// TODO: Once Swiften GetRosterRequest will support setting to="", this can be removed +class AddressedRosterRequest : public Swift::GenericRequest { + public: + typedef boost::shared_ptr ref; + + AddressedRosterRequest(Swift::IQRouter* router, Swift::JID to) : + Swift::GenericRequest(Swift::IQ::Get, to, boost::shared_ptr(new Swift::RosterPayload()), router) { + } +}; + /// Manages roster of one XMPP user. class RosterManager { public: diff --git a/include/transport/userregistration.h b/include/transport/userregistration.h index 3a34480b90223a5508777e90fcdd2ce24e176ed5..32299f09ce0e16cfdfa51a556e324ade07e5ba53 100644 --- a/include/transport/userregistration.h +++ b/include/transport/userregistration.h @@ -70,6 +70,8 @@ class UserRegistration : public Swift::Responder payload); virtual bool handleSetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr payload); + + void handleUnregisterRemoteRosterResponse(boost::shared_ptr payload, Swift::ErrorPayload::ref error, const std::string &barejid); Component *m_component; StorageBackend *m_storageBackend; diff --git a/src/rostermanager.cpp b/src/rostermanager.cpp index 78161f70af168e0f6cf30b511e323af132d81cae..bfbe27aafc6f289a5492dd612c8d02184de8a3d0 100644 --- a/src/rostermanager.cpp +++ b/src/rostermanager.cpp @@ -41,16 +41,6 @@ namespace Transport { static LoggerPtr logger = Logger::getLogger("RosterManager"); -// TODO: Once Swiften GetRosterRequest will support setting to="", this can be removed -class AddressedRosterRequest : public Swift::GenericRequest { - public: - typedef boost::shared_ptr ref; - - AddressedRosterRequest(Swift::IQRouter* router, Swift::JID to) : - Swift::GenericRequest(Swift::IQ::Get, to, boost::shared_ptr(new Swift::RosterPayload()), router) { - } -}; - RosterManager::RosterManager(User *user, Component *component){ m_rosterStorage = NULL; m_user = user; diff --git a/src/userregistration.cpp b/src/userregistration.cpp index 3b0d1d78274048a77ca15b50922a552310775697..3f883f439a398d4d23f91221297334fe162702e2 100644 --- a/src/userregistration.cpp +++ b/src/userregistration.cpp @@ -22,6 +22,7 @@ #include "transport/usermanager.h" #include "transport/storagebackend.h" #include "transport/transport.h" +#include "transport/rostermanager.h" #include "transport/user.h" #include "Swiften/Elements/ErrorPayload.h" #include @@ -45,7 +46,6 @@ UserRegistration::~UserRegistration(){ } bool UserRegistration::registerUser(const UserInfo &row) { - // TODO: move this check to sql()->addUser(...) and let it return bool UserInfo user; bool registered = m_storageBackend->getUser(row.jid, user); // This user is already registered @@ -58,8 +58,7 @@ bool UserRegistration::registerUser(const UserInfo &row) { response->setFrom(m_component->getJID()); response->setTo(Swift::JID(row.jid)); response->setType(Swift::Presence::Subscribe); - - m_component->m_component->sendPresence(response); + m_component->getStanzaChannel()->sendPresence(response); onUserRegistered(row); return true; @@ -74,54 +73,90 @@ bool UserRegistration::unregisterUser(const std::string &barejid) { onUserUnregistered(userInfo); - Swift::Presence::ref response; + // We have to check if server supports remoteroster XEP and use it if it's supported or fallback to unsubscribe otherwise + AddressedRosterRequest::ref request = AddressedRosterRequest::ref(new AddressedRosterRequest(m_component->getIQRouter(), barejid)); + request->onResponse.connect(boost::bind(&UserRegistration::handleUnregisterRemoteRosterResponse, this, _1, _2, barejid)); + request->send(); - User *user = m_userManager->getUser(barejid); + return true; +} + +void UserRegistration::handleUnregisterRemoteRosterResponse(boost::shared_ptr payload, Swift::ErrorPayload::ref remoteRosterNotSupported /*error*/, const std::string &barejid) { + UserInfo userInfo; + bool registered = m_storageBackend->getUser(barejid, userInfo); + // This user is not registered + if (!registered) + return; - // roster contains already escaped jids std::list roster; m_storageBackend->getBuddies(userInfo.id, roster); - for(std::list::iterator u = roster.begin(); u != roster.end() ; u++){ std::string name = (*u).legacyName; - response = Swift::Presence::create(); - response->setTo(Swift::JID(barejid)); - response->setFrom(Swift::JID(name + "@" + m_component->getJID().toString())); - response->setType(Swift::Presence::Unsubscribe); - m_component->m_component->sendPresence(response); + if (remoteRosterNotSupported) { + Swift::Presence::ref response; + response = Swift::Presence::create(); + response->setTo(Swift::JID(barejid)); + response->setFrom(Swift::JID(name + "@" + m_component->getJID().toString())); + response->setType(Swift::Presence::Unsubscribe); + m_component->getStanzaChannel()->sendPresence(response); + + response = Swift::Presence::create(); + response->setTo(Swift::JID(barejid)); + response->setFrom(Swift::JID(name + "@" + m_component->getJID().toString())); + response->setType(Swift::Presence::Unsubscribed); + m_component->getStanzaChannel()->sendPresence(response); + } + else { + Swift::RosterPayload::ref payload = Swift::RosterPayload::ref(new Swift::RosterPayload()); + Swift::RosterItemPayload item; + item.setJID(Swift::JID(name + "@" + m_component->getJID().toString())); + item.setSubscription(Swift::RosterItemPayload::Remove); - response = Swift::Presence::create(); - response->setTo(Swift::JID(barejid)); - response->setFrom(Swift::JID(name + "@" + m_component->getJID().toString())); - response->setType(Swift::Presence::Unsubscribed); - m_component->m_component->sendPresence(response); + payload->addItem(item); + + Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(payload, barejid, m_component->getIQRouter()); + request->send(); + } } // Remove user from database m_storageBackend->removeUser(userInfo.id); // Disconnect the user + User *user = m_userManager->getUser(barejid); if (user) { m_userManager->removeUser(user); } - response = Swift::Presence::create(); - response->setTo(Swift::JID(barejid)); - response->setFrom(m_component->getJID()); - response->setType(Swift::Presence::Unsubscribe); - m_component->m_component->sendPresence(response); - - response = Swift::Presence::create(); - response->setTo(Swift::JID(barejid)); - response->setFrom(m_component->getJID()); - response->setType(Swift::Presence::Unsubscribed); - m_component->m_component->sendPresence(response); + if (remoteRosterNotSupported) { + Swift::Presence::ref response; + response = Swift::Presence::create(); + response->setTo(Swift::JID(barejid)); + response->setFrom(m_component->getJID()); + response->setType(Swift::Presence::Unsubscribe); + m_component->getStanzaChannel()->sendPresence(response); - return true; + response = Swift::Presence::create(); + response->setTo(Swift::JID(barejid)); + response->setFrom(m_component->getJID()); + response->setType(Swift::Presence::Unsubscribed); + m_component->getStanzaChannel()->sendPresence(response); + } + else { + Swift::RosterPayload::ref payload = Swift::RosterPayload::ref(new Swift::RosterPayload()); + Swift::RosterItemPayload item; + item.setJID(m_component->getJID()); + item.setSubscription(Swift::RosterItemPayload::Remove); + payload->addItem(item); + + Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(payload, barejid, m_component->getIQRouter()); + request->send(); + } } bool UserRegistration::handleGetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr payload) { + // TODO: backend should say itself if registration is needed or not... if (CONFIG_STRING(m_config, "service.protocol") == "irc") { sendError(from, id, ErrorPayload::BadRequest, ErrorPayload::Modify); return true; @@ -129,33 +164,32 @@ bool UserRegistration::handleGetRequest(const Swift::JID& from, const Swift::JID std::string barejid = from.toBare().toString(); -// User *user = m_userManager->getUserByJID(barejid); if (!CONFIG_BOOL(m_config,"registration.enable_public_registration")) { std::list const &x = CONFIG_LIST(m_config,"service.allowed_servers"); if (std::find(x.begin(), x.end(), from.getDomain()) == x.end()) { -// Log("UserRegistration", "This user has no permissions to register an account"); + LOG4CXX_INFO(logger, barejid << ": This user has no permissions to register an account") sendError(from, id, ErrorPayload::BadRequest, ErrorPayload::Modify); return true; } } -// const char *_language = user ? user->getLang() : CONFIG_STRING(m_config, "registration.language").c_str(); - boost::shared_ptr reg(new InBandRegistrationPayload()); UserInfo res; bool registered = m_storageBackend->getUser(barejid, res); std::string instructions = CONFIG_STRING(m_config, "registration.instructions"); + std::string usernameField = CONFIG_STRING(m_config, "registration.username_field"); + // normal jabber:iq:register reg->setInstructions(instructions); reg->setRegistered(registered); reg->setUsername(res.uin); if (CONFIG_STRING(m_config, "service.protocol") != "twitter" && CONFIG_STRING(m_config, "service.protocol") != "bonjour") reg->setPassword(res.password); - std::string usernameField = CONFIG_STRING(m_config, "registration.username_field"); + // form Form::ref form(new Form(Form::FormType)); form->setTitle((("Registration"))); form->setInstructions((instructions)); @@ -187,10 +221,6 @@ bool UserRegistration::handleGetRequest(const Swift::JID& from, const Swift::JID language->setValue(res.language); else language->setValue(CONFIG_STRING(m_config, "registration.language")); -// std::map languages = localization.getLanguages(); -// for (std::map ::iterator it = languages.begin(); it != languages.end(); it++) { -// language->addOption(FormField::Option((*it).second, (*it).first)); -// } form->addField(language); TextSingleFormField::ref encoding = TextSingleFormField::create(); @@ -218,6 +248,7 @@ bool UserRegistration::handleGetRequest(const Swift::JID& from, const Swift::JID } bool UserRegistration::handleSetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr payload) { + // TODO: backend should say itself if registration is needed or not... if (CONFIG_STRING(m_config, "service.protocol") == "irc") { sendError(from, id, ErrorPayload::BadRequest, ErrorPayload::Modify); return true; @@ -225,11 +256,10 @@ bool UserRegistration::handleSetRequest(const Swift::JID& from, const Swift::JID std::string barejid = from.toBare().toString(); -// AbstractUser *user = m_component->userManager()->getUserByJID(barejid); if (!CONFIG_BOOL(m_config,"registration.enable_public_registration")) { std::list const &x = CONFIG_LIST(m_config,"service.allowed_servers"); if (std::find(x.begin(), x.end(), from.getDomain()) == x.end()) { -// Log("UserRegistration", "This user has no permissions to register an account"); + LOG4CXX_INFO(logger, barejid << ": This user has no permissions to register an account") sendError(from, id, ErrorPayload::BadRequest, ErrorPayload::Modify); return true; } @@ -298,14 +328,14 @@ bool UserRegistration::handleSetRequest(const Swift::JID& from, const Swift::JID // Register or change password if (payload->getUsername()->empty() || (payload->getPassword()->empty() && CONFIG_STRING(m_config, "service.protocol") != "twitter" && CONFIG_STRING(m_config, "service.protocol") != "bonjour") -// || localization.getLanguages().find(language) == localization.getLanguages().end() ) { sendError(from, id, ErrorPayload::NotAcceptable, ErrorPayload::Modify); return true; } - if (CONFIG_STRING(m_config, "service.protocol") == "xmpp") { + // TODO: Move this check to backend somehow + if (CONFIG_STRING(m_config, "service.protocol") == "prpl-jabber") { // User tries to register himself. if ((Swift::JID(*payload->getUsername()).toBare() == from.toBare())) { sendError(from, id, ErrorPayload::NotAcceptable, ErrorPayload::Modify); @@ -322,20 +352,21 @@ bool UserRegistration::handleSetRequest(const Swift::JID& from, const Swift::JID } std::string username = *payload->getUsername(); -// m_component->protocol()->prepareUsername(username); std::string newUsername(username); if (!CONFIG_STRING(m_config, "registration.username_mask").empty()) { newUsername = CONFIG_STRING(m_config, "registration.username_mask"); -// replace(newUsername, "$username", username.c_str()); + boost::replace_all(newUsername, "$username", username); } +//TODO: Part of spectrum1 registration stuff, this should be potentially rewritten for S2 too // if (!m_component->protocol()->isValidUsername(newUsername)) { // Log("UserRegistration", "This is not valid username: "<< newUsername); // sendError(from, id, ErrorPayload::NotAcceptable, ErrorPayload::Modify); // return true; // } +//TODO: Part of spectrum1 registration stuff, this should be potentially rewritten for S2 too // #if GLIB_CHECK_VERSION(2,14,0) // if (!CONFIG_STRING(m_config, "registration.reg_allowed_usernames").empty() && // !g_regex_match_simple(CONFIG_STRING(m_config, "registration.reg_allowed_usernames"), newUsername.c_str(),(GRegexCompileFlags) (G_REGEX_CASELESS | G_REGEX_EXTENDED), (GRegexMatchFlags) 0)) { @@ -354,8 +385,6 @@ bool UserRegistration::handleSetRequest(const Swift::JID& from, const Swift::JID registerUser(res); } else { - // change passwordhttp://soumar.jabbim.cz/phpmyadmin/index.php -// Log("UserRegistration", "changing user password: "<< barejid << ", " << username); res.jid = barejid; res.password = *payload->getPassword(); res.language = language;