mirror of
https://github.com/simon987/sist2.git
synced 2025-04-19 10:16:42 +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