Browse Source

Merge pull request #10074 from Chocobo1/magneturi

Drop support for "BC Link" format
adaptive-webui-19844
Mike Tzou 6 years ago committed by GitHub
parent
commit
b87987ec89
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 47
      src/base/bittorrent/magneturi.cpp
  2. 13
      src/base/bittorrent/session.cpp
  3. 2
      src/base/bittorrent/session.h
  4. 11
      src/base/net/downloadmanager.cpp
  5. 2
      src/base/net/downloadmanager.h
  6. 3
      src/base/search/searchpluginmanager.cpp
  7. 8
      src/base/utils/misc.cpp
  8. 1
      src/base/utils/misc.h
  9. 32
      src/gui/addnewtorrentdialog.cpp
  10. 4
      src/gui/addnewtorrentdialog.h
  11. 10
      src/gui/mainwindow.cpp
  12. 3
      src/gui/rss/rsswidget.cpp
  13. 3
      src/gui/search/pluginselectdialog.cpp

47
src/base/bittorrent/magneturi.cpp

@ -31,29 +31,26 @@
#include <libtorrent/bencode.hpp> #include <libtorrent/bencode.hpp>
#include <libtorrent/error_code.hpp> #include <libtorrent/error_code.hpp>
#include <libtorrent/magnet_uri.hpp> #include <libtorrent/magnet_uri.hpp>
#include <libtorrent/sha1_hash.hpp>
#include <QByteArray>
#include <QRegularExpression> #include <QRegularExpression>
#include <QStringList>
#include "base/utils/string.h"
namespace namespace
{ {
QString bcLinkToMagnet(QString bcLink) bool isBitTorrentInfoHash(const QString &string)
{ {
QByteArray rawBc = bcLink.toUtf8(); // There are 2 represenations for BitTorrent info hash:
rawBc = rawBc.mid(8); // skip bc://bt/ // 1. 40 chars hex-encoded string
rawBc = QByteArray::fromBase64(rawBc); // Decode base64 // == 20 (SHA-1 length in bytes) * 2 (each byte maps to 2 hex characters)
// Format is now AA/url_encoded_filename/size_bytes/info_hash/ZZ // 2. 32 chars Base32 encoded string
QStringList parts = QString(rawBc).split('/'); // == 20 (SHA-1 length in bytes) * 1.6 (the efficiency of Base32 encoding)
if (parts.size() != 5) return QString(); const int SHA1_HEX_SIZE = libtorrent::sha1_hash::size * 2;
const int SHA1_BASE32_SIZE = libtorrent::sha1_hash::size * 1.6;
QString filename = parts.at(1);
QString hash = parts.at(3); return ((((string.size() == SHA1_HEX_SIZE))
QString magnet = "magnet:?xt=urn:btih:" + hash; && !string.contains(QRegularExpression(QLatin1String("[^0-9A-Fa-f]"))))
magnet += "&dn=" + filename; || ((string.size() == SHA1_BASE32_SIZE)
return magnet; && !string.contains(QRegularExpression(QLatin1String("[^2-7A-Za-z]")))));
} }
} }
@ -66,17 +63,11 @@ MagnetUri::MagnetUri(const QString &source)
{ {
if (source.isEmpty()) return; if (source.isEmpty()) return;
if (source.startsWith("bc://bt/", Qt::CaseInsensitive)) { if (isBitTorrentInfoHash(source))
qDebug("Creating magnet link from bc link"); m_url = QLatin1String("magnet:?xt=urn:btih:") + source;
m_url = bcLinkToMagnet(source);
}
else if (((source.size() == 40) && !source.contains(QRegularExpression("[^0-9A-Fa-f]")))
|| ((source.size() == 32) && !source.contains(QRegularExpression("[^2-7A-Za-z]")))) {
m_url = "magnet:?xt=urn:btih:" + source;
}
libt::error_code ec; libt::error_code ec;
libt::parse_magnet_uri(m_url.toUtf8().constData(), m_addTorrentParams, ec); libt::parse_magnet_uri(m_url.toStdString(), m_addTorrentParams, ec);
if (ec) return; if (ec) return;
m_valid = true; m_valid = true;
@ -84,10 +75,10 @@ MagnetUri::MagnetUri(const QString &source)
m_name = QString::fromStdString(m_addTorrentParams.name); m_name = QString::fromStdString(m_addTorrentParams.name);
for (const std::string &tracker : m_addTorrentParams.trackers) for (const std::string &tracker : m_addTorrentParams.trackers)
m_trackers.append(QString::fromStdString(tracker)); m_trackers.append(TrackerEntry(tracker));
for (const std::string &urlSeed : m_addTorrentParams.url_seeds) for (const std::string &urlSeed : m_addTorrentParams.url_seeds)
m_urlSeeds.append(QUrl(urlSeed.c_str())); m_urlSeeds.append(QUrl(QString::fromStdString(urlSeed)));
} }
bool MagnetUri::isValid() const bool MagnetUri::isValid() const

