Skip to content

Commit

Permalink
Allow torrents to override default share limit action
Browse files Browse the repository at this point in the history
PR #20528.
  • Loading branch information
glassez authored Mar 12, 2024
1 parent 773cb1e commit d5e41bf
Show file tree
Hide file tree
Showing 23 changed files with 456 additions and 235 deletions.
36 changes: 35 additions & 1 deletion src/app/upgrade.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include <QCoreApplication>
#include <QMetaEnum>

#include "base/bittorrent/sharelimitaction.h"
#include "base/bittorrent/torrentcontentlayout.h"
#include "base/global.h"
#include "base/logger.h"
Expand All @@ -45,7 +46,7 @@

namespace
{
const int MIGRATION_VERSION = 6;
const int MIGRATION_VERSION = 7;
const QString MIGRATION_VERSION_KEY = u"Meta/MigrationVersion"_s;

void exportWebUIHttpsFiles()
Expand Down Expand Up @@ -437,6 +438,36 @@ namespace
settingsStorage->storeValue(key, u"zh_CN"_s);
}
}

void migrateShareLimitActionSettings()
{
auto *settingsStorage = SettingsStorage::instance();
const auto oldKey = u"BitTorrent/Session/MaxRatioAction"_s;
const auto newKey = u"BitTorrent/Session/ShareLimitAction"_s;
const auto value = settingsStorage->loadValue<int>(oldKey);

switch (value)
{
case 0:
settingsStorage->storeValue(newKey, BitTorrent::ShareLimitAction::Stop);
break;
case 1:
settingsStorage->storeValue(newKey, BitTorrent::ShareLimitAction::Remove);
break;
case 2:
settingsStorage->storeValue(newKey, BitTorrent::ShareLimitAction::EnableSuperSeeding);
break;
case 3:
settingsStorage->storeValue(newKey, BitTorrent::ShareLimitAction::RemoveWithContent);
break;
default:
LogMsg(QCoreApplication::translate("Upgrade", "Invalid value found in configuration file, reverting it to default. Key: \"%1\". Invalid value: \"%2\".")
.arg(oldKey, QString::number(value)), Log::WARNING);
break;
}

settingsStorage->removeValue(oldKey);
}
}

bool upgrade()
Expand Down Expand Up @@ -475,6 +506,9 @@ bool upgrade()
if (version < 6)
migrateProxySettings();

if (version < 7)
migrateShareLimitActionSettings();

version = MIGRATION_VERSION;
}

Expand Down
1 change: 1 addition & 0 deletions src/base/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ add_library(qbt_base STATIC
bittorrent/session.h
bittorrent/sessionimpl.h
bittorrent/sessionstatus.h
bittorrent/sharelimitaction.h
bittorrent/speedmonitor.h
bittorrent/sslparameters.h
bittorrent/torrent.h
Expand Down
11 changes: 7 additions & 4 deletions src/base/bittorrent/addtorrentparams.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2015-2023 Vladimir Golovnev <glassez@yandex.ru>
* Copyright (C) 2015-2024 Vladimir Golovnev <glassez@yandex.ru>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
Expand Down Expand Up @@ -51,6 +51,7 @@ const QString PARAM_UPLOADLIMIT = u"upload_limit"_s;
const QString PARAM_DOWNLOADLIMIT = u"download_limit"_s;
const QString PARAM_SEEDINGTIMELIMIT = u"seeding_time_limit"_s;
const QString PARAM_INACTIVESEEDINGTIMELIMIT = u"inactive_seeding_time_limit"_s;
const QString PARAM_SHARELIMITACTION = u"share_limit_action"_s;
const QString PARAM_RATIOLIMIT = u"ratio_limit"_s;
const QString PARAM_SSL_CERTIFICATE = u"ssl_certificate"_s;
const QString PARAM_SSL_PRIVATEKEY = u"ssl_private_key"_s;
Expand Down Expand Up @@ -96,10 +97,10 @@ namespace
}

