mirror of
https://github.com/d47081/qBittorrent.git
synced 2025-01-10 23:07:59 +00:00
Rewrite code for returning information about torrents as JSON (Web UI)
- The new code is simpler, cleaner and more efficient
This commit is contained in:
parent
fc4989d738
commit
9a964d871d
11
src/misc.cpp
11
src/misc.cpp
@ -236,15 +236,20 @@ int misc::pythonVersion() {
|
|||||||
// use Binary prefix standards from IEC 60027-2
|
// use Binary prefix standards from IEC 60027-2
|
||||||
// see http://en.wikipedia.org/wiki/Kilobyte
|
// see http://en.wikipedia.org/wiki/Kilobyte
|
||||||
// value must be given in bytes
|
// value must be given in bytes
|
||||||
QString misc::friendlyUnit(qreal val) {
|
QString misc::friendlyUnit(qreal val, bool is_speed) {
|
||||||
if (val < 0)
|
if (val < 0)
|
||||||
return tr("Unknown", "Unknown (size)");
|
return tr("Unknown", "Unknown (size)");
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while(val >= 1024. && i++<6)
|
while(val >= 1024. && i++<6)
|
||||||
val /= 1024.;
|
val /= 1024.;
|
||||||
|
QString ret;
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
return QString::number((long)val) + " " + tr(units[0].source, units[0].comment);
|
ret = QString::number((long)val) + " " + tr(units[0].source, units[0].comment);
|
||||||
return QString::number(val, 'f', 1) + " " + tr(units[i].source, units[i].comment);
|
else
|
||||||
|
ret = QString::number(val, 'f', 1) + " " + tr(units[i].source, units[i].comment);
|
||||||
|
if (is_speed)
|
||||||
|
ret += tr("/s", "per second");
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool misc::isPreviewable(QString extension) {
|
bool misc::isPreviewable(QString extension) {
|
||||||
|
@ -97,7 +97,7 @@ public:
|
|||||||
// use Binary prefix standards from IEC 60027-2
|
// use Binary prefix standards from IEC 60027-2
|
||||||
// see http://en.wikipedia.org/wiki/Kilobyte
|
// see http://en.wikipedia.org/wiki/Kilobyte
|
||||||
// value must be given in bytes
|
// value must be given in bytes
|
||||||
static QString friendlyUnit(qreal val);
|
static QString friendlyUnit(qreal val, bool is_speed = false);
|
||||||
static bool isPreviewable(QString extension);
|
static bool isPreviewable(QString extension);
|
||||||
static QString magnetUriToName(QString magnet_uri);
|
static QString magnetUriToName(QString magnet_uri);
|
||||||
static QString magnetUriToHash(QString magnet_uri);
|
static QString magnetUriToHash(QString magnet_uri);
|
||||||
|
@ -682,7 +682,7 @@ void QBtSession::initWebUi() {
|
|||||||
httpServer->close();
|
httpServer->close();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
httpServer = new HttpServer(3000, this);
|
httpServer = new HttpServer(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef QT_NO_OPENSSL
|
#ifndef QT_NO_OPENSSL
|
||||||
|
333
src/webui/btjson.cpp
Normal file
333
src/webui/btjson.cpp
Normal file
@ -0,0 +1,333 @@
|
|||||||
|
/*
|
||||||
|
* Bittorrent Client using Qt4 and libtorrent.
|
||||||
|
* Copyright (C) 2012, 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 "btjson.h"
|
||||||
|
#include "jsondict.h"
|
||||||
|
#include "jsonlist.h"
|
||||||
|
#include "misc.h"
|
||||||
|
#include "qbtsession.h"
|
||||||
|
#include "torrentpersistentdata.h"
|
||||||
|
|
||||||
|
#include <QElapsedTimer>
|
||||||
|
|
||||||
|
using namespace libtorrent;
|
||||||
|
|
||||||
|
#define CACHED_VARIABLE(VARTYPE, VAR, DUR) \
|
||||||
|
static VARTYPE VAR; \
|
||||||
|
static QElapsedTimer cacheTimer; \
|
||||||
|
static bool initialized = false; \
|
||||||
|
if (initialized && !cacheTimer.hasExpired(DUR)) \
|
||||||
|
return VAR.toString(); \
|
||||||
|
initialized = true; \
|
||||||
|
cacheTimer.start(); \
|
||||||
|
VAR.clear()
|
||||||
|
|
||||||
|
// Numerical constants
|
||||||
|
static const int CACHE_DURATION_MS = 1500; // 1500ms
|
||||||
|
|
||||||
|
// Torrent keys
|
||||||
|
static const char KEY_TORRENT_HASH[] = "hash";
|
||||||
|
static const char KEY_TORRENT_NAME[] = "name";
|
||||||
|
static const char KEY_TORRENT_SIZE[] = "size";
|
||||||
|
static const char KEY_TORRENT_PROGRESS[] = "progress";
|
||||||
|
static const char KEY_TORRENT_DLSPEED[] = "dlspeed";
|
||||||
|
static const char KEY_TORRENT_UPSPEED[] = "upspeed";
|
||||||
|
static const char KEY_TORRENT_PRIORITY[] = "priority";
|
||||||
|
static const char KEY_TORRENT_SEEDS[] = "num_seeds";
|
||||||
|
static const char KEY_TORRENT_LEECHS[] = "num_leechs";
|
||||||
|
static const char KEY_TORRENT_RATIO[] = "ratio";
|
||||||
|
static const char KEY_TORRENT_ETA[] = "eta";
|
||||||
|
static const char KEY_TORRENT_STATE[] = "state";
|
||||||
|
|
||||||
|
// Tracker keys
|
||||||
|
static const char KEY_TRACKER_URL[] = "url";
|
||||||
|
static const char KEY_TRACKER_STATUS[] = "status";
|
||||||
|
static const char KEY_TRACKER_MSG[] = "msg";
|
||||||
|
static const char KEY_TRACKER_PEERS[] = "num_peers";
|
||||||
|
|
||||||
|
// Torrent keys (Properties)
|
||||||
|
static const char KEY_PROP_SAVE_PATH[] = "save_path";
|
||||||
|
static const char KEY_PROP_CREATION_DATE[] = "creation_date";
|
||||||
|
static const char KEY_PROP_PIECE_SIZE[] = "piece_size";
|
||||||
|
static const char KEY_PROP_COMMENT[] = "comment";
|
||||||
|
static const char KEY_PROP_WASTED[] = "total_wasted";
|
||||||
|
static const char KEY_PROP_DOWNLOADED[] = "total_uploaded";
|
||||||
|
static const char KEY_PROP_UPLOADED[] = "total_downloaded";
|
||||||
|
static const char KEY_PROP_UP_LIMIT[] = "up_limit";
|
||||||
|
static const char KEY_PROP_DL_LIMIT[] = "dl_limit";
|
||||||
|
static const char KEY_PROP_TIME_ELAPSED[] = "time_elapsed";
|
||||||
|
static const char KEY_PROP_CONNECT_COUNT[] = "nb_connections";
|
||||||
|
static const char KEY_PROP_RATIO[] = "share_ratio";
|
||||||
|
|
||||||
|
// File keys
|
||||||
|
static const char KEY_FILE_NAME[] = "name";
|
||||||
|
static const char KEY_FILE_SIZE[] = "size";
|
||||||
|
static const char KEY_FILE_PROGRESS[] = "progress";
|
||||||
|
static const char KEY_FILE_PRIORITY[] = "priority";
|
||||||
|
static const char KEY_FILE_IS_SEED[] = "is_seed";
|
||||||
|
|
||||||
|
static JsonDict toJson(const QTorrentHandle& h)
|
||||||
|
{
|
||||||
|
JsonDict ret;
|
||||||
|
ret.add(KEY_TORRENT_HASH, h.hash());
|
||||||
|
ret.add(KEY_TORRENT_NAME, h.name());
|
||||||
|
ret.add(KEY_TORRENT_SIZE, misc::friendlyUnit(h.actual_size())); // FIXME: Should pass as Number, not formatted String (for sorting).
|
||||||
|
ret.add(KEY_TORRENT_PROGRESS, (double)h.progress());
|
||||||
|
ret.add(KEY_TORRENT_DLSPEED, misc::friendlyUnit(h.download_payload_rate(), true)); // FIXME: Should be passed as a Number
|
||||||
|
ret.add(KEY_TORRENT_UPSPEED, misc::friendlyUnit(h.upload_payload_rate(), true)); // FIXME: Should be passed as a Number
|
||||||
|
if (QBtSession::instance()->isQueueingEnabled() && h.queue_position() >= 0)
|
||||||
|
ret.add(KEY_TORRENT_PRIORITY, QString::number(h.queue_position()));
|
||||||
|
else
|
||||||
|
ret.add(KEY_TORRENT_PRIORITY, "*");
|
||||||
|
QString seeds = QString::number(h.num_seeds());
|
||||||
|
if (h.num_complete() > 0)
|
||||||
|
seeds += " ("+QString::number(h.num_complete())+")";
|
||||||
|
ret.add(KEY_TORRENT_SEEDS, seeds);
|
||||||
|
QString leechs = QString::number(h.num_peers() - h.num_seeds());
|
||||||
|
if (h.num_incomplete() > 0)
|
||||||
|
leechs += " ("+QString::number(h.num_incomplete())+")";
|
||||||
|
ret.add(KEY_TORRENT_LEECHS, leechs);
|
||||||
|
const qreal ratio = QBtSession::instance()->getRealRatio(h.hash());
|
||||||
|
ret.add(KEY_TORRENT_RATIO, (ratio > 100.) ? QString::fromUtf8("∞") : QString::number(ratio, 'f', 1));
|
||||||
|
QString eta;
|
||||||
|
QString state;
|
||||||
|
if (h.is_paused()) {
|
||||||
|
if (h.has_error())
|
||||||
|
state = "error";
|
||||||
|
else
|
||||||
|
state = h.is_seed() ? "pausedUP" : "pausedDL";
|
||||||
|
} else {
|
||||||
|
if (QBtSession::instance()->isQueueingEnabled() && h.is_queued())
|
||||||
|
state = h.is_seed() ? "queuedUP" : "queuedDL";
|
||||||
|
else {
|
||||||
|
switch (h.state()) {
|
||||||
|
case torrent_status::finished:
|
||||||
|
case torrent_status::seeding:
|
||||||
|
state = h.upload_payload_rate() > 0 ? "uploading" : "stalledUP";
|
||||||
|
break;
|
||||||
|
case torrent_status::allocating:
|
||||||
|
case torrent_status::checking_files:
|
||||||
|
case torrent_status::queued_for_checking:
|
||||||
|
case torrent_status::checking_resume_data:
|
||||||
|
state = h.is_seed() ? "checkingUP" : "checkingDL";
|
||||||
|
break;
|
||||||
|
case torrent_status::downloading:
|
||||||
|
case torrent_status::downloading_metadata:
|
||||||
|
state = h.download_payload_rate() > 0 ? "downloading" : "stalledDL";
|
||||||
|
eta = misc::userFriendlyDuration(QBtSession::instance()->getETA(h.hash()));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
qWarning("Unrecognized torrent status, should not happen!!! status was %d", h.state());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret.add(KEY_TORRENT_ETA, eta.isEmpty() ? QString::fromUtf8("∞") : eta);
|
||||||
|
ret.add(KEY_TORRENT_STATE, state);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all the torrents in JSON format.
|
||||||
|
*
|
||||||
|
* The return value is a JSON-formatted list of dictionaries.
|
||||||
|
* The dictionary keys are:
|
||||||
|
* - "hash": Torrent hash
|
||||||
|
* - "name": Torrent name
|
||||||
|
* - "size": Torrent size
|
||||||
|
* - "progress: Torrent progress
|
||||||
|
* - "dlspeed": Torrent download speed
|
||||||
|
* - "upspeed": Torrent upload speed
|
||||||
|
* - "priority": Torrent priority ('*' if queuing is disabled)
|
||||||
|
* - "num_seeds": Torrent seed count
|
||||||
|
* - "num_leechs": Torrent leecher count
|
||||||
|
* - "ratio": Torrent share ratio
|
||||||
|
* - "eta": Torrent ETA
|
||||||
|
* - "state": Torrent state
|
||||||
|
*/
|
||||||
|
QString btjson::getTorrents()
|
||||||
|
{
|
||||||
|
CACHED_VARIABLE(JsonList, torrent_list, CACHE_DURATION_MS);
|
||||||
|
std::vector<torrent_handle> torrents = QBtSession::instance()->getTorrents();
|
||||||
|
std::vector<torrent_handle>::const_iterator it = torrents.begin();
|
||||||
|
std::vector<torrent_handle>::const_iterator end = torrents.end();
|
||||||
|
for( ; it != end; ++it) {
|
||||||
|
torrent_list.append(toJson(QTorrentHandle(*it)));
|
||||||
|
}
|
||||||
|
return torrent_list.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the trackers for a torrent in JSON format.
|
||||||
|
*
|
||||||
|
* The return value is a JSON-formatted list of dictionaries.
|
||||||
|
* The dictionary keys are:
|
||||||
|
* - "url": Tracker URL
|
||||||
|
* - "status": Tracker status
|
||||||
|
* - "num_peers": Tracker peer count
|
||||||
|
* - "msg": Tracker message (last)
|
||||||
|
*/
|
||||||
|
QString btjson::getTrackersForTorrent(const QString& hash)
|
||||||
|
{
|
||||||
|
CACHED_VARIABLE(JsonList, tracker_list, CACHE_DURATION_MS);
|
||||||
|
try {
|
||||||
|
QTorrentHandle h = QBtSession::instance()->getTorrentHandle(hash);
|
||||||
|
QHash<QString, TrackerInfos> trackers_data = QBtSession::instance()->getTrackersInfo(hash);
|
||||||
|
std::vector<announce_entry> vect_trackers = h.trackers();
|
||||||
|
std::vector<announce_entry>::const_iterator it = vect_trackers.begin();
|
||||||
|
std::vector<announce_entry>::const_iterator end = vect_trackers.end();
|
||||||
|
for (; it != end; ++it) {
|
||||||
|
JsonDict tracker_dict;
|
||||||
|
const QString tracker_url = misc::toQString(it->url);
|
||||||
|
tracker_dict.add(KEY_TRACKER_URL, tracker_url);
|
||||||
|
const TrackerInfos data = trackers_data.value(tracker_url, TrackerInfos(tracker_url));
|
||||||
|
QString status;
|
||||||
|
if (it->verified)
|
||||||
|
status = tr("Working");
|
||||||
|
else {
|
||||||
|
if (it->updating && it->fails == 0)
|
||||||
|
status = tr("Updating...");
|
||||||
|
else
|
||||||
|
status = it->fails > 0 ? tr("Not working") : tr("Not contacted yet");
|
||||||
|
}
|
||||||
|
tracker_dict.add(KEY_TRACKER_STATUS, status);
|
||||||
|
tracker_dict.add(KEY_TRACKER_PEERS, QString::number(trackers_data.value(tracker_url, TrackerInfos(tracker_url)).num_peers));
|
||||||
|
tracker_dict.add(KEY_TRACKER_MSG, data.last_message.trimmed());
|
||||||
|
|
||||||
|
tracker_list.append(tracker_dict);
|
||||||
|
}
|
||||||
|
} catch(const std::exception&) {
|
||||||
|
qWarning() << "getTrackersForTorrent() called with invalid torrent";
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return tracker_list.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the properties for a torrent in JSON format.
|
||||||
|
*
|
||||||
|
* The return value is a JSON-formatted dictionary.
|
||||||
|
* The dictionary keys are:
|
||||||
|
* - "save_path": Torrent save path
|
||||||
|
* - "creation_date": Torrent creation date
|
||||||
|
* - "piece_size": Torrent piece size
|
||||||
|
* - "comment": Torrent comment
|
||||||
|
* - "total_wasted": Total data wasted for torrent
|
||||||
|
* - "total_uploaded": Total data uploaded for torrent
|
||||||
|
* - "total_downloaded": Total data uploaded for torrent
|
||||||
|
* - "up_limit": Torrent upload limit
|
||||||
|
* - "dl_limit": Torrent download limit
|
||||||
|
* - "time_elapsed": Torrent elapsed time
|
||||||
|
* - "nb_connections": Torrent connection count
|
||||||
|
* - "share_ratio": Torrent share ratio
|
||||||
|
*/
|
||||||
|
QString btjson::getPropertiesForTorrent(const QString& hash)
|
||||||
|
{
|
||||||
|
CACHED_VARIABLE(JsonDict, data, CACHE_DURATION_MS);
|
||||||
|
try {
|
||||||
|
QTorrentHandle h = QBtSession::instance()->getTorrentHandle(hash);
|
||||||
|
|
||||||
|
if (!h.has_metadata())
|
||||||
|
return QString();
|
||||||
|
|
||||||
|
// Save path
|
||||||
|
QString save_path = TorrentPersistentData::getSavePath(hash);
|
||||||
|
if (save_path.isEmpty())
|
||||||
|
save_path = h.save_path();
|
||||||
|
data.add(KEY_PROP_SAVE_PATH, save_path);
|
||||||
|
data.add(KEY_PROP_CREATION_DATE, h.creation_date());
|
||||||
|
data.add(KEY_PROP_PIECE_SIZE, misc::friendlyUnit(h.piece_length()));
|
||||||
|
data.add(KEY_PROP_COMMENT, h.comment());
|
||||||
|
data.add(KEY_PROP_WASTED, misc::friendlyUnit(h.total_failed_bytes() + h.total_redundant_bytes()));
|
||||||
|
data.add(KEY_PROP_UPLOADED, QString(misc::friendlyUnit(h.all_time_upload()) + " (" + misc::friendlyUnit(h.total_payload_upload()) + " " + tr("this session") + ")"));
|
||||||
|
data.add(KEY_PROP_DOWNLOADED, QString(misc::friendlyUnit(h.all_time_download()) + " (" + misc::friendlyUnit(h.total_payload_download()) + " " + tr("this session") + ")"));
|
||||||
|
if (h.upload_limit() <= 0)
|
||||||
|
data.add(KEY_PROP_UPLOADED, QString::fromUtf8("∞"));
|
||||||
|
else
|
||||||
|
data.add(KEY_PROP_UPLOADED, misc::friendlyUnit(h.upload_limit(), true));
|
||||||
|
if (h.download_limit() <= 0)
|
||||||
|
data.add(KEY_PROP_DOWNLOADED, QString::fromUtf8("∞"));
|
||||||
|
else
|
||||||
|
data.add(KEY_PROP_DOWNLOADED, misc::friendlyUnit(h.download_limit(), true));
|
||||||
|
QString elapsed_txt = misc::userFriendlyDuration(h.active_time());
|
||||||
|
if (h.is_seed())
|
||||||
|
elapsed_txt += " ("+tr("Seeded for %1", "e.g. Seeded for 3m10s").arg(misc::userFriendlyDuration(h.seeding_time()))+")";
|
||||||
|
data.add(KEY_PROP_TIME_ELAPSED, elapsed_txt);
|
||||||
|
data.add(KEY_PROP_CONNECT_COUNT, QString(QString::number(h.num_connections()) + " (" + tr("%1 max", "e.g. 10 max").arg(QString::number(h.connections_limit())) + ")"));
|
||||||
|
const qreal ratio = QBtSession::instance()->getRealRatio(h.hash());
|
||||||
|
data.add(KEY_PROP_RATIO, ratio > 100. ? QString::fromUtf8("∞") : QString::number(ratio, 'f', 1));
|
||||||
|
} catch(const std::exception&) {
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return data.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the files in a torrent in JSON format.
|
||||||
|
*
|
||||||
|
* The return value is a JSON-formatted list of dictionaries.
|
||||||
|
* The dictionary keys are:
|
||||||
|
* - "name": File name
|
||||||
|
* - "size": File size
|
||||||
|
* - "progress": File progress
|
||||||
|
* - "priority": File priority
|
||||||
|
* - "is_seed": Flag indicating if torrent is seeding/complete
|
||||||
|
*/
|
||||||
|
QString btjson::getFilesForTorrent(const QString& hash)
|
||||||
|
{
|
||||||
|
CACHED_VARIABLE(JsonList, file_list, CACHE_DURATION_MS);
|
||||||
|
try {
|
||||||
|
QTorrentHandle h = QBtSession::instance()->getTorrentHandle(hash);
|
||||||
|
if (!h.has_metadata())
|
||||||
|
return QString();
|
||||||
|
|
||||||
|
const std::vector<int> priorities = h.file_priorities();
|
||||||
|
std::vector<size_type> fp;
|
||||||
|
h.file_progress(fp);
|
||||||
|
for (int i = 0; i < h.num_files(); ++i) {
|
||||||
|
JsonDict file_dict;
|
||||||
|
file_dict.add(KEY_FILE_NAME, h.filename_at(i));
|
||||||
|
const size_type size = h.filesize_at(i);
|
||||||
|
file_dict.add(KEY_FILE_SIZE, misc::friendlyUnit(size));
|
||||||
|
file_dict.add(KEY_FILE_PROGRESS, (size > 0) ? (fp[i] / (double) size) : 1.);
|
||||||
|
file_dict.add(KEY_FILE_PRIORITY, priorities[i]);
|
||||||
|
if (i == 0)
|
||||||
|
file_dict.add(KEY_FILE_IS_SEED, h.is_seed());
|
||||||
|
|
||||||
|
file_list.append(file_dict);
|
||||||
|
}
|
||||||
|
} catch (const std::exception&) {
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return file_list.toString();
|
||||||
|
}
|
50
src/webui/btjson.h
Normal file
50
src/webui/btjson.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Bittorrent Client using Qt4 and libtorrent.
|
||||||
|
* Copyright (C) 2012, 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BTJSON_H
|
||||||
|
#define BTJSON_H
|
||||||
|
|
||||||
|
#include <QCoreApplication>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
class btjson {
|
||||||
|
Q_DECLARE_TR_FUNCTIONS(misc)
|
||||||
|
|
||||||
|
private:
|
||||||
|
btjson() {}
|
||||||
|
|
||||||
|
public:
|
||||||
|
static QString getTorrents();
|
||||||
|
static QString getTrackersForTorrent(const QString& hash);
|
||||||
|
static QString getPropertiesForTorrent(const QString& hash);
|
||||||
|
static QString getFilesForTorrent(const QString& hash);
|
||||||
|
}; // class btjson
|
||||||
|
|
||||||
|
#endif // BTJSON_H
|
@ -51,68 +51,6 @@ EventManager::EventManager(QObject *parent)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<QVariantMap> EventManager::getEventList() const {
|
|
||||||
return event_list.values();
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<QVariantMap> EventManager::getPropTrackersInfo(QString hash) const {
|
|
||||||
QList<QVariantMap> trackersInfo;
|
|
||||||
QTorrentHandle h = QBtSession::instance()->getTorrentHandle(hash);
|
|
||||||
if (h.is_valid()) {
|
|
||||||
QHash<QString, TrackerInfos> trackers_data = QBtSession::instance()->getTrackersInfo(hash);
|
|
||||||
std::vector<announce_entry> vect_trackers = h.trackers();
|
|
||||||
std::vector<announce_entry>::iterator it;
|
|
||||||
for (it = vect_trackers.begin(); it != vect_trackers.end(); it++) {
|
|
||||||
QVariantMap tracker;
|
|
||||||
QString tracker_url = misc::toQString(it->url);
|
|
||||||
tracker["url"] = tracker_url;
|
|
||||||
TrackerInfos data = trackers_data.value(tracker_url, TrackerInfos(tracker_url));
|
|
||||||
QString error_message = data.last_message.trimmed();
|
|
||||||
if (it->verified) {
|
|
||||||
tracker["status"] = tr("Working");
|
|
||||||
} else {
|
|
||||||
if (it->updating && it->fails == 0) {
|
|
||||||
tracker["status"] = tr("Updating...");
|
|
||||||
} else {
|
|
||||||
if (it->fails > 0) {
|
|
||||||
tracker["status"] = tr("Not working");
|
|
||||||
} else {
|
|
||||||
tracker["status"] = tr("Not contacted yet");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tracker["num_peers"] = QString::number(trackers_data.value(tracker_url, TrackerInfos(tracker_url)).num_peers);
|
|
||||||
tracker["msg"] = error_message;
|
|
||||||
trackersInfo << tracker;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return trackersInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<QVariantMap> EventManager::getPropFilesInfo(QString hash) const {
|
|
||||||
QList<QVariantMap> files;
|
|
||||||
QTorrentHandle h = QBtSession::instance()->getTorrentHandle(hash);
|
|
||||||
if (!h.is_valid() || !h.has_metadata()) return files;
|
|
||||||
std::vector<int> priorities = h.file_priorities();
|
|
||||||
std::vector<size_type> fp;
|
|
||||||
h.file_progress(fp);
|
|
||||||
for (int i=0; i<h.num_files(); ++i) {
|
|
||||||
QVariantMap file;
|
|
||||||
file["name"] = h.filename_at(i);
|
|
||||||
libtorrent::size_type size = h.filesize_at(i);
|
|
||||||
file["size"] = misc::friendlyUnit((double)size);
|
|
||||||
if (size > 0)
|
|
||||||
file["progress"] = fp[i]/(double)size;
|
|
||||||
else
|
|
||||||
file["progress"] = 1.; // Empty file...
|
|
||||||
file["priority"] = priorities[i];
|
|
||||||
if (i == 0)
|
|
||||||
file["is_seed"] = h.is_seed();
|
|
||||||
files << file;
|
|
||||||
}
|
|
||||||
return files;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventManager::setGlobalPreferences(QVariantMap m) {
|
void EventManager::setGlobalPreferences(QVariantMap m) {
|
||||||
// UI
|
// UI
|
||||||
Preferences pref;
|
Preferences pref;
|
||||||
@ -408,140 +346,3 @@ QVariantMap EventManager::getGlobalPreferences() const {
|
|||||||
data["dyndns_domain"] = pref.getDynDomainName();
|
data["dyndns_domain"] = pref.getDynDomainName();
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariantMap EventManager::getPropGeneralInfo(QString hash) const {
|
|
||||||
QVariantMap data;
|
|
||||||
QTorrentHandle h = QBtSession::instance()->getTorrentHandle(hash);
|
|
||||||
if (h.is_valid() && h.has_metadata()) {
|
|
||||||
// Save path
|
|
||||||
QString p = TorrentPersistentData::getSavePath(hash);
|
|
||||||
if (p.isEmpty()) p = h.save_path();
|
|
||||||
data["save_path"] = p;
|
|
||||||
// Creation date
|
|
||||||
data["creation_date"] = h.creation_date();
|
|
||||||
// Piece size
|
|
||||||
data["piece_size"] = misc::friendlyUnit(h.piece_length());
|
|
||||||
// Comment
|
|
||||||
data["comment"] = h.comment();
|
|
||||||
data["total_wasted"] = QVariant(misc::friendlyUnit(h.total_failed_bytes()+h.total_redundant_bytes()));
|
|
||||||
data["total_uploaded"] = QVariant(misc::friendlyUnit(h.all_time_upload()) + " ("+misc::friendlyUnit(h.total_payload_upload())+" "+tr("this session")+")");
|
|
||||||
data["total_downloaded"] = QVariant(misc::friendlyUnit(h.all_time_download()) + " ("+misc::friendlyUnit(h.total_payload_download())+" "+tr("this session")+")");
|
|
||||||
if (h.upload_limit() <= 0)
|
|
||||||
data["up_limit"] = QString::fromUtf8("∞");
|
|
||||||
else
|
|
||||||
data["up_limit"] = QVariant(misc::friendlyUnit(h.upload_limit())+tr("/s", "/second (i.e. per second)"));
|
|
||||||
if (h.download_limit() <= 0)
|
|
||||||
data["dl_limit"] = QString::fromUtf8("∞");
|
|
||||||
else
|
|
||||||
data["dl_limit"] = QVariant(misc::friendlyUnit(h.download_limit())+tr("/s", "/second (i.e. per second)"));
|
|
||||||
QString elapsed_txt = misc::userFriendlyDuration(h.active_time());
|
|
||||||
if (h.is_seed()) {
|
|
||||||
elapsed_txt += " ("+tr("Seeded for %1", "e.g. Seeded for 3m10s").arg(misc::userFriendlyDuration(h.seeding_time()))+")";
|
|
||||||
}
|
|
||||||
data["time_elapsed"] = elapsed_txt;
|
|
||||||
data["nb_connections"] = QVariant(QString::number(h.num_connections())+" ("+tr("%1 max", "e.g. 10 max").arg(QString::number(h.connections_limit()))+")");
|
|
||||||
// Update ratio info
|
|
||||||
qreal ratio = QBtSession::instance()->getRealRatio(h.hash());
|
|
||||||
if (ratio > 100.)
|
|
||||||
data["share_ratio"] = QString::fromUtf8("∞");
|
|
||||||
else
|
|
||||||
data["share_ratio"] = QString(QByteArray::number(ratio, 'f', 1));
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventManager::addedTorrent(const QTorrentHandle& h)
|
|
||||||
{
|
|
||||||
modifiedTorrent(h);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventManager::deletedTorrent(QString hash)
|
|
||||||
{
|
|
||||||
event_list.remove(hash);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventManager::modifiedTorrent(const QTorrentHandle& h)
|
|
||||||
{
|
|
||||||
QString hash = h.hash();
|
|
||||||
QVariantMap event;
|
|
||||||
event["eta"] = QVariant(QString::fromUtf8("∞"));
|
|
||||||
if (h.is_paused()) {
|
|
||||||
if (h.has_error()) {
|
|
||||||
event["state"] = QVariant("error");
|
|
||||||
} else {
|
|
||||||
if (h.is_seed())
|
|
||||||
event["state"] = QVariant("pausedUP");
|
|
||||||
else
|
|
||||||
event["state"] = QVariant("pausedDL");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (QBtSession::instance()->isQueueingEnabled() && h.is_queued()) {
|
|
||||||
if (h.is_seed())
|
|
||||||
event["state"] = QVariant("queuedUP");
|
|
||||||
else
|
|
||||||
event["state"] = QVariant("queuedDL");
|
|
||||||
} else {
|
|
||||||
switch(h.state())
|
|
||||||
{
|
|
||||||
case torrent_status::finished:
|
|
||||||
case torrent_status::seeding:
|
|
||||||
if (h.upload_payload_rate() > 0) {
|
|
||||||
event["state"] = QVariant("uploading");
|
|
||||||
} else {
|
|
||||||
event["state"] = QVariant("stalledUP");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case torrent_status::allocating:
|
|
||||||
case torrent_status::checking_files:
|
|
||||||
case torrent_status::queued_for_checking:
|
|
||||||
case torrent_status::checking_resume_data:
|
|
||||||
if (h.is_seed()) {
|
|
||||||
event["state"] = QVariant("checkingUP");
|
|
||||||
} else {
|
|
||||||
event["state"] = QVariant("checkingDL");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case torrent_status::downloading:
|
|
||||||
case torrent_status::downloading_metadata:
|
|
||||||
if (h.download_payload_rate() > 0)
|
|
||||||
event["state"] = QVariant("downloading");
|
|
||||||
else
|
|
||||||
event["state"] = QVariant("stalledDL");
|
|
||||||
event["eta"] = misc::userFriendlyDuration(QBtSession::instance()->getETA(hash));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
qDebug("No status, should not happen!!! status is %d", h.state());
|
|
||||||
event["state"] = QVariant();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
event["name"] = QVariant(h.name());
|
|
||||||
event["size"] = QVariant(misc::friendlyUnit(h.actual_size()));
|
|
||||||
event["progress"] = QVariant((double)h.progress());
|
|
||||||
event["dlspeed"] = QVariant(tr("%1/s", "e.g. 120 KiB/s").arg(misc::friendlyUnit(h.download_payload_rate())));
|
|
||||||
if (QBtSession::instance()->isQueueingEnabled()) {
|
|
||||||
if (h.queue_position() >= 0)
|
|
||||||
event["priority"] = QVariant(QString::number(h.queue_position()));
|
|
||||||
else
|
|
||||||
event["priority"] = "*";
|
|
||||||
} else {
|
|
||||||
event["priority"] = "*";
|
|
||||||
}
|
|
||||||
event["upspeed"] = QVariant(tr("%1/s", "e.g. 120 KiB/s").arg(misc::friendlyUnit(h.upload_payload_rate())));
|
|
||||||
QString seeds = QString::number(h.num_seeds());
|
|
||||||
if (h.num_complete() > 0)
|
|
||||||
seeds += " ("+QString::number(h.num_complete())+")";
|
|
||||||
event["num_seeds"] = QVariant(seeds);
|
|
||||||
QString leechs = QString::number(h.num_peers()-h.num_seeds());
|
|
||||||
if (h.num_incomplete() > 0)
|
|
||||||
leechs += " ("+QString::number(h.num_incomplete())+")";
|
|
||||||
event["num_leechs"] = QVariant(leechs);
|
|
||||||
event["seed"] = QVariant(h.is_seed());
|
|
||||||
qreal ratio = QBtSession::instance()->getRealRatio(hash);
|
|
||||||
if (ratio > 100.)
|
|
||||||
event["ratio"] = QString::fromUtf8("∞");
|
|
||||||
else
|
|
||||||
event["ratio"] = QVariant(QString::number(ratio, 'f', 1));
|
|
||||||
event["hash"] = QVariant(hash);
|
|
||||||
event_list[hash] = event;
|
|
||||||
}
|
|
||||||
|
@ -41,28 +41,17 @@ class EventManager : public QObject
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_DISABLE_COPY(EventManager)
|
Q_DISABLE_COPY(EventManager)
|
||||||
|
|
||||||
private:
|
|
||||||
QHash<QString, QVariantMap> event_list;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void update(QVariantMap event);
|
void update(QVariantMap event);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
EventManager(QObject *parent);
|
EventManager(QObject *parent);
|
||||||
QList<QVariantMap> getEventList() const;
|
|
||||||
QVariantMap getPropGeneralInfo(QString hash) const;
|
|
||||||
QList<QVariantMap> getPropTrackersInfo(QString hash) const;
|
|
||||||
QList<QVariantMap> getPropFilesInfo(QString hash) const;
|
QList<QVariantMap> getPropFilesInfo(QString hash) const;
|
||||||
QVariantMap getGlobalPreferences() const;
|
QVariantMap getGlobalPreferences() const;
|
||||||
void setGlobalPreferences(QVariantMap m);
|
void setGlobalPreferences(QVariantMap m);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void localeChanged(const QString &locale);
|
void localeChanged(const QString &locale);
|
||||||
|
|
||||||
public slots:
|
|
||||||
void addedTorrent(const QTorrentHandle& h);
|
|
||||||
void deletedTorrent(QString hash);
|
|
||||||
void modifiedTorrent(const QTorrentHandle& h);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include "eventmanager.h"
|
#include "eventmanager.h"
|
||||||
#include "preferences.h"
|
#include "preferences.h"
|
||||||
#include "json.h"
|
#include "json.h"
|
||||||
|
#include "btjson.h"
|
||||||
#include "qbtsession.h"
|
#include "qbtsession.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#ifndef DISABLE_GUI
|
#ifndef DISABLE_GUI
|
||||||
@ -242,8 +243,8 @@ void HttpConnection::respond() {
|
|||||||
|
|
||||||
if (list.size() >= 2) {
|
if (list.size() >= 2) {
|
||||||
if (list[0] == "json") {
|
if (list[0] == "json") {
|
||||||
if (list[1] == "events") {
|
if (list[1] == "torrents") {
|
||||||
respondJson();
|
respondTorrentsJson();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (list.size() > 2) {
|
if (list.size() > 2) {
|
||||||
@ -337,39 +338,31 @@ void HttpConnection::respondNotFound() {
|
|||||||
write();
|
write();
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpConnection::respondJson() {
|
void HttpConnection::respondTorrentsJson() {
|
||||||
EventManager* manager = m_httpserver->eventManager();
|
|
||||||
QString string = json::toJson(manager->getEventList());
|
|
||||||
m_generator.setStatusLine(200, "OK");
|
m_generator.setStatusLine(200, "OK");
|
||||||
m_generator.setContentTypeByExt("js");
|
m_generator.setContentTypeByExt("js");
|
||||||
m_generator.setMessage(string);
|
m_generator.setMessage(btjson::getTorrents());
|
||||||
write();
|
write();
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpConnection::respondGenPropertiesJson(const QString& hash) {
|
void HttpConnection::respondGenPropertiesJson(const QString& hash) {
|
||||||
EventManager* manager = m_httpserver->eventManager();
|
|
||||||
QString string = json::toJson(manager->getPropGeneralInfo(hash));
|
|
||||||
m_generator.setStatusLine(200, "OK");
|
m_generator.setStatusLine(200, "OK");
|
||||||
m_generator.setContentTypeByExt("js");
|
m_generator.setContentTypeByExt("js");
|
||||||
m_generator.setMessage(string);
|
m_generator.setMessage(btjson::getPropertiesForTorrent(hash));
|
||||||
write();
|
write();
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpConnection::respondTrackersPropertiesJson(const QString& hash) {
|
void HttpConnection::respondTrackersPropertiesJson(const QString& hash) {
|
||||||
EventManager* manager = m_httpserver->eventManager();
|
|
||||||
QString string = json::toJson(manager->getPropTrackersInfo(hash));
|
|
||||||
m_generator.setStatusLine(200, "OK");
|
m_generator.setStatusLine(200, "OK");
|
||||||
m_generator.setContentTypeByExt("js");
|
m_generator.setContentTypeByExt("js");
|
||||||
m_generator.setMessage(string);
|
m_generator.setMessage(btjson::getTrackersForTorrent(hash));
|
||||||
write();
|
write();
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpConnection::respondFilesPropertiesJson(const QString& hash) {
|
void HttpConnection::respondFilesPropertiesJson(const QString& hash) {
|
||||||
EventManager* manager = m_httpserver->eventManager();
|
|
||||||
QString string = json::toJson(manager->getPropFilesInfo(hash));
|
|
||||||
m_generator.setStatusLine(200, "OK");
|
m_generator.setStatusLine(200, "OK");
|
||||||
m_generator.setContentTypeByExt("js");
|
m_generator.setContentTypeByExt("js");
|
||||||
m_generator.setMessage(string);
|
m_generator.setMessage(btjson::getFilesForTorrent(hash));
|
||||||
write();
|
write();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ public:
|
|||||||
protected slots:
|
protected slots:
|
||||||
void write();
|
void write();
|
||||||
void respond();
|
void respond();
|
||||||
void respondJson();
|
void respondTorrentsJson();
|
||||||
void respondGenPropertiesJson(const QString& hash);
|
void respondGenPropertiesJson(const QString& hash);
|
||||||
void respondTrackersPropertiesJson(const QString& hash);
|
void respondTrackersPropertiesJson(const QString& hash);
|
||||||
void respondFilesPropertiesJson(const QString& hash);
|
void respondFilesPropertiesJson(const QString& hash);
|
||||||
|
@ -89,7 +89,7 @@ void HttpServer::resetNbFailedAttemptsForIp(const QString& ip) {
|
|||||||
m_clientFailedAttempts.remove(ip);
|
m_clientFailedAttempts.remove(ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpServer::HttpServer(int msec, QObject* parent) : QTcpServer(parent),
|
HttpServer::HttpServer(QObject* parent) : QTcpServer(parent),
|
||||||
m_eventManager(new EventManager(this)) {
|
m_eventManager(new EventManager(this)) {
|
||||||
|
|
||||||
const Preferences pref;
|
const Preferences pref;
|
||||||
@ -109,23 +109,6 @@ HttpServer::HttpServer(int msec, QObject* parent) : QTcpServer(parent),
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Add torrents
|
|
||||||
std::vector<torrent_handle> torrents = QBtSession::instance()->getTorrents();
|
|
||||||
std::vector<torrent_handle>::iterator torrentIT;
|
|
||||||
for (torrentIT = torrents.begin(); torrentIT != torrents.end(); torrentIT++) {
|
|
||||||
QTorrentHandle h = QTorrentHandle(*torrentIT);
|
|
||||||
if (h.is_valid())
|
|
||||||
m_eventManager->addedTorrent(h);
|
|
||||||
}
|
|
||||||
|
|
||||||
//connect QBtSession::instance() to manager
|
|
||||||
connect(QBtSession::instance(), SIGNAL(addedTorrent(QTorrentHandle)), m_eventManager, SLOT(addedTorrent(QTorrentHandle)));
|
|
||||||
connect(QBtSession::instance(), SIGNAL(deletedTorrent(QString)), m_eventManager, SLOT(deletedTorrent(QString)));
|
|
||||||
|
|
||||||
//set timer
|
|
||||||
connect(&m_timer, SIGNAL(timeout()), SLOT(onTimer()));
|
|
||||||
m_timer.start(msec);
|
|
||||||
|
|
||||||
// Additional translations for Web UI
|
// Additional translations for Web UI
|
||||||
QString a = tr("File");
|
QString a = tr("File");
|
||||||
a = tr("Edit");
|
a = tr("Edit");
|
||||||
@ -214,16 +197,6 @@ void HttpServer::handleNewConnection(QTcpSocket *socket)
|
|||||||
connect(connection, SIGNAL(resumeAllTorrents()), QBtSession::instance(), SLOT(resumeAllTorrents()));
|
connect(connection, SIGNAL(resumeAllTorrents()), QBtSession::instance(), SLOT(resumeAllTorrents()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpServer::onTimer() {
|
|
||||||
std::vector<torrent_handle> torrents = QBtSession::instance()->getTorrents();
|
|
||||||
std::vector<torrent_handle>::iterator torrentIT;
|
|
||||||
for (torrentIT = torrents.begin(); torrentIT != torrents.end(); torrentIT++) {
|
|
||||||
QTorrentHandle h = QTorrentHandle(*torrentIT);
|
|
||||||
if (h.is_valid())
|
|
||||||
m_eventManager->modifiedTorrent(h);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QString HttpServer::generateNonce() const {
|
QString HttpServer::generateNonce() const {
|
||||||
QCryptographicHash md5(QCryptographicHash::Md5);
|
QCryptographicHash md5(QCryptographicHash::Md5);
|
||||||
md5.addData(QTime::currentTime().toString("hhmmsszzz").toLocal8Bit());
|
md5.addData(QTime::currentTime().toString("hhmmsszzz").toLocal8Bit());
|
||||||
|
@ -58,7 +58,7 @@ class HttpServer : public QTcpServer {
|
|||||||
Q_DISABLE_COPY(HttpServer)
|
Q_DISABLE_COPY(HttpServer)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
HttpServer(int msec, QObject* parent = 0);
|
HttpServer(QObject* parent = 0);
|
||||||
~HttpServer();
|
~HttpServer();
|
||||||
void setAuthorization(const QString& username, const QString& password_sha1);
|
void setAuthorization(const QString& username, const QString& password_sha1);
|
||||||
bool isAuthorized(const QByteArray& auth, const QString& method) const;
|
bool isAuthorized(const QByteArray& auth, const QString& method) const;
|
||||||
@ -80,7 +80,6 @@ private:
|
|||||||
void incomingConnection(int socketDescriptor);
|
void incomingConnection(int socketDescriptor);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onTimer();
|
|
||||||
void UnbanTimerEvent();
|
void UnbanTimerEvent();
|
||||||
void onLocaleChanged(const QString &locale);
|
void onLocaleChanged(const QString &locale);
|
||||||
|
|
||||||
@ -90,8 +89,7 @@ private:
|
|||||||
private:
|
private:
|
||||||
QByteArray m_username;
|
QByteArray m_username;
|
||||||
QByteArray m_passwordSha1;
|
QByteArray m_passwordSha1;
|
||||||
EventManager *m_eventManager;
|
EventManager *m_eventManager; // TODO: Remove
|
||||||
QTimer m_timer;
|
|
||||||
QHash<QString, int> m_clientFailedAttempts;
|
QHash<QString, int> m_clientFailedAttempts;
|
||||||
bool m_localAuthEnabled;
|
bool m_localAuthEnabled;
|
||||||
bool m_needsTranslation;
|
bool m_needsTranslation;
|
||||||
|
181
src/webui/json.cpp
Normal file
181
src/webui/json.cpp
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
/*
|
||||||
|
* Bittorrent Client using Qt4 and libtorrent.
|
||||||
|
* Copyright (C) 2006-2012 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 "json.h"
|
||||||
|
|
||||||
|
#include <QStringList>
|
||||||
|
#include <QVariantMap>
|
||||||
|
|
||||||
|
QString json::toJson(const QVariant& v) {
|
||||||
|
if (v.isNull())
|
||||||
|
return "null";
|
||||||
|
switch(v.type())
|
||||||
|
{
|
||||||
|
case QVariant::Bool:
|
||||||
|
case QVariant::Double:
|
||||||
|
case QVariant::Int:
|
||||||
|
case QVariant::LongLong:
|
||||||
|
case QVariant::UInt:
|
||||||
|
case QVariant::ULongLong:
|
||||||
|
return v.value<QString>();
|
||||||
|
case QVariant::StringList:
|
||||||
|
case QVariant::List: {
|
||||||
|
QStringList strList;
|
||||||
|
foreach (const QVariant &var, v.toList()) {
|
||||||
|
strList << toJson(var);
|
||||||
|
}
|
||||||
|
return "["+strList.join(",")+"]";
|
||||||
|
}
|
||||||
|
case QVariant::String: {
|
||||||
|
QString s = v.value<QString>();
|
||||||
|
QString result = "\"";
|
||||||
|
for (int i=0; i<s.size(); ++i) {
|
||||||
|
const QChar ch = s[i];
|
||||||
|
switch(ch.toAscii())
|
||||||
|
{
|
||||||
|
case '\b':
|
||||||
|
result += "\\b";
|
||||||
|
break;
|
||||||
|
case '\f':
|
||||||
|
result += "\\f";
|
||||||
|
break;
|
||||||
|
case '\n':
|
||||||
|
result += "\\n";
|
||||||
|
break;
|
||||||
|
case '\r':
|
||||||
|
result += "\\r";
|
||||||
|
break;
|
||||||
|
case '\t':
|
||||||
|
result += "\\t";
|
||||||
|
break;
|
||||||
|
case '\"':
|
||||||
|
case '\'':
|
||||||
|
case '\\':
|
||||||
|
case '&':
|
||||||
|
result += '\\';
|
||||||
|
case '\0':
|
||||||
|
default:
|
||||||
|
result += ch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result += "\"";
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
qDebug("Unknown QVariantType: %d", (int)v.type());
|
||||||
|
return "undefined";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Remove
|
||||||
|
QString json::toJson(const QVariantMap& m) {
|
||||||
|
QStringList vlist;
|
||||||
|
QVariantMap::ConstIterator it;
|
||||||
|
for (it = m.constBegin(); it != m.constEnd(); it++) {
|
||||||
|
vlist << toJson(it.key())+":"+toJson(it.value());
|
||||||
|
}
|
||||||
|
return "{"+vlist.join(",")+"}";
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantMap json::fromJson(const QString& json) {
|
||||||
|
qDebug("JSON is %s", qPrintable(json));
|
||||||
|
QVariantMap m;
|
||||||
|
if (json.startsWith("{") && json.endsWith("}")) {
|
||||||
|
QStringList couples;
|
||||||
|
QString tmp = "";
|
||||||
|
bool in_list = false;
|
||||||
|
foreach (const QChar &c, json.mid(1, json.length()-2)) {
|
||||||
|
if (c == ',' && !in_list) {
|
||||||
|
couples << tmp;
|
||||||
|
tmp = "";
|
||||||
|
} else {
|
||||||
|
if (c == '[')
|
||||||
|
in_list = true;
|
||||||
|
else if (c == ']')
|
||||||
|
in_list = false;
|
||||||
|
tmp += c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!tmp.isEmpty()) couples << tmp;
|
||||||
|
|
||||||
|
foreach (const QString &couple, couples) {
|
||||||
|
QStringList parts = couple.split(":");
|
||||||
|
if (parts.size() != 2) continue;
|
||||||
|
QString key = parts.first();
|
||||||
|
if (key.startsWith("\"") && key.endsWith("\"")) {
|
||||||
|
key = key.mid(1, key.length()-2);
|
||||||
|
}
|
||||||
|
QString value_str = parts.last();
|
||||||
|
QVariant value;
|
||||||
|
if (value_str.startsWith("[") && value_str.endsWith("]")) {
|
||||||
|
value_str = value_str.mid(1, value_str.length()-2);
|
||||||
|
QStringList list_elems = value_str.split(",", QString::SkipEmptyParts);
|
||||||
|
QVariantList varlist;
|
||||||
|
foreach (const QString &list_val, list_elems) {
|
||||||
|
if (list_val.startsWith("\"") && list_val.endsWith("\"")) {
|
||||||
|
varlist << list_val.mid(1, list_val.length()-2).replace("\\n", "\n");
|
||||||
|
} else {
|
||||||
|
varlist << list_val.toInt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
value = varlist;
|
||||||
|
} else {
|
||||||
|
if (value_str.startsWith("\"") && value_str.endsWith("\"")) {
|
||||||
|
value_str = value_str.mid(1, value_str.length()-2).replace("\\n", "\n");
|
||||||
|
value = value_str;
|
||||||
|
} else {
|
||||||
|
if (value_str.compare("false", Qt::CaseInsensitive) == 0)
|
||||||
|
value = false;
|
||||||
|
else if (value_str.compare("true", Qt::CaseInsensitive) == 0)
|
||||||
|
value = true;
|
||||||
|
else
|
||||||
|
value = value_str.toInt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m.insert(key, value);
|
||||||
|
qDebug("%s:%s", key.toLocal8Bit().data(), value_str.toLocal8Bit().data());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Remove
|
||||||
|
QString json::toJson(const QList<QVariantMap>& v) {
|
||||||
|
QStringList res;
|
||||||
|
foreach (QVariantMap m, v) {
|
||||||
|
QStringList vlist;
|
||||||
|
QVariantMap::ConstIterator it;
|
||||||
|
for (it = m.constBegin(); it != m.constEnd(); it++) {
|
||||||
|
vlist << toJson(it.key())+":"+toJson(it.value());
|
||||||
|
}
|
||||||
|
res << "{"+vlist.join(",")+"}";
|
||||||
|
}
|
||||||
|
return "["+res.join(",")+"]";
|
||||||
|
}
|
151
src/webui/json.h
151
src/webui/json.h
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Bittorrent Client using Qt4 and libtorrent.
|
* Bittorrent Client using Qt4 and libtorrent.
|
||||||
* Copyright (C) 2006 Ishan Arora and Christophe Dumez
|
* Copyright (C) 2006-2012 Ishan Arora and Christophe Dumez
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
@ -36,150 +36,11 @@
|
|||||||
|
|
||||||
namespace json {
|
namespace json {
|
||||||
|
|
||||||
QString toJson(const QVariant& v) {
|
QString toJson(const QVariant& v);
|
||||||
if (v.isNull())
|
QString toJson(const QVariantMap& m); // TODO: Remove
|
||||||
return "null";
|
QString toJson(const QList<QVariantMap>& v); // TODO: Remove
|
||||||
switch(v.type())
|
QVariantMap fromJson(const QString& json);
|
||||||
{
|
|
||||||
case QVariant::Bool:
|
|
||||||
case QVariant::Double:
|
|
||||||
case QVariant::Int:
|
|
||||||
case QVariant::LongLong:
|
|
||||||
case QVariant::UInt:
|
|
||||||
case QVariant::ULongLong:
|
|
||||||
return v.value<QString>();
|
|
||||||
case QVariant::StringList:
|
|
||||||
case QVariant::List: {
|
|
||||||
QStringList strList;
|
|
||||||
foreach (const QVariant &var, v.toList()) {
|
|
||||||
strList << toJson(var);
|
|
||||||
}
|
|
||||||
return "["+strList.join(",")+"]";
|
|
||||||
}
|
|
||||||
case QVariant::String: {
|
|
||||||
QString s = v.value<QString>();
|
|
||||||
QString result = "\"";
|
|
||||||
for (int i=0; i<s.size(); ++i) {
|
|
||||||
const QChar ch = s[i];
|
|
||||||
switch(ch.toAscii())
|
|
||||||
{
|
|
||||||
case '\b':
|
|
||||||
result += "\\b";
|
|
||||||
break;
|
|
||||||
case '\f':
|
|
||||||
result += "\\f";
|
|
||||||
break;
|
|
||||||
case '\n':
|
|
||||||
result += "\\n";
|
|
||||||
break;
|
|
||||||
case '\r':
|
|
||||||
result += "\\r";
|
|
||||||
break;
|
|
||||||
case '\t':
|
|
||||||
result += "\\t";
|
|
||||||
break;
|
|
||||||
case '\"':
|
|
||||||
case '\'':
|
|
||||||
case '\\':
|
|
||||||
case '&':
|
|
||||||
result += '\\';
|
|
||||||
case '\0':
|
|
||||||
default:
|
|
||||||
result += ch;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result += "\"";
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
qDebug("Unknown QVariantType: %d", (int)v.type());
|
|
||||||
return "undefined";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QString toJson(const QVariantMap& m) {
|
} // namespace json
|
||||||
QStringList vlist;
|
|
||||||
QVariantMap::ConstIterator it;
|
|
||||||
for (it = m.constBegin(); it != m.constEnd(); it++) {
|
|
||||||
vlist << toJson(it.key())+":"+toJson(it.value());
|
|
||||||
}
|
|
||||||
return "{"+vlist.join(",")+"}";
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariantMap fromJson(const QString& json) {
|
|
||||||
qDebug("JSON is %s", qPrintable(json));
|
|
||||||
QVariantMap m;
|
|
||||||
if (json.startsWith("{") && json.endsWith("}")) {
|
|
||||||
QStringList couples;
|
|
||||||
QString tmp = "";
|
|
||||||
bool in_list = false;
|
|
||||||
foreach (const QChar &c, json.mid(1, json.length()-2)) {
|
|
||||||
if (c == ',' && !in_list) {
|
|
||||||
couples << tmp;
|
|
||||||
tmp = "";
|
|
||||||
} else {
|
|
||||||
if (c == '[')
|
|
||||||
in_list = true;
|
|
||||||
else if (c == ']')
|
|
||||||
in_list = false;
|
|
||||||
tmp += c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!tmp.isEmpty()) couples << tmp;
|
|
||||||
|
|
||||||
foreach (const QString &couple, couples) {
|
|
||||||
QStringList parts = couple.split(":");
|
|
||||||
if (parts.size() != 2) continue;
|
|
||||||
QString key = parts.first();
|
|
||||||
if (key.startsWith("\"") && key.endsWith("\"")) {
|
|
||||||
key = key.mid(1, key.length()-2);
|
|
||||||
}
|
|
||||||
QString value_str = parts.last();
|
|
||||||
QVariant value;
|
|
||||||
if (value_str.startsWith("[") && value_str.endsWith("]")) {
|
|
||||||
value_str = value_str.mid(1, value_str.length()-2);
|
|
||||||
QStringList list_elems = value_str.split(",", QString::SkipEmptyParts);
|
|
||||||
QVariantList varlist;
|
|
||||||
foreach (const QString &list_val, list_elems) {
|
|
||||||
if (list_val.startsWith("\"") && list_val.endsWith("\"")) {
|
|
||||||
varlist << list_val.mid(1, list_val.length()-2).replace("\\n", "\n");
|
|
||||||
} else {
|
|
||||||
varlist << list_val.toInt();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
value = varlist;
|
|
||||||
} else {
|
|
||||||
if (value_str.startsWith("\"") && value_str.endsWith("\"")) {
|
|
||||||
value_str = value_str.mid(1, value_str.length()-2).replace("\\n", "\n");
|
|
||||||
value = value_str;
|
|
||||||
} else {
|
|
||||||
if (value_str.compare("false", Qt::CaseInsensitive) == 0)
|
|
||||||
value = false;
|
|
||||||
else if (value_str.compare("true", Qt::CaseInsensitive) == 0)
|
|
||||||
value = true;
|
|
||||||
else
|
|
||||||
value = value_str.toInt();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m.insert(key, value);
|
|
||||||
qDebug("%s:%s", key.toLocal8Bit().data(), value_str.toLocal8Bit().data());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString toJson(const QList<QVariantMap>& v) {
|
|
||||||
QStringList res;
|
|
||||||
foreach (QVariantMap m, v) {
|
|
||||||
QStringList vlist;
|
|
||||||
QVariantMap::ConstIterator it;
|
|
||||||
for (it = m.constBegin(); it != m.constEnd(); it++) {
|
|
||||||
vlist << toJson(it.key())+":"+toJson(it.value());
|
|
||||||
}
|
|
||||||
res << "{"+vlist.join(",")+"}";
|
|
||||||
}
|
|
||||||
return "["+res.join(",")+"]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
58
src/webui/jsondict.cpp
Normal file
58
src/webui/jsondict.cpp
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Bittorrent Client using Qt4 and libtorrent.
|
||||||
|
* Copyright (C) 2012, 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 "jsondict.h"
|
||||||
|
#include "json.h"
|
||||||
|
|
||||||
|
JsonDict::JsonDict(): m_dirty(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void JsonDict::clear()
|
||||||
|
{
|
||||||
|
m_items.clear();
|
||||||
|
m_dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JsonDict::add(const QString& key, const QVariant& value)
|
||||||
|
{
|
||||||
|
m_items.append("\"" + key + "\":" + json::toJson(value));
|
||||||
|
m_dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString& JsonDict::toString() const
|
||||||
|
{
|
||||||
|
static QString str;
|
||||||
|
if (m_dirty) {
|
||||||
|
str = "{" + m_items.join(",") + "}";
|
||||||
|
m_dirty = false;
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
49
src/webui/jsondict.h
Normal file
49
src/webui/jsondict.h
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Bittorrent Client using Qt4 and libtorrent.
|
||||||
|
* Copyright (C) 2012, 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef JSONDICT_H
|
||||||
|
#define JSONDICT_H
|
||||||
|
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
|
class JsonDict
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
JsonDict();
|
||||||
|
void clear();
|
||||||
|
void add(const QString& key, const QVariant& value);
|
||||||
|
const QString& toString() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
mutable bool m_dirty;
|
||||||
|
QStringList m_items;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // JSONDICT_H
|
64
src/webui/jsonlist.cpp
Normal file
64
src/webui/jsonlist.cpp
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* Bittorrent Client using Qt4 and libtorrent.
|
||||||
|
* Copyright (C) 2012, 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 "jsonlist.h"
|
||||||
|
#include "json.h"
|
||||||
|
|
||||||
|
JsonList::JsonList() : m_dirty(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString& JsonList::toString() const
|
||||||
|
{
|
||||||
|
static QString str;
|
||||||
|
if (m_dirty) {
|
||||||
|
str = "[" + m_items.join(",") + "]";
|
||||||
|
m_dirty = false;
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JsonList::clear()
|
||||||
|
{
|
||||||
|
m_items.clear();
|
||||||
|
m_dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JsonList::append(const QVariant& val)
|
||||||
|
{
|
||||||
|
m_items.append(json::toJson(val));
|
||||||
|
m_dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JsonList::append(const JsonDict& dict)
|
||||||
|
{
|
||||||
|
m_items.append(dict.toString());
|
||||||
|
m_dirty = true;
|
||||||
|
}
|
51
src/webui/jsonlist.h
Normal file
51
src/webui/jsonlist.h
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* Bittorrent Client using Qt4 and libtorrent.
|
||||||
|
* Copyright (C) 2012, 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef JSONLIST_H
|
||||||
|
#define JSONLIST_H
|
||||||
|
|
||||||
|
#include <QStringList>
|
||||||
|
#include "jsondict.h"
|
||||||
|
|
||||||
|
class JsonList
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
JsonList();
|
||||||
|
const QString& toString() const;
|
||||||
|
void clear();
|
||||||
|
void append(const QVariant& val);
|
||||||
|
void append(const JsonDict& dict);
|
||||||
|
|
||||||
|
private:
|
||||||
|
mutable bool m_dirty;
|
||||||
|
QStringList m_items;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // JSONLIST_H
|
@ -232,7 +232,7 @@ window.addEvent('load', function(){
|
|||||||
|
|
||||||
var ajaxfn = function(){
|
var ajaxfn = function(){
|
||||||
var queueing_enabled = false;
|
var queueing_enabled = false;
|
||||||
var url = 'json/events';
|
var url = 'json/torrents';
|
||||||
if (!waiting){
|
if (!waiting){
|
||||||
waiting=true;
|
waiting=true;
|
||||||
var request = new Request.JSON({
|
var request = new Request.JSON({
|
||||||
|
@ -5,12 +5,19 @@ HEADERS += $$PWD/httpserver.h \
|
|||||||
$$PWD/httprequestparser.h \
|
$$PWD/httprequestparser.h \
|
||||||
$$PWD/httpresponsegenerator.h \
|
$$PWD/httpresponsegenerator.h \
|
||||||
$$PWD/eventmanager.h \
|
$$PWD/eventmanager.h \
|
||||||
$$PWD/json.h
|
$$PWD/json.h \
|
||||||
|
$$PWD/jsonlist.h \
|
||||||
|
$$PWD/jsondict.h \
|
||||||
|
$$PWD/btjson.h
|
||||||
|
|
||||||
SOURCES += $$PWD/httpserver.cpp \
|
SOURCES += $$PWD/httpserver.cpp \
|
||||||
$$PWD/httpconnection.cpp \
|
$$PWD/httpconnection.cpp \
|
||||||
$$PWD/httprequestparser.cpp \
|
$$PWD/httprequestparser.cpp \
|
||||||
$$PWD/httpresponsegenerator.cpp \
|
$$PWD/httpresponsegenerator.cpp \
|
||||||
$$PWD/eventmanager.cpp
|
$$PWD/eventmanager.cpp \
|
||||||
|
$$PWD/jsonlist.cpp \
|
||||||
|
$$PWD/jsondict.cpp \
|
||||||
|
$$PWD/btjson.cpp \
|
||||||
|
$$PWD/json.cpp
|
||||||
|
|
||||||
RESOURCES += $$PWD/webui.qrc
|
RESOURCES += $$PWD/webui.qrc
|
Loading…
Reference in New Issue
Block a user