Changeset - 858ac82b1966
[Not reviewed]
Merge
0 8 6
Jan Kaluza - 14 years ago 2012-01-18 09:39:47
hanzz.k@gmail.com
Merge branch 'master' of github.com:hanzz/libtransport
6 files changed with 80 insertions and 35 deletions:
0 comments (0 inline, 0 general)
backends/libpurple/main.cpp
Show inline comments
 
@@ -593,53 +593,55 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
 
				i++;
 
			}
 
			g_strfreev (keys);
 
		}
 

	
 
		void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) {
 
			PurpleAccount *account = NULL;
 
			
 
			std::string name;
 
			std::string protocol;
 
			getProtocolAndName(legacyName, name, protocol);
 

	
 
			if (password.empty()) {
 
				LOG4CXX_INFO(logger,  name.c_str() << ": Empty password");
 
				np->handleDisconnected(user, 0, "Empty password.");
 
				return;
 
			}
 

	
 
			if (!purple_find_prpl(protocol.c_str())) {
 
				LOG4CXX_INFO(logger,  name.c_str() << ": Invalid protocol '" << protocol << "'");
 
				np->handleDisconnected(user, 0, "Invalid protocol " + protocol);
 
				return;
 
			}
 

	
 
			LOG4CXX_INFO(logger,  "Creating account with name '" << name.c_str() << "' and protocol '" << protocol << "'");
 

	
 
			if (purple_accounts_find(name.c_str(), protocol.c_str()) != NULL) {
 
				LOG4CXX_INFO(logger, "Using previously created account with name '" << name.c_str() << "' and protocol '" << protocol << "'");
 
				account = purple_accounts_find(name.c_str(), protocol.c_str());
 
			}
 
			else {
 
				LOG4CXX_INFO(logger, "Creating account with name '" << name.c_str() << "' and protocol '" << protocol << "'");
 
				account = purple_account_new(name.c_str(), protocol.c_str());
 
				purple_accounts_add(account);
 
			}
 

	
 
			m_sessions[user] = account;
 
			m_accounts[account] = user;
 

	
 
			// Default avatar
 
			setDefaultAvatar(account, legacyName);
 

	
 
			purple_account_set_password(account, password.c_str());
 
			purple_account_set_bool(account, "custom_smileys", FALSE);
 
			purple_account_set_bool(account, "direct_connect", FALSE);
 

	
 
			setDefaultAccountOptions(account);
 

	
 
			purple_account_set_enabled(account, "spectrum", TRUE);
 
			if (KEYFILE_BOOL("service", "enable_privacy_lists")) {
 
				purple_account_set_privacy_type(account, PURPLE_PRIVACY_DENY_USERS);
 
			}
 

	
 
			const PurpleStatusType *status_type = purple_account_get_status_type_with_primitive(account, PURPLE_STATUS_AVAILABLE);
 
			if (status_type != NULL) {
 
				purple_account_set_status(account, purple_status_type_get_id(status_type), TRUE, NULL);
 
@@ -1067,48 +1069,50 @@ static std::vector<std::string> getGroups(PurpleBuddy *m_buddy) {
 
		GSList *buddies = purple_find_buddies(purple_buddy_get_account(m_buddy), purple_buddy_get_name(m_buddy));
 
		while(buddies) {
 
			PurpleGroup *g = purple_buddy_get_group((PurpleBuddy *) buddies->data);
 
			buddies = g_slist_delete_link(buddies, buddies);
 

	
 
			if(g && purple_group_get_name(g)) {
 
				groups.push_back(purple_group_get_name(g));
 
			}
 
		}
 
	}
 

	
 
	if (groups.empty()) {
 
		groups.push_back("Buddies");
 
	}
 

	
 
	return groups;
 
}
 

	
 
static void buddyListNewNode(PurpleBlistNode *node) {
 
	if (!PURPLE_BLIST_NODE_IS_BUDDY(node))
 
		return;
 
	PurpleBuddy *buddy = (PurpleBuddy *) node;
 
	PurpleAccount *account = purple_buddy_get_account(buddy);
 

	
 
	LOG4CXX_INFO(logger, "Buddy updated " << np->m_accounts[account] << " " << purple_buddy_get_name(buddy) << " " << getAlias(buddy));
 

	
 
	// Status
 
	pbnetwork::StatusType status = pbnetwork::STATUS_NONE;
 
	std::string message;
 
	getStatus(buddy, status, message);
 

	
 
	// Tooltip
 
	PurplePlugin *prpl = purple_find_prpl(purple_account_get_protocol_id(account));
 
	PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
 

	
 
	bool blocked = false;
 
	if (KEYFILE_BOOL("service", "enable_privacy_lists")) {
 
		if (prpl_info && prpl_info->tooltip_text) {
 
			PurpleNotifyUserInfo *user_info = purple_notify_user_info_new();
 
			prpl_info->tooltip_text(buddy, user_info, true);
 
			GList *entries = purple_notify_user_info_get_entries(user_info);
 

	
 
			while (entries) {
 
				PurpleNotifyUserInfoEntry *entry = (PurpleNotifyUserInfoEntry *)(entries->data);
 
				if (purple_notify_user_info_entry_get_label(entry) && purple_notify_user_info_entry_get_value(entry)) {
 
					std::string label = purple_notify_user_info_entry_get_label(entry);
 
					if (label == "Blocked" ) {
 
						if (std::string(purple_notify_user_info_entry_get_value(entry)) == "Yes") {
 
							blocked = true;
 
							break;
include/Swiften/Server/ServerStanzaChannel.cpp
Show inline comments
 
@@ -11,69 +11,80 @@
 
#include <boost/bind.hpp>
 

	
 
namespace Swift {
 

	
 
namespace {
 
// 	struct PriorityLessThan {
 
// 		bool operator()(const ServerSession* s1, const ServerSession* s2) const {
 
// 			return s1->getPriority() < s2->getPriority();
 
// 		}
 
// 	};
 

	
 
	struct HasJID {
 
		HasJID(const JID& jid) : jid(jid) {}
 
		bool operator()(const boost::shared_ptr<ServerFromClientSession> session) const {
 
			return session->getRemoteJID().equals(jid, JID::WithResource);
 
		}
 
		JID jid;
 
	};
 
}
 

	
 
void ServerStanzaChannel::addSession(boost::shared_ptr<ServerFromClientSession> session) {
 
	sessions[session->getRemoteJID().toBare().toString()].push_back(session);
 
	session->onSessionFinished.connect(boost::bind(&ServerStanzaChannel::handleSessionFinished, this, _1, session));
 
	session->onElementReceived.connect(boost::bind(&ServerStanzaChannel::handleElement, this, _1, session));
 
	session->onDataRead.connect(boost::bind(&ServerStanzaChannel::handleDataRead, this, _1, session));
 
}
 

	
 
void ServerStanzaChannel::removeSession(boost::shared_ptr<ServerFromClientSession> session) {
 
	session->onSessionFinished.disconnect(boost::bind(&ServerStanzaChannel::handleSessionFinished, this, _1, session));
 
	session->onElementReceived.disconnect(boost::bind(&ServerStanzaChannel::handleElement, this, _1, session));
 
	session->onDataRead.disconnect(boost::bind(&ServerStanzaChannel::handleDataRead, this, _1, session));
 
	std::list<boost::shared_ptr<ServerFromClientSession> > &lst = sessions[session->getRemoteJID().toBare().toString()];
 
	lst.erase(std::remove(lst.begin(), lst.end(), session), lst.end());
 
}
 

	
 
void ServerStanzaChannel::sendIQ(boost::shared_ptr<IQ> iq) {
 
	send(iq);
 
}
 

	
 
void ServerStanzaChannel::sendMessage(boost::shared_ptr<Message> message) {
 
	send(message);
 
}
 

	
 
void ServerStanzaChannel::sendPresence(boost::shared_ptr<Presence> presence) {
 
	send(presence);
 
}
 

	
 
void ServerStanzaChannel::handleDataRead(const SafeByteArray &data, const boost::shared_ptr<ServerFromClientSession> &session) {
 
	if (safeByteArrayToString(data).find("</stream:stream>") != std::string::npos) {
 
		Swift::Presence::ref presence = Swift::Presence::create();
 
		presence->setFrom(session->getRemoteJID());
 
		presence->setType(Swift::Presence::Unavailable);
 
		onPresenceReceived(presence);
 
	}
 
}
 

	
 
void ServerStanzaChannel::finishSession(const JID& to, boost::shared_ptr<Element> element, bool last) {
 
	std::vector<boost::shared_ptr<ServerFromClientSession> > candidateSessions;
 
	for (std::list<boost::shared_ptr<ServerFromClientSession> >::const_iterator i = sessions[to.toBare().toString()].begin(); i != sessions[to.toBare().toString()].end(); ++i) {
 
		candidateSessions.push_back(*i);
 
	}
 

	
 
	for (std::vector<boost::shared_ptr<ServerFromClientSession> >::const_iterator i = candidateSessions.begin(); i != candidateSessions.end(); ++i) {
 
		removeSession(*i);
 
		if (element) {
 
			(*i)->sendElement(element);
 
		}
 

	
 
		if (last && (*i)->getRemoteJID().isValid()) {
 
			Swift::Presence::ref presence = Swift::Presence::create();
 
			presence->setFrom((*i)->getRemoteJID());
 
			presence->setType(Swift::Presence::Unavailable);
 
			onPresenceReceived(presence);
 
		}
 

	
 
		(*i)->finishSession();
 
// 		std::cout << "FINISH SESSION " << sessions[to.toBare().toString()].size() << "\n";
 
		if (last) {
 
			break;
 
		}
include/Swiften/Server/ServerStanzaChannel.h
Show inline comments
 
@@ -20,33 +20,34 @@ namespace Swift {
 
	class ServerStanzaChannel : public StanzaChannel {
 
		public:
 
			void addSession(boost::shared_ptr<ServerFromClientSession> session);
 
			void removeSession(boost::shared_ptr<ServerFromClientSession> session);
 

	
 
			void sendIQ(boost::shared_ptr<IQ> iq);
 
			void sendMessage(boost::shared_ptr<Message> message);
 
			void sendPresence(boost::shared_ptr<Presence> presence);
 

	
 
			void finishSession(const JID& to, boost::shared_ptr<Element> element, bool last = false);
 

	
 
			bool getStreamManagementEnabled() const {
 
				return false;
 
			}
 

	
 
			bool isAvailable() const {
 
				return true;
 
			}
 

	
 
		private:
 
			std::string getNewIQID();
 
			void send(boost::shared_ptr<Stanza> stanza);
 
			void handleSessionFinished(const boost::optional<Session::SessionError>&, const boost::shared_ptr<ServerFromClientSession> &session);
 
			void handleElement(boost::shared_ptr<Element> element, const boost::shared_ptr<ServerFromClientSession> &session);
 
			void handleDataRead(const SafeByteArray &data, const boost::shared_ptr<ServerFromClientSession> &session);
 
			void handleSessionInitialized();
 

	
 
		private:
 
			IDGenerator idGenerator;
 
			// [JID][resources][ServerFromClientSession]
 
			std::map<std::string, std::list<boost::shared_ptr<ServerFromClientSession> > > sessions;
 
	};
 

	
 
}
include/transport/pqxxbackend.h
Show inline comments
 
@@ -76,33 +76,34 @@ class PQXXBackend : public StorageBackend
 
		/// \return true if user has been found in database and removed
 
		bool removeUser(long id);
 

	
 
		/// Returns JIDs of all buddies in user's roster.
 
		/// \param id id of user - UserInfo.id
 
		/// \param roster string list used to store user's roster
 
		/// \return true if user has been found in database and roster has been fetched
 
		bool getBuddies(long id, std::list<BuddyInfo> &roster);
 

	
 
		bool getOnlineUsers(std::vector<std::string> &users);
 

	
 
		long addBuddy(long userId, const BuddyInfo &buddyInfo);
 

	
 
		void updateBuddy(long userId, const BuddyInfo &buddyInfo);
 
		void removeBuddy(long id) {}
 

	
 
		void getUserSetting(long userId, const std::string &variable, int &type, std::string &value);
 
		void updateUserSetting(long userId, const std::string &variable, const std::string &value);
 

	
 
		void beginTransaction();
 
		void commitTransaction();
 

	
 
	private:
 
		bool exec(const std::string &query, bool show_error = true);
 
		bool exec(pqxx::work &txn, const std::string &query, bool show_error = true);
 
		Config *m_config;
 
		std::string m_prefix;
 

	
 
		pqxx::connection *m_conn;
 
};
 

	
 
}
 

	
 
#endif
spectrum/src/main.cpp
Show inline comments
 
@@ -375,49 +375,49 @@ int main(int argc, char **argv)
 
	}
 
#else
 
	if (CONFIG_STRING(&config, "database.type") == "mysql") {
 
		std::cerr << "Spectrum2 is not compiled with mysql backend.\n";
 
		return -2;
 
	}
 
#endif
 

	
 
#ifdef WITH_PQXX
 
	if (CONFIG_STRING(&config, "database.type") == "pqxx") {
 
		storageBackend = new PQXXBackend(&config);
 
		if (!storageBackend->connect()) {
 
			std::cerr << "Can't connect to database. Check the log to find out the reason.\n";
 
			return -1;
 
		}
 
	}
 
#else
 
	if (CONFIG_STRING(&config, "database.type") == "pqxx") {
 
		std::cerr << "Spectrum2 is not compiled with pqxx backend.\n";
 
		return -2;
 
	}
 
#endif
 

	
 
	if (CONFIG_STRING(&config, "database.type") != "mysql" && CONFIG_STRING(&config, "database.type") != "sqlite3"
 
		&& CONFIG_STRING(&config, "database.type") != "pqxx") {
 
		&& CONFIG_STRING(&config, "database.type") != "pqxx" && CONFIG_STRING(&config, "database.type") != "none") {
 
		std::cerr << "Unknown storage backend " << CONFIG_STRING(&config, "database.type") << "\n";
 
		return -2;
 
	}
 

	
 
	UserManager userManager(&transport, &userRegistry, storageBackend);
 
	userManager_ = &userManager;
 

	
 
	UserRegistration *userRegistration = NULL;
 
	UsersReconnecter *usersReconnecter = NULL;
 
	if (storageBackend) {
 
		userRegistration = new UserRegistration(&transport, &userManager, storageBackend);
 
		userRegistration->start();
 

	
 
		usersReconnecter = new UsersReconnecter(&transport, storageBackend);
 
	}
 

	
 
	FileTransferManager ftManager(&transport, &userManager);
 

	
 
	NetworkPluginServer plugin(&transport, &config, &userManager, &ftManager);
 

	
 
	AdminInterface adminInterface(&transport, &userManager, &plugin, storageBackend);
 
	StatsResponder statsResponder(&transport, &userManager, &plugin, storageBackend);
 
	statsResponder.start();
 

	
src/pqxxbackend.cpp
Show inline comments
 
@@ -58,150 +58,178 @@ bool PQXXBackend::connect() {
 

	
 
	str += "user=" + CONFIG_STRING(m_config, "database.user") + " ";
 
	m_conn = new pqxx::connection(str);
 

	
 
	createDatabase();
 

	
 
	return true;
 
}
 

	
 
bool PQXXBackend::createDatabase() {
 
	
 
	int exist = exec("SELECT * FROM " + m_prefix + "buddies_settings LIMIT 1;", false);
 

	
 
	if (!exist) {
 
		exec("CREATE TABLE " + m_prefix + "buddies_settings ("
 
				"user_id integer NOT NULL,"
 
				"buddy_id integer NOT NULL,"
 
				"var varchar(50) NOT NULL,"
 
				"type smallint NOT NULL,"
 
				"value varchar(255) NOT NULL,"
 
				"PRIMARY KEY (buddy_id,var)"
 
			");");
 
		
 
		exec("CREATE TYPE Subscription AS ENUM ('to','from','both','ask','none');");
 
		exec("CREATE TABLE IF NOT EXISTS " + m_prefix + "buddies ("
 
		exec("CREATE TABLE " + m_prefix + "buddies ("
 
							"id SERIAL,"
 
							"user_id integer NOT NULL,"
 
							"uin varchar(255) NOT NULL,"
 
							"subscription Subscription NOT NULL,"
 
							"nickname varchar(255) NOT NULL,"
 
							"groups varchar(255) NOT NULL,"
 
							"flags smallint NOT NULL DEFAULT '0',"
 
							"PRIMARY KEY (id),"
 
							"UNIQUE (user_id,uin)"
 
						");");
 
 
 
		exec("CREATE TABLE IF NOT EXISTS " + m_prefix + "users ("
 
		exec("CREATE TABLE " + m_prefix + "users ("
 
				"id SERIAL,"
 
				"jid varchar(255) NOT NULL,"
 
				"uin varchar(4095) NOT NULL,"
 
				"password varchar(255) NOT NULL,"
 
				"language varchar(25) NOT NULL,"
 
				"encoding varchar(50) NOT NULL default 'utf8',"
 
				"last_login timestamp,"
 
				"vip boolean NOT NULL  default '0',"
 
				"online boolean NOT NULL  default '0',"
 
				"PRIMARY KEY (id),"
 
				"UNIQUE (jid)"
 
			");");
 

	
 
		exec("CREATE TABLE IF NOT EXISTS " + m_prefix + "users_settings ("
 
		exec("CREATE TABLE " + m_prefix + "users_settings ("
 
				"user_id integer NOT NULL,"
 
				"var varchar(50) NOT NULL,"
 
				"type smallint NOT NULL,"
 
				"value varchar(255) NOT NULL,"
 
				"PRIMARY KEY (user_id,var)"
 
			");");
 

	
 
		exec("CREATE TABLE IF NOT EXISTS " + m_prefix + "db_version ("
 
		exec("CREATE TABLE " + m_prefix + "db_version ("
 
				"ver integer NOT NULL default '1',"
 
				"UNIQUE (ver)"
 
			");");
 

	
 
// 		exec("INSERT INTO db_version (ver) VALUES ('2');");
 
	}
 

	
 
	return true;
 
}
 

	
 
bool PQXXBackend::exec(const std::string &query, bool show_error) {
 
	pqxx::work txn(*m_conn);
 
	return exec(txn, query, show_error);
 
}
 

	
 
bool PQXXBackend::exec(pqxx::work &txn, const std::string &query, bool show_error) {
 
	try {
 
		txn.exec(query);
 
		txn.commit();
 
	}
 
	catch (std::exception& e) {
 
		if (show_error)
 
			LOG4CXX_ERROR(logger, e.what());
 
		return false;
 
	}
 
	return true;
 
}
 

	
 
void PQXXBackend::setUser(const UserInfo &user) {
 
//	std::string encrypted = user.password;
 
//	if (!CONFIG_STRING(m_config, "database.encryption_key").empty()) {
 
//		encrypted = Util::encryptPassword(encrypted, CONFIG_STRING(m_config, "database.encryption_key"));
 
//	}
 
//	*m_setUser << user.jid << user.uin << encrypted << user.language << user.encoding << user.vip << user.uin << encrypted;
 
//	EXEC(m_setUser, setUser(user));
 
	std::string encrypted = user.password;
 
	if (!CONFIG_STRING(m_config, "database.encryption_key").empty()) {
 
		encrypted = Util::encryptPassword(encrypted, CONFIG_STRING(m_config, "database.encryption_key"));
 
	}
 
	pqxx::work txn(*m_conn);
 
	exec(txn, "UPDATE " + m_prefix + "users SET uin=" + txn.quote(user.uin) + ", password=" + txn.quote(encrypted) + ";"
 
		"INSERT INTO " + m_prefix + "users (jid, uin, password, language, encoding, last_login, vip) VALUES "
 
		 "(" + txn.quote(user.jid) + ","
 
		+ txn.quote(user.uin) + ","
 
		+ txn.quote(encrypted) + ","
 
		+ txn.quote(user.language) + ","
 
		+ txn.quote(user.encoding) + ","
 
		+ "NOW(),"
 
		+ txn.quote(user.vip) +")");
 
}
 

	
 
bool PQXXBackend::getUser(const std::string &barejid, UserInfo &user) {
 
//	*m_getUser << barejid;
 
//	EXEC(m_getUser, getUser(barejid, user));
 
//	if (!exec_ok)
 
//		return false;
 
	try {
 
		pqxx::work txn(*m_conn);
 

	
 
	int ret = false;
 
//	while (m_getUser->fetch() == 0) {
 
//		ret = true;
 
//		*m_getUser >> user.id >> user.jid >> user.uin >> user.password >> user.encoding >> user.language >> user.vip;
 
		pqxx::result r = txn.exec("SELECT id, jid, uin, password, encoding, language, vip FROM " + m_prefix + "users WHERE jid="
 
			+ txn.quote(barejid));
 

	
 
//		if (!CONFIG_STRING(m_config, "database.encryption_key").empty()) {
 
//			user.password = Util::decryptPassword(user.password, CONFIG_STRING(m_config, "database.encryption_key"));
 
//		}
 
//	}
 
		if (r.size() == 0) {
 
			return false;
 
		}
 

	
 
	return ret;
 
		user.id = r[0][0].as<int>();
 
		user.jid = r[0][1].as<std::string>();
 
		user.uin = r[0][2].as<std::string>();
 
		user.password = r[0][3].as<std::string>();
 
		user.encoding = r[0][4].as<std::string>();
 
		user.language = r[0][5].as<std::string>();
 
		user.vip = r[0][6].as<bool>();
 
	}
 
	catch (std::exception& e) {
 
		LOG4CXX_ERROR(logger, e.what());
 
		return false;
 
	}
 

	
 
	return true;
 
}
 

	
 
void PQXXBackend::setUserOnline(long id, bool online) {
 
//	*m_setUserOnline << online << id;
 
//	EXEC(m_setUserOnline, setUserOnline(id, online));
 
	try {
 
		pqxx::work txn(*m_conn);
 
		exec(txn, "UPDATE " + m_prefix + "users SET online=" + txn.quote(online) + ", last_login=NOW() WHERE id=" + txn.quote(id));
 
	}
 
	catch (std::exception& e) {
 
		LOG4CXX_ERROR(logger, e.what());
 
	}
 
}
 

	
 
bool PQXXBackend::getOnlineUsers(std::vector<std::string> &users) {
 
//	EXEC(m_getOnlineUsers, getOnlineUsers(users));
 
//	if (!exec_ok)
 
//		return false;
 
	try {
 
		pqxx::work txn(*m_conn);
 
		pqxx::result r = txn.exec("SELECT jid FROM " + m_prefix + "users WHERE online=1");
 

	
 
//	std::string jid;
 
//	while (m_getOnlineUsers->fetch() == 0) {
 
//		*m_getOnlineUsers >> jid;
 
//		users.push_back(jid);
 
//	}
 
		for (pqxx::result::const_iterator it = r.begin(); it != r.end(); it++)  {
 
			users.push_back((*it)[0].as<std::string>());
 
		}
 
	}
 
	catch (std::exception& e) {
 
		LOG4CXX_ERROR(logger, e.what());
 
		return false;
 
	}
 

	
 
	return true;
 
}
 

	
 
long PQXXBackend::addBuddy(long userId, const BuddyInfo &buddyInfo) {
 
// 	"INSERT INTO " + m_prefix + "buddies (user_id, uin, subscription, groups, nickname, flags) VALUES (?, ?, ?, ?, ?, ?)"
 
//	std::string groups = Util::serializeGroups(buddyInfo.groups);
 
//	*m_addBuddy << userId << buddyInfo.legacyName << buddyInfo.subscription;
 
//	*m_addBuddy << groups;
 
//	*m_addBuddy << buddyInfo.alias << buddyInfo.flags;
 

	
 
//	EXEC(m_addBuddy, addBuddy(userId, buddyInfo));
 

	
 
//	long id = (long) mysql_insert_id(&m_conn);
 

	
 
// 	INSERT OR REPLACE INTO " + m_prefix + "buddies_settings (user_id, buddy_id, var, type, value) VALUES (?, ?, ?, ?, ?)
 
//	if (!buddyInfo.settings.find("icon_hash")->second.s.empty()) {
 
//		*m_updateBuddySetting << userId << id << buddyInfo.settings.find("icon_hash")->first << (int) TYPE_STRING << buddyInfo.settings.find("icon_hash")->second.s << buddyInfo.settings.find("icon_hash")->second.s;
 
//		EXEC(m_updateBuddySetting, addBuddy(userId, buddyInfo));
 
//	}
 

	
 
	return 0;
 
}
 

	
0 comments (0 inline, 0 general)