Changeset - 96fb9b61e85a
[Not reviewed]
0 7 0
HanzZ - 14 years ago 2011-06-05 11:35:37
hanzz.k@gmail.com
Store icon_hask into databa => working avatars
7 files changed with 83 insertions and 28 deletions:
0 comments (0 inline, 0 general)
backends/libpurple/main.cpp
Show inline comments
 
@@ -193,138 +193,150 @@ static std::string getIconHash(PurpleBuddy *m_buddy) {
 
	if (icon) {
 
		avatarHash = purple_buddy_icon_get_full_path(icon);
 
	}
 

	
 
	if (avatarHash) {
 
		// Check if it's patched libpurple which saves icons to directories
 
		char *hash = strrchr(avatarHash,'/');
 
		std::string h;
 
		if (hash) {
 
			char *dot;
 
			hash++;
 
			dot = strchr(hash, '.');
 
			if (dot)
 
				*dot = '\0';
 

	
 
			std::string ret(hash);
 
			g_free(avatarHash);
 
			return ret;
 
		}
 
		else {
 
			std::string ret(avatarHash);
 
			g_free(avatarHash);
 
			return ret;
 
		}
 
	}
 

	
 
	return "";
 
}
 

	
 
static std::vector<std::string> getGroups(PurpleBuddy *m_buddy) {
 
	std::vector<std::string> groups;
 
	groups.push_back(purple_group_get_name(purple_buddy_get_group(m_buddy)) ? std::string(purple_group_get_name(purple_buddy_get_group(m_buddy))) : std::string("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);
 

	
 
	Swift::StatusShow status;
 
	std::string message;
 
	getStatus(buddy, status, message);
 

	
 
	np->handleBuddyChanged(np->m_accounts[account], purple_buddy_get_name(buddy), getAlias(buddy), getGroups(buddy)[0], (int) status.getType(), message, getIconHash(buddy));
 
}
 

	
 
static void buddyStatusChanged(PurpleBuddy *buddy, PurpleStatus *status_, PurpleStatus *old_status) {
 
	PurpleAccount *account = purple_buddy_get_account(buddy);
 

	
 
	Swift::StatusShow status;
 
	std::string message;
 
	getStatus(buddy, status, message);
 

	
 
	np->handleBuddyChanged(np->m_accounts[account], purple_buddy_get_name(buddy), getAlias(buddy), getGroups(buddy)[0], (int) status.getType(), message, getIconHash(buddy));
 
}
 

	
 
static void buddySignedOn(PurpleBuddy *buddy) {
 
	PurpleAccount *account = purple_buddy_get_account(buddy);
 

	
 
	Swift::StatusShow status;
 
	std::string message;
 
	getStatus(buddy, status, message);
 

	
 
	np->handleBuddyChanged(np->m_accounts[account], purple_buddy_get_name(buddy), getAlias(buddy), getGroups(buddy)[0], (int) status.getType(), message, getIconHash(buddy));
 
}
 
// static void buddyStatusChanged(PurpleBuddy *buddy, PurpleStatus *status_, PurpleStatus *old_status) {
 
// 	PurpleAccount *account = purple_buddy_get_account(buddy);
 
// 
 
// 	Swift::StatusShow status;
 
// 	std::string message;
 
// 	getStatus(buddy, status, message);
 
// 
 
// 	np->handleBuddyChanged(np->m_accounts[account], purple_buddy_get_name(buddy), getAlias(buddy), getGroups(buddy)[0], (int) status.getType(), message, getIconHash(buddy));
 
// }
 
// 
 
// static void buddySignedOn(PurpleBuddy *buddy) {
 
// 	PurpleAccount *account = purple_buddy_get_account(buddy);
 
// 
 
// 	Swift::StatusShow status;
 
// 	std::string message;
 
// 	getStatus(buddy, status, message);
 
// 
 
// 	np->handleBuddyChanged(np->m_accounts[account], purple_buddy_get_name(buddy), getAlias(buddy), getGroups(buddy)[0], (int) status.getType(), message, getIconHash(buddy));
 
// }
 
// 
 
// static void buddySignedOff(PurpleBuddy *buddy) {
 
// 	PurpleAccount *account = purple_buddy_get_account(buddy);
 
// 
 
// 	Swift::StatusShow status;
 
// 	std::string message;
 
// 	getStatus(buddy, status, message);
 
// 
 
// 	np->handleBuddyChanged(np->m_accounts[account], purple_buddy_get_name(buddy), getAlias(buddy), getGroups(buddy)[0], (int) status.getType(), message, getIconHash(buddy));
 
// }
 

	
 
static void buddySignedOff(PurpleBuddy *buddy) {
 
void buddyListUpdate(PurpleBuddyList *list, PurpleBlistNode *node) {
 
	if (!PURPLE_BLIST_NODE_IS_BUDDY(node))
 
		return;
 
	PurpleBuddy *buddy = (PurpleBuddy *) node;
 
	PurpleAccount *account = purple_buddy_get_account(buddy);
 

	
 
	Swift::StatusShow status;
 
	std::string message;
 
	getStatus(buddy, status, message);
 

	
 
	np->handleBuddyChanged(np->m_accounts[account], purple_buddy_get_name(buddy), getAlias(buddy), getGroups(buddy)[0], (int) status.getType(), message, getIconHash(buddy));
 
}
 

	
 
static void NodeRemoved(PurpleBlistNode *node, void *data) {
 
	if (!PURPLE_BLIST_NODE_IS_BUDDY(node))
 
		return;
 
// 	PurpleBuddy *buddy = (PurpleBuddy *) node;
 
}
 

	
 
static PurpleBlistUiOps blistUiOps =
 
{
 
	NULL,
 
	buddyListNewNode,
 
	NULL,
 
	NULL, // buddyListUpdate,
 
	buddyListUpdate,
 
	NULL, //NodeRemoved,
 
	NULL,
 
	NULL,
 
	NULL, // buddyListAddBuddy,
 
	NULL,
 
	NULL,
 
	NULL, //buddyListSaveNode,
 
	NULL, //buddyListRemoveNode,
 
	NULL, //buddyListSaveAccount,
 
	NULL
 
};
 

	
 
static void conv_write_im(PurpleConversation *conv, const char *who, const char *message, PurpleMessageFlags flags, time_t mtime) {
 
	// Don't forwards our own messages.
 
	if (flags & PURPLE_MESSAGE_SEND || flags & PURPLE_MESSAGE_SYSTEM)
 
		return;
 
	PurpleAccount *account = purple_conversation_get_account(conv);
 

	
 
	char *striped = purple_markup_strip_html(message);
 
	std::string msg = striped;
 
	g_free(striped);
 

	
 
	std::string w = who;
 
	size_t pos = w.find("/");
 
	if (pos != std::string::npos)
 
		w.erase((int) pos, w.length() - (int) pos);
 

	
 
	np->handleMessage(np->m_accounts[account], w, msg);
 
}
 

	
 
static PurpleConversationUiOps conversation_ui_ops =
 
{
 
	NULL,
 
	NULL,
 
	NULL,//conv_write_chat,                              /* write_chat           */
 
	conv_write_im,             /* write_im             */
 
	NULL,//conv_write_conv,           /* write_conv           */
 
	NULL,//conv_chat_add_users,       /* chat_add_users       */
 
	NULL,//conv_chat_rename_user,     /* chat_rename_user     */
 
	NULL,//conv_chat_remove_users,    /* chat_remove_users    */
 
	NULL,//pidgin_conv_chat_update_user,     /* chat_update_user     */
 
	NULL,//pidgin_conv_present_conversation, /* present              */
 
	NULL,//pidgin_conv_has_focus,            /* has_focus            */
 
	NULL,//pidgin_conv_custom_smiley_add,    /* custom_smiley_add    */
 
	NULL,//pidgin_conv_custom_smiley_write,  /* custom_smiley_write  */
 
	NULL,//pidgin_conv_custom_smiley_close,  /* custom_smiley_close  */
 
	NULL,//pidgin_conv_send_confirm,         /* send_confirm         */
 
	NULL,
 
@@ -498,99 +510,99 @@ static PurpleDebugUiOps debugUiOps =
 
};
 

	
 
static bool initPurple(Config &cfg) {
 
	bool ret;
 

	
 
	purple_util_set_user_dir("./");
 
	remove("./accounts.xml");
 
	remove("./blist.xml");
 

	
 
// 	if (m_configuration.logAreas & LOG_AREA_PURPLE)
 
		purple_debug_set_ui_ops(&debugUiOps);
 

	
 
	purple_core_set_ui_ops(&coreUiOps);
 
	purple_eventloop_set_ui_ops(getEventLoopUiOps());
 

	
 
	ret = purple_core_init("spectrum");
 
	if (ret) {
 
		static int blist_handle;
 

	
 
		purple_set_blist(purple_blist_new());
 
		purple_blist_load();
 

	
 
		purple_prefs_load();
 

	
 
		/* Good default preferences */
 
		/* The combination of these two settings mean that libpurple will never
 
		 * (of its own accord) set all the user accounts idle.
 
		 */
 
		purple_prefs_set_bool("/purple/away/away_when_idle", false);
 
		/*
 
		 * This must be set to something not "none" for idle reporting to work
 
		 * for, e.g., the OSCAR prpl. We don't implement the UI ops, so this is
 
		 * okay for now.
 
		 */
 
		purple_prefs_set_string("/purple/away/idle_reporting", "system");
 

	
 
		/* Disable all logging */
 
		purple_prefs_set_bool("/purple/logging/log_ims", false);
 
		purple_prefs_set_bool("/purple/logging/log_chats", false);
 
		purple_prefs_set_bool("/purple/logging/log_system", false);
 

	
 

	
 
// 		purple_signal_connect(purple_conversations_get_handle(), "received-im-msg", &conversation_handle, PURPLE_CALLBACK(newMessageReceived), NULL);
 
// 		purple_signal_connect(purple_conversations_get_handle(), "buddy-typing", &conversation_handle, PURPLE_CALLBACK(buddyTyping), NULL);
 
// 		purple_signal_connect(purple_conversations_get_handle(), "buddy-typed", &conversation_handle, PURPLE_CALLBACK(buddyTyped), NULL);
 
// 		purple_signal_connect(purple_conversations_get_handle(), "buddy-typing-stopped", &conversation_handle, PURPLE_CALLBACK(buddyTypingStopped), NULL);
 
		purple_signal_connect(purple_connections_get_handle(), "signed-on", &blist_handle,PURPLE_CALLBACK(signed_on), NULL);
 
// 		purple_signal_connect(purple_blist_get_handle(), "buddy-removed", &blist_handle,PURPLE_CALLBACK(buddyRemoved), NULL);
 
		purple_signal_connect(purple_blist_get_handle(), "buddy-signed-on", &blist_handle,PURPLE_CALLBACK(buddySignedOn), NULL);
 
		purple_signal_connect(purple_blist_get_handle(), "buddy-signed-off", &blist_handle,PURPLE_CALLBACK(buddySignedOff), NULL);
 
		purple_signal_connect(purple_blist_get_handle(), "buddy-status-changed", &blist_handle,PURPLE_CALLBACK(buddyStatusChanged), NULL);
 
// 		purple_signal_connect(purple_blist_get_handle(), "buddy-signed-on", &blist_handle,PURPLE_CALLBACK(buddySignedOn), NULL);
 
// 		purple_signal_connect(purple_blist_get_handle(), "buddy-signed-off", &blist_handle,PURPLE_CALLBACK(buddySignedOff), NULL);
 
// 		purple_signal_connect(purple_blist_get_handle(), "buddy-status-changed", &blist_handle,PURPLE_CALLBACK(buddyStatusChanged), NULL);
 
		purple_signal_connect(purple_blist_get_handle(), "blist-node-removed", &blist_handle,PURPLE_CALLBACK(NodeRemoved), NULL);
 
// 		purple_signal_connect(purple_conversations_get_handle(), "chat-topic-changed", &conversation_handle, PURPLE_CALLBACK(conv_chat_topic_changed), NULL);
 
// 
 
// 		purple_commands_init();
 

	
 
	}
 
	return ret;
 
}
 

	
 

	
 
int main(int argc, char **argv) {
 
	GError *error = NULL;
 
	GOptionContext *context;
 
	context = g_option_context_new("config_file_name or profile name");
 
	g_option_context_add_main_entries(context, options_entries, "");
 
	if (!g_option_context_parse (context, &argc, &argv, &error)) {
 
		std::cout << "option parsing failed: " << error->message << "\n";
 
		return -1;
 
	}
 

	
 
	if (ver) {
 
// 		std::cout << VERSION << "\n";
 
		std::cout << "verze\n";
 
		g_option_context_free(context);
 
		return 0;
 
	}
 

	
 
	if (argc != 2) {
 
#ifdef WIN32
 
		std::cout << "Usage: spectrum.exe <configuration_file.cfg>\n";
 
#else
 

	
 
#if GLIB_CHECK_VERSION(2,14,0)
 
	std::cout << g_option_context_get_help(context, FALSE, NULL);
 
#else
 
	std::cout << "Usage: spectrum <configuration_file.cfg>\n";
 
	std::cout << "See \"man spectrum\" for more info.\n";
 
#endif
 
		
 
#endif
 
	}
 
	else {
 
#ifndef WIN32
 
// 		signal(SIGPIPE, SIG_IGN);
 
// 
 
// 		if (signal(SIGCHLD, spectrum_sigchld_handler) == SIG_ERR) {
 
// 			std::cout << "SIGCHLD handler can't be set\n";
 
// 			g_option_context_free(context);
include/transport/sqlite3backend.h
Show inline comments
 
@@ -64,53 +64,54 @@ class SQLite3Backend : public StorageBackend
 
		bool getUser(const std::string &barejid, UserInfo &user);
 

	
 
		/// Changes users online state variable in database.
 
		/// \param id id of user - UserInfo.id
 
		/// \param online online state
 
		void setUserOnline(long id, bool online);
 

	
 
		/// Removes user and all connected data from database.
 
		/// \param id id of user - UserInfo.id
 
		/// \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);
 

	
 
		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);
 

	
 
		sqlite3 *m_db;
 
		Config *m_config;
 
		std::string m_prefix;
 

	
 
		// statements
 
		sqlite3_stmt *m_setUser;
 
		sqlite3_stmt *m_getUser;
 
		sqlite3_stmt *m_getUserSetting;
 
		sqlite3_stmt *m_setUserSetting;
 
		sqlite3_stmt *m_updateUserSetting;
 
		sqlite3_stmt *m_removeUser;
 
		sqlite3_stmt *m_removeUserBuddies;
 
		sqlite3_stmt *m_removeUserSettings;
 
		sqlite3_stmt *m_removeUserBuddiesSettings;
 
		sqlite3_stmt *m_addBuddy;
 
		sqlite3_stmt *m_updateBuddy;
 
		sqlite3_stmt *m_updateBuddySetting;
 
		sqlite3_stmt *m_getBuddies;
 
		sqlite3_stmt *m_getBuddiesSettings;
 
};
 

	
 
}
src/buddy.cpp
Show inline comments
 
@@ -64,99 +64,99 @@ const Swift::JID &Buddy::getJID() {
 
}
 

	
 
void Buddy::setOnline() {
 
	m_online = true;
 
}
 

	
 
void Buddy::setOffline() {
 
	m_online = false;
 
	m_lastPresence = Swift::Presence::ref();
 
}
 

	
 
bool Buddy::isOnline() {
 
	return m_online;
 
}
 

	
 
void Buddy::setSubscription(const std::string &subscription) {
 
	m_subscription = subscription;
 
}
 

	
 
const std::string &Buddy::getSubscription() {
 
	return m_subscription;
 
}
 

	
 
Swift::Presence::ref Buddy::generatePresenceStanza(int features, bool only_new) {
 
	std::string alias = getAlias();
 
	std::string name = getSafeName();
 

	
 
	Swift::StatusShow s;
 
	std::string statusMessage;
 
	if (!getStatus(s, statusMessage))
 
		return Swift::Presence::ref();
 

	
 
	Swift::Presence::ref presence = Swift::Presence::create();
 
 	presence->setFrom(m_jid);
 
	presence->setTo(m_rosterManager->getUser()->getJID().toBare());
 
	presence->setType(Swift::Presence::Available);
 

	
 
	if (!statusMessage.empty())
 
		presence->setStatus(statusMessage);
 

	
 
	if (s.getType() == Swift::StatusShow::None)
 
		presence->setType(Swift::Presence::Unavailable);
 
	presence->setShow(s.getType());
 

	
 
	if (presence->getType() != Swift::Presence::Unavailable) {
 
		// caps
 
// 		presence->addPayload(boost::shared_ptr<Swift::Payload>(new Swift::CapsInfo (CONFIG().caps)));
 

	
 
		if (features & 0/*TRANSPORT_FEATURE_AVATARS*/) {
 
// 		if (features & 0/*TRANSPORT_FEATURE_AVATARS*/) {
 
			presence->addPayload(boost::shared_ptr<Swift::Payload>(new Swift::VCardUpdate (getIconHash())));
 
		}
 
// 		}
 
	}
 

	
 
	if (only_new) {
 
		if (m_lastPresence)
 
			m_lastPresence->setTo(Swift::JID(""));
 
		if (m_lastPresence == presence) {
 
			return Swift::Presence::ref();
 
		}
 
		m_lastPresence = presence;
 
	}
 

	
 
	return presence;
 
}
 

	
 
std::string Buddy::getSafeName() {
 
	if (m_jid.isValid()) {
 
		return m_jid.getNode();
 
	}
 
	std::string name = getName();
 
// 	Transport::instance()->protocol()->prepareUsername(name, purple_buddy_get_account(m_buddy));
 
	if (getFlags() & BUDDY_JID_ESCAPING) {
 
		name = Swift::JID::getEscapedNode(name);
 
	}
 
	else {
 
		if (name.find_last_of("@") != std::string::npos) {
 
			name.replace(name.find_last_of("@"), 1, "%");
 
		}
 
	}
 
// 	if (name.empty()) {
 
// 		Log("SpectrumBuddy::getSafeName", "Name is EMPTY! Previous was " << getName() << ".");
 
// 	}
 
	return name;
 
}
 

	
 
void Buddy::buddyChanged() {
 
	Swift::Presence::ref presence = generatePresenceStanza(255);
 
	if (presence) {
 
		m_rosterManager->getUser()->getComponent()->getStanzaChannel()->sendPresence(presence);
 
	}
 
}
 

	
 
void Buddy::handleVCardReceived(const std::string &id, const Swift::JID &to, Swift::VCard::ref vcard) {
 
	boost::shared_ptr<Swift::GenericRequest<Swift::VCard> > request(new Swift::GenericRequest<Swift::VCard>(Swift::IQ::Result, m_rosterManager->getUser()->getJID(), vcard, m_rosterManager->getUser()->getComponent()->getIQRouter()));
 
	request->send();
 
}
 

	
 
std::string Buddy::JIDToLegacyName(const Swift::JID &jid) {
 
	std::string name;
src/networkpluginserver.cpp
Show inline comments
 
@@ -24,96 +24,98 @@
 
#include "transport/storagebackend.h"
 
#include "transport/rostermanager.h"
 
#include "transport/usermanager.h"
 
#include "transport/conversationmanager.h"
 
#include "transport/localbuddy.h"
 
#include "transport/config.h"
 
#include "transport/conversation.h"
 
#include "transport/vcardresponder.h"
 
#include "Swiften/Swiften.h"
 
#include "Swiften/Server/ServerStanzaChannel.h"
 
#include "Swiften/Elements/StreamError.h"
 
#include "pbnetwork.pb.h"
 
#include "sys/wait.h"
 
#include "sys/signal.h"
 

	
 
namespace Transport {
 

	
 
class NetworkConversation : public Conversation {
 
	public:
 
		NetworkConversation(ConversationManager *conversationManager, const std::string &legacyName, bool muc = false) : Conversation(conversationManager, legacyName, muc) {
 
		}
 

	
 
		void sendMessage(boost::shared_ptr<Swift::Message> &message) {
 
			onMessageToSend(this, message);
 
		}
 

	
 
		boost::signal<void (NetworkConversation *, boost::shared_ptr<Swift::Message> &)> onMessageToSend;
 
};
 

	
 
class NetworkFactory : public Factory {
 
	public:
 
		NetworkFactory(NetworkPluginServer *nps) {
 
			m_nps = nps;
 
		}
 
		
 
		Conversation *createConversation(ConversationManager *conversationManager, const std::string &legacyName) {
 
			NetworkConversation *nc = new NetworkConversation(conversationManager, legacyName);
 
			nc->onMessageToSend.connect(boost::bind(&NetworkPluginServer::handleMessageReceived, m_nps, _1, _2));
 
			return nc;
 
		}
 

	
 
		Buddy *createBuddy(RosterManager *rosterManager, const BuddyInfo &buddyInfo) {
 
			LocalBuddy *buddy = new LocalBuddy(rosterManager, buddyInfo.id);
 
			buddy->setAlias(buddyInfo.alias);
 
			buddy->setName(buddyInfo.legacyName);
 
			buddy->setSubscription(buddyInfo.subscription);
 
			buddy->setGroups(buddyInfo.groups);
 
			buddy->setFlags((BuddyFlag) buddyInfo.flags);
 
			if (buddyInfo.settings.find("icon_hash") != buddyInfo.settings.end())
 
				buddy->setIconHash(buddyInfo.settings.find("icon_hash")->second.s);
 
			return buddy;
 
		}
 
	private:
 
		NetworkPluginServer *m_nps;
 
};
 

	
 
#define WRAP(MESSAGE, TYPE) 	pbnetwork::WrapperMessage wrap; \
 
	wrap.set_type(TYPE); \
 
	wrap.set_payload(MESSAGE); \
 
	wrap.SerializeToString(&MESSAGE);
 
	
 
static int exec_(const char *path, const char *host, const char *port, const char *config) {
 
// 	char *argv[] = {(char*)script_name, '\0'}; 
 
	int status = 0;
 
	pid_t pid = fork();
 
	if ( pid == 0 ) {
 
		// child process
 
		execlp(path, path, "--host", host, "--port", port, config, NULL);
 
		exit(1);
 
	} else if ( pid < 0 ) {
 
		// fork failed
 
		status = -1;
 
	}
 
	return status;
 
}
 

	
 
static void SigCatcher(int n) {
 
	wait3(NULL,WNOHANG,NULL);
 
}
 

	
 
static void handleBuddyPayload(LocalBuddy *buddy, const pbnetwork::Buddy &payload) {
 
	buddy->setName(payload.buddyname());
 
	buddy->setAlias(payload.alias());
 
	std::vector<std::string> groups;
 
	groups.push_back(payload.groups());
 
	buddy->setGroups(groups);
 
	buddy->setStatus(Swift::StatusShow((Swift::StatusShow::Type) payload.status()), payload.statusmessage());
 
	buddy->setIconHash(payload.iconhash());
 
}
 

	
 
NetworkPluginServer::NetworkPluginServer(Component *component, Config *config, UserManager *userManager) {
 
	m_userManager = userManager;
 
	m_config = config;
 
	m_component = component;
 
	m_component->m_factory = new NetworkFactory(this);
 
	m_userManager->onUserCreated.connect(boost::bind(&NetworkPluginServer::handleUserCreated, this, _1));
 
	m_userManager->onUserDestroyed.connect(boost::bind(&NetworkPluginServer::handleUserDestroyed, this, _1));
 

	
src/rostermanager.cpp
Show inline comments
 
@@ -2,96 +2,104 @@
 
 * XMPP - libpurple transport
 
 *
 
 * Copyright (C) 2009, Jan Kaluza <hanzz@soc.pidgin.im>
 
 *
 
 * 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/rostermanager.h"
 
#include "transport/rosterstorage.h"
 
#include "transport/storagebackend.h"
 
#include "transport/buddy.h"
 
#include "transport/usermanager.h"
 
#include "transport/buddy.h"
 
#include "transport/user.h"
 
#include "Swiften/Roster/SetRosterRequest.h"
 
#include "Swiften/Elements/RosterPayload.h"
 
#include "Swiften/Elements/RosterItemPayload.h"
 
#include "Swiften/Elements/RosterItemExchangePayload.h"
 

	
 
namespace Transport {
 

	
 
RosterManager::RosterManager(User *user, Component *component){
 
	m_rosterStorage = NULL;
 
	m_user = user;
 
	m_component = component;
 
	m_setBuddyTimer = m_component->getFactories()->getTimerFactory()->createTimer(1000);
 
	m_RIETimer = m_component->getFactories()->getTimerFactory()->createTimer(5000);
 
	m_RIETimer->onTick.connect(boost::bind(&RosterManager::sendRIE, this));
 

	
 
	
 

	
 
}
 

	
 
RosterManager::~RosterManager() {
 
	m_setBuddyTimer->stop();
 
	m_RIETimer->stop();
 
	if (m_rosterStorage) {
 
		for (std::map<std::string, Buddy *>::const_iterator it = m_buddies.begin(); it != m_buddies.end(); it++) {
 
			Buddy *buddy = (*it).second;
 
			m_rosterStorage->storeBuddy(buddy);
 
		}
 
		m_rosterStorage->storeBuddies();
 
	}
 

	
 
	for (std::map<std::string, Buddy *>::const_iterator it = m_buddies.begin(); it != m_buddies.end(); it++) {
 
		Buddy *buddy = (*it).second;
 
		delete buddy;
 
	}
 
	if (m_rosterStorage)
 
		delete m_rosterStorage;
 
}
 

	
 
void RosterManager::setBuddy(Buddy *buddy) {
 
// 	m_setBuddyTimer->onTick.connect(boost::bind(&RosterManager::setBuddyCallback, this, buddy));
 
// 	m_setBuddyTimer->start();
 
	setBuddyCallback(buddy);
 
}
 

	
 
void RosterManager::sendBuddyRosterPush(Buddy *buddy) {
 
	Swift::RosterPayload::ref payload = Swift::RosterPayload::ref(new Swift::RosterPayload());
 
	Swift::RosterItemPayload item;
 
	item.setJID(buddy->getJID().toBare());
 
	item.setName(buddy->getAlias());
 
	item.setGroups(buddy->getGroups());
 

	
 
	payload->addItem(item);
 

	
 
	Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(payload, m_user->getJID().toBare(), m_component->getIQRouter());
 
	request->onResponse.connect(boost::bind(&RosterManager::handleBuddyRosterPushResponse, this, _1, buddy->getName()));
 
	request->send();
 
}
 

	
 
void RosterManager::setBuddyCallback(Buddy *buddy) {
 
	m_setBuddyTimer->onTick.disconnect(boost::bind(&RosterManager::setBuddyCallback, this, buddy));
 

	
 
	std::cout << "ADDING " << buddy->getName() << "\n";
 
	m_buddies[buddy->getName()] = buddy;
 
	onBuddySet(buddy);
 

	
 
	// In server mode the only way is to send jabber:iq:roster push.
 
	// In component mode we send RIE or Subscribe presences, based on features.
 
	if (m_component->inServerMode()) {
 
		sendBuddyRosterPush(buddy);
 
	}
 
	else {
 
		if (m_setBuddyTimer->onTick.empty()) {
 
			m_setBuddyTimer->stop();
 
			if (true /*&& rie_is_supported*/) {
 
				m_RIETimer->start();
 
			}
 
		}
 
	}
src/rosterstorage.cpp
Show inline comments
 
@@ -61,78 +61,80 @@ namespace Transport {
 
// 	else {
 
// 		id = Transport::instance()->sql()->addBuddy(user->storageId(), name, s_buddy->getSubscription(), s_buddy->getGroup(), alias, s_buddy->getFlags());
 
// 		s_buddy->setId(id);
 
// 	}
 
// 	Log("buddyListSaveNode", id << " " << name << " " << alias << " " << s_buddy->getSubscription());
 
// 	if (s_buddy->getBuddy() && id != -1) {
 
// 		PurpleBuddy *buddy = s_buddy->getBuddy();
 
// 		SaveData *s = new SaveData;
 
// 		s->user = user;
 
// 		s->id = id;
 
// 		g_hash_table_foreach(buddy->node.settings, save_settings, s);
 
// 		delete s;
 
// 	}
 
// 	return TRUE;
 
// }
 

	
 
RosterStorage::RosterStorage(User *user, StorageBackend *storageBackend) {
 
	m_user = user;
 
	m_storageBackend = storageBackend;
 
	m_storageTimer = m_user->getComponent()->getFactories()->getTimerFactory()->createTimer(5000);
 
	m_storageTimer->onTick.connect(boost::bind(&RosterStorage::storeBuddies, this));
 
}
 

	
 
RosterStorage::~RosterStorage() {
 
	m_storageTimer->stop();
 
}
 

	
 
void RosterStorage::storeBuddy(Buddy *buddy) {
 
	m_buddies[buddy->getName()] = buddy;
 
	m_storageTimer->start();
 
}
 

	
 
bool RosterStorage::storeBuddies() {
 
	if (m_buddies.size() == 0) {
 
		return false;
 
	}
 
	
 
	m_storageBackend->beginTransaction();
 

	
 
	for (std::map<std::string, Buddy *>::const_iterator it = m_buddies.begin(); it != m_buddies.end(); it++) {
 
		Buddy *buddy = (*it).second;
 
		BuddyInfo buddyInfo;
 
		buddyInfo.alias = buddy->getAlias();
 
		buddyInfo.legacyName = buddy->getName();
 
		buddyInfo.groups = buddy->getGroups();
 
		buddyInfo.subscription = buddy->getSubscription();
 
		buddyInfo.id = buddy->getID();
 
		buddyInfo.flags = buddy->getFlags();
 
		buddyInfo.settings["icon_hash"].s = buddy->getIconHash();
 
		buddyInfo.settings["icon_hash"].type = TYPE_STRING;
 

	
 
		// Buddy is in DB
 
		if (buddyInfo.id != -1) {
 
			m_storageBackend->updateBuddy(m_user->getUserInfo().id, buddyInfo);
 
		}
 
		else {
 
			buddyInfo.id = m_storageBackend->addBuddy(m_user->getUserInfo().id, buddyInfo);
 
			buddy->setID(buddyInfo.id);
 
		}
 

	
 
// 		Log("buddyListSaveNode", id << " " << name << " " << alias << " " << s_buddy->getSubscription());
 
// 		if (s_buddy->getBuddy() && id != -1) {
 
// 			PurpleBuddy *buddy = s_buddy->getBuddy();
 
// 			SaveData *s = new SaveData;
 
// 			s->user = user;
 
// 			s->id = id;
 
// 			g_hash_table_foreach(buddy->node.settings, save_settings, s);
 
// 			delete s;
 
// 		}
 
	}
 

	
 
	m_storageBackend->commitTransaction();
 
	return true;
 
}
 

	
 
void RosterStorage::removeBuddyFromQueue(Buddy *buddy) {
 
	m_buddies.erase(buddy->getName());
 
}
 

	
 
}
src/sqlite3backend.cpp
Show inline comments
 
@@ -44,121 +44,124 @@
 
#define BEGIN(STATEMENT) 	sqlite3_reset(STATEMENT);\
 
							int STATEMENT##_id = 1;\
 
							int STATEMENT##_id_get = 0;\
 
							(void)STATEMENT##_id_get;
 

	
 
#define BIND_INT(STATEMENT, VARIABLE) sqlite3_bind_int(STATEMENT, STATEMENT##_id++, VARIABLE)
 
#define BIND_STR(STATEMENT, VARIABLE) sqlite3_bind_text(STATEMENT, STATEMENT##_id++, VARIABLE.c_str(), -1, SQLITE_STATIC)
 
#define RESET_GET_COUNTER(STATEMENT)	STATEMENT##_id_get = 0;
 
#define GET_INT(STATEMENT)	sqlite3_column_int(STATEMENT, STATEMENT##_id_get++)
 
#define GET_STR(STATEMENT)	(const char *) sqlite3_column_text(STATEMENT, STATEMENT##_id_get++)
 
#define EXECUTE_STATEMENT(STATEMENT, NAME) 	if(sqlite3_step(STATEMENT) != SQLITE_DONE) {\
 
		onStorageError(NAME, (sqlite3_errmsg(m_db) == NULL ? "" : sqlite3_errmsg(m_db)));\
 
			}
 

	
 
using namespace boost;
 

	
 
namespace Transport {
 

	
 
SQLite3Backend::SQLite3Backend(Config *config) {
 
	m_config = config;
 
	m_db = NULL;
 
	m_prefix = CONFIG_STRING(m_config, "database.prefix");
 
}
 

	
 
SQLite3Backend::~SQLite3Backend(){
 
	if (m_db) {
 
		// Would be nice to use this:
 
		//
 
		//   sqlite3_stmt *pStmt;
 
		//   while((pStmt = sqlite3_next_stmt(db, 0)) != 0 ) {
 
		//    sqlite3_finalize(pStmt);
 
		//   }
 
		//
 
		// But requires SQLite3 >= 3.6.0 beta
 
	
 
		FINALIZE_STMT(m_setUser);
 
		FINALIZE_STMT(m_getUser);
 
		FINALIZE_STMT(m_removeUser);
 
		FINALIZE_STMT(m_removeUserBuddies);
 
		FINALIZE_STMT(m_removeUserSettings);
 
		FINALIZE_STMT(m_removeUserBuddiesSettings);
 
		FINALIZE_STMT(m_addBuddy);
 
		FINALIZE_STMT(m_updateBuddy);
 
		FINALIZE_STMT(m_getBuddies);
 
		FINALIZE_STMT(m_getBuddiesSettings);
 
		FINALIZE_STMT(m_getUserSetting);
 
		FINALIZE_STMT(m_setUserSetting);
 
		FINALIZE_STMT(m_updateUserSetting);
 
		FINALIZE_STMT(m_updateBuddySetting);
 
		sqlite3_close(m_db);
 
	}
 
}
 

	
 
bool SQLite3Backend::connect() {
 
	if (sqlite3_open(CONFIG_STRING(m_config, "database.database").c_str(), &m_db)) {
 
		sqlite3_close(m_db);
 
		return false;
 
	}
 

	
 
	if (createDatabase() == false)
 
		return false;
 

	
 
	PREP_STMT(m_setUser, "INSERT INTO " + m_prefix + "users (jid, uin, password, language, encoding, last_login, vip) VALUES (?, ?, ?, ?, ?, DATETIME('NOW'), ?)");
 
	PREP_STMT(m_getUser, "SELECT id, jid, uin, password, encoding, language, vip FROM " + m_prefix + "users WHERE jid=?");
 

	
 
	PREP_STMT(m_removeUser, "DELETE FROM " + m_prefix + "users WHERE id=?");
 
	PREP_STMT(m_removeUserBuddies, "DELETE FROM " + m_prefix + "buddies WHERE user_id=?");
 
	PREP_STMT(m_removeUserSettings, "DELETE FROM " + m_prefix + "users_settings WHERE user_id=?");
 
	PREP_STMT(m_removeUserBuddiesSettings, "DELETE FROM " + m_prefix + "buddies_settings WHERE user_id=?");
 

	
 
	PREP_STMT(m_addBuddy, "INSERT INTO " + m_prefix + "buddies (user_id, uin, subscription, groups, nickname, flags) VALUES (?, ?, ?, ?, ?, ?)");
 
	PREP_STMT(m_updateBuddy, "UPDATE " + m_prefix + "buddies SET groups=?, nickname=?, flags=?, subscription=? WHERE user_id=? AND uin=?");
 
	PREP_STMT(m_getBuddies, "SELECT id, uin, subscription, nickname, groups, flags FROM " + m_prefix + "buddies WHERE user_id=? ORDER BY id ASC");
 
	PREP_STMT(m_getBuddiesSettings, "SELECT buddy_id, type, var, value FROM " + m_prefix + "buddies_settings WHERE user_id=? ORDER BY buddy_id ASC");
 
	PREP_STMT(m_updateBuddySetting, "INSERT OR REPLACE INTO " + m_prefix + "buddies_settings (user_id, buddy_id, var, type, value) VALUES (?, ?, ?, ?, ?)");
 
	
 
	PREP_STMT(m_getUserSetting, "SELECT type, value FROM " + m_prefix + "users_settings WHERE user_id=? AND var=?");
 
	PREP_STMT(m_setUserSetting, "INSERT INTO " + m_prefix + "users_settings (user_id, var, type, value) VALUES (?,?,?,?)");
 
	PREP_STMT(m_updateUserSetting, "UPDATE " + m_prefix + "users_settings SET value=? WHERE user_id=? AND var=?");
 

	
 
	return true;
 
}
 

	
 
bool SQLite3Backend::createDatabase() {
 
	int not_exist = exec("CREATE TABLE " + m_prefix + "buddies ("
 
				"  id INTEGER PRIMARY KEY NOT NULL,"
 
				"  user_id int(10) NOT NULL,"
 
				"  uin varchar(255) NOT NULL,"
 
				"  subscription varchar(20) NOT NULL,"
 
				"  nickname varchar(255) NOT NULL,"
 
				"  groups varchar(255) NOT NULL,"
 
				"  flags int(4) NOT NULL DEFAULT '0'"
 
				");");
 

	
 
	if (not_exist) {
 
		exec("CREATE UNIQUE INDEX IF NOT EXISTS user_id ON " + m_prefix + "buddies (user_id, uin);");
 

	
 
		exec("CREATE TABLE IF NOT EXISTS " + m_prefix + "buddies_settings ("
 
					"  user_id int(10) NOT NULL,"
 
					"  buddy_id int(10) NOT NULL,"
 
					"  var varchar(50) NOT NULL,"
 
					"  type int(4) NOT NULL,"
 
					"  value varchar(255) NOT NULL,"
 
					"  PRIMARY KEY (buddy_id, var)"
 
					");");
 

	
 
		exec("CREATE INDEX IF NOT EXISTS user_id02 ON " + m_prefix + "buddies_settings (user_id);");
 

	
 
		exec("CREATE TABLE IF NOT EXISTS " + m_prefix + "users ("
 
					"  id INTEGER PRIMARY KEY NOT NULL,"
 
					"  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 datetime,"
 
					"  vip int(1) NOT NULL DEFAULT '0',"
 
					"  online int(1) NOT NULL DEFAULT '0'"
 
					");");
 

	
 
		exec("CREATE UNIQUE INDEX IF NOT EXISTS jid ON " + m_prefix + "users (jid);");
 

	
 
		exec("CREATE TABLE " + m_prefix + "users_settings ("
 
					"  user_id int(10) NOT NULL,"
 
@@ -200,157 +203,184 @@ void SQLite3Backend::setUser(const UserInfo &user) {
 

	
 
	if(sqlite3_step(m_setUser) != SQLITE_DONE) {
 
		onStorageError("setUser query", (sqlite3_errmsg(m_db) == NULL ? "" : sqlite3_errmsg(m_db)));
 
	}
 
}
 

	
 
bool SQLite3Backend::getUser(const std::string &barejid, UserInfo &user) {
 
// 	SELECT id, jid, uin, password, encoding, language, vip FROM " + m_prefix + "users WHERE jid=?
 
	sqlite3_reset(m_getUser);
 
	sqlite3_bind_text(m_getUser, 1, barejid.c_str(), -1, SQLITE_TRANSIENT);
 

	
 
	int ret;
 
	while((ret = sqlite3_step(m_getUser)) == SQLITE_ROW) {
 
		user.id = sqlite3_column_int(m_getUser, 0);
 
		user.jid = (const char *) sqlite3_column_text(m_getUser, 1);
 
		user.uin = (const char *) sqlite3_column_text(m_getUser, 2);
 
		user.password = (const char *) sqlite3_column_text(m_getUser, 3);
 
		user.encoding = (const char *) sqlite3_column_text(m_getUser, 4);
 
		user.language = (const char *) sqlite3_column_text(m_getUser, 5);
 
		user.vip = sqlite3_column_int(m_getUser, 6);
 
		return true;
 
	}
 

	
 
	if (ret != SQLITE_DONE) {
 
		onStorageError("getUser query", (sqlite3_errmsg(m_db) == NULL ? "" : sqlite3_errmsg(m_db)));
 
	}
 

	
 
	return false;
 
}
 

	
 
void SQLite3Backend::setUserOnline(long id, bool online) {
 
	
 
}
 

	
 
long SQLite3Backend::addBuddy(long userId, const BuddyInfo &buddyInfo) {
 
// 	"INSERT INTO " + m_prefix + "buddies (user_id, uin, subscription, groups, nickname, flags) VALUES (?, ?, ?, ?, ?, ?)"
 
	BEGIN(m_addBuddy);
 
	BIND_INT(m_addBuddy, userId);
 
	BIND_STR(m_addBuddy, buddyInfo.legacyName);
 
	BIND_STR(m_addBuddy, buddyInfo.subscription);
 
	BIND_STR(m_addBuddy, buddyInfo.groups[0]); // TODO: serialize groups
 
	BIND_STR(m_addBuddy, buddyInfo.alias);
 
	BIND_INT(m_addBuddy, buddyInfo.flags);
 

	
 
	if(sqlite3_step(m_addBuddy) != SQLITE_DONE) {
 
		onStorageError("addBuddy query", (sqlite3_errmsg(m_db) == NULL ? "" : sqlite3_errmsg(m_db)));
 
		return -1;
 
	}
 
	return (long) sqlite3_last_insert_rowid(m_db);
 

	
 
	long id = (long) sqlite3_last_insert_rowid(m_db);
 

	
 
// 	INSERT OR REPLACE INTO " + m_prefix + "buddies_settings (user_id, buddy_id, var, type, value) VALUES (?, ?, ?, ?, ?)
 
	BEGIN(m_updateBuddySetting);
 
	BIND_INT(m_updateBuddySetting, userId);
 
	BIND_INT(m_updateBuddySetting, id);
 
	BIND_STR(m_updateBuddySetting, buddyInfo.settings.find("icon_hash")->first);
 
	BIND_INT(m_updateBuddySetting, TYPE_STRING);
 
	BIND_STR(m_updateBuddySetting, buddyInfo.settings.find("icon_hash")->second.s);
 

	
 
	EXECUTE_STATEMENT(m_updateBuddySetting, "updateBuddySetting query");
 
	return id;
 
}
 

	
 
void SQLite3Backend::updateBuddy(long userId, const BuddyInfo &buddyInfo) {
 
// 	UPDATE " + m_prefix + "buddies SET groups=?, nickname=?, flags=?, subscription=? WHERE user_id=? AND uin=?
 
	BEGIN(m_updateBuddy);
 
	BIND_STR(m_updateBuddy, buddyInfo.groups[0]); // TODO: serialize groups
 
	BIND_STR(m_updateBuddy, buddyInfo.alias);
 
	BIND_INT(m_updateBuddy, buddyInfo.flags);
 
	BIND_STR(m_updateBuddy, buddyInfo.subscription);
 
	BIND_INT(m_updateBuddy, userId);
 
	BIND_STR(m_updateBuddy, buddyInfo.legacyName);
 

	
 
	EXECUTE_STATEMENT(m_updateBuddy, "updateBuddy query");
 

	
 
// 	INSERT OR REPLACE INTO " + m_prefix + "buddies_settings (user_id, buddy_id, var, type, value) VALUES (?, ?, ?, ?, ?)
 
	BEGIN(m_updateBuddySetting);
 
	BIND_INT(m_updateBuddySetting, userId);
 
	BIND_INT(m_updateBuddySetting, buddyInfo.id);
 
	BIND_STR(m_updateBuddySetting, buddyInfo.settings.find("icon_hash")->first);
 
	BIND_INT(m_updateBuddySetting, TYPE_STRING);
 
	BIND_STR(m_updateBuddySetting, buddyInfo.settings.find("icon_hash")->second.s);
 

	
 
	EXECUTE_STATEMENT(m_updateBuddySetting, "updateBuddySetting query");
 
}
 

	
 
bool SQLite3Backend::getBuddies(long id, std::list<BuddyInfo> &roster) {
 
//	SELECT id, uin, subscription, nickname, groups, flags FROM " + m_prefix + "buddies WHERE user_id=? ORDER BY id ASC
 
	BEGIN(m_getBuddies);
 
	BIND_INT(m_getBuddies, id);
 

	
 
// 	"SELECT buddy_id, type, var, value FROM " + m_prefix + "buddies_settings WHERE user_id=? ORDER BY buddy_id ASC"
 
	BEGIN(m_getBuddiesSettings);
 
	BIND_INT(m_getBuddiesSettings, id);
 

	
 
	SettingVariableInfo var;
 
	long buddy_id = -1;
 
	std::string key;
 

	
 
	int ret;
 
	while((ret = sqlite3_step(m_getBuddies)) == SQLITE_ROW) {
 
		BuddyInfo b;
 
		RESET_GET_COUNTER(m_getBuddies);
 
		b.id = GET_INT(m_getBuddies);
 
		b.legacyName = GET_STR(m_getBuddies);
 
		b.subscription = GET_STR(m_getBuddies);
 
		b.alias = GET_STR(m_getBuddies);
 
		b.groups.push_back(GET_STR(m_getBuddies));
 
		b.flags = GET_INT(m_getBuddies);
 

	
 
		if (buddy_id == b.id) {
 
			std::cout << "Adding buddy info " << key << "\n";
 
			b.settings[key] = var;
 
			buddy_id = -1;
 
		}
 

	
 
		while(buddy_id == -1 && (ret = sqlite3_step(m_getBuddiesSettings)) == SQLITE_ROW) {
 
			RESET_GET_COUNTER(m_getBuddiesSettings);
 
			buddy_id = GET_INT(m_getBuddiesSettings);
 
			
 
			var.type = GET_INT(m_getBuddiesSettings);
 
			key = GET_STR(m_getBuddiesSettings);
 
			std::string val = GET_STR(m_getBuddiesSettings);
 

	
 
			switch (var.type) {
 
				case TYPE_BOOLEAN:
 
					var.b = atoi(val.c_str());
 
					break;
 
				case TYPE_STRING:
 
					var.s = val;
 
					break;
 
				default:
 
					if (buddy_id == b.id) {
 
						buddy_id = -1;
 
					}
 
					continue;
 
					break;
 
			}
 
			if (buddy_id == b.id) {
 
				std::cout << "Adding buddy info " << key << "=" << val << "\n";
 
				b.settings[key] = var;
 
				buddy_id = -1;
 
			}
 
		}
 

	
 
// 		if (ret != SQLITE_DONE) {
 
// 			onStorageError("getBuddiesSettings query", (sqlite3_errmsg(m_db) == NULL ? "" : sqlite3_errmsg(m_db)));
 
// 			return false;
 
// 		}
 

	
 
		roster.push_back(b);
 
	}
 

	
 
	if (ret != SQLITE_DONE) {
 
		onStorageError("getBuddies query", (sqlite3_errmsg(m_db) == NULL ? "" : sqlite3_errmsg(m_db)));
 
		return false;
 
	}
 
	
 
	return true;
 
}
 

	
 
bool SQLite3Backend::removeUser(long id) {
 
	sqlite3_reset(m_removeUser);
 
	sqlite3_bind_int(m_removeUser, 1, id);
 
	if(sqlite3_step(m_removeUser) != SQLITE_DONE) {
 
		onStorageError("removeUser query", (sqlite3_errmsg(m_db) == NULL ? "" : sqlite3_errmsg(m_db)));
 
		return false;
 
	}
 

	
 
	sqlite3_reset(m_removeUserSettings);
 
	sqlite3_bind_int(m_removeUserSettings, 1, id);
 
	if(sqlite3_step(m_removeUserSettings) != SQLITE_DONE) {
 
		onStorageError("removeUserSettings query", (sqlite3_errmsg(m_db) == NULL ? "" : sqlite3_errmsg(m_db)));
 
		return false;
 
	}
 

	
 
	sqlite3_reset(m_removeUserBuddies);
 
	sqlite3_bind_int(m_removeUserBuddies, 1, id);
 
	if(sqlite3_step(m_removeUserBuddies) != SQLITE_DONE) {
 
		onStorageError("removeUserBuddies query", (sqlite3_errmsg(m_db) == NULL ? "" : sqlite3_errmsg(m_db)));
 
		return false;
 
	}
 

	
 
	sqlite3_reset(m_removeUserBuddiesSettings);
0 comments (0 inline, 0 general)