Browse Source

Load torrents that have big metadata file. Closes #1889.

adaptive-webui-19844
sledgehammer999 10 years ago
parent
commit
f35e06540e
  1. 15
      src/addnewtorrentdialog.cpp
  2. 13
      src/misc.cpp
  3. 3
      src/misc.h
  4. 125
      src/qtlibtorrent/qbtsession.cpp
  5. 37
      src/torrentimportdlg.cpp

15
src/addnewtorrentdialog.cpp

@ -191,11 +191,16 @@ bool AddNewTorrentDialog::loadTorrent(const QString& torrent_path, const QString
m_hasMetadata = true; m_hasMetadata = true;
try { try {
m_torrentInfo = new torrent_info(fsutils::toNativePath(m_filePath).toUtf8().data()); std::vector<char> buffer;
m_hash = misc::toQString(m_torrentInfo->info_hash()); lazy_entry entry;
} catch(const std::exception& e) { libtorrent::error_code ec;
MessageBoxRaised::critical(0, tr("Invalid torrent"), tr("Failed to load the torrent: %1").arg(misc::toQStringU(e.what()))); misc::loadBencodedFile(m_filePath, buffer, entry, ec);
return false; m_torrentInfo = new torrent_info(entry);
m_hash = misc::toQString(m_torrentInfo->info_hash());
}
catch(const std::exception& e) {
MessageBoxRaised::critical(0, tr("Invalid torrent"), tr("Failed to load the torrent: %1").arg(misc::toQStringU(e.what())));
return false;
} }
// Prevent showing the dialog if download is already present // Prevent showing the dialog if download is already present

13
src/misc.cpp

@ -77,6 +77,7 @@ const int UNLEN = 256;
#include <libtorrent/sha1_hash.hpp> #include <libtorrent/sha1_hash.hpp>
#endif #endif
#include <libtorrent/escape_string.hpp> #include <libtorrent/escape_string.hpp>
#include <libtorrent/lazy_entry.hpp>
using namespace libtorrent; using namespace libtorrent;
@ -655,6 +656,18 @@ bool misc::slowEquals(const QByteArray &a, const QByteArray &b)
return (diff == 0); return (diff == 0);
} }
void misc::loadBencodedFile(const QString &filename, std::vector<char> &buffer, libtorrent::lazy_entry &entry, libtorrent::error_code &ec)
{
QFile file(filename);
if (!file.open(QIODevice::ReadOnly)) return;
const qint64 content_size = file.bytesAvailable();
if (content_size <= 0) return;
buffer.resize(content_size);
file.read(&buffer[0], content_size);
// bdecode
lazy_bdecode(&buffer[0], &buffer[0] + buffer.size(), entry, ec);
}
namespace { namespace {
// Trick to get a portable sleep() function // Trick to get a portable sleep() function
class SleeperThread : public QThread { class SleeperThread : public QThread {

3
src/misc.h

@ -44,6 +44,7 @@
#endif #endif
#include <libtorrent/version.hpp> #include <libtorrent/version.hpp>
#include <libtorrent/error_code.hpp>
namespace libtorrent { namespace libtorrent {
#if LIBTORRENT_VERSION_NUM < 10000 #if LIBTORRENT_VERSION_NUM < 10000
@ -52,6 +53,7 @@ namespace libtorrent {
#else #else
class sha1_hash; class sha1_hash;
#endif #endif
struct lazy_entry;
} }
const qlonglong MAX_ETA = 8640000; const qlonglong MAX_ETA = 8640000;
@ -109,6 +111,7 @@ namespace misc
// Implements constant-time comparison to protect against timing attacks // Implements constant-time comparison to protect against timing attacks
// Taken from https://crackstation.net/hashing-security.htm // Taken from https://crackstation.net/hashing-security.htm
bool slowEquals(const QByteArray &a, const QByteArray &b); bool slowEquals(const QByteArray &a, const QByteArray &b);
void loadBencodedFile(const QString &filename, std::vector<char> &buffer, libtorrent::lazy_entry &entry, libtorrent::error_code &ec);
void msleep(unsigned long msecs); void msleep(unsigned long msecs);
} }

125
src/qtlibtorrent/qbtsession.cpp

@ -1058,7 +1058,11 @@ QTorrentHandle QBtSession::addTorrent(QString path, bool fromScanDir, QString fr
try { try {
qDebug() << "Loading torrent at" << path; qDebug() << "Loading torrent at" << path;
// Getting torrent file informations // Getting torrent file informations
t = new torrent_info(fsutils::toNativePath(path).toUtf8().constData()); std::vector<char> buffer;
lazy_entry entry;
libtorrent::error_code ec;
misc::loadBencodedFile(path, buffer, entry, ec);
t = new torrent_info(entry);
if (!t->is_valid()) if (!t->is_valid())
throw std::exception(); throw std::exception();
} catch(std::exception& e) { } catch(std::exception& e) {
@ -1508,17 +1512,10 @@ void QBtSession::loadSessionState() {
fsutils::forceRemove(state_path); fsutils::forceRemove(state_path);
return; return;
} }
QFile state_file(state_path);
if (!state_file.open(QIODevice::ReadOnly)) return;
std::vector<char> in; std::vector<char> in;
const qint64 content_size = state_file.bytesAvailable();
if (content_size <= 0) return;
in.resize(content_size);
state_file.read(&in[0], content_size);
// bdecode
lazy_entry e; lazy_entry e;
libtorrent::error_code ec; libtorrent::error_code ec;
lazy_bdecode(&in[0], &in[0] + in.size(), e, ec); misc::loadBencodedFile(state_path, in, e, ec);
if (!ec) if (!ec)
s->load_state(e); s->load_state(e);
} }
@ -1752,28 +1749,33 @@ bool QBtSession::isFilePreviewPossible(const QString &hash) const {
return false; return false;
} }
void QBtSession::addTorrentsFromScanFolder(QStringList &pathList) { void QBtSession::addTorrentsFromScanFolder(QStringList &pathList)
foreach (const QString &file, pathList) { {
qDebug("File %s added", qPrintable(file)); foreach (const QString &file, pathList) {
if (file.endsWith(".magnet")) { qDebug("File %s added", qPrintable(file));
QFile f(file); if (file.endsWith(".magnet")) {
if (!f.open(QIODevice::ReadOnly)) { QFile f(file);
qDebug("Failed to open magnet file: %s", qPrintable(f.errorString())); if (!f.open(QIODevice::ReadOnly)) {
} else { qDebug("Failed to open magnet file: %s", qPrintable(f.errorString()));
const QString link = QString::fromLocal8Bit(f.readAll()); } else {
addMagnetUri(link, false, true, file); const QString link = QString::fromLocal8Bit(f.readAll());
f.remove(); addMagnetUri(link, false, true, file);
} f.remove();
continue; }
} continue;
try { }
torrent_info t(fsutils::toNativePath(file).toUtf8().constData()); try {
if (t.is_valid()) std::vector<char> buffer;
addTorrent(file, true); lazy_entry entry;
} catch(std::exception&) { libtorrent::error_code ec;
qDebug("Ignoring incomplete torrent file: %s", qPrintable(file)); misc::loadBencodedFile(file, buffer, entry, ec);
torrent_info t(entry);
if (t.is_valid())
addTorrent(file, true);
} catch(std::exception&) {
qDebug("Ignoring incomplete torrent file: %s", qPrintable(file));
}
} }
}
} }
void QBtSession::setDefaultSavePath(const QString &savepath) { void QBtSession::setDefaultSavePath(const QString &savepath) {
@ -2049,24 +2051,30 @@ void QBtSession::disableIPFilter() {
filterPath = ""; filterPath = "";
} }
void QBtSession::recursiveTorrentDownload(const QTorrentHandle &h) { void QBtSession::recursiveTorrentDownload(const QTorrentHandle &h)
try { {
for (int i=0; i<h.num_files(); ++i) { try {
const QString torrent_relpath = h.filepath_at(i); for (int i=0; i<h.num_files(); ++i) {
if (torrent_relpath.endsWith(".torrent")) { const QString torrent_relpath = h.filepath_at(i);
addConsoleMessage(tr("Recursive download of file %1 embedded in torrent %2", "Recursive download of test.torrent embedded in torrent test2").arg(fsutils::toNativePath(torrent_relpath)).arg(h.name())); if (torrent_relpath.endsWith(".torrent")) {
const QString torrent_fullpath = h.save_path()+"/"+torrent_relpath; addConsoleMessage(tr("Recursive download of file %1 embedded in torrent %2", "Recursive download of test.torrent embedded in torrent test2").arg(fsutils::toNativePath(torrent_relpath)).arg(h.name()));
const QString torrent_fullpath = h.save_path()+"/"+torrent_relpath;
boost::intrusive_ptr<torrent_info> t = new torrent_info(fsutils::toNativePath(torrent_fullpath).toUtf8().constData());
const QString sub_hash = misc::toQString(t->info_hash()); std::vector<char> buffer;
// Passing the save path along to the sub torrent file lazy_entry entry;
TorrentTempData::setSavePath(sub_hash, h.save_path()); libtorrent::error_code ec;
addTorrent(torrent_fullpath); misc::loadBencodedFile(torrent_fullpath, buffer, entry, ec);
} boost::intrusive_ptr<torrent_info> t = new torrent_info(entry);
const QString sub_hash = misc::toQString(t->info_hash());
// Passing the save path along to the sub torrent file
TorrentTempData::setSavePath(sub_hash, h.save_path());
addTorrent(torrent_fullpath);
}
}
}
catch(std::exception&) {
qDebug("Caught error loading torrent");
} }
} catch(std::exception&) {
qDebug("Caught error loading torrent");
}
} }
void QBtSession::autoRunExternalProgram(const QTorrentHandle &h) { void QBtSession::autoRunExternalProgram(const QTorrentHandle &h) {
@ -2218,15 +2226,20 @@ void QBtSession::handleTorrentFinishedAlert(libtorrent::torrent_finished_alert*
const QString torrent_fullpath = h.save_path()+"/"+torrent_relpath; const QString torrent_fullpath = h.save_path()+"/"+torrent_relpath;
qDebug("Full subtorrent path is %s", qPrintable(torrent_fullpath)); qDebug("Full subtorrent path is %s", qPrintable(torrent_fullpath));
try { try {
boost::intrusive_ptr<torrent_info> t = new torrent_info(fsutils::toNativePath(torrent_fullpath).toUtf8().constData()); std::vector<char> buffer;
if (t->is_valid()) { lazy_entry entry;
qDebug("emitting recursiveTorrentDownloadPossible()"); libtorrent::error_code ec;
emit recursiveTorrentDownloadPossible(h); misc::loadBencodedFile(torrent_fullpath, buffer, entry, ec);
break; boost::intrusive_ptr<torrent_info> t = new torrent_info(entry);
} if (t->is_valid()) {
} catch(std::exception&) { qDebug("emitting recursiveTorrentDownloadPossible()");
qDebug("Caught error loading torrent"); emit recursiveTorrentDownloadPossible(h);
addConsoleMessage(tr("Unable to decode %1 torrent file.").arg(fsutils::toNativePath(torrent_fullpath)), QString::fromUtf8("red")); break;
}
}
catch(std::exception&) {
qDebug("Caught error loading torrent");
addConsoleMessage(tr("Unable to decode %1 torrent file.").arg(fsutils::toNativePath(torrent_fullpath)), QString::fromUtf8("red"));
} }
} }
} }

37
src/torrentimportdlg.cpp

@ -215,22 +215,27 @@ void TorrentImportDlg::importTorrent()
void TorrentImportDlg::loadTorrent(const QString &torrent_path) void TorrentImportDlg::loadTorrent(const QString &torrent_path)
{ {
// Load the torrent file // Load the torrent file
try { try {
t = new torrent_info(fsutils::toNativePath(torrent_path).toUtf8().constData()); std::vector<char> buffer;
if (!t->is_valid() || t->num_files() == 0) lazy_entry entry;
throw std::exception(); libtorrent::error_code ec;
} catch(std::exception&) { misc::loadBencodedFile(torrent_path, buffer, entry, ec);
ui->browseContentBtn->setEnabled(false); t = new torrent_info(entry);
ui->lineTorrent->clear(); if (!t->is_valid() || t->num_files() == 0)
QMessageBox::warning(this, tr("Invalid torrent file"), tr("This is not a valid torrent file.")); throw std::exception();
return; }
} catch(std::exception&) {
// Update display ui->browseContentBtn->setEnabled(false);
ui->lineTorrent->setText(fsutils::toNativePath(torrent_path)); ui->lineTorrent->clear();
ui->browseContentBtn->setEnabled(true); QMessageBox::warning(this, tr("Invalid torrent file"), tr("This is not a valid torrent file."));
// Load the file names return;
initializeFilesPath(); }
// Update display
ui->lineTorrent->setText(fsutils::toNativePath(torrent_path));
ui->browseContentBtn->setEnabled(true);
// Load the file names
initializeFilesPath();
} }
void TorrentImportDlg::initializeFilesPath() void TorrentImportDlg::initializeFilesPath()

Loading…
Cancel
Save