mirror of
https://git.deluge-torrent.org/deluge
synced 2025-08-09 01:48:40 +00:00
prepping for fix release
This commit is contained in:
parent
dbbace5f23
commit
ba7143acb9
57 changed files with 9535 additions and 450 deletions
|
@ -1,4 +1,8 @@
|
||||||
Deluge 0.5.6 (xx October 2007)
|
Deluge 0.5.7 (xx November 2007)
|
||||||
|
* Set default piece size to 256-KiB in TorrentCreator plugin and add 2048KiB
|
||||||
|
as a size option.
|
||||||
|
|
||||||
|
Deluge 0.5.6 (24 October 2007)
|
||||||
* Web Interface Plugin
|
* Web Interface Plugin
|
||||||
* Hopefully fix "losing data" and having to re-download parts (for real this time :p)
|
* Hopefully fix "losing data" and having to re-download parts (for real this time :p)
|
||||||
* Use new full allocation method which does not create files until one of its
|
* Use new full allocation method which does not create files until one of its
|
||||||
|
|
7
TODO
7
TODO
|
@ -1,2 +1,5 @@
|
||||||
for 0.5.6
|
for 0.5.7
|
||||||
1. fix ratio saving
|
1. manual recheck
|
||||||
|
2. preference for .torrent location
|
||||||
|
3. have blocklist detect 7zip files and popup a warning instead of crashing
|
||||||
|
4. add auto-pickup folder
|
||||||
|
|
|
@ -375,12 +375,6 @@ namespace libtorrent
|
||||||
// buffers from.
|
// buffers from.
|
||||||
boost::pool<> m_send_buffers;
|
boost::pool<> m_send_buffers;
|
||||||
|
|
||||||
// this is where all active sockets are stored.
|
|
||||||
// the selector can sleep while there's no activity on
|
|
||||||
// them
|
|
||||||
io_service m_io_service;
|
|
||||||
asio::strand m_strand;
|
|
||||||
|
|
||||||
// the file pool that all storages in this session's
|
// the file pool that all storages in this session's
|
||||||
// torrents uses. It sets a limit on the number of
|
// torrents uses. It sets a limit on the number of
|
||||||
// open files by this session.
|
// open files by this session.
|
||||||
|
@ -395,6 +389,12 @@ namespace libtorrent
|
||||||
// object.
|
// object.
|
||||||
disk_io_thread m_disk_thread;
|
disk_io_thread m_disk_thread;
|
||||||
|
|
||||||
|
// this is where all active sockets are stored.
|
||||||
|
// the selector can sleep while there's no activity on
|
||||||
|
// them
|
||||||
|
io_service m_io_service;
|
||||||
|
asio::strand m_strand;
|
||||||
|
|
||||||
// this is a list of half-open tcp connections
|
// this is a list of half-open tcp connections
|
||||||
// (only outgoing connections)
|
// (only outgoing connections)
|
||||||
// this has to be one of the last
|
// this has to be one of the last
|
||||||
|
@ -646,7 +646,7 @@ namespace libtorrent
|
||||||
|
|
||||||
void debug_log(const std::string& line)
|
void debug_log(const std::string& line)
|
||||||
{
|
{
|
||||||
(*m_ses.m_logger) << line << "\n";
|
(*m_ses.m_logger) << time_now_string() << " " << line << "\n";
|
||||||
}
|
}
|
||||||
session_impl& m_ses;
|
session_impl& m_ses;
|
||||||
};
|
};
|
||||||
|
|
|
@ -56,6 +56,7 @@ public:
|
||||||
void done(int ticket);
|
void done(int ticket);
|
||||||
void limit(int limit);
|
void limit(int limit);
|
||||||
int limit() const;
|
int limit() const;
|
||||||
|
void close();
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
|
|
||||||
|
|
|
@ -130,6 +130,8 @@ namespace libtorrent
|
||||||
, proxy_settings const& ps
|
, proxy_settings const& ps
|
||||||
, std::string const& password = "");
|
, std::string const& password = "");
|
||||||
|
|
||||||
|
void close();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
boost::intrusive_ptr<http_tracker_connection> self()
|
boost::intrusive_ptr<http_tracker_connection> self()
|
||||||
|
|
|
@ -357,6 +357,7 @@ namespace libtorrent
|
||||||
// the different priority levels
|
// the different priority levels
|
||||||
switch (piece_priority)
|
switch (piece_priority)
|
||||||
{
|
{
|
||||||
|
case 1: return prio;
|
||||||
case 2: return prio - 1;
|
case 2: return prio - 1;
|
||||||
case 3: return (std::max)(prio / 2, 1);
|
case 3: return (std::max)(prio / 2, 1);
|
||||||
case 4: return (std::max)(prio / 2 - 1, 1);
|
case 4: return (std::max)(prio / 2 - 1, 1);
|
||||||
|
|
|
@ -111,6 +111,7 @@ namespace libtorrent
|
||||||
, initial_picker_threshold(4)
|
, initial_picker_threshold(4)
|
||||||
, allowed_fast_set_size(10)
|
, allowed_fast_set_size(10)
|
||||||
, max_outstanding_disk_bytes_per_connection(64 * 1024)
|
, max_outstanding_disk_bytes_per_connection(64 * 1024)
|
||||||
|
, handshake_timeout(10)
|
||||||
#ifndef TORRENT_DISABLE_DHT
|
#ifndef TORRENT_DISABLE_DHT
|
||||||
, use_dht_as_fallback(true)
|
, use_dht_as_fallback(true)
|
||||||
#endif
|
#endif
|
||||||
|
@ -270,6 +271,11 @@ namespace libtorrent
|
||||||
// to not completely disrupt normal downloads.
|
// to not completely disrupt normal downloads.
|
||||||
int max_outstanding_disk_bytes_per_connection;
|
int max_outstanding_disk_bytes_per_connection;
|
||||||
|
|
||||||
|
// the number of seconds to wait for a handshake
|
||||||
|
// response from a peer. If no response is received
|
||||||
|
// within this time, the peer is disconnected.
|
||||||
|
int handshake_timeout;
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_DHT
|
#ifndef TORRENT_DISABLE_DHT
|
||||||
// while this is true, the dht will note be used unless the
|
// while this is true, the dht will note be used unless the
|
||||||
// tracker is online
|
// tracker is online
|
||||||
|
|
|
@ -240,8 +240,8 @@ namespace libtorrent
|
||||||
|
|
||||||
void parse_info_section(entry const& e);
|
void parse_info_section(entry const& e);
|
||||||
|
|
||||||
entry extra(char const* key) const
|
entry const* extra(char const* key) const
|
||||||
{ return m_extra_info[key]; }
|
{ return m_extra_info.find_key(key); }
|
||||||
|
|
||||||
// frees parts of the metadata that isn't
|
// frees parts of the metadata that isn't
|
||||||
// used by seeds
|
// used by seeds
|
||||||
|
|
|
@ -202,7 +202,7 @@ namespace libtorrent
|
||||||
|
|
||||||
void fail(int code, char const* msg);
|
void fail(int code, char const* msg);
|
||||||
void fail_timeout();
|
void fail_timeout();
|
||||||
void close();
|
virtual void close();
|
||||||
address const& bind_interface() const { return m_bind_interface; }
|
address const& bind_interface() const { return m_bind_interface; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -74,6 +74,8 @@ namespace libtorrent
|
||||||
, boost::weak_ptr<request_callback> c
|
, boost::weak_ptr<request_callback> c
|
||||||
, session_settings const& stn);
|
, session_settings const& stn);
|
||||||
|
|
||||||
|
void close();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
enum action_t
|
enum action_t
|
||||||
|
|
|
@ -148,8 +148,19 @@ private:
|
||||||
{
|
{
|
||||||
mapping[0].protocol = 0;
|
mapping[0].protocol = 0;
|
||||||
mapping[1].protocol = 1;
|
mapping[1].protocol = 1;
|
||||||
|
#ifndef NDEBUG
|
||||||
|
magic = 1337;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
~rootdevice()
|
||||||
|
{
|
||||||
|
TORRENT_ASSERT(magic == 1337);
|
||||||
|
magic = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// the interface url, through which the list of
|
// the interface url, through which the list of
|
||||||
// supported interfaces are fetched
|
// supported interfaces are fetched
|
||||||
std::string url;
|
std::string url;
|
||||||
|
@ -174,8 +185,12 @@ private:
|
||||||
|
|
||||||
mutable boost::shared_ptr<http_connection> upnp_connection;
|
mutable boost::shared_ptr<http_connection> upnp_connection;
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
int magic;
|
||||||
|
#endif
|
||||||
void close() const
|
void close() const
|
||||||
{
|
{
|
||||||
|
TORRENT_ASSERT(magic == 1337);
|
||||||
if (!upnp_connection) return;
|
if (!upnp_connection) return;
|
||||||
upnp_connection->close();
|
upnp_connection->close();
|
||||||
upnp_connection.reset();
|
upnp_connection.reset();
|
||||||
|
|
|
@ -48,8 +48,8 @@ namespace aux
|
||||||
template<class IO_Control_Command>
|
template<class IO_Control_Command>
|
||||||
struct io_control_visitor_ec: boost::static_visitor<>
|
struct io_control_visitor_ec: boost::static_visitor<>
|
||||||
{
|
{
|
||||||
io_control_visitor_ec(IO_Control_Command& ioc, asio::error_code& ec)
|
io_control_visitor_ec(IO_Control_Command& ioc, asio::error_code& ec_)
|
||||||
: ioc(ioc), ec(ec) {}
|
: ioc(ioc), ec(ec_) {}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
void operator()(T* p) const
|
void operator()(T* p) const
|
||||||
|
@ -188,7 +188,7 @@ namespace aux
|
||||||
: boost::static_visitor<>
|
: boost::static_visitor<>
|
||||||
{
|
{
|
||||||
close_visitor_ec(asio::error_code& ec_)
|
close_visitor_ec(asio::error_code& ec_)
|
||||||
: ec(ec)
|
: ec(ec_)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
|
@ -329,9 +329,9 @@ namespace aux
|
||||||
struct read_some_visitor_ec
|
struct read_some_visitor_ec
|
||||||
: boost::static_visitor<std::size_t>
|
: boost::static_visitor<std::size_t>
|
||||||
{
|
{
|
||||||
read_some_visitor_ec(Mutable_Buffers const& buffers, asio::error_code& ec)
|
read_some_visitor_ec(Mutable_Buffers const& buffers, asio::error_code& ec_)
|
||||||
: buffers(buffers)
|
: buffers(buffers)
|
||||||
, ec(ec)
|
, ec(ec_)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
|
|
|
@ -86,6 +86,11 @@ namespace libtorrent
|
||||||
try_connect();
|
try_connect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void connection_queue::close()
|
||||||
|
{
|
||||||
|
m_timer.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
void connection_queue::limit(int limit)
|
void connection_queue::limit(int limit)
|
||||||
{ m_half_open_limit = limit; }
|
{ m_half_open_limit = limit; }
|
||||||
|
|
||||||
|
|
|
@ -342,6 +342,10 @@ namespace libtorrent
|
||||||
try { if (handler) handler(ret, j); }
|
try { if (handler) handler(ret, j); }
|
||||||
catch (std::exception&) {}
|
catch (std::exception&) {}
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
m_current.storage = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (j.buffer && free_buffer)
|
if (j.buffer && free_buffer)
|
||||||
{
|
{
|
||||||
l.lock();
|
l.lock();
|
||||||
|
|
|
@ -489,7 +489,9 @@ namespace libtorrent
|
||||||
, boost::lexical_cast<std::string>(m_port));
|
, boost::lexical_cast<std::string>(m_port));
|
||||||
m_name_lookup.async_resolve(q, m_strand.wrap(
|
m_name_lookup.async_resolve(q, m_strand.wrap(
|
||||||
boost::bind(&http_tracker_connection::name_lookup, self(), _1, _2)));
|
boost::bind(&http_tracker_connection::name_lookup, self(), _1, _2)));
|
||||||
set_timeout(m_settings.tracker_completion_timeout
|
set_timeout(req.event == tracker_request::stopped
|
||||||
|
? m_settings.stop_tracker_timeout
|
||||||
|
: m_settings.tracker_completion_timeout
|
||||||
, m_settings.tracker_receive_timeout);
|
, m_settings.tracker_receive_timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -503,6 +505,17 @@ namespace libtorrent
|
||||||
fail_timeout();
|
fail_timeout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void http_tracker_connection::close()
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
m_socket.close(ec);
|
||||||
|
m_name_lookup.cancel();
|
||||||
|
if (m_connection_ticket > -1) m_cc.done(m_connection_ticket);
|
||||||
|
m_connection_ticket = -1;
|
||||||
|
m_timed_out = true;
|
||||||
|
tracker_connection::close();
|
||||||
|
}
|
||||||
|
|
||||||
void http_tracker_connection::name_lookup(asio::error_code const& error
|
void http_tracker_connection::name_lookup(asio::error_code const& error
|
||||||
, tcp::resolver::iterator i) try
|
, tcp::resolver::iterator i) try
|
||||||
{
|
{
|
||||||
|
@ -759,7 +772,6 @@ namespace libtorrent
|
||||||
if (m_parser.status_code() != 200)
|
if (m_parser.status_code() != 200)
|
||||||
{
|
{
|
||||||
fail(m_parser.status_code(), m_parser.message().c_str());
|
fail(m_parser.status_code(), m_parser.message().c_str());
|
||||||
close();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -821,6 +833,7 @@ namespace libtorrent
|
||||||
TORRENT_ASSERT(false);
|
TORRENT_ASSERT(false);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
peer_entry http_tracker_connection::extract_peer_info(const entry& info)
|
peer_entry http_tracker_connection::extract_peer_info(const entry& info)
|
||||||
|
|
|
@ -184,5 +184,6 @@ void lsd::on_announce(udp::endpoint const& from, char* buffer
|
||||||
void lsd::close()
|
void lsd::close()
|
||||||
{
|
{
|
||||||
m_socket.close();
|
m_socket.close();
|
||||||
|
m_broadcast_timer.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -382,6 +382,8 @@ void natpmp::try_next_mapping(int i)
|
||||||
|
|
||||||
void natpmp::close()
|
void natpmp::close()
|
||||||
{
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
m_socket.close(ec);
|
||||||
if (m_disabled) return;
|
if (m_disabled) return;
|
||||||
for (int i = 0; i < num_mappings; ++i)
|
for (int i = 0; i < num_mappings; ++i)
|
||||||
{
|
{
|
||||||
|
@ -390,5 +392,7 @@ void natpmp::close()
|
||||||
m_mappings[i].external_port = 0;
|
m_mappings[i].external_port = 0;
|
||||||
refresh_mapping(i);
|
refresh_mapping(i);
|
||||||
}
|
}
|
||||||
|
m_refresh_timer.cancel();
|
||||||
|
m_send_timer.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3000,13 +3000,12 @@ namespace libtorrent
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if it takes more than 5 seconds to receive
|
// do not stall waiting for a handshake
|
||||||
// handshake, disconnect
|
if (in_handshake() && d > seconds(m_ses.settings().handshake_timeout))
|
||||||
if (in_handshake() && d > seconds(5))
|
|
||||||
{
|
{
|
||||||
#ifdef TORRENT_VERBOSE_LOGGING
|
#ifdef TORRENT_VERBOSE_LOGGING
|
||||||
(*m_logger) << time_now_string() << " *** NO HANDSHAKE [ "
|
(*m_logger) << time_now_string() << " *** NO HANDSHAKE [ waited "
|
||||||
<< total_seconds(d) << " seconds ago ] ***\n";
|
<< total_seconds(d) << " seconds ] ***\n";
|
||||||
#endif
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -547,8 +547,8 @@ namespace detail
|
||||||
, fingerprint const& cl_fprint
|
, fingerprint const& cl_fprint
|
||||||
, char const* listen_interface)
|
, char const* listen_interface)
|
||||||
: m_send_buffers(send_buffer_size)
|
: m_send_buffers(send_buffer_size)
|
||||||
, m_strand(m_io_service)
|
|
||||||
, m_files(40)
|
, m_files(40)
|
||||||
|
, m_strand(m_io_service)
|
||||||
, m_half_open(m_io_service)
|
, m_half_open(m_io_service)
|
||||||
, m_download_channel(m_io_service, peer_connection::download_channel)
|
, m_download_channel(m_io_service, peer_connection::download_channel)
|
||||||
, m_upload_channel(m_io_service, peer_connection::upload_channel)
|
, m_upload_channel(m_io_service, peer_connection::upload_channel)
|
||||||
|
@ -675,6 +675,14 @@ namespace detail
|
||||||
if (m_dht) m_dht->stop();
|
if (m_dht) m_dht->stop();
|
||||||
#endif
|
#endif
|
||||||
m_timer.cancel();
|
m_timer.cancel();
|
||||||
|
|
||||||
|
// close the listen sockets
|
||||||
|
for (std::list<listen_socket_t>::iterator i = m_listen_sockets.begin()
|
||||||
|
, end(m_listen_sockets.end()); i != end; ++i)
|
||||||
|
{
|
||||||
|
i->sock->close();
|
||||||
|
}
|
||||||
|
|
||||||
// abort all torrents
|
// abort all torrents
|
||||||
for (torrent_map::iterator i = m_torrents.begin()
|
for (torrent_map::iterator i = m_torrents.begin()
|
||||||
, end(m_torrents.end()); i != end; ++i)
|
, end(m_torrents.end()); i != end; ++i)
|
||||||
|
@ -682,7 +690,15 @@ namespace detail
|
||||||
i->second->abort();
|
i->second->abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_io_service.stop();
|
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||||
|
(*m_logger) << time_now_string() << " aborting all tracker requests\n";
|
||||||
|
#endif
|
||||||
|
m_tracker_manager.abort_all_requests();
|
||||||
|
|
||||||
|
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||||
|
(*m_logger) << time_now_string() << " shutting down connection queue\n";
|
||||||
|
#endif
|
||||||
|
m_half_open.close();
|
||||||
|
|
||||||
mutex::scoped_lock l2(m_checker_impl.m_mutex);
|
mutex::scoped_lock l2(m_checker_impl.m_mutex);
|
||||||
// abort the checker thread
|
// abort the checker thread
|
||||||
|
@ -977,6 +993,17 @@ namespace detail
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// don't allow more connections than the max setting
|
||||||
|
if (m_connections.size() > max_connections())
|
||||||
|
{
|
||||||
|
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||||
|
(*m_logger) << "number of connections limit exceeded (conns: "
|
||||||
|
<< num_connections() << ", limit: " << max_connections()
|
||||||
|
<< "), connection rejected\n";
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// check if we have any active torrents
|
// check if we have any active torrents
|
||||||
// if we don't reject the connection
|
// if we don't reject the connection
|
||||||
if (m_torrents.empty()) return;
|
if (m_torrents.empty()) return;
|
||||||
|
@ -1474,20 +1501,12 @@ namespace detail
|
||||||
while (!m_abort);
|
while (!m_abort);
|
||||||
|
|
||||||
deadline_timer tracker_timer(m_io_service);
|
deadline_timer tracker_timer(m_io_service);
|
||||||
// this will remove the port mappings
|
|
||||||
if (m_natpmp.get())
|
|
||||||
m_natpmp->close();
|
|
||||||
if (m_upnp.get())
|
|
||||||
m_upnp->close();
|
|
||||||
|
|
||||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||||
(*m_logger) << time_now_string() << " locking mutex\n";
|
(*m_logger) << time_now_string() << " locking mutex\n";
|
||||||
#endif
|
#endif
|
||||||
session_impl::mutex_t::scoped_lock l(m_mutex);
|
session_impl::mutex_t::scoped_lock l(m_mutex);
|
||||||
|
|
||||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
|
||||||
(*m_logger) << time_now_string() << " aborting all tracker requests\n";
|
|
||||||
#endif
|
|
||||||
m_tracker_manager.abort_all_requests();
|
m_tracker_manager.abort_all_requests();
|
||||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||||
(*m_logger) << time_now_string() << " sending stopped to all torrent's trackers\n";
|
(*m_logger) << time_now_string() << " sending stopped to all torrent's trackers\n";
|
||||||
|
@ -2127,16 +2146,10 @@ namespace detail
|
||||||
|
|
||||||
session_impl::~session_impl()
|
session_impl::~session_impl()
|
||||||
{
|
{
|
||||||
abort();
|
|
||||||
|
|
||||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||||
(*m_logger) << time_now_string() << "\n\n *** shutting down session *** \n\n";
|
(*m_logger) << time_now_string() << "\n\n *** shutting down session *** \n\n";
|
||||||
#endif
|
#endif
|
||||||
// lock the main thread and abort it
|
abort();
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
|
||||||
m_abort = true;
|
|
||||||
m_io_service.stop();
|
|
||||||
l.unlock();
|
|
||||||
|
|
||||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||||
(*m_logger) << time_now_string() << " waiting for main thread\n";
|
(*m_logger) << time_now_string() << " waiting for main thread\n";
|
||||||
|
|
|
@ -1526,7 +1526,7 @@ namespace libtorrent
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||||
(*m_ses.m_logger) << time_now_string() << " resolving: " << url << "\n";
|
(*m_ses.m_logger) << time_now_string() << " resolving web seed: " << url << "\n";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
m_resolving_web_seeds.insert(url);
|
m_resolving_web_seeds.insert(url);
|
||||||
|
@ -3055,7 +3055,7 @@ namespace libtorrent
|
||||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||||
void torrent::debug_log(const std::string& line)
|
void torrent::debug_log(const std::string& line)
|
||||||
{
|
{
|
||||||
(*m_ses.m_logger) << line << "\n";
|
(*m_ses.m_logger) << time_now_string() << " " << line << "\n";
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -302,12 +302,12 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
m_completion_timeout = completion_timeout;
|
m_completion_timeout = completion_timeout;
|
||||||
m_read_timeout = read_timeout;
|
m_read_timeout = read_timeout;
|
||||||
m_start_time = time_now();
|
m_start_time = m_read_time = time_now();
|
||||||
m_read_time = time_now();
|
|
||||||
|
|
||||||
m_timeout.expires_at((std::min)(
|
m_timeout.expires_at((std::min)(
|
||||||
m_read_time + seconds(m_read_timeout)
|
m_read_time + seconds(m_read_timeout)
|
||||||
, m_start_time + seconds(m_completion_timeout)));
|
, m_start_time + seconds((std::min)(m_completion_timeout
|
||||||
|
, m_read_timeout))));
|
||||||
m_timeout.async_wait(m_strand.wrap(bind(
|
m_timeout.async_wait(m_strand.wrap(bind(
|
||||||
&timeout_handler::timeout_callback, self(), _1)));
|
&timeout_handler::timeout_callback, self(), _1)));
|
||||||
}
|
}
|
||||||
|
@ -343,7 +343,8 @@ namespace libtorrent
|
||||||
|
|
||||||
m_timeout.expires_at((std::min)(
|
m_timeout.expires_at((std::min)(
|
||||||
m_read_time + seconds(m_read_timeout)
|
m_read_time + seconds(m_read_timeout)
|
||||||
, m_start_time + seconds(m_completion_timeout)));
|
, m_start_time + seconds((std::min)(m_completion_timeout
|
||||||
|
, m_read_timeout))));
|
||||||
m_timeout.async_wait(m_strand.wrap(
|
m_timeout.async_wait(m_strand.wrap(
|
||||||
bind(&timeout_handler::timeout_callback, self(), _1)));
|
bind(&timeout_handler::timeout_callback, self(), _1)));
|
||||||
}
|
}
|
||||||
|
@ -567,12 +568,24 @@ namespace libtorrent
|
||||||
m_abort = true;
|
m_abort = true;
|
||||||
tracker_connections_t keep_connections;
|
tracker_connections_t keep_connections;
|
||||||
|
|
||||||
for (tracker_connections_t::const_iterator i =
|
while (!m_connections.empty())
|
||||||
m_connections.begin(); i != m_connections.end(); ++i)
|
|
||||||
{
|
{
|
||||||
tracker_request const& req = (*i)->tracker_req();
|
boost::intrusive_ptr<tracker_connection>& c = m_connections.back();
|
||||||
|
if (!c)
|
||||||
|
{
|
||||||
|
m_connections.pop_back();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
tracker_request const& req = c->tracker_req();
|
||||||
if (req.event == tracker_request::stopped)
|
if (req.event == tracker_request::stopped)
|
||||||
keep_connections.push_back(*i);
|
{
|
||||||
|
keep_connections.push_back(c);
|
||||||
|
m_connections.pop_back();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// close will remove the entry from m_connections
|
||||||
|
// so no need to pop
|
||||||
|
c->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::swap(m_connections, keep_connections);
|
std::swap(m_connections, keep_connections);
|
||||||
|
|
|
@ -96,7 +96,9 @@ namespace libtorrent
|
||||||
m_name_lookup.async_resolve(q
|
m_name_lookup.async_resolve(q
|
||||||
, m_strand.wrap(boost::bind(
|
, m_strand.wrap(boost::bind(
|
||||||
&udp_tracker_connection::name_lookup, self(), _1, _2)));
|
&udp_tracker_connection::name_lookup, self(), _1, _2)));
|
||||||
set_timeout(m_settings.tracker_completion_timeout
|
set_timeout(req.event == tracker_request::stopped
|
||||||
|
? m_settings.stop_tracker_timeout
|
||||||
|
: m_settings.tracker_completion_timeout
|
||||||
, m_settings.tracker_receive_timeout);
|
, m_settings.tracker_receive_timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,11 +158,20 @@ namespace libtorrent
|
||||||
|
|
||||||
void udp_tracker_connection::on_timeout()
|
void udp_tracker_connection::on_timeout()
|
||||||
{
|
{
|
||||||
m_socket.close();
|
asio::error_code ec;
|
||||||
|
m_socket.close(ec);
|
||||||
m_name_lookup.cancel();
|
m_name_lookup.cancel();
|
||||||
fail_timeout();
|
fail_timeout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void udp_tracker_connection::close()
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
m_socket.close(ec);
|
||||||
|
m_name_lookup.cancel();
|
||||||
|
tracker_connection::close();
|
||||||
|
}
|
||||||
|
|
||||||
void udp_tracker_connection::send_udp_connect()
|
void udp_tracker_connection::send_udp_connect()
|
||||||
{
|
{
|
||||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||||
|
@ -468,6 +479,7 @@ namespace libtorrent
|
||||||
, complete, incomplete);
|
, complete, incomplete);
|
||||||
|
|
||||||
m_man.remove_request(this);
|
m_man.remove_request(this);
|
||||||
|
close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
|
@ -543,6 +555,7 @@ namespace libtorrent
|
||||||
if (!cb)
|
if (!cb)
|
||||||
{
|
{
|
||||||
m_man.remove_request(this);
|
m_man.remove_request(this);
|
||||||
|
close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -551,6 +564,7 @@ namespace libtorrent
|
||||||
, complete, incomplete);
|
, complete, incomplete);
|
||||||
|
|
||||||
m_man.remove_request(this);
|
m_man.remove_request(this);
|
||||||
|
close();
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
|
|
|
@ -148,6 +148,7 @@ void upnp::set_mappings(int tcp, int udp)
|
||||||
, end(m_devices.end()); i != end; ++i)
|
, end(m_devices.end()); i != end; ++i)
|
||||||
{
|
{
|
||||||
rootdevice& d = const_cast<rootdevice&>(*i);
|
rootdevice& d = const_cast<rootdevice&>(*i);
|
||||||
|
TORRENT_ASSERT(d.magic == 1337);
|
||||||
if (d.mapping[0].local_port != m_tcp_local_port)
|
if (d.mapping[0].local_port != m_tcp_local_port)
|
||||||
{
|
{
|
||||||
if (d.mapping[0].external_port == 0)
|
if (d.mapping[0].external_port == 0)
|
||||||
|
@ -200,8 +201,13 @@ try
|
||||||
// we don't have a WANIP or WANPPP url for this device,
|
// we don't have a WANIP or WANPPP url for this device,
|
||||||
// ask for it
|
// ask for it
|
||||||
rootdevice& d = const_cast<rootdevice&>(*i);
|
rootdevice& d = const_cast<rootdevice&>(*i);
|
||||||
|
TORRENT_ASSERT(d.magic == 1337);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
#ifdef TORRENT_UPNP_LOGGING
|
||||||
|
m_log << time_now_string()
|
||||||
|
<< " ==> connecting to " << d.url << std::endl;
|
||||||
|
#endif
|
||||||
d.upnp_connection.reset(new http_connection(m_io_service
|
d.upnp_connection.reset(new http_connection(m_io_service
|
||||||
, m_cc, m_strand.wrap(bind(&upnp::on_upnp_xml, self(), _1, _2
|
, m_cc, m_strand.wrap(bind(&upnp::on_upnp_xml, self(), _1, _2
|
||||||
, boost::ref(d)))));
|
, boost::ref(d)))));
|
||||||
|
@ -270,7 +276,7 @@ try
|
||||||
{
|
{
|
||||||
#ifdef TORRENT_UPNP_LOGGING
|
#ifdef TORRENT_UPNP_LOGGING
|
||||||
m_log << time_now_string()
|
m_log << time_now_string()
|
||||||
<< " <== Rootdevice responded with incorrect HTTP packet. Ignoring device (" << e.what() << ")" << std::endl;
|
<< " <== (" << from << ") Rootdevice responded with incorrect HTTP packet. Ignoring device (" << e.what() << ")" << std::endl;
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -280,11 +286,11 @@ try
|
||||||
#ifdef TORRENT_UPNP_LOGGING
|
#ifdef TORRENT_UPNP_LOGGING
|
||||||
if (p.method().empty())
|
if (p.method().empty())
|
||||||
m_log << time_now_string()
|
m_log << time_now_string()
|
||||||
<< " <== Device responded with HTTP status: " << p.status_code()
|
<< " <== (" << from << ") Device responded with HTTP status: " << p.status_code()
|
||||||
<< ". Ignoring device" << std::endl;
|
<< ". Ignoring device" << std::endl;
|
||||||
else
|
else
|
||||||
m_log << time_now_string()
|
m_log << time_now_string()
|
||||||
<< " <== Device with HTTP method: " << p.method()
|
<< " <== (" << from << ") Device with HTTP method: " << p.method()
|
||||||
<< ". Ignoring device" << std::endl;
|
<< ". Ignoring device" << std::endl;
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
|
@ -294,7 +300,7 @@ try
|
||||||
{
|
{
|
||||||
#ifdef TORRENT_UPNP_LOGGING
|
#ifdef TORRENT_UPNP_LOGGING
|
||||||
m_log << time_now_string()
|
m_log << time_now_string()
|
||||||
<< " <== Rootdevice responded with incomplete HTTP "
|
<< " <== (" << from << ") Rootdevice responded with incomplete HTTP "
|
||||||
"packet. Ignoring device" << std::endl;
|
"packet. Ignoring device" << std::endl;
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
|
@ -305,7 +311,7 @@ try
|
||||||
{
|
{
|
||||||
#ifdef TORRENT_UPNP_LOGGING
|
#ifdef TORRENT_UPNP_LOGGING
|
||||||
m_log << time_now_string()
|
m_log << time_now_string()
|
||||||
<< " <== Rootdevice response is missing a location header. "
|
<< " <== (" << from << ") Rootdevice response is missing a location header. "
|
||||||
"Ignoring device" << std::endl;
|
"Ignoring device" << std::endl;
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
|
@ -332,7 +338,7 @@ try
|
||||||
{
|
{
|
||||||
#ifdef TORRENT_UPNP_LOGGING
|
#ifdef TORRENT_UPNP_LOGGING
|
||||||
m_log << time_now_string()
|
m_log << time_now_string()
|
||||||
<< " <== Rootdevice uses unsupported protocol: '" << protocol
|
<< " <== (" << from << ") Rootdevice uses unsupported protocol: '" << protocol
|
||||||
<< "'. Ignoring device" << std::endl;
|
<< "'. Ignoring device" << std::endl;
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
|
@ -342,16 +348,27 @@ try
|
||||||
{
|
{
|
||||||
#ifdef TORRENT_UPNP_LOGGING
|
#ifdef TORRENT_UPNP_LOGGING
|
||||||
m_log << time_now_string()
|
m_log << time_now_string()
|
||||||
<< " <== Rootdevice responded with a url with port 0. "
|
<< " <== (" << from << ") Rootdevice responded with a url with port 0. "
|
||||||
"Ignoring device" << std::endl;
|
"Ignoring device" << std::endl;
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#ifdef TORRENT_UPNP_LOGGING
|
#ifdef TORRENT_UPNP_LOGGING
|
||||||
m_log << time_now_string()
|
m_log << time_now_string()
|
||||||
<< " <== Found rootdevice: " << d.url << std::endl;
|
<< " <== (" << from << ") Found rootdevice: " << d.url
|
||||||
|
<< " total: " << m_devices.size() << std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (m_devices.size() >= 50)
|
||||||
|
{
|
||||||
|
#ifdef TORRENT_UPNP_LOGGING
|
||||||
|
m_log << time_now_string()
|
||||||
|
<< " <== (" << from << ") Too many devices (" << m_devices.size() << "), "
|
||||||
|
"ignoring: " << d.url << std::endl;
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_tcp_local_port != 0)
|
if (m_tcp_local_port != 0)
|
||||||
{
|
{
|
||||||
d.mapping[0].need_update = true;
|
d.mapping[0].need_update = true;
|
||||||
|
@ -390,8 +407,13 @@ try
|
||||||
// we don't have a WANIP or WANPPP url for this device,
|
// we don't have a WANIP or WANPPP url for this device,
|
||||||
// ask for it
|
// ask for it
|
||||||
rootdevice& d = const_cast<rootdevice&>(*i);
|
rootdevice& d = const_cast<rootdevice&>(*i);
|
||||||
|
TORRENT_ASSERT(d.magic == 1337);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
#ifdef TORRENT_UPNP_LOGGING
|
||||||
|
m_log << time_now_string()
|
||||||
|
<< " ==> connecting to " << d.url << std::endl;
|
||||||
|
#endif
|
||||||
d.upnp_connection.reset(new http_connection(m_io_service
|
d.upnp_connection.reset(new http_connection(m_io_service
|
||||||
, m_cc, m_strand.wrap(bind(&upnp::on_upnp_xml, self(), _1, _2
|
, m_cc, m_strand.wrap(bind(&upnp::on_upnp_xml, self(), _1, _2
|
||||||
, boost::ref(d)))));
|
, boost::ref(d)))));
|
||||||
|
@ -420,6 +442,7 @@ catch (std::exception&)
|
||||||
void upnp::post(upnp::rootdevice const& d, std::string const& soap
|
void upnp::post(upnp::rootdevice const& d, std::string const& soap
|
||||||
, std::string const& soap_action)
|
, std::string const& soap_action)
|
||||||
{
|
{
|
||||||
|
TORRENT_ASSERT(d.magic == 1337);
|
||||||
std::stringstream header;
|
std::stringstream header;
|
||||||
|
|
||||||
header << "POST " << d.control_url << " HTTP/1.1\r\n"
|
header << "POST " << d.control_url << " HTTP/1.1\r\n"
|
||||||
|
@ -439,6 +462,7 @@ void upnp::post(upnp::rootdevice const& d, std::string const& soap
|
||||||
|
|
||||||
void upnp::create_port_mapping(http_connection& c, rootdevice& d, int i)
|
void upnp::create_port_mapping(http_connection& c, rootdevice& d, int i)
|
||||||
{
|
{
|
||||||
|
TORRENT_ASSERT(d.magic == 1337);
|
||||||
std::string soap_action = "AddPortMapping";
|
std::string soap_action = "AddPortMapping";
|
||||||
|
|
||||||
std::stringstream soap;
|
std::stringstream soap;
|
||||||
|
@ -463,6 +487,7 @@ void upnp::create_port_mapping(http_connection& c, rootdevice& d, int i)
|
||||||
|
|
||||||
void upnp::map_port(rootdevice& d, int i)
|
void upnp::map_port(rootdevice& d, int i)
|
||||||
{
|
{
|
||||||
|
TORRENT_ASSERT(d.magic == 1337);
|
||||||
if (d.upnp_connection) return;
|
if (d.upnp_connection) return;
|
||||||
|
|
||||||
if (!d.mapping[i].need_update)
|
if (!d.mapping[i].need_update)
|
||||||
|
@ -479,6 +504,10 @@ void upnp::map_port(rootdevice& d, int i)
|
||||||
TORRENT_ASSERT(!d.upnp_connection);
|
TORRENT_ASSERT(!d.upnp_connection);
|
||||||
TORRENT_ASSERT(d.service_namespace);
|
TORRENT_ASSERT(d.service_namespace);
|
||||||
|
|
||||||
|
#ifdef TORRENT_UPNP_LOGGING
|
||||||
|
m_log << time_now_string()
|
||||||
|
<< " ==> connecting to " << d.hostname << std::endl;
|
||||||
|
#endif
|
||||||
d.upnp_connection.reset(new http_connection(m_io_service
|
d.upnp_connection.reset(new http_connection(m_io_service
|
||||||
, m_cc, m_strand.wrap(bind(&upnp::on_upnp_map_response, self(), _1, _2
|
, m_cc, m_strand.wrap(bind(&upnp::on_upnp_map_response, self(), _1, _2
|
||||||
, boost::ref(d), i)), true
|
, boost::ref(d), i)), true
|
||||||
|
@ -490,6 +519,7 @@ void upnp::map_port(rootdevice& d, int i)
|
||||||
|
|
||||||
void upnp::delete_port_mapping(rootdevice& d, int i)
|
void upnp::delete_port_mapping(rootdevice& d, int i)
|
||||||
{
|
{
|
||||||
|
TORRENT_ASSERT(d.magic == 1337);
|
||||||
std::stringstream soap;
|
std::stringstream soap;
|
||||||
|
|
||||||
std::string soap_action = "DeletePortMapping";
|
std::string soap_action = "DeletePortMapping";
|
||||||
|
@ -510,23 +540,24 @@ void upnp::delete_port_mapping(rootdevice& d, int i)
|
||||||
// requires the mutex to be locked
|
// requires the mutex to be locked
|
||||||
void upnp::unmap_port(rootdevice& d, int i)
|
void upnp::unmap_port(rootdevice& d, int i)
|
||||||
{
|
{
|
||||||
if (d.mapping[i].external_port == 0)
|
TORRENT_ASSERT(d.magic == 1337);
|
||||||
|
if (d.mapping[i].external_port == 0
|
||||||
|
|| d.disabled)
|
||||||
{
|
{
|
||||||
if (i < num_mappings - 1)
|
if (i < num_mappings - 1)
|
||||||
{
|
{
|
||||||
unmap_port(d, i + 1);
|
unmap_port(d, i + 1);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
m_devices.erase(d);
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#ifdef TORRENT_UPNP_LOGGING
|
||||||
|
m_log << time_now_string()
|
||||||
|
<< " ==> connecting to " << d.hostname << std::endl;
|
||||||
|
#endif
|
||||||
d.upnp_connection.reset(new http_connection(m_io_service
|
d.upnp_connection.reset(new http_connection(m_io_service
|
||||||
, m_cc, m_strand.wrap(bind(&upnp::on_upnp_unmap_response, self(), _1, _2
|
, m_cc, m_strand.wrap(bind(&upnp::on_upnp_unmap_response, self(), _1, _2
|
||||||
, boost::ref(d), i)), true
|
, boost::ref(d), i)), true
|
||||||
, bind(&upnp::delete_port_mapping, self(), boost::ref(d), i)));
|
, bind(&upnp::delete_port_mapping, self(), boost::ref(d), i)));
|
||||||
|
|
||||||
d.upnp_connection->start(d.hostname, boost::lexical_cast<std::string>(d.port)
|
d.upnp_connection->start(d.hostname, boost::lexical_cast<std::string>(d.port)
|
||||||
, seconds(10));
|
, seconds(10));
|
||||||
}
|
}
|
||||||
|
@ -591,6 +622,7 @@ namespace
|
||||||
void upnp::on_upnp_xml(asio::error_code const& e
|
void upnp::on_upnp_xml(asio::error_code const& e
|
||||||
, libtorrent::http_parser const& p, rootdevice& d) try
|
, libtorrent::http_parser const& p, rootdevice& d) try
|
||||||
{
|
{
|
||||||
|
TORRENT_ASSERT(d.magic == 1337);
|
||||||
if (d.upnp_connection)
|
if (d.upnp_connection)
|
||||||
{
|
{
|
||||||
d.upnp_connection->close();
|
d.upnp_connection->close();
|
||||||
|
@ -601,8 +633,10 @@ void upnp::on_upnp_xml(asio::error_code const& e
|
||||||
{
|
{
|
||||||
#ifdef TORRENT_UPNP_LOGGING
|
#ifdef TORRENT_UPNP_LOGGING
|
||||||
m_log << time_now_string()
|
m_log << time_now_string()
|
||||||
<< " <== error while fetching control url: " << e.message() << std::endl;
|
<< " <== (" << d.url << ") error while fetching control url: "
|
||||||
|
<< e.message() << std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
d.disabled = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -610,8 +644,9 @@ void upnp::on_upnp_xml(asio::error_code const& e
|
||||||
{
|
{
|
||||||
#ifdef TORRENT_UPNP_LOGGING
|
#ifdef TORRENT_UPNP_LOGGING
|
||||||
m_log << time_now_string()
|
m_log << time_now_string()
|
||||||
<< " <== error while fetching control url: incomplete http message" << std::endl;
|
<< " <== (" << d.url << ") error while fetching control url: incomplete http message" << std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
d.disabled = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -619,8 +654,9 @@ void upnp::on_upnp_xml(asio::error_code const& e
|
||||||
{
|
{
|
||||||
#ifdef TORRENT_UPNP_LOGGING
|
#ifdef TORRENT_UPNP_LOGGING
|
||||||
m_log << time_now_string()
|
m_log << time_now_string()
|
||||||
<< " <== error while fetching control url: " << p.message() << std::endl;
|
<< " <== (" << d.url << ") error while fetching control url: " << p.message() << std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
d.disabled = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -647,15 +683,17 @@ void upnp::on_upnp_xml(asio::error_code const& e
|
||||||
{
|
{
|
||||||
#ifdef TORRENT_UPNP_LOGGING
|
#ifdef TORRENT_UPNP_LOGGING
|
||||||
m_log << time_now_string()
|
m_log << time_now_string()
|
||||||
<< " <== Rootdevice response, did not find a port mapping interface" << std::endl;
|
<< " <== (" << d.url << ") Rootdevice response, did not find "
|
||||||
|
"a port mapping interface" << std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
d.disabled = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TORRENT_UPNP_LOGGING
|
#ifdef TORRENT_UPNP_LOGGING
|
||||||
m_log << time_now_string()
|
m_log << time_now_string()
|
||||||
<< " <== Rootdevice response, found control URL: " << s.control_url
|
<< " <== (" << d.url << ") Rootdevice response, found control URL: " << s.control_url
|
||||||
<< " namespace: " << d.service_namespace << std::endl;
|
<< " namespace: " << d.service_namespace << std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -732,6 +770,7 @@ namespace
|
||||||
void upnp::on_upnp_map_response(asio::error_code const& e
|
void upnp::on_upnp_map_response(asio::error_code const& e
|
||||||
, libtorrent::http_parser const& p, rootdevice& d, int mapping) try
|
, libtorrent::http_parser const& p, rootdevice& d, int mapping) try
|
||||||
{
|
{
|
||||||
|
TORRENT_ASSERT(d.magic == 1337);
|
||||||
if (d.upnp_connection)
|
if (d.upnp_connection)
|
||||||
{
|
{
|
||||||
d.upnp_connection->close();
|
d.upnp_connection->close();
|
||||||
|
@ -744,7 +783,7 @@ void upnp::on_upnp_map_response(asio::error_code const& e
|
||||||
m_log << time_now_string()
|
m_log << time_now_string()
|
||||||
<< " <== error while adding portmap: " << e.message() << std::endl;
|
<< " <== error while adding portmap: " << e.message() << std::endl;
|
||||||
#endif
|
#endif
|
||||||
m_devices.erase(d);
|
d.disabled = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -773,7 +812,7 @@ void upnp::on_upnp_map_response(asio::error_code const& e
|
||||||
m_log << time_now_string()
|
m_log << time_now_string()
|
||||||
<< " <== error while adding portmap: incomplete http message" << std::endl;
|
<< " <== error while adding portmap: incomplete http message" << std::endl;
|
||||||
#endif
|
#endif
|
||||||
m_devices.erase(d);
|
d.disabled = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -877,6 +916,7 @@ catch (std::exception&)
|
||||||
void upnp::on_upnp_unmap_response(asio::error_code const& e
|
void upnp::on_upnp_unmap_response(asio::error_code const& e
|
||||||
, libtorrent::http_parser const& p, rootdevice& d, int mapping) try
|
, libtorrent::http_parser const& p, rootdevice& d, int mapping) try
|
||||||
{
|
{
|
||||||
|
TORRENT_ASSERT(d.magic == 1337);
|
||||||
if (d.upnp_connection)
|
if (d.upnp_connection)
|
||||||
{
|
{
|
||||||
d.upnp_connection->close();
|
d.upnp_connection->close();
|
||||||
|
@ -906,7 +946,7 @@ void upnp::on_upnp_unmap_response(asio::error_code const& e
|
||||||
m_log << time_now_string()
|
m_log << time_now_string()
|
||||||
<< " <== error while deleting portmap: " << p.message() << std::endl;
|
<< " <== error while deleting portmap: " << p.message() << std::endl;
|
||||||
#endif
|
#endif
|
||||||
m_devices.erase(d);
|
d.disabled = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -922,10 +962,6 @@ void upnp::on_upnp_unmap_response(asio::error_code const& e
|
||||||
unmap_port(d, mapping + 1);
|
unmap_port(d, mapping + 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// the main thread is likely to be waiting for
|
|
||||||
// all the unmap operations to complete
|
|
||||||
m_devices.erase(d);
|
|
||||||
}
|
}
|
||||||
catch (std::exception&)
|
catch (std::exception&)
|
||||||
{
|
{
|
||||||
|
@ -943,6 +979,7 @@ void upnp::on_expire(asio::error_code const& e) try
|
||||||
, end(m_devices.end()); i != end; ++i)
|
, end(m_devices.end()); i != end; ++i)
|
||||||
{
|
{
|
||||||
rootdevice& d = const_cast<rootdevice&>(*i);
|
rootdevice& d = const_cast<rootdevice&>(*i);
|
||||||
|
TORRENT_ASSERT(d.magic == 1337);
|
||||||
for (int m = 0; m < num_mappings; ++m)
|
for (int m = 0; m < num_mappings; ++m)
|
||||||
{
|
{
|
||||||
if (d.mapping[m].expires != max_time())
|
if (d.mapping[m].expires != max_time())
|
||||||
|
@ -984,15 +1021,11 @@ void upnp::close()
|
||||||
}
|
}
|
||||||
|
|
||||||
for (std::set<rootdevice>::iterator i = m_devices.begin()
|
for (std::set<rootdevice>::iterator i = m_devices.begin()
|
||||||
, end(m_devices.end()); i != end;)
|
, end(m_devices.end()); i != end; ++i)
|
||||||
{
|
{
|
||||||
rootdevice& d = const_cast<rootdevice&>(*i);
|
rootdevice& d = const_cast<rootdevice&>(*i);
|
||||||
if (d.control_url.empty())
|
TORRENT_ASSERT(d.magic == 1337);
|
||||||
{
|
if (d.control_url.empty()) continue;
|
||||||
m_devices.erase(i++);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
++i;
|
|
||||||
unmap_port(d, 0);
|
unmap_port(d, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,7 +82,7 @@ class TorrentCreator:
|
||||||
self.glade = gtk.glade.XML(self.path + "/torrentcreator.glade")
|
self.glade = gtk.glade.XML(self.path + "/torrentcreator.glade")
|
||||||
|
|
||||||
self.dialog = self.glade.get_widget("torrentcreator")
|
self.dialog = self.glade.get_widget("torrentcreator")
|
||||||
self.glade.get_widget("piece_size_combobox").set_active(0)
|
self.glade.get_widget("piece_size_combobox").set_active(3)
|
||||||
self.glade.get_widget("torrent_chooserbutton").connect("clicked", self.torrent_chooserbutton_clicked)
|
self.glade.get_widget("torrent_chooserbutton").connect("clicked", self.torrent_chooserbutton_clicked)
|
||||||
self.glade.get_widget("ok_button").connect("clicked", self.create_torrent)
|
self.glade.get_widget("ok_button").connect("clicked", self.create_torrent)
|
||||||
self.glade.get_widget("close_button").connect("clicked", self.destroy)
|
self.glade.get_widget("close_button").connect("clicked", self.destroy)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
|
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
|
||||||
<!--Generated with glade3 3.2.2 on Wed Sep 5 12:27:39 2007 by markybob@peg-->
|
<!--Generated with glade3 3.2.2 on Thu Oct 25 22:18:52 2007 by markybob@peg-->
|
||||||
<glade-interface>
|
<glade-interface>
|
||||||
<widget class="GtkDialog" id="torrentcreator">
|
<widget class="GtkDialog" id="torrentcreator">
|
||||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
|
@ -54,7 +54,6 @@
|
||||||
<widget class="GtkFrame" id="frame2">
|
<widget class="GtkFrame" id="frame2">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
<property name="label_xalign">0</property>
|
|
||||||
<property name="shadow_type">GTK_SHADOW_NONE</property>
|
<property name="shadow_type">GTK_SHADOW_NONE</property>
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkAlignment" id="alignment2">
|
<widget class="GtkAlignment" id="alignment2">
|
||||||
|
@ -151,7 +150,6 @@
|
||||||
<widget class="GtkFrame" id="frame1">
|
<widget class="GtkFrame" id="frame1">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
<property name="label_xalign">0</property>
|
|
||||||
<property name="shadow_type">GTK_SHADOW_NONE</property>
|
<property name="shadow_type">GTK_SHADOW_NONE</property>
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkAlignment" id="alignment3">
|
<widget class="GtkAlignment" id="alignment3">
|
||||||
|
@ -271,7 +269,6 @@
|
||||||
<widget class="GtkFrame" id="frame3">
|
<widget class="GtkFrame" id="frame3">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
<property name="label_xalign">0</property>
|
|
||||||
<property name="shadow_type">GTK_SHADOW_NONE</property>
|
<property name="shadow_type">GTK_SHADOW_NONE</property>
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkAlignment" id="alignment4">
|
<widget class="GtkAlignment" id="alignment4">
|
||||||
|
@ -318,7 +315,6 @@
|
||||||
<widget class="GtkFrame" id="frame4">
|
<widget class="GtkFrame" id="frame4">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
<property name="label_xalign">0</property>
|
|
||||||
<property name="shadow_type">GTK_SHADOW_NONE</property>
|
<property name="shadow_type">GTK_SHADOW_NONE</property>
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkAlignment" id="alignment5">
|
<widget class="GtkAlignment" id="alignment5">
|
||||||
|
@ -365,7 +361,6 @@
|
||||||
<widget class="GtkFrame" id="frame5">
|
<widget class="GtkFrame" id="frame5">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
<property name="label_xalign">0</property>
|
|
||||||
<property name="shadow_type">GTK_SHADOW_NONE</property>
|
<property name="shadow_type">GTK_SHADOW_NONE</property>
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkAlignment" id="alignment6">
|
<widget class="GtkAlignment" id="alignment6">
|
||||||
|
@ -417,6 +412,9 @@
|
||||||
<property name="n_rows">2</property>
|
<property name="n_rows">2</property>
|
||||||
<property name="n_columns">2</property>
|
<property name="n_columns">2</property>
|
||||||
<property name="column_spacing">10</property>
|
<property name="column_spacing">10</property>
|
||||||
|
<child>
|
||||||
|
<placeholder/>
|
||||||
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkCheckButton" id="chk_set_priv">
|
<widget class="GtkCheckButton" id="chk_set_priv">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
|
@ -431,9 +429,6 @@
|
||||||
<property name="bottom_attach">2</property>
|
<property name="bottom_attach">2</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
|
||||||
<placeholder/>
|
|
||||||
</child>
|
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkComboBox" id="piece_size_combobox">
|
<widget class="GtkComboBox" id="piece_size_combobox">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
|
@ -445,6 +440,7 @@
|
||||||
256 KiB
|
256 KiB
|
||||||
512 KiB
|
512 KiB
|
||||||
1024 KiB
|
1024 KiB
|
||||||
|
2048 KiB
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
<packing>
|
<packing>
|
||||||
|
|
|
@ -28,10 +28,10 @@
|
||||||
# but you are not obligated to do so. If you do not wish to do so, delete
|
# but you are not obligated to do so. If you do not wish to do so, delete
|
||||||
# this exception statement from your version. If you delete this exception
|
# this exception statement from your version. If you delete this exception
|
||||||
|
|
||||||
plugin_name = "Web User Interface"
|
plugin_name = _("Web User Interface")
|
||||||
plugin_author = "Martijn Voncken"
|
plugin_author = "Martijn Voncken"
|
||||||
plugin_version = "rev."
|
plugin_version = "rev."
|
||||||
plugin_description = """A Web based User Interface
|
plugin_description = _("""A Web based User Interface
|
||||||
|
|
||||||
Firefox greasemonkey script: http://userscripts.org/scripts/show/12639
|
Firefox greasemonkey script: http://userscripts.org/scripts/show/12639
|
||||||
|
|
||||||
|
@ -41,8 +41,8 @@ There is support for multiple templates, but just one is included.
|
||||||
|
|
||||||
Other contributors:
|
Other contributors:
|
||||||
*somedude : template enhancements.
|
*somedude : template enhancements.
|
||||||
|
*markybob : stability : synced with his changes in deluge-svn.
|
||||||
"""
|
""")
|
||||||
|
|
||||||
import deluge.common
|
import deluge.common
|
||||||
import deluge.pref
|
import deluge.pref
|
||||||
|
@ -80,9 +80,10 @@ class plugin_WebUi(object):
|
||||||
self.web_server = None
|
self.web_server = None
|
||||||
if not deluge.common.windows_check():
|
if not deluge.common.windows_check():
|
||||||
import commands
|
import commands
|
||||||
status = commands.getstatusoutput('ps x |grep -v grep |grep run_webserver')
|
status = commands.getstatusoutput(
|
||||||
|
'ps x |grep -v grep |grep run_webserver')
|
||||||
if status[0] == 0:
|
if status[0] == 0:
|
||||||
os.kill(status[1].split()[0], 9)
|
os.kill(int(status[1].split()[0]), 9)
|
||||||
time.sleep(1) #safe time to wait for kill to finish.
|
time.sleep(1) #safe time to wait for kill to finish.
|
||||||
self.config_file = deluge.common.CONFIG_DIR + "/webui.conf"
|
self.config_file = deluge.common.CONFIG_DIR + "/webui.conf"
|
||||||
self.config = deluge.pref.Preferences(self.config_file, False)
|
self.config = deluge.pref.Preferences(self.config_file, False)
|
||||||
|
@ -95,9 +96,6 @@ class plugin_WebUi(object):
|
||||||
if not self.config.get('port'): #ugly way to detect new config file.
|
if not self.config.get('port'): #ugly way to detect new config file.
|
||||||
#set default values:
|
#set default values:
|
||||||
self.config.set("port", 8112)
|
self.config.set("port", 8112)
|
||||||
#future->use deluge-core setting for download_dir (if it is set)
|
|
||||||
self.config.set("download_dir", os.path.expanduser("~"))
|
|
||||||
self.config.set("torrent_dir", os.path.expanduser("~"))
|
|
||||||
self.config.set("button_style", 2)
|
self.config.set("button_style", 2)
|
||||||
self.config.set("auto_refresh", False)
|
self.config.set("auto_refresh", False)
|
||||||
self.config.set("auto_refresh_secs", 4)
|
self.config.set("auto_refresh_secs", 4)
|
||||||
|
@ -112,11 +110,9 @@ class plugin_WebUi(object):
|
||||||
self.config.set("cache_templates", True)
|
self.config.set("cache_templates", True)
|
||||||
|
|
||||||
if deluge.common.windows_check():
|
if deluge.common.windows_check():
|
||||||
if self.config.get("run_in_thread") == None:
|
self.config.set("run_in_thread", True)
|
||||||
self.config.set("run_in_thread", True)
|
|
||||||
else:
|
else:
|
||||||
if self.config.get("run_in_thread") == None:
|
self.config.set("run_in_thread", False)
|
||||||
self.config.set("run_in_thread", False)
|
|
||||||
|
|
||||||
self.dbus_manager = get_dbus_manager(deluge_core, deluge_interface,
|
self.dbus_manager = get_dbus_manager(deluge_core, deluge_interface,
|
||||||
self.config, self.config_file)
|
self.config, self.config_file)
|
||||||
|
@ -141,8 +137,8 @@ class plugin_WebUi(object):
|
||||||
self.kill_server()
|
self.kill_server()
|
||||||
|
|
||||||
if self.config.get("run_in_thread"):
|
if self.config.get("run_in_thread"):
|
||||||
print 'start Webui(inside gtk)..'
|
print 'Start Webui(inside gtk)..'
|
||||||
webserver_common.init() #reload changed config.
|
webserver_common.init_gtk_05() #reload changed config.
|
||||||
from deluge_webserver import WebServer #only import in threaded mode
|
from deluge_webserver import WebServer #only import in threaded mode
|
||||||
|
|
||||||
|
|
||||||
|
@ -150,11 +146,9 @@ class plugin_WebUi(object):
|
||||||
self.web_server.start_gtk()
|
self.web_server.start_gtk()
|
||||||
|
|
||||||
else:
|
else:
|
||||||
print 'start Webui(in process)..'
|
print 'Start Webui(in process)..'
|
||||||
path = os.path.dirname(__file__)
|
server_bin = os.path.dirname(__file__) + '/run_webserver'
|
||||||
server_bin = path + '/run_webserver'
|
self.proc = Popen((server_bin,'env=0.5'))
|
||||||
port = str(self.config.get('port'))
|
|
||||||
self.proc = Popen((server_bin, port),cwd=path)
|
|
||||||
|
|
||||||
def kill_server(self):
|
def kill_server(self):
|
||||||
if self.web_server:
|
if self.web_server:
|
||||||
|
@ -187,7 +181,8 @@ class ConfigDialog(gtk.Dialog):
|
||||||
template_path = os.path.join(os.path.dirname(__file__), 'templates')
|
template_path = os.path.join(os.path.dirname(__file__), 'templates')
|
||||||
self.templates = [dirname for dirname
|
self.templates = [dirname for dirname
|
||||||
in os.listdir(template_path)
|
in os.listdir(template_path)
|
||||||
if os.path.isdir(os.path.join(template_path, dirname))]
|
if os.path.isdir(os.path.join(template_path, dirname))
|
||||||
|
and not dirname.startswith('.')]
|
||||||
|
|
||||||
self.port = self.add_widget(_('Port Number'), gtk.SpinButton())
|
self.port = self.add_widget(_('Port Number'), gtk.SpinButton())
|
||||||
self.pwd1 = self.add_widget(_('New Password'), gtk.Entry())
|
self.pwd1 = self.add_widget(_('New Password'), gtk.Entry())
|
||||||
|
@ -195,16 +190,11 @@ class ConfigDialog(gtk.Dialog):
|
||||||
self.template = self.add_widget(_('Template'), gtk.combo_box_new_text())
|
self.template = self.add_widget(_('Template'), gtk.combo_box_new_text())
|
||||||
self.button_style = self.add_widget(_('Button Style'),
|
self.button_style = self.add_widget(_('Button Style'),
|
||||||
gtk.combo_box_new_text())
|
gtk.combo_box_new_text())
|
||||||
self.download_dir = self.add_widget(_('Download Directory'),
|
|
||||||
gtk.FileChooserButton(_('Download Directory')))
|
|
||||||
self.torrent_dir = self.add_widget(_('Torrent Directory'),
|
|
||||||
gtk.FileChooserButton(_('Torrent Directory')))
|
|
||||||
self.cache_templates = self.add_widget(_('Cache Templates'),
|
self.cache_templates = self.add_widget(_('Cache Templates'),
|
||||||
gtk.CheckButton())
|
gtk.CheckButton())
|
||||||
self.run_in_thread = self.add_widget(_('Run inside GTK'), gtk.CheckButton())
|
#self.share_downloads = self.add_widget(_('Share Download Directory'),
|
||||||
|
# gtk.CheckButton())
|
||||||
|
|
||||||
self.download_dir.set_action(gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER)
|
|
||||||
self.torrent_dir.set_action(gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER)
|
|
||||||
self.port.set_range(80, 65536)
|
self.port.set_range(80, 65536)
|
||||||
self.port.set_increments(1, 10)
|
self.port.set_increments(1, 10)
|
||||||
self.pwd1.set_visibility(False)
|
self.pwd1.set_visibility(False)
|
||||||
|
@ -218,23 +208,16 @@ class ConfigDialog(gtk.Dialog):
|
||||||
|
|
||||||
for item in [_('Text and image'), _('Image Only'), _('Text Only')]:
|
for item in [_('Text and image'), _('Image Only'), _('Text Only')]:
|
||||||
self.button_style.append_text(item)
|
self.button_style.append_text(item)
|
||||||
if not self.config.get("button_style"):
|
if self.config.get("button_style") == None:
|
||||||
self.config.set("button_style", 2)
|
self.config.set("button_style", 2)
|
||||||
|
|
||||||
self.port.set_value(int(self.config.get("port")))
|
self.port.set_value(int(self.config.get("port")))
|
||||||
self.template.set_active(
|
self.template.set_active(
|
||||||
self.templates.index(self.config.get("template")))
|
self.templates.index(self.config.get("template")))
|
||||||
self.button_style.set_active(self.config.get("button_style"))
|
self.button_style.set_active(self.config.get("button_style"))
|
||||||
|
#self.share_downloads.set_active(
|
||||||
|
# bool(self.config.get("share_downloads")))
|
||||||
|
|
||||||
self.torrent_dir.set_filename(self.config.get("torrent_dir"))
|
|
||||||
self.download_dir.set_filename(self.config.get("download_dir"))
|
|
||||||
|
|
||||||
if deluge.common.windows_check():
|
|
||||||
self.run_in_thread.set_active(True)
|
|
||||||
self.run_in_thread.set_sensitive(False)
|
|
||||||
else:
|
|
||||||
self.run_in_thread.set_active(False)
|
|
||||||
self.run_in_thread.set_sensitive(False)
|
|
||||||
self.cache_templates.set_active(self.config.get("cache_templates"))
|
self.cache_templates.set_active(self.config.get("cache_templates"))
|
||||||
|
|
||||||
self.vbox.pack_start(self.vb, True, True, 0)
|
self.vbox.pack_start(self.vb, True, True, 0)
|
||||||
|
@ -270,9 +253,7 @@ class ConfigDialog(gtk.Dialog):
|
||||||
self.config.set("port", int(self.port.get_value()))
|
self.config.set("port", int(self.port.get_value()))
|
||||||
self.config.set("template", self.template.get_active_text())
|
self.config.set("template", self.template.get_active_text())
|
||||||
self.config.set("button_style", self.button_style.get_active())
|
self.config.set("button_style", self.button_style.get_active())
|
||||||
self.config.set("torrent_dir", self.torrent_dir.get_filename())
|
|
||||||
self.config.set("download_dir",self.download_dir.get_filename())
|
|
||||||
self.config.set("cache_templates", self.cache_templates.get_active())
|
self.config.set("cache_templates", self.cache_templates.get_active())
|
||||||
self.config.set("run_in_thread", self.run_in_thread.get_active())
|
#self.config.set("share_downloads", self.share_downloads.get_active())
|
||||||
self.config.save(self.plugin.config_file)
|
self.config.save(self.plugin.config_file)
|
||||||
self.plugin.start_server() #restarts server
|
self.plugin.start_server() #restarts server
|
||||||
|
|
|
@ -68,7 +68,7 @@ class DbusManager(dbus.service.Object):
|
||||||
|
|
||||||
@dbus.service.method(dbus_interface=dbus_interface,
|
@dbus.service.method(dbus_interface=dbus_interface,
|
||||||
in_signature="",out_signature="as")
|
in_signature="",out_signature="as")
|
||||||
def get_torrent_state(self):
|
def get_session_state(self):
|
||||||
"""Returns a list of torrent_ids in the session.
|
"""Returns a list of torrent_ids in the session.
|
||||||
same as 0.6, but returns type "as" instead of a pickle
|
same as 0.6, but returns type "as" instead of a pickle
|
||||||
"""
|
"""
|
||||||
|
@ -129,18 +129,20 @@ class DbusManager(dbus.service.Object):
|
||||||
return status_subset
|
return status_subset
|
||||||
|
|
||||||
@dbus.service.method(dbus_interface=dbus_interface,
|
@dbus.service.method(dbus_interface=dbus_interface,
|
||||||
in_signature="s",out_signature="")
|
in_signature="as",out_signature="")
|
||||||
def pause_torrent(self, torrent_id):
|
def pause_torrent(self, torrents):
|
||||||
"""same as 0.6 interface"""
|
"""same as 0.6 interface"""
|
||||||
torrent_id = int(torrent_id)
|
for torrent_id in torrents:
|
||||||
self.core.set_user_pause(torrent_id,True)
|
torrent_id = int(torrent_id)
|
||||||
|
self.core.set_user_pause(torrent_id,True)
|
||||||
|
|
||||||
@dbus.service.method(dbus_interface=dbus_interface,
|
@dbus.service.method(dbus_interface=dbus_interface,
|
||||||
in_signature="s", out_signature="")
|
in_signature="as", out_signature="")
|
||||||
def resume_torrent(self, torrent_id):
|
def resume_torrent(self, torrents):
|
||||||
"""same as 0.6 interface"""
|
"""same as 0.6 interface"""
|
||||||
torrent_id = int(torrent_id)
|
for torrent_id in torrents:
|
||||||
self.core.set_user_pause(torrent_id,False)
|
torrent_id = int(torrent_id)
|
||||||
|
self.core.set_user_pause(torrent_id,False)
|
||||||
|
|
||||||
@dbus.service.method(dbus_interface=dbus_interface,
|
@dbus.service.method(dbus_interface=dbus_interface,
|
||||||
in_signature="sbb", out_signature="")
|
in_signature="sbb", out_signature="")
|
||||||
|
@ -157,7 +159,6 @@ class DbusManager(dbus.service.Object):
|
||||||
@dbus.service.method(dbus_interface=dbus_interface,
|
@dbus.service.method(dbus_interface=dbus_interface,
|
||||||
in_signature="s", out_signature="b")
|
in_signature="s", out_signature="b")
|
||||||
def add_torrent_url(self, url):
|
def add_torrent_url(self, url):
|
||||||
"""not available in deluge 0.6 interface"""
|
|
||||||
filename = fetch_url(url)
|
filename = fetch_url(url)
|
||||||
self._add_torrent(filename)
|
self._add_torrent(filename)
|
||||||
return True
|
return True
|
||||||
|
@ -182,8 +183,8 @@ class DbusManager(dbus.service.Object):
|
||||||
#name = fillename without directory
|
#name = fillename without directory
|
||||||
name = name.replace('\\','/')
|
name = name.replace('\\','/')
|
||||||
name = 'deluge_' + str(random.random()) + '_' + name.split('/')[-1]
|
name = 'deluge_' + str(random.random()) + '_' + name.split('/')[-1]
|
||||||
|
filename = os.path.join(self.core.config.get("default_download_path"), name)
|
||||||
|
|
||||||
filename = os.path.join(self.config.get("torrent_dir"),name)
|
|
||||||
filecontent = base64.b64decode(filecontent_b64)
|
filecontent = base64.b64decode(filecontent_b64)
|
||||||
f = open(filename,"wb") #no with statement, that's py 2.5+
|
f = open(filename,"wb") #no with statement, that's py 2.5+
|
||||||
f.write(filecontent)
|
f.write(filecontent)
|
||||||
|
@ -192,11 +193,42 @@ class DbusManager(dbus.service.Object):
|
||||||
self._add_torrent(filename)
|
self._add_torrent(filename)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@dbus.service.method(dbus_interface=dbus_interface,
|
||||||
|
in_signature="", out_signature="a{sv}")
|
||||||
|
def get_config(self):
|
||||||
|
return self.core.config.mapping
|
||||||
|
|
||||||
|
@dbus.service.method(dbus_interface=dbus_interface,
|
||||||
|
in_signature="s", out_signature="v")
|
||||||
|
def get_config_value(self,key):
|
||||||
|
return self.core.config.mapping[pythonize(key)] #ugly!
|
||||||
|
|
||||||
|
@dbus.service.method(dbus_interface=dbus_interface,
|
||||||
|
in_signature="a{sv}", out_signature="")
|
||||||
|
def set_config(self, config):
|
||||||
|
"""Set the config with values from dictionary"""
|
||||||
|
config = deluge.common.pythonize(config)
|
||||||
|
# Load all the values into the configuration
|
||||||
|
for key in self.core.config.keys():
|
||||||
|
self.core.config[key] = config[key]
|
||||||
|
self.core.apply_prefs()
|
||||||
|
|
||||||
|
@dbus.service.method(dbus_interface=dbus_interface,
|
||||||
|
in_signature="", out_signature="v")
|
||||||
|
def get_download_rate(self):
|
||||||
|
return self.core.get_state()['download_rate']
|
||||||
|
|
||||||
|
@dbus.service.method(dbus_interface=dbus_interface,
|
||||||
|
in_signature="", out_signature="v")
|
||||||
|
def get_upload_rate(self):
|
||||||
|
return self.core.get_state()['upload_rate']
|
||||||
|
|
||||||
|
|
||||||
#internal
|
#internal
|
||||||
def _add_torrent(self, filename):
|
def _add_torrent(self, filename):
|
||||||
#dbus types break pickle, again.....
|
|
||||||
filename = unicode(filename)
|
filename = unicode(filename)
|
||||||
target = self.config.get("download_dir")
|
target = self.core.config.get("default_download_path")
|
||||||
|
|
||||||
torrent_id = self.core.add_torrent(filename, target,
|
torrent_id = self.core.add_torrent(filename, target,
|
||||||
self.interface.config.get("use_compact_storage"))
|
self.interface.config.get("use_compact_storage"))
|
||||||
|
|
|
@ -31,67 +31,15 @@
|
||||||
# this exception statement from your version. If you delete this exception
|
# this exception statement from your version. If you delete this exception
|
||||||
# statement from all source files in the program, then also delete it here.
|
# statement from all source files in the program, then also delete it here.
|
||||||
|
|
||||||
|
|
||||||
from webserver_common import TORRENT_KEYS, STATE_MESSAGES
|
|
||||||
import webserver_common as ws
|
import webserver_common as ws
|
||||||
from webserver_framework import *
|
from webserver_framework import *
|
||||||
|
|
||||||
|
|
||||||
import webpy022 as web
|
import webpy022 as web
|
||||||
from webpy022.http import seeother, url
|
from webpy022.http import seeother, url
|
||||||
from webpy022.utils import Storage
|
|
||||||
|
|
||||||
from md5 import md5
|
|
||||||
import base64
|
import base64
|
||||||
from deluge.common import fsize
|
|
||||||
from operator import attrgetter
|
from operator import attrgetter
|
||||||
|
import os
|
||||||
#utils:
|
|
||||||
def check_pwd(pwd):
|
|
||||||
m = md5()
|
|
||||||
m.update(ws.config.get('pwd_salt'))
|
|
||||||
m.update(pwd)
|
|
||||||
return (m.digest() == ws.config.get('pwd_md5'))
|
|
||||||
|
|
||||||
def get_torrent_status(torrent_id):
|
|
||||||
"""
|
|
||||||
helper method.
|
|
||||||
enhance ws.proxy.get_torrent_status with some extra data
|
|
||||||
"""
|
|
||||||
status = ws.proxy.get_torrent_status(torrent_id,TORRENT_KEYS)
|
|
||||||
status["id"] = torrent_id
|
|
||||||
|
|
||||||
#for naming the status-images
|
|
||||||
status["calc_state_str"] = "downloading"
|
|
||||||
if status["paused"]:
|
|
||||||
status["calc_state_str"] = "inactive"
|
|
||||||
elif status["is_seed"]:
|
|
||||||
status["calc_state_str"] = "seeding"
|
|
||||||
|
|
||||||
#action for torrent_pause
|
|
||||||
if status["calc_state_str"] == "inactive":
|
|
||||||
status["action"] = "start"
|
|
||||||
else:
|
|
||||||
status["action"] = "stop"
|
|
||||||
|
|
||||||
if status["paused"]:
|
|
||||||
status["message"] = _("Paused %s%%") % status['progress']
|
|
||||||
else:
|
|
||||||
status["message"] = "%s %i%%" % (STATE_MESSAGES[status["state"]]
|
|
||||||
, status['progress'])
|
|
||||||
|
|
||||||
#add some pre-calculated values
|
|
||||||
status.update({
|
|
||||||
"calc_total_downloaded" : (fsize(status["total_done"])
|
|
||||||
+ " (" + fsize(status["total_download"]) + ")"),
|
|
||||||
"calc_total_uploaded": (fsize(status['uploaded_memory']
|
|
||||||
+ status["total_payload_upload"]) + " ("
|
|
||||||
+ fsize(status["total_upload"]) + ")"),
|
|
||||||
})
|
|
||||||
|
|
||||||
return Storage(status) #Storage for easy templating.
|
|
||||||
|
|
||||||
#/utils
|
|
||||||
|
|
||||||
#routing:
|
#routing:
|
||||||
urls = (
|
urls = (
|
||||||
|
@ -107,15 +55,21 @@ urls = (
|
||||||
"/resume_all(.*)", "resume_all",
|
"/resume_all(.*)", "resume_all",
|
||||||
"/refresh/set(.*)", "refresh_set",
|
"/refresh/set(.*)", "refresh_set",
|
||||||
"/refresh/(.*)", "refresh",
|
"/refresh/(.*)", "refresh",
|
||||||
|
"/config(.*)","config",
|
||||||
"/home(.*)", "home",
|
"/home(.*)", "home",
|
||||||
"/about(.*)", "about",
|
"/about(.*)", "about",
|
||||||
|
"/logout(.*)", "logout",
|
||||||
#default-pages
|
#default-pages
|
||||||
"/", "login",
|
"/", "home",
|
||||||
"", "login",
|
"", "home",
|
||||||
#remote-api:
|
#remote-api:
|
||||||
"/remote/torrent/add(.*)", "remote_torrent_add"
|
"/remote/torrent/add(.*)", "remote_torrent_add",
|
||||||
)
|
#static:
|
||||||
|
"/static/(.*)","static",
|
||||||
|
"/template/static/(.*)","template_static",
|
||||||
|
#"/downloads/(.*)","downloads" disabled until it can handle large downloads.
|
||||||
|
|
||||||
|
)
|
||||||
#/routing
|
#/routing
|
||||||
|
|
||||||
#pages:
|
#pages:
|
||||||
|
@ -133,15 +87,10 @@ class login:
|
||||||
start_session()
|
start_session()
|
||||||
do_redirect()
|
do_redirect()
|
||||||
elif vars.redir:
|
elif vars.redir:
|
||||||
seeother(url('/login',error=1,redir=vars.redir))
|
seeother(url('/login',error=1, redir=vars.redir))
|
||||||
else:
|
else:
|
||||||
seeother('/login?error=1')
|
seeother('/login?error=1')
|
||||||
|
|
||||||
class home:
|
|
||||||
@check_session
|
|
||||||
def GET(self, name):
|
|
||||||
do_redirect()
|
|
||||||
|
|
||||||
class index:
|
class index:
|
||||||
"page containing the torrent list."
|
"page containing the torrent list."
|
||||||
@auto_refreshed
|
@auto_refreshed
|
||||||
|
@ -150,7 +99,7 @@ class index:
|
||||||
vars = web.input(sort=None, order=None)
|
vars = web.input(sort=None, order=None)
|
||||||
|
|
||||||
status_rows = [get_torrent_status(torrent_id)
|
status_rows = [get_torrent_status(torrent_id)
|
||||||
for torrent_id in ws.proxy.get_torrent_state()]
|
for torrent_id in ws.proxy.get_session_state()]
|
||||||
|
|
||||||
#sorting:
|
#sorting:
|
||||||
if vars.sort:
|
if vars.sort:
|
||||||
|
@ -164,21 +113,19 @@ class index:
|
||||||
return ws.render.index(status_rows)
|
return ws.render.index(status_rows)
|
||||||
|
|
||||||
class torrent_info:
|
class torrent_info:
|
||||||
"torrent details"
|
|
||||||
@auto_refreshed
|
@auto_refreshed
|
||||||
@deluge_page
|
@deluge_page
|
||||||
def GET(self, torrent_id):
|
def GET(self, torrent_id):
|
||||||
return ws.render.torrent_info(get_torrent_status(torrent_id))
|
return ws.render.torrent_info(get_torrent_status(torrent_id))
|
||||||
|
|
||||||
class torrent_pause:
|
class torrent_pause:
|
||||||
"start/stop a torrent"
|
|
||||||
@check_session
|
@check_session
|
||||||
def POST(self, name):
|
def POST(self, name):
|
||||||
vars = web.input(stop = None, start = None, redir = None)
|
vars = web.input(stop = None, start = None, redir = None)
|
||||||
if vars.stop:
|
if vars.stop:
|
||||||
ws.proxy.pause_torrent(vars.stop)
|
ws.proxy.pause_torrent([vars.stop])
|
||||||
elif vars.start:
|
elif vars.start:
|
||||||
ws.proxy.resume_torrent(vars.start)
|
ws.proxy.resume_torrent([vars.start])
|
||||||
|
|
||||||
do_redirect()
|
do_redirect()
|
||||||
|
|
||||||
|
@ -194,7 +141,7 @@ class torrent_add:
|
||||||
if vars.url and vars.torrent.filename:
|
if vars.url and vars.torrent.filename:
|
||||||
error_page(_("Choose an url or a torrent, not both."))
|
error_page(_("Choose an url or a torrent, not both."))
|
||||||
if vars.url:
|
if vars.url:
|
||||||
ws.proxy.add_torrent_url(vars.url)
|
ws.proxy.add_torrent_url(vars.url )
|
||||||
do_redirect()
|
do_redirect()
|
||||||
elif vars.torrent.filename:
|
elif vars.torrent.filename:
|
||||||
data = vars.torrent.file.read()
|
data = vars.torrent.file.read()
|
||||||
|
@ -227,8 +174,7 @@ class torrent_delete:
|
||||||
return ws.render.torrent_delete(get_torrent_status(torrent_id))
|
return ws.render.torrent_delete(get_torrent_status(torrent_id))
|
||||||
|
|
||||||
@check_session
|
@check_session
|
||||||
def POST(self, name):
|
def POST(self, torrent_id):
|
||||||
torrent_id = name
|
|
||||||
vars = web.input(data_also = None, torrent_also = None)
|
vars = web.input(data_also = None, torrent_also = None)
|
||||||
data_also = bool(vars.data_also)
|
data_also = bool(vars.data_also)
|
||||||
torrent_also = bool(vars.torrent_also)
|
torrent_also = bool(vars.torrent_also)
|
||||||
|
@ -238,30 +184,26 @@ class torrent_delete:
|
||||||
|
|
||||||
class torrent_queue_up:
|
class torrent_queue_up:
|
||||||
@check_session
|
@check_session
|
||||||
def POST(self, name):
|
def POST(self, torrent_id):
|
||||||
torrent_id = name
|
|
||||||
ws.proxy.queue_up(torrent_id)
|
ws.proxy.queue_up(torrent_id)
|
||||||
do_redirect()
|
do_redirect()
|
||||||
|
|
||||||
class torrent_queue_down:
|
class torrent_queue_down:
|
||||||
@check_session
|
@check_session
|
||||||
def POST(self, name):
|
def POST(self, torrent_id):
|
||||||
torrent_id = name
|
|
||||||
ws.proxy.queue_down(torrent_id)
|
ws.proxy.queue_down(torrent_id)
|
||||||
do_redirect()
|
do_redirect()
|
||||||
|
|
||||||
class pause_all:
|
class pause_all:
|
||||||
@check_session
|
@check_session
|
||||||
def POST(self, name):
|
def POST(self, name):
|
||||||
for torrent_id in ws.proxy.get_torrent_state():
|
ws.proxy.pause_torrent(ws.proxy.get_session_state())
|
||||||
ws.proxy.pause_torrent(torrent_id)
|
|
||||||
do_redirect()
|
do_redirect()
|
||||||
|
|
||||||
class resume_all:
|
class resume_all:
|
||||||
@check_session
|
@check_session
|
||||||
def POST(self, name):
|
def POST(self, name):
|
||||||
for torrent_id in ws.proxy.get_torrent_state():
|
ws.proxy.resume_torrent(ws.proxy.get_session_state())
|
||||||
ws.proxy.resume_torrent(torrent_id)
|
|
||||||
do_redirect()
|
do_redirect()
|
||||||
|
|
||||||
class refresh:
|
class refresh:
|
||||||
|
@ -287,13 +229,61 @@ class refresh_set:
|
||||||
else:
|
else:
|
||||||
error_page(_('refresh must be > 0'))
|
error_page(_('refresh must be > 0'))
|
||||||
|
|
||||||
|
class config:
|
||||||
|
"""core config
|
||||||
|
TODO:good validation.
|
||||||
|
"""
|
||||||
|
cfg_form = web.form.Form(
|
||||||
|
web.form.Dropdown('max_download', ws.SPEED_VALUES,
|
||||||
|
description=_('Download Speed Limit'),
|
||||||
|
post='%s Kib/sec' % ws.proxy.get_config_value('max_download_speed')
|
||||||
|
)
|
||||||
|
,web.form.Dropdown('max_upload', ws.SPEED_VALUES,
|
||||||
|
description=_('Upload Speed Limit'),
|
||||||
|
post='%s Kib/sec' % ws.proxy.get_config_value('max_upload_speed')
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
@deluge_page
|
||||||
|
def GET(self, name):
|
||||||
|
return ws.render.config(self.cfg_form())
|
||||||
|
|
||||||
|
def POST(self, name):
|
||||||
|
vars = web.input(max_download=None, max_upload=None)
|
||||||
|
|
||||||
|
#self.config.set("max_download_speed", float(str_bwdown))
|
||||||
|
raise NotImplementedError('todo')
|
||||||
|
|
||||||
|
class home:
|
||||||
|
@check_session
|
||||||
|
def GET(self, name):
|
||||||
|
do_redirect()
|
||||||
|
|
||||||
class about:
|
class about:
|
||||||
@deluge_page_noauth
|
@deluge_page_noauth
|
||||||
def GET(self, name):
|
def GET(self, name):
|
||||||
return ws.render.about()
|
return ws.render.about()
|
||||||
|
|
||||||
#/pages
|
class logout:
|
||||||
|
def POST(self, name):
|
||||||
|
end_session()
|
||||||
|
seeother('/login')
|
||||||
|
|
||||||
|
class static(static_handler):
|
||||||
|
base_dir = os.path.join(os.path.dirname(__file__),'static')
|
||||||
|
|
||||||
|
class template_static(static_handler):
|
||||||
|
def get_base_dir(self):
|
||||||
|
return os.path.join(os.path.dirname(__file__),
|
||||||
|
'templates/%s/static' % ws.config.get('template'))
|
||||||
|
|
||||||
|
class downloads(static_handler):
|
||||||
|
def GET(self, name):
|
||||||
|
self.base_dir = ws.proxy.get_config_value('default_download_path')
|
||||||
|
if not ws.config.get('share_downloads'):
|
||||||
|
raise Exception('Access to downloads is forbidden.')
|
||||||
|
return static_handler.GET(self, name)
|
||||||
|
#/pages
|
||||||
|
|
||||||
def WebServer():
|
def WebServer():
|
||||||
return create_webserver(urls, globals())
|
return create_webserver(urls, globals())
|
||||||
|
@ -307,4 +297,3 @@ def run():
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
run()
|
run()
|
||||||
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
87
|
112
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
from deluge_webserver import *
|
import deluge_webserver
|
||||||
web.run(urls, globals())
|
deluge_webserver.run()
|
||||||
|
|
10
plugins/WebUi/scripts/add_torrent_to_deluge_webui
Executable file
10
plugins/WebUi/scripts/add_torrent_to_deluge_webui
Executable file
|
@ -0,0 +1,10 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
pwd=deluge
|
||||||
|
url=http://localhost:8112
|
||||||
|
|
||||||
|
for arg in "$@"
|
||||||
|
do
|
||||||
|
curl -F torrent=@"$arg" -F pwd=$pwd $url/remote/torrent/add
|
||||||
|
done
|
||||||
|
|
BIN
plugins/WebUi/static/images/tango/system-log-out.png
Normal file
BIN
plugins/WebUi/static/images/tango/system-log-out.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 799 B |
136
plugins/WebUi/static_handler.py
Normal file
136
plugins/WebUi/static_handler.py
Normal file
|
@ -0,0 +1,136 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
#(c) Martijn Voncken, mvoncken@gmail.com
|
||||||
|
#Same Licence as web.py 0.22 ->Public Domain
|
||||||
|
#
|
||||||
|
"""
|
||||||
|
static fileserving for web.py
|
||||||
|
without the need for wsgi wrapper magic.
|
||||||
|
"""
|
||||||
|
import webpy022 as web
|
||||||
|
from webpy022.http import seeother, url
|
||||||
|
|
||||||
|
import posixpath
|
||||||
|
import urlparse
|
||||||
|
import urllib
|
||||||
|
import mimetypes
|
||||||
|
import os
|
||||||
|
import datetime
|
||||||
|
import cgi
|
||||||
|
from StringIO import StringIO
|
||||||
|
mimetypes.init() # try to read system mime.types
|
||||||
|
|
||||||
|
class static_handler:
|
||||||
|
"""
|
||||||
|
mostly c&p from SimpleHttpServer
|
||||||
|
serves relative from start location
|
||||||
|
"""
|
||||||
|
base_dir = './'
|
||||||
|
extensions_map = mimetypes.types_map
|
||||||
|
|
||||||
|
def get_base_dir(self):
|
||||||
|
#override this if you have a config that changes the base dir at runtime
|
||||||
|
#deluge on windows :(
|
||||||
|
return self.base_dir
|
||||||
|
|
||||||
|
def GET(self, path):
|
||||||
|
path = self.translate_path(path)
|
||||||
|
if os.path.isdir(path):
|
||||||
|
if not path.endswith('/'):
|
||||||
|
path += "/"
|
||||||
|
return self.list_directory(path)
|
||||||
|
|
||||||
|
ctype = self.guess_type(path)
|
||||||
|
|
||||||
|
try:
|
||||||
|
f = open(path, 'rb')
|
||||||
|
except IOError:
|
||||||
|
raise Exception('file not found:%s' % path)
|
||||||
|
#web.header("404", "File not found")
|
||||||
|
#return
|
||||||
|
web.header("Content-type", ctype)
|
||||||
|
fs = os.fstat(f.fileno())
|
||||||
|
web.header("Content-Length", str(fs[6]))
|
||||||
|
web.lastmodified(datetime.datetime.fromtimestamp(fs.st_mtime))
|
||||||
|
print f.read()
|
||||||
|
|
||||||
|
def translate_path(self, path):
|
||||||
|
"""Translate a /-separated PATH to the local filename syntax.
|
||||||
|
|
||||||
|
Components that mean special things to the local file system
|
||||||
|
(e.g. drive or directory names) are ignored. (XXX They should
|
||||||
|
probably be diagnosed.)
|
||||||
|
|
||||||
|
"""
|
||||||
|
# abandon query parameters
|
||||||
|
path = urlparse.urlparse(path)[2]
|
||||||
|
path = posixpath.normpath(urllib.unquote(path))
|
||||||
|
words = path.split('/')
|
||||||
|
words = filter(None, words)
|
||||||
|
path = self.get_base_dir()
|
||||||
|
for word in words:
|
||||||
|
drive, word = os.path.splitdrive(word)
|
||||||
|
head, word = os.path.split(word)
|
||||||
|
if word in (os.curdir, os.pardir): continue
|
||||||
|
path = os.path.join(path, word)
|
||||||
|
return path
|
||||||
|
|
||||||
|
def guess_type(self, path):
|
||||||
|
base, ext = posixpath.splitext(path)
|
||||||
|
if ext in self.extensions_map:
|
||||||
|
return self.extensions_map[ext]
|
||||||
|
ext = ext.lower()
|
||||||
|
if ext in self.extensions_map:
|
||||||
|
return self.extensions_map[ext]
|
||||||
|
else:
|
||||||
|
return 'application/octet-stream'
|
||||||
|
|
||||||
|
|
||||||
|
def list_directory(self, path):
|
||||||
|
"""Helper to produce a directory listing (absent index.html).
|
||||||
|
|
||||||
|
Return value is either a file object, or None (indicating an
|
||||||
|
error). In either case, the headers are sent, making the
|
||||||
|
interface the same as for send_head().
|
||||||
|
#TODO ->use web.py +template!
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
list = os.listdir(path)
|
||||||
|
except os.error:
|
||||||
|
web.header('404', "No permission to list directory")
|
||||||
|
return None
|
||||||
|
list.sort(key=lambda a: a.lower())
|
||||||
|
f = StringIO()
|
||||||
|
displaypath = cgi.escape(urllib.unquote(path))
|
||||||
|
f.write("<title>Directory listing for %s</title>\n" % displaypath)
|
||||||
|
f.write("<h2>Directory listing for %s</h2>\n" % displaypath)
|
||||||
|
f.write("<hr>\n<ul>\n")
|
||||||
|
for name in list:
|
||||||
|
fullname = os.path.join(path, name)
|
||||||
|
displayname = linkname = name
|
||||||
|
# Append / for directories or @ for symbolic links
|
||||||
|
if os.path.isdir(fullname):
|
||||||
|
displayname = name + "/"
|
||||||
|
linkname = name + "/"
|
||||||
|
if os.path.islink(fullname):
|
||||||
|
displayname = name + "@"
|
||||||
|
# Note: a link to a directory displays with @ and links with /
|
||||||
|
f.write('<li><a href="%s">%s</a>\n'
|
||||||
|
% (urllib.quote(linkname), cgi.escape(displayname)))
|
||||||
|
f.write("</ul>\n<hr>\n")
|
||||||
|
length = f.tell()
|
||||||
|
f.seek(0)
|
||||||
|
|
||||||
|
web.header("Content-type", "text/html")
|
||||||
|
web.header("Content-Length", str(length))
|
||||||
|
print f.read()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
#example:
|
||||||
|
class usr_static(static_handler):
|
||||||
|
base_dir = os.path.expanduser('~')
|
||||||
|
|
||||||
|
urls = ('/relative/(.*)','static_handler',
|
||||||
|
'/(.*)','usr_static')
|
||||||
|
|
||||||
|
web.run(urls,globals())
|
|
@ -7,6 +7,7 @@ $:render.header(_('About'))
|
||||||
<li><a href="http://deluge-torrent.org">Deluge</a></li>
|
<li><a href="http://deluge-torrent.org">Deluge</a></li>
|
||||||
<li><a href="http://forum.deluge-torrent.org/viewtopic.php?f=9&t=425">
|
<li><a href="http://forum.deluge-torrent.org/viewtopic.php?f=9&t=425">
|
||||||
WebUi forum Thread</a>
|
WebUi forum Thread</a>
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
<li><a href="http://www.gnu.org/licenses/old-licenses/gpl-2.0.html">GPL v2
|
<li><a href="http://www.gnu.org/licenses/old-licenses/gpl-2.0.html">GPL v2
|
||||||
</a></li>
|
</a></li>
|
||||||
|
@ -18,6 +19,7 @@ $:render.header(_('About'))
|
||||||
<ul>
|
<ul>
|
||||||
<li>Martijn Voncken</li>
|
<li>Martijn Voncken</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h3>Template</h3>
|
<h3>Template</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Martijn Voncken</li>
|
<li>Martijn Voncken</li>
|
||||||
|
@ -27,6 +29,7 @@ $:render.header(_('About'))
|
||||||
<ul>
|
<ul>
|
||||||
<li>Zach Tibbitts</li>
|
<li>Zach Tibbitts</li>
|
||||||
<li>Alon Zakai</li>
|
<li>Alon Zakai</li>
|
||||||
|
|
||||||
<li>Alon Zakai</li>
|
<li>Alon Zakai</li>
|
||||||
<li>Marcos Pinto</li>
|
<li>Marcos Pinto</li>
|
||||||
<li>Andrew Resch</li>
|
<li>Andrew Resch</li>
|
||||||
|
|
10
plugins/WebUi/templates/deluge/config.html
Normal file
10
plugins/WebUi/templates/deluge/config.html
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
$def with (form)
|
||||||
|
$:render.header(_('Config'))
|
||||||
|
|
||||||
|
<div class="error">Not Implemented!</div>
|
||||||
|
<form method="POST">
|
||||||
|
$:form.render()
|
||||||
|
<input type="submit" value="$_('Apply')"/>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
$:render.footer()
|
|
@ -51,8 +51,10 @@ $for torrent in torrent_list:
|
||||||
$:render.part_button('GET', '/torrent/add', _('Add torrent'), 'tango/list-add.png')
|
$:render.part_button('GET', '/torrent/add', _('Add torrent'), 'tango/list-add.png')
|
||||||
$:render.part_button('POST', '/pause_all', _('Pause all'), 'tango/media-playback-pause.png')
|
$:render.part_button('POST', '/pause_all', _('Pause all'), 'tango/media-playback-pause.png')
|
||||||
$:render.part_button('POST', '/resume_all', _('Resume all'), 'tango/media-playback-start.png')
|
$:render.part_button('POST', '/resume_all', _('Resume all'), 'tango/media-playback-start.png')
|
||||||
|
$:render.part_button('POST', '/logout', _('Logout'), 'tango/system-log-out.png')
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
$:render.part_refresh()
|
$:part_stats()
|
||||||
|
|
||||||
$:render.footer()
|
$:render.footer()
|
||||||
|
|
||||||
|
|
|
@ -2,21 +2,25 @@ $def with (method, url, title, image='')
|
||||||
<div class="deluge_button">
|
<div class="deluge_button">
|
||||||
<form method="$method" action="$url" class="deluge_button">
|
<form method="$method" action="$url" class="deluge_button">
|
||||||
<input type="hidden" name="redir" value="$self_url()">
|
<input type="hidden" name="redir" value="$self_url()">
|
||||||
<button type="submit" class="deluge_button">
|
|
||||||
$if (get_config('button_style') == 0):
|
$if (get_config('button_style') == 0):
|
||||||
|
<button type="submit" class="deluge_button" alt="$title">
|
||||||
$title
|
$title
|
||||||
$if image:
|
$if image:
|
||||||
<image src="/static/images/$image" class="button" alt="$title"/>
|
<image src="/static/images/$image" class="button" alt="$title"/>
|
||||||
|
</button>
|
||||||
|
|
||||||
$if (get_config('button_style') == 1):
|
$if (get_config('button_style') == 1):
|
||||||
$if image:
|
$if image:
|
||||||
<image src="/static/images/$image" class="button" alt="$title"/>
|
<input type="image" image src="/static/images/$image" class="img_button" alt="$title"/>
|
||||||
$else:
|
$else:
|
||||||
|
<button type="submit" class="deluge_button" alt="$title">
|
||||||
$title
|
$title
|
||||||
|
</button>
|
||||||
|
|
||||||
$if (get_config('button_style') == 2):
|
$if (get_config('button_style') == 2):
|
||||||
|
<button type="submit" class="deluge_button" alt="$title">
|
||||||
$title
|
$title
|
||||||
|
</button>
|
||||||
|
|
||||||
</button>
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
30
plugins/WebUi/templates/deluge/part_stats.html
Normal file
30
plugins/WebUi/templates/deluge/part_stats.html
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
$def with (stats)
|
||||||
|
|
||||||
|
|
||||||
|
<div class="panel" id='refresh_panel'>
|
||||||
|
|
||||||
|
$_('Auto refresh:')
|
||||||
|
$if getcookie('auto_refresh') == '1':
|
||||||
|
($getcookie('auto_refresh_secs')) $_('seconds')
|
||||||
|
$:render.part_button('GET', '/refresh/set', _('Set'), 'tango/preferences-system.png')
|
||||||
|
$:render.part_button('POST', '/refresh/off', _('Disable'), 'tango/process-stop.png')
|
||||||
|
$else:
|
||||||
|
$_('Off')
|
||||||
|
$:render.part_button('POST', '/refresh/on', _('Enable'), 'tango/view-refresh.png')
|
||||||
|
$#end
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="panel" id='refresh_panel'>
|
||||||
|
<a href='/config'>
|
||||||
|
$_('Down Speed') : $stats.download_rate ($stats.max_download)
|
||||||
|
|
||||||
|
$_('Up Speed') : $stats.upload_rate ($stats.max_upload)
|
||||||
|
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
(<a href='/about'>$_('About')</a>)
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -84,6 +84,7 @@ $:render.part_button('GET', '/torrent/delete/' + str(torrent.id), _('Remove'), '
|
||||||
|
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
<!--
|
||||||
[<a onclick="javascript:toggle_dump()">$_('Debug:Data Dump')</a>]
|
[<a onclick="javascript:toggle_dump()">$_('Debug:Data Dump')</a>]
|
||||||
|
|
||||||
<pre style="background-color:white;color:black;display:none" id="data_dump">
|
<pre style="background-color:white;color:black;display:none" id="data_dump">
|
||||||
|
@ -102,6 +103,8 @@ function toggle_dump(){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
-->
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
@ -114,6 +117,6 @@ $:render.part_button('POST', '/torrent/queue/up/' + str(torrent.id), _('Queue Up
|
||||||
$:render.part_button('POST', '/torrent/queue/down/' + str(torrent.id), _('Queue Down'), 'tango/down.png')
|
$:render.part_button('POST', '/torrent/queue/down/' + str(torrent.id), _('Queue Down'), 'tango/down.png')
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
$:render.part_refresh()
|
$:part_stats()
|
||||||
|
|
||||||
$:render.footer()
|
$:render.footer()
|
||||||
|
|
3
plugins/WebUi/templates/example/footer.html
Normal file
3
plugins/WebUi/templates/example/footer.html
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
12
plugins/WebUi/templates/example/header.html
Normal file
12
plugins/WebUi/templates/example/header.html
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
$def with (title)
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Deluge(example) : $title</title>
|
||||||
|
<link rel="icon" href="/static/images/deluge_icon.gif" type="image/gif" />
|
||||||
|
<link rel="shortcut icon" href="/static/images/deluge_icon.gif" type="image/gif" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<img src="/template/static/example.png">
|
||||||
|
<a href=/home>[HOME]</a>
|
||||||
|
|
||||||
|
<h1>$title</h1>
|
42
plugins/WebUi/templates/example/index.html
Normal file
42
plugins/WebUi/templates/example/index.html
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
$def with (torrent_list)
|
||||||
|
$:render.header(_('Torrent list'))
|
||||||
|
|
||||||
|
<form action="/torrent/pause" method="POST">
|
||||||
|
<table class="torrent_list" border=1>
|
||||||
|
<tr>
|
||||||
|
$:(sort_head('calc_state_str', 'S'))
|
||||||
|
$:(sort_head('queue_pos', '#'))
|
||||||
|
$:(sort_head('name', _('Name')))
|
||||||
|
$:(sort_head('progress', _('Progress')))
|
||||||
|
</tr>
|
||||||
|
$#4-space indentation is mandatory for for-loops in templetor!
|
||||||
|
$for torrent in torrent_list:
|
||||||
|
<tr>
|
||||||
|
<td><input type="image"
|
||||||
|
src="/static/images/$(torrent.calc_state_str)16.png"
|
||||||
|
name="$torrent.action" value="$torrent.id">
|
||||||
|
</td>
|
||||||
|
<td>$torrent.queue_pos</td>
|
||||||
|
<td style="width:100px; overflow:hidden;white-space: nowrap">
|
||||||
|
<a href="/torrent/info/$torrent.id">$(crop(torrent.name, 40))</a></td>
|
||||||
|
<td class="progress_bar">
|
||||||
|
<div class="progress_bar_outer">
|
||||||
|
<div class="progress_bar" style="width:$(torrent.progress)%">
|
||||||
|
$torrent.message
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div class="panel" bgcolor="5555AA">
|
||||||
|
$:render.part_button('GET', '/torrent/add', _('Add torrent'), 'tango/list-add.png')
|
||||||
|
$:render.part_button('POST', '/pause_all', _('Pause all'), 'tango/media-playback-pause.png')
|
||||||
|
$:render.part_button('POST', '/resume_all', _('Resume all'), 'tango/media-playback-start.png')
|
||||||
|
$:render.part_button('POST', '/logout', _('Logout'), 'tango/system-log-out.png')
|
||||||
|
</div>
|
||||||
|
|
||||||
|
$:render.footer()
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
revision-id: mvoncken@gmail.com-20070930083408-sv8mo0mi1rbjnfvk
|
revision-id: mvoncken@gmail.com-20070930083408-sv8mo0mi1rbjnfvk
|
||||||
date: 2007-10-23 15:10:08 +0200
|
date: 2007-10-23 15:10:08 +0200
|
||||||
build-date: 2007-10-23 15:34:50 +0200
|
build-date: 2007-10-23 15:34:50 +0200
|
||||||
revno: 87
|
revno: 112
|
||||||
branch-nick: WebUi
|
branch-nick: WebUi
|
||||||
|
|
|
@ -29,40 +29,96 @@
|
||||||
# this exception statement from your version. If you delete this exception
|
# this exception statement from your version. If you delete this exception
|
||||||
# statement from all source files in the program, then also delete it here.
|
# statement from all source files in the program, then also delete it here.
|
||||||
|
|
||||||
|
"""
|
||||||
|
initializes config,render and proxy.
|
||||||
|
contains all hacks to support running in process0.5 ,run inside-gtk0.5 and
|
||||||
|
run in process0.6
|
||||||
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import deluge
|
import deluge
|
||||||
from deluge.common import INSTALL_PREFIX
|
|
||||||
import random
|
import random
|
||||||
import pickle
|
import pickle
|
||||||
|
import sys
|
||||||
from webpy022 import template
|
from webpy022 import template
|
||||||
|
|
||||||
random.seed()
|
random.seed()
|
||||||
|
path = os.path.dirname(__file__)
|
||||||
|
|
||||||
config_file = deluge.common.CONFIG_DIR + "/webui.conf"
|
try:
|
||||||
|
_('translate something')
|
||||||
|
except:
|
||||||
|
import gettext
|
||||||
|
gettext.install('~/') #no translations :(
|
||||||
|
|
||||||
#a bit hacky way of detecting i'm in the deluge gui or in a process :(
|
try:
|
||||||
if not hasattr(deluge,'pref'):
|
config_dir = deluge.common.CONFIG_DIR
|
||||||
|
except:
|
||||||
|
config_dir = os.path.expanduser("~/.config/deluge")
|
||||||
|
|
||||||
|
config_file = os.path.join(config_dir,'webui.conf')
|
||||||
|
session_file = os.path.join(config_dir,'webui.sessions')
|
||||||
|
|
||||||
|
|
||||||
|
class subclassed_render(object):
|
||||||
|
"""
|
||||||
|
try to use the html template in configured dir.
|
||||||
|
not available : use template in /deluge/
|
||||||
|
"""
|
||||||
|
def __init__(self, template_dirname, cache=False):
|
||||||
|
self.base_template = template.render(
|
||||||
|
os.path.join(path, 'templates/deluge/'),
|
||||||
|
cache=cache)
|
||||||
|
|
||||||
|
self.sub_template = template.render(
|
||||||
|
os.path.join(path, 'templates/%s/' % template_dirname),
|
||||||
|
cache=cache)
|
||||||
|
|
||||||
|
def __getattr__(self, attr):
|
||||||
|
if hasattr(self.sub_template, attr):
|
||||||
|
return getattr(self.sub_template, attr)
|
||||||
|
else:
|
||||||
|
return getattr(self.base_template, attr)
|
||||||
|
|
||||||
|
def init_process():
|
||||||
|
globals()['config'] = pickle.load(open(config_file))
|
||||||
|
globals()['render'] = subclassed_render(config.get('template'),
|
||||||
|
config.get('cache_templates'))
|
||||||
|
|
||||||
|
def init_06():
|
||||||
|
import deluge.ui.client as proxy
|
||||||
|
proxy.set_core_uri('http://localhost:58846') #How to configure this?
|
||||||
|
|
||||||
|
init_process()
|
||||||
|
globals()['proxy'] = proxy
|
||||||
|
|
||||||
|
def init_05():
|
||||||
import dbus
|
import dbus
|
||||||
|
init_process()
|
||||||
bus = dbus.SessionBus()
|
bus = dbus.SessionBus()
|
||||||
proxy = bus.get_object("org.deluge_torrent.dbusplugin"
|
proxy = bus.get_object("org.deluge_torrent.dbusplugin"
|
||||||
, "/org/deluge_torrent/DelugeDbusPlugin")
|
, "/org/deluge_torrent/DelugeDbusPlugin")
|
||||||
config = pickle.load(open(config_file))
|
globals()['proxy'] = proxy
|
||||||
render = template.render('templates/%s/' % config.get('template'),
|
|
||||||
cache=config.get('cache_templates'))
|
|
||||||
|
|
||||||
def init():
|
def init_gtk_05():
|
||||||
#appy possibly changed config-vars, only called in when runing inside gtk.
|
#appy possibly changed config-vars, only called in when runing inside gtk.
|
||||||
path = os.path.dirname(__file__)
|
|
||||||
from dbus_interface import get_dbus_manager
|
from dbus_interface import get_dbus_manager
|
||||||
globals()['proxy'] = get_dbus_manager()
|
globals()['proxy'] = get_dbus_manager()
|
||||||
globals()['config'] = deluge.pref.Preferences(config_file, False)
|
globals()['config'] = deluge.pref.Preferences(config_file, False)
|
||||||
globals()['render'] = template.render(os.path.join(path, 'templates/%s/' %
|
globals()['render'] = subclassed_render(config.get('template'),
|
||||||
config.get('template')), cache=config.get('cache_templates'))
|
config.get('cache_templates'))
|
||||||
|
|
||||||
|
|
||||||
|
#hacks to determine environment, TODO: clean up.
|
||||||
|
if 'env=0.5' in sys.argv:
|
||||||
|
init_05()
|
||||||
|
elif not hasattr(deluge, 'common'):
|
||||||
|
init_06()
|
||||||
|
elif not hasattr(deluge,'pref'):
|
||||||
|
init_05()
|
||||||
|
|
||||||
|
|
||||||
REVNO = '0.56.stable.' + open(os.path.join(os.path.dirname(__file__),'revno')).read()
|
#constants
|
||||||
|
REVNO = open(os.path.join(os.path.dirname(__file__),'revno')).read()
|
||||||
VERSION = open(os.path.join(os.path.dirname(__file__),'version')).read()
|
VERSION = open(os.path.join(os.path.dirname(__file__),'version')).read()
|
||||||
|
|
||||||
TORRENT_KEYS = ['distributed_copies', 'download_payload_rate',
|
TORRENT_KEYS = ['distributed_copies', 'download_payload_rate',
|
||||||
|
@ -82,3 +138,30 @@ STATE_MESSAGES = (_("Queued"),
|
||||||
_("Finished"),
|
_("Finished"),
|
||||||
_("Seeding"),
|
_("Seeding"),
|
||||||
_("Allocating"))
|
_("Allocating"))
|
||||||
|
|
||||||
|
SPEED_VALUES = [
|
||||||
|
(-1, 'Unlimited'),
|
||||||
|
(5, '5.0 Kib/sec'),
|
||||||
|
(10, '10.0 Kib/sec'),
|
||||||
|
(15, '15.0 Kib/sec'),
|
||||||
|
(25, '25.0 Kib/sec'),
|
||||||
|
(30, '30.0 Kib/sec'),
|
||||||
|
(50, '50.0 Kib/sec'),
|
||||||
|
(80, '80.0 Kib/sec'),
|
||||||
|
(300, '300.0 Kib/sec'),
|
||||||
|
(500, '500.0 Kib/sec')
|
||||||
|
]
|
||||||
|
|
||||||
|
COOKIE_DEFAULTS = {
|
||||||
|
'auto_refresh_secs':'10'
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
SESSIONS = pickle.load(open(session_file))
|
||||||
|
except:
|
||||||
|
SESSIONS = []
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -45,15 +45,21 @@ import webpy022 as web
|
||||||
from webpy022.webapi import cookies, setcookie as w_setcookie
|
from webpy022.webapi import cookies, setcookie as w_setcookie
|
||||||
from webpy022.http import seeother, url
|
from webpy022.http import seeother, url
|
||||||
from webpy022 import template,changequery as self_url
|
from webpy022 import template,changequery as self_url
|
||||||
|
from webpy022.utils import Storage
|
||||||
|
from static_handler import static_handler
|
||||||
|
|
||||||
|
from deluge.common import fsize,fspeed
|
||||||
|
|
||||||
import traceback
|
import traceback
|
||||||
import random
|
import random
|
||||||
from operator import attrgetter
|
from operator import attrgetter
|
||||||
|
import datetime
|
||||||
|
import pickle
|
||||||
|
from md5 import md5
|
||||||
|
|
||||||
from deluge import common
|
from deluge import common
|
||||||
from webserver_common import REVNO, VERSION
|
from webserver_common import REVNO, VERSION, COOKIE_DEFAULTS
|
||||||
import webserver_common as ws
|
import webserver_common as ws
|
||||||
|
|
||||||
from debugerror import deluge_debugerror
|
from debugerror import deluge_debugerror
|
||||||
|
|
||||||
#init:
|
#init:
|
||||||
|
@ -65,14 +71,22 @@ def setcookie(key, val):
|
||||||
"""add 30 days expires header for persistent cookies"""
|
"""add 30 days expires header for persistent cookies"""
|
||||||
return w_setcookie(key, val , expires=2592000)
|
return w_setcookie(key, val , expires=2592000)
|
||||||
|
|
||||||
SESSIONS = [] #dumb sessions.
|
#really simple sessions, to bad i had to implement them myself.
|
||||||
def start_session():
|
def start_session():
|
||||||
session_id = str(random.random())
|
session_id = str(random.random())
|
||||||
SESSIONS.append(session_id)
|
ws.SESSIONS.append(session_id)
|
||||||
|
if len(ws.SESSIONS) > 20: #save max 20 sessions?
|
||||||
|
ws.SESSIONS = ws.SESSIONS[-20:]
|
||||||
|
#not thread safe! , but a verry rare bug.
|
||||||
|
pickle.dump(ws.SESSIONS, open(ws.session_file,'wb'))
|
||||||
setcookie("session_id", session_id)
|
setcookie("session_id", session_id)
|
||||||
|
|
||||||
if getcookie('auto_refresh_secs') == None:
|
def end_session():
|
||||||
setcookie('auto_refresh_secs','10')
|
session_id = getcookie("session_id")
|
||||||
|
if session_id in ws.SESSIONS:
|
||||||
|
ws.SESSIONS.remove(session_id)
|
||||||
|
#not thread safe! , but a verry rare bug.
|
||||||
|
pickle.dump(ws.SESSIONS, open(ws.session_file,'wb'))
|
||||||
|
|
||||||
def do_redirect():
|
def do_redirect():
|
||||||
"""for redirects after a POST"""
|
"""for redirects after a POST"""
|
||||||
|
@ -92,7 +106,6 @@ def error_page(error):
|
||||||
print ws.render.error(error)
|
print ws.render.error(error)
|
||||||
|
|
||||||
def getcookie(key, default=None):
|
def getcookie(key, default=None):
|
||||||
COOKIE_DEFAULTS = {'auto_refresh_secs':'10'}
|
|
||||||
key = str(key).strip()
|
key = str(key).strip()
|
||||||
ck = cookies()
|
ck = cookies()
|
||||||
val = ck.get(key, default)
|
val = ck.get(key, default)
|
||||||
|
@ -120,9 +133,8 @@ def check_session(func):
|
||||||
"""
|
"""
|
||||||
def deco(self, name):
|
def deco(self, name):
|
||||||
vars = web.input(redir_after_login=None)
|
vars = web.input(redir_after_login=None)
|
||||||
|
|
||||||
ck = cookies()
|
ck = cookies()
|
||||||
if ck.has_key("session_id") and ck["session_id"] in SESSIONS:
|
if ck.has_key("session_id") and ck["session_id"] in ws.SESSIONS:
|
||||||
return func(self, name) #ok, continue..
|
return func(self, name) #ok, continue..
|
||||||
elif vars.redir_after_login:
|
elif vars.redir_after_login:
|
||||||
seeother(url("/login",redir=self_url()))
|
seeother(url("/login",redir=self_url()))
|
||||||
|
@ -154,6 +166,77 @@ def remote(func):
|
||||||
print traceback.format_exc()
|
print traceback.format_exc()
|
||||||
return deco
|
return deco
|
||||||
|
|
||||||
|
#utils:
|
||||||
|
def check_pwd(pwd):
|
||||||
|
m = md5()
|
||||||
|
m.update(ws.config.get('pwd_salt'))
|
||||||
|
m.update(pwd)
|
||||||
|
return (m.digest() == ws.config.get('pwd_md5'))
|
||||||
|
|
||||||
|
def get_stats():
|
||||||
|
stats = Storage({
|
||||||
|
'download_rate':fspeed(ws.proxy.get_download_rate()),
|
||||||
|
'upload_rate':fspeed(ws.proxy.get_upload_rate()),
|
||||||
|
'max_download':ws.proxy.get_config_value('max_download_speed_bps'),
|
||||||
|
'max_upload':ws.proxy.get_config_value('max_upload_speed_bps'),
|
||||||
|
})
|
||||||
|
if stats.max_upload < 0:
|
||||||
|
stats.max_upload = _("Unlimited")
|
||||||
|
else:
|
||||||
|
stats.max_upload = fspeed(stats.max_upload)
|
||||||
|
|
||||||
|
if stats.max_download < 0:
|
||||||
|
stats.max_download = _("Unlimited")
|
||||||
|
else:
|
||||||
|
stats.max_download = fspeed(stats.max_download)
|
||||||
|
|
||||||
|
return stats
|
||||||
|
|
||||||
|
|
||||||
|
def get_torrent_status(torrent_id):
|
||||||
|
"""
|
||||||
|
helper method.
|
||||||
|
enhance ws.proxy.get_torrent_status with some extra data
|
||||||
|
"""
|
||||||
|
status = Storage(ws.proxy.get_torrent_status(torrent_id,ws.TORRENT_KEYS))
|
||||||
|
|
||||||
|
#add missing values for deluge 0.6:
|
||||||
|
for key in ws.TORRENT_KEYS:
|
||||||
|
if not key in status:
|
||||||
|
status[key] = 0
|
||||||
|
|
||||||
|
status["id"] = torrent_id
|
||||||
|
|
||||||
|
#for naming the status-images
|
||||||
|
status["calc_state_str"] = "downloading"
|
||||||
|
if status["paused"]:
|
||||||
|
status["calc_state_str"] = "inactive"
|
||||||
|
elif status["is_seed"]:
|
||||||
|
status["calc_state_str"] = "seeding"
|
||||||
|
|
||||||
|
#action for torrent_pause
|
||||||
|
if status["calc_state_str"] == "inactive":
|
||||||
|
status["action"] = "start"
|
||||||
|
else:
|
||||||
|
status["action"] = "stop"
|
||||||
|
|
||||||
|
if status["paused"]:
|
||||||
|
status["message"] = _("Paused %s%%") % status['progress']
|
||||||
|
else:
|
||||||
|
status["message"] = "%s %i%%" % (ws.STATE_MESSAGES[status["state"]]
|
||||||
|
, status['progress'])
|
||||||
|
|
||||||
|
#add some pre-calculated values
|
||||||
|
status.update({
|
||||||
|
"calc_total_downloaded" : (fsize(status["total_done"])
|
||||||
|
+ " (" + fsize(status["total_download"]) + ")"),
|
||||||
|
"calc_total_uploaded": (fsize(status['uploaded_memory']
|
||||||
|
+ status["total_payload_upload"]) + " ("
|
||||||
|
+ fsize(status["total_upload"]) + ")"),
|
||||||
|
})
|
||||||
|
return status
|
||||||
|
#/utils
|
||||||
|
|
||||||
#template-defs:
|
#template-defs:
|
||||||
def template_crop(text, end):
|
def template_crop(text, end):
|
||||||
if len(text) > end:
|
if len(text) > end:
|
||||||
|
@ -176,12 +259,15 @@ def template_sort_head(id,name):
|
||||||
|
|
||||||
return ws.render.sort_column_head(id, name, order, active_up, active_down)
|
return ws.render.sort_column_head(id, name, order, active_up, active_down)
|
||||||
|
|
||||||
|
def template_part_stats():
|
||||||
|
return ws.render.part_stats(get_stats())
|
||||||
|
|
||||||
def get_config(var):
|
def get_config(var):
|
||||||
return ws.config.get(var)
|
return ws.config.get(var)
|
||||||
|
|
||||||
template.Template.globals.update({
|
template.Template.globals.update({
|
||||||
'sort_head': template_sort_head,
|
'sort_head': template_sort_head,
|
||||||
|
'part_stats':template_part_stats,
|
||||||
'crop': template_crop,
|
'crop': template_crop,
|
||||||
'_': _ , #gettext/translations
|
'_': _ , #gettext/translations
|
||||||
'str': str, #because % in templetor is broken.
|
'str': str, #because % in templetor is broken.
|
||||||
|
@ -198,145 +284,20 @@ template.Template.globals.update({
|
||||||
})
|
})
|
||||||
#/template-defs
|
#/template-defs
|
||||||
|
|
||||||
|
def create_webserver(urls, methods):
|
||||||
|
from webpy022.request import webpyfunc
|
||||||
|
from webpy022 import webapi
|
||||||
|
from gtk_cherrypy_wsgiserver import CherryPyWSGIServer
|
||||||
|
|
||||||
|
func = webapi.wsgifunc(webpyfunc(urls, methods, False))
|
||||||
#------------------------------------------------------------------------------
|
server_address=("0.0.0.0", int(ws.config.get('port')))
|
||||||
#Some copy and paste from web.py
|
|
||||||
#mostly caused by /static
|
|
||||||
#TODO : FIX THIS.
|
|
||||||
#static-files serving should be moved to the normal webserver!
|
|
||||||
from SimpleHTTPServer import SimpleHTTPRequestHandler
|
|
||||||
from BaseHTTPServer import BaseHTTPRequestHandler
|
|
||||||
from gtk_cherrypy_wsgiserver import CherryPyWSGIServer
|
|
||||||
from BaseHTTPServer import BaseHTTPRequestHandler
|
|
||||||
|
|
||||||
from webpy022.request import webpyfunc
|
|
||||||
from webpy022 import webapi
|
|
||||||
import os
|
|
||||||
|
|
||||||
import posixpath
|
|
||||||
import urllib
|
|
||||||
import urlparse
|
|
||||||
|
|
||||||
class RelativeHandler(SimpleHTTPRequestHandler):
|
|
||||||
def translate_path(self, path):
|
|
||||||
"""Translate a /-separated PATH to the local filename syntax.
|
|
||||||
|
|
||||||
Components that mean special things to the local file system
|
|
||||||
(e.g. drive or directory names) are ignored. (XXX They should
|
|
||||||
probably be diagnosed.)
|
|
||||||
|
|
||||||
"""
|
|
||||||
# abandon query parameters
|
|
||||||
path = urlparse.urlparse(path)[2]
|
|
||||||
path = posixpath.normpath(urllib.unquote(path))
|
|
||||||
words = path.split('/')
|
|
||||||
words = filter(None, words)
|
|
||||||
path = os.path.dirname(__file__)
|
|
||||||
for word in words:
|
|
||||||
drive, word = os.path.splitdrive(word)
|
|
||||||
head, word = os.path.split(word)
|
|
||||||
if word in (os.curdir, os.pardir): continue
|
|
||||||
path = os.path.join(path, word)
|
|
||||||
return path
|
|
||||||
|
|
||||||
class StaticApp(RelativeHandler):
|
|
||||||
"""WSGI application for serving static files."""
|
|
||||||
def __init__(self, environ, start_response):
|
|
||||||
self.headers = []
|
|
||||||
self.environ = environ
|
|
||||||
self.start_response = start_response
|
|
||||||
|
|
||||||
def send_response(self, status, msg=""):
|
|
||||||
self.status = str(status) + " " + msg
|
|
||||||
|
|
||||||
def send_header(self, name, value):
|
|
||||||
self.headers.append((name, value))
|
|
||||||
|
|
||||||
def end_headers(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def log_message(*a): pass
|
|
||||||
|
|
||||||
def __iter__(self):
|
|
||||||
environ = self.environ
|
|
||||||
|
|
||||||
self.path = environ.get('PATH_INFO', '')
|
|
||||||
self.client_address = environ.get('REMOTE_ADDR','-'), \
|
|
||||||
environ.get('REMOTE_PORT','-')
|
|
||||||
self.command = environ.get('REQUEST_METHOD', '-')
|
|
||||||
|
|
||||||
from cStringIO import StringIO
|
|
||||||
self.wfile = StringIO() # for capturing error
|
|
||||||
|
|
||||||
f = self.send_head()
|
|
||||||
self.start_response(self.status, self.headers)
|
|
||||||
|
|
||||||
if f:
|
|
||||||
block_size = 16 * 1024
|
|
||||||
while True:
|
|
||||||
buf = f.read(block_size)
|
|
||||||
if not buf:
|
|
||||||
break
|
|
||||||
yield buf
|
|
||||||
f.close()
|
|
||||||
else:
|
|
||||||
value = self.wfile.getvalue()
|
|
||||||
yield value
|
|
||||||
|
|
||||||
class WSGIWrapper(BaseHTTPRequestHandler):
|
|
||||||
"""WSGI wrapper for logging the status and serving static files."""
|
|
||||||
def __init__(self, app):
|
|
||||||
self.app = app
|
|
||||||
self.format = '%s - - [%s] "%s %s %s" - %s'
|
|
||||||
|
|
||||||
def __call__(self, environ, start_response):
|
|
||||||
def xstart_response(status, response_headers, *args):
|
|
||||||
write = start_response(status, response_headers, *args)
|
|
||||||
self.log(status, environ)
|
|
||||||
return write
|
|
||||||
|
|
||||||
path = environ.get('PATH_INFO', '')
|
|
||||||
if path.startswith('/static/'):
|
|
||||||
return StaticApp(environ, xstart_response)
|
|
||||||
else:
|
|
||||||
return self.app(environ, xstart_response)
|
|
||||||
|
|
||||||
def log(self, status, environ):
|
|
||||||
#mvoncken,no logging..
|
|
||||||
return
|
|
||||||
|
|
||||||
outfile = environ.get('wsgi.errors', web.debug)
|
|
||||||
req = environ.get('PATH_INFO', '_')
|
|
||||||
protocol = environ.get('ACTUAL_SERVER_PROTOCOL', '-')
|
|
||||||
method = environ.get('REQUEST_METHOD', '-')
|
|
||||||
host = "%s:%s" % (environ.get('REMOTE_ADDR','-'),
|
|
||||||
environ.get('REMOTE_PORT','-'))
|
|
||||||
|
|
||||||
#@@ It is really bad to extend from
|
|
||||||
#@@ BaseHTTPRequestHandler just for this method
|
|
||||||
time = self.log_date_time_string()
|
|
||||||
|
|
||||||
print >> outfile, self.format % (host, time, protocol,
|
|
||||||
method, req, status)
|
|
||||||
|
|
||||||
def create_webserver(urls,methods):
|
|
||||||
func = webapi.wsgifunc(webpyfunc(urls,methods, False))
|
|
||||||
server_address=("0.0.0.0",ws.config.get('port'))
|
|
||||||
|
|
||||||
func = WSGIWrapper(func)
|
|
||||||
server = CherryPyWSGIServer(server_address, func, server_name="localhost")
|
server = CherryPyWSGIServer(server_address, func, server_name="localhost")
|
||||||
|
print "http://%s:%d/" % server_address
|
||||||
|
|
||||||
print "(created) http://%s:%d/" % server_address
|
|
||||||
|
|
||||||
return server
|
return server
|
||||||
|
|
||||||
#------
|
#------
|
||||||
__all__ = ['deluge_page_noauth', 'deluge_page', 'remote',
|
__all__ = ['deluge_page_noauth', 'deluge_page', 'remote',
|
||||||
'auto_refreshed', 'check_session',
|
'auto_refreshed', 'check_session',
|
||||||
'do_redirect', 'error_page','start_session','getcookie'
|
'do_redirect', 'error_page','start_session','getcookie'
|
||||||
,'create_webserver','setcookie']
|
,'setcookie','create_webserver','end_session',
|
||||||
|
'get_torrent_status', 'check_pwd','static_handler']
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -54,3 +54,7 @@ plugins/WebSeed/__init__.py
|
||||||
plugins/WebSeed/webseed.glade
|
plugins/WebSeed/webseed.glade
|
||||||
plugins/Scheduler/__init__.py
|
plugins/Scheduler/__init__.py
|
||||||
plugins/Scheduler/plugin.py
|
plugins/Scheduler/plugin.py
|
||||||
|
plugins/WebUi/__init__.py
|
||||||
|
plugins/WebUi/webserver_common.py
|
||||||
|
plugins/WebUi/deluge_webserver.py
|
||||||
|
plugins/WebUi/scripts/template_strings.py
|
||||||
|
|
254
po/deluge.pot
254
po/deluge.pot
|
@ -8,7 +8,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2007-10-22 22:35-0500\n"
|
"POT-Creation-Date: 2007-10-27 20:34-0500\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
@ -88,7 +88,7 @@ msgstr ""
|
||||||
msgid "<b>Torrent Info</b>"
|
msgid "<b>Torrent Info</b>"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: glade/delugegtk.glade:750
|
#: glade/delugegtk.glade:750 plugins/WebUi/scripts/template_strings.py:8
|
||||||
msgid "Details"
|
msgid "Details"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -140,7 +140,7 @@ msgstr ""
|
||||||
msgid "_Columns"
|
msgid "_Columns"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: glade/delugegtk.glade:947 src/interface.py:596 src/files.py:79
|
#: glade/delugegtk.glade:947 src/interface.py:596 src/files.py:80
|
||||||
msgid "Size"
|
msgid "Size"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -149,11 +149,13 @@ msgid "Status"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: glade/delugegtk.glade:965 src/interface.py:602
|
#: glade/delugegtk.glade:965 src/interface.py:602
|
||||||
|
#: plugins/WebUi/scripts/template_strings.py:19
|
||||||
msgid "Seeders"
|
msgid "Seeders"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: glade/delugegtk.glade:974 src/interface.py:605
|
#: glade/delugegtk.glade:974 src/interface.py:605
|
||||||
#: plugins/TorrentPeers/__init__.py:72
|
#: plugins/TorrentPeers/__init__.py:72
|
||||||
|
#: plugins/WebUi/scripts/template_strings.py:15
|
||||||
msgid "Peers"
|
msgid "Peers"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -171,11 +173,11 @@ msgstr ""
|
||||||
msgid "Time Remaining"
|
msgid "Time Remaining"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: glade/delugegtk.glade:1010
|
#: glade/delugegtk.glade:1010 plugins/WebUi/scripts/template_strings.py:4
|
||||||
msgid "Availability"
|
msgid "Availability"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: glade/delugegtk.glade:1019
|
#: glade/delugegtk.glade:1019 plugins/WebUi/scripts/template_strings.py:21
|
||||||
msgid "Share Ratio"
|
msgid "Share Ratio"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -211,7 +213,7 @@ msgstr ""
|
||||||
msgid "Remove Torrent"
|
msgid "Remove Torrent"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: glade/delugegtk.glade:1157
|
#: glade/delugegtk.glade:1157 plugins/WebUi/scripts/template_strings.py:18
|
||||||
msgid "Remove"
|
msgid "Remove"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -278,7 +280,7 @@ msgstr ""
|
||||||
msgid "Delete downloaded files"
|
msgid "Delete downloaded files"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: glade/dgtkpopups.glade:88
|
#: glade/dgtkpopups.glade:88 plugins/WebUi/scripts/template_strings.py:6
|
||||||
msgid "Delete .torrent file"
|
msgid "Delete .torrent file"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -294,7 +296,7 @@ msgstr ""
|
||||||
msgid "Clear Finished"
|
msgid "Clear Finished"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: glade/dgtkpopups.glade:241
|
#: glade/dgtkpopups.glade:241 plugins/WebUi/scripts/template_strings.py:22
|
||||||
msgid "Speed"
|
msgid "Speed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -542,6 +544,7 @@ msgid "<b>Seeding</b>"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: glade/preferences_dialog.glade:964 src/core.py:91
|
#: glade/preferences_dialog.glade:964 src/core.py:91
|
||||||
|
#: plugins/WebUi/webserver_common.py:139
|
||||||
msgid "Seeding"
|
msgid "Seeding"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -646,6 +649,7 @@ msgstr ""
|
||||||
|
|
||||||
#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1672
|
#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1672
|
||||||
#: glade/preferences_dialog.glade:1866 glade/preferences_dialog.glade:2060
|
#: glade/preferences_dialog.glade:1866 glade/preferences_dialog.glade:2060
|
||||||
|
#: plugins/WebUi/scripts/template_strings.py:13
|
||||||
msgid "Password"
|
msgid "Password"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1004,7 +1008,7 @@ msgstr ""
|
||||||
msgid "Name"
|
msgid "Name"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/interface.py:614
|
#: src/interface.py:614 plugins/WebUi/scripts/template_strings.py:10
|
||||||
msgid "ETA"
|
msgid "ETA"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1088,31 +1092,32 @@ msgstr ""
|
||||||
msgid "Are you sure that you want to remove all seeding torrents?"
|
msgid "Are you sure that you want to remove all seeding torrents?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/core.py:85
|
#: src/core.py:85 plugins/WebUi/webserver_common.py:133
|
||||||
msgid "Queued"
|
msgid "Queued"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/core.py:86
|
#: src/core.py:86 plugins/WebUi/webserver_common.py:134
|
||||||
msgid "Checking"
|
msgid "Checking"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/core.py:87
|
#: src/core.py:87 plugins/WebUi/webserver_common.py:135
|
||||||
msgid "Connecting"
|
msgid "Connecting"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/core.py:88
|
#: src/core.py:88 plugins/WebUi/webserver_common.py:136
|
||||||
msgid "Downloading Metadata"
|
msgid "Downloading Metadata"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/core.py:89 plugins/BlocklistImport/ui.py:117
|
#: src/core.py:89 plugins/BlocklistImport/ui.py:117
|
||||||
|
#: plugins/WebUi/webserver_common.py:137
|
||||||
msgid "Downloading"
|
msgid "Downloading"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/core.py:90
|
#: src/core.py:90 plugins/WebUi/webserver_common.py:138
|
||||||
msgid "Finished"
|
msgid "Finished"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/core.py:92
|
#: src/core.py:92 plugins/WebUi/webserver_common.py:140
|
||||||
msgid "Allocating"
|
msgid "Allocating"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1156,11 +1161,11 @@ msgstr ""
|
||||||
msgid "Filename"
|
msgid "Filename"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/files.py:81
|
#: src/files.py:82
|
||||||
msgid "Priority"
|
msgid "Priority"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/files.py:103
|
#: src/files.py:104
|
||||||
msgid ""
|
msgid ""
|
||||||
"File priority can only be set when using full allocation.\n"
|
"File priority can only be set when using full allocation.\n"
|
||||||
"Please change your preference to disable compact allocation, then remove and "
|
"Please change your preference to disable compact allocation, then remove and "
|
||||||
|
@ -1175,11 +1180,11 @@ msgstr ""
|
||||||
msgid "Enabled"
|
msgid "Enabled"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/dialogs.py:433
|
#: src/dialogs.py:435
|
||||||
msgid "translator-credits"
|
msgid "translator-credits"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/dialogs.py:434
|
#: src/dialogs.py:436
|
||||||
msgid ""
|
msgid ""
|
||||||
"Deluge is free software, you can redistribute it and/or\n"
|
"Deluge is free software, you can redistribute it and/or\n"
|
||||||
"modify it under the terms of the GNU General Public\n"
|
"modify it under the terms of the GNU General Public\n"
|
||||||
|
@ -1196,15 +1201,15 @@ msgid ""
|
||||||
"1301 USA"
|
"1301 USA"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/dialogs.py:474
|
#: src/dialogs.py:476
|
||||||
msgid "Choose a .torrent file"
|
msgid "Choose a .torrent file"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/dialogs.py:479
|
#: src/dialogs.py:481
|
||||||
msgid "Torrent files"
|
msgid "Torrent files"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/dialogs.py:483
|
#: src/dialogs.py:485
|
||||||
msgid "All files"
|
msgid "All files"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1390,66 +1395,66 @@ msgstr ""
|
||||||
msgid "Torrent Creator"
|
msgid "Torrent Creator"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: plugins/TorrentCreator/torrentcreator.glade:103
|
#: plugins/TorrentCreator/torrentcreator.glade:102
|
||||||
msgid "This torrent will be made from a single file"
|
msgid "This torrent will be made from a single file"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: plugins/TorrentCreator/torrentcreator.glade:104
|
#: plugins/TorrentCreator/torrentcreator.glade:103
|
||||||
msgid "File:"
|
msgid "File:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: plugins/TorrentCreator/torrentcreator.glade:120
|
#: plugins/TorrentCreator/torrentcreator.glade:119
|
||||||
msgid "This torrent will be made from a directory"
|
msgid "This torrent will be made from a directory"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: plugins/TorrentCreator/torrentcreator.glade:121
|
#: plugins/TorrentCreator/torrentcreator.glade:120
|
||||||
msgid "Folder:"
|
msgid "Folder:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: plugins/TorrentCreator/torrentcreator.glade:138
|
#: plugins/TorrentCreator/torrentcreator.glade:137
|
||||||
msgid "<b>Source</b>"
|
msgid "<b>Source</b>"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: plugins/TorrentCreator/torrentcreator.glade:184
|
#: plugins/TorrentCreator/torrentcreator.glade:182
|
||||||
msgid "Save Torrent File As:"
|
msgid "Save Torrent File As:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: plugins/TorrentCreator/torrentcreator.glade:237
|
#: plugins/TorrentCreator/torrentcreator.glade:235
|
||||||
msgid "Load this torrent into Deluge for seeding"
|
msgid "Load this torrent into Deluge for seeding"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: plugins/TorrentCreator/torrentcreator.glade:238
|
#: plugins/TorrentCreator/torrentcreator.glade:236
|
||||||
msgid "Add new torrent to queue"
|
msgid "Add new torrent to queue"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: plugins/TorrentCreator/torrentcreator.glade:257
|
#: plugins/TorrentCreator/torrentcreator.glade:255
|
||||||
msgid "<b>Torrent File</b>"
|
msgid "<b>Torrent File</b>"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: plugins/TorrentCreator/torrentcreator.glade:305
|
#: plugins/TorrentCreator/torrentcreator.glade:302
|
||||||
msgid "<b>Trackers</b>"
|
msgid "<b>Trackers</b>"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: plugins/TorrentCreator/torrentcreator.glade:352
|
#: plugins/TorrentCreator/torrentcreator.glade:348
|
||||||
msgid "<b>Comments</b>"
|
msgid "<b>Comments</b>"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: plugins/TorrentCreator/torrentcreator.glade:389
|
#: plugins/TorrentCreator/torrentcreator.glade:384
|
||||||
msgid "<b>Author</b>"
|
msgid "<b>Author</b>"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: plugins/TorrentCreator/torrentcreator.glade:425
|
#: plugins/TorrentCreator/torrentcreator.glade:423
|
||||||
msgid "Set Private Flag"
|
msgid "Set Private Flag"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: plugins/TorrentCreator/torrentcreator.glade:441
|
#: plugins/TorrentCreator/torrentcreator.glade:436
|
||||||
#: plugins/TorrentCreator/torrentcreator.glade:461
|
#: plugins/TorrentCreator/torrentcreator.glade:457
|
||||||
msgid ""
|
msgid ""
|
||||||
"The smaller the piece sizes, the more efficient the transfers will be, but "
|
"The smaller the piece sizes, the more efficient the transfers will be, but "
|
||||||
"the actual \".torrent\" file will be larger"
|
"the actual \".torrent\" file will be larger"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: plugins/TorrentCreator/torrentcreator.glade:442
|
#: plugins/TorrentCreator/torrentcreator.glade:437
|
||||||
msgid ""
|
msgid ""
|
||||||
"32 KiB\n"
|
"32 KiB\n"
|
||||||
"64 KiB\n"
|
"64 KiB\n"
|
||||||
|
@ -1457,13 +1462,14 @@ msgid ""
|
||||||
"256 KiB\n"
|
"256 KiB\n"
|
||||||
"512 KiB\n"
|
"512 KiB\n"
|
||||||
"1024 KiB\n"
|
"1024 KiB\n"
|
||||||
|
"2048 KiB\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: plugins/TorrentCreator/torrentcreator.glade:463
|
#: plugins/TorrentCreator/torrentcreator.glade:459
|
||||||
msgid "Piece Size:"
|
msgid "Piece Size:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: plugins/TorrentCreator/torrentcreator.glade:477
|
#: plugins/TorrentCreator/torrentcreator.glade:473
|
||||||
msgid "<b>Advanced</b>"
|
msgid "<b>Advanced</b>"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -2102,3 +2108,171 @@ msgid ""
|
||||||
"When set to -1 (unlimited), the global limits in Deluge's preferences will "
|
"When set to -1 (unlimited), the global limits in Deluge's preferences will "
|
||||||
"be obeyed."
|
"be obeyed."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/WebUi/__init__.py:31
|
||||||
|
msgid "Web User Interface"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/WebUi/__init__.py:34
|
||||||
|
msgid ""
|
||||||
|
"A Web based User Interface\n"
|
||||||
|
"\n"
|
||||||
|
"Firefox greasemonkey script: http://userscripts.org/scripts/show/12639\n"
|
||||||
|
"\n"
|
||||||
|
"Remotely add a file: \"curl -F torrent=@./test1.torrent -F pwd=deluge http://"
|
||||||
|
"localhost:8112/remote/torrent/add\"\n"
|
||||||
|
"\n"
|
||||||
|
"There is support for multiple templates, but just one is included.\n"
|
||||||
|
"\n"
|
||||||
|
"Other contributors:\n"
|
||||||
|
"*somedude : template enhancements.\n"
|
||||||
|
"*markybob : stability : synced with his changes in deluge-svn.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/WebUi/__init__.py:179
|
||||||
|
msgid "WebUi Config"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/WebUi/__init__.py:187
|
||||||
|
msgid "Port Number"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/WebUi/__init__.py:188
|
||||||
|
msgid "New Password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/WebUi/__init__.py:189
|
||||||
|
msgid "New Password(confirm)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/WebUi/__init__.py:190
|
||||||
|
msgid "Template"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/WebUi/__init__.py:191
|
||||||
|
msgid "Button Style"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/WebUi/__init__.py:193
|
||||||
|
msgid "Cache Templates"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/WebUi/__init__.py:209
|
||||||
|
msgid "Text and image"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/WebUi/__init__.py:209
|
||||||
|
msgid "Image Only"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/WebUi/__init__.py:209
|
||||||
|
msgid "Text Only"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/WebUi/__init__.py:243
|
||||||
|
msgid "Confirmed Password <> New Password\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/WebUi/webserver_common.py:48
|
||||||
|
msgid "translate something"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/WebUi/deluge_webserver.py:142
|
||||||
|
msgid "Choose an url or a torrent, not both."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/WebUi/deluge_webserver.py:153
|
||||||
|
msgid "no data."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/WebUi/deluge_webserver.py:230
|
||||||
|
msgid "refresh must be > 0"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/WebUi/deluge_webserver.py:238
|
||||||
|
msgid "Download Speed Limit"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/WebUi/deluge_webserver.py:242
|
||||||
|
msgid "Upload Speed Limit"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/WebUi/scripts/template_strings.py:1
|
||||||
|
msgid "# Of Files"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/WebUi/scripts/template_strings.py:2
|
||||||
|
msgid "About"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/WebUi/scripts/template_strings.py:3
|
||||||
|
msgid "Auto refresh:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/WebUi/scripts/template_strings.py:5
|
||||||
|
msgid "Debug:Data Dump"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/WebUi/scripts/template_strings.py:7
|
||||||
|
msgid "Delete downloaded files."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/WebUi/scripts/template_strings.py:9
|
||||||
|
msgid "Downloaded"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/WebUi/scripts/template_strings.py:11
|
||||||
|
msgid "Next Announce"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/WebUi/scripts/template_strings.py:12
|
||||||
|
msgid "Off"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/WebUi/scripts/template_strings.py:14
|
||||||
|
msgid "Password is invalid,try again"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/WebUi/scripts/template_strings.py:16
|
||||||
|
msgid "Pieces"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/WebUi/scripts/template_strings.py:17
|
||||||
|
msgid "Refresh page every:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/WebUi/scripts/template_strings.py:20
|
||||||
|
msgid "Set"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/WebUi/scripts/template_strings.py:23
|
||||||
|
msgid "Submit"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/WebUi/scripts/template_strings.py:24
|
||||||
|
msgid "Total Size"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/WebUi/scripts/template_strings.py:25
|
||||||
|
msgid "Tracker"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/WebUi/scripts/template_strings.py:26
|
||||||
|
msgid "Tracker Status"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/WebUi/scripts/template_strings.py:27
|
||||||
|
msgid "Upload torrent"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/WebUi/scripts/template_strings.py:28
|
||||||
|
msgid "Uploaded"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/WebUi/scripts/template_strings.py:29
|
||||||
|
msgid "Url"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/WebUi/scripts/template_strings.py:30
|
||||||
|
msgid "seconds"
|
||||||
|
msgstr ""
|
||||||
|
|
2
setup.py
2
setup.py
|
@ -28,7 +28,7 @@
|
||||||
|
|
||||||
NAME = "deluge"
|
NAME = "deluge"
|
||||||
FULLNAME = "Deluge BitTorrent Client"
|
FULLNAME = "Deluge BitTorrent Client"
|
||||||
VERSION = "0.5.5.95"
|
VERSION = "0.5.6.1"
|
||||||
AUTHOR = "Zach Tibbitts, Alon Zakai, Marcos Pinto, Andrew Resch, Alex Dedul"
|
AUTHOR = "Zach Tibbitts, Alon Zakai, Marcos Pinto, Andrew Resch, Alex Dedul"
|
||||||
EMAIL = "zach@collegegeek.org, kripkensteiner@gmail.com, marcospinto@dipconsultants.com, alonzakai@gmail.com, rotmer@gmail.com"
|
EMAIL = "zach@collegegeek.org, kripkensteiner@gmail.com, marcospinto@dipconsultants.com, alonzakai@gmail.com, rotmer@gmail.com"
|
||||||
DESCRIPTION = "A bittorrent client written in PyGTK"
|
DESCRIPTION = "A bittorrent client written in PyGTK"
|
||||||
|
|
|
@ -32,7 +32,7 @@ import os
|
||||||
import xdg.BaseDirectory
|
import xdg.BaseDirectory
|
||||||
|
|
||||||
PROGRAM_NAME = "Deluge"
|
PROGRAM_NAME = "Deluge"
|
||||||
PROGRAM_VERSION = "0.5.5.95"
|
PROGRAM_VERSION = "0.5.6.1"
|
||||||
|
|
||||||
CLIENT_CODE = "DE"
|
CLIENT_CODE = "DE"
|
||||||
CLIENT_VERSION = "".join(PROGRAM_VERSION.split('.'))+"0"*(4 - len(PROGRAM_VERSION.split('.')))
|
CLIENT_VERSION = "".join(PROGRAM_VERSION.split('.'))+"0"*(4 - len(PROGRAM_VERSION.split('.')))
|
||||||
|
|
|
@ -646,7 +646,6 @@ static PyObject *torrent_set_max_connections_global(PyObject *self, PyObject *ar
|
||||||
|
|
||||||
// printf("Setting max connections: %d\r\n", max_conn);
|
// printf("Setting max connections: %d\r\n", max_conn);
|
||||||
M_ses->set_max_connections(max_conn);
|
M_ses->set_max_connections(max_conn);
|
||||||
|
|
||||||
Py_INCREF(Py_None); return Py_None;
|
Py_INCREF(Py_None); return Py_None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1217,11 +1216,12 @@ static PyObject *torrent_get_session_info(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
session_status s = M_ses->status();
|
session_status s = M_ses->status();
|
||||||
|
|
||||||
return Py_BuildValue("{s:l,s:f,s:f,s:l,s:f,s:f}",
|
return Py_BuildValue("{s:l,s:f,s:f,s:ls:l,s:f,s:f}",
|
||||||
"has_incoming_connections", long(s.has_incoming_connections),
|
"has_incoming_connections", long(s.has_incoming_connections),
|
||||||
"upload_rate", float(s.payload_upload_rate),
|
"upload_rate", float(s.payload_upload_rate),
|
||||||
"download_rate", float(s.payload_download_rate),
|
"download_rate", float(s.payload_download_rate),
|
||||||
"num_peers", long(s.num_peers),
|
"num_peers", long(s.num_peers),
|
||||||
|
"num_connections", long(M_ses->num_connections()),
|
||||||
"total_downloaded", float(s.total_payload_download),
|
"total_downloaded", float(s.total_payload_download),
|
||||||
"total_uploaded", float(s.total_payload_upload));
|
"total_uploaded", float(s.total_payload_upload));
|
||||||
}
|
}
|
||||||
|
@ -1778,8 +1778,7 @@ static PyObject *torrent_replace_trackers(PyObject *self, PyObject *args)
|
||||||
if (PyErr_Occurred())
|
if (PyErr_Occurred())
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
torrent_handle& h = M_torrents->at(index).handle;
|
if (M_torrents->at(index).handle.is_valid()){
|
||||||
if (h.is_valid()){
|
|
||||||
std::vector<libtorrent::announce_entry> trackerlist;
|
std::vector<libtorrent::announce_entry> trackerlist;
|
||||||
std::istringstream trackers(tracker);
|
std::istringstream trackers(tracker);
|
||||||
std::string line;
|
std::string line;
|
||||||
|
@ -1787,8 +1786,8 @@ static PyObject *torrent_replace_trackers(PyObject *self, PyObject *args)
|
||||||
libtorrent::announce_entry a_entry(line);
|
libtorrent::announce_entry a_entry(line);
|
||||||
trackerlist.push_back(a_entry);
|
trackerlist.push_back(a_entry);
|
||||||
}
|
}
|
||||||
h.replace_trackers(trackerlist);
|
M_torrents->at(index).handle.replace_trackers(trackerlist);
|
||||||
h.force_reannounce();
|
M_torrents->at(index).handle.force_reannounce();
|
||||||
}
|
}
|
||||||
Py_INCREF(Py_None); return Py_None;
|
Py_INCREF(Py_None); return Py_None;
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,8 @@ import gtk
|
||||||
|
|
||||||
def cell_data_speed(column, cell, model, iter, data):
|
def cell_data_speed(column, cell, model, iter, data):
|
||||||
speed = int(model.get_value(iter, data))
|
speed = int(model.get_value(iter, data))
|
||||||
speed_str = common.fspeed(speed)
|
if speed<100: speed_str = ""
|
||||||
|
else: speed_str = common.fspeed(speed)
|
||||||
cell.set_property('text', speed_str)
|
cell.set_property('text', speed_str)
|
||||||
|
|
||||||
def cell_data_size(column, cell, model, iter, data):
|
def cell_data_size(column, cell, model, iter, data):
|
||||||
|
|
|
@ -428,6 +428,8 @@ def show_about_dialog(window):
|
||||||
abt.set_transient_for(window)
|
abt.set_transient_for(window)
|
||||||
abt.set_name(common.PROGRAM_NAME)
|
abt.set_name(common.PROGRAM_NAME)
|
||||||
abt.set_version(common.PROGRAM_VERSION)
|
abt.set_version(common.PROGRAM_VERSION)
|
||||||
|
abt.set_comments("Deluge is a full-featured BitTorrent\nclient for Linux, Mac OS X and Windows")
|
||||||
|
abt.set_documenters(["Marcos Pinto"])
|
||||||
abt.set_authors(["Zach Tibbitts", "Alon Zakai", "Marcos Pinto", "Andrew Resch", "Alex Dedul"])
|
abt.set_authors(["Zach Tibbitts", "Alon Zakai", "Marcos Pinto", "Andrew Resch", "Alex Dedul"])
|
||||||
abt.set_artists(["Andrew Wedderburn"])
|
abt.set_artists(["Andrew Wedderburn"])
|
||||||
abt.set_translator_credits(_("translator-credits"))
|
abt.set_translator_credits(_("translator-credits"))
|
||||||
|
|
|
@ -947,11 +947,17 @@ window, please enter your password"))
|
||||||
unique_id = self.manager.get_torrent_unique_id(torrent)
|
unique_id = self.manager.get_torrent_unique_id(torrent)
|
||||||
try:
|
try:
|
||||||
if self.manager.unique_IDs[unique_id].trackers:
|
if self.manager.unique_IDs[unique_id].trackers:
|
||||||
self.manager.replace_trackers(unique_id, \
|
try:
|
||||||
|
self.manager.replace_trackers(unique_id, \
|
||||||
self.manager.unique_IDs[unique_id].trackers)
|
self.manager.unique_IDs[unique_id].trackers)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
if self.manager.unique_IDs[unique_id].uploaded_memory:
|
if self.manager.unique_IDs[unique_id].uploaded_memory:
|
||||||
self.manager.unique_IDs[unique_id].initial_uploaded_memory \
|
try:
|
||||||
|
self.manager.unique_IDs[unique_id].initial_uploaded_memory \
|
||||||
= self.manager.unique_IDs[unique_id].uploaded_memory
|
= self.manager.unique_IDs[unique_id].uploaded_memory
|
||||||
|
except:
|
||||||
|
pass
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -1091,7 +1097,7 @@ window, please enter your password"))
|
||||||
def update_statusbar_and_tray(self):
|
def update_statusbar_and_tray(self):
|
||||||
plugin_messages = self.plugins.get_plugin_tray_messages()
|
plugin_messages = self.plugins.get_plugin_tray_messages()
|
||||||
core_state = self.manager.get_state()
|
core_state = self.manager.get_state()
|
||||||
connections = core_state['num_peers']
|
connections = core_state['num_connections']
|
||||||
if self.config.get("max_connections_global") < 0 :
|
if self.config.get("max_connections_global") < 0 :
|
||||||
max_connections = _("Unlimited")
|
max_connections = _("Unlimited")
|
||||||
else:
|
else:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue