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

Refactored available presence handler

This commit is contained in:
James Booth 2014-11-26 21:07:46 +00:00
parent ed228ebb59
commit 508bfeb2bf
3 changed files with 119 additions and 73 deletions

View File

@ -562,95 +562,47 @@ _available_handler(xmpp_conn_t * const conn,
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");
}
int err = 0;
XMPPPresence *xmpp_presence = stanza_parse_presence(stanza, &err);
// exit when no from attribute
if (!from) {
log_warning("No from attribute found.");
if (!xmpp_presence) {
char *from = NULL;
switch(err) {
case STANZA_PARSE_ERROR_NO_FROM:
log_warning("Available presence handler fired with no from attribute.");
break;
case STANZA_PARSE_ERROR_INVALID_FROM:
from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
log_warning("Available presence handler fired with invalid from attribute: %s", from);
break;
default:
log_warning("Available presence handler fired, could not parse stanza.");
break;
}
return 1;
} else if (xmpp_presence->jid->fulljid) {
log_debug("Presence available handler fired for: %s", xmpp_presence->jid->fulljid);
} else {
log_debug("Presence available handler fired for: %s", xmpp_presence->jid->barejid);
}
// 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))) {
if ((g_strcmp0(my_jid->fulljid, xmpp_presence->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);
Resource *resource = stanza_resource_from_presence(xmpp_presence);
// check for self presence
if (g_strcmp0(my_jid->barejid, from_jid->barejid) == 0) {
if (g_strcmp0(xmpp_presence->jid->barejid, my_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);
handle_contact_online(xmpp_presence->jid->barejid, resource, xmpp_presence->last_activity);
}
jid_destroy(my_jid);
jid_destroy(from_jid);
stanza_free_presence(xmpp_presence);
return 1;
}

View File

@ -1577,3 +1577,80 @@ stanza_get_presence_string_from_type(resource_presence_t presence_type)
return NULL;
}
}
Resource*
stanza_resource_from_presence(XMPPPresence *presence)
{
// create Resource
Resource *resource = NULL;
resource_presence_t resource_presence = resource_presence_from_string(presence->show);
if (presence->jid->resourcepart == NULL) { // hack for servers that do not send full jid
resource = resource_new("__prof_default", resource_presence, presence->status, presence->priority);
} else {
resource = resource_new(presence->jid->resourcepart, resource_presence, presence->status, presence->priority);
}
return resource;
}
void
stanza_free_presence(XMPPPresence *presence)
{
if (presence) {
if (presence->jid) {
jid_destroy(presence->jid);
}
if (presence->last_activity) {
g_date_time_unref(presence->last_activity);
}
if (presence->show) {
free(presence->show);
}
if (presence->status) {
free(presence->status);
}
}
}
XMPPPresence *
stanza_parse_presence(xmpp_stanza_t *stanza, int *err)
{
char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
if (!from) {
*err = STANZA_PARSE_ERROR_NO_FROM;
return NULL;
}
Jid *from_jid = jid_create(from);
if (!from_jid) {
*err = STANZA_PARSE_ERROR_INVALID_FROM;
return NULL;
}
XMPPPresence *result = (XMPPPresence *)malloc(sizeof(XMPPPresence));
result->jid = from_jid;
result->show = stanza_get_show(stanza, "online");
result->status = stanza_get_status(stanza, NULL);
int idle_seconds = stanza_get_idle_time(stanza);
if (idle_seconds > 0) {
GDateTime *now = g_date_time_new_now_local();
result->last_activity = g_date_time_add_seconds(now, 0 - idle_seconds);
g_date_time_unref(now);
} else {
result->last_activity = NULL;
}
result->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) {
result->priority = atoi(priority_str);
}
free(priority_str);
}
return result;
}

View File

@ -157,6 +157,19 @@
#define STANZA_DATAFORM_SOFTWARE "urn:xmpp:dataforms:softwareinfo"
typedef struct presence_stanza_t {
Jid *jid;
char *show;
char *status;
int priority;
GDateTime *last_activity;
} XMPPPresence;
typedef enum {
STANZA_PARSE_ERROR_NO_FROM,
STANZA_PARSE_ERROR_INVALID_FROM
} stanza_parse_error_t;
xmpp_stanza_t* stanza_create_bookmarks_storage_request(xmpp_ctx_t *ctx);
xmpp_stanza_t* stanza_create_chat_state(xmpp_ctx_t *ctx,
@ -261,4 +274,8 @@ char* stanza_get_muc_destroy_reason(xmpp_stanza_t *stanza);
char* stanza_get_actor(xmpp_stanza_t *stanza);
char* stanza_get_reason(xmpp_stanza_t *stanza);
Resource* stanza_resource_from_presence(XMPPPresence *presence);
XMPPPresence* stanza_parse_presence(xmpp_stanza_t *stanza, int *err);
void stanza_free_presence(XMPPPresence *presence);
#endif