Some work about adaptive color scheme for Web UI (PR #19901)
http://[316:c51a:62a3:8b9::4]/d4708/qBittorrent/src/branch/adaptive-webui
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
682 lines
23 KiB
682 lines
23 KiB
/* |
|
* Bittorrent Client using Qt4 and libtorrent. |
|
* Copyright (C) 2006 Ishan Arora and Christophe Dumez |
|
* |
|
* This program is free software; you can redistribute it and/or |
|
* modify it under the terms of the GNU General Public License |
|
* as published by the Free Software Foundation; either version 2 |
|
* of the License, or (at your option) any later version. |
|
* |
|
* This program is distributed in the hope that it will be useful, |
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
* GNU General Public License for more details. |
|
* |
|
* You should have received a copy of the GNU General Public License |
|
* along with this program; if not, write to the Free Software |
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
* |
|
* In addition, as a special exception, the copyright holders give permission to |
|
* link this program with the OpenSSL project's "OpenSSL" library (or with |
|
* modified versions of it that use the same license as the "OpenSSL" library), |
|
* and distribute the linked executables. You must obey the GNU General Public |
|
* License in all respects for all of the code used other than "OpenSSL". If you |
|
* modify file(s), you may extend this exception to your version of the file(s), |
|
* but you are not obligated to do so. If you do not wish to do so, delete this |
|
* exception statement from your version. |
|
* |
|
* Contact : chris@qbittorrent.org |
|
*/ |
|
|
|
|
|
#include "httpconnection.h" |
|
#include "httpserver.h" |
|
#include "httprequestheader.h" |
|
#include "httpresponseheader.h" |
|
#include "preferences.h" |
|
#include "btjson.h" |
|
#include "prefjson.h" |
|
#include "qbtsession.h" |
|
#include "misc.h" |
|
#include "fs_utils.h" |
|
#ifndef DISABLE_GUI |
|
#include "iconprovider.h" |
|
#endif |
|
#include <QTcpSocket> |
|
#include <QDateTime> |
|
#include <QStringList> |
|
#include <QFile> |
|
#include <QDebug> |
|
#include <QRegExp> |
|
#include <QTemporaryFile> |
|
#include <queue> |
|
#include <vector> |
|
|
|
using namespace libtorrent; |
|
|
|
HttpConnection::HttpConnection(QTcpSocket *socket, HttpServer *parent) |
|
: QObject(parent), m_socket(socket), m_httpserver(parent) |
|
{ |
|
m_socket->setParent(this); |
|
connect(m_socket, SIGNAL(readyRead()), SLOT(read())); |
|
connect(m_socket, SIGNAL(disconnected()), SLOT(deleteLater())); |
|
} |
|
|
|
HttpConnection::~HttpConnection() { |
|
delete m_socket; |
|
} |
|
|
|
void HttpConnection::processDownloadedFile(const QString &url, |
|
const QString &file_path) { |
|
qDebug("URL %s successfully downloaded !", qPrintable(url)); |
|
emit torrentReadyToBeDownloaded(file_path, false, url, false); |
|
} |
|
|
|
void HttpConnection::handleDownloadFailure(const QString& url, |
|
const QString& reason) { |
|
std::cerr << "Could not download " << qPrintable(url) << ", reason: " |
|
<< qPrintable(reason) << std::endl; |
|
} |
|
|
|
void HttpConnection::read() |
|
{ |
|
m_receivedData.append(m_socket->readAll()); |
|
|
|
// Parse HTTP request header |
|
const int header_end = m_receivedData.indexOf("\r\n\r\n"); |
|
if (header_end < 0) { |
|
qDebug() << "Partial request: \n" << m_receivedData; |
|
// Partial request waiting for the rest |
|
return; |
|
} |
|
|
|
const QByteArray header = m_receivedData.left(header_end); |
|
m_parser.writeHeader(header); |
|
if (m_parser.isError()) { |
|
qWarning() << Q_FUNC_INFO << "header parsing error"; |
|
m_receivedData.clear(); |
|
m_generator.setStatusLine(400, "Bad Request"); |
|
m_generator.setContentEncoding(m_parser.acceptsEncoding()); |
|
write(); |
|
return; |
|
} |
|
|
|
// Parse HTTP request message |
|
if (m_parser.header().hasContentLength()) { |
|
const int expected_length = m_parser.header().contentLength(); |
|
QByteArray message = m_receivedData.mid(header_end + 4, expected_length); |
|
|
|
if (expected_length > 10000000 /* ~10MB */) { |
|
qWarning() << "Bad request: message too long"; |
|
m_generator.setStatusLine(400, "Bad Request"); |
|
m_generator.setContentEncoding(m_parser.acceptsEncoding()); |
|
m_receivedData.clear(); |
|
write(); |
|
return; |
|
} |
|
|
|
if (message.length() < expected_length) { |
|
// Message too short, waiting for the rest |
|
qDebug() << "Partial message:\n" << message; |
|
return; |
|
} |
|
|
|
m_parser.writeMessage(message); |
|
m_receivedData = m_receivedData.mid(header_end + 4 + expected_length); |
|
} else { |
|
m_receivedData.clear(); |
|
} |
|
|
|
if (m_parser.isError()) { |
|
qWarning() << Q_FUNC_INFO << "message parsing error"; |
|
m_generator.setStatusLine(400, "Bad Request"); |
|
m_generator.setContentEncoding(m_parser.acceptsEncoding()); |
|
write(); |
|
} else { |
|
respond(); |
|
} |
|
} |
|
|
|
void HttpConnection::write() |
|
{ |
|
m_socket->write(m_generator.toByteArray()); |
|
m_socket->disconnectFromHost(); |
|
} |
|
|
|
void HttpConnection::translateDocument(QString& data) { |
|
static QRegExp regex(QString::fromUtf8("_\\(([\\w\\s?!:\\/\\(\\),%µ&\\-\\.]+)\\)")); |
|
static QRegExp mnemonic("\\(?&([a-zA-Z]?\\))?"); |
|
const std::string contexts[] = {"TransferListFiltersWidget", "TransferListWidget", |
|
"PropertiesWidget", "MainWindow", "HttpServer", |
|
"confirmDeletionDlg", "TrackerList", "TorrentFilesModel", |
|
"options_imp", "Preferences", "TrackersAdditionDlg", |
|
"ScanFoldersModel", "PropTabBar", "TorrentModel", |
|
"downloadFromURL", "misc"}; |
|
const size_t context_count = sizeof(contexts)/sizeof(contexts[0]); |
|
int i = 0; |
|
bool found = true; |
|
|
|
const QString locale = Preferences::instance()->getLocale(); |
|
bool isTranslationNeeded = !locale.startsWith("en") || locale.startsWith("en_AU") || locale.startsWith("en_GB"); |
|
|
|
while(i < data.size() && found) { |
|
i = regex.indexIn(data, i); |
|
if (i >= 0) { |
|
//qDebug("Found translatable string: %s", regex.cap(1).toUtf8().data()); |
|
QByteArray word = regex.cap(1).toUtf8(); |
|
|
|
QString translation = word; |
|
if (isTranslationNeeded) { |
|
size_t context_index = 0; |
|
while(context_index < context_count && translation == word) { |
|
#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0)) |
|
translation = qApp->translate(contexts[context_index].c_str(), word.constData(), 0, QCoreApplication::UnicodeUTF8, 1); |
|
#else |
|
translation = qApp->translate(contexts[context_index].c_str(), word.constData(), 0, 1); |
|
#endif |
|
++context_index; |
|
} |
|
} |
|
// Remove keyboard shortcuts |
|
translation.replace(mnemonic, ""); |
|
|
|
data.replace(i, regex.matchedLength(), translation); |
|
i += translation.length(); |
|
} else { |
|
found = false; // no more translatable strings |
|
} |
|
} |
|
} |
|
|
|
void HttpConnection::respond() { |
|
if ((m_socket->peerAddress() != QHostAddress::LocalHost |
|
&& m_socket->peerAddress() != QHostAddress::LocalHostIPv6) |
|
|| m_httpserver->isLocalAuthEnabled()) { |
|
// Authentication |
|
const QString peer_ip = m_socket->peerAddress().toString(); |
|
const int nb_fail = m_httpserver->NbFailedAttemptsForIp(peer_ip); |
|
if (nb_fail >= MAX_AUTH_FAILED_ATTEMPTS) { |
|
m_generator.setStatusLine(403, "Forbidden"); |
|
m_generator.setMessage(tr("Your IP address has been banned after too many failed authentication attempts.")); |
|
m_generator.setContentEncoding(m_parser.acceptsEncoding()); |
|
write(); |
|
return; |
|
} |
|
QString auth = m_parser.header().value("Authorization"); |
|
if (auth.isEmpty()) { |
|
// Return unauthorized header |
|
qDebug("Auth is Empty..."); |
|
m_generator.setStatusLine(401, "Unauthorized"); |
|
m_generator.setValue("WWW-Authenticate", "Digest realm=\""+QString(QBT_REALM)+"\", nonce=\""+m_httpserver->generateNonce()+"\", opaque=\""+m_httpserver->generateNonce()+"\", stale=\"false\", algorithm=\"MD5\", qop=\"auth\""); |
|
m_generator.setContentEncoding(m_parser.acceptsEncoding()); |
|
write(); |
|
return; |
|
} |
|
//qDebug("Auth: %s", qPrintable(auth.split(" ").first())); |
|
if (QString::compare(auth.split(" ").first(), "Digest", Qt::CaseInsensitive) != 0 |
|
|| !m_httpserver->isAuthorized(auth.toUtf8(), m_parser.header().method())) { |
|
// Update failed attempt counter |
|
m_httpserver->increaseNbFailedAttemptsForIp(peer_ip); |
|
qDebug("client IP: %s (%d failed attempts)", qPrintable(peer_ip), nb_fail); |
|
// Return unauthorized header |
|
m_generator.setStatusLine(401, "Unauthorized"); |
|
m_generator.setValue("WWW-Authenticate", "Digest realm=\""+QString(QBT_REALM)+"\", nonce=\""+m_httpserver->generateNonce()+"\", opaque=\""+m_httpserver->generateNonce()+"\", stale=\"false\", algorithm=\"MD5\", qop=\"auth\""); |
|
m_generator.setContentEncoding(m_parser.acceptsEncoding()); |
|
write(); |
|
return; |
|
} |
|
// Client successfully authenticated, reset number of failed attempts |
|
m_httpserver->resetNbFailedAttemptsForIp(peer_ip); |
|
} |
|
QString url = m_parser.url(); |
|
// Favicon |
|
if (url.endsWith("favicon.ico")) { |
|
qDebug("Returning favicon"); |
|
QFile favicon(":/Icons/skin/qbittorrent16.png"); |
|
if (favicon.open(QIODevice::ReadOnly)) { |
|
const QByteArray data = favicon.readAll(); |
|
favicon.close(); |
|
m_generator.setStatusLine(200, "OK"); |
|
m_generator.setContentTypeByExt("png"); |
|
m_generator.setMessage(data); |
|
m_generator.setContentEncoding(m_parser.acceptsEncoding()); |
|
write(); |
|
} else { |
|
respondNotFound(); |
|
} |
|
return; |
|
} |
|
|
|
QStringList list = url.split('/', QString::SkipEmptyParts); |
|
if (list.contains(".") || list.contains("..")) { |
|
respondNotFound(); |
|
return; |
|
} |
|
|
|
if (list.isEmpty()) |
|
list.append("index.html"); |
|
|
|
if (list.size() >= 2) { |
|
if (list[0] == "json") { |
|
if (list[1] == "torrents") { |
|
respondTorrentsJson(); |
|
return; |
|
} |
|
if (list.size() > 2) { |
|
if (list[1] == "propertiesGeneral") { |
|
const QString& hash = list[2]; |
|
respondGenPropertiesJson(hash); |
|
return; |
|
} |
|
if (list[1] == "propertiesTrackers") { |
|
const QString& hash = list[2]; |
|
respondTrackersPropertiesJson(hash); |
|
return; |
|
} |
|
if (list[1] == "propertiesFiles") { |
|
const QString& hash = list[2]; |
|
respondFilesPropertiesJson(hash); |
|
return; |
|
} |
|
} else { |
|
if (list[1] == "preferences") { |
|
respondPreferencesJson(); |
|
return; |
|
} else { |
|
if (list[1] == "transferInfo") { |
|
respondGlobalTransferInfoJson(); |
|
return; |
|
} |
|
} |
|
} |
|
} |
|
if (list[0] == "command") { |
|
const QString& command = list[1]; |
|
if (command == "shutdown") { |
|
qDebug() << "Shutdown request from Web UI"; |
|
// Special case handling for shutdown, we |
|
// need to reply to the Web UI before |
|
// actually shutting down. |
|
m_generator.setStatusLine(200, "OK"); |
|
m_generator.setContentEncoding(m_parser.acceptsEncoding()); |
|
write(); |
|
qApp->processEvents(); |
|
// Exit application |
|
qApp->exit(); |
|
} else { |
|
respondCommand(command); |
|
m_generator.setStatusLine(200, "OK"); |
|
m_generator.setContentEncoding(m_parser.acceptsEncoding()); |
|
write(); |
|
} |
|
return; |
|
} |
|
} |
|
|
|
// Icons from theme |
|
//qDebug() << "list[0]" << list[0]; |
|
if (list[0] == "theme" && list.size() == 2) { |
|
#ifdef DISABLE_GUI |
|
url = ":/Icons/oxygen/"+list[1]+".png"; |
|
#else |
|
url = IconProvider::instance()->getIconPath(list[1]); |
|
#endif |
|
qDebug() << "There icon:" << url; |
|
} else { |
|
if (list[0] == "images") { |
|
list[0] = "Icons"; |
|
} else { |
|
if (list.last().endsWith(".html")) |
|
list.prepend("html"); |
|
list.prepend("webui"); |
|
} |
|
url = ":/" + list.join("/"); |
|
} |
|
QFile file(url); |
|
if (!file.open(QIODevice::ReadOnly)) { |
|
qDebug("File %s was not found!", qPrintable(url)); |
|
respondNotFound(); |
|
return; |
|
} |
|
QString ext = list.last(); |
|
int index = ext.lastIndexOf('.') + 1; |
|
if (index > 0) |
|
ext.remove(0, index); |
|
else |
|
ext.clear(); |
|
QByteArray data = file.readAll(); |
|
file.close(); |
|
|
|
// Translate the page |
|
if (ext == "html" || (ext == "js" && !list.last().startsWith("excanvas"))) { |
|
QString dataStr = QString::fromUtf8(data.constData()); |
|
translateDocument(dataStr); |
|
if (url.endsWith("about.html")) { |
|
dataStr.replace("${VERSION}", VERSION); |
|
} |
|
data = dataStr.toUtf8(); |
|
} |
|
m_generator.setStatusLine(200, "OK"); |
|
m_generator.setContentTypeByExt(ext); |
|
m_generator.setMessage(data); |
|
m_generator.setContentEncoding(m_parser.acceptsEncoding()); |
|
write(); |
|
} |
|
|
|
void HttpConnection::respondNotFound() { |
|
m_generator.setStatusLine(404, "File not found"); |
|
m_generator.setContentEncoding(m_parser.acceptsEncoding()); |
|
write(); |
|
} |
|
|
|
void HttpConnection::respondTorrentsJson() { |
|
m_generator.setStatusLine(200, "OK"); |
|
m_generator.setContentTypeByExt("js"); |
|
m_generator.setMessage(btjson::getTorrents()); |
|
m_generator.setContentEncoding(m_parser.acceptsEncoding()); |
|
write(); |
|
} |
|
|
|
void HttpConnection::respondGenPropertiesJson(const QString& hash) { |
|
m_generator.setStatusLine(200, "OK"); |
|
m_generator.setContentTypeByExt("js"); |
|
m_generator.setMessage(btjson::getPropertiesForTorrent(hash)); |
|
m_generator.setContentEncoding(m_parser.acceptsEncoding()); |
|
write(); |
|
} |
|
|
|
void HttpConnection::respondTrackersPropertiesJson(const QString& hash) { |
|
m_generator.setStatusLine(200, "OK"); |
|
m_generator.setContentTypeByExt("js"); |
|
m_generator.setMessage(btjson::getTrackersForTorrent(hash)); |
|
m_generator.setContentEncoding(m_parser.acceptsEncoding()); |
|
write(); |
|
} |
|
|
|
void HttpConnection::respondFilesPropertiesJson(const QString& hash) { |
|
m_generator.setStatusLine(200, "OK"); |
|
m_generator.setContentTypeByExt("js"); |
|
m_generator.setMessage(btjson::getFilesForTorrent(hash)); |
|
m_generator.setContentEncoding(m_parser.acceptsEncoding()); |
|
write(); |
|
} |
|
|
|
void HttpConnection::respondPreferencesJson() { |
|
m_generator.setStatusLine(200, "OK"); |
|
m_generator.setContentTypeByExt("js"); |
|
m_generator.setMessage(prefjson::getPreferences()); |
|
m_generator.setContentEncoding(m_parser.acceptsEncoding()); |
|
write(); |
|
} |
|
|
|
void HttpConnection::respondGlobalTransferInfoJson() { |
|
m_generator.setStatusLine(200, "OK"); |
|
m_generator.setContentTypeByExt("js"); |
|
m_generator.setMessage(btjson::getTransferInfo()); |
|
m_generator.setContentEncoding(m_parser.acceptsEncoding()); |
|
write(); |
|
} |
|
|
|
void HttpConnection::respondCommand(const QString& command) { |
|
qDebug() << Q_FUNC_INFO << command; |
|
if (command == "download") { |
|
QString urls = m_parser.post("urls"); |
|
QStringList list = urls.split('\n'); |
|
foreach (QString url, list) { |
|
url = url.trimmed(); |
|
if (!url.isEmpty()) { |
|
if (url.startsWith("bc://bt/", Qt::CaseInsensitive)) { |
|
qDebug("Converting bc link to magnet link"); |
|
url = misc::bcLinkToMagnet(url); |
|
} |
|
if (url.startsWith("magnet:", Qt::CaseInsensitive)) { |
|
emit MagnetReadyToBeDownloaded(url); |
|
} else { |
|
qDebug("Downloading url: %s", qPrintable(url)); |
|
emit UrlReadyToBeDownloaded(url); |
|
} |
|
} |
|
} |
|
return; |
|
} |
|
|
|
if (command == "addTrackers") { |
|
QString hash = m_parser.post("hash"); |
|
if (!hash.isEmpty()) { |
|
QTorrentHandle h = QBtSession::instance()->getTorrentHandle(hash); |
|
if (h.is_valid() && h.has_metadata()) { |
|
QString urls = m_parser.post("urls"); |
|
QStringList list = urls.split('\n'); |
|
foreach (const QString& url, list) { |
|
announce_entry e(url.toStdString()); |
|
h.add_tracker(e); |
|
} |
|
} |
|
} |
|
return; |
|
} |
|
if (command == "upload") { |
|
qDebug() << Q_FUNC_INFO << "upload"; |
|
const QList<QByteArray>& torrents = m_parser.torrents(); |
|
foreach(const QByteArray& torrentContent, torrents) { |
|
// Get a unique filename |
|
QTemporaryFile *tmpfile = new QTemporaryFile(QDir::temp().absoluteFilePath("qBT-XXXXXX.torrent")); |
|
tmpfile->setAutoRemove(false); |
|
if (tmpfile->open()) { |
|
QString filePath = tmpfile->fileName(); |
|
tmpfile->write(torrentContent); |
|
tmpfile->close(); |
|
// XXX: tmpfile needs to be deleted on Windows before using the file |
|
// or it will complain that the file is used by another process. |
|
delete tmpfile; |
|
emit torrentReadyToBeDownloaded(filePath, false, QString(), false); |
|
// Clean up |
|
fsutils::forceRemove(filePath); |
|
} else { |
|
std::cerr << "I/O Error: Could not create temporary file" << std::endl; |
|
delete tmpfile; |
|
return; |
|
} |
|
} |
|
// Prepare response |
|
m_generator.setStatusLine(200, "OK"); |
|
m_generator.setContentTypeByExt("html"); |
|
m_generator.setMessage(QString("<script type=\"text/javascript\">window.parent.hideAll();</script>")); |
|
m_generator.setContentEncoding(m_parser.acceptsEncoding()); |
|
write(); |
|
return; |
|
} |
|
if (command == "resumeall") { |
|
emit resumeAllTorrents(); |
|
return; |
|
} |
|
if (command == "pauseall") { |
|
emit pauseAllTorrents(); |
|
return; |
|
} |
|
if (command == "resume") { |
|
emit resumeTorrent(m_parser.post("hash")); |
|
return; |
|
} |
|
if (command == "setPreferences") { |
|
prefjson::setPreferences(m_parser.post("json")); |
|
return; |
|
} |
|
if (command == "setFilePrio") { |
|
QString hash = m_parser.post("hash"); |
|
int file_id = m_parser.post("id").toInt(); |
|
int priority = m_parser.post("priority").toInt(); |
|
QTorrentHandle h = QBtSession::instance()->getTorrentHandle(hash); |
|
if (h.is_valid() && h.has_metadata()) { |
|
h.file_priority(file_id, priority); |
|
} |
|
return; |
|
} |
|
if (command == "getGlobalUpLimit") { |
|
m_generator.setStatusLine(200, "OK"); |
|
m_generator.setContentTypeByExt("html"); |
|
m_generator.setMessage(QByteArray::number(QBtSession::instance()->getSession()->settings().upload_rate_limit)); |
|
m_generator.setContentEncoding(m_parser.acceptsEncoding()); |
|
write(); |
|
return; |
|
} |
|
if (command == "getGlobalDlLimit") { |
|
m_generator.setStatusLine(200, "OK"); |
|
m_generator.setContentTypeByExt("html"); |
|
m_generator.setMessage(QByteArray::number(QBtSession::instance()->getSession()->settings().download_rate_limit)); |
|
m_generator.setContentEncoding(m_parser.acceptsEncoding()); |
|
write(); |
|
return; |
|
} |
|
if (command == "getTorrentUpLimit") { |
|
QString hash = m_parser.post("hash"); |
|
QTorrentHandle h = QBtSession::instance()->getTorrentHandle(hash); |
|
if (h.is_valid()) { |
|
m_generator.setStatusLine(200, "OK"); |
|
m_generator.setContentTypeByExt("html"); |
|
m_generator.setMessage(QByteArray::number(h.upload_limit())); |
|
m_generator.setContentEncoding(m_parser.acceptsEncoding()); |
|
write(); |
|
} |
|
return; |
|
} |
|
if (command == "getTorrentDlLimit") { |
|
QString hash = m_parser.post("hash"); |
|
QTorrentHandle h = QBtSession::instance()->getTorrentHandle(hash); |
|
if (h.is_valid()) { |
|
m_generator.setStatusLine(200, "OK"); |
|
m_generator.setContentTypeByExt("html"); |
|
m_generator.setMessage(QByteArray::number(h.download_limit())); |
|
m_generator.setContentEncoding(m_parser.acceptsEncoding()); |
|
write(); |
|
} |
|
return; |
|
} |
|
if (command == "setTorrentUpLimit") { |
|
QString hash = m_parser.post("hash"); |
|
qlonglong limit = m_parser.post("limit").toLongLong(); |
|
if (limit == 0) limit = -1; |
|
QTorrentHandle h = QBtSession::instance()->getTorrentHandle(hash); |
|
if (h.is_valid()) { |
|
h.set_upload_limit(limit); |
|
} |
|
return; |
|
} |
|
if (command == "setTorrentDlLimit") { |
|
QString hash = m_parser.post("hash"); |
|
qlonglong limit = m_parser.post("limit").toLongLong(); |
|
if (limit == 0) limit = -1; |
|
QTorrentHandle h = QBtSession::instance()->getTorrentHandle(hash); |
|
if (h.is_valid()) { |
|
h.set_download_limit(limit); |
|
} |
|
return; |
|
} |
|
if (command == "setGlobalUpLimit") { |
|
qlonglong limit = m_parser.post("limit").toLongLong(); |
|
if (limit == 0) limit = -1; |
|
QBtSession::instance()->setUploadRateLimit(limit); |
|
Preferences::instance()->setGlobalUploadLimit(limit/1024.); |
|
return; |
|
} |
|
if (command == "setGlobalDlLimit") { |
|
qlonglong limit = m_parser.post("limit").toLongLong(); |
|
if (limit == 0) limit = -1; |
|
QBtSession::instance()->setDownloadRateLimit(limit); |
|
Preferences::instance()->setGlobalDownloadLimit(limit/1024.); |
|
return; |
|
} |
|
if (command == "pause") { |
|
emit pauseTorrent(m_parser.post("hash")); |
|
return; |
|
} |
|
if (command == "delete") { |
|
QStringList hashes = m_parser.post("hashes").split("|"); |
|
foreach (const QString &hash, hashes) { |
|
emit deleteTorrent(hash, false); |
|
} |
|
return; |
|
} |
|
if (command == "deletePerm") { |
|
QStringList hashes = m_parser.post("hashes").split("|"); |
|
foreach (const QString &hash, hashes) { |
|
emit deleteTorrent(hash, true); |
|
} |
|
return; |
|
} |
|
if (command == "increasePrio") { |
|
increaseTorrentsPriority(m_parser.post("hashes").split("|")); |
|
return; |
|
} |
|
if (command == "decreasePrio") { |
|
decreaseTorrentsPriority(m_parser.post("hashes").split("|")); |
|
return; |
|
} |
|
if (command == "topPrio") { |
|
foreach (const QString &hash, m_parser.post("hashes").split("|")) { |
|
QTorrentHandle h = QBtSession::instance()->getTorrentHandle(hash); |
|
if (h.is_valid()) h.queue_position_top(); |
|
} |
|
return; |
|
} |
|
if (command == "bottomPrio") { |
|
foreach (const QString &hash, m_parser.post("hashes").split("|")) { |
|
QTorrentHandle h = QBtSession::instance()->getTorrentHandle(hash); |
|
if (h.is_valid()) h.queue_position_bottom(); |
|
} |
|
return; |
|
} |
|
if (command == "recheck") { |
|
QBtSession::instance()->recheckTorrent(m_parser.post("hash")); |
|
return; |
|
} |
|
} |
|
|
|
void HttpConnection::decreaseTorrentsPriority(const QStringList &hashes) { |
|
qDebug() << Q_FUNC_INFO << hashes; |
|
std::priority_queue<QPair<int, QTorrentHandle>, |
|
std::vector<QPair<int, QTorrentHandle> >, |
|
std::less<QPair<int, QTorrentHandle> > > torrent_queue; |
|
// Sort torrents by priority |
|
foreach (const QString &hash, hashes) { |
|
try { |
|
QTorrentHandle h = QBtSession::instance()->getTorrentHandle(hash); |
|
if (!h.is_seed()) { |
|
torrent_queue.push(qMakePair(h.queue_position(), h)); |
|
} |
|
}catch(invalid_handle&) {} |
|
} |
|
// Decrease torrents priority (starting with the ones with lowest priority) |
|
while(!torrent_queue.empty()) { |
|
QTorrentHandle h = torrent_queue.top().second; |
|
try { |
|
h.queue_position_down(); |
|
} catch(invalid_handle& h) {} |
|
torrent_queue.pop(); |
|
} |
|
} |
|
|
|
void HttpConnection::increaseTorrentsPriority(const QStringList &hashes) |
|
{ |
|
qDebug() << Q_FUNC_INFO << hashes; |
|
std::priority_queue<QPair<int, QTorrentHandle>, |
|
std::vector<QPair<int, QTorrentHandle> >, |
|
std::greater<QPair<int, QTorrentHandle> > > torrent_queue; |
|
// Sort torrents by priority |
|
foreach (const QString &hash, hashes) { |
|
try { |
|
QTorrentHandle h = QBtSession::instance()->getTorrentHandle(hash); |
|
if (!h.is_seed()) { |
|
torrent_queue.push(qMakePair(h.queue_position(), h)); |
|
} |
|
}catch(invalid_handle&) {} |
|
} |
|
// Increase torrents priority (starting with the ones with highest priority) |
|
while(!torrent_queue.empty()) { |
|
QTorrentHandle h = torrent_queue.top().second; |
|
try { |
|
h.queue_position_up(); |
|
} catch(invalid_handle& h) {} |
|
torrent_queue.pop(); |
|
} |
|
}
|
|
|