diff libpurple/protocols/jabber/jabber.c @ 25982:7e020fbe2cdb

propagate from branch 'im.pidgin.pidgin' (head 303af74a38e7b313d4fb0be4d4054a16cb13d819) to branch 'im.pidgin.cpw.darkrain42.xmpp.avatars' (head 11e989f3ac36a0f958f031d55245db093923ea76)
author Paul Aurich <paul@darkrain42.org>
date Sat, 07 Mar 2009 01:32:29 +0000
parents 2d92bbe6807b 5f9a24d1c25e
children 7027cc42e56c
line wrap: on
line diff
--- a/libpurple/protocols/jabber/jabber.c	Sat Feb 14 18:23:13 2009 +0000
+++ b/libpurple/protocols/jabber/jabber.c	Sat Mar 07 01:32:29 2009 +0000
@@ -149,7 +149,8 @@
 }
 
 static char *jabber_prep_resource(char *input) {
-	char hostname[256]; /* current hostname */
+	char hostname[256], /* current hostname */
+		 *dot = NULL;
 
 	/* Empty resource == don't send any */
 	if (input == NULL || *input == '\0')
@@ -171,6 +172,12 @@
 	}
 	hostname[sizeof(hostname) - 1] = '\0';
 
+	/* We want only the short hostname, not the FQDN - this will prevent the
+	 * resource string from being unreasonably long on systems which stuff the
+	 * whole FQDN in the hostname */
+	if((dot = strchr(hostname, '.')))
+			dot = '\0';
+
 	return purple_strreplace(input, "__HOSTNAME__", hostname);
 }
 
@@ -178,7 +185,7 @@
 {
 	if(xmlnode_get_child(packet, "starttls")) {
 		if(jabber_process_starttls(js, packet))
-	
+
 			return;
 	} else if(purple_account_get_bool(js->gc->account, "require_tls", FALSE) && !js->gsc) {
 		purple_connection_error_reason (js->gc,
@@ -461,10 +468,10 @@
 
 	if (js->keepalive_timeout == -1) {
 		JabberIq *iq = jabber_iq_new(js, JABBER_IQ_GET);
-		
+
 		xmlnode *ping = xmlnode_new_child(iq->node, "ping");
 		xmlnode_set_namespace(ping, "urn:xmpp:ping");
-		
+
 		js->keepalive_timeout = purple_timeout_add_seconds(120, (GSourceFunc)(jabber_pong_timeout), gc);
 		jabber_iq_set_callback(iq, jabber_pong_cb, NULL);
 		jabber_iq_send(iq);
@@ -572,7 +579,7 @@
 		jabber_send_raw(js, "<?xml version='1.0' ?>", -1);
 	jabber_stream_set_state(js, JABBER_STREAM_INITIALIZING);
 	purple_ssl_input_add(gsc, jabber_recv_cb_ssl, gc);
-	
+
 	/* Tell the app that we're doing encryption */
 	jabber_stream_set_state(js, JABBER_STREAM_INITIALIZING_ENCRYPTION);
 }
@@ -731,7 +738,7 @@
 			_("Invalid XMPP ID"));
 		return;
 	}
-	
+
 	if (!js->user->domain || *(js->user->domain) == '\0') {
 		purple_connection_error_reason (gc,
 			PURPLE_CONNECTION_ERROR_INVALID_SETTINGS,
@@ -815,10 +822,11 @@
 				js->user->node, js->user->domain);
 			if(account->registration_cb)
 				(account->registration_cb)(account, TRUE, account->registration_cb_user_data);
-		}
-		else
+		} else {
+			g_return_if_fail(to != NULL);
 			buf = g_strdup_printf(_("Registration to %s successful"),
 				to);
+		}
 		purple_notify_info(NULL, _("Registration Successful"),
 				_("Registration Successful"), buf);
 		g_free(buf);
@@ -845,7 +853,11 @@
 	const char *type = xmlnode_get_attrib(packet, "type");
 	char *buf;
 	char *to = data;
