1
0
Fork 0
mirror of https://github.com/transmission/transmission synced 2024-12-31 20:16:57 +00:00

feat: support webseeds in transmission-create (#2611)

This commit is contained in:
Charles Kerr 2022-02-12 12:50:47 -06:00 committed by GitHub
parent e14c7f38e5
commit 2410ad2fa6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 121 additions and 11 deletions

View file

@ -284,7 +284,7 @@ void MakeDialog::Impl::onResponse(int response)
else
{
announce_urls.push_front(str);
trackers.push_back(tr_tracker_info{ tier, announce_urls.front().data(), nullptr, 0 });
trackers.push_back(tr_tracker_info{ tier, announce_urls.front().data() });
}
}
@ -295,6 +295,8 @@ void MakeDialog::Impl::onResponse(int response)
target.c_str(),
trackers.data(),
trackers.size(),
nullptr,
0,
useComment ? comment.c_str() : nullptr,
isPrivate,
useSource ? source.c_str() : nullptr);

View file

@ -234,6 +234,11 @@ void tr_metaInfoBuilderFree(tr_metainfo_builder* builder)
tr_free(builder->trackers[i].announce);
}
for (int i = 0; i < builder->webseedCount; ++i)
{
tr_free(builder->webseeds[i]);
}
tr_free(builder->trackers);
tr_free(builder->outputFile);
tr_free(builder);
@ -420,7 +425,6 @@ static void tr_realMakeMetaInfo(tr_metainfo_builder* builder)
{
tr_variant top;
/* allow an empty set, but if URLs *are* listed, verify them. #814, #971 */
for (int i = 0; i < builder->trackerCount && builder->result == TrMakemetaResult::OK; ++i)
{
if (!tr_urlIsValidTracker(builder->trackers[i].announce))
@ -430,6 +434,15 @@ static void tr_realMakeMetaInfo(tr_metainfo_builder* builder)
}
}
for (int i = 0; i < builder->webseedCount && builder->result == TrMakemetaResult::OK; ++i)
{
if (!tr_urlIsValid(builder->webseeds[i]))
{
tr_strlcpy(builder->errfile, builder->webseeds[i], sizeof(builder->errfile));
builder->result = TrMakemetaResult::ERR_URL;
}
}
tr_variantInitDict(&top, 6);
if (builder->fileCount == 0 || builder->totalSize == 0 || builder->pieceSize == 0 || builder->pieceCount == 0)
@ -464,6 +477,16 @@ static void tr_realMakeMetaInfo(tr_metainfo_builder* builder)
tr_variantDictAddStr(&top, TR_KEY_announce, builder->trackers[0].announce);
}
if (builder->result == TrMakemetaResult::OK && builder->webseedCount > 0)
{
tr_variant* url_list = tr_variantDictAddList(&top, TR_KEY_url_list, builder->webseedCount);
for (int i = 0; i < builder->webseedCount; ++i)
{
tr_variantListAddStr(url_list, builder->webseeds[i]);
}
}
if (builder->result == TrMakemetaResult::OK && !builder->abortFlag)
{
if (!tr_str_is_empty(builder->comment))
@ -543,6 +566,8 @@ void tr_makeMetaInfo(
char const* outputFile,
tr_tracker_info const* trackers,
int trackerCount,
char const** webseeds,
int webseedCount,
char const* comment,
bool isPrivate,
char const* source)
@ -572,6 +597,13 @@ void tr_makeMetaInfo(
builder->trackers[i].announce = tr_strdup(trackers[i].announce);
}
builder->webseedCount = webseedCount;
builder->webseeds = tr_new0(char*, webseedCount);
for (int i = 0; i < webseedCount; ++i)
{
builder->webseeds[i] = tr_strdup(webseeds[i]);
}
builder->comment = tr_strdup(comment);
builder->isPrivate = isPrivate;
builder->source = tr_strdup(source);

View file

@ -26,8 +26,6 @@ struct tr_tracker_info
{
int tier;
char* announce;
char* scrape;
uint32_t id; /* unique identifier used to match to a tr_tracker_stat */
};
struct tr_metainfo_builder
@ -53,6 +51,10 @@ struct tr_metainfo_builder
tr_tracker_info* trackers;
int trackerCount;
char** webseeds;
int webseedCount;
char* comment;
char* outputFile;
bool isPrivate;
@ -116,9 +118,11 @@ void tr_metaInfoBuilderFree(tr_metainfo_builder*);
*/
void tr_makeMetaInfo(
tr_metainfo_builder* builder,
char const* outputFile,
char const* output_file,
tr_tracker_info const* trackers,
int trackerCount,
int n_trackers,
char const** webseeds,
int n_webseeds,
char const* comment,
bool isPrivate,
bool is_private,
char const* source);

View file

@ -569,6 +569,8 @@ NSMutableSet* creatorWindowControllerSet = nil;
fLocation.path.UTF8String,
trackerInfo,
fTrackers.count,
nullptr,
0,
fCommentView.string.UTF8String,
fPrivateCheck.state == NSControlStateValueOn,
fSource.stringValue.UTF8String);

