241 lines
8 KiB
C++
241 lines
8 KiB
C++
/**
|
|
* libtransport -- C++ library for easy XMPP Transports development
|
|
*
|
|
* Copyright (C) 2011, Jan Kaluza <hanzz.k@gmail.com>
|
|
*
|
|
* 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/usermanager.h"
|
|
#include "transport/user.h"
|
|
#include "transport/transport.h"
|
|
#include "transport/storagebackend.h"
|
|
#include "transport/conversationmanager.h"
|
|
#include "transport/rostermanager.h"
|
|
#include "storageresponder.h"
|
|
#include "rosterresponder.h"
|
|
#include "vcardresponder.h"
|
|
|
|
namespace Transport {
|
|
|
|
UserManager::UserManager(Component *component, StorageBackend *storageBackend) {
|
|
m_cachedUser = NULL;
|
|
m_onlineBuddies = 0;
|
|
m_component = component;
|
|
m_storageBackend = storageBackend;
|
|
|
|
m_storageResponder = new StorageResponder(component->getIQRouter(), m_storageBackend, this);
|
|
m_storageResponder->start();
|
|
|
|
m_rosterResponder = new RosterResponder(component->getIQRouter(), m_storageBackend, this);
|
|
m_rosterResponder->start();
|
|
|
|
m_vcardResponder = new VCardResponder(component->getIQRouter(), m_storageBackend, this);
|
|
m_vcardResponder->start();
|
|
|
|
component->onUserPresenceReceived.connect(bind(&UserManager::handlePresence, this, _1));
|
|
m_component->getStanzaChannel()->onMessageReceived.connect(bind(&UserManager::handleMessageReceived, this, _1));
|
|
m_component->getStanzaChannel()->onPresenceReceived.connect(bind(&UserManager::handleGeneralPresenceReceived, this, _1));
|
|
// component->onDiscoInfoResponse.connect(bind(&UserManager::handleDiscoInfoResponse, this, _1, _2, _3));
|
|
}
|
|
|
|
UserManager::~UserManager(){
|
|
m_storageResponder->stop();
|
|
delete m_storageResponder;
|
|
delete m_rosterResponder;
|
|
delete m_vcardResponder;
|
|
}
|
|
|
|
void UserManager::addUser(User *user) {
|
|
m_users[user->getJID().toBare().toString()] = user;
|
|
onUserCreated(user);
|
|
}
|
|
|
|
User *UserManager::getUser(const std::string &barejid){
|
|
if (m_cachedUser && barejid == m_cachedUser->getJID().toBare().toString()) {
|
|
return m_cachedUser;
|
|
}
|
|
|
|
if (m_users.find(barejid) != m_users.end()) {
|
|
User *user = m_users[barejid];
|
|
m_cachedUser = user;
|
|
return user;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void UserManager::removeUser(User *user) {
|
|
m_users.erase(user->getJID().toBare().toString());
|
|
if (m_cachedUser == user)
|
|
m_cachedUser = NULL;
|
|
onUserDestroyed(user);
|
|
delete user;
|
|
}
|
|
|
|
int UserManager::getUserCount() {
|
|
return m_users.size();
|
|
}
|
|
|
|
void UserManager::handlePresence(Swift::Presence::ref presence) {
|
|
std::string barejid = presence->getTo().toBare().toString();
|
|
std::string userkey = presence->getFrom().toBare().toString();
|
|
|
|
User *user = getUser(userkey);
|
|
if (!user) {
|
|
// No user and unavailable presence -> answer with unavailable
|
|
if (presence->getType() == Swift::Presence::Unavailable) {
|
|
Swift::Presence::ref response = Swift::Presence::create();
|
|
response->setTo(presence->getFrom());
|
|
response->setFrom(presence->getTo());
|
|
response->setType(Swift::Presence::Unavailable);
|
|
m_component->getStanzaChannel()->sendPresence(response);
|
|
|
|
UserInfo res;
|
|
bool registered = m_storageBackend->getUser(userkey, res);
|
|
if (registered) {
|
|
m_storageBackend->setUserOnline(res.id, false);
|
|
}
|
|
return;
|
|
}
|
|
|
|
UserInfo res;
|
|
bool registered = m_storageBackend->getUser(userkey, res);
|
|
|
|
if (m_component->inServerMode()) {
|
|
if (!registered) {
|
|
res.password = "";
|
|
res.uin = presence->getFrom().getNode();
|
|
res.jid = userkey;
|
|
if (res.uin.find_last_of("%") != std::string::npos) {
|
|
res.uin.replace(res.uin.find_last_of("%"), 1, "@");
|
|
}
|
|
m_storageBackend->setUser(res);
|
|
registered = m_storageBackend->getUser(userkey, res);
|
|
}
|
|
res.password = m_component->getUserRegistryPassword(userkey);
|
|
}
|
|
|
|
if (!registered) {
|
|
// TODO: logging
|
|
return;
|
|
}
|
|
|
|
// TODO: isVIP
|
|
// // bool isVip = res.vip;
|
|
// // std::list<std::string> const &x = CONFIG().allowedServers;
|
|
// // if (CONFIG().onlyForVIP && !isVip && std::find(x.begin(), x.end(), presence->getFrom().getDomain().getUTF8String()) == x.end()) {
|
|
// // Log(presence->getFrom().toString().getUTF8String(), "This user is not VIP, can't login...");
|
|
// // return;
|
|
// // }
|
|
// //
|
|
// //
|
|
user = new User(presence->getFrom(), res, m_component, this);
|
|
user->getRosterManager()->setStorageBackend(m_storageBackend);
|
|
// TODO: handle features somehow
|
|
// // user->setFeatures(isVip ? CONFIG().VIPFeatures : CONFIG().transportFeatures);
|
|
// // // if (c != NULL)
|
|
// // // if (Transport::instance()->hasClientCapabilities(c->findAttribute("ver")))
|
|
// // // user->setResource(stanza.from().resource(), stanza.priority(), Transport::instance()->getCapabilities(c->findAttribute("ver")));
|
|
// // //
|
|
addUser(user);
|
|
}
|
|
user->handlePresence(presence);
|
|
|
|
bool isMUC = presence->getPayload<Swift::MUCPayload>() != NULL || *presence->getTo().getNode().c_str() == '#';
|
|
if (isMUC)
|
|
return;
|
|
|
|
if (presence->getType() == Swift::Presence::Unavailable) {
|
|
if (user) {
|
|
Swift::Presence::ref highest = m_component->getPresenceOracle()->getHighestPriorityPresence(presence->getFrom().toBare());
|
|
// There's no presence for this user, so disconnect
|
|
if (!highest || (highest && highest->getType() == Swift::Presence::Unavailable)) {
|
|
removeUser(user);
|
|
}
|
|
}
|
|
// TODO: HANDLE MUC SOMEHOW
|
|
// else if (user && Transport::instance()->protocol()->tempAccountsAllowed() && !((User *) user)->hasOpenedMUC()) {
|
|
// Transport::instance()->userManager()->removeUser(user);
|
|
// }
|
|
}
|
|
}
|
|
|
|
void UserManager::handleMessageReceived(Swift::Message::ref message) {
|
|
User *user = getUser(message->getFrom().toBare().toString());
|
|
if (!user ){
|
|
return;
|
|
}
|
|
|
|
user->getConversationManager()->handleMessageReceived(message);
|
|
}
|
|
|
|
void UserManager::handleGeneralPresenceReceived(Swift::Presence::ref presence) {
|
|
switch(presence->getType()) {
|
|
case Swift::Presence::Subscribe:
|
|
case Swift::Presence::Subscribed:
|
|
case Swift::Presence::Unsubscribe:
|
|
case Swift::Presence::Unsubscribed:
|
|
handleSubscription(presence);
|
|
break;
|
|
case Swift::Presence::Available:
|
|
case Swift::Presence::Unavailable:
|
|
break;
|
|
case Swift::Presence::Probe:
|
|
handleProbePresence(presence);
|
|
break;
|
|
default:
|
|
break;
|
|
};
|
|
}
|
|
|
|
void UserManager::handleProbePresence(Swift::Presence::ref presence) {
|
|
|
|
}
|
|
|
|
void UserManager::handleSubscription(Swift::Presence::ref presence) {
|
|
// answer to subscibe for transport itself
|
|
if (presence->getType() == Swift::Presence::Subscribe && presence->getTo().getNode().empty()) {
|
|
Swift::Presence::ref response = Swift::Presence::create();
|
|
response->setFrom(presence->getTo());
|
|
response->setTo(presence->getFrom());
|
|
response->setType(Swift::Presence::Subscribed);
|
|
m_component->getStanzaChannel()->sendPresence(response);
|
|
|
|
response = Swift::Presence::create();
|
|
response->setFrom(presence->getTo());
|
|
response->setTo(presence->getFrom());
|
|
response->setType(Swift::Presence::Subscribe);
|
|
m_component->getStanzaChannel()->sendPresence(response);
|
|
return;
|
|
}
|
|
|
|
User *user = getUser(presence->getFrom().toBare().toString());
|
|
|
|
if (user) {
|
|
user->handleSubscription(presence);
|
|
}
|
|
else if (presence->getType() == Swift::Presence::Unsubscribe) {
|
|
Swift::Presence::ref response = Swift::Presence::create();
|
|
response->setFrom(presence->getTo());
|
|
response->setTo(presence->getFrom());
|
|
response->setType(Swift::Presence::Unsubscribed);
|
|
m_component->getStanzaChannel()->sendPresence(response);
|
|
}
|
|
// else {
|
|
// // Log(presence->getFrom().toString().getUTF8String(), "Subscribe presence received, but this user is not logged in");
|
|
// }
|
|
}
|
|
|
|
}
|