static int _muc_user_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata) { // handler still fires if error if (g_strcmp0(xmpp_stanza_get_type(stanza), STANZA_TYPE_ERROR) == 0) { return 1; } char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM); Jid *from_jid = jid_create(from); if (from_jid == NULL || from_jid->resourcepart == NULL) { return 1; } char *from_room = from_jid->barejid; char *from_nick = from_jid->resourcepart; // handle self presence if (stanza_is_muc_self_presence(stanza, jabber_get_fulljid())) { char *type = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_TYPE); char *new_nick = stanza_get_new_nick(stanza); if ((type != NULL) && (strcmp(type, STANZA_TYPE_UNAVAILABLE) == 0)) { // leave room if not self nick change if (new_nick != NULL) { muc_set_room_pending_nick_change(from_room, new_nick); } else { handle_leave_room(from_room); } // handle self nick change } else if (muc_is_room_pending_nick_change(from_room)) { muc_complete_room_nick_change(from_room, from_nick); handle_room_nick_change(from_room, from_nick); // handle roster complete } else if (!muc_get_roster_received(from_room)) { handle_room_roster_complete(from_room); // room configuration required if (stanza_muc_requires_config(stanza)) { handle_room_requires_config(from_room); } } // handle presence from room members } else { char *type = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_TYPE); char *status_str; log_debug("Room presence received from %s", from_jid->fulljid); status_str = stanza_get_status(stanza, NULL); if ((type != NULL) && (strcmp(type, STANZA_TYPE_UNAVAILABLE) == 0)) { // handle nickname change if (stanza_is_room_nick_change(stanza)) { char *new_nick = stanza_get_new_nick(stanza); if (new_nick != NULL) { muc_set_roster_pending_nick_change(from_room, new_nick, from_nick); free(new_nick); } } else { handle_room_member_offline(from_room, from_nick, "offline", status_str); } } else { // send disco info for capabilities, if not cached if (stanza_contains_caps(stanza)) { log_info("Presence contains capabilities."); _handle_caps(stanza); } char *show_str = stanza_get_show(stanza, "online"); if (!muc_get_roster_received(from_room)) { muc_add_to_roster(from_room, from_nick, show_str, status_str); } else { char *old_nick = muc_complete_roster_nick_change(from_room, from_nick); if (old_nick != NULL) { muc_add_to_roster(from_room, from_nick, show_str, status_str); handle_room_member_nick_change(from_room, old_nick, from_nick); free(old_nick); } else { if (!muc_nick_in_roster(from_room, from_nick)) { handle_room_member_online(from_room, from_nick, show_str, status_str); } else { handle_room_member_presence(from_room, from_nick, show_str, status_str); } } } free(show_str); } free(status_str); } jid_destroy(from_jid); return 1; }
static int _available_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata) { // handler still fires if error if (g_strcmp0(xmpp_stanza_get_type(stanza), STANZA_TYPE_ERROR) == 0) { return 1; } // handler still fires if other types if ((g_strcmp0(xmpp_stanza_get_type(stanza), STANZA_TYPE_UNAVAILABLE) == 0) || (g_strcmp0(xmpp_stanza_get_type(stanza), STANZA_TYPE_SUBSCRIBE) == 0) || (g_strcmp0(xmpp_stanza_get_type(stanza), STANZA_TYPE_SUBSCRIBED) == 0) || (g_strcmp0(xmpp_stanza_get_type(stanza), STANZA_TYPE_UNSUBSCRIBED) == 0)) { return 1; } // handler still fires for muc presence if (stanza_is_muc_presence(stanza)) { return 1; } char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM); if (from) { log_info("Available presence handler fired for: %s", from); } else { log_info("Available presence handler fired"); } // exit when no from attribute if (!from) { log_warning("No from attribute found."); return 1; } // own jid is invalid const char *my_jid_str = xmpp_conn_get_jid(conn); Jid *my_jid = jid_create(my_jid_str); if (!my_jid) { if (my_jid_str) { log_error("Could not parse account JID: %s", my_jid_str); } else { log_error("Could not parse account JID: NULL"); } return 1; } // contact jid invalud Jid *from_jid = jid_create(from); if (!from_jid) { log_warning("Could not parse contact JID: %s", from); jid_destroy(my_jid); return 1; } // presence properties char *show_str = stanza_get_show(stanza, "online"); char *status_str = stanza_get_status(stanza, NULL); // presence last activity int idle_seconds = stanza_get_idle_time(stanza); GDateTime *last_activity = NULL; if (idle_seconds > 0) { GDateTime *now = g_date_time_new_now_local(); last_activity = g_date_time_add_seconds(now, 0 - idle_seconds); g_date_time_unref(now); } // priority int priority = 0; xmpp_stanza_t *priority_stanza = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_PRIORITY); if (priority_stanza != NULL) { char *priority_str = xmpp_stanza_get_text(priority_stanza); if (priority_str != NULL) { priority = atoi(priority_str); } free(priority_str); } // send disco info for capabilities, if not cached if ((g_strcmp0(my_jid->fulljid, from_jid->fulljid) != 0) && (stanza_contains_caps(stanza))) { log_info("Presence contains capabilities."); _handle_caps(stanza); } // create Resource Resource *resource = NULL; resource_presence_t presence = resource_presence_from_string(show_str); if (from_jid->resourcepart == NULL) { // hack for servers that do not send full jid resource = resource_new("__prof_default", presence, status_str, priority); } else { resource = resource_new(from_jid->resourcepart, presence, status_str, priority); } free(status_str); free(show_str); // check for self presence if (g_strcmp0(my_jid->barejid, from_jid->barejid) == 0) { connection_add_available_resource(resource); // contact presence } else { handle_contact_online(from_jid->barejid, resource, last_activity); } if (last_activity != NULL) { g_date_time_unref(last_activity); } jid_destroy(my_jid); jid_destroy(from_jid); return 1; }
static void _muc_user_occupant_handler(xmpp_stanza_t *stanza) { const char *from = xmpp_stanza_get_from(stanza); Jid *from_jid = jid_create(from); 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) { // handle nickname change const char *new_nick = stanza_get_new_nick(stanza); if (new_nick) { muc_occupant_nick_change_start(room, new_nick, nick); // handle left room } else { GSList *status_codes = stanza_get_status_codes_by_ns(stanza, STANZA_NS_MUC_USER); // kicked from room if (g_slist_find_custom(status_codes, "307", (GCompareFunc)g_strcmp0)) { const char *actor = stanza_get_actor(stanza); char *reason = stanza_get_reason(stanza); sv_ev_room_occupent_kicked(room, nick, actor, reason); free(reason); // banned from room } else if (g_slist_find_custom(status_codes, "301", (GCompareFunc)g_strcmp0)) { const char *actor = stanza_get_actor(stanza); char *reason = stanza_get_reason(stanza); sv_ev_room_occupent_banned(room, nick, actor, reason); free(reason); // normal exit } else { sv_ev_room_occupant_offline(room, nick, "offline", status_str); } g_slist_free_full(status_codes, free); } // room occupant online } else { // send disco info for capabilities, if not cached XMPPCaps *caps = stanza_parse_caps(stanza); if (caps) { log_info("Presence contains capabilities."); _handle_caps(from, caps); } stanza_free_caps(caps); const char *actor = stanza_get_actor(stanza); char *show_str = stanza_get_show(stanza, "online"); 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); free(show_str); free(reason); } jid_destroy(from_jid); free(status_str); }
static int _available_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata) { // handler still fires if error if (g_strcmp0(xmpp_stanza_get_type(stanza), STANZA_TYPE_ERROR) == 0) { return 1; } // handler still fires if other types if ((g_strcmp0(xmpp_stanza_get_type(stanza), STANZA_TYPE_UNAVAILABLE) == 0) || (g_strcmp0(xmpp_stanza_get_type(stanza), STANZA_TYPE_SUBSCRIBE) == 0) || (g_strcmp0(xmpp_stanza_get_type(stanza), STANZA_TYPE_SUBSCRIBED) == 0) || (g_strcmp0(xmpp_stanza_get_type(stanza), STANZA_TYPE_UNSUBSCRIBED) == 0)) { return 1; } // handler still fires for muc presence if (stanza_is_muc_presence(stanza)) { return 1; } const char *jid = xmpp_conn_get_jid(conn); char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM); log_debug("Available presence handler fired for %s", from); Jid *my_jid = jid_create(jid); Jid *from_jid = jid_create(from); if (my_jid == NULL || from_jid == NULL) { jid_destroy(my_jid); jid_destroy(from_jid); return 1; } char *show_str = stanza_get_show(stanza, "online"); char *status_str = stanza_get_status(stanza, NULL); int idle_seconds = stanza_get_idle_time(stanza); GDateTime *last_activity = NULL; char *caps_key = NULL; if (stanza_contains_caps(stanza)) { caps_key = _get_caps_key(stanza); } if (idle_seconds > 0) { GDateTime *now = g_date_time_new_now_local(); last_activity = g_date_time_add_seconds(now, 0 - idle_seconds); g_date_time_unref(now); } // get priority int priority = 0; xmpp_stanza_t *priority_stanza = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_PRIORITY); if (priority_stanza != NULL) { char *priority_str = xmpp_stanza_get_text(priority_stanza); if (priority_str != NULL) { priority = atoi(priority_str); } free(priority_str); } resource_presence_t presence = resource_presence_from_string(show_str); Resource *resource = NULL; // hack for servers that do not send fulljid with initial presence if (from_jid->resourcepart == NULL) { resource = resource_new("__prof_default", presence, status_str, priority, caps_key); } else { resource = resource_new(from_jid->resourcepart, presence, status_str, priority, caps_key); } // self presence if (strcmp(my_jid->barejid, from_jid->barejid) == 0) { connection_add_available_resource(resource); // contact presence } else { handle_contact_online(from_jid->barejid, resource, last_activity); } free(caps_key); free(status_str); free(show_str); jid_destroy(my_jid); jid_destroy(from_jid); if (last_activity != NULL) { g_date_time_unref(last_activity); } return 1; }
static void _muc_user_self_handler(xmpp_stanza_t *stanza) { const char *from = xmpp_stanza_get_from(stanza); Jid *from_jid = jid_create(from); log_debug("Room self presence received from %s", from_jid->fulljid); char *room = from_jid->barejid; const char *type = xmpp_stanza_get_type(stanza); if (g_strcmp0(type, STANZA_TYPE_UNAVAILABLE) == 0) { // handle nickname change const char *new_nick = stanza_get_new_nick(stanza); if (new_nick) { muc_nick_change_start(room, new_nick); // handle left room } else { GSList *status_codes = stanza_get_status_codes_by_ns(stanza, STANZA_NS_MUC_USER); // room destroyed if (stanza_room_destroyed(stanza)) { const char *new_jid = stanza_get_muc_destroy_alternative_room(stanza); char *password = stanza_get_muc_destroy_alternative_password(stanza); char *reason = stanza_get_muc_destroy_reason(stanza); sv_ev_room_destroyed(room, new_jid, password, reason); free(password); free(reason); // kicked from room } else if (g_slist_find_custom(status_codes, "307", (GCompareFunc)g_strcmp0)) { const char *actor = stanza_get_actor(stanza); char *reason = stanza_get_reason(stanza); sv_ev_room_kicked(room, actor, reason); free(reason); // banned from room } else if (g_slist_find_custom(status_codes, "301", (GCompareFunc)g_strcmp0)) { const char *actor = stanza_get_actor(stanza); char *reason = stanza_get_reason(stanza); sv_ev_room_banned(room, actor, reason); free(reason); // normal exit } else { sv_ev_leave_room(room); } g_slist_free_full(status_codes, free); } } else { gboolean config_required = stanza_muc_requires_config(stanza); const char *actor = stanza_get_actor(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); free(show_str); free(status_str); free(reason); } jid_destroy(from_jid); }