View file

@ -189,6 +189,8 @@ void MakeDialog::makeTorrent()
target.toUtf8().constData(),
trackers.empty() ? nullptr : trackers.data(),
trackers.size(),
nullptr,
0,
comment.isEmpty() ? nullptr : comment.toUtf8().constData(),
ui_.privateCheck->isChecked(),
source.isNull() ? nullptr : source.toUtf8().constData());

View file

@ -34,6 +34,8 @@ protected:
tr_torrent_metainfo& metainfo,
tr_tracker_info const* trackers,
int const trackerCount,
char const** webseeds,
int const webseedCount,
void const* payload,
size_t const payloadSize,
char const* comment,
@ -56,7 +58,16 @@ protected:
// have tr_makeMetaInfo() build the .torrent file
auto const torrent_file = tr_strvJoin(input_file, ".torrent");
tr_makeMetaInfo(builder, torrent_file.c_str(), trackers, trackerCount, comment, isPrivate, std::string(source).c_str());
tr_makeMetaInfo(
builder,
torrent_file.c_str(),
trackers,
trackerCount,
webseeds,
webseedCount,
comment,
isPrivate,
std::string(source).c_str());
EXPECT_EQ(isPrivate, builder->isPrivate);
EXPECT_EQ(torrent_file, builder->outputFile);
EXPECT_STREQ(comment, builder->comment);
@ -78,6 +89,7 @@ protected:
EXPECT_EQ(comment, metainfo.comment());
EXPECT_EQ(isPrivate, metainfo.isPrivate());
EXPECT_EQ(size_t(trackerCount), std::size(metainfo.announceList()));
EXPECT_EQ(size_t(webseedCount), metainfo.webseedCount());
EXPECT_EQ(tr_file_index_t{ 1 }, metainfo.fileCount());
EXPECT_EQ(makeString(tr_sys_path_basename(input_file.data(), nullptr)), metainfo.fileSubpath(0));
EXPECT_EQ(payloadSize, metainfo.fileSize(0));
@ -89,6 +101,8 @@ protected:
void testSingleDirectoryImpl(
tr_tracker_info const* trackers,
int const tracker_count,
char const** webseeds,
int const webseed_count,
void const** payloads,
size_t const* payload_sizes,
size_t const payload_count,
@ -135,7 +149,16 @@ protected:
// build the .torrent file
auto torrent_file = tr_strvJoin(top, ".torrent"sv);
tr_makeMetaInfo(builder, torrent_file.c_str(), trackers, tracker_count, comment, is_private, source);
tr_makeMetaInfo(
builder,
torrent_file.c_str(),
trackers,
tracker_count,
webseeds,
webseed_count,
comment,
is_private,
source);
EXPECT_EQ(is_private, builder->isPrivate);
EXPECT_EQ(torrent_file, builder->outputFile);
EXPECT_STREQ(comment, builder->comment);
@ -170,6 +193,8 @@ protected:
void testSingleDirectoryRandomPayloadImpl(
tr_tracker_info const* trackers,
int const tracker_count,
char const** webseeds,
int const webseed_count,
size_t const max_file_count,
size_t const max_file_size,
char const* comment,
@ -193,6 +218,8 @@ protected:
testSingleDirectoryImpl(
trackers,
tracker_count,
webseeds,
webseed_count,
const_cast<void const**>(payloads),
payload_sizes,
payload_count,
@ -229,6 +256,32 @@ TEST_F(MakemetaTest, singleFile)
metainfo,
trackers.data(),
tracker_count,
nullptr,
0,
payload.data(),
payload.size(),
comment,
is_private,
"TESTME"sv);
}
TEST_F(MakemetaTest, webseed)
{
auto trackers = std::vector<tr_tracker_info>{};
auto webseeds = std::vector<char const*>{};
webseeds.emplace_back("https://www.example.com/linux.iso");
auto const payload = std::string{ "Hello, World!\n" };
char const* const comment = "This is the comment";
bool const is_private = false;
auto metainfo = tr_torrent_metainfo{};
testSingleFileImpl(
metainfo,
std::data(trackers),
std::size(trackers),
std::data(webseeds),
std::size(webseeds),
payload.data(),
payload.size(),
comment,
@ -255,6 +308,8 @@ TEST_F(MakemetaTest, singleFileDifferentSourceFlags)
metainfo_foobar,
trackers.data(),
tracker_count,
nullptr,
0,
payload.data(),
payload.size(),
comment,
@ -266,6 +321,8 @@ TEST_F(MakemetaTest, singleFileDifferentSourceFlags)
metainfo_testme,
trackers.data(),
tracker_count,
nullptr,
0,
payload.data(),
payload.size(),
comment,
@ -297,6 +354,8 @@ TEST_F(MakemetaTest, singleDirectoryRandomPayload)
testSingleDirectoryRandomPayloadImpl(
trackers.data(),
tracker_count,
nullptr,
0,
DefaultMaxFileCount,
DefaultMaxFileSize,
comment,

View file

@ -7,6 +7,7 @@
#include <cinttypes>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <string>
#include <libtransmission/transmission.h>
@ -30,13 +31,14 @@ char constexpr Usage[] = "Usage: transmission-create [options] <file|directory>"
uint32_t constexpr KiB = 1024;
auto constexpr Options = std::array<tr_option, 8>{
auto constexpr Options = std::array<tr_option, 9>{
{ { 'p', "private", "Allow this torrent to only be used with the specified tracker(s)", "p", false, nullptr },
{ 'r', "source", "Set the source for private trackers", "r", true, "<source>" },
{ 'o', "outfile", "Save the generated .torrent to this filename", "o", true, "<file>" },
{ 's', "piecesize", "Set the piece size in KiB, overriding the preferred default", "s", true, "<KiB>" },
{ 'c', "comment", "Add a comment", "c", true, "<comment>" },
{ 't', "tracker", "Add a tracker's announce URL", "t", true, "<url>" },
{ 'w', "webseed", "Add a webseed URL", "w", true, "<url>" },
{ 'V', "version", "Show version number and exit", "V", false, nullptr },
{ 0, nullptr, nullptr, nullptr, false, nullptr } }
};
@ -44,6 +46,7 @@ auto constexpr Options = std::array<tr_option, 8>{
struct app_options
{
std::vector<tr_tracker_info> trackers;
std::vector<char const*> webseeds;
std::string outfile;
char const* comment = nullptr;
char const* infile = nullptr;
@ -79,7 +82,11 @@ int parseCommandLine(app_options& options, int argc, char const* const* argv)
break;
case 't':
options.trackers.push_back(tr_tracker_info{ 0, const_cast<char*>(optarg), nullptr, 0 });
options.trackers.push_back(tr_tracker_info{ 0, const_cast<char*>(optarg) });
break;
case 'w':
options.webseeds.push_back(optarg);
break;
case 's':
@ -220,6 +227,8 @@ int tr_main(int argc, char* argv[])
options.outfile.c_str(),
std::data(options.trackers),
std::size(options.trackers),
std::data(options.webseeds),
std::size(options.webseeds),
options.comment,
options.is_private,
options.source);