mirror of
https://github.com/KingDuckZ/kamokan.git
synced 2024-11-23 00:33:44 +00:00
Use lua script to retrieve a pastie from its token.
The self-destruct logic is in lua now.
This commit is contained in:
parent
48ccb8eec5
commit
b421299884
7 changed files with 128 additions and 14 deletions
|
@ -1 +1 @@
|
|||
Subproject commit 0aee978661e0f31722a28ff039490a98c829644b
|
||||
Subproject commit d2fff64381402a4ada9bbe3673603bbc81b2d0f6
|
|
@ -22,6 +22,7 @@ add_library(${PROJECT_NAME} STATIC
|
|||
string_conv.cpp
|
||||
edit_response.cpp
|
||||
general_pastie_response.cpp
|
||||
${CMAKE_CURRENT_BINARY_DIR}/include/lua_scripts_for_redis.cpp
|
||||
)
|
||||
|
||||
target_include_directories(${PROJECT_NAME}
|
||||
|
@ -62,3 +63,10 @@ configure_file(
|
|||
"${CMAKE_CURRENT_SOURCE_DIR}/kamokan_config.h.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/include/kamokan_config.h"
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT include/lua_scripts_for_redis.cpp
|
||||
COMMAND ${CMAKE_COMMAND} -DSOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}" -P ${CMAKE_CURRENT_SOURCE_DIR}/lua_to_cpp.cmake
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/retrieve_pastie.lua ${CMAKE_CURRENT_SOURCE_DIR}/save_pastie.lua
|
||||
COMMENT "Embedding save/load lua scripts into the c++ code"
|
||||
)
|
||||
|
|
27
src/kamokan_impl/lua_scripts_for_redis.hpp
Normal file
27
src/kamokan_impl/lua_scripts_for_redis.hpp
Normal file
|
@ -0,0 +1,27 @@
|
|||
/* Copyright 2017, Michele Santullo
|
||||
* This file is part of "kamokan".
|
||||
*
|
||||
* "kamokan" is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* "kamokan" is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with "kamokan". If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace kamokan {
|
||||
extern const char g_save_script[];
|
||||
extern const char g_load_script[];
|
||||
extern const std::size_t g_save_script_size;
|
||||
extern const std::size_t g_load_script_size;
|
||||
} //namespace kamokan
|
31
src/kamokan_impl/lua_to_cpp.cmake
Normal file
31
src/kamokan_impl/lua_to_cpp.cmake
Normal file
|
@ -0,0 +1,31 @@
|
|||
file(READ ${SOURCE_DIR}/retrieve_pastie.lua retrieve_pastie)
|
||||
file(READ ${SOURCE_DIR}/save_pastie.lua save_pastie)
|
||||
string(REGEX REPLACE "[ \t]*=[ \t]*" "=" retrieve_pastie "${retrieve_pastie}")
|
||||
string(REGEX REPLACE "[ \t]*=[ \t]*" "=" save_pastie "${save_pastie}")
|
||||
string(REGEX REPLACE ",[ \t]*" "," retrieve_pastie "${retrieve_pastie}")
|
||||
string(REGEX REPLACE ",[ \t]*" "," save_pastie "${save_pastie}")
|
||||
string(REGEX REPLACE "(^|\n)[ \t]+" "\\1" retrieve_pastie "${retrieve_pastie}")
|
||||
string(REGEX REPLACE "(^|\n)[ \t]+" "\\1" save_pastie "${save_pastie}")
|
||||
string(LENGTH "${retrieve_pastie}" retrieve_pastie_length)
|
||||
string(LENGTH "${save_pastie}" save_pastie_length)
|
||||
|
||||
set(lua_scripts_for_redis_content "//File autogenerated by cmake, changes will be lost
|
||||
#include <cstddef>
|
||||
namespace kamokan {
|
||||
extern const char g_save_script[] = R\"lua(${save_pastie})lua\";
|
||||
extern const char g_load_script[] = R\"lua(${retrieve_pastie})lua\";
|
||||
extern const std::size_t g_save_script_size = ${save_pastie_length} + 1;
|
||||
extern const std::size_t g_load_script_size = ${retrieve_pastie_length} + 1;
|
||||
} //namespace kamokan
|
||||
")
|
||||
|
||||
file(WRITE
|
||||
include/lua_scripts_for_redis.cpp
|
||||
"${lua_scripts_for_redis_content}"
|
||||
)
|
||||
|
||||
unset(lua_scripts_for_redis_content)
|
||||
unset(save_pastie_length)
|
||||
unset(retrieve_pastie_length)
|
||||
unset(save_pastie)
|
||||
unset(retrieve_pastie)
|
10
src/kamokan_impl/retrieve_pastie.lua
Normal file
10
src/kamokan_impl/retrieve_pastie.lua
Normal file
|
@ -0,0 +1,10 @@
|
|||
local token = KEYS[1]
|
||||
local result = redis.call("HMGET", token, "pastie", "selfdes", "lang")
|
||||
local selfdes = 0
|
||||
local deleted = 0
|
||||
if result[2] == 1 then
|
||||
deleted = redis.call("DEL", token)
|
||||
selfdes = 1
|
||||
end
|
||||
|
||||
return {result[1], selfdes, deleted, result[3]}
|
29
src/kamokan_impl/save_pastie.lua
Normal file
29
src/kamokan_impl/save_pastie.lua
Normal file
|
@ -0,0 +1,29 @@
|
|||
function num_to_value (num)
|
||||
local retval = ""
|
||||
local running = true
|
||||
|
||||
while (running)
|
||||
do
|
||||
local remainder = num % 26
|
||||
retval = string.char(97 + remainder) .. retval
|
||||
num = math.floor(num / 26)
|
||||
running = (num ~= 0)
|
||||
end
|
||||
return retval
|
||||
end
|
||||
|
||||
paste_counter = KEYS[1]
|
||||
next_id = redis.call("INCR", paste_counter) - 1
|
||||
token = num_to_token(next_id)
|
||||
text = ARGV[1]
|
||||
ttl = ARGV[2]
|
||||
lang = ARGV[3]
|
||||
selfdestruct = ARGV[4]
|
||||
redis.call("HMSET", token,
|
||||
"pastie", text,
|
||||
"max_ttl", ttl,
|
||||
"lang", lang,
|
||||
"selfdes", selfdestruct
|
||||
)
|
||||
|
||||
return token
|
|
@ -23,6 +23,7 @@
|
|||
#include "spdlog.hpp"
|
||||
#include "truncated_string.hpp"
|
||||
#include "string_conv.hpp"
|
||||
#include "lua_scripts_for_redis.hpp"
|
||||
#include <cassert>
|
||||
#include <ciso646>
|
||||
#include <string>
|
||||
|
@ -129,6 +130,7 @@ namespace kamokan {
|
|||
const std::string& parRemoteIP
|
||||
) const {
|
||||
using tawashi::ErrorReasons;
|
||||
using redis::RedisInt;
|
||||
|
||||
if (not is_connected())
|
||||
return make_submission_result(ErrorReasons::RedisDisconnected);
|
||||
|
@ -156,7 +158,7 @@ namespace kamokan {
|
|||
"pastie", parText,
|
||||
"max_ttl", dhandy::lexical_cast<std::string>(parExpiry),
|
||||
"lang", parLang,
|
||||
"selfdes", (parSelfDestruct ? "1" : "0"))
|
||||
"selfdes", static_cast<RedisInt>(parSelfDestruct ? 1 : 0))
|
||||
) {
|
||||
redis.set(parRemoteIP, "");
|
||||
redis.expire(parRemoteIP, m_settings->as<uint32_t>("resubmit_wait"));
|
||||
|
@ -168,7 +170,6 @@ namespace kamokan {
|
|||
}
|
||||
|
||||
auto Storage::retrieve_pastie (const boost::string_view& parToken, uint32_t parMaxTokenLen) const -> RetrievedPastie {
|
||||
using opt_string = redis::IncRedis::opt_string;
|
||||
using opt_string_list = redis::IncRedis::opt_string_list;
|
||||
|
||||
RetrievedPastie retval;
|
||||
|
@ -176,18 +177,26 @@ namespace kamokan {
|
|||
if (not retval.valid_token)
|
||||
return retval;
|
||||
|
||||
opt_string_list pastie_reply = m_redis->hmget(parToken, "pastie", "selfdes", "lang");
|
||||
retval.pastie = (pastie_reply and not pastie_reply->empty() ? (*pastie_reply)[0] : opt_string());
|
||||
opt_string selfdes = (pastie_reply and pastie_reply->size() > 1 ? (*pastie_reply)[1] : opt_string());
|
||||
retval.lang = (pastie_reply and pastie_reply->size() > 2 ? (*pastie_reply)[2] : opt_string());
|
||||
|
||||
if (selfdes and string_conv<bool>(*selfdes)) {
|
||||
const bool deleted = m_redis->del(parToken);
|
||||
retval.self_destructed = deleted;
|
||||
if (not deleted) {
|
||||
auto statuslog = spdlog::get("statuslog");
|
||||
statuslog->error("Pastie \"{}\" was marked as self-destructing but DEL failed to delete it", parToken);
|
||||
}
|
||||
redis::Script retrieve = m_redis->command().make_script(boost::string_view(g_load_script, g_load_script_size - 1));
|
||||
auto batch = m_redis->command().make_batch();
|
||||
retrieve.run(batch, std::make_tuple(parToken), std::make_tuple());
|
||||
auto raw_replies = batch.replies();
|
||||
if (raw_replies.empty())
|
||||
return retval;
|
||||
|
||||
assert(not raw_replies.front().is_error());
|
||||
auto pastie_reply = get_array(raw_replies.front());
|
||||
|
||||
retval.pastie = get_string(pastie_reply[0]);
|
||||
const redis::RedisInt selfdes = get_integer(pastie_reply[1]);
|
||||
const redis::RedisInt deleted = get_integer(pastie_reply[2]);
|
||||
retval.lang = get_string(pastie_reply[3]);
|
||||
retval.self_destructed = selfdes and deleted;
|
||||
|
||||
if (selfdes and not deleted) {
|
||||
auto statuslog = spdlog::get("statuslog");
|
||||
statuslog->error("Pastie \"{}\" was marked as self-destructing but DEL failed to delete it", parToken);
|
||||
}
|
||||
|
||||
#if defined(SPDLOG_DEBUG_ON)
|
||||
|
|
Loading…
Reference in a new issue