Index: protocols/jabber/iq.c
===================================================================
--- protocols/jabber/iq.c	(revision e101506a3e660d3165a89aab0898293b367e2b5b)
+++ protocols/jabber/iq.c	(revision cfbb3a6e5e11a8d2d162d80958d6ce997104e9d3)
@@ -184,2 +184,45 @@
 	return st;
 }
+
+int jabber_add_to_roster( struct gaim_connection *gc, char *handle, char *name )
+{
+	struct xt_node *node;
+	int st;
+	
+	/* Build the item entry */
+	node = xt_new_node( "item", NULL, NULL );
+	xt_add_attr( node, "jid", handle );
+	if( name )
+		xt_add_attr( node, "name", name );
+	
+	/* And pack it into a roster-add packet */
+	node = xt_new_node( "query", NULL, node );
+	xt_add_attr( node, "xmlns", "jabber:iq:roster" );
+	node = jabber_make_packet( "iq", "set", NULL, node );
+	
+	st = jabber_write_packet( gc, node );
+	
+	xt_free_node( node );
+	return st;
+}
+
+int jabber_remove_from_roster( struct gaim_connection *gc, char *handle )
+{
+	struct xt_node *node;
+	int st;
+	
+	/* Build the item entry */
+	node = xt_new_node( "item", NULL, NULL );
+	xt_add_attr( node, "jid", handle );
+	xt_add_attr( node, "subscription", "remove" );
+	
+	/* And pack it into a roster-add packet */
+	node = xt_new_node( "query", NULL, node );
+	xt_add_attr( node, "xmlns", "jabber:iq:roster" );
+	node = jabber_make_packet( "iq", "set", NULL, node );
+	
+	st = jabber_write_packet( gc, node );
+	
+	xt_free_node( node );
+	return st;
+}
Index: protocols/jabber/jabber.c
===================================================================
--- protocols/jabber/jabber.c	(revision e101506a3e660d3165a89aab0898293b367e2b5b)
+++ protocols/jabber/jabber.c	(revision cfbb3a6e5e11a8d2d162d80958d6ce997104e9d3)
@@ -153,4 +153,16 @@
 	
 	presence_send_update( gc );
+}
+
+static void jabber_add_buddy( struct gaim_connection *gc, char *who )
+{
+	if( jabber_add_to_roster( gc, who, NULL ) )
+		presence_send_request( gc, who, "subscribe" );
+}
+
+static void jabber_remove_buddy( struct gaim_connection *gc, char *who, char *group )
+{
+	if( jabber_remove_from_roster( gc, who ) )
+		presence_send_request( gc, who, "unsubscribe" );
 }
 
@@ -175,6 +187,6 @@
 //	ret->set_info = jabber_set_info;
 //	ret->get_info = jabber_get_info;
-//	ret->add_buddy = jabber_add_buddy;
-//	ret->remove_buddy = jabber_remove_buddy;
+	ret->add_buddy = jabber_add_buddy;
+	ret->remove_buddy = jabber_remove_buddy;
 //	ret->chat_send = jabber_chat_send;
 //	ret->chat_invite = jabber_chat_invite;
Index: protocols/jabber/jabber.h
===================================================================
--- protocols/jabber/jabber.h	(revision e101506a3e660d3165a89aab0898293b367e2b5b)
+++ protocols/jabber/jabber.h	(revision cfbb3a6e5e11a8d2d162d80958d6ce997104e9d3)
@@ -73,5 +73,8 @@
 int jabber_start_iq_auth( struct gaim_connection *gc );
 int jabber_get_roster( struct gaim_connection *gc );
+int jabber_add_to_roster( struct gaim_connection *gc, char *handle, char *name );
+int jabber_remove_from_roster( struct gaim_connection *gc, char *handle );
 
+/* message.c */
 xt_status jabber_pkt_message( struct xt_node *node, gpointer data );
 
@@ -79,4 +82,5 @@
 xt_status jabber_pkt_presence( struct xt_node *node, gpointer data );
 int presence_send_update( struct gaim_connection *gc );
+int presence_send_request( struct gaim_connection *gc, char *handle, char *request );
 
 /* jabber_util.c */
Index: protocols/jabber/presence.c
===================================================================
--- protocols/jabber/presence.c	(revision e101506a3e660d3165a89aab0898293b367e2b5b)
+++ protocols/jabber/presence.c	(revision cfbb3a6e5e11a8d2d162d80958d6ce997104e9d3)
@@ -78,2 +78,18 @@
 	return st;
 }
+
+/* Send a subscribe/unsubscribe request to a buddy. */
+int presence_send_request( struct gaim_connection *gc, char *handle, char *request )
+{
+	struct xt_node *node;
+	int st;
+	
+	node = jabber_make_packet( "presence", NULL, NULL, NULL );
+	xt_add_attr( node, "to", handle );
+	xt_add_attr( node, "type", request );
+	
+	st = jabber_write_packet( gc, node );
+	
+	xt_free_node( node );
+	return st;
+}
