about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/xmpp/presence.c100
-rw-r--r--src/xmpp/stanza.c77
-rw-r--r--src/xmpp/stanza.h17
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