diff --git a/src/contact.c b/src/contact.c index 45ace58f..372ccf5f 100644 --- a/src/contact.c +++ b/src/contact.c @@ -75,6 +75,12 @@ p_contact_add_resource(PContact contact, Resource *resource) g_hash_table_insert(contact->available_resources, strdup(resource->name), resource); } +gboolean +p_contact_remove_resource(PContact contact, const char * const resource) +{ + return g_hash_table_remove(contact->available_resources, resource); +} + PContact p_contact_new_subscription(const char * const barejid, const char * const subscription, gboolean pending_out) @@ -178,20 +184,9 @@ p_contact_caps_str(const PContact contact) } void -p_contact_set_presence(const PContact contact, const char * const presence) +p_contact_set_presence(const PContact contact, Resource *resource) { - if (g_strcmp0(presence, "offline") == 0) { - g_hash_table_remove(contact->available_resources, "default"); - } else { - resource_presence_t resource_presence = resource_presence_from_string(presence); - if (g_hash_table_size(contact->available_resources) == 0) { - Resource *resource = resource_new("default", resource_presence, NULL, 0, NULL); - g_hash_table_insert(contact->available_resources, strdup(resource->name), resource); - } else { - Resource *resource = g_hash_table_lookup(contact->available_resources, "default"); - resource->presence = resource_presence; - } - } + g_hash_table_replace(contact->available_resources, strdup(resource->name), resource); } void diff --git a/src/contact.h b/src/contact.h index c32f3800..0b376d81 100644 --- a/src/contact.h +++ b/src/contact.h @@ -32,6 +32,7 @@ PContact p_contact_new(const char * const barejid, const char * const name, PContact p_contact_new_subscription(const char * const barejid, const char * const subscription, gboolean pending_out); void p_contact_add_resource(PContact contact, Resource *resource); +gboolean p_contact_remove_resource(PContact contact, const char * const resource); void p_contact_free(PContact contact); const char* p_contact_barejid(PContact contact); const char* p_contact_name(PContact contact); @@ -41,7 +42,7 @@ const char* p_contact_subscription(const PContact contact); const char* p_contact_caps_str(const PContact contact); GDateTime* p_contact_last_activity(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_presence(const PContact contact, Resource *resource); 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_caps_str(const PContact contact, const char * const caps_str); diff --git a/src/contact_list.c b/src/contact_list.c index 13c71f0a..3b6aab1a 100644 --- a/src/contact_list.c +++ b/src/contact_list.c @@ -20,6 +20,7 @@ * */ +#include #include #include @@ -86,36 +87,35 @@ contact_list_remove(const char * const barejid) } gboolean -contact_list_update_contact(const char * const barejid, const char * const presence, - const char * const status, GDateTime *last_activity, const char * const caps_str) +contact_list_update_presence(const char * const barejid, Resource *resource, + GDateTime *last_activity) { - gboolean presence_changed = FALSE; - PContact contact = g_hash_table_lookup(contacts, barejid); + assert(barejid != NULL); + assert(resource != NULL); + PContact contact = g_hash_table_lookup(contacts, barejid); + if (contact == NULL) { + return FALSE; + } + + if (!_datetimes_equal(p_contact_last_activity(contact), last_activity)) { + p_contact_set_last_activity(contact, last_activity); + } + p_contact_set_presence(contact, resource); + + return TRUE; +} + +gboolean +contact_list_contact_offline(const char * const barejid, + const char * const resource, const char * const status) +{ + PContact contact = g_hash_table_lookup(contacts, barejid); if (contact == NULL) { return FALSE; } - if (g_strcmp0(p_contact_presence(contact), presence) != 0) { - p_contact_set_presence(contact, presence); - presence_changed = TRUE; - } - - if (g_strcmp0(p_contact_status(contact), status) != 0) { - p_contact_set_status(contact, status); - presence_changed = TRUE; - } - - if (!_datetimes_equal(p_contact_last_activity(contact), last_activity)) { - p_contact_set_last_activity(contact, last_activity); - presence_changed = TRUE; - } - - if (g_strcmp0(p_contact_caps_str(contact), caps_str) != 0) { - p_contact_set_caps_str(contact, caps_str); - } - - return presence_changed; + return p_contact_remove_resource(contact, resource); } void diff --git a/src/contact_list.h b/src/contact_list.h index 37511e67..581d6f66 100644 --- a/src/contact_list.h +++ b/src/contact_list.h @@ -34,13 +34,15 @@ void contact_list_reset_search_attempts(void); void contact_list_remove(const char * const barejid); gboolean contact_list_add(const char * const barejid, const char * const name, const char * const subscription, gboolean pending_out); -gboolean contact_list_update_contact(const char * const barejid, const char * const presence, - const char * const status, GDateTime *last_activity, const char * const caps_str); +gboolean contact_list_update_presence(const char * const barejid, + Resource *resource, GDateTime *last_activity); void contact_list_update_subscription(const char * const barejid, const char * const subscription, gboolean pending_out); gboolean contact_list_has_pending_subscriptions(void); GSList * get_contact_list(void); char * contact_list_find_contact(char *search_str); PContact contact_list_get_contact(const char const *barejid); +gboolean contact_list_contact_offline(const char * const barejid, + const char * const resource, const char * const status); #endif diff --git a/src/profanity.c b/src/profanity.c index 0ba0fb15..d294a266 100644 --- a/src/profanity.c +++ b/src/profanity.c @@ -41,6 +41,7 @@ #include "contact_list.h" #include "log.h" #include "muc.h" +#include "resource.h" #include "ui/ui.h" #include "xmpp/xmpp.h" @@ -316,16 +317,17 @@ prof_handle_leave_room(const char * const room) } void -prof_handle_contact_online(char *contact, char *show, char *status, - GDateTime *last_activity, char *caps_str) +prof_handle_contact_online(char *contact, Resource *resource, + GDateTime *last_activity) { - gboolean presence_changed = contact_list_update_contact(contact, show, status, last_activity, caps_str); + gboolean updated = contact_list_update_presence(contact, resource, last_activity); - if (presence_changed) { + if (updated) { PContact result = contact_list_get_contact(contact); if (p_contact_subscription(result) != NULL) { if (strcmp(p_contact_subscription(result), "none") != 0) { - ui_contact_online(contact, show, status, last_activity); + const char *show = string_from_resource_presence(resource->presence); + ui_contact_online(contact, resource->name, show, resource->status, last_activity); win_current_page_off(); } } @@ -333,15 +335,15 @@ prof_handle_contact_online(char *contact, char *show, char *status, } void -prof_handle_contact_offline(char *contact, char *show, char *status) +prof_handle_contact_offline(char *contact, char *resource, char *status) { - gboolean presence_changed = contact_list_update_contact(contact, "offline", status, NULL, NULL); + gboolean updated = contact_list_contact_offline(contact, resource, status); - if (presence_changed) { + if (updated) { PContact result = contact_list_get_contact(contact); if (p_contact_subscription(result) != NULL) { if (strcmp(p_contact_subscription(result), "none") != 0) { - ui_contact_offline(contact, show, status); + ui_contact_offline(contact, "offline", status); win_current_page_off(); } } diff --git a/src/profanity.h b/src/profanity.h index 8cbec501..366188e1 100644 --- a/src/profanity.h +++ b/src/profanity.h @@ -23,6 +23,7 @@ #ifndef PROFANITY_H #define PROFANITY_H +#include "resource.h" #include "xmpp/xmpp.h" void prof_run(const int disable_tls, char *log_level); @@ -33,8 +34,8 @@ void prof_handle_lost_connection(void); void prof_handle_disconnect(const char * const jid); void prof_handle_failed_login(void); void prof_handle_typing(char *from); -void prof_handle_contact_online(char *contact, char *show, char *status, - GDateTime *last_activity, char *caps_str); +void prof_handle_contact_online(char *contact, Resource *resource, + GDateTime *last_activity); void prof_handle_contact_offline(char *contact, char *show, char *status); void prof_handle_incoming_message(char *from, char *message, gboolean priv); void prof_handle_delayed_message(char *from, char *message, GTimeVal tv_stamp, diff --git a/src/ui/ui.h b/src/ui/ui.h index 6686acb7..80139cc1 100644 --- a/src/ui/ui.h +++ b/src/ui/ui.h @@ -70,8 +70,8 @@ void ui_show_typing(const char * const from); void ui_idle(void); void ui_show_incoming_msg(const char * const from, const char * const message, GTimeVal *tv_stamp, gboolean priv); -void ui_contact_online(const char * const from, const char * const show, - const char * const status, GDateTime *last_activity); +void ui_contact_online(const char * const barejid, const char * const resource, + const char * const show, const char * const status, GDateTime *last_activity); void ui_contact_offline(const char * const from, const char * const show, const char * const status); void ui_disconnected(void); diff --git a/src/ui/windows.c b/src/ui/windows.c index d764755b..2b269223 100644 --- a/src/ui/windows.c +++ b/src/ui/windows.c @@ -453,19 +453,22 @@ ui_show_incoming_msg(const char * const from, const char * const message, } void -ui_contact_online(const char * const from, const char * const show, - const char * const status, GDateTime *last_activity) +ui_contact_online(const char * const barejid, const char * const resource, + const char * const show, const char * const status, GDateTime *last_activity) { - _show_status_string(console->win, from, show, status, last_activity, "++", + Jid *jid = jid_create_from_bare_and_resource(barejid, resource); + _show_status_string(console->win, jid->fulljid, show, status, last_activity, "++", "online"); - int win_index = _find_prof_win_index(from); + int win_index = _find_prof_win_index(barejid); if (win_index != NUM_WINS) { WINDOW *win = windows[win_index]->win; - _show_status_string(win, from, show, status, last_activity, "++", + _show_status_string(win, jid->fulljid, show, status, last_activity, "++", "online"); } + jid_destroy(jid); + if (win_index == current_index) dirty = TRUE; } diff --git a/src/xmpp/presence.c b/src/xmpp/presence.c index aaca0e00..5773e349 100644 --- a/src/xmpp/presence.c +++ b/src/xmpp/presence.c @@ -342,7 +342,7 @@ _unavailable_handler(xmpp_conn_t * const conn, status_str = NULL; if (strcmp(my_jid->barejid, from_jid->barejid) !=0) { - prof_handle_contact_offline(from_jid->barejid, "offline", status_str); + prof_handle_contact_offline(from_jid->barejid, "default", status_str); } jid_destroy(my_jid); @@ -406,9 +406,25 @@ _available_handler(xmpp_conn_t * const conn, else status_str = NULL; + // 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); + } + } + + // if not self presence (TODO allow self presence from other resources?) if (strcmp(my_jid->barejid, from_jid->barejid) !=0) { - prof_handle_contact_online(from_jid->barejid, show_str, status_str, - last_activity, caps_key); + // create the resource + resource_presence_t presence = resource_presence_from_string(show_str); + Resource *resource = resource_new("default", presence, + status_str, priority, caps_key); + prof_handle_contact_online(from_jid->barejid, resource, last_activity); } jid_destroy(my_jid);