Use the string_utf8 text objects in the *.or_base64 and *.or_as_binary commands

Names and paths with C0 controls other than tab and line feed are now sent as binary.
This commit is contained in:
Ivan
2026-10-21 15:54:10 +03:00
committed by Jari Sundell
parent 19ef2d1830
commit b46c71b98d
5 changed files with 137 additions and 15 deletions
+6 -6
View File
@@ -668,8 +668,8 @@ initialize_command_download() {
CMD2_DL("d.base_path.base64", [](auto* download, auto) { return retrieve_d_base_path(download).object_base64(); });
CMD2_DL("d.base_path.base64_as_binary", [](auto* download, auto) { return retrieve_d_base_path(download).object_base64_as_binary(); });
CMD2_DL("d.base_path.as_binary", [](auto* download, auto) { return retrieve_d_base_path(download).object_as_binary(); });
CMD2_DL("d.base_path.or_base64", [](auto* download, auto) { return retrieve_d_base_path(download).object_utf8_or_base64(); });
CMD2_DL("d.base_path.or_as_binary", [](auto* download, auto) { return retrieve_d_base_path(download).object_utf8_or_as_binary(); });
CMD2_DL("d.base_path.or_base64", [](auto* download, auto) { return retrieve_d_base_path(download).object_utf8_text_or_base64(); });
CMD2_DL("d.base_path.or_as_binary", [](auto* download, auto) { return retrieve_d_base_path(download).object_utf8_text_or_as_binary(); });
CMD2_DL("d.base_path.realpath.or_empty", [](auto* download, auto) { return resolve_path(retrieve_d_base_path(download).str()); });
CMD2_DL("d.base_path.realpath.or_throw", [](auto* download, auto) { return resolve_path_or_throw(retrieve_d_base_path(download).str()); });
CMD2_DL("d.base_filename", [](auto* download, auto) { return retrieve_d_base_filename(download).str(); });
@@ -677,16 +677,16 @@ initialize_command_download() {
CMD2_DL("d.base_filename.base64", [](auto* download, auto) { return retrieve_d_base_filename(download).object_base64(); });
CMD2_DL("d.base_filename.base64_as_binary", [](auto* download, auto) { return retrieve_d_base_filename(download).object_base64_as_binary(); });
CMD2_DL("d.base_filename.as_binary", [](auto* download, auto) { return retrieve_d_base_filename(download).object_as_binary(); });
CMD2_DL("d.base_filename.or_base64", [](auto* download, auto) { return retrieve_d_base_filename(download).object_utf8_or_base64(); });
CMD2_DL("d.base_filename.or_as_binary", [](auto* download, auto) { return retrieve_d_base_filename(download).object_utf8_or_as_binary(); });
CMD2_DL("d.base_filename.or_base64", [](auto* download, auto) { return retrieve_d_base_filename(download).object_utf8_text_or_base64(); });
CMD2_DL("d.base_filename.or_as_binary", [](auto* download, auto) { return retrieve_d_base_filename(download).object_utf8_text_or_as_binary(); });
CMD2_DL("d.name", [](auto* download, auto) { return download->info()->name().str(); });
CMD2_DL("d.name.hex", [](auto* download, auto) { return download->info()->name().object_hex(); });
CMD2_DL("d.name.base64", [](auto* download, auto) { return download->info()->name().object_base64(); });
CMD2_DL("d.name.base64_as_binary", [](auto* download, auto) { return download->info()->name().object_base64_as_binary(); });
CMD2_DL("d.name.as_binary", [](auto* download, auto) { return download->info()->name().object_as_binary(); });
CMD2_DL("d.name.or_base64", [](auto* download, auto) { return download->info()->name().object_utf8_or_base64(); });
CMD2_DL("d.name.or_as_binary", [](auto* download, auto) { return download->info()->name().object_utf8_or_as_binary(); });
CMD2_DL("d.name.or_base64", [](auto* download, auto) { return download->info()->name().object_utf8_text_or_base64(); });
CMD2_DL("d.name.or_as_binary", [](auto* download, auto) { return download->info()->name().object_utf8_text_or_as_binary(); });
CMD2_DL("d.creation_date", [](auto* download, auto) { return download->info()->creation_date(); });
CMD2_DL("d.load_date", [](auto* download, auto) { return download->info()->load_date(); });
+9 -9
View File
@@ -40,13 +40,13 @@ apply_f_path_components(torrent::File* file, int output_type) {
for (const auto& itr : *file->path()) {
switch (output_type) {
case 0: result.push_back(itr.str()); break;
case 1: result.push_back(itr.object_hex()); break;
case 2: result.push_back(itr.object_base64()); break;
case 3: result.push_back(itr.object_base64_as_binary()); break;
case 4: result.push_back(itr.object_as_binary()); break;
case 5: result.push_back(itr.object_utf8_or_base64()); break;
case 6: result.push_back(itr.object_utf8_or_as_binary()); break;
case 0: result.push_back(itr.str()); break;
case 1: result.push_back(itr.object_hex()); break;
case 2: result.push_back(itr.object_base64()); break;
case 3: result.push_back(itr.object_base64_as_binary()); break;
case 4: result.push_back(itr.object_as_binary()); break;
case 5: result.push_back(itr.object_utf8_text_or_base64()); break;
case 6: result.push_back(itr.object_utf8_text_or_as_binary()); break;
default: throw torrent::input_error("apply_f_path_components(): invalid output type");
};
}
@@ -114,8 +114,8 @@ initialize_command_file() {
CMD2_FILE("f.frozen_path.hex", [](auto* file, auto) { return file->frozen_path().object_hex(); });
CMD2_FILE("f.frozen_path.base64", [](auto* file, auto) { return file->frozen_path().object_base64(); });
CMD2_FILE("f.frozen_path.as_binary", [](auto* file, auto) { return file->frozen_path().object_as_binary(); });
CMD2_FILE("f.frozen_path.or_base64", [](auto* file, auto) { return file->frozen_path().object_utf8_or_base64(); });
CMD2_FILE("f.frozen_path.or_as_binary", [](auto* file, auto) { return file->frozen_path().object_utf8_or_as_binary(); });
CMD2_FILE("f.frozen_path.or_base64", [](auto* file, auto) { return file->frozen_path().object_utf8_text_or_base64(); });
CMD2_FILE("f.frozen_path.or_as_binary", [](auto* file, auto) { return file->frozen_path().object_utf8_text_or_as_binary(); });
CMD2_FILE("f.frozen_path.realpath.or_empty", [](auto* file, auto) { return resolve_path(file->frozen_path().str()); });
CMD2_FILE("f.frozen_path.realpath.or_throw", [](auto* file, auto) { return resolve_path_or_throw(file->frozen_path().str()); });
+2
View File
@@ -59,6 +59,8 @@ rtorrent_Test_Rpc_SOURCES = $(rtorrent_Test_Common) \
rpc/test_rpc_manager.h
rtorrent_Test_Src_SOURCES = $(rtorrent_Test_Common) \
src/test_command_download.cc \
src/test_command_download.h \
src/test_command_dynamic.cc \
src/test_command_dynamic.h \
src/test_command_groups.cc \
+99
View File
@@ -0,0 +1,99 @@
#include "config.h"
#include "test/src/test_command_download.h"
#include <torrent/download.h>
#include <torrent/object.h>
#include <torrent/torrent.h>
#include <torrent/utils/string_manip.h>
#include "control.h"
#include "core/download.h"
#include "globals.h"
#include "rpc/parse_commands.h"
CPPUNIT_TEST_SUITE_REGISTRATION(TestCommandDownload);
void initialize_command_download();
namespace {
// Valid UTF-8 with a carriage return and a C0 control character.
const std::string control_name = "cr\r ctl\x01 \xc3\xa9.bin";
core::Download*
insert_download(core::DownloadList* list, const std::string& name) {
torrent::Object info = torrent::Object::create_map();
info.insert_key("name", name);
info.insert_key("length", int64_t{16});
info.insert_key("piece length", int64_t{262144});
info.insert_key("pieces", std::string(20, char(0)));
auto* object = new torrent::Object(torrent::Object::create_map());
object->insert_key("info", info);
auto* download = new core::Download(torrent::download_add(object, 0));
list->insert(download);
return download;
}
torrent::Object
call_d(const char* key, core::Download* download) {
return rpc::commands.call_command_d(key, download, torrent::Object());
}
}
void
TestCommandDownload::setUp() {
// torrent::download_add() opens a socket through the mocked fd functions.
mock_redirect_defaults();
torrent::initialize_main_thread();
torrent::initialize();
if (control == nullptr)
control = new Control;
if (!rpc::commands.has("d.name"))
initialize_command_download();
}
void
TestCommandDownload::tearDown() {
m_list.clear();
torrent::cleanup();
}
void
TestCommandDownload::test_name_or_base64() {
auto* plain = insert_download(&m_list, "plain.bin");
auto* download = insert_download(&m_list, control_name);
auto plain_result = call_d("d.name.or_base64", plain);
CPPUNIT_ASSERT_EQUAL(std::string("plain.bin"), plain_result.as_string());
CPPUNIT_ASSERT_EQUAL(uint32_t{0}, plain_result.flags());
auto result = call_d("d.name.or_base64", download);
CPPUNIT_ASSERT_EQUAL(torrent::utils::transform_to_base64(control_name), result.as_string());
CPPUNIT_ASSERT_EQUAL(torrent::Object::flag_base64 | torrent::Object::flag_as_binary, result.flags());
CPPUNIT_ASSERT_EQUAL(control_name, call_d("d.name", download).as_string());
CPPUNIT_ASSERT_EQUAL(uint32_t{0}, call_d("d.name", download).flags());
}
void
TestCommandDownload::test_name_or_as_binary() {
auto* plain = insert_download(&m_list, "plain.bin");
auto* download = insert_download(&m_list, control_name);
auto plain_result = call_d("d.name.or_as_binary", plain);
CPPUNIT_ASSERT_EQUAL(std::string("plain.bin"), plain_result.as_string());
CPPUNIT_ASSERT_EQUAL(uint32_t{0}, plain_result.flags());
auto result = call_d("d.name.or_as_binary", download);
CPPUNIT_ASSERT_EQUAL(control_name, result.as_string());
CPPUNIT_ASSERT_EQUAL(torrent::Object::flag_as_binary, result.flags());
}
+21
View File
@@ -0,0 +1,21 @@
#include "core/download_list.h"
#include "test/helpers/test_fixture.h"
class TestCommandDownload : public test_fixture {
CPPUNIT_TEST_SUITE(TestCommandDownload);
CPPUNIT_TEST(test_name_or_base64);
CPPUNIT_TEST(test_name_or_as_binary);
CPPUNIT_TEST_SUITE_END();
public:
void setUp();
void tearDown();
void test_name_or_base64();
void test_name_or_as_binary();
private:
core::DownloadList m_list;
};