about summary refs log tree commit diff stats
path: root/src/xmpp/iq.c
diff options
context:
space:
mode:
authorDominik Heidler <dominik@heidler.eu>2016-04-11 20:13:18 +0200
committerDominik Heidler <dominik@heidler.eu>2016-04-26 23:50:55 +0200
commit1b0ce852bba81c3bbed1f7cbf04d0b60f1f0961b (patch)
tree6a611a76d29452910014f9cee4060b372145ece4 /src/xmpp/iq.c
parent28e260c7da7bddebcb7b08003174eb16b9a6f596 (diff)
downloadprofani-tty-1b0ce852bba81c3bbed1f7cbf04d0b60f1f0961b.tar.gz
Implement XEP-0363: HTTP File Upload
Diffstat (limited to 'src/xmpp/iq.c')
-rw-r--r--src/xmpp/iq.c92
1 files changed, 92 insertions, 0 deletions
diff --git a/src/xmpp/iq.c b/src/xmpp/iq.c
index a2566945..ef1a45b5 100644
--- a/src/xmpp/iq.c
+++ b/src/xmpp/iq.c
@@ -64,6 +64,7 @@
 #include "roster_list.h"
 #include "xmpp/xmpp.h"
 #include "plugins/plugins.h"
+#include "tools/http_upload.h"
 
 typedef struct p_room_info_data_t {
     char *room;
@@ -88,6 +89,7 @@ static void _ping_get_handler(xmpp_stanza_t *const stanza);
 static int _version_result_id_handler(xmpp_stanza_t *const stanza, void *const userdata);
 static int _disco_info_response_id_handler(xmpp_stanza_t *const stanza, void *const userdata);
 static int _disco_info_response_id_handler_onconnect(xmpp_stanza_t *const stanza, void *const userdata);
+static int _http_upload_response_id_handler(xmpp_stanza_t *const stanza, void *const upload_ctx);
 static int _last_activity_response_id_handler(xmpp_stanza_t *const stanza, void *const userdata);
 static int _room_info_response_id_handler(xmpp_stanza_t *const stanza, void *const userdata);
 static int _destroy_room_result_id_handler(xmpp_stanza_t *const stanza, void *const userdata);
@@ -294,6 +296,42 @@ iq_disable_carbons(void)
 }
 
 void
+iq_http_upload_request(HTTPUpload *upload)
+{
+    GSList *disco_items = jabber_get_disco_items();
+    DiscoInfo *disco_info;
+    if (disco_items && (g_slist_length(disco_items) > 0)) {
+        while (disco_items) {
+            disco_info = disco_items->data;
+            if (g_hash_table_lookup_extended(disco_info->features, STANZA_NS_HTTP_UPLOAD, NULL, NULL)) {
+                break;
+            }
+            disco_items = g_slist_next(disco_items);
+            if (!disco_items) {
+                cons_show_error("XEP-0363 HTTP File Upload is not supported by the server");
+                return;
+            }
+        }
+    } else {
+        cons_show_error("No disco items");
+        return;
+    }
+
+    xmpp_ctx_t * const ctx = connection_get_ctx();
+    char *id = create_unique_id("http_upload_request");
+
+    xmpp_stanza_t *iq = stanza_create_http_upload_request(ctx, id, disco_info->item, upload);
+
+    id_handler_add(id, _http_upload_response_id_handler, upload);
+
+    free(id);
+
+    send_iq_stanza(iq);
+    xmpp_stanza_release(iq);
+    return;
+}
+
+void
 iq_disco_info_request(gchar *jid)
 {
     xmpp_ctx_t * const ctx = connection_get_ctx();
@@ -1904,6 +1942,60 @@ _disco_info_response_id_handler_onconnect(xmpp_stanza_t *const stanza, void *con
     return 0;
 }
 
+static int
+_http_upload_response_id_handler(xmpp_stanza_t *const stanza, void *const userdata)
+{
+    HTTPUpload *upload = (HTTPUpload *)userdata;
+    const char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
+    const char *type = xmpp_stanza_get_type(stanza);
+
+    if (from) {
+        log_info("Received http_upload response from: %s", from);
+    } else {
+        log_info("Received http_upload response");
+    }
+
+    // handle error responses
+    if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) {
+        char *error_message = stanza_get_error_message(stanza);
+        if (from) {
+            cons_show_error("Uploading '%s' failed for %s: %s", upload->filename, from, error_message);
+        } else {
+            cons_show_error("Uploading '%s' failed: %s", upload->filename, error_message);
+        }
+        free(error_message);
+        return 0;
+    }
+
+    xmpp_stanza_t *slot = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_SLOT);
+
+    if (slot && g_strcmp0(xmpp_stanza_get_ns(slot), STANZA_NS_HTTP_UPLOAD) == 0) {
+        xmpp_stanza_t *put = xmpp_stanza_get_child_by_name(slot, STANZA_NAME_PUT);
+        xmpp_stanza_t *get = xmpp_stanza_get_child_by_name(slot, STANZA_NAME_GET);
+
+        if (put && get) {
+            char *put_url = xmpp_stanza_get_text(put);
+            char *get_url = xmpp_stanza_get_text(get);
+
+            upload->put_url = strdup(put_url);
+            upload->get_url = strdup(get_url);
+
+            xmpp_conn_t *conn = connection_get_conn();
+            xmpp_ctx_t *ctx = xmpp_conn_get_context(conn);
+            if (put_url) xmpp_free(ctx, put_url);
+            if (get_url) xmpp_free(ctx, get_url);
+
+            pthread_create(&(upload->worker), NULL, &http_file_put, upload);
+            upload_processes = g_slist_append(upload_processes, upload);
+        } else {
+            log_error("Invalid XML in HTTP Upload slot");
+            return 1;
+        }
+    }
+
+    return 0;
+}
+
 static void
 _disco_items_result_handler(xmpp_stanza_t *const stanza)
 {