-	
+
+	/* This function is never called for unregistering our XMPP account from
+	 * the server, so there should always be a 'to' address. */
+	g_return_if_fail(to != NULL);
+
 	if(!strcmp(type, "result")) {
 		buf = g_strdup_printf(_("Registration from %s successfully removed"),
 							  to);
@@ -854,10 +866,10 @@
 		g_free(buf);
 	} else {
 		char *msg = jabber_parse_error(js, packet, NULL);
-		
+
 		if(!msg)
 			msg = g_strdup(_("Unknown Error"));
-		
+
 		purple_notify_error(NULL, _("Unregistration Failed"),
 							_("Unregistration Failed"), msg);
 		g_free(msg);
@@ -880,7 +892,8 @@
 
 	iq = jabber_iq_new_query(cbdata->js, JABBER_IQ_SET, "jabber:iq:register");
 	query = xmlnode_get_child(iq->node, "query");
-	xmlnode_set_attrib(iq->node, "to", cbdata->who);
+	if (cbdata->who)
+		xmlnode_set_attrib(iq->node, "to", cbdata->who);
 
 	for(groups = purple_request_fields_get_groups(fields); groups;
 			groups = groups->next) {
@@ -896,11 +909,12 @@
 					jabber_iq_free(iq);
 					iq = jabber_iq_new_query(cbdata->js, JABBER_IQ_SET, "jabber:iq:register");
 					query = xmlnode_get_child(iq->node, "query");
-					xmlnode_set_attrib(iq->node,"to",cbdata->who);
+					if (cbdata->who)
+						xmlnode_set_attrib(iq->node,"to",cbdata->who);
 					xmlnode_new_child(query, "remove");
-					
+
 					jabber_iq_set_callback(iq, jabber_unregistration_result_cb, cbdata->who);
-					
+
 					jabber_iq_send(iq);
 					g_free(cbdata);
 					return;
@@ -941,8 +955,7 @@
 			}
 			xmlnode_insert_data(y, value, -1);
 				if(cbdata->js->registration && !strcmp(id, "username")) {
-					if(cbdata->js->user->node)
-						g_free(cbdata->js->user->node);
+					g_free(cbdata->js->user->node);
 					cbdata->js->user->node = g_strdup(value);
 			}
 				if(cbdata->js->registration && !strcmp(id, "password"))
@@ -985,7 +998,8 @@
 
 	iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:register");
 	query = xmlnode_get_child(iq->node, "query");
-	xmlnode_set_attrib(iq->node,"to",to);
+	if (to)
+		xmlnode_set_attrib(iq->node,"to",to);
 
 	xmlnode_insert_child(query, result);
 
@@ -1010,10 +1024,7 @@
 		return;
 
 	from = xmlnode_get_attrib(packet, "from");
-	if (!from)
-		from = js->serverFQDN;
-	g_return_if_fail(from != NULL);
-	
+
 	if(js->registration) {
 		/* get rid of the login thingy */
 		purple_connection_set_state(js->gc, PURPLE_CONNECTED);
@@ -1033,12 +1044,12 @@
 			return;
 		}
 	}
