Index: protocols/msn/sb.c
===================================================================
--- protocols/msn/sb.c	(revision 1c3008ac0b2b29f7e14ec9b874af3277c511c7a4)
+++ protocols/msn/sb.c	(revision f8cb76dea3554fd82c01c5cae61f35d2b6cb0936)
@@ -29,5 +29,4 @@
 #include "passport.h"
 #include "md5.h"
-#include "invitation.h"
 
 static gboolean msn_sb_callback( gpointer data, gint source, b_input_condition cond );
@@ -175,7 +174,7 @@
 			i = g_snprintf( buf, i, MSN_TYPING_HEADERS, sb->ic->acc->user );
 		}
-		else if( strncmp( text, MSN_INVITE_HEADERS, sizeof( MSN_INVITE_HEADERS ) - 1 ) == 0 ) 
-		{
-			buf = g_strdup( text );
+		else if( strcmp( text, SB_KEEPALIVE_MESSAGE ) == 0 )
+		{
+			buf = g_strdup( SB_KEEPALIVE_HEADERS );
 			i = strlen( buf );
 		}
@@ -256,4 +255,5 @@
 	
 	msn_msgq_purge( ic, &sb->msgq );
+	msn_sb_stop_keepalives( sb );
 	
 	if( sb->key ) g_free( sb->key );
@@ -328,7 +328,11 @@
 	struct msn_data *md = ic->proto_data;
 	
-	if( msn_handler( sb->handler ) == -1 )
+	if( msn_handler( sb->handler ) != -1 )
+		return TRUE;
+	
+	if( sb->msgq != NULL )
 	{
 		time_t now = time( NULL );
+		char buf[1024];
 		
 		if( now - md->first_sb_failure > 600 )
@@ -347,35 +351,26 @@
 			              "There might be problems delivering your messages." );
 		
-		if( sb->msgq != NULL )
-		{
-			char buf[1024];
-			
-			if( md->msgq == NULL )
-			{
-				md->msgq = sb->msgq;
-			}
-			else
-			{
-				GSList *l;
-				
-				for( l = md->msgq; l->next; l = l->next );
-				l->next = sb->msgq;
-			}
-			sb->msgq = NULL;
-			
-			debug( "Moved queued messages back to the main queue, creating a new switchboard to retry." );
-			g_snprintf( buf, sizeof( buf ), "XFR %d SB\r\n", ++md->trId );
-			if( !msn_write( ic, buf, strlen( buf ) ) )
-				return FALSE;
-		}
-		
-		msn_sb_destroy( sb );
-		
-		return FALSE;
-	}
-	else
-	{
-		return TRUE;
-	}
+		if( md->msgq == NULL )
+		{
+			md->msgq = sb->msgq;
+		}
+		else
+		{
+			GSList *l;
+			
+			for( l = md->msgq; l->next; l = l->next );
+			l->next = sb->msgq;
+		}
+		sb->msgq = NULL;
+		
+		debug( "Moved queued messages back to the main queue, "
+		       "creating a new switchboard to retry." );
+		g_snprintf( buf, sizeof( buf ), "XFR %d SB\r\n", ++md->trId );
+		if( !msn_write( ic, buf, strlen( buf ) ) )
+			return FALSE;
+	}
+	
+	msn_sb_destroy( sb );
+	return FALSE;
 }
 
@@ -477,4 +472,6 @@
 		
 		sb->ready = 1;
+		
+		msn_sb_start_keepalives( sb, FALSE );
 	}
 	else if( strcmp( cmd[0], "CAL" ) == 0 )
@@ -526,4 +523,6 @@
 			}
 			
+			msn_sb_start_keepalives( sb, FALSE );
+			
 			return( st );
 		}
