soc.2009.transport: 4cfb3e95: Added initial support for MSN (usernames...

hanzz at soc.pidgin.im hanzz at soc.pidgin.im
Fri Jun 5 03:05:41 EDT 2009


-----------------------------------------------------------------
Revision: 4cfb3e95b4d7da08c5d2ba1af356d09d31f1d1c9
Ancestor: 72aae753d4a87754326c8b4683e549e8cba01171
Author: hanzz at soc.pidgin.im
Date: 2009-06-05T07:01:42
Branch: im.pidgin.soc.2009.transport
URL: http://d.pidgin.im/viewmtn/revision/info/4cfb3e95b4d7da08c5d2ba1af356d09d31f1d1c9

Added files:
        protocols/msn.cpp protocols/msn.h
Modified files:
        CMakeLists.txt adhochandler.cpp main.cpp main.h user.cpp

ChangeLog: 

Added initial support for MSN (usernames with @ are properly translated to JID). Roster item exchange and chatting should work.

-------------- next part --------------
============================================================
--- protocols/msn.cpp	7579ee98fe809d9a021dd9d4087e8a4198453024
+++ protocols/msn.cpp	7579ee98fe809d9a021dd9d4087e8a4198453024
@@ -0,0 +1,82 @@
+/**
+ * XMPP - libpurple transport
+ *
+ * Copyright (C) 2009, Jan Kaluza <hanzz at 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 "msn.h"
+#include "../main.h"
+
+MSNProtocol::MSNProtocol(GlooxMessageHandler *main){
+	m_main = main;
+	m_transportFeatures.push_back("jabber:iq:register");
+	m_transportFeatures.push_back("http://jabber.org/protocol/disco#info");
+	m_transportFeatures.push_back("http://jabber.org/protocol/caps");
+	m_transportFeatures.push_back("http://jabber.org/protocol/chatstates");
+// 	m_transportFeatures.push_back("http://jabber.org/protocol/activity+notify");
+	m_transportFeatures.push_back("http://jabber.org/protocol/commands");
+	
+	m_buddyFeatures.push_back("http://jabber.org/protocol/disco#info");
+	m_buddyFeatures.push_back("http://jabber.org/protocol/caps");
+	m_buddyFeatures.push_back("http://jabber.org/protocol/chatstates");
+	m_buddyFeatures.push_back("http://jabber.org/protocol/commands");
+
+// 	m_buddyFeatures.push_back("http://jabber.org/protocol/si/profile/file-transfer");
+// 	m_buddyFeatures.push_back("http://jabber.org/protocol/bytestreams");
+// 	m_buddyFeatures.push_back("http://jabber.org/protocol/si");
+}
+	
+MSNProtocol::~MSNProtocol() {}
+
+std::string MSNProtocol::replace(std::string &str, const char *string_to_replace, const char *new_string)
+{
+	// Find the first string to replace
+	int index = str.find(string_to_replace);
+	// while there is one
+	while(index != (int) std::string::npos)
+	{
+		// Replace it
+		str.replace(index, strlen(string_to_replace), new_string);
+		// Find the next one
+		index = str.find(string_to_replace, index + strlen(new_string));
+	}
+	return str;
+}
+
+std::string MSNProtocol::prepareUserName(std::string &str){
+	str = replace(str," ","");
+	return str;
+}
+
+bool MSNProtocol::isValidUsername(std::string &str){
+	// TODO: check valid email address
+	return true;
+}
+
+std::list<std::string> MSNProtocol::transportFeatures(){
+	return m_transportFeatures;
+}
+
+std::list<std::string> MSNProtocol::buddyFeatures(){
+	return m_buddyFeatures;
+}
+
+std::string MSNProtocol::text(const std::string &key) {
+	if (key == "instructions")
+		return "Enter your GG number and password:";
+	return "not defined";
+}
============================================================
--- protocols/msn.h	976f3ce4eb6c3988f7c1debeabb255c36e481ea5
+++ protocols/msn.h	976f3ce4eb6c3988f7c1debeabb255c36e481ea5
@@ -0,0 +1,52 @@
+/**
+ * XMPP - libpurple transport
+ *
+ * Copyright (C) 2009, Jan Kaluza <hanzz at 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
+ */
+
+#ifndef _HI_MSN_PROTOCOL_H
+#define _HI_MSN_PROTOCOL_H
+
+#include "abstractprotocol.h"
+
+class GlooxMessageHandler;
+
+class MSNProtocol : AbstractProtocol
+{
+	public:
+		MSNProtocol(GlooxMessageHandler *main);
+		~MSNProtocol();
+		std::string gatewayIdentity() { return "msn"; }
+		std::string protocol() { return "prpl-msn"; }
+		bool isValidUsername(std::string &username);
+		std::string prepareUserName(std::string &username);
+		std::list<std::string> transportFeatures();
+		std::list<std::string> buddyFeatures();
+		std::string text(const std::string &key);
+		Tag *getVCardTag(User *user, GList *vcardEntries) { return NULL; }
+		
+		std::string replace(std::string &str, const char *string_to_replace, const char *new_string);
+	
+	private:
+		GlooxMessageHandler *m_main;
+		std::list<std::string> m_transportFeatures;
+		std::list<std::string> m_buddyFeatures;
+	
+};
+
+#endif	
+	
\ No newline at end of file
============================================================
--- CMakeLists.txt	2264023d914ec1f31267c310e4d9fad4341c754d
+++ CMakeLists.txt	b9e02ee4e08479cf3199baf70003bd19b124575e
@@ -92,6 +92,7 @@
 	protocols/icq.cpp
 	protocols/facebook.cpp
 	protocols/gg.cpp
+	protocols/msn.cpp
 )
 
 set(hiicq_MOC_HDRS
@@ -121,6 +122,7 @@
 	protocols/icq.h
 	protocols/facebook.h
 	protocols/gg.h
+	protocols/msn.h
 )
 
 add_executable(hiicq ${hiicq_SRCS} ${lrelease_outputs})