-	
-	if((x = xmlnode_get_child_with_namespace(packet, "x", "jabber:x:data"))) {
+
+	if((x = xmlnode_get_child_with_namespace(query, "x", "jabber:x:data"))) {
 		jabber_x_data_request(js, x, jabber_register_x_data_cb, g_strdup(from));
 		return;
 
-	} else if((x = xmlnode_get_child_with_namespace(packet, "x", "jabber:x:oob"))) {
+	} else if((x = xmlnode_get_child_with_namespace(query, "x", "jabber:x:oob"))) {
 		xmlnode *url;
 
 		if((url = xmlnode_get_child(x, "url"))) {
@@ -1158,7 +1169,9 @@
 				purple_connection_get_account(js->gc), NULL, NULL,
 				cbdata);
 	else {
-		char *title = registered?g_strdup_printf(_("Change Account Registration at %s"), from)
+		char *title;
+		g_return_if_fail(from != NULL);
+		title = registered ? g_strdup_printf(_("Change Account Registration at %s"), from)
 								:g_strdup_printf(_("Register New Account at %s"), from);
 		purple_request_fields(js->gc, title,
 			  title, instructions, fields,
@@ -1182,7 +1195,7 @@
 
 void jabber_register_gateway(JabberStream *js, const char *gateway) {
 	JabberIq *iq;
-	
+
 	iq = jabber_iq_new_query(js, JABBER_IQ_GET, "jabber:iq:register");
 	xmlnode_set_attrib(iq->node, "to", gateway);
 	jabber_iq_send(iq);
@@ -1257,7 +1270,7 @@
 	const char *type = xmlnode_get_attrib(packet,"type");
 	if(!strcmp(type,"error")) {
 		char *msg = jabber_parse_error(js, packet, NULL);
-		
+
 		purple_notify_error(js->gc, _("Error unregistering account"),
 							_("Error unregistering account"), msg);
 		g_free(msg);
@@ -1291,7 +1304,7 @@
 void jabber_unregister_account(PurpleAccount *account, PurpleAccountUnregistrationCb cb, void *user_data) {
 	PurpleConnection *gc = purple_account_get_connection(account);
 	JabberStream *js;
-	
+
 	if(gc->state != PURPLE_CONNECTED) {
 		if(gc->state != PURPLE_CONNECTING)
 			jabber_login(account);
@@ -1301,7 +1314,7 @@
 		js->unregistration_user_data = user_data;
 		return;
 	}
-	
+
 	js = gc->proto_data;
 
 	if (js->unregistration) {
@@ -1603,10 +1616,10 @@
 	feat->shortname = g_strdup(shortname);
 	feat->namespace = g_strdup(namespace);
 	feat->is_enabled = cb;
-	
+
 	/* try to remove just in case it already exists in the list */
 	jabber_remove_feature(shortname);
-	
+
 	jabber_features = g_list_append(jabber_features, feat);
 }
 
@@ -1617,7 +1630,7 @@
 		if(!strcmp(feat->shortname, shortname)) {
 			g_free(feat->shortname);
 			g_free(feat->namespace);
-			
+
 			g_free(feature->data);
 			jabber_features = g_list_delete_link(jabber_features, feature);
 			break;
@@ -1634,13 +1647,14 @@
 {
 	JabberStream *js;
 	JabberBuddy *jb = NULL;
-
-	if(!b->account->gc)
+	PurpleConnection *gc = purple_account_get_connection(purple_buddy_get_account(b));
+
+	if(!gc)
 		return NULL;
 
-	js = b->account->gc->proto_data;
+	js = gc->proto_data;
 	if(js)
-		jb = jabber_buddy_find(js, b->name, FALSE);
+		jb = jabber_buddy_find(js, purple_buddy_get_name(b), FALSE);
 
 	if(!PURPLE_BUDDY_IS_ONLINE(b)) {
 		if(jb && (jb->subscription & JABBER_SUB_PENDING ||
@@ -1654,9 +1668,11 @@
 {
 	char *ret = NULL;
 	JabberBuddy *jb = NULL;
-	
-	if (b->account->gc && b->account->gc->proto_data)
-		jb = jabber_buddy_find(b->account->gc->proto_data, b->name, FALSE);
+	PurpleAccount *account = purple_buddy_get_account(b);
+	PurpleConnection *gc = purple_account_get_connection(account);
+
+	if (gc && gc->proto_data)
+		jb = jabber_buddy_find(gc->proto_data, purple_buddy_get_name(b), FALSE);
 
 	if(jb && !PURPLE_BUDDY_IS_ONLINE(b) && (jb->subscription & JABBER_SUB_PENDING || !(jb->subscription & JABBER_SUB_TO))) {
 		ret = g_strdup(_("Not Authorized"));
@@ -1685,14 +1701,19 @@
 void jabber_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full)
 {
 	JabberBuddy *jb;
+	PurpleAccount *account;
+	PurpleConnection *gc;
 
 	g_return_if_fail(b != NULL);
-	g_return_if_fail(b->account != NULL);
-	g_return_if_fail(b->account->gc != NULL);
-	g_return_if_fail(b->account->gc->proto_data != NULL);
-
-	jb = jabber_buddy_find(b->account->gc->proto_data, b->name,
-			FALSE);
+
+	account = purple_buddy_get_account(b);
+	g_return_if_fail(account != NULL);
+
+	gc = purple_account_get_connection(account);
+	g_return_if_fail(gc != NULL);
+	g_return_if_fail(gc->proto_data != NULL);
+
+	jb = jabber_buddy_find(gc->proto_data, purple_buddy_get_name(b), FALSE);
 
 	if(jb) {
 		JabberBuddyResource *jbr = NULL;
@@ -1800,9 +1821,12 @@
 	PurpleStatusType *type;
 	GList *types = NULL;
 	PurpleValue *priority_value;
+	PurpleValue *buzz_enabled;
 
 	priority_value = purple_value_new(PURPLE_TYPE_INT);
 	purple_value_set_int(priority_value, 1);
+	buzz_enabled = purple_value_new(PURPLE_TYPE_BOOLEAN);
+	purple_value_set_boolean(buzz_enabled, TRUE);
 	type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE,
 			jabber_buddy_state_get_status_id(JABBER_BUDDY_STATE_ONLINE),
 			NULL, TRUE, TRUE, FALSE,
@@ -1811,12 +1835,14 @@
 			"mood", _("Mood"), purple_value_new(PURPLE_TYPE_STRING),
 			"moodtext", _("Mood Text"), purple_value_new(PURPLE_TYPE_STRING),
 			"nick", _("Nickname"), purple_value_new(PURPLE_TYPE_STRING),
-			"buzz", _("Allow Buzz"), purple_value_new(PURPLE_TYPE_BOOLEAN),
+			"buzz", _("Allow Buzz"), buzz_enabled,
 			NULL);
 	types = g_list_append(types, type);
 
 	priority_value = purple_value_new(PURPLE_TYPE_INT);
 	purple_value_set_int(priority_value, 1);
+	buzz_enabled = purple_value_new(PURPLE_TYPE_BOOLEAN);
+	purple_value_set_boolean(buzz_enabled, TRUE);
 	type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE,
 			jabber_buddy_state_get_status_id(JABBER_BUDDY_STATE_CHAT),
 			_("Chatty"), TRUE, TRUE, FALSE,
@@ -1825,12 +1851,14 @@
 			"mood", _("Mood"), purple_value_new(PURPLE_TYPE_STRING),
 			"moodtext", _("Mood Text"), purple_value_new(PURPLE_TYPE_STRING),
 			"nick", _("Nickname"), purple_value_new(PURPLE_TYPE_STRING),
-			"buzz", _("Allow Buzz"), purple_value_new(PURPLE_TYPE_BOOLEAN),
+			"buzz", _("Allow Buzz"), buzz_enabled,
 			NULL);
 	types = g_list_append(types, type);
 
 	priority_value = purple_value_new(PURPLE_TYPE_INT);
 	purple_value_set_int(priority_value, 0);
+	buzz_enabled = purple_value_new(PURPLE_TYPE_BOOLEAN);
+	purple_value_set_boolean(buzz_enabled, TRUE);
 	type = purple_status_type_new_with_attrs(PURPLE_STATUS_AWAY,
 			jabber_buddy_state_get_status_id(JABBER_BUDDY_STATE_AWAY),
 			NULL, TRUE, TRUE, FALSE,
@@ -1839,12 +1867,14 @@
 			"mood", _("Mood"), purple_value_new(PURPLE_TYPE_STRING),
 			"moodtext", _("Mood Text"), purple_value_new(PURPLE_TYPE_STRING),
 			"nick", _("Nickname"), purple_value_new(PURPLE_TYPE_STRING),
-			"buzz", _("Allow Buzz"), purple_value_new(PURPLE_TYPE_BOOLEAN),
+			"buzz", _("Allow Buzz"), buzz_enabled,
 			NULL);
 	types = g_list_append(types, type);
 
 	priority_value = purple_value_new(PURPLE_TYPE_INT);
 	purple_value_set_int(priority_value, 0);
+	buzz_enabled = purple_value_new(PURPLE_TYPE_BOOLEAN);
+	purple_value_set_boolean(buzz_enabled, TRUE);
 	type = purple_status_type_new_with_attrs(PURPLE_STATUS_EXTENDED_AWAY,
 			jabber_buddy_state_get_status_id(JABBER_BUDDY_STATE_XA),
 			NULL, TRUE, TRUE, FALSE,
@@ -1853,7 +1883,7 @@
 			"mood", _("Mood"), purple_value_new(PURPLE_TYPE_STRING),
 			"moodtext", _("Mood Text"), purple_value_new(PURPLE_TYPE_STRING),
 			"nick", _("Nickname"), purple_value_new(PURPLE_TYPE_STRING),
-			"buzz", _("Allow Buzz"), purple_value_new(PURPLE_TYPE_BOOLEAN),
+			"buzz", _("Allow Buzz"), buzz_enabled,
 			NULL);
 	types = g_list_append(types, type);
 
@@ -1867,7 +1897,6 @@
 			"mood", _("Mood"), purple_value_new(PURPLE_TYPE_STRING),
 			"moodtext", _("Mood Text"), purple_value_new(PURPLE_TYPE_STRING),
 			"nick", _("Nickname"), purple_value_new(PURPLE_TYPE_STRING),
-			"buzz", _("Allow Buzz"), purple_value_new(PURPLE_TYPE_BOOLEAN),
 			NULL);
 	types = g_list_append(types, type);
 
@@ -2013,7 +2042,7 @@
 
 	if(js->pep)
 		jabber_pep_init_actions(&m);
-	
+
 	if(js->commands)
 		jabber_adhoc_init_server_commands(js, &m);
 
@@ -2028,19 +2057,24 @@
 	if(!(jid = jabber_id_new(name)))
 		return NULL;
 
-	for(gnode = purple_get_blist()->root; gnode; gnode = gnode->next) {
-		for(cnode = gnode->child; cnode; cnode = cnode->next) {
+	for(gnode = purple_blist_get_root(); gnode;
+			gnode = purple_blist_node_get_sibling_next(gnode)) {
+		for(cnode = purple_blist_node_get_first_child(gnode);
+				cnode;
+				cnode = purple_blist_node_get_sibling_next(cnode)) {
 			PurpleChat *chat = (PurpleChat*)cnode;
 			const char *room, *server;
+			GHashTable *components;
 			if(!PURPLE_BLIST_NODE_IS_CHAT(cnode))
 				continue;
 
-			if(chat->account != account)
+			if (purple_chat_get_account(chat) != account)
 				continue;
 
-			if(!(room = g_hash_table_lookup(chat->components, "room")))
+			components = purple_chat_get_components(chat);
+			if(!(room = g_hash_table_lookup(components, "room")))
 				continue;
-			if(!(server = g_hash_table_lookup(chat->components, "server")))
+			if(!(server = g_hash_table_lookup(components, "server")))
 				continue;
 
 			if(jid->node && jid->domain &&
@@ -2060,7 +2094,7 @@
 	JabberID *jid;
 	JabberBuddy *jb;
 	JabberBuddyResource *jbr;
-	
+
 	if(!(jid = jabber_id_new(who)))
 		return;
 
@@ -2321,7 +2355,7 @@
 	if (!chat || !args || !args[0] || !args[1])
 		return PURPLE_CMD_RET_FAILED;
 
-	if (strcmp(args[1], "owner") != 0 && 
+	if (strcmp(args[1], "owner") != 0 &&
 	    strcmp(args[1], "admin") != 0 &&
 	    strcmp(args[1], "member") != 0 &&
 	    strcmp(args[1], "outcast") != 0 &&
@@ -2450,63 +2484,92 @@
 
 	JabberBuddy *jb;
 	JabberBuddyResource *jbr;
-	GList *iter;
+	PurpleConnection *gc = js->gc;
+	PurpleBuddy *buddy =
+		purple_find_buddy(purple_connection_get_account(gc), username);
+	const gchar *alias =
+		buddy ? purple_buddy_get_contact_alias(buddy) : username;
 
 	if(!username)
 		return FALSE;
 
 	jb = jabber_buddy_find(js, username, FALSE);
 	if(!jb) {
-		*error = g_strdup_printf(_("Unable to buzz, because there is nothing known about user %s."), username);
+		*error = g_strdup_printf(_("Unable to buzz, because there is nothing "
+			"known about %s."), alias);
 		return FALSE;
 	}
 
 	jbr = jabber_buddy_find_resource(jb, NULL);
-	if(!jbr) {
-		*error = g_strdup_printf(_("Unable to buzz, because user %s might be offline."), username);
-		return FALSE;
-	}
-
-	if(!jbr->caps) {
-		*error = g_strdup_printf(_("Unable to buzz, because there is nothing known about user %s."), username);
+	if (!jbr) {
+		*error = g_strdup_printf(_("Unable to buzz, because %s might be offline."),
+			alias);
 		return FALSE;
 	}
 
-	for(iter = jbr->caps->features; iter; iter = g_list_next(iter)) {
-		if(!strcmp(iter->data, "http://www.xmpp.org/extensions/xep-0224.html#ns")) {
-			xmlnode *buzz, *msg = xmlnode_new("message");
-			gchar *to;
-
-			to = g_strdup_printf("%s/%s", username, jbr->name);
-			xmlnode_set_attrib(msg, "to", to);
-			g_free(to);
-
-			/* avoid offline storage */
-			xmlnode_set_attrib(msg, "type", "headline");
-
-			buzz = xmlnode_new_child(msg, "attention");
-			xmlnode_set_namespace(buzz, "http://www.xmpp.org/extensions/xep-0224.html#ns");
-
-			jabber_send(js, msg);
-			xmlnode_free(msg);
-
-			return TRUE;
-		}
+	if (jabber_resource_has_capability(jbr, XEP_0224_NAMESPACE)) {
+		xmlnode *buzz, *msg = xmlnode_new("message");
+		gchar *to;
+
+		to = g_strdup_printf("%s/%s", username, jbr->name);
+		xmlnode_set_attrib(msg, "to", to);
+		g_free(to);
+
+		/* avoid offline storage */
+		xmlnode_set_attrib(msg, "type", "headline");
+
+		buzz = xmlnode_new_child(msg, "attention");
+		xmlnode_set_namespace(buzz, XEP_0224_NAMESPACE);
+
+		jabber_send(js, msg);
+		xmlnode_free(msg);
+
+		return TRUE;
+	} else {
+		*error = g_strdup_printf(_("Unable to buzz, because %s does "
+			"not support it or do not wish to receive buzzes now."), alias);
+		return FALSE;
 	}
-
-	*error = g_strdup_printf(_("Unable to buzz, because the user %s does not support it."), username);
-	return FALSE;
 }
 
 static PurpleCmdRet jabber_cmd_buzz(PurpleConversation *conv,
 		const char *cmd, char **args, char **error, void *data)
 {
 	JabberStream *js = conv->account->gc->proto_data;
-
-	if(!args || !args[0])
+	const gchar *who;
+
+	if (!args || !args[0]) {
+		/* use the buddy from conversation, if it's a one-to-one conversation */
+		if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
+			who = purple_conversation_get_name(conv);
+		} else {
+			return PURPLE_CMD_RET_FAILED;
+		}
+	} else {
+		who = args[0];
+	}
+
+	if (_jabber_send_buzz(js, who, error)) {
+		const gchar *alias;
+		gchar *str;
+		PurpleBuddy *buddy =
+			purple_find_buddy(purple_connection_get_account(conv->account->gc),
+				who);
+
+		if (buddy != NULL)
+			alias = purple_buddy_get_contact_alias(buddy);
+		else
+			alias = who;
+
+		str = g_strdup_printf(_("Buzzing %s..."), alias);
+		purple_conversation_write(conv, NULL, str,
+			PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NOTIFY, time(NULL));
+		g_free(str);
+
+		return PURPLE_CMD_RET_OK;
+	} else {
 		return PURPLE_CMD_RET_FAILED;
-
-	return _jabber_send_buzz(js, args[0], error)  ? PURPLE_CMD_RET_OK : PURPLE_CMD_RET_FAILED;
+	}
 }
 
 GList *jabber_attention_types(PurpleAccount *account)
@@ -2619,8 +2682,9 @@
 					  "prpl-jabber", jabber_cmd_ping,
 					  _("ping &lt;jid&gt;:	Ping a user/component/server."),
 					  NULL);
-	purple_cmd_register("buzz", "s", PURPLE_CMD_P_PRPL,
-					  PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PRPL_ONLY,
+	purple_cmd_register("buzz", "w", PURPLE_CMD_P_PRPL,
+					  PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PRPL_ONLY |
+					  PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS,
 					  "prpl-jabber", jabber_cmd_buzz,
 					  _("buzz: Buzz a user to get their attention"), NULL);
 }