soc.2009.transport: df1bcd1a: Added fist support for more networks whe...

hanzz at soc.pidgin.im hanzz at soc.pidgin.im
Wed Jul 8 06:21:14 EDT 2009


-----------------------------------------------------------------
Revision: df1bcd1abffc000060e72cbf51963d52a5e06116
Ancestor: 19ccfab6a5c710a9aeaf4f97fcb41281915065ce
Author: hanzz at soc.pidgin.im
Date: 2009-07-08T10:17:36
Branch: im.pidgin.soc.2009.transport
URL: http://d.pidgin.im/viewmtn/revision/info/df1bcd1abffc000060e72cbf51963d52a5e06116

Modified files:
        main.cpp muchandler.cpp protocols/abstractprotocol.h
        protocols/irc.h user.cpp user.h usermanager.cpp
        usermanager.h

ChangeLog: 

Added fist support for more networks when using IRC.

-------------- next part --------------
============================================================
--- main.cpp	f46041ac93f13d8539a87a80f8a16df860bdcfd9
+++ main.cpp	e0f407e8249bf0ef194d20b688f32f902d5c25d4
@@ -1119,8 +1119,15 @@ void GlooxMessageHandler::handleSubscrip
 		reply->addAttribute( "type", "subscribed" );
 		j->send( reply );
 	}
-	
-	User *user = userManager()->getUserByJID(stanza.from().bare());
+
+	User *user;
+	if (protocol()->isMUC(NULL, stanza.to().bare())) {
+		std::string server = stanza.to().username().substr(stanza.to().username().find("%") + 1, stanza.to().username().length() - stanza.to().username().find("%"));
+		user = userManager()->getUserByJID(stanza.from().bare() + server);
+	}
+	else {
+		user = userManager()->getUserByJID(stanza.from().bare());
+	}
 	if (user)
 		user->receivedSubscription(stanza);
 	
@@ -1134,7 +1141,7 @@ void GlooxMessageHandler::handlePresence
 	Tag *c = NULL;
 	Log().Get(stanza.from().full()) << "Presence received (" << stanza.subtype() << ") for: " << stanza.to().full();
 
-	if (stanza.presence() != Presence::Unavailable && stanza.to().username() == ""){
+	if (stanza.presence() != Presence::Unavailable && ((stanza.to().username() == "" && !protocol()->tempAccountsAllowed()) || protocol()->isMUC(NULL, stanza.to().bare()))){
 		Tag *stanzaTag = stanza.tag();
 		if (!stanzaTag) return;
 		Tag *c = stanzaTag->findChildWithAttrib("xmlns","http://jabber.org/protocol/caps");
@@ -1168,8 +1175,14 @@ void GlooxMessageHandler::handlePresence
 		}
 		delete stanzaTag;
 	}
