|
|
@ -35,22 +35,23 @@ |
|
|
|
#include <queue> |
|
|
|
#include <queue> |
|
|
|
#include <vector> |
|
|
|
#include <vector> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "base/bittorrent/session.h" |
|
|
|
|
|
|
|
#include "base/bittorrent/torrenthandle.h" |
|
|
|
|
|
|
|
#include "base/bittorrent/torrentinfo.h" |
|
|
|
|
|
|
|
#include "base/bittorrent/trackerentry.h" |
|
|
|
#include "base/iconprovider.h" |
|
|
|
#include "base/iconprovider.h" |
|
|
|
#include "base/logger.h" |
|
|
|
#include "base/logger.h" |
|
|
|
#include "base/utils/misc.h" |
|
|
|
#include "base/net/downloadmanager.h" |
|
|
|
|
|
|
|
#include "base/preferences.h" |
|
|
|
|
|
|
|
#include "base/tristatebool.h" |
|
|
|
#include "base/utils/fs.h" |
|
|
|
#include "base/utils/fs.h" |
|
|
|
|
|
|
|
#include "base/utils/misc.h" |
|
|
|
#include "base/utils/string.h" |
|
|
|
#include "base/utils/string.h" |
|
|
|
#include "base/preferences.h" |
|
|
|
|
|
|
|
#include "base/bittorrent/session.h" |
|
|
|
|
|
|
|
#include "base/bittorrent/trackerentry.h" |
|
|
|
|
|
|
|
#include "base/bittorrent/torrentinfo.h" |
|
|
|
|
|
|
|
#include "base/bittorrent/torrenthandle.h" |
|
|
|
|
|
|
|
#include "base/net/downloadmanager.h" |
|
|
|
|
|
|
|
#include "btjson.h" |
|
|
|
#include "btjson.h" |
|
|
|
#include "prefjson.h" |
|
|
|
|
|
|
|
#include "jsonutils.h" |
|
|
|
#include "jsonutils.h" |
|
|
|
#include "websessiondata.h" |
|
|
|
#include "prefjson.h" |
|
|
|
#include "webapplication.h" |
|
|
|
#include "webapplication.h" |
|
|
|
|
|
|
|
#include "websessiondata.h" |
|
|
|
|
|
|
|
|
|
|
|
static const int API_VERSION = 15; |
|
|
|
static const int API_VERSION = 15; |
|
|
|
static const int API_VERSION_MIN = 15; |
|
|
|
static const int API_VERSION_MIN = 15; |
|
|
@ -67,9 +68,9 @@ const QString MAX_AGE_MONTH = "public, max-age=2592000"; |
|
|
|
|
|
|
|
|
|
|
|
#define ADD_ACTION(scope, action) actions[#scope][#action] = &WebApplication::action_##scope##_##action |
|
|
|
#define ADD_ACTION(scope, action) actions[#scope][#action] = &WebApplication::action_##scope##_##action |
|
|
|
|
|
|
|
|
|
|
|
QMap<QString, QMap<QString, WebApplication::Action> > WebApplication::initializeActions() |
|
|
|
QMap<QString, QMap<QString, WebApplication::Action>> WebApplication::initializeActions() |
|
|
|
{ |
|
|
|
{ |
|
|
|
QMap<QString,QMap<QString, WebApplication::Action> > actions; |
|
|
|
QMap<QString,QMap<QString, WebApplication::Action>> actions; |
|
|
|
|
|
|
|
|
|
|
|
ADD_ACTION(public, webui); |
|
|
|
ADD_ACTION(public, webui); |
|
|
|
ADD_ACTION(public, index); |
|
|
|
ADD_ACTION(public, index); |
|
|
@ -135,6 +136,8 @@ QMap<QString, QMap<QString, WebApplication::Action> > WebApplication::initialize |
|
|
|
return actions; |
|
|
|
return actions; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace |
|
|
|
|
|
|
|
{ |
|
|
|
#define CHECK_URI(ARGS_NUM) \ |
|
|
|
#define CHECK_URI(ARGS_NUM) \ |
|
|
|
if (args_.size() != ARGS_NUM) { \ |
|
|
|
if (args_.size() != ARGS_NUM) { \ |
|
|
|
status(404, "Not Found"); \ |
|
|
|
status(404, "Not Found"); \ |
|
|
@ -154,6 +157,23 @@ QMap<QString, QMap<QString, WebApplication::Action> > WebApplication::initialize |
|
|
|
} \ |
|
|
|
} \ |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool parseBool(const QString &string, const bool defaultValue) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (defaultValue) |
|
|
|
|
|
|
|
return (string.compare("false", Qt::CaseInsensitive) == 0) ? false : true; |
|
|
|
|
|
|
|
return (string.compare("true", Qt::CaseInsensitive) == 0) ? true : false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TriStateBool parseTristatebool(const QString &string) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (string.compare("true", Qt::CaseInsensitive) == 0) |
|
|
|
|
|
|
|
return TriStateBool::True; |
|
|
|
|
|
|
|
if (string.compare("false", Qt::CaseInsensitive) == 0) |
|
|
|
|
|
|
|
return TriStateBool::False; |
|
|
|
|
|
|
|
return TriStateBool::Undefined; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void WebApplication::action_public_index() |
|
|
|
void WebApplication::action_public_index() |
|
|
|
{ |
|
|
|
{ |
|
|
|
QString path; |
|
|
|
QString path; |
|
|
@ -390,45 +410,39 @@ void WebApplication::action_command_shutdown() |
|
|
|
void WebApplication::action_command_download() |
|
|
|
void WebApplication::action_command_download() |
|
|
|
{ |
|
|
|
{ |
|
|
|
CHECK_URI(0); |
|
|
|
CHECK_URI(0); |
|
|
|
QString urls = request().posts["urls"]; |
|
|
|
|
|
|
|
QStringList list = urls.split('\n'); |
|
|
|
const QString urls = request().posts.value("urls"); |
|
|
|
bool skipChecking = request().posts["skip_checking"] == "true"; |
|
|
|
const bool skipChecking = parseBool(request().posts.value("skip_checking"), false); |
|
|
|
bool addPaused = request().posts["paused"] == "true"; |
|
|
|
const TriStateBool addPaused = parseTristatebool(request().posts.value("paused")); |
|
|
|
bool hasRootFolder = request().posts["root_folder"] == "true"; |
|
|
|
const TriStateBool rootFolder = parseTristatebool(request().posts.value("root_folder")); |
|
|
|
QString savepath = request().posts["savepath"]; |
|
|
|
const QString savepath = request().posts.value("savepath").trimmed(); |
|
|
|
QString category = request().posts["category"]; |
|
|
|
const QString category = request().posts.value("category").trimmed(); |
|
|
|
QString cookie = request().posts["cookie"]; |
|
|
|
const QString cookie = request().posts.value("cookie"); |
|
|
|
|
|
|
|
|
|
|
|
QList<QNetworkCookie> cookies; |
|
|
|
QList<QNetworkCookie> cookies; |
|
|
|
if (!cookie.isEmpty()) { |
|
|
|
if (!cookie.isEmpty()) { |
|
|
|
|
|
|
|
const QStringList cookiesStr = cookie.split("; "); |
|
|
|
QStringList cookiesStr = cookie.split("; "); |
|
|
|
for (QString cookieStr : cookiesStr) { |
|
|
|
foreach (QString cookieStr, cookiesStr) { |
|
|
|
|
|
|
|
cookieStr = cookieStr.trimmed(); |
|
|
|
cookieStr = cookieStr.trimmed(); |
|
|
|
int index = cookieStr.indexOf('='); |
|
|
|
int index = cookieStr.indexOf('='); |
|
|
|
if (index > 1) { |
|
|
|
if (index > 1) { |
|
|
|
QByteArray name = cookieStr.left(index).toLatin1(); |
|
|
|
QByteArray name = cookieStr.left(index).toLatin1(); |
|
|
|
QByteArray value = cookieStr.right(cookieStr.length() - index - 1).toLatin1(); |
|
|
|
QByteArray value = cookieStr.right(cookieStr.length() - index - 1).toLatin1(); |
|
|
|
QNetworkCookie c(name, value); |
|
|
|
cookies += QNetworkCookie(name, value); |
|
|
|
cookies << c; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
savepath = savepath.trimmed(); |
|
|
|
|
|
|
|
category = category.trimmed(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BitTorrent::AddTorrentParams params; |
|
|
|
BitTorrent::AddTorrentParams params; |
|
|
|
|
|
|
|
|
|
|
|
// TODO: Check if destination actually exists
|
|
|
|
// TODO: Check if destination actually exists
|
|
|
|
params.skipChecking = skipChecking; |
|
|
|
params.skipChecking = skipChecking; |
|
|
|
|
|
|
|
params.addPaused = addPaused; |
|
|
|
params.addPaused = TriStateBool(addPaused); |
|
|
|
params.createSubfolder = rootFolder; |
|
|
|
params.createSubfolder = TriStateBool(hasRootFolder); |
|
|
|
|
|
|
|
params.savePath = savepath; |
|
|
|
params.savePath = savepath; |
|
|
|
params.category = category; |
|
|
|
params.category = category; |
|
|
|
|
|
|
|
|
|
|
|
bool partialSuccess = false; |
|
|
|
bool partialSuccess = false; |
|
|
|
foreach (QString url, list) { |
|
|
|
for (QString url : urls.split('\n')) { |
|
|
|
url = url.trimmed(); |
|
|
|
url = url.trimmed(); |
|
|
|
if (!url.isEmpty()) { |
|
|
|
if (!url.isEmpty()) { |
|
|
|
Net::DownloadManager::instance()->setCookiesFromUrl(cookies, QUrl::fromEncoded(url.toUtf8())); |
|
|
|
Net::DownloadManager::instance()->setCookiesFromUrl(cookies, QUrl::fromEncoded(url.toUtf8())); |
|
|
@ -444,36 +458,37 @@ void WebApplication::action_command_download() |
|
|
|
|
|
|
|
|
|
|
|
void WebApplication::action_command_upload() |
|
|
|
void WebApplication::action_command_upload() |
|
|
|
{ |
|
|
|
{ |
|
|
|
qDebug() << Q_FUNC_INFO; |
|
|
|
|
|
|
|
CHECK_URI(0); |
|
|
|
CHECK_URI(0); |
|
|
|
bool skipChecking = request().posts["skip_checking"] == "true"; |
|
|
|
|
|
|
|
bool addPaused = request().posts["paused"] == "true"; |
|
|
|
|
|
|
|
bool hasRootFolder = request().posts["root_folder"] == "true"; |
|
|
|
|
|
|
|
QString savepath = request().posts["savepath"]; |
|
|
|
|
|
|
|
QString category = request().posts["category"]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
savepath = savepath.trimmed(); |
|
|
|
const bool skipChecking = parseBool(request().posts.value("skip_checking"), false); |
|
|
|
category = category.trimmed(); |
|
|
|
const TriStateBool addPaused = parseTristatebool(request().posts.value("paused")); |
|
|
|
|
|
|
|
const TriStateBool rootFolder = parseTristatebool(request().posts.value("root_folder")); |
|
|
|
|
|
|
|
const QString savepath = request().posts.value("savepath").trimmed(); |
|
|
|
|
|
|
|
const QString category = request().posts.value("category").trimmed(); |
|
|
|
|
|
|
|
|
|
|
|
foreach(const Http::UploadedFile& torrent, request().files) { |
|
|
|
for (const Http::UploadedFile &torrent : request().files) { |
|
|
|
QString filePath = saveTmpFile(torrent.data); |
|
|
|
const QString filePath = saveTmpFile(torrent.data); |
|
|
|
|
|
|
|
if (filePath.isEmpty()) { |
|
|
|
|
|
|
|
qWarning() << "I/O Error: Could not create temporary file"; |
|
|
|
|
|
|
|
status(500, "Internal Server Error"); |
|
|
|
|
|
|
|
print(QObject::tr("I/O Error: Could not create temporary file."), Http::CONTENT_TYPE_TXT); |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (!filePath.isEmpty()) { |
|
|
|
const BitTorrent::TorrentInfo torrentInfo = BitTorrent::TorrentInfo::loadFromFile(filePath); |
|
|
|
BitTorrent::TorrentInfo torrentInfo = BitTorrent::TorrentInfo::loadFromFile(filePath); |
|
|
|
|
|
|
|
if (!torrentInfo.isValid()) { |
|
|
|
if (!torrentInfo.isValid()) { |
|
|
|
status(415, "Unsupported Media Type"); |
|
|
|
status(415, "Unsupported Media Type"); |
|
|
|
print(QObject::tr("Error: '%1' is not a valid torrent file.\n").arg(torrent.filename), Http::CONTENT_TYPE_TXT); |
|
|
|
print(QObject::tr("Error: '%1' is not a valid torrent file.\n").arg(torrent.filename), Http::CONTENT_TYPE_TXT); |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
else { |
|
|
|
BitTorrent::AddTorrentParams params; |
|
|
|
BitTorrent::AddTorrentParams params; |
|
|
|
|
|
|
|
|
|
|
|
// TODO: Check if destination actually exists
|
|
|
|
// TODO: Check if destination actually exists
|
|
|
|
params.skipChecking = skipChecking; |
|
|
|
params.skipChecking = skipChecking; |
|
|
|
|
|
|
|
params.addPaused = addPaused; |
|
|
|
params.addPaused = TriStateBool(addPaused); |
|
|
|
params.createSubfolder = rootFolder; |
|
|
|
params.createSubfolder = TriStateBool(hasRootFolder); |
|
|
|
|
|
|
|
params.savePath = savepath; |
|
|
|
params.savePath = savepath; |
|
|
|
params.category = category; |
|
|
|
params.category = category; |
|
|
|
|
|
|
|
|
|
|
|
if (!BitTorrent::Session::instance()->addTorrent(torrentInfo, params)) { |
|
|
|
if (!BitTorrent::Session::instance()->addTorrent(torrentInfo, params)) { |
|
|
|
status(500, "Internal Server Error"); |
|
|
|
status(500, "Internal Server Error"); |
|
|
|
print(QObject::tr("Error: Could not add torrent to session."), Http::CONTENT_TYPE_TXT); |
|
|
|
print(QObject::tr("Error: Could not add torrent to session."), Http::CONTENT_TYPE_TXT); |
|
|
@ -482,12 +497,6 @@ void WebApplication::action_command_upload() |
|
|
|
// Clean up
|
|
|
|
// Clean up
|
|
|
|
Utils::Fs::forceRemove(filePath); |
|
|
|
Utils::Fs::forceRemove(filePath); |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
|
|
|
|
qWarning() << "I/O Error: Could not create temporary file"; |
|
|
|
|
|
|
|
status(500, "Internal Server Error"); |
|
|
|
|
|
|
|
print(QObject::tr("I/O Error: Could not create temporary file."), Http::CONTENT_TYPE_TXT); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void WebApplication::action_command_addTrackers() |
|
|
|
void WebApplication::action_command_addTrackers() |
|
|
|