@@ -587,4 +586,6 @@
 		if( sb->who )
 		{
+			msn_sb_stop_keepalives( sb );
+			
 			/* This is a single-person chat, and the other person is leaving. */
 			g_free( sb->who );
@@ -693,39 +694,60 @@
 		else if( g_strncasecmp( ct, "text/x-msmsgsinvite", 19 ) == 0 )
 		{
-			char *command = msn_findheader( body, "Invitation-Command:", blen );
-			char *cookie = msn_findheader( body, "Invitation-Cookie:", blen );
-			unsigned int icookie;
+			char *itype = msn_findheader( body, "Application-GUID:", blen );
+			char buf[1024];
 			
 			g_free( ct );
 			
-			/* Every invite should have both a Command and Cookie header */
-			if( !command || !cookie ) {
-				g_free( command );
-				g_free( cookie );
-				imcb_log( ic, "Warning: No command or cookie from %s", sb->who );
-				return 1;
-			}
-			
-			icookie = strtoul( cookie, NULL, 10 );
-			g_free( cookie );
-			
-			if( g_strncasecmp( command, "INVITE", 6 ) == 0 ) {
-				msn_invitation_invite( sb, cmd[1], icookie, body, blen );
-			} else if( g_strncasecmp( command, "ACCEPT", 6 ) == 0 ) {
-				msn_invitation_accept( sb, cmd[1], icookie, body, blen );
-			} else if( g_strncasecmp( command, "CANCEL", 6 ) == 0 ) {
-				msn_invitation_cancel( sb, cmd[1], icookie, body, blen );
-			} else {
-				imcb_log( ic, "Warning: Received invalid invitation with "
-						"command %s from %s", command, sb->who );
-			}
-			
-			g_free( command );
-		}
-		else if( g_strncasecmp( ct, "application/x-msnmsgrp2p", 24 ) == 0 ) 
-		{
-			imcb_error( sb->ic, "Cannot receive file from %s: BitlBee does not "
-					"support msnmsgrp2p yet.", sb->who );
-			g_free( ct );
+			*buf = 0;
+			
+			if( !itype )
+				return( 1 );
+			
+			/* File transfer. */
+			if( strcmp( itype, "{5D3E02AB-6190-11d3-BBBB-00C04F795683}" ) == 0 )
+			{
+				char *name = msn_findheader( body, "Application-File:", blen );
+				char *size = msn_findheader( body, "Application-FileSize:", blen );
+				
+				if( name && size )
+				{
+					g_snprintf( buf, sizeof( buf ), "<< \x02""BitlBee\x02"" - Filetransfer: `%s', %s bytes >>\n"
+					            "Filetransfers are not supported by BitlBee for now...", name, size );
+				}
+				else
+				{
+					strcpy( buf, "<< \x02""BitlBee\x02"" - Corrupted MSN filetransfer invitation message >>" );
+				}
+				
+				if( name ) g_free( name );
+				if( size ) g_free( size );
+			}
+			else
+			{
+				char *iname = msn_findheader( body, "Application-Name:", blen );
+				
+				g_snprintf( buf, sizeof( buf ), "<< \x02""BitlBee\x02"" - Unknown MSN invitation - %s (%s) >>",
+				                                itype, iname ? iname : "no name" );
+				
+				if( iname ) g_free( iname );
+			}
+			
+			g_free( itype );
+			
+			if( !*buf )
+				return( 1 );
+			
+			if( sb->who )
+			{
+				imcb_buddy_msg( ic, cmd[1], buf, 0, 0 );
+			}
+			else if( sb->chat )
+			{
+				imcb_chat_msg( sb->chat, cmd[1], buf, 0, 0 );
+			}
+			else
+			{
+				/* PANIC! */
+			}
 		}
 		else if( g_strncasecmp( ct, "text/x-msmsgscontrol", 20 ) == 0 )
@@ -749,2 +771,32 @@
 	return( 1 );
 }
+
+static gboolean msn_sb_keepalive( gpointer data, gint source, b_input_condition cond )
+{
+	struct msn_switchboard *sb = data;
+	return sb->ready && msn_sb_sendmessage( sb, SB_KEEPALIVE_MESSAGE );
+}
+
+void msn_sb_start_keepalives( struct msn_switchboard *sb, gboolean initial )
+{
+	struct buddy *b;
+	
+	if( sb && sb->who && sb->keepalive == 0 &&
+	    ( b = imcb_find_buddy( sb->ic, sb->who ) ) && !b->present &&
+	    set_getbool( &sb->ic->acc->set, "switchboard_keepalives" ) )
+	{
+		if( initial )
+			msn_sb_keepalive( sb, 0, 0 );
+		
+		sb->keepalive = b_timeout_add( 20000, msn_sb_keepalive, sb );
+	}
+}
+
+void msn_sb_stop_keepalives( struct msn_switchboard *sb )
+{
+	if( sb && sb->keepalive > 0 )
+	{
+		b_event_remove( sb->keepalive );
+		sb->keepalive = 0;
+	}
+}
