1
0
mirror of https://github.com/profanity-im/profanity.git synced 2024-12-04 14:46:46 -05:00

Handle roster subscription updates

This commit is contained in:
James Booth 2012-11-27 23:43:32 +00:00
parent 2f2fa8de66
commit a061b0d452
7 changed files with 122 additions and 18 deletions

View File

@ -276,18 +276,20 @@ static struct cmd_t main_commands[] =
{ "/sub",
_cmd_sub, parse_args, 1, 2,
{ "/sub <add|del|req|show> [jid]", "Manage subscriptions.",
{ "/sub <add|del|req|show> [jid]",
"-----------------------------",
"add : Approve subscription to a contact.",
"del : Remove subscription for a contact.",
"req : Send a subscription request to the user to be informed of their",
" : presence.",
"show : Show subscriprion status for a contact.",
{ "/sub <request|allow|deny|show> [jid]", "Manage subscriptions.",
{ "/sub <request|allow|deny|show> [jid]",
"------------------------------------",
"request : Send a subscription request to the user to be informed of their",
" : presence.",
"allow : Approve contacts subscription reqeust to see your presence.",
"deny : Remove subscription for a contact, or deny a request",
"show : Show subscriprion status for a contact.",
"",
"If optional parameter 'jid' isn't set command belongs to the current window.",
"",
"Example: /sub add myfriend@jabber.org",
"Example: /sub request myfriend@jabber.org",
"Example: /sub allow myfriend@jabber.org",
"Example: /sub request (whilst in chat with contact)",
NULL } } },
{ "/tiny",
@ -622,9 +624,9 @@ cmd_init(void)
p_autocomplete_add(notify_ac, strdup("remind"));
sub_ac = p_autocomplete_new();
p_autocomplete_add(sub_ac, strdup("add"));
p_autocomplete_add(sub_ac, strdup("del"));
p_autocomplete_add(sub_ac, strdup("req"));
p_autocomplete_add(sub_ac, strdup("request"));
p_autocomplete_add(sub_ac, strdup("allow"));
p_autocomplete_add(sub_ac, strdup("deny"));
p_autocomplete_add(sub_ac, strdup("show"));
log_ac = p_autocomplete_new();
@ -995,15 +997,15 @@ _cmd_sub(gchar **args, struct cmd_help_t help)
bare_jid = strtok(jid, "/");
if (strcmp(subcmd, "add") == 0) {
if (strcmp(subcmd, "allow") == 0) {
jabber_subscription(bare_jid, PRESENCE_SUBSCRIBED);
cons_show("Accepted subscription for %s", bare_jid);
log_info("Accepted subscription for %s", bare_jid);
} else if (strcmp(subcmd, "del") == 0) {
} else if (strcmp(subcmd, "deny") == 0) {
jabber_subscription(bare_jid, PRESENCE_UNSUBSCRIBED);
cons_show("Deleted subscription for %s", bare_jid);
log_info("Deleted subscription for %s", bare_jid);
} else if (strcmp(subcmd, "req") == 0) {
cons_show("Deleted/denied subscription for %s", bare_jid);
log_info("Deleted/denied subscription for %s", bare_jid);
} else if (strcmp(subcmd, "request") == 0) {
jabber_subscription(bare_jid, PRESENCE_SUBSCRIBE);
cons_show("Sent subscription request to %s.", bare_jid);
log_info("Sent subscription request to %s.", bare_jid);

View File

@ -195,6 +195,27 @@ p_contact_set_status(const PContact contact, const char * const status)
}
}
void
p_contact_set_subscription(const PContact contact, const char * const subscription)
{
if (contact->subscription != NULL) {
free(contact->subscription);
contact->subscription = NULL;
}
if (subscription == NULL) {
contact->subscription = strdup("none");
} else {
contact->subscription = strdup(subscription);
}
}
void
p_contact_set_pending_out(const PContact contact, gboolean pending_out)
{
contact->pending_out = pending_out;
}
int
p_contacts_equal_deep(const PContact c1, const PContact c2)
{

View File

@ -38,6 +38,8 @@ const char * p_contact_subscription(const PContact contact);
gboolean p_contact_pending_out(const PContact contact);
void p_contact_set_presence(const PContact contact, const char * const presence);
void p_contact_set_status(const PContact contact, const char * const status);
void p_contact_set_subscription(const PContact contact, const char * const subscription);
void p_contact_set_pending_out(const PContact contact, gboolean pending_out);
int p_contacts_equal_deep(const PContact c1, const PContact c2);
#endif

View File

@ -96,6 +96,20 @@ contact_list_update_contact(const char * const jid, const char * const presence,
return changed;
}
void
contact_list_update_subscription(const char * const jid,
const char * const subscription, gboolean pending_out)
{
PContact contact = g_hash_table_lookup(contacts, jid);
if (contact == NULL) {
return;
} else {
p_contact_set_subscription(contact, subscription);
p_contact_set_pending_out(contact, pending_out);
}
}
GSList *
get_contact_list(void)
{

View File

@ -35,6 +35,8 @@ gboolean contact_list_add(const char * const jid, const char * const name,
const char * const subscription, gboolean pending_out);
gboolean contact_list_update_contact(const char * const jid, const char * const presence,
const char * const status);
void contact_list_update_subscription(const char * const jid,
const char * const subscription, gboolean pending_out);
GSList * get_contact_list(void);
char * contact_list_find_contact(char *search_str);
PContact contact_list_get_contact(const char const *jid);

View File

@ -71,6 +71,8 @@ static int _groupchat_message_handler(xmpp_stanza_t * const stanza);
static int _error_handler(xmpp_stanza_t * const stanza);
static int _chat_message_handler(xmpp_stanza_t * const stanza);
static int _iq_handler(xmpp_conn_t * const conn,
xmpp_stanza_t * const stanza, void * const userdata);
static int _roster_handler(xmpp_conn_t * const conn,
xmpp_stanza_t * const stanza, void * const userdata);
static int _presence_handler(xmpp_conn_t * const conn,
@ -673,7 +675,7 @@ _connection_handler(xmpp_conn_t * const conn,
xmpp_handler_add(conn, _message_handler, NULL, STANZA_NAME_MESSAGE, NULL, ctx);
xmpp_handler_add(conn, _presence_handler, NULL, STANZA_NAME_PRESENCE, NULL, ctx);
xmpp_id_handler_add(conn, _roster_handler, "roster", ctx);
xmpp_handler_add(conn, _iq_handler, NULL, STANZA_NAME_IQ, NULL, ctx);
if (prefs_get_autoping() != 0) {
int millis = prefs_get_autoping() * 1000;
@ -743,6 +745,66 @@ _connection_handler(xmpp_conn_t * const conn,
}
}
static int
_iq_handler(xmpp_conn_t * const conn,
xmpp_stanza_t * const stanza, void * const userdata)
{
char *id = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_ID);
// handle the initial roster request
if ((id != NULL) && (strcmp(id, "roster") == 0)) {
return _roster_handler(conn, stanza, userdata);
// handle roster updates
} else {
char *type = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_TYPE);
if (type == NULL) {
return TRUE;
}
if (strcmp(type, "set") != 0) {
return TRUE;
}
xmpp_stanza_t *query =
xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_QUERY);
if (query == NULL) {
return TRUE;
}
char *xmlns = xmpp_stanza_get_attribute(query, STANZA_ATTR_XMLNS);
if (xmlns == NULL) {
return TRUE;
}
if (strcmp(xmlns, XMPP_NS_ROSTER) != 0) {
return TRUE;
}
xmpp_stanza_t *item =
xmpp_stanza_get_child_by_name(query, STANZA_NAME_ITEM);
if (item == NULL) {
return TRUE;
}
const char *jid = xmpp_stanza_get_attribute(item, STANZA_ATTR_JID);
const char *sub = xmpp_stanza_get_attribute(item, STANZA_ATTR_SUBSCRIPTION);
gboolean pending_out = FALSE;
const char *ask = xmpp_stanza_get_attribute(item, STANZA_ATTR_ASK);
if ((ask != NULL) && (strcmp(ask, "subscribe") == 0)) {
pending_out = TRUE;
}
contact_list_update_subscription(jid, sub, pending_out);
return TRUE;
}
}
static int
_roster_handler(xmpp_conn_t * const conn,
xmpp_stanza_t * const stanza, void * const userdata)

View File

@ -68,6 +68,7 @@
#define STANZA_ATTR_XMLNS "xmlns"
#define STANZA_ATTR_NICK "nick"
#define STANZA_ATTR_ASK "ask"
#define STANZA_ATTR_ID "id"
#define STANZA_TEXT_AWAY "away"
#define STANZA_TEXT_DND "dnd"