13
src/base/bittorrent/session.cpp

@ -2090,14 +2090,11 @@ TorrentStatusReport Session::torrentStatusReport() const
return m_torrentStatusReport; return m_torrentStatusReport;
} }
// source - .torrent file path/url or magnet uri bool Session::addTorrent(const QString &source, const AddTorrentParams &params)
bool Session::addTorrent(QString source, const AddTorrentParams &params)
{ {
MagnetUri magnetUri(source); // `source`: .torrent file path/url or magnet uri
if (magnetUri.isValid())
return addTorrent_impl(CreateTorrentParams(params), magnetUri);
if (Utils::Misc::isUrl(source)) { if (Net::DownloadManager::hasSupportedScheme(source)) {
LogMsg(tr("Downloading '%1', please wait...", "e.g: Downloading 'xxx.torrent', please wait...").arg(source)); LogMsg(tr("Downloading '%1', please wait...", "e.g: Downloading 'xxx.torrent', please wait...").arg(source));
// Launch downloader // Launch downloader
Net::DownloadHandler *handler = Net::DownloadHandler *handler =
@ -2110,6 +2107,10 @@ bool Session::addTorrent(QString source, const AddTorrentParams &params)
return true; return true;
} }
const MagnetUri magnetUri {source};
if (magnetUri.isValid())
return addTorrent_impl(CreateTorrentParams(params), magnetUri);
TorrentFileGuard guard(source); TorrentFileGuard guard(source);
if (addTorrent_impl(CreateTorrentParams(params) if (addTorrent_impl(CreateTorrentParams(params)
, MagnetUri(), TorrentInfo::loadFromFile(source))) { , MagnetUri(), TorrentInfo::loadFromFile(source))) {

2
src/base/bittorrent/session.h

@ -469,7 +469,7 @@ namespace BitTorrent
void banIP(const QString &ip); void banIP(const QString &ip);
bool isKnownTorrent(const InfoHash &hash) const; bool isKnownTorrent(const InfoHash &hash) const;
bool addTorrent(QString source, const AddTorrentParams &params = AddTorrentParams()); bool addTorrent(const QString &source, const AddTorrentParams &params = AddTorrentParams());
bool addTorrent(const TorrentInfo &torrentInfo, const AddTorrentParams &params = AddTorrentParams()); bool addTorrent(const TorrentInfo &torrentInfo, const AddTorrentParams &params = AddTorrentParams());
bool deleteTorrent(const QString &hash, bool deleteLocalFiles = false); bool deleteTorrent(const QString &hash, bool deleteLocalFiles = false);
bool loadMetadata(const MagnetUri &magnetUri); bool loadMetadata(const MagnetUri &magnetUri);

11
src/base/net/downloadmanager.cpp

@ -29,6 +29,8 @@
#include "downloadmanager.h" #include "downloadmanager.h"
#include <algorithm>
#include <QDateTime> #include <QDateTime>
#include <QDebug> #include <QDebug>
#include <QNetworkCookie> #include <QNetworkCookie>
@ -210,6 +212,15 @@ bool Net::DownloadManager::deleteCookie(const QNetworkCookie &cookie)
return static_cast<NetworkCookieJar *>(m_networkManager.cookieJar())->deleteCookie(cookie); return static_cast<NetworkCookieJar *>(m_networkManager.cookieJar())->deleteCookie(cookie);
} }
bool Net::DownloadManager::hasSupportedScheme(const QString &url)
{
const QStringList schemes = instance()->m_networkManager.supportedSchemes();
return std::any_of(schemes.cbegin(), schemes.cend(), [&url](const QString &scheme)
{
return url.startsWith((scheme + QLatin1Char(':')), Qt::CaseInsensitive);
});
}
void Net::DownloadManager::applyProxySettings() void Net::DownloadManager::applyProxySettings()
{ {
auto proxyManager = ProxyConfigurationManager::instance(); auto proxyManager = ProxyConfigurationManager::instance();

2
src/base/net/downloadmanager.h

@ -103,6 +103,8 @@ namespace Net
void setAllCookies(const QList<QNetworkCookie> &cookieList); void setAllCookies(const QList<QNetworkCookie> &cookieList);
bool deleteCookie(const QNetworkCookie &cookie); bool deleteCookie(const QNetworkCookie &cookie);
static bool hasSupportedScheme(const QString &url);
private slots: private slots:
#ifndef QT_NO_OPENSSL #ifndef QT_NO_OPENSSL
void ignoreSslErrors(QNetworkReply *, const QList<QSslError> &); void ignoreSslErrors(QNetworkReply *, const QList<QSslError> &);

3
src/base/search/searchpluginmanager.cpp

@ -50,7 +50,6 @@
#include "base/utils/bytearray.h" #include "base/utils/bytearray.h"
#include "base/utils/foreignapps.h" #include "base/utils/foreignapps.h"
#include "base/utils/fs.h" #include "base/utils/fs.h"
#include "base/utils/misc.h"
#include "searchdownloadhandler.h" #include "searchdownloadhandler.h"
#include "searchhandler.h" #include "searchhandler.h"
@ -198,7 +197,7 @@ void SearchPluginManager::installPlugin(const QString &source)
{ {
clearPythonCache(engineLocation()); clearPythonCache(engineLocation());
if (Utils::Misc::isUrl(source)) { if (Net::DownloadManager::hasSupportedScheme(source)) {
using namespace Net; using namespace Net;
DownloadHandler *handler = DownloadManager::instance()->download(DownloadRequest(source).saveToFile(true)); DownloadHandler *handler = DownloadManager::instance()->download(DownloadRequest(source).saveToFile(true));
connect(handler, static_cast<void (DownloadHandler::*)(const QString &, const QString &)>(&DownloadHandler::downloadFinished) connect(handler, static_cast<void (DownloadHandler::*)(const QString &, const QString &)>(&DownloadHandler::downloadFinished)

8
src/base/utils/misc.cpp

@ -414,14 +414,6 @@ QList<bool> Utils::Misc::boolListfromStringList(const QStringList &l)
return ret; return ret;
} }
bool Utils::Misc::isUrl(const QString &s)
{
static const QRegularExpression reURLScheme(
"http[s]?|ftp", QRegularExpression::CaseInsensitiveOption);
return reURLScheme.match(QUrl(s).scheme()).hasMatch();
}
QString Utils::Misc::parseHtmlLinks(const QString &rawText) QString Utils::Misc::parseHtmlLinks(const QString &rawText)
{ {
QString result = rawText; QString result = rawText;

1
src/base/utils/misc.h

@ -71,7 +71,6 @@ namespace Utils
}; };
QString parseHtmlLinks(const QString &rawText); QString parseHtmlLinks(const QString &rawText);
bool isUrl(const QString &s);
void shutdownComputer(const ShutdownDialogAction &action); void shutdownComputer(const ShutdownDialogAction &action);

32
src/gui/addnewtorrentdialog.cpp

@ -227,11 +227,11 @@ void AddNewTorrentDialog::saveState()
settings()->storeValue(KEY_EXPANDED, m_ui->toolButtonAdvanced->isChecked()); settings()->storeValue(KEY_EXPANDED, m_ui->toolButtonAdvanced->isChecked());
} }
void AddNewTorrentDialog::show(QString source, const BitTorrent::AddTorrentParams &inParams, QWidget *parent) void AddNewTorrentDialog::show(const QString &source, const BitTorrent::AddTorrentParams &inParams, QWidget *parent)
{ {
AddNewTorrentDialog *dlg = new AddNewTorrentDialog(inParams, parent); AddNewTorrentDialog *dlg = new AddNewTorrentDialog(inParams, parent);
if (Utils::Misc::isUrl(source)) { if (Net::DownloadManager::hasSupportedScheme(source)) {
// Launch downloader // Launch downloader
// TODO: Don't save loaded torrent to file, just use downloaded data! // TODO: Don't save loaded torrent to file, just use downloaded data!
Net::DownloadHandler *handler = Net::DownloadManager::instance()->download( Net::DownloadHandler *handler = Net::DownloadManager::instance()->download(
@ -240,27 +240,27 @@ void AddNewTorrentDialog::show(QString source, const BitTorrent::AddTorrentParam
, dlg, &AddNewTorrentDialog::handleDownloadFinished); , dlg, &AddNewTorrentDialog::handleDownloadFinished);
connect(handler, &Net::DownloadHandler::downloadFailed, dlg, &AddNewTorrentDialog::handleDownloadFailed); connect(handler, &Net::DownloadHandler::downloadFailed, dlg, &AddNewTorrentDialog::handleDownloadFailed);
connect(handler, &Net::DownloadHandler::redirectedToMagnet, dlg, &AddNewTorrentDialog::handleRedirectedToMagnet); connect(handler, &Net::DownloadHandler::redirectedToMagnet, dlg, &AddNewTorrentDialog::handleRedirectedToMagnet);
return;
} }
else {
bool ok = false; const BitTorrent::MagnetUri magnetUri(source);
BitTorrent::MagnetUri magnetUri(source); const bool isLoaded = magnetUri.isValid()
if (magnetUri.isValid()) ? dlg->loadMagnet(magnetUri)
ok = dlg->loadMagnet(magnetUri); : dlg->loadTorrent(source);
else
ok = dlg->loadTorrent(source); if (isLoaded) {
if (ok)
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
dlg->exec(); dlg->exec();
#else #else
dlg->open(); dlg->open();
#endif #endif
else }
delete dlg; else {
delete dlg;
} }
} }
void AddNewTorrentDialog::show(QString source, QWidget *parent) void AddNewTorrentDialog::show(const QString &source, QWidget *parent)
{ {
show(source, BitTorrent::AddTorrentParams(), parent); show(source, BitTorrent::AddTorrentParams(), parent);
} }

4
src/gui/addnewtorrentdialog.h

@ -68,8 +68,8 @@ public:
static int savePathHistoryLength(); static int savePathHistoryLength();
static void setSavePathHistoryLength(int value); static void setSavePathHistoryLength(int value);
static void show(QString source, const BitTorrent::AddTorrentParams &inParams, QWidget *parent); static void show(const QString &source, const BitTorrent::AddTorrentParams &inParams, QWidget *parent);
static void show(QString source, QWidget *parent); static void show(const QString &source, QWidget *parent);
private slots: private slots:
void showAdvancedSettings(bool show); void showAdvancedSettings(bool show);

10
src/gui/mainwindow.cpp

@ -38,7 +38,6 @@
#include <QMimeData> #include <QMimeData>
#include <QProcess> #include <QProcess>
#include <QPushButton> #include <QPushButton>
#include <QRegularExpression>
#include <QScrollBar> #include <QScrollBar>
#include <QShortcut> #include <QShortcut>
#include <QSplitter> #include <QSplitter>
@ -61,6 +60,7 @@
#include "base/bittorrent/torrenthandle.h" #include "base/bittorrent/torrenthandle.h"
#include "base/global.h" #include "base/global.h"
#include "base/logger.h" #include "base/logger.h"
#include "base/net/downloadmanager.h"
#include "base/preferences.h" #include "base/preferences.h"
#include "base/rss/rss_folder.h" #include "base/rss/rss_folder.h"
#include "base/rss/rss_session.h" #include "base/rss/rss_session.h"
@ -1296,7 +1296,7 @@ void MainWindow::dropEvent(QDropEvent *event)
for (const QString &file : asConst(files)) { for (const QString &file : asConst(files)) {
const bool isTorrentLink = (file.startsWith("magnet:", Qt::CaseInsensitive) const bool isTorrentLink = (file.startsWith("magnet:", Qt::CaseInsensitive)
|| file.endsWith(C_TORRENT_FILE_EXTENSION, Qt::CaseInsensitive) || file.endsWith(C_TORRENT_FILE_EXTENSION, Qt::CaseInsensitive)
|| Utils::Misc::isUrl(file)); || Net::DownloadManager::hasSupportedScheme(file));
if (isTorrentLink) if (isTorrentLink)
torrentFiles << file; torrentFiles << file;
else else
@ -1628,11 +1628,7 @@ void MainWindow::showNotificationBaloon(QString title, QString msg) const
void MainWindow::downloadFromURLList(const QStringList &urlList) void MainWindow::downloadFromURLList(const QStringList &urlList)
{ {
const bool useTorrentAdditionDialog = AddNewTorrentDialog::isEnabled(); const bool useTorrentAdditionDialog = AddNewTorrentDialog::isEnabled();
for (QString url : urlList) { for (const QString &url : urlList) {
if (((url.size() == 40) && !url.contains(QRegularExpression("[^0-9A-Fa-f]")))
|| ((url.size() == 32) && !url.contains(QRegularExpression("[^2-7A-Za-z]"))))
url = "magnet:?xt=urn:btih:" + url;
if (useTorrentAdditionDialog) if (useTorrentAdditionDialog)
AddNewTorrentDialog::show(url, this); AddNewTorrentDialog::show(url, this);
else else

3
src/gui/rss/rsswidget.cpp

@ -48,7 +48,6 @@
#include "base/rss/rss_feed.h" #include "base/rss/rss_feed.h"
#include "base/rss/rss_folder.h" #include "base/rss/rss_folder.h"
#include "base/rss/rss_session.h" #include "base/rss/rss_session.h"
#include "base/utils/misc.h"
#include "addnewtorrentdialog.h" #include "addnewtorrentdialog.h"
#include "articlelistwidget.h" #include "articlelistwidget.h"
#include "autoexpandabledialog.h" #include "autoexpandabledialog.h"
@ -249,7 +248,7 @@ void RSSWidget::on_newFeedButton_clicked()
{ {
// Ask for feed URL // Ask for feed URL
const QString clipText = qApp->clipboard()->text(); const QString clipText = qApp->clipboard()->text();
const QString defaultURL = (Utils::Misc::isUrl(clipText) ? clipText : "http://"); const QString defaultURL = Net::DownloadManager::hasSupportedScheme(clipText) ? clipText : "http://";
bool ok; bool ok;
QString newURL = AutoExpandableDialog::getText( QString newURL = AutoExpandableDialog::getText(

3
src/gui/search/pluginselectdialog.cpp

@ -43,7 +43,6 @@
#include "base/net/downloadhandler.h" #include "base/net/downloadhandler.h"
#include "base/net/downloadmanager.h" #include "base/net/downloadmanager.h"
#include "base/utils/fs.h" #include "base/utils/fs.h"
#include "base/utils/misc.h"
#include "autoexpandabledialog.h" #include "autoexpandabledialog.h"
#include "guiiconprovider.h" #include "guiiconprovider.h"
#include "pluginsourcedialog.h" #include "pluginsourcedialog.h"
@ -337,7 +336,7 @@ void PluginSelectDialog::askForPluginUrl()
bool ok = false; bool ok = false;
QString clipTxt = qApp->clipboard()->text(); QString clipTxt = qApp->clipboard()->text();
QString defaultUrl = "http://"; QString defaultUrl = "http://";
if (Utils::Misc::isUrl(clipTxt) && clipTxt.endsWith(".py")) if (Net::DownloadManager::hasSupportedScheme(clipTxt) && clipTxt.endsWith(".py"))
defaultUrl = clipTxt; defaultUrl = clipTxt;
QString url = AutoExpandableDialog::getText( QString url = AutoExpandableDialog::getText(
this, tr("New search engine plugin URL"), this, tr("New search engine plugin URL"),

Loading…
Cancel
Save