template <typename Enum>
Enum getEnum(const QJsonObject &jsonObj, const QString &key)
Enum getEnum(const QJsonObject &jsonObj, const QString &key, const Enum defaultValue = {})
{
const QJsonValue jsonVal = jsonObj.value(key);
return Utils::String::toEnum<Enum>(jsonVal.toString(), {});
return Utils::String::toEnum<Enum>(jsonVal.toString(), defaultValue);
}
}

Expand Down Expand Up @@ -127,6 +128,7 @@ BitTorrent::AddTorrentParams BitTorrent::parseAddTorrentParams(const QJsonObject
.seedingTimeLimit = jsonObj.value(PARAM_SEEDINGTIMELIMIT).toInt(Torrent::USE_GLOBAL_SEEDING_TIME),
.inactiveSeedingTimeLimit = jsonObj.value(PARAM_INACTIVESEEDINGTIMELIMIT).toInt(Torrent::USE_GLOBAL_INACTIVE_SEEDING_TIME),
.ratioLimit = jsonObj.value(PARAM_RATIOLIMIT).toDouble(Torrent::USE_GLOBAL_RATIO),
.shareLimitAction = getEnum<ShareLimitAction>(jsonObj, PARAM_SHARELIMITACTION, ShareLimitAction::Default),
.sslParameters =
{
.certificate = QSslCertificate(jsonObj.value(PARAM_SSL_CERTIFICATE).toString().toLatin1()),
Expand All @@ -146,12 +148,13 @@ QJsonObject BitTorrent::serializeAddTorrentParams(const AddTorrentParams &params
{PARAM_SAVEPATH, params.savePath.data()},
{PARAM_DOWNLOADPATH, params.downloadPath.data()},
{PARAM_OPERATINGMODE, Utils::String::fromEnum(params.addForced
? TorrentOperatingMode::Forced : TorrentOperatingMode::AutoManaged)},
? TorrentOperatingMode::Forced : TorrentOperatingMode::AutoManaged)},
{PARAM_SKIPCHECKING, params.skipChecking},
{PARAM_UPLOADLIMIT, params.uploadLimit},
{PARAM_DOWNLOADLIMIT, params.downloadLimit},
{PARAM_SEEDINGTIMELIMIT, params.seedingTimeLimit},
{PARAM_INACTIVESEEDINGTIMELIMIT, params.inactiveSeedingTimeLimit},
{PARAM_SHARELIMITACTION, Utils::String::fromEnum(params.shareLimitAction)},
{PARAM_RATIOLIMIT, params.ratioLimit},
{PARAM_SSL_CERTIFICATE, QString::fromLatin1(params.sslParameters.certificate.toPem())},
{PARAM_SSL_PRIVATEKEY, QString::fromLatin1(params.sslParameters.privateKey.toPem())},
Expand Down
4 changes: 3 additions & 1 deletion src/base/bittorrent/addtorrentparams.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2015-2023 Vladimir Golovnev <glassez@yandex.ru>
* Copyright (C) 2015-2024 Vladimir Golovnev <glassez@yandex.ru>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
Expand Down Expand Up @@ -36,6 +36,7 @@

#include "base/path.h"
#include "base/tagset.h"
#include "sharelimitaction.h"
#include "sslparameters.h"
#include "torrent.h"
#include "torrentcontentlayout.h"
Expand Down Expand Up @@ -70,6 +71,7 @@ namespace BitTorrent
int seedingTimeLimit = Torrent::USE_GLOBAL_SEEDING_TIME;
int inactiveSeedingTimeLimit = Torrent::USE_GLOBAL_INACTIVE_SEEDING_TIME;
qreal ratioLimit = Torrent::USE_GLOBAL_RATIO;
ShareLimitAction shareLimitAction = ShareLimitAction::Default;
SSLParameters sslParameters;

friend bool operator==(const AddTorrentParams &lhs, const AddTorrentParams &rhs) = default;
Expand Down
10 changes: 7 additions & 3 deletions src/base/bittorrent/bencoderesumedatastorage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -231,14 +231,16 @@ BitTorrent::LoadResumeDataResult BitTorrent::BencodeResumeDataStorage::loadTorre
torrentParams.firstLastPiecePriority = resumeDataRoot.dict_find_int_value("qBt-firstLastPiecePriority");
torrentParams.seedingTimeLimit = resumeDataRoot.dict_find_int_value("qBt-seedingTimeLimit", Torrent::USE_GLOBAL_SEEDING_TIME);
torrentParams.inactiveSeedingTimeLimit = resumeDataRoot.dict_find_int_value("qBt-inactiveSeedingTimeLimit", Torrent::USE_GLOBAL_INACTIVE_SEEDING_TIME);
torrentParams.shareLimitAction = Utils::String::toEnum(
fromLTString(resumeDataRoot.dict_find_string_value("qBt-shareLimitAction")), ShareLimitAction::Default);

torrentParams.savePath = Profile::instance()->fromPortablePath(
Path(fromLTString(resumeDataRoot.dict_find_string_value("qBt-savePath"))));
Path(fromLTString(resumeDataRoot.dict_find_string_value("qBt-savePath"))));
torrentParams.useAutoTMM = torrentParams.savePath.isEmpty();
if (!torrentParams.useAutoTMM)
{
torrentParams.downloadPath = Profile::instance()->fromPortablePath(
Path(fromLTString(resumeDataRoot.dict_find_string_value("qBt-downloadPath"))));
Path(fromLTString(resumeDataRoot.dict_find_string_value("qBt-downloadPath"))));
}

