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

Merge branch 'master' into osx-functional

This commit is contained in:
James Booth 2016-08-21 00:58:49 +01:00
commit 9f14e2c0aa
2 changed files with 547 additions and 468 deletions

View File

@ -681,11 +681,33 @@ _handle_carbons(xmpp_stanza_t *const stanza)
} }
const char *name = xmpp_stanza_get_name(carbons); const char *name = xmpp_stanza_get_name(carbons);
if ((g_strcmp0(name, "received") == 0) || (g_strcmp0(name, "sent")) == 0) { if (!name) {
xmpp_stanza_t *forwarded = xmpp_stanza_get_child_by_ns(carbons, STANZA_NS_FORWARD); log_error("Unable to retrieve stanza name for Carbon");
xmpp_stanza_t *message = xmpp_stanza_get_child_by_name(forwarded, STANZA_NAME_MESSAGE); return TRUE;
}
xmpp_ctx_t *ctx = connection_get_ctx(); if ((g_strcmp0(name, "received") != 0) && (g_strcmp0(name, "sent") != 0)) {
log_warning("Carbon received with unrecognised stanza name: %s", name);
return TRUE;
}
xmpp_stanza_t *forwarded = xmpp_stanza_get_child_by_ns(carbons, STANZA_NS_FORWARD);
if (!forwarded) {
log_warning("Carbon received with no forwarded element");
return TRUE;
}
xmpp_stanza_t *message = xmpp_stanza_get_child_by_name(forwarded, STANZA_NAME_MESSAGE);
if (!message) {
log_warning("Carbon received with no message element");
return TRUE;
}
char *message_txt = xmpp_message_get_body(message);
if (!message_txt) {
log_warning("Carbon received with no message.");
return TRUE;
}
const gchar *to = xmpp_stanza_get_to(message); const gchar *to = xmpp_stanza_get_to(message);
const gchar *from = xmpp_stanza_get_from(message); const gchar *from = xmpp_stanza_get_from(message);
@ -697,9 +719,6 @@ _handle_carbons(xmpp_stanza_t *const stanza)
Jid *jid_to = jid_create(to); Jid *jid_to = jid_create(to);
Jid *my_jid = jid_create(connection_get_fulljid()); Jid *my_jid = jid_create(connection_get_fulljid());
// check for and deal with message
char *message_txt = xmpp_message_get_body(message);
if (message_txt) {
// check for pgp encrypted message // check for pgp encrypted message
char *enc_message = NULL; char *enc_message = NULL;
xmpp_stanza_t *x = xmpp_stanza_get_child_by_ns(message, STANZA_NS_ENCRYPTED); xmpp_stanza_t *x = xmpp_stanza_get_child_by_ns(message, STANZA_NS_ENCRYPTED);
@ -715,9 +734,10 @@ _handle_carbons(xmpp_stanza_t *const stanza)
} else { } else {
sv_ev_outgoing_carbon(jid_to->barejid, message_txt, enc_message); sv_ev_outgoing_carbon(jid_to->barejid, message_txt, enc_message);
} }
xmpp_ctx_t *ctx = connection_get_ctx();
xmpp_free(ctx, message_txt); xmpp_free(ctx, message_txt);
xmpp_free(ctx, enc_message); xmpp_free(ctx, enc_message);
}
jid_destroy(jid_from); jid_destroy(jid_from);
jid_destroy(jid_to); jid_destroy(jid_to);
@ -726,9 +746,6 @@ _handle_carbons(xmpp_stanza_t *const stanza)
return TRUE; return TRUE;
} }
return FALSE;
}
static void static void
_handle_chat(xmpp_stanza_t *const stanza) _handle_chat(xmpp_stanza_t *const stanza)
{ {

View File

@ -78,7 +78,6 @@ static void _available_handler(xmpp_stanza_t *const stanza);
void _send_caps_request(char *node, char *caps_key, char *id, char *from); void _send_caps_request(char *node, char *caps_key, char *id, char *from);
static void _send_room_presence(xmpp_stanza_t *presence); static void _send_room_presence(xmpp_stanza_t *presence);
static void _send_presence_stanza(xmpp_stanza_t *const stanza); static void _send_presence_stanza(xmpp_stanza_t *const stanza);
void void
@ -87,14 +86,283 @@ presence_sub_requests_init(void)
sub_requests_ac = autocomplete_new(); sub_requests_ac = autocomplete_new();
} }
void
presence_handlers_init(void)
{
xmpp_conn_t * const conn = connection_get_conn();
xmpp_ctx_t * const ctx = connection_get_ctx();
xmpp_handler_add(conn, _presence_handler, NULL, STANZA_NAME_PRESENCE, NULL, ctx);
}
void
presence_subscription(const char *const jid, const jabber_subscr_t action)
{
assert(jid != NULL);
Jid *jidp = jid_create(jid);
autocomplete_remove(sub_requests_ac, jidp->barejid);
const char *type = NULL;
switch (action)
{
case PRESENCE_SUBSCRIBE:
log_debug("Sending presence subscribe: %s", jid);
type = STANZA_TYPE_SUBSCRIBE;
break;
case PRESENCE_SUBSCRIBED:
log_debug("Sending presence subscribed: %s", jid);
type = STANZA_TYPE_SUBSCRIBED;
break;
case PRESENCE_UNSUBSCRIBED:
log_debug("Sending presence usubscribed: %s", jid);
type = STANZA_TYPE_UNSUBSCRIBED;
break;
default:
break;
}
if (!type) {
log_error("Attempt to send unknown subscription action: %s", jid);
return;
}
xmpp_ctx_t * const ctx = connection_get_ctx();
xmpp_stanza_t *presence = xmpp_presence_new(ctx);
char *id = create_unique_id("sub");
xmpp_stanza_set_id(presence, id);
free(id);
xmpp_stanza_set_type(presence, type);
xmpp_stanza_set_to(presence, jidp->barejid);
jid_destroy(jidp);
_send_presence_stanza(presence);
xmpp_stanza_release(presence);
}
GSList*
presence_get_subscription_requests(void)
{
return autocomplete_create_list(sub_requests_ac);
}
gint
presence_sub_request_count(void)
{
return autocomplete_length(sub_requests_ac);
}
void
presence_clear_sub_requests(void)
{
autocomplete_clear(sub_requests_ac);
}
char*
presence_sub_request_find(const char *const search_str)
{
return autocomplete_complete(sub_requests_ac, search_str, TRUE);
}
gboolean
presence_sub_request_exists(const char *const bare_jid)
{
gboolean result = FALSE;
GSList *requests = autocomplete_create_list(sub_requests_ac);
GSList *curr = requests;
while (curr) {
if (strcmp(curr->data, bare_jid) == 0) {
result = TRUE;
break;
}
curr = g_slist_next(curr);
}
g_slist_free_full(requests, free);
return result;
}
void
presence_reset_sub_request_search(void)
{
autocomplete_reset(sub_requests_ac);
}
void
presence_send(const resource_presence_t presence_type, const char *const msg, const int idle, char *signed_status)
{
if (connection_get_status() != JABBER_CONNECTED) {
log_warning("Error setting presence, not connected.");
return;
}
if (msg) {
log_debug("Updating presence: %s, \"%s\"", string_from_resource_presence(presence_type), msg);
} else {
log_debug("Updating presence: %s", string_from_resource_presence(presence_type));
}
connection_set_presence_msg(msg);
const int pri = accounts_get_priority_for_presence_type(session_get_account_name(), presence_type);
connection_set_priority(pri);
xmpp_ctx_t * const ctx = connection_get_ctx();
xmpp_stanza_t *presence = xmpp_presence_new(ctx);
char *id = create_unique_id("presence");
xmpp_stanza_set_id(presence, id);
free(id);
const char *show = stanza_get_presence_string_from_type(presence_type);
stanza_attach_show(ctx, presence, show);
stanza_attach_status(ctx, presence, msg);
if (signed_status) {
xmpp_stanza_t *x = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(x, STANZA_NAME_X);
xmpp_stanza_set_ns(x, STANZA_NS_SIGNED);
xmpp_stanza_t *signed_text = xmpp_stanza_new(ctx);
xmpp_stanza_set_text(signed_text, signed_status);
xmpp_stanza_add_child(x, signed_text);
xmpp_stanza_release(signed_text);
xmpp_stanza_add_child(presence, x);
xmpp_stanza_release(x);
}
stanza_attach_priority(ctx, presence, pri);
if (idle > 0) {
stanza_attach_last_activity(ctx, presence, idle);
}
stanza_attach_caps(ctx, presence);
_send_presence_stanza(presence);
_send_room_presence(presence);
xmpp_stanza_release(presence);
// set last presence for account
const char *last = show;
if (last == NULL) {
last = STANZA_TEXT_ONLINE;
}
char *account = session_get_account_name();
accounts_set_last_presence(account, last);
accounts_set_last_status(account, msg);
}
static void
_send_room_presence(xmpp_stanza_t *presence)
{
GList *rooms = muc_rooms();
GList *curr = rooms;
while (curr) {
const char *room = curr->data;
const char *nick = muc_nick(room);
if (nick) {
char *full_room_jid = create_fulljid(room, nick);
xmpp_stanza_set_to(presence, full_room_jid);
log_debug("Sending presence to room: %s", full_room_jid);
free(full_room_jid);
_send_presence_stanza(presence);
}
curr = g_list_next(curr);
}
g_list_free(rooms);
}
void
presence_join_room(const char *const room, const char *const nick, const char *const passwd)
{
Jid *jid = jid_create_from_bare_and_resource(room, nick);
log_debug("Sending room join presence to: %s", jid->fulljid);
resource_presence_t presence_type = accounts_get_last_presence(session_get_account_name());
const char *show = stanza_get_presence_string_from_type(presence_type);
char *status = connection_get_presence_msg();
int pri = accounts_get_priority_for_presence_type(session_get_account_name(), presence_type);
xmpp_ctx_t *ctx = connection_get_ctx();
xmpp_stanza_t *presence = stanza_create_room_join_presence(ctx, jid->fulljid, passwd);
stanza_attach_show(ctx, presence, show);
stanza_attach_status(ctx, presence, status);
stanza_attach_priority(ctx, presence, pri);
stanza_attach_caps(ctx, presence);
_send_presence_stanza(presence);
xmpp_stanza_release(presence);
jid_destroy(jid);
}
void
presence_change_room_nick(const char *const room, const char *const nick)
{
assert(room != NULL);
assert(nick != NULL);
log_debug("Sending room nickname change to: %s, nick: %s", room, nick);
resource_presence_t presence_type = accounts_get_last_presence(session_get_account_name());
const char *show = stanza_get_presence_string_from_type(presence_type);
char *status = connection_get_presence_msg();
int pri = accounts_get_priority_for_presence_type(session_get_account_name(), presence_type);
char *full_room_jid = create_fulljid(room, nick);
xmpp_ctx_t *ctx = connection_get_ctx();
xmpp_stanza_t *presence = stanza_create_room_newnick_presence(ctx, full_room_jid);
stanza_attach_show(ctx, presence, show);
stanza_attach_status(ctx, presence, status);
stanza_attach_priority(ctx, presence, pri);
stanza_attach_caps(ctx, presence);
_send_presence_stanza(presence);
xmpp_stanza_release(presence);
free(full_room_jid);
}
void
presence_leave_chat_room(const char *const room_jid)
{
assert(room_jid != NULL);
char *nick = muc_nick(room_jid);
if (!nick) {
log_error("Could not get nickname for room: %s", room_jid);
return;
}
log_debug("Sending room leave presence to: %s", room_jid);
xmpp_ctx_t *ctx = connection_get_ctx();
xmpp_stanza_t *presence = stanza_create_room_leave_presence(ctx, room_jid, nick);
_send_presence_stanza(presence);
xmpp_stanza_release(presence);
}
static int static int
_presence_handler(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza, void *const userdata) _presence_handler(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza, void *const userdata)
{ {
log_debug("Presence stanza handler fired"); log_debug("Presence stanza handler fired");
char *text; char *text = NULL;
size_t text_size; size_t text_size;
xmpp_stanza_to_text(stanza, &text, &text_size); xmpp_stanza_to_text(stanza, &text, &text_size);
gboolean cont = plugins_on_presence_stanza_receive(text); gboolean cont = plugins_on_presence_stanza_receive(text);
xmpp_free(connection_get_ctx(), text); xmpp_free(connection_get_ctx(), text);
if (!cont) { if (!cont) {
@ -133,285 +401,20 @@ _presence_handler(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza, void *co
return 1; return 1;
} }
void
presence_handlers_init(void)
{
xmpp_conn_t * const conn = connection_get_conn();
xmpp_ctx_t * const ctx = connection_get_ctx();
xmpp_handler_add(conn, _presence_handler, NULL, STANZA_NAME_PRESENCE, NULL, ctx);
}
void
presence_subscription(const char *const jid, const jabber_subscr_t action)
{
assert(jid != NULL);
xmpp_ctx_t * const ctx = connection_get_ctx();
const char *type = NULL;
Jid *jidp = jid_create(jid);
autocomplete_remove(sub_requests_ac, jidp->barejid);
switch (action)
{
case PRESENCE_SUBSCRIBE:
log_debug("Sending presence subscribe: %s", jid);
type = STANZA_TYPE_SUBSCRIBE;
break;
case PRESENCE_SUBSCRIBED:
log_debug("Sending presence subscribed: %s", jid);
type = STANZA_TYPE_SUBSCRIBED;
break;
case PRESENCE_UNSUBSCRIBED:
log_debug("Sending presence usubscribed: %s", jid);
type = STANZA_TYPE_UNSUBSCRIBED;
break;
default:
log_warning("Attempt to send unknown subscription action: %s", jid);
break;
}
xmpp_stanza_t *presence = xmpp_presence_new(ctx);
char *id = create_unique_id("sub");
xmpp_stanza_set_id(presence, id);
xmpp_stanza_set_type(presence, type);
xmpp_stanza_set_to(presence, jidp->barejid);
_send_presence_stanza(presence);
xmpp_stanza_release(presence);
jid_destroy(jidp);
free(id);
}
GSList*
presence_get_subscription_requests(void)
{
return autocomplete_create_list(sub_requests_ac);
}
gint
presence_sub_request_count(void)
{
return autocomplete_length(sub_requests_ac);
}
void
presence_clear_sub_requests(void)
{
autocomplete_clear(sub_requests_ac);
}
char*
presence_sub_request_find(const char *const search_str)
{
return autocomplete_complete(sub_requests_ac, search_str, TRUE);
}
gboolean
presence_sub_request_exists(const char *const bare_jid)
{
gboolean result = FALSE;
GSList *requests_p = autocomplete_create_list(sub_requests_ac);
GSList *requests = requests_p;
while (requests) {
if (strcmp(requests->data, bare_jid) == 0) {
result = TRUE;
break;
}
requests = g_slist_next(requests);
}
if (requests_p) {
g_slist_free_full(requests_p, free);
}
return result;
}
void
presence_reset_sub_request_search(void)
{
autocomplete_reset(sub_requests_ac);
}
void
presence_send(const resource_presence_t presence_type, const char *const msg, const int idle, char *signed_status)
{
if (connection_get_status() != JABBER_CONNECTED) {
log_warning("Error setting presence, not connected.");
return;
}
if (msg) {
log_debug("Updating presence: %s, \"%s\"", string_from_resource_presence(presence_type), msg);
} else {
log_debug("Updating presence: %s", string_from_resource_presence(presence_type));
}
xmpp_ctx_t * const ctx = connection_get_ctx();
const int pri = accounts_get_priority_for_presence_type(session_get_account_name(), presence_type);
const char *show = stanza_get_presence_string_from_type(presence_type);
connection_set_presence_msg(msg);
connection_set_priority(pri);
xmpp_stanza_t *presence = xmpp_presence_new(ctx);
char *id = create_unique_id("presence");
xmpp_stanza_set_id(presence, id);
stanza_attach_show(ctx, presence, show);
stanza_attach_status(ctx, presence, msg);
if (signed_status) {
xmpp_stanza_t *x = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(x, STANZA_NAME_X);
xmpp_stanza_set_ns(x, STANZA_NS_SIGNED);
xmpp_stanza_t *signed_text = xmpp_stanza_new(ctx);
xmpp_stanza_set_text(signed_text, signed_status);
xmpp_stanza_add_child(x, signed_text);
xmpp_stanza_release(signed_text);
xmpp_stanza_add_child(presence, x);
xmpp_stanza_release(x);
}
stanza_attach_priority(ctx, presence, pri);
if (idle > 0) {
stanza_attach_last_activity(ctx, presence, idle);
}
stanza_attach_caps(ctx, presence);
_send_presence_stanza(presence);
_send_room_presence(presence);
xmpp_stanza_release(presence);
// set last presence for account
const char *last = show;
if (last == NULL) {
last = STANZA_TEXT_ONLINE;
}
char *account = session_get_account_name();
accounts_set_last_presence(account, last);
accounts_set_last_status(account, msg);
free(id);
}
static void
_send_room_presence(xmpp_stanza_t *presence)
{
GList *rooms = muc_rooms();
GList *curr = rooms;
while (curr) {
const char *room = curr->data;
const char *nick = muc_nick(room);
if (nick) {
char *full_room_jid = create_fulljid(room, nick);
xmpp_stanza_set_to(presence, full_room_jid);
log_debug("Sending presence to room: %s", full_room_jid);
_send_presence_stanza(presence);
free(full_room_jid);
}
curr = g_list_next(curr);
}
g_list_free(rooms);
}
void
presence_join_room(const char *const room, const char *const nick, const char *const passwd)
{
Jid *jid = jid_create_from_bare_and_resource(room, nick);
log_debug("Sending room join presence to: %s", jid->fulljid);
xmpp_ctx_t *ctx = connection_get_ctx();
resource_presence_t presence_type =
accounts_get_last_presence(session_get_account_name());
const char *show = stanza_get_presence_string_from_type(presence_type);
char *status = connection_get_presence_msg();
int pri = accounts_get_priority_for_presence_type(session_get_account_name(),
presence_type);
xmpp_stanza_t *presence = stanza_create_room_join_presence(ctx, jid->fulljid, passwd);
stanza_attach_show(ctx, presence, show);
stanza_attach_status(ctx, presence, status);
stanza_attach_priority(ctx, presence, pri);
stanza_attach_caps(ctx, presence);
_send_presence_stanza(presence);
xmpp_stanza_release(presence);
jid_destroy(jid);
}
void
presence_change_room_nick(const char *const room, const char *const nick)
{
assert(room != NULL);
assert(nick != NULL);
log_debug("Sending room nickname change to: %s, nick: %s", room, nick);
xmpp_ctx_t *ctx = connection_get_ctx();
resource_presence_t presence_type =
accounts_get_last_presence(session_get_account_name());
const char *show = stanza_get_presence_string_from_type(presence_type);
char *status = connection_get_presence_msg();
int pri = accounts_get_priority_for_presence_type(session_get_account_name(),
presence_type);
char *full_room_jid = create_fulljid(room, nick);
xmpp_stanza_t *presence =
stanza_create_room_newnick_presence(ctx, full_room_jid);
stanza_attach_show(ctx, presence, show);
stanza_attach_status(ctx, presence, status);
stanza_attach_priority(ctx, presence, pri);
stanza_attach_caps(ctx, presence);
_send_presence_stanza(presence);
xmpp_stanza_release(presence);
free(full_room_jid);
}
void
presence_leave_chat_room(const char *const room_jid)
{
assert(room_jid != NULL);
log_debug("Sending room leave presence to: %s", room_jid);
xmpp_ctx_t *ctx = connection_get_ctx();
char *nick = muc_nick(room_jid);
if (nick) {
xmpp_stanza_t *presence = stanza_create_room_leave_presence(ctx, room_jid, nick);
_send_presence_stanza(presence);
xmpp_stanza_release(presence);
}
}
static void static void
_presence_error_handler(xmpp_stanza_t *const stanza) _presence_error_handler(xmpp_stanza_t *const stanza)
{ {
const char *id = xmpp_stanza_get_id(stanza);
const char *from = xmpp_stanza_get_from(stanza);
xmpp_stanza_t *error_stanza = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_ERROR);
xmpp_stanza_t *x = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_X);
const char *xmlns = NULL; const char *xmlns = NULL;
xmpp_stanza_t *x = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_X);
if (x) { if (x) {
xmlns = xmpp_stanza_get_ns(x); xmlns = xmpp_stanza_get_ns(x);
} }
const char *type = NULL;
if (error_stanza) { const char *from = xmpp_stanza_get_from(stanza);
type = xmpp_stanza_get_type(error_stanza); xmpp_stanza_t *error_stanza = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_ERROR);
}
// handle MUC join errors // handle MUC join errors
if (g_strcmp0(xmlns, STANZA_NS_MUC) == 0) { if (g_strcmp0(xmlns, STANZA_NS_MUC) == 0) {
Jid *fulljid = jid_create(from);
const char *error_cond = NULL; const char *error_cond = NULL;
xmpp_stanza_t *reason_st = xmpp_stanza_get_child_by_ns(error_stanza, STANZA_NS_STANZAS); xmpp_stanza_t *reason_st = xmpp_stanza_get_child_by_ns(error_stanza, STANZA_NS_STANZAS);
if (reason_st) { if (reason_st) {
@ -421,19 +424,19 @@ _presence_error_handler(xmpp_stanza_t *const stanza)
error_cond = "unknown"; error_cond = "unknown";
} }
Jid *fulljid = jid_create(from);
log_info("Error joining room: %s, reason: %s", fulljid->barejid, error_cond); log_info("Error joining room: %s, reason: %s", fulljid->barejid, error_cond);
if (muc_active(fulljid->barejid)) { if (muc_active(fulljid->barejid)) {
muc_leave(fulljid->barejid); muc_leave(fulljid->barejid);
} }
cons_show_error("Error joining room %s, reason: %s", fulljid->barejid, error_cond); cons_show_error("Error joining room %s, reason: %s", fulljid->barejid, error_cond);
jid_destroy(fulljid); jid_destroy(fulljid);
return; return;
} }
// stanza_get_error never returns NULL
char *err_msg = stanza_get_error_message(stanza);
GString *log_msg = g_string_new("presence stanza error received"); GString *log_msg = g_string_new("presence stanza error received");
const char *id = xmpp_stanza_get_id(stanza);
if (id) { if (id) {
g_string_append(log_msg, " id="); g_string_append(log_msg, " id=");
g_string_append(log_msg, id); g_string_append(log_msg, id);
@ -442,10 +445,18 @@ _presence_error_handler(xmpp_stanza_t *const stanza)
g_string_append(log_msg, " from="); g_string_append(log_msg, " from=");
g_string_append(log_msg, from); g_string_append(log_msg, from);
} }
const char *type = NULL;
if (error_stanza) {
type = xmpp_stanza_get_type(error_stanza);
}
if (type) { if (type) {
g_string_append(log_msg, " type="); g_string_append(log_msg, " type=");
g_string_append(log_msg, type); g_string_append(log_msg, type);
} }
// stanza_get_error never returns NULL
char *err_msg = stanza_get_error_message(stanza);
g_string_append(log_msg, " error="); g_string_append(log_msg, " error=");
g_string_append(log_msg, err_msg); g_string_append(log_msg, err_msg);
@ -462,14 +473,17 @@ _presence_error_handler(xmpp_stanza_t *const stanza)
free(err_msg); free(err_msg);
} }
static void static void
_unsubscribed_handler(xmpp_stanza_t *const stanza) _unsubscribed_handler(xmpp_stanza_t *const stanza)
{ {
const char *from = xmpp_stanza_get_from(stanza); const char *from = xmpp_stanza_get_from(stanza);
Jid *from_jid = jid_create(from); if (!from) {
log_warning("Unsubscribed presence handler received with no from attribute");
return;
}
log_debug("Unsubscribed presence handler fired for %s", from); log_debug("Unsubscribed presence handler fired for %s", from);
Jid *from_jid = jid_create(from);
sv_ev_subscription(from_jid->barejid, PRESENCE_UNSUBSCRIBED); sv_ev_subscription(from_jid->barejid, PRESENCE_UNSUBSCRIBED);
autocomplete_remove(sub_requests_ac, from_jid->barejid); autocomplete_remove(sub_requests_ac, from_jid->barejid);
@ -480,9 +494,13 @@ static void
_subscribed_handler(xmpp_stanza_t *const stanza) _subscribed_handler(xmpp_stanza_t *const stanza)
{ {
const char *from = xmpp_stanza_get_from(stanza); const char *from = xmpp_stanza_get_from(stanza);
Jid *from_jid = jid_create(from); if (!from) {
log_warning("Subscribed presence handler received with no from attribute");
return;
}
log_debug("Subscribed presence handler fired for %s", from); log_debug("Subscribed presence handler fired for %s", from);
Jid *from_jid = jid_create(from);
sv_ev_subscription(from_jid->barejid, PRESENCE_SUBSCRIBED); sv_ev_subscription(from_jid->barejid, PRESENCE_SUBSCRIBED);
autocomplete_remove(sub_requests_ac, from_jid->barejid); autocomplete_remove(sub_requests_ac, from_jid->barejid);
@ -493,6 +511,9 @@ static void
_subscribe_handler(xmpp_stanza_t *const stanza) _subscribe_handler(xmpp_stanza_t *const stanza)
{ {
const char *from = xmpp_stanza_get_from(stanza); const char *from = xmpp_stanza_get_from(stanza);
if (!from) {
log_warning("Subscribe presence handler received with no from attribute", from);
}
log_debug("Subscribe presence handler fired for %s", from); log_debug("Subscribe presence handler fired for %s", from);
Jid *from_jid = jid_create(from); Jid *from_jid = jid_create(from);
@ -514,6 +535,9 @@ _unavailable_handler(xmpp_stanza_t *const stanza)
xmpp_conn_t *conn = connection_get_conn(); xmpp_conn_t *conn = connection_get_conn();
const char *jid = xmpp_conn_get_jid(conn); const char *jid = xmpp_conn_get_jid(conn);
const char *from = xmpp_stanza_get_from(stanza); const char *from = xmpp_stanza_get_from(stanza);
if (!from) {
log_warning("Unavailable presence received with no from attribute");
}
log_debug("Unavailable presence handler fired for %s", from); log_debug("Unavailable presence handler fired for %s", from);
Jid *my_jid = jid_create(jid); Jid *my_jid = jid_create(jid);
@ -524,9 +548,8 @@ _unavailable_handler(xmpp_stanza_t *const stanza)
return; return;
} }
char *status_str = stanza_get_status(stanza, NULL);
if (strcmp(my_jid->barejid, from_jid->barejid) !=0) { if (strcmp(my_jid->barejid, from_jid->barejid) !=0) {
char *status_str = stanza_get_status(stanza, NULL);
if (from_jid->resourcepart) { if (from_jid->resourcepart) {
sv_ev_contact_offline(from_jid->barejid, from_jid->resourcepart, status_str); sv_ev_contact_offline(from_jid->barejid, from_jid->resourcepart, status_str);
@ -534,13 +557,13 @@ _unavailable_handler(xmpp_stanza_t *const stanza)
} else { } else {
sv_ev_contact_offline(from_jid->barejid, "__prof_default", status_str); sv_ev_contact_offline(from_jid->barejid, "__prof_default", status_str);
} }
free(status_str);
} else { } else {
if (from_jid->resourcepart) { if (from_jid->resourcepart) {
connection_remove_available_resource(from_jid->resourcepart); connection_remove_available_resource(from_jid->resourcepart);
} }
} }
free(status_str);
jid_destroy(my_jid); jid_destroy(my_jid);
jid_destroy(from_jid); jid_destroy(from_jid);
} }
@ -661,74 +684,45 @@ _available_handler(xmpp_stanza_t *const stanza)
void void
_send_caps_request(char *node, char *caps_key, char *id, char *from) _send_caps_request(char *node, char *caps_key, char *id, char *from)
{ {
xmpp_ctx_t *ctx = connection_get_ctx(); if (!node) {
if (node) {
log_debug("Node string: %s.", node);
if (!caps_cache_contains(caps_key)) {
log_debug("Capabilities not cached for '%s', sending discovery IQ.", from);
xmpp_stanza_t *iq = stanza_create_disco_info_iq(ctx, id, from, node);
iq_send_stanza(iq);
xmpp_stanza_release(iq);
} else {
log_debug("Capabilities already cached, for %s", caps_key);
}
} else {
log_debug("No node string, not sending discovery IQ."); log_debug("No node string, not sending discovery IQ.");
return;
} }
log_debug("Node string: %s.", node);
if (caps_cache_contains(caps_key)) {
log_debug("Capabilities already cached, for %s", caps_key);
return;
}
log_debug("Capabilities not cached for '%s', sending discovery IQ.", from);
xmpp_ctx_t *ctx = connection_get_ctx();
xmpp_stanza_t *iq = stanza_create_disco_info_iq(ctx, id, from, node);
iq_send_stanza(iq);
xmpp_stanza_release(iq);
} }
static void static void
_muc_user_handler(xmpp_stanza_t *const stanza) _muc_user_self_handler(xmpp_stanza_t *stanza)
{ {
inp_nonblocking(TRUE);
const char *type = xmpp_stanza_get_type(stanza);
const char *from = xmpp_stanza_get_from(stanza); const char *from = xmpp_stanza_get_from(stanza);
// handler still fires if error
if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) {
return;
}
// invalid from attribute
Jid *from_jid = jid_create(from); Jid *from_jid = jid_create(from);
if (from_jid == NULL || from_jid->resourcepart == NULL) {
jid_destroy(from_jid);
return;
}
char *room = from_jid->barejid;
char *nick = from_jid->resourcepart;
char *show_str = stanza_get_show(stanza, "online");
char *status_str = stanza_get_status(stanza, NULL);
const char *jid = NULL;
const char *role = NULL;
const char *affiliation = NULL;
xmpp_stanza_t *x = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_MUC_USER);
if (x) {
xmpp_stanza_t *item = xmpp_stanza_get_child_by_name(x, STANZA_NAME_ITEM);
if (item) {
jid = xmpp_stanza_get_attribute(item, "jid");
role = xmpp_stanza_get_attribute(item, "role");
affiliation = xmpp_stanza_get_attribute(item, "affiliation");
}
}
// handle self presence
if (stanza_is_muc_self_presence(stanza, connection_get_fulljid())) {
log_debug("Room self presence received from %s", from_jid->fulljid); log_debug("Room self presence received from %s", from_jid->fulljid);
// self unavailable char *room = from_jid->barejid;
const char *type = xmpp_stanza_get_type(stanza);
if (g_strcmp0(type, STANZA_TYPE_UNAVAILABLE) == 0) { if (g_strcmp0(type, STANZA_TYPE_UNAVAILABLE) == 0) {
// handle nickname change // handle nickname change
const char *new_nick = stanza_get_new_nick(stanza); const char *new_nick = stanza_get_new_nick(stanza);
if (new_nick) { if (new_nick) {
muc_nick_change_start(room, new_nick); muc_nick_change_start(room, new_nick);
// handle left room
} else { } else {
GSList *status_codes = stanza_get_status_codes_by_ns(stanza, STANZA_NS_MUC_USER); GSList *status_codes = stanza_get_status_codes_by_ns(stanza, STANZA_NS_MUC_USER);
@ -762,20 +756,45 @@ _muc_user_handler(xmpp_stanza_t *const stanza)
g_slist_free_full(status_codes, free); g_slist_free_full(status_codes, free);
} }
// self online
} else { } else {
gboolean config_required = stanza_muc_requires_config(stanza); gboolean config_required = stanza_muc_requires_config(stanza);
const char *actor = stanza_get_actor(stanza); const char *actor = stanza_get_actor(stanza);
char *reason = stanza_get_reason(stanza); char *reason = stanza_get_reason(stanza);
char *nick = from_jid->resourcepart;
char *show_str = stanza_get_show(stanza, "online");
char *status_str = stanza_get_status(stanza, NULL);
const char *jid = NULL;
const char *role = NULL;
const char *affiliation = NULL;
xmpp_stanza_t *x = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_MUC_USER);
if (x) {
xmpp_stanza_t *item = xmpp_stanza_get_child_by_name(x, STANZA_NAME_ITEM);
if (item) {
jid = xmpp_stanza_get_attribute(item, "jid");
role = xmpp_stanza_get_attribute(item, "role");
affiliation = xmpp_stanza_get_attribute(item, "affiliation");
}
}
sv_ev_muc_self_online(room, nick, config_required, role, affiliation, actor, reason, jid, show_str, status_str); sv_ev_muc_self_online(room, nick, config_required, role, affiliation, actor, reason, jid, show_str, status_str);
free(show_str);
free(status_str);
free(reason); free(reason);
} }
}
static void
_muc_user_occupant_handler(xmpp_stanza_t *stanza)
{
const char *from = xmpp_stanza_get_from(stanza);
Jid *from_jid = jid_create(from);
// handle presence from room members
} else {
log_debug("Room presence received from %s", from_jid->fulljid); log_debug("Room presence received from %s", from_jid->fulljid);
char *room = from_jid->barejid;
char *nick = from_jid->resourcepart;
char *status_str = stanza_get_status(stanza, NULL);
const char *type = xmpp_stanza_get_type(stanza);
if (g_strcmp0(type, STANZA_TYPE_UNAVAILABLE) == 0) { if (g_strcmp0(type, STANZA_TYPE_UNAVAILABLE) == 0) {
// handle nickname change // handle nickname change
@ -820,15 +839,58 @@ _muc_user_handler(xmpp_stanza_t *const stanza)
stanza_free_caps(caps); stanza_free_caps(caps);
const char *actor = stanza_get_actor(stanza); const char *actor = stanza_get_actor(stanza);
char *show_str = stanza_get_show(stanza, "online");
char *reason = stanza_get_reason(stanza); char *reason = stanza_get_reason(stanza);
const char *jid = NULL;
const char *role = NULL;
const char *affiliation = NULL;
xmpp_stanza_t *x = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_MUC_USER);
if (x) {
xmpp_stanza_t *item = xmpp_stanza_get_child_by_name(x, STANZA_NAME_ITEM);
if (item) {
jid = xmpp_stanza_get_attribute(item, "jid");
role = xmpp_stanza_get_attribute(item, "role");
affiliation = xmpp_stanza_get_attribute(item, "affiliation");
}
}
sv_ev_muc_occupant_online(room, nick, jid, role, affiliation, actor, reason, show_str, status_str); sv_ev_muc_occupant_online(room, nick, jid, role, affiliation, actor, reason, show_str, status_str);
free(show_str);
free(reason); free(reason);
} }
free(status_str);
} }
free(show_str); static void
free(status_str); _muc_user_handler(xmpp_stanza_t *const stanza)
{
inp_nonblocking(TRUE);
const char *type = xmpp_stanza_get_type(stanza);
// handler still fires if error
if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) {
return;
}
const char *from = xmpp_stanza_get_from(stanza);
if (!from) {
log_warning("MUC User stanza received with no from attribute");
return;
}
Jid *from_jid = jid_create(from);
if (from_jid == NULL || from_jid->resourcepart == NULL) {
log_warning("MUC User stanza received with invalid from attribute: %s", from);
jid_destroy(from_jid); jid_destroy(from_jid);
return;
}
jid_destroy(from_jid);
if (stanza_is_muc_self_presence(stanza, connection_get_fulljid())) {
_muc_user_self_handler(stanza);
} else {
_muc_user_occupant_handler(stanza);
}
} }
static void static void