-
-	User *user = userManager()->getUserByJID(stanza.from().bare());
+	User *user;
+	if (protocol()->isMUC(NULL, stanza.to().bare())) {
+		std::string server = stanza.to().username().substr(stanza.to().username().find("%") + 1, stanza.to().username().length() - stanza.to().username().find("%"));
+		user = userManager()->getUserByJID(stanza.from().bare() + server);
+	}
+	else {
+		user = userManager()->getUserByJID(stanza.from().bare());
+	}
 	if (user==NULL){
 		// we are not connected and probe arrived => answer with unavailable
 		if (stanza.subtype() == Presence::Probe){
@@ -1180,9 +1193,9 @@ void GlooxMessageHandler::handlePresence
 			tag->addAttribute("type","unavailable");
 			j->send(tag);
 		}
-		else if (stanza.to().username() == "" && stanza.presence() != Presence::Unavailable){
+		else if (((stanza.to().username() == "" && !protocol()->tempAccountsAllowed()) || protocol()->isMUC(NULL, stanza.to().bare())) && stanza.presence() != Presence::Unavailable){
 			UserRow res = sql()->getUserByJid(stanza.from().bare());
-			if(res.id==-1) {
+			if(res.id==-1 && !protocol()->tempAccountsAllowed()) {
 				// presence from unregistered user
 				Log().Get(stanza.from().full()) << "This user is not registered";
 				return;
@@ -1196,7 +1209,13 @@ void GlooxMessageHandler::handlePresence
 				}
 
 				Log().Get(stanza.from().full()) << "Creating new User instance";
-				user = new User(this, stanza.from(), res.uin, res.password);
+				if (protocol()->tempAccountsAllowed()) {
+					std::string server = stanza.to().username().substr(stanza.to().username().find("%") + 1, stanza.to().username().length() - stanza.to().username().find("%"));
+					std::cout << "SERVER" << stanza.from().bare() + server << "\n";
+					user = new User(this, stanza.from(), stanza.to().resource() + "@" + server, "", stanza.from().bare() + server);
+				}
+				else
+					user = new User(this, stanza.from(), res.uin, res.password, stanza.from().bare());
 				if (c!=NULL)
 					if(hasCaps(c->findAttribute("ver")))
 						user->setResource(stanza.from().resource(), stanza.priority(), c->findAttribute("ver"));
@@ -1218,7 +1237,13 @@ void GlooxMessageHandler::handlePresence
 // 				user->init(this);
 				m_userManager->addUser(user);
 				user->receivedPresence(stanza);
-				g_timeout_add(15000,&connectUser,g_strdup(stanza.from().bare().c_str()));
+				if (protocol()->isMUC(NULL, stanza.to().bare())) {
+					std::string server = stanza.to().username().substr(stanza.to().username().find("%") + 1, stanza.to().username().length() - stanza.to().username().find("%"));
+					server = stanza.from().bare() + server;
+					g_timeout_add(15000,&connectUser,g_strdup(server.c_str()));
+				}
+				else
+					g_timeout_add(15000,&connectUser,g_strdup(stanza.from().bare().c_str()));
 			}
 		}
 		if (stanza.presence() == Presence::Unavailable && stanza.to().username() == ""){
@@ -1282,14 +1307,21 @@ void GlooxMessageHandler::handleMessage 
 void GlooxMessageHandler::handleMessage (const Message &msg, MessageSession *session) {
 	if (msg.from().bare() == msg.to().bare())
 		return;
-	User *user = userManager()->getUserByJID(msg.from().bare());
+	User *user;
+	if (protocol()->isMUC(NULL, msg.to().bare())) {
+		std::string server = msg.to().username().substr(msg.to().username().find("%") + 1, msg.to().username().length() - msg.to().username().find("%"));
+		user = userManager()->getUserByJID(msg.from().bare() + server);
+	}
+	else {
+		user = userManager()->getUserByJID(msg.from().bare());
+	}
 	if (user!=NULL){
 		if (user->isConnected()){
 			Tag *msgTag = msg.tag();
 			if (!msgTag) return;
 			Tag *chatstates = msgTag->findChildWithAttrib("xmlns","http://jabber.org/protocol/chatstates");
 			if (chatstates!=NULL){
-				std::string username;
+				std::string username = msg.to().username();
 				std::for_each( username.begin(), username.end(), replaceJidCharacters() );
 				user->receivedChatState(username,chatstates->name());
 			}
============================================================
--- muchandler.cpp	3e18d5f4399f04dec75858d6b72c4095a565516d
+++ muchandler.cpp	6019a7d276737e2f06038197b4f7985efbcd45bf
@@ -42,8 +42,11 @@ Tag * MUCHandler::handlePresence(const P
 		GHashTable *comps = NULL;
 		std::string name = stanza.to().username();
 		PurpleConnection *gc = purple_account_get_connection(m_user->account());
-		if (PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults != NULL)
+		if (PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults != NULL) {
+			if (name.find("%") != std::string::npos)
+				name = name.substr(0, name.find("%"));
 			comps = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults(gc, name.c_str());
+		}
 		if (comps) {
 			serv_join_chat(gc, comps);
 		}
============================================================
--- protocols/abstractprotocol.h	f544b2fbcf8106db79f976d1ebaea8d22c5821fb
+++ protocols/abstractprotocol.h	100bcd8f7e0c099503fa2ce39983778594869ff0
@@ -81,6 +81,10 @@ class AbstractProtocol
 		 * Returns ID of column used for UIN/name/ID of founded users in searchresults
 		 */
 		virtual std::string userSearchColumn() { return ""; }
+		/*
+		 * Returns true if temporary accounts for MUC are allows (this is useful for IRC, if you want to connect more network from one account)
+		 */
+		virtual bool tempAccountsAllowed() { return false; }
 };
 
 #endif
============================================================
--- protocols/irc.h	d460c8418a38f97e977925f314c33c36f6d9e839
+++ protocols/irc.h	62b1faa991624cab024b0d4cea82efa6b19acb08
@@ -39,8 +39,8 @@ class IRCProtocol : AbstractProtocol
 		std::list<std::string> buddyFeatures();
 		std::string text(const std::string &key);
 		Tag *getVCardTag(User *user, GList *vcardEntries);
-		bool isMUC(User *user, const std::string &jid) { return jid.find("#") == 0; }
-		
+		bool isMUC(User *user, const std::string &jid) { return jid.find("#") == 0 && jid.find("%") != std::string::npos; }
+		bool tempAccountsAllowed() { return true; }
 	
 	private:
 		GlooxMessageHandler *m_main;
============================================================
--- user.cpp	1d2333356d169ad259deff883aaebcabb15a2a07
+++ user.cpp	778cf3e19c98e3208643e0f187da5760f118c008
@@ -48,7 +48,7 @@ static void sendXhtmlTag(Tag *tag, Tag *
 	GlooxMessageHandler::instance()->j->send(stanzaTag);
 }
 
-User::User(GlooxMessageHandler *parent, JID jid, const std::string &username, const std::string &password){
+User::User(GlooxMessageHandler *parent, JID jid, const std::string &username, const std::string &password, const std::string &userKey){
 	p = parent;
 	m_jid = jid.bare();
 	Resource r;
@@ -56,6 +56,7 @@ User::User(GlooxMessageHandler *parent, 
 	m_resource = jid.resource();
 	m_username = username;
 	m_password = password;
+	m_userKey = userKey;
 	m_connected = false;
 	m_roster = p->sql()->getRosterByJid(m_jid);
 	m_vip = p->sql()->isVIP(m_jid);
@@ -70,6 +71,7 @@ User::User(GlooxMessageHandler *parent, 
 	m_lang = NULL;
 	this->features = 6; // TODO: I can't be hardcoded
 	m_mucs = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
+	m_tempAccounts = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
 	PurpleValue *value;
 	
 	// check default settings
@@ -528,8 +530,10 @@ void User::purpleConversationWriteChat(P
 	if (who == NULL)
 		return;
 
-	std::string name(who);
-	MUCHandler *muc = (MUCHandler*) g_hash_table_lookup(m_mucs, purple_conversation_get_name(conv));
+// 	std::string name(who);
+	std::string name(purple_conversation_get_name(conv));
+	name = name + "%" + JID(m_username).server();
+	MUCHandler *muc = (MUCHandler*) g_hash_table_lookup(m_mucs, name.c_str());
 	if (!isOpenedConversation(name)) {
 		m_conversations[name].conv = conv;
 		if (muc)
@@ -631,6 +635,7 @@ void User::purpleChatAddUsers(PurpleConv
 
 void User::purpleChatAddUsers(PurpleConversation *conv, GList *cbuddies, gboolean new_arrivals) {
 	std::string name(purple_conversation_get_name(conv));
+	name = name + "%" + JID(m_username).server();
 	MUCHandler *muc = (MUCHandler*) g_hash_table_lookup(m_mucs, name.c_str());
 	if (!muc)
 		return;
@@ -642,14 +647,18 @@ void User::purpleChatRenameUser(PurpleCo
 }
 
 void User::purpleChatRenameUser(PurpleConversation *conv, const char *old_name, const char *new_name, const char *new_alias) {
-	MUCHandler *muc = (MUCHandler*) g_hash_table_lookup(m_mucs, purple_conversation_get_name(conv));
+	std::string name(purple_conversation_get_name(conv));
+	name = name + "%" + JID(m_username).server();
+	MUCHandler *muc = (MUCHandler*) g_hash_table_lookup(m_mucs, name.c_str());
 	if (muc) {
 		muc->renameUser(old_name, new_name, new_alias);
 	}
 }
 
 void User::purpleChatRemoveUsers(PurpleConversation *conv, GList *users) {
-	MUCHandler *muc = (MUCHandler*) g_hash_table_lookup(m_mucs, purple_conversation_get_name(conv));
+	std::string name(purple_conversation_get_name(conv));
+	name = name + "%" + JID(m_username).server();
+	MUCHandler *muc = (MUCHandler*) g_hash_table_lookup(m_mucs, name.c_str());
 	if (muc) {
 		muc->removeUsers(users);
 	}
@@ -753,7 +762,8 @@ void User::receivedMessage(const Message
 void User::receivedMessage(const Message& msg){
 	PurpleConversation * conv;
 	std::string username = msg.to().username();
-	std::for_each( username.begin(), username.end(), replaceJidCharacters() );
+	if (!p->protocol()->isMUC(this, username))
+		std::for_each( username.begin(), username.end(), replaceJidCharacters() );
 	// open new conversation or get the opened one
 	if (!isOpenedConversation(username)){
 		conv = purple_conversation_new(PURPLE_CONV_TYPE_IM,m_account,username.c_str());
@@ -764,7 +774,6 @@ void User::receivedMessage(const Message
 		conv = m_conversations[username].conv;
 		m_conversations[username].resource = msg.from().resource();
 	}
-	
 	std::string body = msg.body();
 	
 	if (body.find("/transport ") == 0) {
@@ -868,7 +877,7 @@ void User::connect(){
 	m_connectionStart = time(NULL);
 	m_readyForConnect = false;
 	purple_account_set_string(m_account,"bind",std::string(m_bindIP).c_str());
-	purple_account_set_string(m_account,"lastUsedJid",std::string(m_jid +"/"+m_resource).c_str());
+	purple_account_set_string(m_account,"lastUsedJid",m_userKey.c_str());
 	purple_account_set_password(m_account,m_password.c_str());
 	Log().Get(m_jid) << "UIN:" << m_username << " PASSWORD:" << m_password;
 
@@ -908,6 +917,16 @@ void User::connected() {
 void User::connected() {
 	m_connected = true;
 	m_reconnectCount = 0;
+	for (std::list <Tag*>::iterator it = m_autoConnectRooms.begin(); it != m_autoConnectRooms.end() ; it++ ) {
+		Presence stanza((*it));
+		MUCHandler *muc = new MUCHandler(this, stanza.to().bare(), stanza.from().full());
+		g_hash_table_replace(m_mucs, g_strdup(stanza.to().username().c_str()), muc);
+		Tag * ret = muc->handlePresence(stanza);
+		if (ret)
+			p->j->send(ret);
+		delete (*it);
+	};
+	
 }
 
 void User::receivedSubscription(const Subscription &subscription) {
@@ -1037,33 +1056,35 @@ void User::receivedPresence(const Presen
  * Received jabber presence...
  */
 void User::receivedPresence(const Presence &stanza){
-	// we're connected
 
-
-
-	if (m_connected){
-
-		if (stanza.to().username()!="") {
-			MUCHandler *muc = (MUCHandler*) g_hash_table_lookup(m_mucs, stanza.to().username().c_str());
-			if (muc) {
-				Tag * ret = muc->handlePresence(stanza);
-				if (ret)
-					p->j->send(ret);
-				if (stanza.presence() == Presence::Unavailable) {
-					g_hash_table_remove(m_mucs, stanza.to().username().c_str());
-					m_conversations.erase(stanza.to().username());
-					delete muc;
-				}
+	if (stanza.to().username()!="") {
+		MUCHandler *muc = (MUCHandler*) g_hash_table_lookup(m_mucs, stanza.to().username().c_str());
+		if (muc) {
+			Tag * ret = muc->handlePresence(stanza);
+			if (ret)
+				p->j->send(ret);
+			if (stanza.presence() == Presence::Unavailable) {
+				g_hash_table_remove(m_mucs, stanza.to().username().c_str());
+				m_conversations.erase(stanza.to().username());
+				delete muc;
 			}
-			else if (p->protocol()->isMUC(this, stanza.to().bare()) && stanza.presence() != Presence::Unavailable) {
+		}
+		else if (p->protocol()->isMUC(this, stanza.to().bare()) && stanza.presence() != Presence::Unavailable) {
+			if (m_connected) {
 				MUCHandler *muc = new MUCHandler(this, stanza.to().bare(), stanza.from().full());
 				g_hash_table_replace(m_mucs, g_strdup(stanza.to().username().c_str()), muc);
 				Tag * ret = muc->handlePresence(stanza);
 				if (ret)
 					p->j->send(ret);
 			}
+			else {
+				m_autoConnectRooms.push_back(stanza.tag());
+			}
 		}
+	}
 
+	if (m_connected){
+
 		// respond to probe presence
 		if (stanza.subtype() == Presence::Probe && stanza.to().username()!=""){
 			std::string name(stanza.to().username());
@@ -1101,7 +1122,7 @@ void User::receivedPresence(const Presen
 	}
 
 	// this presence is for the transport
-	if(stanza.to().username() == ""){
+	if(stanza.to().username() == ""  || ((!p->protocol()->tempAccountsAllowed()) || p->protocol()->isMUC(NULL, stanza.to().bare()))){
 		if(stanza.presence() == Presence::Unavailable) {
 			// disconnect from legacy network if we are connected
 			std::map<std::string,Resource> ::iterator iter = m_resources.begin();
@@ -1281,6 +1302,9 @@ User::~User(){
 	m_roster.clear();
 	m_conversations.clear();
 	m_authRequests.clear();
+	g_hash_table_destroy(m_mucs);
+	g_hash_table_destroy(m_tempAccounts);
+	g_hash_table_destroy(m_settings);
 }
 
 
============================================================
--- user.h	1f241651ccca6844d64b4cd5c47ad2ec79f49a8a
+++ user.h	0c0847596a3083b310d20db37596fd764f0c6939
@@ -75,7 +75,7 @@ class User {
 
 class User {
 	public:
-		User(GlooxMessageHandler *parent, JID jid, const std::string &username, const std::string &password);
+		User(GlooxMessageHandler *parent, JID jid, const std::string &username, const std::string &password, const std::string &userKey);
 		~User();
 
 		void connect();
@@ -161,9 +161,13 @@ class User {
 		GHashTable *settings() { return m_settings; }
 		
 		GlooxMessageHandler *p;
+		std::string & userKey() { return m_userKey; }
 	
 	private:
+		std::string m_userKey;
 		PurpleAccount *m_account;	// PurpleAccount to which this user is connected
+		GHashTable *m_tempAccounts;	// temp accounts for MUC (need to have them because of connection to more network)
+		std::list <Tag *> m_autoConnectRooms;
 		guint m_syncTimer;			// timer used for syncing purple buddy list and roster
 		int m_subscribeLastCount;	// number of buddies which was in subscribeCache in previous iteration of m_syncTimer
 		bool m_vip;					// true if the user is VIP
============================================================
--- usermanager.cpp	a4c6f22a6dd5f711996f393413dc2a2908bc36f2
+++ usermanager.cpp	448dbaca07667f33c290b464a2fed82140756217
@@ -41,7 +41,7 @@ User *UserManager::getUserByJID(std::str
 }
 
 User *UserManager::getUserByJID(std::string barejid){
-	if (m_cachedUser && barejid == m_cachedUser->jid()) {
+	if (m_cachedUser && barejid == m_cachedUser->userKey()) {
 		return m_cachedUser;
 	}
 	User *user = (User*) g_hash_table_lookup(m_users, barejid.c_str());
@@ -57,8 +57,8 @@ void UserManager::removeUser(User *user)
 
 void UserManager::removeUser(User *user){
 	Log().Get("logout") << "removing user";
-	g_hash_table_remove(m_users, user->jid().c_str());
-	if (m_cachedUser && user->jid() == m_cachedUser->jid()) {
+	g_hash_table_remove(m_users, user->userKey().c_str());
+	if (m_cachedUser && user->userKey() == m_cachedUser->userKey()) {
 		m_cachedUser = NULL;
 	}
 	delete user;
@@ -67,8 +67,8 @@ void UserManager::removeUserTimer(User *
 
 void UserManager::removeUserTimer(User *user){
 	Log().Get("logout") << "removing user by timer";
-	g_hash_table_remove(m_users, user->jid().c_str());
-	if (m_cachedUser && user->jid() == m_cachedUser->jid()) {
+	g_hash_table_remove(m_users, user->userKey().c_str());
+	if (m_cachedUser && user->userKey() == m_cachedUser->userKey()) {
 		m_cachedUser = NULL;
 	}
 	// this will be called by gloop after all
============================================================
--- usermanager.h	ec329deda93f3d3d451bf9ce02429c71b5cc6b4b
+++ usermanager.h	85a866f871c5ebeed1f12c055f311a60d50a99fb
@@ -35,7 +35,7 @@ class UserManager
 		~UserManager();
 		User *getUserByJID(std::string barejid);
 		User *getUserByAccount(PurpleAccount *account);
-		void addUser(User *user) { g_hash_table_replace(m_users, g_strdup(user->jid().c_str()), user); }
+		void addUser(User *user) { g_hash_table_replace(m_users, g_strdup(user->userKey().c_str()), user); }
 		void removeUser(User *user);
 		void removeUserTimer(User *user);
 		void buddyOnline();


More information about the Commits mailing list