// TODO: The following code is deprecated. Replace with the commented one after several releases in 4.4.x.
Expand All @@ -261,7 +263,7 @@ BitTorrent::LoadResumeDataResult BitTorrent::BencodeResumeDataStorage::loadTorre
// === END REPLACEMENT CODE === //

torrentParams.stopCondition = Utils::String::toEnum(
fromLTString(resumeDataRoot.dict_find_string_value("qBt-stopCondition")), Torrent::StopCondition::None);
fromLTString(resumeDataRoot.dict_find_string_value("qBt-stopCondition")), Torrent::StopCondition::None);
torrentParams.sslParameters =
{
.certificate = QSslCertificate(toByteArray(resumeDataRoot.dict_find_string_value(KEY_SSL_CERTIFICATE))),
Expand Down Expand Up @@ -418,6 +420,8 @@ void BitTorrent::BencodeResumeDataStorage::Worker::store(const TorrentID &id, co
data["qBt-ratioLimit"] = static_cast<int>(resumeData.ratioLimit * 1000);
data["qBt-seedingTimeLimit"] = resumeData.seedingTimeLimit;
data["qBt-inactiveSeedingTimeLimit"] = resumeData.inactiveSeedingTimeLimit;
data["qBt-shareLimitAction"] = Utils::String::fromEnum(resumeData.shareLimitAction).toStdString();

data["qBt-category"] = resumeData.category.toStdString();
data["qBt-tags"] = setToEntryList(resumeData.tags);
data["qBt-name"] = resumeData.name.toStdString();
Expand Down
17 changes: 13 additions & 4 deletions src/base/bittorrent/dbresumedatastorage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ namespace
{
const QString DB_CONNECTION_NAME = u"ResumeDataStorage"_s;

const int DB_VERSION = 6;
const int DB_VERSION = 7;

const QString DB_TABLE_META = u"meta"_s;
const QString DB_TABLE_TORRENTS = u"torrents"_s;
Expand Down Expand Up @@ -138,6 +138,7 @@ namespace
const Column DB_COLUMN_RATIO_LIMIT = makeColumn("ratio_limit");
const Column DB_COLUMN_SEEDING_TIME_LIMIT = makeColumn("seeding_time_limit");
const Column DB_COLUMN_INACTIVE_SEEDING_TIME_LIMIT = makeColumn("inactive_seeding_time_limit");
const Column DB_COLUMN_SHARE_LIMIT_ACTION = makeColumn("share_limit_action");
const Column DB_COLUMN_HAS_OUTER_PIECES_PRIORITY = makeColumn("has_outer_pieces_priority");
const Column DB_COLUMN_HAS_SEED_STATUS = makeColumn("has_seed_status");
const Column DB_COLUMN_OPERATING_MODE = makeColumn("operating_mode");
Expand Down Expand Up @@ -234,13 +235,15 @@ namespace
resumeData.ratioLimit = query.value(DB_COLUMN_RATIO_LIMIT.name).toInt() / 1000.0;
resumeData.seedingTimeLimit = query.value(DB_COLUMN_SEEDING_TIME_LIMIT.name).toInt();
resumeData.inactiveSeedingTimeLimit = query.value(DB_COLUMN_INACTIVE_SEEDING_TIME_LIMIT.name).toInt();
resumeData.shareLimitAction = Utils::String::toEnum<ShareLimitAction>(
query.value(DB_COLUMN_SHARE_LIMIT_ACTION.name).toString(), ShareLimitAction::Default);
resumeData.contentLayout = Utils::String::toEnum<TorrentContentLayout>(
query.value(DB_COLUMN_CONTENT_LAYOUT.name).toString(), TorrentContentLayout::Original);
query.value(DB_COLUMN_CONTENT_LAYOUT.name).toString(), TorrentContentLayout::Original);
resumeData.operatingMode = Utils::String::toEnum<TorrentOperatingMode>(
query.value(DB_COLUMN_OPERATING_MODE.name).toString(), TorrentOperatingMode::AutoManaged);
query.value(DB_COLUMN_OPERATING_MODE.name).toString(), TorrentOperatingMode::AutoManaged);
resumeData.stopped = query.value(DB_COLUMN_STOPPED.name).toBool();
resumeData.stopCondition = Utils::String::toEnum(
query.value(DB_COLUMN_STOP_CONDITION.name).toString(), Torrent::StopCondition::None);
query.value(DB_COLUMN_STOP_CONDITION.name).toString(), Torrent::StopCondition::None);
resumeData.sslParameters =
{
.certificate = QSslCertificate(query.value(DB_COLUMN_SSL_CERTIFICATE.name).toByteArray()),
Expand Down Expand Up @@ -540,6 +543,7 @@ void BitTorrent::DBResumeDataStorage::createDB() const
makeColumnDefinition(DB_COLUMN_RATIO_LIMIT, "INTEGER NOT NULL"),
makeColumnDefinition(DB_COLUMN_SEEDING_TIME_LIMIT, "INTEGER NOT NULL"),
makeColumnDefinition(DB_COLUMN_INACTIVE_SEEDING_TIME_LIMIT, "INTEGER NOT NULL"),
makeColumnDefinition(DB_COLUMN_SHARE_LIMIT_ACTION, "TEXT NOT NULL DEFAULT `Default`"),
makeColumnDefinition(DB_COLUMN_HAS_OUTER_PIECES_PRIORITY, "INTEGER NOT NULL"),
makeColumnDefinition(DB_COLUMN_HAS_SEED_STATUS, "INTEGER NOT NULL"),
makeColumnDefinition(DB_COLUMN_OPERATING_MODE, "TEXT NOT NULL"),
Expand Down Expand Up @@ -623,6 +627,9 @@ void BitTorrent::DBResumeDataStorage::updateDB(const int fromVersion) const
addColumn(DB_TABLE_TORRENTS, DB_COLUMN_SSL_DH_PARAMS, "TEXT");
}

