mirror of
https://github.com/simon987/sist2.git
synced 2025-12-12 23:18:51 +00:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3282ab56ba | |||
| 8300838d30 | |||
| c9870a6d3d | |||
| a143cc4fcf | |||
| 9ef1f3781d | |||
| bbee8aa721 | |||
| d22f83c797 | |||
| 50615486a4 | |||
| ca79e4f797 | |||
| 6a9fd08a80 | |||
| cab890dc9b | |||
| b3c4faf2df | |||
| 353937171a |
@@ -1,8 +1,6 @@
|
|||||||
cmake_minimum_required(VERSION 3.7)
|
cmake_minimum_required(VERSION 3.7)
|
||||||
set(CMAKE_C_STANDARD 11)
|
set(CMAKE_C_STANDARD 11)
|
||||||
|
|
||||||
option(CURL_STATIC "Link to curl statically" on)
|
|
||||||
|
|
||||||
project(sist2 C)
|
project(sist2 C)
|
||||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMakeModules")
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMakeModules")
|
||||||
|
|
||||||
@@ -85,7 +83,7 @@ target_link_directories(
|
|||||||
target_compile_options(sist2
|
target_compile_options(sist2
|
||||||
PRIVATE
|
PRIVATE
|
||||||
-Ofast
|
-Ofast
|
||||||
-march=native
|
# -march=native
|
||||||
-fPIC
|
-fPIC
|
||||||
-fno-stack-protector
|
-fno-stack-protector
|
||||||
-fomit-frame-pointer
|
-fomit-frame-pointer
|
||||||
@@ -114,10 +112,6 @@ TARGET_LINK_LIBRARIES(
|
|||||||
|
|
||||||
pthread
|
pthread
|
||||||
|
|
||||||
# curl
|
|
||||||
${PROJECT_SOURCE_DIR}/lib/libcurl.a
|
|
||||||
ssl crypto
|
|
||||||
|
|
||||||
m
|
m
|
||||||
bz2
|
bz2
|
||||||
${PROJECT_SOURCE_DIR}/lib/libmagic.a
|
${PROJECT_SOURCE_DIR}/lib/libmagic.a
|
||||||
@@ -136,6 +130,12 @@ TARGET_LINK_LIBRARIES(
|
|||||||
${PROJECT_SOURCE_DIR}/lib/libtiff.a
|
${PROJECT_SOURCE_DIR}/lib/libtiff.a
|
||||||
${PROJECT_SOURCE_DIR}/lib/libpng16.a
|
${PROJECT_SOURCE_DIR}/lib/libpng16.a
|
||||||
stdc++
|
stdc++
|
||||||
|
|
||||||
|
# curl
|
||||||
|
${PROJECT_SOURCE_DIR}/lib/libcurl.a
|
||||||
|
${PROJECT_SOURCE_DIR}/lib/libcrypto.a
|
||||||
|
${PROJECT_SOURCE_DIR}/lib/libssl.a
|
||||||
|
dl
|
||||||
)
|
)
|
||||||
|
|
||||||
add_custom_target(
|
add_custom_target(
|
||||||
|
|||||||
@@ -16,4 +16,7 @@ RUN mkdir -p /usr/share/tessdata && \
|
|||||||
|
|
||||||
ADD sist2 /root/sist2
|
ADD sist2 /root/sist2
|
||||||
|
|
||||||
|
ENV LANG C.UTF-8
|
||||||
|
ENV LC_ALL C.UTF-8
|
||||||
|
|
||||||
ENTRYPOINT ["/root/sist2"]
|
ENTRYPOINT ["/root/sist2"]
|
||||||
|
|||||||
@@ -8,3 +8,5 @@ echo "Version ${version}"
|
|||||||
docker build . -t simon987/sist2:${version} -t simon987/sist2:latest
|
docker build . -t simon987/sist2:${version} -t simon987/sist2:latest
|
||||||
docker push simon987/sist2:${version}
|
docker push simon987/sist2:${version}
|
||||||
docker push simon987/sist2:latest
|
docker push simon987/sist2:latest
|
||||||
|
|
||||||
|
docker run --rm -it simon987/sist2 -v
|
||||||
@@ -29,7 +29,7 @@ sist2 (Simple incremental search tool)
|
|||||||
1. Have an [Elasticsearch](https://www.elastic.co/downloads/elasticsearch) instance running
|
1. Have an [Elasticsearch](https://www.elastic.co/downloads/elasticsearch) instance running
|
||||||
1.
|
1.
|
||||||
1. Download the [latest sist2 release](https://github.com/simon987/sist2/releases) *
|
1. Download the [latest sist2 release](https://github.com/simon987/sist2/releases) *
|
||||||
1. *(or)* Download an [development snapshot](https://files.simon987.net/artifacts/Sist2/Build/) *(Not recommended!)*
|
1. *(or)* Download a [development snapshot](https://files.simon987.net/artifacts/Sist2/Build/) *(Not recommended!)*
|
||||||
1. *(or)* `docker pull simon987/sist2:latest`
|
1. *(or)* `docker pull simon987/sist2:latest`
|
||||||
|
|
||||||
|
|
||||||
@@ -39,6 +39,9 @@ sist2 (Simple incremental search tool)
|
|||||||
|
|
||||||
## Example usage
|
## Example usage
|
||||||
|
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
See help page `sist2 --help` for more details.
|
See help page `sist2 --help` for more details.
|
||||||
|
|
||||||
**Scan a directory**
|
**Scan a directory**
|
||||||
|
|||||||
Binary file not shown.
@@ -7,7 +7,7 @@
|
|||||||
},
|
},
|
||||||
"suggest-path": {
|
"suggest-path": {
|
||||||
"type": "completion",
|
"type": "completion",
|
||||||
"analyzer": "keyword"
|
"analyzer": "case_insensitive_kw_analyzer"
|
||||||
},
|
},
|
||||||
"mime": {
|
"mime": {
|
||||||
"type": "keyword"
|
"type": "keyword"
|
||||||
|
|||||||
@@ -21,6 +21,12 @@
|
|||||||
"lowercase"
|
"lowercase"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"case_insensitive_kw_analyzer": {
|
||||||
|
"tokenizer": "keyword",
|
||||||
|
"filter": [
|
||||||
|
"lowercase"
|
||||||
|
]
|
||||||
|
},
|
||||||
"my_nGram": {
|
"my_nGram": {
|
||||||
"tokenizer": "my_nGram_tokenizer",
|
"tokenizer": "my_nGram_tokenizer",
|
||||||
"filter": [
|
"filter": [
|
||||||
|
|||||||
@@ -106,12 +106,23 @@ make -j $THREADS
|
|||||||
cd ..
|
cd ..
|
||||||
mv libpng/.libs/libpng16.a .
|
mv libpng/.libs/libpng16.a .
|
||||||
|
|
||||||
|
# openssl...
|
||||||
|
git clone --depth 1 -b OpenSSL_1_1_0-stable https://github.com/openssl/openssl
|
||||||
|
cd openssl
|
||||||
|
./config --prefix=$(pwd)/../ssl
|
||||||
|
make depend
|
||||||
|
make -j $THREADS
|
||||||
|
make install
|
||||||
|
cd ..
|
||||||
|
mv ./openssl/libcrypto.a ./openssl/libssl.a .
|
||||||
|
|
||||||
# curl
|
# curl
|
||||||
wget -nc https://curl.haxx.se/download/curl-7.68.0.tar.gz
|
wget -nc https://curl.haxx.se/download/curl-7.68.0.tar.gz
|
||||||
tar -xzf curl-7.68.0.tar.gz
|
tar -xzf curl-7.68.0.tar.gz
|
||||||
cd curl-7.68.0
|
cd curl-7.68.0
|
||||||
./configure --disable-ldap --disable-ldaps --without-librtmp --disable-rtsp --disable-crypto-auth \
|
./configure --disable-ldap --disable-ldaps --without-librtmp --disable-rtsp --disable-crypto-auth \
|
||||||
--disable-smtp --enable-static --disable-shared
|
--disable-smtp --without-libidn2 --without-nghttp2 --without-brotli --enable-static --disable-shared \
|
||||||
|
--without-libpsl --with-ssl=$(pwd)/../ssl
|
||||||
make -j $THREADS
|
make -j $THREADS
|
||||||
cd ..
|
cd ..
|
||||||
mv curl-7.68.0/lib/.libs/libcurl.a .
|
mv curl-7.68.0/lib/.libs/libcurl.a .
|
||||||
|
|||||||
22
src/cli.c
22
src/cli.c
@@ -15,6 +15,13 @@
|
|||||||
#define DEFAULT_BIND_ADDR "localhost"
|
#define DEFAULT_BIND_ADDR "localhost"
|
||||||
#define DEFAULT_PORT "4090"
|
#define DEFAULT_PORT "4090"
|
||||||
|
|
||||||
|
const char* TESS_DATAPATHS[] = {
|
||||||
|
"/usr/share/tessdata/",
|
||||||
|
"/usr/share/tesseract-ocr/tessdata/",
|
||||||
|
"./",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
scan_args_t *scan_args_create() {
|
scan_args_t *scan_args_create() {
|
||||||
scan_args_t *args = calloc(sizeof(scan_args_t), 1);
|
scan_args_t *args = calloc(sizeof(scan_args_t), 1);
|
||||||
@@ -136,13 +143,23 @@ int scan_args_validate(scan_args_t *args, int argc, const char **argv) {
|
|||||||
|
|
||||||
if (args->tesseract_lang != NULL) {
|
if (args->tesseract_lang != NULL) {
|
||||||
TessBaseAPI *api = TessBaseAPICreate();
|
TessBaseAPI *api = TessBaseAPICreate();
|
||||||
ret = TessBaseAPIInit3(api, TESS_DATAPATH, args->tesseract_lang);
|
|
||||||
|
char filename[128];
|
||||||
|
sprintf(filename, "%s.traineddata", args->tesseract_lang);
|
||||||
|
const char * path = find_file_in_paths(TESS_DATAPATHS, filename);
|
||||||
|
if (path == NULL) {
|
||||||
|
LOG_FATAL("cli.c", "Could not find tesseract language file!");
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = TessBaseAPIInit3(api, path, args->tesseract_lang);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
fprintf(stderr, "Could not initialize tesseract with lang '%s'\n", args->tesseract_lang);
|
fprintf(stderr, "Could not initialize tesseract with lang '%s'\n", args->tesseract_lang);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
TessBaseAPIEnd(api);
|
TessBaseAPIEnd(api);
|
||||||
TessBaseAPIDelete(api);
|
TessBaseAPIDelete(api);
|
||||||
|
|
||||||
|
args->tesseract_path = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_DEBUGF("cli.c", "arg quality=%f", args->quality)
|
LOG_DEBUGF("cli.c", "arg quality=%f", args->quality)
|
||||||
@@ -156,7 +173,8 @@ int scan_args_validate(scan_args_t *args, int argc, const char **argv) {
|
|||||||
LOG_DEBUGF("cli.c", "arg depth=%d", args->depth)
|
LOG_DEBUGF("cli.c", "arg depth=%d", args->depth)
|
||||||
LOG_DEBUGF("cli.c", "arg path=%s", args->path)
|
LOG_DEBUGF("cli.c", "arg path=%s", args->path)
|
||||||
LOG_DEBUGF("cli.c", "arg archive=%s", args->archive)
|
LOG_DEBUGF("cli.c", "arg archive=%s", args->archive)
|
||||||
LOG_DEBUGF("cli.c", "arg ocr=%s", args->tesseract_lang)
|
LOG_DEBUGF("cli.c", "arg tesseract_lang=%s", args->tesseract_lang)
|
||||||
|
LOG_DEBUGF("cli.c", "arg tesseract_path=%s", args->tesseract_path)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ typedef struct scan_args {
|
|||||||
char *archive;
|
char *archive;
|
||||||
archive_mode_t archive_mode;
|
archive_mode_t archive_mode;
|
||||||
char *tesseract_lang;
|
char *tesseract_lang;
|
||||||
|
const char *tesseract_path;
|
||||||
} scan_args_t;
|
} scan_args_t;
|
||||||
|
|
||||||
scan_args_t *scan_args_create();
|
scan_args_t *scan_args_create();
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ struct {
|
|||||||
|
|
||||||
pthread_mutex_t mupdf_mu;
|
pthread_mutex_t mupdf_mu;
|
||||||
char * tesseract_lang;
|
char * tesseract_lang;
|
||||||
|
char * tesseract_path;
|
||||||
} ScanCtx;
|
} ScanCtx;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
|||||||
@@ -274,3 +274,28 @@ cJSON *elastic_get_document(const char *uuid_str) {
|
|||||||
free_response(r);
|
free_response(r);
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *elastic_get_status() {
|
||||||
|
char url[4096];
|
||||||
|
snprintf(url, 4096,
|
||||||
|
"%s/_cluster/state/metadata/sist2?filter_path=metadata.indices.*.state", WebCtx.es_url);
|
||||||
|
|
||||||
|
response_t *r = web_get(url);
|
||||||
|
cJSON *json = NULL;
|
||||||
|
char *status = malloc(128 * sizeof(char));
|
||||||
|
status[0] = '\0';
|
||||||
|
|
||||||
|
if (r->status_code == 200) {
|
||||||
|
json = cJSON_Parse(r->body);
|
||||||
|
const cJSON *metadata = cJSON_GetObjectItem(json, "metadata");
|
||||||
|
if (metadata != NULL) {
|
||||||
|
const cJSON *indices = cJSON_GetObjectItem(metadata, "indices");
|
||||||
|
const cJSON *sist2 = cJSON_GetObjectItem(indices, "sist2");
|
||||||
|
const cJSON *state = cJSON_GetObjectItem(sist2, "state");
|
||||||
|
strcpy(status, state->valuestring);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free_response(r);
|
||||||
|
cJSON_Delete(json);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|||||||
@@ -30,4 +30,6 @@ void elastic_init(int force_reset);
|
|||||||
|
|
||||||
cJSON *elastic_get_document(const char *uuid_str);
|
cJSON *elastic_get_document(const char *uuid_str);
|
||||||
|
|
||||||
|
char *elastic_get_status();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -6,7 +6,7 @@
|
|||||||
#define EPILOG "Made by simon987 <me@simon987.net>. Released under GPL-3.0"
|
#define EPILOG "Made by simon987 <me@simon987.net>. Released under GPL-3.0"
|
||||||
|
|
||||||
|
|
||||||
static const char *const Version = "1.2.3";
|
static const char *const Version = "1.2.4";
|
||||||
static const char *const usage[] = {
|
static const char *const usage[] = {
|
||||||
"sist2 scan [OPTION]... PATH",
|
"sist2 scan [OPTION]... PATH",
|
||||||
"sist2 index [OPTION]... INDEX",
|
"sist2 index [OPTION]... INDEX",
|
||||||
@@ -51,6 +51,7 @@ void sist2_scan(scan_args_t *args) {
|
|||||||
strncpy(ScanCtx.index.desc.root, args->path, sizeof(ScanCtx.index.desc.root));
|
strncpy(ScanCtx.index.desc.root, args->path, sizeof(ScanCtx.index.desc.root));
|
||||||
ScanCtx.index.desc.root_len = (short) strlen(ScanCtx.index.desc.root);
|
ScanCtx.index.desc.root_len = (short) strlen(ScanCtx.index.desc.root);
|
||||||
ScanCtx.tesseract_lang = args->tesseract_lang;
|
ScanCtx.tesseract_lang = args->tesseract_lang;
|
||||||
|
ScanCtx.tesseract_path = args->tesseract_path;
|
||||||
|
|
||||||
init_dir(ScanCtx.index.path);
|
init_dir(ScanCtx.index.path);
|
||||||
|
|
||||||
|
|||||||
@@ -55,7 +55,14 @@ __always_inline
|
|||||||
void read_part(opcContainer *c, dyn_buffer_t *buf, opcPart part, document_t *doc) {
|
void read_part(opcContainer *c, dyn_buffer_t *buf, opcPart part, document_t *doc) {
|
||||||
|
|
||||||
mceTextReader_t reader;
|
mceTextReader_t reader;
|
||||||
int ret = opcXmlReaderOpen(c, &reader, part, NULL, "UTF-8", 0);
|
int options;
|
||||||
|
if (LogCtx.very_verbose) {
|
||||||
|
options = XML_PARSE_NONET;
|
||||||
|
} else {
|
||||||
|
options = XML_PARSE_NOWARNING | XML_PARSE_NOERROR | XML_PARSE_NONET;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret = opcXmlReaderOpen(c, &reader, part, NULL, "UTF-8", options);
|
||||||
|
|
||||||
if (ret != OPC_ERROR_NONE) {
|
if (ret != OPC_ERROR_NONE) {
|
||||||
LOG_ERRORF(doc->filepath, "(doc.c) opcXmlReaderOpen() returned error code %d", ret);
|
LOG_ERRORF(doc->filepath, "(doc.c) opcXmlReaderOpen() returned error code %d", ret);
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ void fill_image(fz_context *ctx, UNUSED(fz_device *dev),
|
|||||||
|
|
||||||
if (pix->h > MIN_OCR_SIZE && img->h > MIN_OCR_SIZE && img->xres != 0) {
|
if (pix->h > MIN_OCR_SIZE && img->h > MIN_OCR_SIZE && img->xres != 0) {
|
||||||
TessBaseAPI *api = TessBaseAPICreate();
|
TessBaseAPI *api = TessBaseAPICreate();
|
||||||
TessBaseAPIInit3(api, TESS_DATAPATH, ScanCtx.tesseract_lang);
|
TessBaseAPIInit3(api, ScanCtx.tesseract_path, ScanCtx.tesseract_lang);
|
||||||
|
|
||||||
TessBaseAPISetImage(api, pix->samples, pix->w, pix->h, pix->n, pix->stride);
|
TessBaseAPISetImage(api, pix->samples, pix->w, pix->h, pix->n, pix->stride);
|
||||||
TessBaseAPISetSourceResolution(api, pix->xres);
|
TessBaseAPISetSourceResolution(api, pix->xres);
|
||||||
@@ -157,8 +157,8 @@ void fill_image(fz_context *ctx, UNUSED(fz_device *dev),
|
|||||||
|
|
||||||
TessBaseAPIEnd(api);
|
TessBaseAPIEnd(api);
|
||||||
TessBaseAPIDelete(api);
|
TessBaseAPIDelete(api);
|
||||||
fz_drop_pixmap(ctx, pix);
|
|
||||||
}
|
}
|
||||||
|
fz_drop_pixmap(ctx, pix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
#define UUID_STR_LEN 37
|
#define UUID_STR_LEN 37
|
||||||
#define UNUSED(x) __attribute__((__unused__)) x
|
#define UNUSED(x) __attribute__((__unused__)) x
|
||||||
#define TESS_DATAPATH "/usr/share/tessdata/"
|
|
||||||
|
|
||||||
#include <glib-2.0/glib.h>
|
#include <glib-2.0/glib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|||||||
26
src/util.c
26
src/util.c
@@ -1,4 +1,5 @@
|
|||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "src/ctx.h"
|
||||||
|
|
||||||
dyn_buffer_t dyn_buffer_create() {
|
dyn_buffer_t dyn_buffer_create() {
|
||||||
dyn_buffer_t buf;
|
dyn_buffer_t buf;
|
||||||
@@ -317,4 +318,29 @@ GHashTable *incremental_get_table() {
|
|||||||
return file_table;
|
return file_table;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *find_file_in_paths(const char *paths[], const char *filename) {
|
||||||
|
|
||||||
|
for (int i = 0; paths[i] != NULL; i++) {
|
||||||
|
|
||||||
|
char *apath = abspath(paths[i]);
|
||||||
|
if (apath == NULL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
char path[PATH_MAX];
|
||||||
|
snprintf(path, sizeof(path), "%s%s", apath, filename);
|
||||||
|
|
||||||
|
LOG_DEBUGF("util.c", "Looking for '%s' in folder '%s'", filename, apath)
|
||||||
|
free(apath);
|
||||||
|
|
||||||
|
struct stat info;
|
||||||
|
int ret = stat(path, &info);
|
||||||
|
if (ret != -1) {
|
||||||
|
return paths[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -74,5 +74,6 @@ int incremental_get(GHashTable *table, unsigned long inode_no);
|
|||||||
|
|
||||||
int incremental_mark_file_for_copy(GHashTable *table, unsigned long inode_no);
|
int incremental_mark_file_for_copy(GHashTable *table, unsigned long inode_no);
|
||||||
|
|
||||||
|
const char *find_file_in_paths(const char **paths, const char *filename);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -431,6 +431,23 @@ int file(UNUSED(void *p), onion_request *req, onion_response *res) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int status(UNUSED(void *p), UNUSED(onion_request *req), onion_response *res) {
|
||||||
|
set_default_headers(res);
|
||||||
|
|
||||||
|
onion_response_set_header(res, "Content-Type", "application/x-empty");
|
||||||
|
|
||||||
|
char *status = elastic_get_status();
|
||||||
|
if (strcmp(status, "open") == 0) {
|
||||||
|
onion_response_set_code(res, 204);
|
||||||
|
} else {
|
||||||
|
onion_response_set_code(res, 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(status);
|
||||||
|
|
||||||
|
return OCS_PROCESSED;
|
||||||
|
}
|
||||||
|
|
||||||
void serve(const char *hostname, const char *port) {
|
void serve(const char *hostname, const char *port) {
|
||||||
onion *o = onion_new(O_POOL);
|
onion *o = onion_new(O_POOL);
|
||||||
onion_set_timeout(o, 3500);
|
onion_set_timeout(o, 3500);
|
||||||
@@ -450,6 +467,7 @@ void serve(const char *hostname, const char *port) {
|
|||||||
|
|
||||||
onion_url_add(urls, "es", search);
|
onion_url_add(urls, "es", search);
|
||||||
onion_url_add(urls, "scroll", scroll);
|
onion_url_add(urls, "scroll", scroll);
|
||||||
|
onion_url_add(urls, "status", status);
|
||||||
onion_url_add(
|
onion_url_add(
|
||||||
urls,
|
urls,
|
||||||
"^t/([a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12})/"
|
"^t/([a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12})/"
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
<nav class="navbar navbar-expand-lg">
|
<nav class="navbar navbar-expand-lg">
|
||||||
<a class="navbar-brand" href="/">sist2</a>
|
<a class="navbar-brand" href="/">sist2</a>
|
||||||
<span class="badge badge-pill version">v1.2.3</span>
|
<span class="badge badge-pill version">v1.2.4</span>
|
||||||
<span class="tagline">Lightning-fast file system indexer and search tool </span>
|
<span class="tagline">Lightning-fast file system indexer and search tool </span>
|
||||||
<a style="margin-left: auto" id="theme" class="btn" title="Toggle theme" href="/">Theme</a>
|
<a style="margin-left: auto" id="theme" class="btn" title="Toggle theme" href="/">Theme</a>
|
||||||
</nav>
|
</nav>
|
||||||
|
|||||||
Reference in New Issue
Block a user