From 6ade6375dec2b883d3528424bee83ecbd54f0a93 Mon Sep 17 00:00:00 2001 From: ngn Date: Sun, 4 Feb 2024 14:26:25 +0300 Subject: [PATCH] Now links can be saved to a file --- .gitignore | 1 + Dockerfile | 4 +- Makefile | 2 +- README.md | 15 +++++++- src/config.cpp | 4 ++ src/config.hpp | 5 +++ src/link.cpp | 94 ++++++++++++++++++++++++++++++++++++++++++----- src/link.hpp | 9 +++++ src/log.cpp | 26 +++++++++++++ src/log.hpp | 12 ++++++ src/main.cpp | 12 +++++- static/global.css | 4 +- static/index.html | 2 +- 13 files changed, 172 insertions(+), 18 deletions(-) create mode 100644 src/config.cpp create mode 100644 src/config.hpp create mode 100644 src/log.cpp create mode 100644 src/log.hpp diff --git a/.gitignore b/.gitignore index 336f7cb..afecf53 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ kisalt +data/ diff --git a/Dockerfile b/Dockerfile index e9fad15..7f1fa94 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ FROM alpine as build RUN apk update && apk upgrade -RUN apk add --no-cache build-base wget boost-dev openssl-dev +RUN apk add --no-cache build-base wget boost-dev openssl-dev jsoncpp-dev WORKDIR /app COPY src ./src @@ -25,5 +25,5 @@ RUN make && rm -r crow FROM alpine as main COPY --from=build /app / EXPOSE 8080 -RUN apk add --no-cache libstdc++ libgcc libcrypto3 +RUN apk add --no-cache libstdc++ libgcc libcrypto3 jsoncpp ENTRYPOINT ["/kisalt"] diff --git a/Makefile b/Makefile index 62068ad..3844f87 100644 --- a/Makefile +++ b/Makefile @@ -2,4 +2,4 @@ SRCS:=$(wildcard src/*.cpp) CC=g++ kisalt: $(SRCS) - $(CC) -o $@ $^ -lcrypto + $(CC) -o $@ $^ -lcrypto -ljsoncpp diff --git a/README.md b/README.md index 2e121f3..360458d 100644 --- a/README.md +++ b/README.md @@ -9,11 +9,22 @@ kisalt is a simple link shortener written with [Crow](https://github.com/CrowCpp You can easily deploy the app with docker and place it behind a proxy: ```bash docker run -d --restart=unless-stopped \ + -v $PWD/data:/data \ -p 127.0.0.1:8080:8080 \ -e URL=https://k.example.com \ ghcr.io/ngn13/kisalt ``` -Change the `URL` accordingly. +Change the `URL` accordingly. + +To disable the saving the links, you can use the `NOSAVE` option. +A volume is not needed when using this option: +```bash +docker run -d --restart=unless-stopped \ + -p 127.0.0.1:8080:8080 \ + -e URL=https://k.example.com \ + -e NOSAVE=1 \ + ghcr.io/ngn13/kisalt +``` ### Usage You can use the web interface to shorten links, or you can directly use the API: @@ -22,5 +33,5 @@ curl https://k.example.com/add\?url= ``` ### Todo -- Save links to a database +- ~~Save links to a database~~ - Better web UI diff --git a/src/config.cpp b/src/config.cpp new file mode 100644 index 0000000..c6523e2 --- /dev/null +++ b/src/config.cpp @@ -0,0 +1,4 @@ +#include "config.hpp" + +std::string envurl = nullptr==getenv("URL") ? "http://127.0.0.1:8080/" : getenv("URL"); +bool envsave = nullptr==getenv("NOSAVE"); diff --git a/src/config.hpp b/src/config.hpp new file mode 100644 index 0000000..53dd9b7 --- /dev/null +++ b/src/config.hpp @@ -0,0 +1,5 @@ +#pragma once +#include + +extern bool envsave; +extern std::string envurl; diff --git a/src/link.cpp b/src/link.cpp index 4460d41..c4a4c7a 100644 --- a/src/link.cpp +++ b/src/link.cpp @@ -1,18 +1,101 @@ #include +#include +#include "config.hpp" #include #include #include "link.hpp" +#include "log.hpp" #include #include #include +#include #include #include #include std::list links; +std::string find_org(std::string org) { + for(auto const& i : links) { + if(i.org.compare(org)==0) + return i.url; + } + return ""; +} + +std::string find_url(std::string url) { + for(auto const& i : links) { + if(i.url.compare(url)==0) + return i.org; + } + return ""; +} + +bool load_links() { + std::ifstream stream = std::ifstream("data/links.json"); + if(stream.fail()) + return false; + + std::string json, buf = std::string(4096, '\0'); + while (stream.read(& buf[0], 4096)) { + json.append(buf, 0, stream.gcount()); + } + json.append(buf, 0, stream.gcount()); + stream.close(); + + Json::Value root; + JSONCPP_STRING err; + Json::CharReaderBuilder builder; + + const std::unique_ptr reader(builder.newCharReader()); + if (!reader->parse(json.c_str(), json.c_str() + json.length(), + &root, &err)) { + error("Cannot load saved links file"); + return false; + } + + if(root["links"].empty()) + return false; + + for(auto const& l : root["links"]){ + links.push_front({ + .org = l["org"].asString(), + .url = l["url"].asString(), + }); + } + + info("Loaded total of %d saved links", root["links"].size()); + return true; +} + +bool save_links() { + if(!envsave) + return true; + + Json::Value root, link; + for(auto const& i : links) { + link["url"] = i.url; + link["org"] = i.org; + root["links"].append(link); + } + + Json::StreamWriterBuilder builder; + const std::string json = Json::writeString(builder, root); + std::ofstream jsonfile; + + jsonfile.open("data/links.json"); + if(jsonfile.fail()){ + error("Failed to open the links file"); + return false; + } + + jsonfile << json; + jsonfile.close(); + return true; +} + std::string add_url(std::string org) { - std::string found = find_url(org); + std::string found = find_org(org); if(!found.empty()) return found; @@ -37,13 +120,6 @@ std::string add_url(std::string org) { .url = url, }); + save_links(); return url; } - -std::string find_url(std::string url) { - for(auto const& i : links) { - if(i.url.compare(url)==0) - return i.org; - } - return ""; -} diff --git a/src/link.hpp b/src/link.hpp index 3105780..975c3ec 100644 --- a/src/link.hpp +++ b/src/link.hpp @@ -1,8 +1,16 @@ #pragma once #include +#include +#include "config.hpp" +#include +#include +#include "link.hpp" #include #include +#include +#include #include +#include #include extern std::list links; @@ -13,3 +21,4 @@ struct Link { std::string add_url(std::string); std::string find_url(std::string); +bool load_links(); diff --git a/src/log.cpp b/src/log.cpp new file mode 100644 index 0000000..4804e2e --- /dev/null +++ b/src/log.cpp @@ -0,0 +1,26 @@ +#include +#include "log.hpp" +#include +#include + +void error(std::string msg, ...){ + va_list args; + va_start(args, msg); + + printf(BOLD RED "ERROR: " RESET); + vprintf(msg.c_str(), args); + printf(RESET"\n"); + + va_end(args); +} + +void info(std::string msg, ...){ + va_list args; + va_start(args, msg); + + printf(BOLD BLUE "INFO : " RESET); + vprintf(msg.c_str(), args); + printf(RESET"\n"); + + va_end(args); +} diff --git a/src/log.hpp b/src/log.hpp new file mode 100644 index 0000000..b5febd4 --- /dev/null +++ b/src/log.hpp @@ -0,0 +1,12 @@ +#pragma once +#include +#include +#include + +#define RED "\x1b[31m" +#define BOLD "\x1b[1m" +#define BLUE "\x1b[34m" +#define RESET "\x1b[0m" + +void error(std::string, ...); +void info(std::string, ...); diff --git a/src/main.cpp b/src/main.cpp index 315f39c..b34fd12 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,11 +1,11 @@ #include #include +#include "config.hpp" #include "link.hpp" +#include "log.hpp" #include #include -std::string envurl = nullptr==getenv("URL") ? "http://127.0.0.1:8080/" : getenv("URL"); - std::string join_url(std::string url) { if(envurl[envurl.length()-1] == '/') return envurl+url; @@ -15,7 +15,15 @@ std::string join_url(std::string url) { int main(){ crow::SimpleApp app; app.loglevel(crow::LogLevel::Warning); + if(!envsave){ + info("NOSAVE is set, not loading any saved links"); + goto SKIP_LOAD; + } + + if(!load_links()) + info("No saved links, loading an empty list"); +SKIP_LOAD: CROW_ROUTE(app, "/add")([](const crow::request& req, crow::response& res){ char* url = req.url_params.get("url"); diff --git a/static/global.css b/static/global.css index 8ea6e1e..6c67396 100644 --- a/static/global.css +++ b/static/global.css @@ -47,13 +47,15 @@ form input { font-size: 20px; outline: none; border: solid 1px #DFDFDF; + border-radius: 5px; color: white; padding: 10px; } form button { + border-radius: 5px; border: none; - background: #101010; + background: none; padding: 10px; font-size: 20px; outline: none; diff --git a/static/index.html b/static/index.html index 3f0c9ac..58611df 100644 --- a/static/index.html +++ b/static/index.html @@ -17,7 +17,7 @@ GitHub Actions Workflow Status
- +