diff options
-rw-r--r-- | src/xmpp/presence.c | 100 | ||||
-rw-r--r-- | src/xmpp/stanza.c | 77 | ||||
-rw-r--r-- | src/xmpp/stanza.h | 17 |
3 files changed, 120 insertions, 74 deletions
diff --git a/src/xmpp/presence.c b/src/xmpp/presence.c index 8f2230a7..389540e8 100644 --- a/src/xmpp/presence.c +++ b/src/xmpp/presence.c @@ -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"); - } - - // exit when no from attribute - if (!from) { - log_warning("No from attribute found."); + int err = 0; + XMPPPresence *xmpp_presence = stanza_parse_presence(stanza, &err); + + 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; } diff --git a/src/xmpp/stanza.c b/src/xmpp/stanza.c index 43901ef7..e0943b1f 100644 --- a/src/xmpp/stanza.c +++ b/src/xmpp/stanza.c @@ -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; +} diff --git a/src/xmpp/stanza.h b/src/xmpp/stanza.h index 1a83c5a6..d6a3b042 100644 --- a/src/xmpp/stanza.h +++ b/src/xmpp/stanza.h @@ -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 |