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_pass, ptr + 1, strlen(ptr + 1));
 | 
			
		||||
        strcpy(args->auth_pass, ptr);
 | 
			
		||||
 | 
			
		||||
        if (strlen(args->auth_user) == 0) {
 | 
			
		||||
            fprintf(stderr, "--auth username must be at least one character long");
 | 
			
		||||
 | 
			
		||||
@ -13,6 +13,7 @@
 | 
			
		||||
#include "libscan/text/text.h"
 | 
			
		||||
#include "libscan/mobi/scan_mobi.h"
 | 
			
		||||
#include "libscan/raw/raw.h"
 | 
			
		||||
#include "src/io/store.h"
 | 
			
		||||
 | 
			
		||||
#include <glib.h>
 | 
			
		||||
#include <pcre.h>
 | 
			
		||||
 | 
			
		||||
@ -313,6 +313,11 @@ void finish_indexer(char *script, char *index_id) {
 | 
			
		||||
    r = web_post(url, "");
 | 
			
		||||
    LOG_INFOF("elastic.c", "Merge index <%d>", r->status_code);
 | 
			
		||||
    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) {
 | 
			
		||||
 | 
			
		||||
@ -1,9 +1,10 @@
 | 
			
		||||
#include "store.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->chunk_size = chunk_size;
 | 
			
		||||
    pthread_rwlock_init(&store->lock, NULL);
 | 
			
		||||
 | 
			
		||||
    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)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    store->size = (size_t) 1024 * 1024 * 5;
 | 
			
		||||
    store->size = (size_t) store->chunk_size;
 | 
			
		||||
    ScanCtx.stat_tn_size = 0;
 | 
			
		||||
    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.
 | 
			
		||||
        //  Resize take effect on the next commit.
 | 
			
		||||
        pthread_rwlock_wrlock(&store->lock);
 | 
			
		||||
        store->size += 1024 * 1024 * 50;
 | 
			
		||||
        store->size += store->chunk_size;
 | 
			
		||||
        mdb_env_set_mapsize(store->env, store->size);
 | 
			
		||||
        mdb_txn_begin(store->env, NULL, 0, &txn);
 | 
			
		||||
        put_ret = mdb_put(txn, store->dbi, &mdb_key, &mdb_value, 0);
 | 
			
		||||
 | 
			
		||||
@ -4,14 +4,18 @@
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
#include <lmdb.h>
 | 
			
		||||
 | 
			
		||||
#define STORE_SIZE_TN 1024 * 1024 * 5
 | 
			
		||||
#define STORE_SIZE_TAG 1024 * 16
 | 
			
		||||
 | 
			
		||||
typedef struct store_t {
 | 
			
		||||
    MDB_dbi dbi;
 | 
			
		||||
    MDB_env *env;
 | 
			
		||||
    size_t size;
 | 
			
		||||
    size_t chunk_size;
 | 
			
		||||
    pthread_rwlock_t lock;
 | 
			
		||||
} store_t;
 | 
			
		||||
 | 
			
		||||
store_t *store_create(char *path);
 | 
			
		||||
store_t *store_create(char *path, size_t chunk_size);
 | 
			
		||||
 | 
			
		||||
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];
 | 
			
		||||
    snprintf(store_path, PATH_MAX, "%sthumbs", ScanCtx.index.path);
 | 
			
		||||
    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();
 | 
			
		||||
 | 
			
		||||
