application/davcontroller.c

changeset 51
e324291ca9f8
parent 49
2f71f4ee247a
--- a/application/davcontroller.c	Sun Oct 06 18:43:06 2024 +0200
+++ b/application/davcontroller.c	Sun Oct 20 21:24:13 2024 +0200
@@ -34,6 +34,7 @@
 #include "config.h"
 
 #include "system.h"
+#include "common/context.h"
 
 #include <libidav/config.h>
 #include <libidav/utils.h>
@@ -48,6 +49,8 @@
     doc->navstack_pos = 0;
 
     doc->dav_queue = ui_threadpool_create(1);
+    
+    doc->res_open_inprogress = cxHashMapCreate(ctx->allocator, CX_STORE_POINTERS, 4);
 
     doc->path = ui_string_new(ctx, "path");
     doc->resources = ui_list_new(ctx, "reslist");
@@ -198,6 +201,64 @@
     }
 }
 
+void davbrowser_open_resource(UiObject *ui, DavBrowser *browser, DavResource *res) {
+    char *url = util_concat_path(browser->sn->base_url, res->path);
+    void *x = cxMapGet(browser->res_open_inprogress, url);
+    free(url);
+    if(x) {
+        return; // open resource already in progress
+    }
+    
+    DavResourceViewType type = DAV_RESOURCE_VIEW_PROPERTIES;
+    if(res->iscollection) {
+        // default type
+    } else if(res->contenttype) {
+        cxstring contenttype = cx_str(res->contenttype);
+        if(cx_strprefix(contenttype, CX_STR("text/"))) {
+            type = DAV_RESOURCE_VIEW_TEXT;
+        } else if(cx_strprefix(contenttype, CX_STR("image/"))) {
+            type = DAV_RESOURCE_VIEW_IMAGE;
+        } else if(cx_strprefix(contenttype, CX_STR("application/"))) {
+            if(cx_strsuffix(contenttype, CX_STR("json"))) {
+                type = DAV_RESOURCE_VIEW_TEXT;
+            } else if(cx_strsuffix(contenttype, CX_STR("/xml"))) {
+                type = DAV_RESOURCE_VIEW_TEXT;
+            } else if(cx_strsuffix(contenttype, CX_STR("+xml"))) {
+                type = DAV_RESOURCE_VIEW_TEXT;
+            } else if(cx_strsuffix(contenttype, CX_STR("/xml"))) {
+                type = DAV_RESOURCE_VIEW_TEXT;
+            }
+        }
+    } else {
+        cxstring path = cx_str(res->path);
+        if(cx_strsuffix(path, CX_STR(".png"))) {
+            type = DAV_RESOURCE_VIEW_IMAGE;
+        } else if(cx_strsuffix(path, CX_STR(".jpg"))) {
+            type = DAV_RESOURCE_VIEW_IMAGE;
+        } else if(cx_strsuffix(path, CX_STR(".jpeg"))) {
+            type = DAV_RESOURCE_VIEW_IMAGE;
+        } else if(cx_strsuffix(path, CX_STR(".tif"))) {
+            type = DAV_RESOURCE_VIEW_IMAGE;
+        } else if(cx_strsuffix(path, CX_STR(".tiff"))) {
+            type = DAV_RESOURCE_VIEW_IMAGE;
+        } else if(cx_strsuffix(path, CX_STR(".webp"))) {
+            type = DAV_RESOURCE_VIEW_IMAGE;
+        } else if(cx_strsuffix(path, CX_STR(".bmp"))) {
+            type = DAV_RESOURCE_VIEW_IMAGE;
+        } else if(cx_strsuffix(path, CX_STR(".gif"))) {
+            type = DAV_RESOURCE_VIEW_IMAGE;
+        } else if(cx_strsuffix(path, CX_STR(".txt"))) {
+            type = DAV_RESOURCE_VIEW_TEXT;
+        } else if(cx_strsuffix(path, CX_STR(".md"))) {
+            type = DAV_RESOURCE_VIEW_TEXT;
+        } else if(cx_strsuffix(path, CX_STR(".xml"))) {
+            type = DAV_RESOURCE_VIEW_TEXT;
+        }
+    }
+    
+    dav_resourceviewer_new(browser, res->path, type);
+}
+
 void davbrowser_add2navstack(DavBrowser *browser, const char *base, const char *path) {
     if (browser->navstack_enabled) {
         for (int i = 0; i < browser->navstack_pos; i++) {
@@ -1152,3 +1213,102 @@
 void davbrowser_newfile(UiObject *ui, DavBrowser *browser, const char *name) {
     davbrowser_create_resource(ui, browser, name, FALSE);
 }
+
+
+
+DavResourceViewer* dav_resourceviewer_create(DavSession *sn, const char *path, DavResourceViewType type) {
+    DavResourceViewer *doc = ui_document_new(sizeof(DavResourceViewer));
+    UiContext *ctx = ui_document_context(doc);
+    doc->ctx = ctx;
+    
+    doc->sn = dav_session_clone(sn);
+    doc->path = strdup(path);
+    doc->type = type;
+    
+    doc->tabview = ui_int_new(ctx, "tabview");
+    doc->loading = ui_int_new(ctx, "loading");
+    doc->message = ui_string_new(ctx, "message");
+    
+    doc->text = ui_text_new(ctx, "text");
+    doc->image = ui_generic_new(ctx, "image");
+    
+    doc->properties = ui_list_new(ctx, "properties");
+    
+    return doc;
+}
+
+static char* gen_tmp_download_filename(const char *name) {
+    char *dir = ui_getappdir();
+    
+    unsigned char rd[8];
+    memset(rd, 0, 8);
+    dav_rand_bytes(rd, 8);   
+    char *hex = util_hexstr(rd, 8);
+    cxmutstr tmp = cx_asprintf("%sdownload-%s-%s", dir, name, hex);
+    return tmp.ptr;
+}
+
+static int jobthr_resourceviewer_load(void *data) {
+    DavResourceViewer *doc = data;
+    
+    DavResource *res = dav_resource_new(doc->sn, doc->path);
+    doc->error = dav_load(res);
+    if(!doc->error) {
+        doc->current = res;
+        
+        if(res->contentlength < DAV_RESOURCEVIEWER_PREVIEW_MAX_SIZE) {
+            if(doc->type == DAV_RESOURCE_VIEW_TEXT) {
+                doc->text_content = cxBufferCreate(NULL, res->contentlength, cxDefaultAllocator, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS);
+                int err = dav_get_content(res, doc->text_content, (dav_write_func)cxBufferWrite);
+                cxBufferPut(doc->text_content, 0);
+                if(err) {
+                    doc->error = err;
+                    doc->message_str = "Cannot load content"; // TODO: better message
+                }
+            } else if(doc->type == DAV_RESOURCE_VIEW_IMAGE) {
+                char *tmp = gen_tmp_download_filename(res->name);
+                FILE *f = fopen(tmp, "w");
+                if(f) {
+                    int err = dav_get_content(res, f, (dav_write_func)fwrite);
+                    if(!err) {
+                        doc->tmp_file = tmp;
+                    } else {
+                        free(tmp);
+                    }
+                    fclose(f);
+                } else {
+                    free(tmp);
+                }
+            }
+        } else {
+            // TODO: add file too large message
+        }
+    } else {
+        doc->message_str = "Cannot load properties"; // TODO: better message
+        dav_resource_free(res);
+    }
+    
+    return 0;
+}
+
+static void resourceviewer_load_finished(UiEvent *event, void *data) {
+    DavResourceViewer *doc = data;
+    
+    if(doc->type == DAV_RESOURCE_VIEW_TEXT) {
+        ui_set(doc->text, doc->text_content->space);
+    } else if(doc->type == DAV_RESOURCE_VIEW_IMAGE) {
+        ui_image_load_file(doc->image, doc->tmp_file);
+        unlink(doc->tmp_file);
+    }
+    
+    ui_set(doc->tabview, 1);
+}
+
+void dav_resourceviewer_load(UiObject *ui, DavResourceViewer *res) {
+    ui_set(res->loading, 1);
+    ui_set(res->message, "Loading...");
+    ui_set(res->tabview, 0);
+    
+    ui_job(ui, jobthr_resourceviewer_load, res, resourceviewer_load_finished, res);
+}
+

mercurial