if (fromVersion <= 6)
addColumn(DB_TABLE_TORRENTS, DB_COLUMN_SHARE_LIMIT_ACTION, "TEXTNOT NULL DEFAULT `Default`");

const QString updateMetaVersionQuery = makeUpdateStatement(DB_TABLE_META, {DB_COLUMN_NAME, DB_COLUMN_VALUE});
if (!query.prepare(updateMetaVersionQuery))
throw RuntimeError(query.lastError().text());
Expand Down Expand Up @@ -801,6 +808,7 @@ namespace
DB_COLUMN_RATIO_LIMIT,
DB_COLUMN_SEEDING_TIME_LIMIT,
DB_COLUMN_INACTIVE_SEEDING_TIME_LIMIT,
DB_COLUMN_SHARE_LIMIT_ACTION,
DB_COLUMN_HAS_OUTER_PIECES_PRIORITY,
DB_COLUMN_HAS_SEED_STATUS,
DB_COLUMN_OPERATING_MODE,
Expand Down Expand Up @@ -863,6 +871,7 @@ namespace
query.bindValue(DB_COLUMN_RATIO_LIMIT.placeholder, static_cast<int>(m_resumeData.ratioLimit * 1000));
query.bindValue(DB_COLUMN_SEEDING_TIME_LIMIT.placeholder, m_resumeData.seedingTimeLimit);
query.bindValue(DB_COLUMN_INACTIVE_SEEDING_TIME_LIMIT.placeholder, m_resumeData.inactiveSeedingTimeLimit);
query.bindValue(DB_COLUMN_SHARE_LIMIT_ACTION.placeholder, Utils::String::fromEnum(m_resumeData.shareLimitAction));
query.bindValue(DB_COLUMN_HAS_OUTER_PIECES_PRIORITY.placeholder, m_resumeData.firstLastPiecePriority);
query.bindValue(DB_COLUMN_HAS_SEED_STATUS.placeholder, m_resumeData.hasFinishedStatus);
query.bindValue(DB_COLUMN_OPERATING_MODE.placeholder, Utils::String::fromEnum(m_resumeData.operatingMode));
Expand Down
5 changes: 4 additions & 1 deletion src/base/bittorrent/loadtorrentparams.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2021 Vladimir Golovnev <glassez@yandex.ru>
* Copyright (C) 2021-2024 Vladimir Golovnev <glassez@yandex.ru>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
Expand Down Expand Up @@ -34,6 +34,7 @@

