spectrum2/src/usermanager.cpp
2011-05-31 17:03:24 +02:00

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");
// }
}
}