Files @ 441ce14dbf54
Branch filter:

Location: libtransport.git/src/usermanager.cpp - annotation

Jan Kaluza
fixed xhtmlim
c5edfd19b1aa
c5edfd19b1aa
c5edfd19b1aa
c5edfd19b1aa
c5edfd19b1aa
c5edfd19b1aa
c5edfd19b1aa
c5edfd19b1aa
c5edfd19b1aa
c5edfd19b1aa
c5edfd19b1aa
c5edfd19b1aa
c5edfd19b1aa
c5edfd19b1aa
c5edfd19b1aa
c5edfd19b1aa
c5edfd19b1aa
c5edfd19b1aa
c5edfd19b1aa
c5edfd19b1aa
c5edfd19b1aa
c5edfd19b1aa
c5edfd19b1aa
2ae880ff94b5
c8006a0ebab6
64536009a864
1e8eb7076f17
c0a01941fc10
c00d5149d528
c00d5149d528
c00d5149d528
c5edfd19b1aa
c5edfd19b1aa
c5edfd19b1aa
c00d5149d528
c00d5149d528
1e8eb7076f17
c5edfd19b1aa
c5edfd19b1aa
2ae880ff94b5
2ae880ff94b5
bb1a8e4c36e2
1e8eb7076f17
c5edfd19b1aa
bb1a8e4c36e2
bb1a8e4c36e2
bb1a8e4c36e2
bb1a8e4c36e2
c0a01941fc10
c5edfd19b1aa
c8006a0ebab6
5797b554ea69
1e8eb7076f17
1e8eb7076f17
5f017bd15dc7
c5edfd19b1aa
c5edfd19b1aa
c5edfd19b1aa
bb1a8e4c36e2
bb1a8e4c36e2
bb1a8e4c36e2
bb1a8e4c36e2
c5edfd19b1aa
c5edfd19b1aa
2ae880ff94b5
2ae880ff94b5
2ae880ff94b5
2ae880ff94b5
2ae880ff94b5
2ae880ff94b5
e5fcbf00b799
c5edfd19b1aa
c5edfd19b1aa
c5edfd19b1aa
c5edfd19b1aa
c5edfd19b1aa
c5edfd19b1aa
c5edfd19b1aa
c5edfd19b1aa
c5edfd19b1aa
c5edfd19b1aa
c5edfd19b1aa
2ae880ff94b5
2ae880ff94b5
2ae880ff94b5
2ae880ff94b5
2ae880ff94b5
2ae880ff94b5
2ae880ff94b5
2ae880ff94b5
2ae880ff94b5
c5edfd19b1aa
c5edfd19b1aa
c5edfd19b1aa
c5edfd19b1aa
2ae880ff94b5
2ae880ff94b5
2ae880ff94b5
2ae880ff94b5
8ab47cce7012
2ae880ff94b5
2ae880ff94b5
2ae880ff94b5
2ae880ff94b5
2ae880ff94b5
2ae880ff94b5
79cc6dc63de8
2ae880ff94b5
2ae880ff94b5
bb1a8e4c36e2
bb1a8e4c36e2
bb1a8e4c36e2
bb1a8e4c36e2
bb1a8e4c36e2
2ae880ff94b5
2ae880ff94b5
2ae880ff94b5
2ae880ff94b5
2ae880ff94b5
bb1a8e4c36e2
2ae880ff94b5
63a7b8eef572
63a7b8eef572
63a7b8eef572
63a7b8eef572
63a7b8eef572
63a7b8eef572
63a7b8eef572
63a7b8eef572
bb1a8e4c36e2
bb1a8e4c36e2
bb1a8e4c36e2
bb1a8e4c36e2
bb1a8e4c36e2
bb1a8e4c36e2
bb1a8e4c36e2
79cc6dc63de8
1e8eb7076f17
79cc6dc63de8
79cc6dc63de8
2ae880ff94b5
c00d5149d528
2ae880ff94b5
2ae880ff94b5
2ae880ff94b5
2ae880ff94b5
2ae880ff94b5
c5edfd19b1aa
c5edfd19b1aa
c5edfd19b1aa
c5edfd19b1aa
c5edfd19b1aa
c5edfd19b1aa
c5edfd19b1aa
c5edfd19b1aa
50bcfbf84cb1
64536009a864
2ae880ff94b5
c5edfd19b1aa
c5edfd19b1aa
c5edfd19b1aa
c5edfd19b1aa
c5edfd19b1aa
2ae880ff94b5
2ae880ff94b5
2ae880ff94b5
2ae880ff94b5
1ebe5535c4f3
1ebe5535c4f3
1ebe5535c4f3
1ebe5535c4f3
2ae880ff94b5
2ae880ff94b5
2ae880ff94b5
2ae880ff94b5
2ae880ff94b5
2ae880ff94b5
2ae880ff94b5
2ae880ff94b5
2ae880ff94b5
c5edfd19b1aa
c5edfd19b1aa
c5edfd19b1aa
2ae880ff94b5
c5edfd19b1aa
c5edfd19b1aa
c8006a0ebab6
c8006a0ebab6
c8006a0ebab6
c8006a0ebab6
c8006a0ebab6
c8006a0ebab6
c8006a0ebab6
c8006a0ebab6
c8006a0ebab6
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
5797b554ea69
9477e3f83882
9477e3f83882
9477e3f83882
9477e3f83882
9477e3f83882
9477e3f83882
9477e3f83882
9477e3f83882
9477e3f83882
9477e3f83882
9477e3f83882
9477e3f83882
9477e3f83882
9477e3f83882
c5edfd19b1aa
/**
 * 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 "transport/userregistry.h"
#include "storageresponder.h"
#include "log4cxx/logger.h"

using namespace log4cxx;

namespace Transport {

static LoggerPtr logger = Logger::getLogger("UserManager");

UserManager::UserManager(Component *component, UserRegistry *userRegistry, StorageBackend *storageBackend) {
	m_cachedUser = NULL;
	m_onlineBuddies = 0;
	m_component = component;
	m_storageBackend = storageBackend;
	m_storageResponder = NULL;
	m_userRegistry = userRegistry;

	if (m_storageBackend) {
		m_storageResponder = new StorageResponder(component->getIQRouter(), m_storageBackend, this);
		m_storageResponder->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));

	m_userRegistry->onConnectUser.connect(bind(&UserManager::connectUser, this, _1));
// 	component->onDiscoInfoResponse.connect(bind(&UserManager::handleDiscoInfoResponse, this, _1, _2, _3));
}

UserManager::~UserManager(){
	if (m_storageResponder) {
		m_storageResponder->stop();
		delete m_storageResponder;
	}
}

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;
			if (m_storageBackend) {
				bool registered = m_storageBackend->getUser(userkey, res);
				if (registered) {
					m_storageBackend->setUserOnline(res.id, false);
				}
			}
			return;
		}

		UserInfo res;
		bool registered = m_storageBackend ? m_storageBackend->getUser(userkey, res) : false;

		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, "@");
				}
				if (m_storageBackend) {
					m_storageBackend->setUser(res);
					registered = m_storageBackend->getUser(userkey, res);
				}
				else {
					registered = true;
				}
			}
			res.password = m_userRegistry->getUserPassword(userkey);
		}

		if (!registered) {
			LOG4CXX_WARN(logger, "Unregistered user " << userkey << " tried to login");
			// 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");
// 	}
}

void UserManager::connectUser(const Swift::JID &user) {
	if (m_users.find(user.toBare().toString()) != m_users.end()) {
		m_userRegistry->onPasswordValid(user);
	}
	else {
		Swift::Presence::ref response = Swift::Presence::create();
		response->setTo(m_component->getJID());
		response->setFrom(user);
		response->setType(Swift::Presence::Available);
		m_component->onUserPresenceReceived(response);
	}
}


}