2022-01-20 18:27:56 +00:00
|
|
|
// This file Copyright © 2005-2022 Mnemosyne LLC.
|
|
|
|
// It may be used under GPLv2 (SPDX: GPL-2.0), GPLv3 (SPDX: GPL-3.0),
|
|
|
|
// or any future license endorsed by Mnemosyne LLC.
|
|
|
|
// License text can be found in the licenses/ folder.
|
2021-12-25 21:21:13 +00:00
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <ctime>
|
|
|
|
#include <string>
|
|
|
|
#include <string_view>
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
#include "transmission.h"
|
|
|
|
|
|
|
|
#include "block-info.h"
|
|
|
|
#include "magnet-metainfo.h"
|
|
|
|
|
|
|
|
struct tr_error;
|
|
|
|
|
|
|
|
struct tr_torrent_metainfo : public tr_magnet_metainfo
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
[[nodiscard]] auto empty() const
|
|
|
|
{
|
|
|
|
return std::empty(files_);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool parseBenc(std::string_view benc, tr_error** error = nullptr);
|
|
|
|
|
|
|
|
// Helper function wrapper around parseBenc().
|
|
|
|
// If you're looping through several files, passing in a non-nullptr
|
|
|
|
// `buffer` can reduce the number of memory allocations needed to
|
|
|
|
// load multiple files.
|
|
|
|
bool parseTorrentFile(std::string_view benc_filename, std::vector<char>* buffer = nullptr, tr_error** error = nullptr);
|
|
|
|
|
2022-01-07 19:13:37 +00:00
|
|
|
/// BLOCK INFO
|
|
|
|
|
2022-01-08 18:53:35 +00:00
|
|
|
[[nodiscard]] constexpr auto const& blockInfo() const
|
|
|
|
{
|
|
|
|
return block_info_;
|
|
|
|
}
|
|
|
|
|
2022-01-07 19:13:37 +00:00
|
|
|
[[nodiscard]] constexpr auto blockCount() const
|
2021-12-25 21:21:13 +00:00
|
|
|
{
|
2022-01-07 19:13:37 +00:00
|
|
|
return blockInfo().blockCount();
|
|
|
|
}
|
2022-02-18 23:17:19 +00:00
|
|
|
[[nodiscard]] auto byteLoc(uint64_t byte) const
|
2022-01-07 19:13:37 +00:00
|
|
|
{
|
2022-02-18 23:17:19 +00:00
|
|
|
return blockInfo().byteLoc(byte);
|
2022-01-07 19:13:37 +00:00
|
|
|
}
|
2022-02-18 23:17:19 +00:00
|
|
|
[[nodiscard]] auto blockLoc(tr_block_index_t block) const
|
2022-01-07 19:13:37 +00:00
|
|
|
{
|
2022-02-18 23:17:19 +00:00
|
|
|
return blockInfo().blockLoc(block);
|
|
|
|
}
|
2022-02-19 16:07:08 +00:00
|
|
|
[[nodiscard]] auto pieceLoc(tr_piece_index_t piece, uint32_t offset = 0, uint32_t length = 0) const
|
2022-02-18 23:17:19 +00:00
|
|
|
{
|
|
|
|
return blockInfo().pieceLoc(piece, offset, length);
|
2022-01-07 19:13:37 +00:00
|
|
|
}
|
|
|
|
[[nodiscard]] constexpr auto blockSize(tr_block_index_t block) const
|
|
|
|
{
|
|
|
|
return blockInfo().blockSize(block);
|
|
|
|
}
|
|
|
|
[[nodiscard]] constexpr auto blockSpanForPiece(tr_piece_index_t piece) const
|
|
|
|
{
|
|
|
|
return blockInfo().blockSpanForPiece(piece);
|
|
|
|
}
|
|
|
|
[[nodiscard]] constexpr auto pieceCount() const
|
2021-12-25 21:21:13 +00:00
|
|
|
{
|
2022-01-07 19:13:37 +00:00
|
|
|
return blockInfo().pieceCount();
|
2021-12-25 21:21:13 +00:00
|
|
|
}
|
2022-01-07 19:13:37 +00:00
|
|
|
[[nodiscard]] constexpr auto pieceSize() const
|
|
|
|
{
|
|
|
|
return blockInfo().pieceSize();
|
|
|
|
}
|
|
|
|
[[nodiscard]] constexpr auto pieceSize(tr_piece_index_t piece) const
|
|
|
|
{
|
|
|
|
return blockInfo().pieceSize(piece);
|
|
|
|
}
|
|
|
|
[[nodiscard]] constexpr auto totalSize() const
|
|
|
|
{
|
|
|
|
return blockInfo().totalSize();
|
|
|
|
}
|
|
|
|
|
2022-01-16 18:02:47 +00:00
|
|
|
[[nodiscard]] auto const& comment() const
|
2021-12-25 21:21:13 +00:00
|
|
|
{
|
|
|
|
return comment_;
|
|
|
|
}
|
2022-01-16 18:02:47 +00:00
|
|
|
[[nodiscard]] auto const& creator() const
|
2021-12-25 21:21:13 +00:00
|
|
|
{
|
|
|
|
return creator_;
|
|
|
|
}
|
2022-01-07 19:13:37 +00:00
|
|
|
[[nodiscard]] auto const& source() const
|
|
|
|
{
|
|
|
|
return source_;
|
|
|
|
}
|
2021-12-25 21:21:13 +00:00
|
|
|
|
2022-01-16 18:02:47 +00:00
|
|
|
[[nodiscard]] auto fileCount() const
|
2022-01-08 18:53:35 +00:00
|
|
|
{
|
|
|
|
return std::size(files_);
|
|
|
|
}
|
2022-01-16 18:02:47 +00:00
|
|
|
|
|
|
|
[[nodiscard]] std::string const& fileSubpath(tr_file_index_t i) const;
|
|
|
|
|
|
|
|
void setFileSubpath(tr_file_index_t i, std::string_view subpath);
|
|
|
|
|
|
|
|
[[nodiscard]] uint64_t fileSize(tr_file_index_t i) const;
|
2021-12-25 21:21:13 +00:00
|
|
|
|
|
|
|
[[nodiscard]] auto const& isPrivate() const
|
|
|
|
{
|
|
|
|
return is_private_;
|
|
|
|
}
|
|
|
|
|
|
|
|
[[nodiscard]] tr_sha1_digest_t const& pieceHash(tr_piece_index_t piece) const;
|
|
|
|
|
|
|
|
[[nodiscard]] auto const& dateCreated() const
|
|
|
|
{
|
|
|
|
return date_created_;
|
|
|
|
}
|
|
|
|
|
|
|
|
[[nodiscard]] std::string benc() const;
|
|
|
|
|
|
|
|
[[nodiscard]] auto infoDictSize() const
|
|
|
|
{
|
|
|
|
return info_dict_size_;
|
|
|
|
}
|
|
|
|
|
|
|
|
[[nodiscard]] auto infoDictOffset() const
|
|
|
|
{
|
|
|
|
return info_dict_offset_;
|
|
|
|
}
|
|
|
|
|
2022-01-29 21:37:42 +00:00
|
|
|
[[nodiscard]] auto piecesOffset() const
|
|
|
|
{
|
|
|
|
return pieces_offset_;
|
|
|
|
}
|
|
|
|
|
2022-02-18 23:17:19 +00:00
|
|
|
[[nodiscard]] std::string torrentFile(std::string_view torrent_dir) const
|
2022-01-15 19:33:57 +00:00
|
|
|
{
|
|
|
|
return makeFilename(torrent_dir, name(), infoHashString(), BasenameFormat::Hash, ".torrent");
|
|
|
|
}
|
|
|
|
|
2022-02-24 21:52:29 +00:00
|
|
|
[[nodiscard]] std::string magnetFile(std::string_view torrent_dir) const
|
|
|
|
{
|
|
|
|
return makeFilename(torrent_dir, name(), infoHashString(), BasenameFormat::Hash, ".magnet");
|
|
|
|
}
|
|
|
|
|
2022-02-18 23:17:19 +00:00
|
|
|
[[nodiscard]] std::string resumeFile(std::string_view resume_dir) const
|
2022-01-15 19:33:57 +00:00
|
|
|
{
|
|
|
|
return makeFilename(resume_dir, name(), infoHashString(), BasenameFormat::Hash, ".resume");
|
|
|
|
}
|
|
|
|
|
2022-01-23 22:47:41 +00:00
|
|
|
static bool migrateFile(
|
2022-01-18 02:36:41 +00:00
|
|
|
std::string_view dirname,
|
|
|
|
std::string_view name,
|
|
|
|
std::string_view info_hash_string,
|
2022-01-23 22:47:41 +00:00
|
|
|
std::string_view suffix);
|
2022-01-18 02:36:41 +00:00
|
|
|
|
2022-01-23 22:47:41 +00:00
|
|
|
static void removeFile(
|
2022-01-15 19:33:57 +00:00
|
|
|
std::string_view dirname,
|
|
|
|
std::string_view name,
|
|
|
|
std::string_view info_hash_string,
|
|
|
|
std::string_view suffix);
|
|
|
|
|
2021-12-25 21:21:13 +00:00
|
|
|
private:
|
2022-01-15 19:33:57 +00:00
|
|
|
static bool parsePath(std::string_view root, tr_variant* path, std::string& setme);
|
2021-12-25 21:21:13 +00:00
|
|
|
static std::string fixWebseedUrl(tr_torrent_metainfo const& tm, std::string_view url);
|
|
|
|
static std::string_view parseFiles(tr_torrent_metainfo& setme, tr_variant* info_dict, uint64_t* setme_total_size);
|
|
|
|
static std::string_view parseImpl(tr_torrent_metainfo& setme, tr_variant* meta, std::string_view benc);
|
|
|
|
static std::string_view parseAnnounce(tr_torrent_metainfo& setme, tr_variant* meta);
|
|
|
|
static void parseWebseeds(tr_torrent_metainfo& setme, tr_variant* meta);
|
|
|
|
|
2022-01-15 19:33:57 +00:00
|
|
|
enum class BasenameFormat
|
|
|
|
{
|
|
|
|
Hash,
|
|
|
|
NameAndPartialHash
|
|
|
|
};
|
|
|
|
|
|
|
|
static std::string makeFilename(
|
|
|
|
std::string_view dirname,
|
|
|
|
std::string_view name,
|
|
|
|
std::string_view info_hash_string,
|
|
|
|
BasenameFormat format,
|
|
|
|
std::string_view suffix);
|
|
|
|
|
2022-02-18 23:17:19 +00:00
|
|
|
[[nodiscard]] std::string makeFilename(std::string_view dirname, BasenameFormat format, std::string_view suffix) const
|
2022-01-15 19:33:57 +00:00
|
|
|
{
|
|
|
|
return makeFilename(dirname, name(), infoHashString(), format, suffix);
|
|
|
|
}
|
|
|
|
|
2021-12-25 21:21:13 +00:00
|
|
|
struct file_t
|
|
|
|
{
|
|
|
|
public:
|
2022-02-18 23:17:19 +00:00
|
|
|
[[nodiscard]] std::string const& path() const
|
2021-12-25 21:21:13 +00:00
|
|
|
{
|
|
|
|
return path_;
|
|
|
|
}
|
2022-01-15 19:33:57 +00:00
|
|
|
|
|
|
|
void setSubpath(std::string_view subpath)
|
|
|
|
{
|
|
|
|
path_ = subpath;
|
|
|
|
}
|
|
|
|
|
2022-02-18 23:17:19 +00:00
|
|
|
[[nodiscard]] uint64_t size() const
|
2021-12-25 21:21:13 +00:00
|
|
|
{
|
2022-01-08 18:53:35 +00:00
|
|
|
return size_;
|
2021-12-25 21:21:13 +00:00
|
|
|
}
|
|
|
|
|
2022-01-08 18:53:35 +00:00
|
|
|
file_t(std::string_view path, uint64_t size)
|
2021-12-25 21:21:13 +00:00
|
|
|
: path_{ path }
|
2022-01-08 18:53:35 +00:00
|
|
|
, size_{ size }
|
2021-12-25 21:21:13 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
std::string path_;
|
2022-01-08 18:53:35 +00:00
|
|
|
uint64_t size_ = 0;
|
2021-12-25 21:21:13 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
tr_block_info block_info_ = tr_block_info{ 0, 0 };
|
|
|
|
|
|
|
|
std::vector<tr_sha1_digest_t> pieces_;
|
|
|
|
std::vector<file_t> files_;
|
|
|
|
|
|
|
|
std::string comment_;
|
|
|
|
std::string creator_;
|
|
|
|
std::string source_;
|
|
|
|
|
|
|
|
time_t date_created_ = 0;
|
|
|
|
|
|
|
|
// Offset + size of the bencoded info dict subset of the bencoded data.
|
|
|
|
// Used when loading pieces of it to sent to magnet peers.
|
|
|
|
// See http://bittorrent.org/beps/bep_0009.html
|
|
|
|
uint64_t info_dict_size_ = 0;
|
|
|
|
uint64_t info_dict_offset_ = 0;
|
|
|
|
|
|
|
|
// Offset of the bencoded 'pieces' checksums subset of the bencoded data.
|
|
|
|
// Used when loading piece checksums on demand.
|
|
|
|
uint64_t pieces_offset_ = 0;
|
|
|
|
|
|
|
|
bool is_private_ = false;
|
|
|
|
};
|