mirror of
				https://github.com/simon987/sist2.git
				synced 2025-11-04 09:36:53 +00:00 
			
		
		
		
	wip
This commit is contained in:
		
							parent
							
								
									230988d6d1
								
							
						
					
					
						commit
						8127745f2b
					
				@ -326,7 +326,7 @@ int web_args_validate(web_args_t *args, int argc, const char **argv) {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        strncpy(args->auth_user, args->credentials, (ptr - args->credentials));
 | 
					        strncpy(args->auth_user, args->credentials, (ptr - args->credentials));
 | 
				
			||||||
        strncpy(args->auth_pass, ptr + 1, strlen(ptr + 1));
 | 
					        strcpy(args->auth_pass, ptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (strlen(args->auth_user) == 0) {
 | 
					        if (strlen(args->auth_user) == 0) {
 | 
				
			||||||
            fprintf(stderr, "--auth username must be at least one character long");
 | 
					            fprintf(stderr, "--auth username must be at least one character long");
 | 
				
			||||||
 | 
				
			|||||||
@ -13,6 +13,7 @@
 | 
				
			|||||||
#include "libscan/text/text.h"
 | 
					#include "libscan/text/text.h"
 | 
				
			||||||
#include "libscan/mobi/scan_mobi.h"
 | 
					#include "libscan/mobi/scan_mobi.h"
 | 
				
			||||||
#include "libscan/raw/raw.h"
 | 
					#include "libscan/raw/raw.h"
 | 
				
			||||||
 | 
					#include "src/io/store.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <glib.h>
 | 
					#include <glib.h>
 | 
				
			||||||
#include <pcre.h>
 | 
					#include <pcre.h>
 | 
				
			||||||
 | 
				
			|||||||
@ -313,6 +313,11 @@ void finish_indexer(char *script, char *index_id) {
 | 
				
			|||||||
    r = web_post(url, "");
 | 
					    r = web_post(url, "");
 | 
				
			||||||
    LOG_INFOF("elastic.c", "Merge index <%d>", r->status_code);
 | 
					    LOG_INFOF("elastic.c", "Merge index <%d>", r->status_code);
 | 
				
			||||||
    free_response(r);
 | 
					    free_response(r);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    snprintf(url, sizeof(url), "%s/sist2/_settings", IndexCtx.es_url);
 | 
				
			||||||
 | 
					    r = web_put(url, "{\"index\":{\"refresh_interval\":\"1s\"}}");
 | 
				
			||||||
 | 
					    LOG_INFOF("elastic.c", "Set refresh interval <%d>", r->status_code);
 | 
				
			||||||
 | 
					    free_response(r);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void elastic_init(int force_reset) {
 | 
					void elastic_init(int force_reset) {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,9 +1,10 @@
 | 
				
			|||||||
#include "store.h"
 | 
					#include "store.h"
 | 
				
			||||||
#include "src/ctx.h"
 | 
					#include "src/ctx.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
store_t *store_create(char *path) {
 | 
					store_t *store_create(char *path, size_t chunk_size) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    store_t *store = malloc(sizeof(struct store_t));
 | 
					    store_t *store = malloc(sizeof(struct store_t));
 | 
				
			||||||
 | 
					    store->chunk_size = chunk_size;
 | 
				
			||||||
    pthread_rwlock_init(&store->lock, NULL);
 | 
					    pthread_rwlock_init(&store->lock, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    mdb_env_create(&store->env);
 | 
					    mdb_env_create(&store->env);
 | 
				
			||||||
@ -18,7 +19,7 @@ store_t *store_create(char *path) {
 | 
				
			|||||||
        LOG_FATALF("store.c", "Error while opening store: %s (%s)\n", mdb_strerror(open_ret), path)
 | 
					        LOG_FATALF("store.c", "Error while opening store: %s (%s)\n", mdb_strerror(open_ret), path)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    store->size = (size_t) 1024 * 1024 * 5;
 | 
					    store->size = (size_t) store->chunk_size;
 | 
				
			||||||
    ScanCtx.stat_tn_size = 0;
 | 
					    ScanCtx.stat_tn_size = 0;
 | 
				
			||||||
    mdb_env_set_mapsize(store->env, store->size);
 | 
					    mdb_env_set_mapsize(store->env, store->size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -69,7 +70,7 @@ void store_write(store_t *store, char *key, size_t key_len, char *buf, size_t bu
 | 
				
			|||||||
        // Cannot resize when there is a opened transaction.
 | 
					        // Cannot resize when there is a opened transaction.
 | 
				
			||||||
        //  Resize take effect on the next commit.
 | 
					        //  Resize take effect on the next commit.
 | 
				
			||||||
        pthread_rwlock_wrlock(&store->lock);
 | 
					        pthread_rwlock_wrlock(&store->lock);
 | 
				
			||||||
        store->size += 1024 * 1024 * 50;
 | 
					        store->size += store->chunk_size;
 | 
				
			||||||
        mdb_env_set_mapsize(store->env, store->size);
 | 
					        mdb_env_set_mapsize(store->env, store->size);
 | 
				
			||||||
        mdb_txn_begin(store->env, NULL, 0, &txn);
 | 
					        mdb_txn_begin(store->env, NULL, 0, &txn);
 | 
				
			||||||
        put_ret = mdb_put(txn, store->dbi, &mdb_key, &mdb_value, 0);
 | 
					        put_ret = mdb_put(txn, store->dbi, &mdb_key, &mdb_value, 0);
 | 
				
			||||||
 | 
				
			|||||||
@ -4,14 +4,18 @@
 | 
				
			|||||||
#include <pthread.h>
 | 
					#include <pthread.h>
 | 
				
			||||||
#include <lmdb.h>
 | 
					#include <lmdb.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define STORE_SIZE_TN 1024 * 1024 * 5
 | 
				
			||||||
 | 
					#define STORE_SIZE_TAG 1024 * 16
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct store_t {
 | 
					typedef struct store_t {
 | 
				
			||||||
    MDB_dbi dbi;
 | 
					    MDB_dbi dbi;
 | 
				
			||||||
    MDB_env *env;
 | 
					    MDB_env *env;
 | 
				
			||||||
    size_t size;
 | 
					    size_t size;
 | 
				
			||||||
 | 
					    size_t chunk_size;
 | 
				
			||||||
    pthread_rwlock_t lock;
 | 
					    pthread_rwlock_t lock;
 | 
				
			||||||
} store_t;
 | 
					} store_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
store_t *store_create(char *path);
 | 
					store_t *store_create(char *path, size_t chunk_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void store_destroy(store_t *store);
 | 
					void store_destroy(store_t *store);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										10
									
								
								src/main.c
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								src/main.c
									
									
									
									
									
								
							@ -176,7 +176,7 @@ void sist2_scan(scan_args_t *args) {
 | 
				
			|||||||
    char store_path[PATH_MAX];
 | 
					    char store_path[PATH_MAX];
 | 
				
			||||||
    snprintf(store_path, PATH_MAX, "%sthumbs", ScanCtx.index.path);
 | 
					    snprintf(store_path, PATH_MAX, "%sthumbs", ScanCtx.index.path);
 | 
				
			||||||
    mkdir(store_path, S_IWUSR | S_IRUSR | S_IXUSR);
 | 
					    mkdir(store_path, S_IWUSR | S_IRUSR | S_IXUSR);
 | 
				
			||||||
    ScanCtx.index.store = store_create(store_path);
 | 
					    ScanCtx.index.store = store_create(store_path, STORE_SIZE_TN);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    scan_print_header();
 | 
					    scan_print_header();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -223,7 +223,7 @@ void sist2_scan(scan_args_t *args) {
 | 
				
			|||||||
        char dst_path[PATH_MAX];
 | 
					        char dst_path[PATH_MAX];
 | 
				
			||||||
        snprintf(store_path, PATH_MAX, "%sthumbs", args->incremental);
 | 
					        snprintf(store_path, PATH_MAX, "%sthumbs", args->incremental);
 | 
				
			||||||
        snprintf(dst_path, PATH_MAX, "%s_index_original", ScanCtx.index.path);
 | 
					        snprintf(dst_path, PATH_MAX, "%s_index_original", ScanCtx.index.path);
 | 
				
			||||||
        store_t *source = store_create(store_path);
 | 
					        store_t *source = store_create(store_path, STORE_SIZE_TN);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        DIR *dir = opendir(args->incremental);
 | 
					        DIR *dir = opendir(args->incremental);
 | 
				
			||||||
        if (dir == NULL) {
 | 
					        if (dir == NULL) {
 | 
				
			||||||
@ -339,7 +339,11 @@ void sist2_web(web_args_t *args) {
 | 
				
			|||||||
        char path_tmp[PATH_MAX];
 | 
					        char path_tmp[PATH_MAX];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        snprintf(path_tmp, PATH_MAX, "%sthumbs", abs_path);
 | 
					        snprintf(path_tmp, PATH_MAX, "%sthumbs", abs_path);
 | 
				
			||||||
        WebCtx.indices[i].store = store_create(path_tmp);
 | 
					        WebCtx.indices[i].store = store_create(path_tmp, STORE_SIZE_TN);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        snprintf(path_tmp, PATH_MAX, "%stags", abs_path);
 | 
				
			||||||
 | 
					        mkdir(path_tmp, S_IWUSR | S_IRUSR | S_IXUSR);
 | 
				
			||||||
 | 
					        WebCtx.indices[i].tag_store = store_create(path_tmp, STORE_SIZE_TAG);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        snprintf(path_tmp, PATH_MAX, "%sdescriptor.json", abs_path);
 | 
					        snprintf(path_tmp, PATH_MAX, "%sdescriptor.json", abs_path);
 | 
				
			||||||
        WebCtx.indices[i].desc = read_index_descriptor(path_tmp);
 | 
					        WebCtx.indices[i].desc = read_index_descriptor(path_tmp);
 | 
				
			||||||
 | 
				
			|||||||
@ -106,6 +106,21 @@ body {
 | 
				
			|||||||
    background-color: #e0e0e0;
 | 
					    background-color: #e0e0e0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.badge {
 | 
				
			||||||
 | 
					    margin-right: 3px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.badge-delete {
 | 
				
			||||||
 | 
					    margin-right: -2px;
 | 
				
			||||||
 | 
					    margin-left: 2px;
 | 
				
			||||||
 | 
					    font-family: monospace;
 | 
				
			||||||
 | 
					    font-size: 90%;
 | 
				
			||||||
 | 
					    background: rgba(0,0,0,0.2);
 | 
				
			||||||
 | 
					    padding: 0.1em 0.4em;
 | 
				
			||||||
 | 
					    color: white;
 | 
				
			||||||
 | 
					    cursor: pointer;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.badge-text {
 | 
					.badge-text {
 | 
				
			||||||
    color: #FFFFFF;
 | 
					    color: #FFFFFF;
 | 
				
			||||||
    background-color: #FAAB3C;
 | 
					    background-color: #FAAB3C;
 | 
				
			||||||
@ -137,9 +152,6 @@ body {
 | 
				
			|||||||
    overflow: hidden;
 | 
					    overflow: hidden;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.badge {
 | 
					 | 
				
			||||||
    margin-right: 3px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
.fit {
 | 
					.fit {
 | 
				
			||||||
    display: block;
 | 
					    display: block;
 | 
				
			||||||
 | 
				
			|||||||
@ -153,6 +153,14 @@ function getTags(hit, mimeCategory) {
 | 
				
			|||||||
    // User tags
 | 
					    // User tags
 | 
				
			||||||
    if (hit["_source"].hasOwnProperty("tag")) {
 | 
					    if (hit["_source"].hasOwnProperty("tag")) {
 | 
				
			||||||
        hit["_source"]["tag"].forEach(tag => {
 | 
					        hit["_source"]["tag"].forEach(tag => {
 | 
				
			||||||
 | 
					            tags.push(makeUserTag(tag, hit));
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return tags
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function makeUserTag(tag, hit) {
 | 
				
			||||||
    const userTag = document.createElement("span");
 | 
					    const userTag = document.createElement("span");
 | 
				
			||||||
    userTag.setAttribute("class", "badge badge-pill badge-user");
 | 
					    userTag.setAttribute("class", "badge badge-pill badge-user");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -164,13 +172,22 @@ function getTags(hit, mimeCategory) {
 | 
				
			|||||||
        userTag.setAttribute("style", `background-color: ${bg}; color: ${fg}`);
 | 
					        userTag.setAttribute("style", `background-color: ${bg}; color: ${fg}`);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const deleteButton = document.createElement("span");
 | 
				
			||||||
 | 
					    deleteButton.setAttribute("class", "badge badge-pill badge-delete")
 | 
				
			||||||
 | 
					    deleteButton.setAttribute("title", "Delete tag")
 | 
				
			||||||
 | 
					    deleteButton.appendChild(document.createTextNode("X"));
 | 
				
			||||||
 | 
					    deleteButton.addEventListener("click", () => {
 | 
				
			||||||
 | 
					        deleteTag(tag, hit).then(() => {
 | 
				
			||||||
 | 
					            userTag.remove();
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    userTag.addEventListener("mouseenter", () => userTag.appendChild(deleteButton));
 | 
				
			||||||
 | 
					    userTag.addEventListener("mouseleave", () => deleteButton.remove());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const name = tokens[0].split(".")[tokens[0].split(".").length - 1];
 | 
					    const name = tokens[0].split(".")[tokens[0].split(".").length - 1];
 | 
				
			||||||
    userTag.appendChild(document.createTextNode(name));
 | 
					    userTag.appendChild(document.createTextNode(name));
 | 
				
			||||||
            tags.push(userTag);
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return tags
 | 
					    return userTag;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function infoButtonCb(hit) {
 | 
					function infoButtonCb(hit) {
 | 
				
			||||||
@ -338,11 +355,11 @@ function createDocCard(hit) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    docCardBody.appendChild(tagContainer);
 | 
					    docCardBody.appendChild(tagContainer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    attachTagContainerEventListener(tagContainer);
 | 
					    attachTagContainerEventListener(tagContainer, hit);
 | 
				
			||||||
    return docCard;
 | 
					    return docCard;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function attachTagContainerEventListener(tagContainer) {
 | 
					function attachTagContainerEventListener(tagContainer, hit) {
 | 
				
			||||||
    const sizeTag = Array.from(tagContainer.children).find(child => child.tagName === "SMALL");
 | 
					    const sizeTag = Array.from(tagContainer.children).find(child => child.tagName === "SMALL");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const addTagButton = document.createElement("span");
 | 
					    const addTagButton = document.createElement("span");
 | 
				
			||||||
@ -354,6 +371,10 @@ function attachTagContainerEventListener(tagContainer) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    addTagButton.addEventListener("click", () => {
 | 
					    addTagButton.addEventListener("click", () => {
 | 
				
			||||||
        tagBar.value = "";
 | 
					        tagBar.value = "";
 | 
				
			||||||
 | 
					        currentDocToTag = hit;
 | 
				
			||||||
 | 
					        currentTagCallback = tag => {
 | 
				
			||||||
 | 
					            tagContainer.insertBefore(makeUserTag(tag, hit), sizeTag);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        $("#tagModal").modal("show");
 | 
					        $("#tagModal").modal("show");
 | 
				
			||||||
        tagBar.focus();
 | 
					        tagBar.focus();
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
@ -431,7 +452,6 @@ function createDocLine(hit) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    if (hit["_source"].hasOwnProperty("parent")) {
 | 
					    if (hit["_source"].hasOwnProperty("parent")) {
 | 
				
			||||||
        line.classList.add("sub-document");
 | 
					        line.classList.add("sub-document");
 | 
				
			||||||
        isSubDocument = true;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const infoButton = makeInfoButton(hit);
 | 
					    const infoButton = makeInfoButton(hit);
 | 
				
			||||||
@ -504,6 +524,8 @@ function createDocLine(hit) {
 | 
				
			|||||||
    pathLine.appendChild(path);
 | 
					    pathLine.appendChild(path);
 | 
				
			||||||
    pathLine.appendChild(tagContainer);
 | 
					    pathLine.appendChild(tagContainer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    attachTagContainerEventListener(tagContainer, hit);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return line;
 | 
					    return line;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -7,6 +7,8 @@ let tagTree;
 | 
				
			|||||||
let searchBar = document.getElementById("searchBar");
 | 
					let searchBar = document.getElementById("searchBar");
 | 
				
			||||||
let pathBar = document.getElementById("pathBar");
 | 
					let pathBar = document.getElementById("pathBar");
 | 
				
			||||||
let tagBar = document.getElementById("tagBar");
 | 
					let tagBar = document.getElementById("tagBar");
 | 
				
			||||||
 | 
					let currentDocToTag = null;
 | 
				
			||||||
 | 
					let currentTagCallback = null;
 | 
				
			||||||
let lastDoc = null;
 | 
					let lastDoc = null;
 | 
				
			||||||
let reachedEnd = false;
 | 
					let reachedEnd = false;
 | 
				
			||||||
let docCount = 0;
 | 
					let docCount = 0;
 | 
				
			||||||
@ -136,8 +138,8 @@ window.onload = () => {
 | 
				
			|||||||
    [tagBar, document.getElementById("tag-color")].forEach(elem => {
 | 
					    [tagBar, document.getElementById("tag-color")].forEach(elem => {
 | 
				
			||||||
        elem.addEventListener("keyup", e => {
 | 
					        elem.addEventListener("keyup", e => {
 | 
				
			||||||
            if (e.key === "Enter") {
 | 
					            if (e.key === "Enter") {
 | 
				
			||||||
                console.log("Add tag");
 | 
					                const tag = tagBar.value + document.getElementById("tag-color").value;
 | 
				
			||||||
                //TODO
 | 
					                saveTag(tag, currentDocToTag).then(() => currentTagCallback(tag));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
@ -159,11 +161,57 @@ window.onload = () => {
 | 
				
			|||||||
    });
 | 
					    });
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function saveTag(tag, hit) {
 | 
				
			||||||
 | 
					    const relPath = hit["_source"]["path"] + "/" + hit["_source"] + ext(hit);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return $.jsonPost("/tag/" + hit["_source"]["index"], {
 | 
				
			||||||
 | 
					        delete: false,
 | 
				
			||||||
 | 
					        name: tag,
 | 
				
			||||||
 | 
					        doc_id: hit["_id"],
 | 
				
			||||||
 | 
					        relpath: relPath
 | 
				
			||||||
 | 
					    }).then(() => {
 | 
				
			||||||
 | 
					        tagBar.blur();
 | 
				
			||||||
 | 
					        $("#tagModal").modal("hide");
 | 
				
			||||||
 | 
					        $.toast({
 | 
				
			||||||
 | 
					            heading: "Tag added",
 | 
				
			||||||
 | 
					            text: "Tag saved to index storage and updated in ElasticSearch",
 | 
				
			||||||
 | 
					            stack: 3,
 | 
				
			||||||
 | 
					            bgColor: "#00a4bc",
 | 
				
			||||||
 | 
					            textColor: "#fff",
 | 
				
			||||||
 | 
					            position: 'bottom-right',
 | 
				
			||||||
 | 
					            hideAfter: 3000,
 | 
				
			||||||
 | 
					            loaderBg: "#08c7e8",
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function deleteTag(tag, hit) {
 | 
				
			||||||
 | 
					    const relPath = hit["_source"]["path"] + "/" + hit["_source"] + ext(hit);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return $.jsonPost("/tag/" + hit["_source"]["index"], {
 | 
				
			||||||
 | 
					        delete: true,
 | 
				
			||||||
 | 
					        name: tag,
 | 
				
			||||||
 | 
					        doc_id: hit["_id"],
 | 
				
			||||||
 | 
					        relpath: relPath
 | 
				
			||||||
 | 
					    }).then(() => {
 | 
				
			||||||
 | 
					        $.toast({
 | 
				
			||||||
 | 
					            heading: "Tag deleted",
 | 
				
			||||||
 | 
					            text: "Tag deleted index storage and updated in ElasticSearch",
 | 
				
			||||||
 | 
					            stack: 3,
 | 
				
			||||||
 | 
					            bgColor: "#00a4bc",
 | 
				
			||||||
 | 
					            textColor: "#fff",
 | 
				
			||||||
 | 
					            position: 'bottom-right',
 | 
				
			||||||
 | 
					            hideAfter: 3000,
 | 
				
			||||||
 | 
					            loaderBg: "#08c7e8",
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function toggleFuzzy() {
 | 
					function toggleFuzzy() {
 | 
				
			||||||
    searchDebounced();
 | 
					    searchDebounced();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$.jsonPost("i").then(resp => {
 | 
					$.get("i").then(resp => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const urlIndices = (new URLSearchParams(location.search)).get("i");
 | 
					    const urlIndices = (new URLSearchParams(location.search)).get("i");
 | 
				
			||||||
    resp["indices"].forEach(idx => {
 | 
					    resp["indices"].forEach(idx => {
 | 
				
			||||||
 | 
				
			|||||||
@ -19,6 +19,7 @@ typedef struct index_descriptor {
 | 
				
			|||||||
typedef struct index_t {
 | 
					typedef struct index_t {
 | 
				
			||||||
    struct index_descriptor desc;
 | 
					    struct index_descriptor desc;
 | 
				
			||||||
    struct store_t *store;
 | 
					    struct store_t *store;
 | 
				
			||||||
 | 
					    struct store_t *tag_store;
 | 
				
			||||||
    char path[PATH_MAX];
 | 
					    char path[PATH_MAX];
 | 
				
			||||||
} index_t;
 | 
					} index_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										166
									
								
								src/web/serve.c
									
									
									
									
									
								
							
							
						
						
									
										166
									
								
								src/web/serve.c
									
									
									
									
									
								
							@ -53,6 +53,14 @@ store_t *get_store(const char *index_id) {
 | 
				
			|||||||
    return NULL;
 | 
					    return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					store_t *get_tag_store(const char *index_id) {
 | 
				
			||||||
 | 
					    index_t *idx = get_index_by_id(index_id);
 | 
				
			||||||
 | 
					    if (idx != NULL) {
 | 
				
			||||||
 | 
					        return idx->tag_store;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void search_index(struct mg_connection *nc) {
 | 
					void search_index(struct mg_connection *nc) {
 | 
				
			||||||
    send_response_line(nc, 200, sizeof(search_html), "Content-Type: text/html");
 | 
					    send_response_line(nc, 200, sizeof(search_html), "Content-Type: text/html");
 | 
				
			||||||
    mg_send(nc, search_html, sizeof(search_html));
 | 
					    mg_send(nc, search_html, sizeof(search_html));
 | 
				
			||||||
@ -422,6 +430,162 @@ void status(struct mg_connection *nc) {
 | 
				
			|||||||
    nc->flags |= MG_F_SEND_AND_CLOSE;
 | 
					    nc->flags |= MG_F_SEND_AND_CLOSE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
					    char *name;
 | 
				
			||||||
 | 
					    int delete;
 | 
				
			||||||
 | 
					    char *relpath;
 | 
				
			||||||
 | 
					    char *doc_id;
 | 
				
			||||||
 | 
					} tag_req_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					tag_req_t *parse_tag_request(cJSON *json) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!cJSON_IsObject(json)) {
 | 
				
			||||||
 | 
					        return NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    cJSON *arg_name = cJSON_GetObjectItem(json, "name");
 | 
				
			||||||
 | 
					    if (arg_name == NULL || !cJSON_IsString(arg_name)) {
 | 
				
			||||||
 | 
					        return NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    cJSON *arg_delete = cJSON_GetObjectItem(json, "delete");
 | 
				
			||||||
 | 
					    if (arg_delete == NULL || !cJSON_IsBool(arg_delete)) {
 | 
				
			||||||
 | 
					        return NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    cJSON *arg_relpath = cJSON_GetObjectItem(json, "relpath");
 | 
				
			||||||
 | 
					    if (arg_relpath == NULL || !cJSON_IsString(arg_relpath)) {
 | 
				
			||||||
 | 
					        return NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    cJSON *arg_doc_id = cJSON_GetObjectItem(json, "doc_id");
 | 
				
			||||||
 | 
					    if (arg_doc_id == NULL || !cJSON_IsString(arg_doc_id)) {
 | 
				
			||||||
 | 
					        return NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tag_req_t *req = malloc(sizeof(tag_req_t));
 | 
				
			||||||
 | 
					    req->delete = arg_delete->valueint;
 | 
				
			||||||
 | 
					    req->name = arg_name->valuestring;
 | 
				
			||||||
 | 
					    req->relpath = arg_relpath->valuestring;
 | 
				
			||||||
 | 
					    req->doc_id = arg_doc_id->valuestring;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return req;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void tag(struct mg_connection *nc, struct http_message *hm, struct mg_str *path) {
 | 
				
			||||||
 | 
					    if (path->len != UUID_STR_LEN + 4) {
 | 
				
			||||||
 | 
					        LOG_DEBUGF("serve.c", "Invalid tag path: %.*s", (int) path->len, path->p)
 | 
				
			||||||
 | 
					        mg_http_send_error(nc, 404, NULL);
 | 
				
			||||||
 | 
					        nc->flags |= MG_F_SEND_AND_CLOSE;
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    char arg_index[UUID_STR_LEN];
 | 
				
			||||||
 | 
					    memcpy(arg_index, hm->uri.p + 5, UUID_STR_LEN);
 | 
				
			||||||
 | 
					    *(arg_index + UUID_STR_LEN - 1) = '\0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (hm->body.len < 2 || hm->method.len != 4 || memcmp(&hm->method, "POST", 4) == 0) {
 | 
				
			||||||
 | 
					        LOG_DEBUG("serve.c", "Invalid tag request")
 | 
				
			||||||
 | 
					        mg_http_send_error(nc, 400, NULL);
 | 
				
			||||||
 | 
					        nc->flags |= MG_F_SEND_AND_CLOSE;
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    store_t *store = get_tag_store(arg_index);
 | 
				
			||||||
 | 
					    if (store == NULL) {
 | 
				
			||||||
 | 
					        LOG_DEBUGF("serve.c", "Could not get tag store for index: %s", arg_index)
 | 
				
			||||||
 | 
					        mg_http_send_error(nc, 404, NULL);
 | 
				
			||||||
 | 
					        nc->flags |= MG_F_SEND_AND_CLOSE;
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    char *body = malloc(hm->body.len + 1);
 | 
				
			||||||
 | 
					    memcpy(body, hm->body.p, hm->body.len);
 | 
				
			||||||
 | 
					    *(body + hm->body.len) = '\0';
 | 
				
			||||||
 | 
					    cJSON *json = cJSON_Parse(body);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tag_req_t *arg_req = parse_tag_request(json);
 | 
				
			||||||
 | 
					    if (arg_req == NULL) {
 | 
				
			||||||
 | 
					        LOG_DEBUGF("serve.c", "Could not parse tag request", arg_index)
 | 
				
			||||||
 | 
					        cJSON_Delete(json);
 | 
				
			||||||
 | 
					        free(body);
 | 
				
			||||||
 | 
					        mg_http_send_error(nc, 400, NULL);
 | 
				
			||||||
 | 
					        nc->flags |= MG_F_SEND_AND_CLOSE;
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    cJSON *arr = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    size_t data_len = 0;
 | 
				
			||||||
 | 
					    const char *data = store_read(store, arg_req->relpath, strlen(arg_req->relpath), &data_len);
 | 
				
			||||||
 | 
					    if (data_len == 0) {
 | 
				
			||||||
 | 
					        arr = cJSON_CreateArray();
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        arr = cJSON_Parse(data);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (arg_req->delete) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (data_len > 0) {
 | 
				
			||||||
 | 
					            cJSON *element = NULL;
 | 
				
			||||||
 | 
					            int i = 0;
 | 
				
			||||||
 | 
					            cJSON_ArrayForEach(element, arr) {
 | 
				
			||||||
 | 
					                if (strcmp(element->valuestring, arg_req->name) == 0) {
 | 
				
			||||||
 | 
					                    cJSON_DeleteItemFromArray(arr, i);
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                i++;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        char buf[8196];
 | 
				
			||||||
 | 
					        snprintf(buf, sizeof(buf),
 | 
				
			||||||
 | 
					                 "{"
 | 
				
			||||||
 | 
					                 "    \"script\" : {"
 | 
				
			||||||
 | 
					                 "        \"source\": \"if (ctx._source.tag.contains(params.tag)) { ctx._source.tag.remove(ctx._source.tag.indexOf(params.tag)) }\","
 | 
				
			||||||
 | 
					                 "        \"lang\": \"painless\","
 | 
				
			||||||
 | 
					                 "        \"params\" : {"
 | 
				
			||||||
 | 
					                 "            \"tag\" : \"%s\""
 | 
				
			||||||
 | 
					                 "        }"
 | 
				
			||||||
 | 
					                 "    }"
 | 
				
			||||||
 | 
					                 "}", arg_req->name
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        char url[4096];
 | 
				
			||||||
 | 
					        snprintf(url, sizeof(url), "%s/sist2/_update/%s", WebCtx.es_url, arg_req->doc_id);
 | 
				
			||||||
 | 
					        nc->user_data = web_post_async(url, buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        cJSON_AddItemToArray(arr, cJSON_CreateString(arg_req->name));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        char buf[8196];
 | 
				
			||||||
 | 
					        snprintf(buf, sizeof(buf),
 | 
				
			||||||
 | 
					                 "{"
 | 
				
			||||||
 | 
					                 "    \"script\" : {"
 | 
				
			||||||
 | 
					                 "        \"source\": \"ctx._source.tag.add(params.tag)\","
 | 
				
			||||||
 | 
					                 "        \"lang\": \"painless\","
 | 
				
			||||||
 | 
					                 "        \"params\" : {"
 | 
				
			||||||
 | 
					                 "            \"tag\" : \"%s\""
 | 
				
			||||||
 | 
					                 "        }"
 | 
				
			||||||
 | 
					                 "    }"
 | 
				
			||||||
 | 
					                 "}", arg_req->name
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        char url[4096];
 | 
				
			||||||
 | 
					        snprintf(url, sizeof(url), "%s/sist2/_update/%s", WebCtx.es_url, arg_req->doc_id);
 | 
				
			||||||
 | 
					        nc->user_data = web_post_async(url, buf);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    char *json_str = cJSON_PrintUnformatted(arr);
 | 
				
			||||||
 | 
					    store_write(store, arg_req->relpath, strlen(arg_req->relpath), json_str, strlen(json_str) + 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    free(arg_req);
 | 
				
			||||||
 | 
					    free(json_str);
 | 
				
			||||||
 | 
					    cJSON_Delete(json);
 | 
				
			||||||
 | 
					    cJSON_Delete(arr);
 | 
				
			||||||
 | 
					    free(body);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void ev_router(struct mg_connection *nc, int ev, void *p) {
 | 
					static void ev_router(struct mg_connection *nc, int ev, void *p) {
 | 
				
			||||||
    struct mg_str scheme;
 | 
					    struct mg_str scheme;
 | 
				
			||||||
    struct mg_str user_info;
 | 
					    struct mg_str user_info;
 | 
				
			||||||
@ -479,6 +643,8 @@ static void ev_router(struct mg_connection *nc, int ev, void *p) {
 | 
				
			|||||||
            thumbnail(nc, hm, &path);
 | 
					            thumbnail(nc, hm, &path);
 | 
				
			||||||
        } else if (has_prefix(&path, &((struct mg_str) MG_MK_STR("/s/")))) {
 | 
					        } else if (has_prefix(&path, &((struct mg_str) MG_MK_STR("/s/")))) {
 | 
				
			||||||
            stats_files(nc, hm, &path);
 | 
					            stats_files(nc, hm, &path);
 | 
				
			||||||
 | 
					        } else if (has_prefix(&path, &((struct mg_str) MG_MK_STR("/tag/")))) {
 | 
				
			||||||
 | 
					            tag(nc, hm, &path);
 | 
				
			||||||
        } else if (has_prefix(&path, &((struct mg_str) MG_MK_STR("/d/")))) {
 | 
					        } else if (has_prefix(&path, &((struct mg_str) MG_MK_STR("/d/")))) {
 | 
				
			||||||
            document_info(nc, hm, &path);
 | 
					            document_info(nc, hm, &path);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
 | 
				
			|||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user