@ -223,7 +223,7 @@ void sist2_scan(scan_args_t *args) {
 | 
			
		||||
        char dst_path[PATH_MAX];
 | 
			
		||||
        snprintf(store_path, PATH_MAX, "%sthumbs", args->incremental);
 | 
			
		||||
        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);
 | 
			
		||||
        if (dir == NULL) {
 | 
			
		||||
@ -339,7 +339,11 @@ void sist2_web(web_args_t *args) {
 | 
			
		||||
        char path_tmp[PATH_MAX];
 | 
			
		||||
 | 
			
		||||
        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);
 | 
			
		||||
        WebCtx.indices[i].desc = read_index_descriptor(path_tmp);
 | 
			
		||||
 | 
			
		||||
@ -106,6 +106,21 @@ body {
 | 
			
		||||
    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 {
 | 
			
		||||
    color: #FFFFFF;
 | 
			
		||||
    background-color: #FAAB3C;
 | 
			
		||||
@ -137,9 +152,6 @@ body {
 | 
			
		||||
    overflow: hidden;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.badge {
 | 
			
		||||
    margin-right: 3px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.fit {
 | 
			
		||||
    display: block;
 | 
			
		||||
 | 
			
		||||
@ -153,6 +153,14 @@ function getTags(hit, mimeCategory) {
 | 
			
		||||
    // User tags
 | 
			
		||||
    if (hit["_source"].hasOwnProperty("tag")) {
 | 
			
		||||
        hit["_source"]["tag"].forEach(tag => {
 | 
			
		||||
            tags.push(makeUserTag(tag, hit));
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return tags
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function makeUserTag(tag, hit) {
 | 
			
		||||
    const userTag = document.createElement("span");
 | 
			
		||||
    userTag.setAttribute("class", "badge badge-pill badge-user");
 | 
			
		||||
 | 
			
		||||
@ -164,13 +172,22 @@ function getTags(hit, mimeCategory) {
 | 
			
		||||
        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];
 | 
			
		||||
    userTag.appendChild(document.createTextNode(name));
 | 
			
		||||
            tags.push(userTag);
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return tags
 | 
			
		||||
    return userTag;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function infoButtonCb(hit) {
 | 
			
		||||
@ -338,11 +355,11 @@ function createDocCard(hit) {
 | 
			
		||||
 | 
			
		||||
    docCardBody.appendChild(tagContainer);
 | 
			
		||||
 | 
			
		||||
    attachTagContainerEventListener(tagContainer);
 | 
			
		||||
    attachTagContainerEventListener(tagContainer, hit);
 | 
			
		||||
    return docCard;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function attachTagContainerEventListener(tagContainer) {
 | 
			
		||||
function attachTagContainerEventListener(tagContainer, hit) {
 | 
			
		||||
    const sizeTag = Array.from(tagContainer.children).find(child => child.tagName === "SMALL");
 | 
			
		||||
 | 
			
		||||
    const addTagButton = document.createElement("span");
 | 
			
		||||
@ -354,6 +371,10 @@ function attachTagContainerEventListener(tagContainer) {
 | 
			
		||||
 | 
			
		||||
    addTagButton.addEventListener("click", () => {
 | 
			
		||||
        tagBar.value = "";
 | 
			
		||||
        currentDocToTag = hit;
 | 
			
		||||
        currentTagCallback = tag => {
 | 
			
		||||
            tagContainer.insertBefore(makeUserTag(tag, hit), sizeTag);
 | 
			
		||||
        }
 | 
			
		||||
        $("#tagModal").modal("show");
 | 
			
		||||
        tagBar.focus();
 | 
			
		||||
    });
 | 
			
		||||
@ -431,7 +452,6 @@ function createDocLine(hit) {
 | 
			
		||||
 | 
			
		||||
    if (hit["_source"].hasOwnProperty("parent")) {
 | 
			
		||||
        line.classList.add("sub-document");
 | 
			
		||||
        isSubDocument = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const infoButton = makeInfoButton(hit);
 | 
			
		||||
@ -504,6 +524,8 @@ function createDocLine(hit) {
 | 
			
		||||
    pathLine.appendChild(path);
 | 
			
		||||
    pathLine.appendChild(tagContainer);
 | 
			
		||||
 | 
			
		||||
    attachTagContainerEventListener(tagContainer, hit);
 | 
			
		||||
 | 
			
		||||
    return line;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -7,6 +7,8 @@ let tagTree;
 | 
			
		||||
let searchBar = document.getElementById("searchBar");
 | 
			
		||||
let pathBar = document.getElementById("pathBar");
 | 
			
		||||
let tagBar = document.getElementById("tagBar");
 | 
			
		||||
let currentDocToTag = null;
 | 
			
		||||
let currentTagCallback = null;
 | 
			
		||||
let lastDoc = null;
 | 
			
		||||
let reachedEnd = false;
 | 
			
		||||
let docCount = 0;
 | 
			
		||||
@ -136,8 +138,8 @@ window.onload = () => {
 | 
			
		||||
    [tagBar, document.getElementById("tag-color")].forEach(elem => {
 | 
			
		||||
        elem.addEventListener("keyup", e => {
 | 
			
		||||
            if (e.key === "Enter") {
 | 
			
		||||
                console.log("Add tag");
 | 
			
		||||
                //TODO
 | 
			
		||||
                const tag = tagBar.value + document.getElementById("tag-color").value;
 | 
			
		||||
                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() {
 | 
			
		||||
    searchDebounced();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
$.jsonPost("i").then(resp => {
 | 
			
		||||
$.get("i").then(resp => {
 | 
			
		||||
 | 
			
		||||
    const urlIndices = (new URLSearchParams(location.search)).get("i");
 | 
			
		||||
    resp["indices"].forEach(idx => {
 | 
			
		||||
 | 
			
		||||
@ -19,6 +19,7 @@ typedef struct index_descriptor {
 | 
			
		||||
typedef struct index_t {
 | 
			
		||||
    struct index_descriptor desc;
 | 
			
		||||
    struct store_t *store;
 | 
			
		||||
    struct store_t *tag_store;
 | 
			
		||||
    char path[PATH_MAX];
 | 
			
		||||
} 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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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) {
 | 
			
		||||
    send_response_line(nc, 200, sizeof(search_html), "Content-Type: text/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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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) {
 | 
			
		||||
    struct mg_str scheme;
 | 
			
		||||
    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);
 | 
			
		||||
        } else if (has_prefix(&path, &((struct mg_str) MG_MK_STR("/s/")))) {
 | 
			
		||||
            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/")))) {
 | 
			
		||||
            document_info(nc, hm, &path);
 | 
			
		||||
        } else {
 | 
			
		||||
 | 
			
		||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user