============================================================
--- adhochandler.cpp	e1e945c79db049389c3cb10be8acdb65e73da830
+++ adhochandler.cpp	bc806f593d320af689a21f791133d0e9e0e207d5
@@ -67,7 +67,7 @@ Disco::ItemList GlooxAdhocHandler::handl
 						for (l = actions; l != NULL; l = l->next) {
 							if (l->data) {
 								action = (PurplePluginAction *) l->data;
-								lst.push_back( new Disco::Item( main->jid(), (std::string) action->label, (std::string) action->label ) );
+								lst.push_back( new Disco::Item( main->jid(), (std::string) tr(user->getLang(), action->label), (std::string) action->label ) );
 								purple_plugin_action_free(action);
 							}
 						}
@@ -79,6 +79,7 @@ Disco::ItemList GlooxAdhocHandler::handl
 			User *user = main->userManager()->getUserByJID(from);
 			if (user) {
 				if (user->isConnected() && purple_account_get_connection(user->account())) {
+					Log().Get("GlooxAdhocHandler") << user->getLang();
 					GList *l, *ll;
 					PurpleConnection *gc = purple_account_get_connection(user->account());
 					PurplePlugin *plugin = gc && PURPLE_CONNECTION_IS_CONNECTED(gc) ? gc->prpl : NULL;
@@ -86,12 +87,13 @@ Disco::ItemList GlooxAdhocHandler::handl
 
 					if(!prpl_info || !prpl_info->blist_node_menu)
 						return lst;
+					std::string name(JID(to).username());
+					std::for_each( name.begin(), name.end(), replaceJidCharacters() );
+					PurpleBuddy *buddy = purple_find_buddy(user->account(), name.c_str());
 
-					PurpleBuddy *buddy = purple_find_buddy(user->account(), JID(to).username().c_str());
-
 					for(l = ll = prpl_info->blist_node_menu((PurpleBlistNode*)buddy); l; l = l->next) {
 						PurpleMenuAction *action = (PurpleMenuAction *) l->data;
-						lst.push_back( new Disco::Item( _to.bare(), (std::string) action->label, (std::string) action->label ) );
+						lst.push_back( new Disco::Item( _to.bare(), (std::string) tr(user->getLang(), action->label), (std::string) action->label ) );
 						purple_menu_action_free(action);
 					}
 				}
@@ -156,7 +158,9 @@ bool GlooxAdhocHandler::handleIq( const 
 
 				if(!prpl_info || !prpl_info->blist_node_menu)
 					return true;
-				PurpleBuddy *buddy = purple_find_buddy(user->account(), JID(to).username().c_str());
+				std::string name(JID(to).username());
+				std::for_each( name.begin(), name.end(), replaceJidCharacters() );
+				PurpleBuddy *buddy = purple_find_buddy(user->account(), name.c_str());
 
 				for(l = ll = prpl_info->blist_node_menu((PurpleBlistNode*)buddy); l; l = l->next) {
 					PurpleMenuAction *action = (PurpleMenuAction *) l->data;
============================================================
--- main.cpp	5f10813cc57bf714e62aacbb5af18b261e685554
+++ main.cpp	c214ccdf531210b1f87052454c90154e716153f2
@@ -30,6 +30,7 @@
 #include "protocols/icq.h"
 #include "protocols/facebook.h"
 #include "protocols/gg.h"
+#include "protocols/msn.h"
 #include "blistsaving.h"
 
 #include <gloox/tlsbase.h>
@@ -259,7 +260,9 @@ static void * notify_user_info(PurpleCon
  */
 static void * notify_user_info(PurpleConnection *gc, const char *who, PurpleNotifyUserInfo *user_info)
 {
-	GlooxMessageHandler::instance()->vcard()->userInfoArrived(gc,(std::string) who,user_info);
+	std::string name(who);
+	std::for_each( name.begin(), name.end(), replaceBadJidCharacters() );
+	GlooxMessageHandler::instance()->vcard()->userInfoArrived(gc, name, user_info);
 	return NULL;
 }
 
@@ -538,7 +541,8 @@ void GlooxMessageHandler::loadProtocol()
 		m_protocol = (AbstractProtocol*) new FacebookProtocol(this);
 	else if (configuration().protocol == "gg")
 		m_protocol = (AbstractProtocol*) new GGProtocol(this);
-	
+	else if (configuration().protocol == "msn")
+		m_protocol = (AbstractProtocol*) new MSNProtocol(this);
 // 	PurplePlugin *plugin = purple_find_prpl(m_protocol->protocol().c_str());
 // 	if (plugin && PURPLE_PLUGIN_HAS_ACTIONS(plugin)) {
 // 		PurplePluginAction *action = NULL;
@@ -581,7 +585,7 @@ void GlooxMessageHandler::purpleConnecti
 			m_userManager->removeUserTimer(user);
 		}
 		else{
-			if (user->reconnectCount()==1){
+			if (user->reconnectCount() > 0){
 				if (text){
 					Message s(Message::Chat, user->jid(), (std::string)text);
 					std::string from;
@@ -594,7 +598,7 @@ void GlooxMessageHandler::purpleConnecti
 				m_userManager->removeUserTimer(user);
 			}
 			else{
-
+				user->disconnected();
 				g_timeout_add(5000,&reconnect,g_strdup(user->jid().c_str()));
 			}
 		}
============================================================
--- main.h	7680e2aab97c4c4ba989bd73fa4b31a6476b72b2
+++ main.h	2c3ce2f0d2a657c50f2e9597cffa37f74796c2bb
@@ -102,7 +102,14 @@ struct authData;
 struct UserRow;
 struct authData;
 
+struct replaceBadJidCharacters {
+	void operator()(char& c) { if(c == '@') c = '%'; }
+};
 
+struct replaceJidCharacters {
+	void operator()(char& c) { if(c == '%') c = '@'; }
+};
+
 typedef enum { 	TRANSPORT_FEATURE_TYPING_NOTIFY = 2,
 				TRANSPORT_FEATURE_AVATARS = 4,
                 TRANSPORT_MANGLE_STATUS = 8,
============================================================
--- user.cpp	56711e102628e26b93f6f67a926331b0b90ace19
+++ user.cpp	e0c887ef00ca7174d9341e5a6ede410883b53f15
@@ -159,6 +159,7 @@ void User::sendRosterX()
 	while(it != m_subscribeCache.end()) {
 		PurpleBuddy *buddy = (*it).second;
 		std::string name(purple_buddy_get_name(buddy));
+		std::for_each( name.begin(), name.end(), replaceBadJidCharacters() );
 		if (!name.empty()){
 			RosterRow user;
 			std::string alias;                                                                                                                                          
@@ -201,7 +202,9 @@ void User::syncContacts()
 	PurpleBuddy *buddy;
 	Log().Get(m_jid) << "Syncing contacts with legacy network.";
 	for(std::map<std::string, RosterRow>::iterator u = m_roster.begin(); u != m_roster.end() ; u++){
-		buddy = purple_find_buddy(m_account, (*u).second.uin.c_str());
+		std::string name((*u).second.uin);
+		std::for_each( name.begin(), name.end(), replaceJidCharacters() );
+		buddy = purple_find_buddy(m_account, name.c_str());
 		// buddy is not in blist, so it's not on server
 		if (!buddy) {
 			// add buddy to server
@@ -226,6 +229,7 @@ Tag *User::generatePresenceStanza(Purple
 		alias = (std::string) purple_buddy_get_alias(buddy);
 
 	std::string name(purple_buddy_get_name(buddy));
+	std::for_each( name.begin(), name.end(), replaceBadJidCharacters() );
 	PurplePresence *pres = purple_buddy_get_presence(buddy);
 	if (pres==NULL)
 		return NULL;
@@ -339,6 +343,7 @@ void User::purpleReauthorizeBuddy(Purple
 		return;
 	GList *l, *ll;
 	std::string name(purple_buddy_get_name(buddy));
+	std::for_each( name.begin(), name.end(), replaceBadJidCharacters() );	
 	if (purple_account_get_connection(m_account)){
 		PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_account_get_connection(m_account)->prpl);
 		if(prpl_info && prpl_info->blist_node_menu){
@@ -373,6 +378,7 @@ void User::purpleBuddyChanged(PurpleBudd
 		alias = (std::string) purple_buddy_get_alias(buddy);
 
 	std::string name(purple_buddy_get_name(buddy));
+	std::for_each( name.begin(), name.end(), replaceBadJidCharacters() );
 	PurplePresence *pres = purple_buddy_get_presence(buddy);
 	if (pres==NULL)
 		return;
@@ -449,6 +455,7 @@ void User::purpleBuddyRemoved(PurpleBudd
 void User::purpleBuddyRemoved(PurpleBuddy *buddy) {
 	// we should remove pointer to buddy from subscribCache
 	std::string name(purple_buddy_get_name(buddy));
+	std::for_each( name.begin(), name.end(), replaceBadJidCharacters() );
 	m_subscribeCache.erase(name);
 }
 
@@ -677,7 +684,9 @@ void User::receivedSubscription(const Su
 				m_authRequests.erase(subscription.to().username());
 			}
 			// subscribed user is not in roster, so we must add him/her there.
-			PurpleBuddy *buddy = purple_find_buddy(m_account, subscription.to().username().c_str());
+			std::string name(subscription.to().username());
+			std::for_each( name.begin(), name.end(), replaceJidCharacters() );
+			PurpleBuddy *buddy = purple_find_buddy(m_account, name.c_str());
 			if(!isInRoster(subscription.to().username(),"both")) {
 				if(!buddy) {
 					Log().Get(m_jid) << "user is not in legacy network contact lists => nothing to be subscribed";
@@ -713,7 +722,9 @@ void User::receivedSubscription(const Su
 			return;
 		}
 		else if(subscription.subtype() == Subscription::Subscribe) {
-			PurpleBuddy *b = purple_find_buddy(m_account, subscription.to().username().c_str());
+			std::string name(subscription.to().username());
+			std::for_each( name.begin(), name.end(), replaceJidCharacters() );
+			PurpleBuddy *b = purple_find_buddy(m_account, name.c_str());
 			if (b){
 				purpleReauthorizeBuddy(b);
 			}
@@ -744,7 +755,9 @@ void User::receivedSubscription(const Su
 			}
 			return;
 		} else if(subscription.subtype() == Subscription::Unsubscribe || subscription.subtype() == Subscription::Unsubscribed) {
-			PurpleBuddy *buddy = purple_find_buddy(m_account, subscription.to().username().c_str());
+			std::string name(subscription.to().username());
+			std::for_each( name.begin(), name.end(), replaceJidCharacters() );
+			PurpleBuddy *buddy = purple_find_buddy(m_account, name.c_str());
 			if(subscription.subtype() == Subscription::Unsubscribed) {
 				// user respond to auth request from legacy network and deny it
 				if (hasAuthRequest((std::string)subscription.to().username())){
@@ -793,7 +806,9 @@ void User::receivedPresence(const Presen
 	
 		// respond to probe presence
 		if (stanza.subtype() == Presence::Probe && stanza.to().username()!=""){
-			PurpleBuddy *buddy = purple_find_buddy(m_account, stanza.to().username().c_str());
+			std::string name(stanza.to().username());
+			std::for_each( name.begin(), name.end(), replaceJidCharacters() );
+			PurpleBuddy *buddy = purple_find_buddy(m_account, name.c_str());
 			if (buddy){
 				Tag *probe = generatePresenceStanza(buddy);
 				if (probe){
@@ -814,11 +829,15 @@ void User::receivedPresence(const Presen
 	}
 
 	if (m_lang == NULL) {
-		std::string lang = stanza.xmlLang();
-		if (lang == "default")
+		Tag *tag = stanza.tag();
+		std::string lang = tag->findAttribute("xml:lang");
+		Log().Get("LANG") << tag->xml();
+		delete tag;
+		if (lang == "")
 			lang = "en";
 		setLang(lang.c_str());
 		localization.loadLocale(getLang());
+		Log().Get("LANG") << lang << " " << lang.c_str();
 	}
 
 	// this presence is for the transport


More information about the Commits mailing list