#include "base/path.h"
#include "base/tagset.h"
#include "sharelimitaction.h"
#include "sslparameters.h"
#include "torrent.h"
#include "torrentcontentlayout.h"
Expand Down Expand Up @@ -62,6 +63,8 @@ namespace BitTorrent
qreal ratioLimit = Torrent::USE_GLOBAL_RATIO;
int seedingTimeLimit = Torrent::USE_GLOBAL_SEEDING_TIME;
int inactiveSeedingTimeLimit = Torrent::USE_GLOBAL_INACTIVE_SEEDING_TIME;
ShareLimitAction shareLimitAction = ShareLimitAction::Default;

SSLParameters sslParameters;
};
}
19 changes: 5 additions & 14 deletions src/base/bittorrent/session.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2015-2023 Vladimir Golovnev <glassez@yandex.ru>
* Copyright (C) 2015-2024 Vladimir Golovnev <glassez@yandex.ru>
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
*
* This program is free software; you can redistribute it and/or
Expand Down Expand Up @@ -36,20 +36,11 @@
#include "base/tagset.h"
#include "addtorrentparams.h"
#include "categoryoptions.h"
#include "sharelimitaction.h"
#include "trackerentry.h"

class QString;

// These values should remain unchanged when adding new items
// so as not to break the existing user settings.
enum MaxRatioAction
{
Pause = 0,
Remove = 1,
DeleteFiles = 3,
EnableSuperSeeding = 2
};

enum DeleteOption
{
DeleteTorrent,
Expand Down Expand Up @@ -209,6 +200,9 @@ namespace BitTorrent
virtual void setGlobalMaxSeedingMinutes(int minutes) = 0;
virtual int globalMaxInactiveSeedingMinutes() const = 0;
virtual void setGlobalMaxInactiveSeedingMinutes(int minutes) = 0;
virtual ShareLimitAction shareLimitAction() const = 0;
virtual void setShareLimitAction(ShareLimitAction act) = 0;

virtual QString getDHTBootstrapNodes() const = 0;
virtual void setDHTBootstrapNodes(const QString &nodes) = 0;
virtual bool isDHTEnabled() const = 0;
Expand Down Expand Up @@ -446,9 +440,6 @@ namespace BitTorrent
virtual const CacheStatus &cacheStatus() const = 0;
virtual bool isListening() const = 0;

virtual MaxRatioAction maxRatioAction() const = 0;
virtual void setMaxRatioAction(MaxRatioAction act) = 0;

virtual void banIP(const QString &ip) = 0;

virtual bool isKnownTorrent(const InfoHash &infoHash) const = 0;
Expand Down
Loading

0 comments on commit d5e41bf

Please sign in to comment.