mirror of
https://github.com/transmission/transmission
synced 2025-02-21 21:57:01 +00:00
refactor: remove tr_loadFile() (#3540)
* refactor: use the std::vector variant of tr_loadFile() in rpc-server.cc * refactor: use the std::vector variant of tr_loadFile() in rename-test.cc * refactor: remove the unused raw ptr variant of tr_loadFile()
This commit is contained in:
parent
e491f9d215
commit
e0ca366b2d
4 changed files with 41 additions and 137 deletions
|
@ -163,44 +163,46 @@ static char const* mimetype_guess(std::string_view path)
|
|||
return "application/octet-stream";
|
||||
}
|
||||
|
||||
static void add_response(struct evhttp_request* req, tr_rpc_server* server, struct evbuffer* out, struct evbuffer* content)
|
||||
static evbuffer* make_response(struct evhttp_request* req, tr_rpc_server* server, std::string_view content)
|
||||
{
|
||||
auto* const out = evbuffer_new();
|
||||
|
||||
char const* key = "Accept-Encoding";
|
||||
char const* encoding = evhttp_find_header(req->input_headers, key);
|
||||
bool const do_compress = encoding != nullptr && strstr(encoding, "gzip") != nullptr;
|
||||
|
||||
if (!do_compress)
|
||||
{
|
||||
evbuffer_add_buffer(out, content);
|
||||
evbuffer_add(out, std::data(content), std::size(content));
|
||||
}
|
||||
else
|
||||
{
|
||||
auto const* const content_ptr = evbuffer_pullup(content, -1);
|
||||
size_t const content_len = evbuffer_get_length(content);
|
||||
auto const max_compressed_len = libdeflate_deflate_compress_bound(server->compressor.get(), content_len);
|
||||
auto const max_compressed_len = libdeflate_deflate_compress_bound(server->compressor.get(), std::size(content));
|
||||
|
||||
struct evbuffer_iovec iovec[1];
|
||||
evbuffer_reserve_space(out, std::max(content_len, max_compressed_len), iovec, 1);
|
||||
evbuffer_reserve_space(out, std::max(std::size(content), max_compressed_len), iovec, 1);
|
||||
|
||||
auto const compressed_len = libdeflate_gzip_compress(
|
||||
server->compressor.get(),
|
||||
content_ptr,
|
||||
content_len,
|
||||
std::data(content),
|
||||
std::size(content),
|
||||
iovec[0].iov_base,
|
||||
iovec[0].iov_len);
|
||||
if (0 < compressed_len && compressed_len < content_len)
|
||||
if (0 < compressed_len && compressed_len < std::size(content))
|
||||
{
|
||||
iovec[0].iov_len = compressed_len;
|
||||
evhttp_add_header(req->output_headers, "Content-Encoding", "gzip");
|
||||
}
|
||||
else
|
||||
{
|
||||
std::copy_n(content_ptr, content_len, static_cast<char*>(iovec[0].iov_base));
|
||||
iovec[0].iov_len = content_len;
|
||||
std::copy(std::begin(content), std::end(content), static_cast<char*>(iovec[0].iov_base));
|
||||
iovec[0].iov_len = std::size(content);
|
||||
}
|
||||
|
||||
evbuffer_commit_space(out, iovec, 1);
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
static void add_time_header(struct evkeyvalq* headers, char const* key, time_t now)
|
||||
|
@ -209,48 +211,32 @@ static void add_time_header(struct evkeyvalq* headers, char const* key, time_t n
|
|||
evhttp_add_header(headers, key, fmt::format("{:%a %b %d %T %Y%n}", fmt::gmtime(now)).c_str());
|
||||
}
|
||||
|
||||
static void evbuffer_ref_cleanup_tr_free(void const* /*data*/, size_t /*datalen*/, void* extra)
|
||||
{
|
||||
tr_free(extra);
|
||||
}
|
||||
|
||||
static void serve_file(struct evhttp_request* req, tr_rpc_server* server, std::string_view filename)
|
||||
{
|
||||
if (req->type != EVHTTP_REQ_GET)
|
||||
{
|
||||
evhttp_add_header(req->output_headers, "Allow", "GET");
|
||||
send_simple_response(req, 405, nullptr);
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
||||
auto content = std::vector<char>{};
|
||||
tr_error* error = nullptr;
|
||||
if (!tr_loadFile(filename, content, &error))
|
||||
{
|
||||
auto file_len = size_t{};
|
||||
tr_error* error = nullptr;
|
||||
void* const file = tr_loadFile(filename, &file_len, &error);
|
||||
|
||||
if (file == nullptr)
|
||||
{
|
||||
auto const tmp = fmt::format(FMT_STRING("{:s} ({:s})"), filename, error->message);
|
||||
send_simple_response(req, HTTP_NOTFOUND, tmp.c_str());
|
||||
tr_error_free(error);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto const now = tr_time();
|
||||
|
||||
auto* const content = evbuffer_new();
|
||||
evbuffer_add_reference(content, file, file_len, evbuffer_ref_cleanup_tr_free, file);
|
||||
|
||||
auto* const out = evbuffer_new();
|
||||
evhttp_add_header(req->output_headers, "Content-Type", mimetype_guess(filename));
|
||||
add_time_header(req->output_headers, "Date", now);
|
||||
add_time_header(req->output_headers, "Expires", now + (24 * 60 * 60));
|
||||
add_response(req, server, out, content);
|
||||
evhttp_send_reply(req, HTTP_OK, "OK", out);
|
||||
|
||||
evbuffer_free(out);
|
||||
evbuffer_free(content);
|
||||
}
|
||||
send_simple_response(req, HTTP_NOTFOUND, fmt::format("{} ({})", filename, error->message).c_str());
|
||||
tr_error_free(error);
|
||||
return;
|
||||
}
|
||||
|
||||
auto const now = tr_time();
|
||||
add_time_header(req->output_headers, "Date", now);
|
||||
add_time_header(req->output_headers, "Expires", now + (24 * 60 * 60));
|
||||
evhttp_add_header(req->output_headers, "Content-Type", mimetype_guess(filename));
|
||||
|
||||
auto* const response = make_response(req, server, std::string_view{ std::data(content), std::size(content) });
|
||||
evhttp_send_reply(req, HTTP_OK, "OK", response);
|
||||
evbuffer_free(response);
|
||||
}
|
||||
|
||||
static void handle_web_client(struct evhttp_request* req, tr_rpc_server* server)
|
||||
|
@ -298,18 +284,15 @@ struct rpc_response_data
|
|||
tr_rpc_server* server;
|
||||
};
|
||||
|
||||
static void rpc_response_func(tr_session* /*session*/, tr_variant* response, void* user_data)
|
||||
static void rpc_response_func(tr_session* /*session*/, tr_variant* content, void* user_data)
|
||||
{
|
||||
auto* data = static_cast<struct rpc_response_data*>(user_data);
|
||||
struct evbuffer* response_buf = tr_variantToBuf(response, TR_VARIANT_FMT_JSON_LEAN);
|
||||
struct evbuffer* buf = evbuffer_new();
|
||||
|
||||
add_response(data->req, data->server, buf, response_buf);
|
||||
auto* const response = make_response(data->req, data->server, tr_variantToStr(content, TR_VARIANT_FMT_JSON_LEAN));
|
||||
evhttp_add_header(data->req->output_headers, "Content-Type", "application/json; charset=UTF-8");
|
||||
evhttp_send_reply(data->req, HTTP_OK, "OK", buf);
|
||||
evhttp_send_reply(data->req, HTTP_OK, "OK", response);
|
||||
evbuffer_free(response);
|
||||
|
||||
evbuffer_free(buf);
|
||||
evbuffer_free(response_buf);
|
||||
tr_free(data);
|
||||
}
|
||||
|
||||
|
|
|
@ -142,70 +142,6 @@ void tr_timerAddMsec(struct event& timer, int msec)
|
|||
***
|
||||
**/
|
||||
|
||||
uint8_t* tr_loadFile(std::string_view path_in, size_t* size, tr_error** error)
|
||||
{
|
||||
auto const path = tr_pathbuf{ path_in };
|
||||
|
||||
/* try to stat the file */
|
||||
auto info = tr_sys_path_info{};
|
||||
tr_error* my_error = nullptr;
|
||||
if (!tr_sys_path_get_info(path.c_str(), 0, &info, &my_error))
|
||||
{
|
||||
tr_logAddError(fmt::format(
|
||||
_("Couldn't read '{path}': {error} ({error_code})"),
|
||||
fmt::arg("path", path),
|
||||
fmt::arg("error", my_error->message),
|
||||
fmt::arg("error_code", my_error->code)));
|
||||
tr_error_propagate(error, &my_error);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (info.type != TR_SYS_PATH_IS_FILE)
|
||||
{
|
||||
tr_logAddError(fmt::format(_("Couldn't read '{path}': Not a regular file"), fmt::arg("path", path)));
|
||||
tr_error_set(error, TR_ERROR_EISDIR, "Not a regular file"sv);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* file size should be able to fit into size_t */
|
||||
if constexpr (sizeof(info.size) > sizeof(*size))
|
||||
{
|
||||
TR_ASSERT(info.size <= SIZE_MAX);
|
||||
}
|
||||
|
||||
/* Load the torrent file into our buffer */
|
||||
auto const fd = tr_sys_file_open(path.c_str(), TR_SYS_FILE_READ | TR_SYS_FILE_SEQUENTIAL, 0, &my_error);
|
||||
if (fd == TR_BAD_SYS_FILE)
|
||||
{
|
||||
tr_logAddError(fmt::format(
|
||||
_("Couldn't read '{path}': {error} ({error_code})"),
|
||||
fmt::arg("path", path),
|
||||
fmt::arg("error", my_error->message),
|
||||
fmt::arg("error_code", my_error->code)));
|
||||
tr_error_propagate(error, &my_error);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto* buf = static_cast<uint8_t*>(tr_malloc(info.size + 1));
|
||||
if (!tr_sys_file_read(fd, buf, info.size, nullptr, &my_error))
|
||||
{
|
||||
tr_logAddError(fmt::format(
|
||||
_("Couldn't read '{path}': {error} ({error_code})"),
|
||||
fmt::arg("path", path),
|
||||
fmt::arg("error", my_error->message),
|
||||
fmt::arg("error_code", my_error->code)));
|
||||
tr_sys_file_close(fd);
|
||||
tr_free(buf);
|
||||
tr_error_propagate(error, &my_error);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
tr_sys_file_close(fd);
|
||||
buf[info.size] = '\0';
|
||||
*size = info.size;
|
||||
return buf;
|
||||
}
|
||||
|
||||
bool tr_loadFile(std::string_view path_in, std::vector<char>& setme, tr_error** error)
|
||||
{
|
||||
auto const path = tr_pathbuf{ path_in };
|
||||
|
|
|
@ -72,12 +72,6 @@ struct tr_error;
|
|||
*/
|
||||
[[nodiscard]] bool tr_wildmat(std::string_view text, std::string_view pattern);
|
||||
|
||||
/**
|
||||
* @brief Loads a file and returns its contents.
|
||||
* On failure, NULL is returned and errno is set.
|
||||
*/
|
||||
uint8_t* tr_loadFile(std::string_view filename, size_t* size, struct tr_error** error) TR_GNUC_MALLOC;
|
||||
|
||||
bool tr_loadFile(std::string_view filename, std::vector<char>& contents, tr_error** error = nullptr);
|
||||
|
||||
bool tr_saveFile(std::string_view filename, std::string_view contents, tr_error** error = nullptr);
|
||||
|
|
|
@ -87,26 +87,17 @@ protected:
|
|||
return tor;
|
||||
}
|
||||
|
||||
static bool testFileExistsAndConsistsOfThisString(tr_torrent const* tor, tr_file_index_t file_index, std::string const& str)
|
||||
static bool testFileExistsAndConsistsOfThisString(tr_torrent const* tor, tr_file_index_t file_index, std::string_view str)
|
||||
{
|
||||
auto const str_len = str.size();
|
||||
auto success = false;
|
||||
|
||||
auto* path = tr_torrentFindFile(tor, file_index);
|
||||
if (path != nullptr)
|
||||
if (auto const found = tor->findFile(file_index); found)
|
||||
{
|
||||
EXPECT_TRUE(tr_sys_path_exists(path));
|
||||
|
||||
size_t contents_len;
|
||||
uint8_t* contents = tr_loadFile(path, &contents_len, nullptr);
|
||||
|
||||
success = contents != nullptr && str_len == contents_len && memcmp(contents, str.data(), contents_len) == 0;
|
||||
|
||||
tr_free(contents);
|
||||
tr_free(path);
|
||||
EXPECT_TRUE(tr_sys_path_exists(found->filename()));
|
||||
auto contents = std::vector<char>{};
|
||||
return tr_loadFile(found->filename(), contents) &&
|
||||
std::string_view{ std::data(contents), std::size(contents) } == str;
|
||||
}
|
||||
|
||||
return success;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void expectHaveNone(tr_torrent* tor, uint64_t total_size)
|
||||
|
|
Loading…
Reference in a new issue