diff options
author | James Booth <boothj5@gmail.com> | 2013-02-02 19:47:41 +0000 |
---|---|---|
committer | James Booth <boothj5@gmail.com> | 2013-02-02 19:47:41 +0000 |
commit | 1d3739bb79d0e56af83bd1a5f3a3606740cc3ade (patch) | |
tree | d997b37f1110d17c7898d134a3e962b3c52a6697 /src/xmpp_presence.c | |
parent | 029a0161035778c3e2803f44cfda4b4cb801ceb5 (diff) | |
download | profani-tty-1d3739bb79d0e56af83bd1a5f3a3606740cc3ade.tar.gz |
Added xmpp subdir to source
Diffstat (limited to 'src/xmpp_presence.c')
-rw-r--r-- | src/xmpp_presence.c | 487 |
1 files changed, 0 insertions, 487 deletions
diff --git a/src/xmpp_presence.c b/src/xmpp_presence.c deleted file mode 100644 index 745389a6..00000000 --- a/src/xmpp_presence.c +++ /dev/null @@ -1,487 +0,0 @@ -/* - * xmpp_presence.c - * - * Copyright (C) 2012, 2013 James Booth <boothj5@gmail.com> - * - * This file is part of Profanity. - * - * Profanity is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Profanity is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Profanity. If not, see <http://www.gnu.org/licenses/>. - * - */ - -#include <stdlib.h> -#include <string.h> - -#include <glib.h> - -#include "common.h" -#include "log.h" -#include "muc.h" -#include "preferences.h" -#include "profanity.h" -#include "xmpp.h" - -static GHashTable *sub_requests; - -#define HANDLE(ns, type, func) xmpp_handler_add(conn, func, ns, STANZA_NAME_PRESENCE, type, ctx) - -static int _presence_handler(xmpp_conn_t * const conn, - xmpp_stanza_t * const stanza, void * const userdata); -static char* _handle_presence_caps(xmpp_stanza_t * const stanza); -static int _room_presence_handler(const char * const jid, - xmpp_stanza_t * const stanza); - -void -presence_init(void) -{ - sub_requests = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); -} - -void -presence_add_handlers(void) -{ - xmpp_conn_t * const conn = jabber_get_conn(); - xmpp_ctx_t * const ctx = jabber_get_ctx(); - HANDLE(NULL, NULL, _presence_handler); -} - -void -presence_subscription(const char * const jid, const jabber_subscr_t action) -{ - xmpp_ctx_t *ctx = jabber_get_ctx(); - xmpp_conn_t *conn = jabber_get_conn(); - xmpp_stanza_t *presence; - char *type, *jid_cpy, *bare_jid; - - // jid must be a bare JID - jid_cpy = strdup(jid); - bare_jid = strtok(jid_cpy, "/"); - g_hash_table_remove(sub_requests, bare_jid); - - if (action == PRESENCE_SUBSCRIBE) - type = STANZA_TYPE_SUBSCRIBE; - else if (action == PRESENCE_SUBSCRIBED) - type = STANZA_TYPE_SUBSCRIBED; - else if (action == PRESENCE_UNSUBSCRIBED) - type = STANZA_TYPE_UNSUBSCRIBED; - else { // unknown action - free(jid_cpy); - return; - } - - presence = xmpp_stanza_new(ctx); - xmpp_stanza_set_name(presence, STANZA_NAME_PRESENCE); - xmpp_stanza_set_type(presence, type); - xmpp_stanza_set_attribute(presence, STANZA_ATTR_TO, bare_jid); - xmpp_send(conn, presence); - xmpp_stanza_release(presence); - free(jid_cpy); -} - -GList * -presence_get_subscription_requests(void) -{ - return g_hash_table_get_keys(sub_requests); -} - -void -presence_free_sub_requests(void) -{ - if (sub_requests != NULL) - g_hash_table_remove_all(sub_requests); -} - -void -presence_join_room(Jid *jid) -{ - xmpp_ctx_t *ctx = jabber_get_ctx(); - xmpp_conn_t *conn = jabber_get_conn(); - xmpp_stanza_t *presence = stanza_create_room_join_presence(ctx, jid->fulljid); - xmpp_send(conn, presence); - xmpp_stanza_release(presence); - - muc_join_room(jid->barejid, jid->resourcepart); -} - -void -presence_change_room_nick(const char * const room, const char * const nick) -{ - xmpp_ctx_t *ctx = jabber_get_ctx(); - xmpp_conn_t *conn = jabber_get_conn(); - char *full_room_jid = create_fulljid(room, nick); - xmpp_stanza_t *presence = stanza_create_room_newnick_presence(ctx, full_room_jid); - xmpp_send(conn, presence); - xmpp_stanza_release(presence); - - free(full_room_jid); -} - -void -presence_leave_chat_room(const char * const room_jid) -{ - xmpp_ctx_t *ctx = jabber_get_ctx(); - xmpp_conn_t *conn = jabber_get_conn(); - char *nick = muc_get_room_nick(room_jid); - - xmpp_stanza_t *presence = stanza_create_room_leave_presence(ctx, room_jid, - nick); - xmpp_send(conn, presence); - xmpp_stanza_release(presence); -} - -void -presence_update(jabber_presence_t presence_type, const char * const msg, - int idle) -{ - xmpp_ctx_t *ctx = jabber_get_ctx(); - xmpp_conn_t *conn = jabber_get_conn(); - int pri; - char *show, *last; - - // don't send presence when disconnected - if (jabber_get_connection_status() != JABBER_CONNECTED) - return; - - pri = accounts_get_priority_for_presence_type(jabber_get_account_name(), - presence_type); - if (pri < JABBER_PRIORITY_MIN || pri > JABBER_PRIORITY_MAX) - pri = 0; - - jabber_conn_set_presence_type(presence_type); - jabber_conn_set_presence_message(msg); - jabber_conn_set_priority(pri); - - switch(presence_type) - { - case PRESENCE_AWAY: - show = STANZA_TEXT_AWAY; - last = STANZA_TEXT_AWAY; - break; - case PRESENCE_DND: - show = STANZA_TEXT_DND; - last = STANZA_TEXT_DND; - break; - case PRESENCE_CHAT: - show = STANZA_TEXT_CHAT; - last = STANZA_TEXT_CHAT; - break; - case PRESENCE_XA: - show = STANZA_TEXT_XA; - last = STANZA_TEXT_XA; - break; - default: // PRESENCE_ONLINE - show = NULL; - last = STANZA_TEXT_ONLINE; - break; - } - - - xmpp_stanza_t *presence = stanza_create_presence(ctx, show, msg); - - // servers must treat no priority as 0 - if (pri != 0) { - xmpp_stanza_t *priority, *value; - char pri_str[10]; - - snprintf(pri_str, sizeof(pri_str), "%d", pri); - priority = xmpp_stanza_new(ctx); - value = xmpp_stanza_new(ctx); - xmpp_stanza_set_name(priority, STANZA_NAME_PRIORITY); - xmpp_stanza_set_text(value, pri_str); - xmpp_stanza_add_child(priority, value); - xmpp_stanza_add_child(presence, priority); - } - - if (idle > 0) { - xmpp_stanza_t *query = xmpp_stanza_new(ctx); - xmpp_stanza_set_name(query, STANZA_NAME_QUERY); - xmpp_stanza_set_ns(query, STANZA_NS_LASTACTIVITY); - char idle_str[10]; - snprintf(idle_str, sizeof(idle_str), "%d", idle); - xmpp_stanza_set_attribute(query, STANZA_ATTR_SECONDS, idle_str); - xmpp_stanza_add_child(presence, query); - } - - // add caps - xmpp_stanza_t *caps = xmpp_stanza_new(ctx); - xmpp_stanza_set_name(caps, STANZA_NAME_C); - xmpp_stanza_set_ns(caps, STANZA_NS_CAPS); - xmpp_stanza_t *query = caps_create_query_response_stanza(ctx); - - char *sha1 = caps_create_sha1_str(query); - xmpp_stanza_set_attribute(caps, STANZA_ATTR_HASH, "sha-1"); - xmpp_stanza_set_attribute(caps, STANZA_ATTR_NODE, "http://www.profanity.im"); - xmpp_stanza_set_attribute(caps, STANZA_ATTR_VER, sha1); - xmpp_stanza_add_child(presence, caps); - - xmpp_send(conn, presence); - - // send presence for each room - GList *rooms = muc_get_active_room_list(); - while (rooms != NULL) { - char *room = rooms->data; - char *nick = muc_get_room_nick(room); - char *full_room_jid = create_fulljid(room, nick); - - xmpp_stanza_set_attribute(presence, STANZA_ATTR_TO, full_room_jid); - xmpp_send(conn, presence); - - rooms = g_list_next(rooms); - } - g_list_free(rooms); - - xmpp_stanza_release(presence); - - FREE_SET_NULL(sha1); - - // set last presence for account - accounts_set_last_presence(jabber_get_account_name(), last); -} - - -static int -_presence_handler(xmpp_conn_t * const conn, - xmpp_stanza_t * const stanza, void * const userdata) -{ - const char *jid = xmpp_conn_get_jid(conn); - char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM); - char *type = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_TYPE); - - Jid *my_jid = jid_create(jid); - Jid *from_jid = jid_create(from); - - if ((type != NULL) && (strcmp(type, STANZA_TYPE_ERROR) == 0)) { - return error_handler(stanza); - } - - // handle chat room presence - if (muc_room_is_active(from_jid)) { - return _room_presence_handler(from_jid->str, stanza); - - // handle regular presence - } else { - char *type = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_TYPE); - char *show_str, *status_str; - 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); - } - - char *caps_key = _handle_presence_caps(stanza); - - xmpp_stanza_t *status = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_STATUS); - if (status != NULL) - status_str = xmpp_stanza_get_text(status); - else - status_str = NULL; - - if (type == NULL) { // available - xmpp_stanza_t *show = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_SHOW); - if (show != NULL) - show_str = xmpp_stanza_get_text(show); - else - show_str = "online"; - - if (strcmp(my_jid->barejid, from_jid->barejid) !=0) { - prof_handle_contact_online(from_jid->barejid, show_str, status_str, last_activity, caps_key); - } - } else if (strcmp(type, STANZA_TYPE_UNAVAILABLE) == 0) { - if (strcmp(my_jid->barejid, from_jid->barejid) !=0) { - prof_handle_contact_offline(from_jid->barejid, "offline", status_str); - } - - if (last_activity != NULL) { - g_date_time_unref(last_activity); - } - - // subscriptions - } else if (strcmp(type, STANZA_TYPE_SUBSCRIBE) == 0) { - prof_handle_subscription(from_jid->barejid, PRESENCE_SUBSCRIBE); - g_hash_table_insert(sub_requests, strdup(from_jid->barejid), strdup(from_jid->barejid)); - } else if (strcmp(type, STANZA_TYPE_SUBSCRIBED) == 0) { - prof_handle_subscription(from_jid->barejid, PRESENCE_SUBSCRIBED); - g_hash_table_remove(sub_requests, from_jid->barejid); - } else if (strcmp(type, STANZA_TYPE_UNSUBSCRIBED) == 0) { - prof_handle_subscription(from_jid->barejid, PRESENCE_UNSUBSCRIBED); - g_hash_table_remove(sub_requests, from_jid->barejid); - } else { /* unknown type */ - log_debug("Received presence with unknown type '%s'", type); - } - } - - return 1; -} - -static char * -_handle_presence_caps(xmpp_stanza_t * const stanza) -{ - xmpp_ctx_t *ctx = jabber_get_ctx(); - xmpp_conn_t *conn = jabber_get_conn(); - char *caps_key = NULL; - char *node = NULL; - char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM); - if (stanza_contains_caps(stanza)) { - char *hash_type = stanza_caps_get_hash(stanza); - - // xep-0115 - if (hash_type != NULL) { - - // supported hash - if (strcmp(hash_type, "sha-1") == 0) { - node = stanza_get_caps_str(stanza); - caps_key = node; - - if (node != NULL) { - if (!caps_contains(caps_key)) { - xmpp_stanza_t *iq = stanza_create_disco_iq(ctx, "disco", from, node); - xmpp_send(conn, iq); - xmpp_stanza_release(iq); - } - } - - // unsupported hash - } else { - node = stanza_get_caps_str(stanza); - caps_key = from; - - if (node != NULL) { - if (!caps_contains(caps_key)) { - GString *id = g_string_new("disco_"); - g_string_append(id, from); - xmpp_stanza_t *iq = stanza_create_disco_iq(ctx, id->str, from, node); - xmpp_send(conn, iq); - xmpp_stanza_release(iq); - g_string_free(id, TRUE); - } - } - } - - return strdup(caps_key); - - //ignore or handle legacy caps - } else { - node = stanza_get_caps_str(stanza); - caps_key = from; - - if (node != NULL) { - if (!caps_contains(caps_key)) { - GString *id = g_string_new("disco_"); - g_string_append(id, from); - xmpp_stanza_t *iq = stanza_create_disco_iq(ctx, id->str, from, node); - xmpp_send(conn, iq); - xmpp_stanza_release(iq); - g_string_free(id, TRUE); - } - } - - return caps_key; - } - } - return NULL; -} - -static int -_room_presence_handler(const char * const jid, xmpp_stanza_t * const stanza) -{ - char *room = NULL; - char *nick = NULL; - - if (!parse_room_jid(jid, &room, &nick)) { - log_error("Could not parse room jid: %s", room); - return 1; - } - - // handle self presence - if (stanza_is_muc_self_presence(stanza, jabber_get_jid())) { - char *type = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_TYPE); - gboolean nick_change = stanza_is_room_nick_change(stanza); - - if ((type != NULL) && (strcmp(type, STANZA_TYPE_UNAVAILABLE) == 0)) { - - // leave room if not self nick change - if (nick_change) { - muc_set_room_pending_nick_change(room); - } else { - prof_handle_leave_room(room); - } - - // handle self nick change - } else if (muc_is_room_pending_nick_change(room)) { - muc_complete_room_nick_change(room, nick); - prof_handle_room_nick_change(room, nick); - - // handle roster complete - } else if (!muc_get_roster_received(room)) { - prof_handle_room_roster_complete(room); - - } - - // handle presence from room members - } else { - char *type = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_TYPE); - char *show_str, *status_str; - char *caps_key = _handle_presence_caps(stanza); - - xmpp_stanza_t *status = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_STATUS); - if (status != NULL) { - status_str = xmpp_stanza_get_text(status); - } else { - status_str = 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); - muc_set_roster_pending_nick_change(room, new_nick, nick); - } else { - prof_handle_room_member_offline(room, nick, "offline", status_str); - } - } else { - xmpp_stanza_t *show = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_SHOW); - if (show != NULL) { - show_str = xmpp_stanza_get_text(show); - } else { - show_str = "online"; - } - if (!muc_get_roster_received(room)) { - muc_add_to_roster(room, nick, show_str, status_str, caps_key); - } else { - char *old_nick = muc_complete_roster_nick_change(room, nick); - - if (old_nick != NULL) { - muc_add_to_roster(room, nick, show_str, status_str, caps_key); - prof_handle_room_member_nick_change(room, old_nick, nick); - } else { - if (!muc_nick_in_roster(room, nick)) { - prof_handle_room_member_online(room, nick, show_str, status_str, caps_key); - } else { - prof_handle_room_member_presence(room, nick, show_str, status_str, caps_key); - } - } - } - } - } - - free(room); - free(nick); - - return 1; -} - |