Compare commits

...

863 Commits

Author SHA1 Message Date
9bec5142c7 Update Changelog and bump version to 1.3.14
- Minify js files
2017-03-06 09:56:20 +00:00
0f1f62ec62 Update translation files 2017-03-06 09:53:07 +00:00
318ab17986 [WebUI] Only accept application/json content-type requests
- Protects against CSRF (Cross-site request forgery)
2017-03-01 14:35:49 +00:00
25150f13af [Core] Catch None type country in get_peers 2017-02-23 19:18:01 +00:00
7cde3efb94 [#2976] [Console] Fix help showing usage details 2017-02-22 23:28:27 +00:00
7f01dc909e [#2879] [OSX] Fix dyld error opening file from within Deluge
- Using DYLD_LIBRARY_PATH seems to have the unintended effect of making associated apps
   unusable (unable to locate dylds) when opening a file from within Deluge. The workaround
   for now is to switch to using DYLD_FALLBACK_LIBRARY_PATH.
2017-02-22 11:24:45 +00:00
10ebf9b0b0 Fix mistakes in commit 42ba908
commit accidentally pushed before being tested
2017-02-21 10:36:04 +00:00
3ba5443c76 [#2826] Fix create_torrent filedump not encoded 2017-02-20 22:40:14 +00:00
c39f00fa0b [WebUI] Log successful logins with associated ip 2017-02-20 18:47:25 +00:00
3962c41a55 [Core] Switch move_storage flag to dont_replace 2017-02-20 18:47:25 +00:00
42ba9086d0 [#2956] Fix empty file_priorities with magnets 2017-02-20 16:25:08 +00:00
2d4dec669e [AutoAdd] Remove duplicate magnet extension when splitting 2017-02-20 13:22:47 +00:00
bcf0fe4a61 [#2957] [GTKUI] Fix AttributeError in torrentview column sort 2017-02-20 10:02:54 +00:00
1dc4c465c7 [#2964] Fix TypeError when checking auth level in RPC Server
- self.factory.authorized_sessions requires tuple of (int, string).
2017-02-20 09:44:32 +00:00
b52de1549e [Core] Fix adding magnet with trailing newline
* A bug in libtorrent means that a magnet with a trailing newline will be added
   but with an invalid info_hash. Strip any whitespace before add is a workaround.
2017-02-15 23:33:28 +00:00
8a3f15e5c0 [Autoadd] Fixes for splitting magnets from file
* use splitlines to remove line endings so filter with len works as intended.
 * use a short form of the magnet hash so the resulting filename will be unique
   and prevent potential overwriting of other files.
 * verify magnet is valid
2017-02-14 18:37:20 +00:00
8565eccb3d [#2149] [Core] Fix for overwriting single proxy in lt>=0.16 2017-01-30 10:36:33 +00:00
30eaf775c2 [#2948] [Console] Fix decode error comparing non-ascii (str) torrent name 2017-01-18 11:11:00 +00:00
ffb1316f09 [#2861] [Core] Add support for python-geoip 2017-01-17 09:28:46 +00:00
bd80ad62a0 [Core] Fix return type in t.get_file_progress 2017-01-17 09:20:11 +00:00
78851becf2 [#2946] Workaround 1.1 libtorrent default piece priority
* The default piece priority was changed in lt 1.1 from 1 to 4
   so in 1.3 we will simple convert them back to 1 as 4 is not used.
 * The set_file_priorities method was refactored to make the changes simpler.
2017-01-17 09:20:11 +00:00
af76abb038 [UI] Fix usage of 'with Image.open' in trackericons
* Revert changes made to fix 'too many files open' as Image.open does
   not return a file descriptor and generated the following error:
     exceptions.AttributeError: 'NoneType' object has no attribute 'startswith'
 * Also fix style for raising an exception.
2017-01-11 22:56:05 +00:00
bf01b53bda [WebUI] Fix missing self.interface attribute for 8a48ec012 2017-01-11 13:00:28 +00:00
8a48ec0126 [#2951] [#1908] [WebUI] Add bind interface option for server 2017-01-10 20:20:44 +00:00
c3a02e5291 [#2888] [WebUI] Fix shift-click in FilesTab 2017-01-10 17:30:35 +00:00
3c1995476d [#2953] Fix except variable typo 2017-01-09 17:55:52 +00:00
48cedf635f [GTKUI] [WEBUI] Add tracker_status translation to UIs 2016-11-30 13:29:33 +00:00
0b4627be8a [#2941] Remove tracker_status translation markup from core
* A UnicodeDecodeError can occur if creating a string using translated
   text but we should not be translating anything in core anyway so
   remove the markup and do the translating in UI.
2016-11-30 13:29:33 +00:00
739537f860 [#2942] Catch file_progress IndexError when checking a torrent 2016-11-30 11:54:59 +00:00
df88c82265 [#2784] Fix typo in bugfix 5f92810f 2016-11-01 11:59:52 +00:00
5394ac5604 [#2875][Web] Fix: WebUI Json dumps Error
* A torrent file contains an uncommon field 'filehash' which must be hex encoded
   to allow dumping the torrent info to json. Otherwise it will fail with:
   UnicodeDecodeError: 'utf8' codec can't decode byte 0xe5 in position 0: invalid continuation byte
2016-10-19 11:58:03 +01:00
f739269dfd [GTKUI] Autofill infohash entry from clipboard 2016-10-18 19:20:47 +01:00
f57ee74ee2 [#2901] [GTKUI] Strip whitespace from infohash entry before checks
* Copy-pasting from web page can include extra space at end of string.
 * Also make minor change to populate the magnet name with infohash
   for nicer UI display.
2016-10-18 19:14:51 +01:00
798f5e2deb [#2889] Fix for UnboundLocalError in exception handler 2016-10-17 12:49:22 +01:00
a7fe4d4510 [#2889] Fixes for 'Too many files open' error
* Ensure all file descriptors are closed. Using the with statement ensures
   closure and adding 'from __future__ ...' for Python 2.5 compatibility.
 * The main problem was with thousands of unclosed file desciptors from
   tracker_icons mkstemp.
 * Use a prefix 'deluge_ticon.' to identify created tracker_icon tmp files.
2016-10-17 12:46:28 +01:00
6c73105a73 [#2882] [Core] Nicer log message about missing GeoIP support in lt 1.1.1 2016-09-28 10:36:06 +01:00
e66be42c81 [#2768] [GTKUI] [OSX] Fix invalid file error at startup
When installed to the system, not using .app, error is raised on startup
as nsapp_open_file is ignoring Deluge-bin but not deluge or deluge-gtk for
potential 'filename' when connecting NSApplicationOpenFile.
2016-07-20 20:31:40 +01:00
2263463114 Bump version to 1.3.13 and update dates 2016-07-20 15:23:28 +01:00
454c7be364 Revert "[#2852] Set maximum supported libtorrent version to 1.0.x"
This reverts commit 852b51f224.

Changes applied for libtorrent 1.1.1 release should bring back
backward compatibility for Deluge 1.3.
2016-07-19 20:06:27 +01:00
85fdacc0e7 [Changelog] Update with recent changes 2016-07-19 17:38:15 +01:00
869dbab459 [WebUI] Compress javascript files 2016-07-19 17:37:43 +01:00
852b51f224 [#2852] Set maximum supported libtorrent version to 1.0.x 2016-07-19 15:20:38 +01:00
492ad07965 [#2293] [WebUI] Fix plugins not loading when using WebUI plugin
- Any plugins that were started before the WebUI plugin would not be loaded
   upon starting the web server and would be not show up. The fix is to use
   web.pluginmanager.start to get all enabled plugins from core.
 - Update log message output for enable/disable in pluginmanager.
 - Deregister plugin events on json_api disable.
2016-07-19 15:04:50 +01:00
904a51835b [#2857] [Notification] Fix issues with SMTP port input 2016-07-19 12:56:33 +01:00
d38b8fc45c [#2855] [WebUI] Unable to add UDP trackers 2016-07-19 11:50:26 +01:00
5f92810f76 [#2784] [Execute] Escape ampersand in args for Windows
Due to the nature of passing a command and args to cmd.exe and then
to a batch file in Windows any ampersands in execute args need to be
double-escaped so prefixing with tripe-caret (^^^&) is the fix for this.
2016-06-29 23:25:30 +01:00
34e12fcb38 [Translations] Update po's, pot and gettext.js 2016-06-19 12:30:30 +01:00
f769afd3ac [WebUI] Compress javascript 2016-06-19 12:30:29 +01:00
e1d78c3de6 [Changelog] Add recent changes 2016-06-19 12:30:05 +01:00
15a4023208 [#2077] [Extractor] Ignore the remaining rar part files
* Bump version to 0.6
2016-06-10 16:14:52 +01:00
cbb7415a18 [#2785] [Extractor] Fix successful claimed extract leaving empty folder
* The main fix here is adding os.environ to the command call otherwise in some configurations
   the extraction would fail. Was unable to reproduce locally but users confirm this fix works.
 * Refactored the code to properly report errors if the extract command fails and the
   actual command output.
 * Bump version to 0.5.
2016-06-10 16:00:23 +01:00
1a11e085b2 [#2828] [Packaging] Fix ImportError with setuptools version > 18.8 2016-05-19 17:23:07 +01:00
fcb65940d9 [AutoAdd] Fix watch dir not accepting uppercase file extension
- Auto-add feature will now accept torrents when the .torrent extension
   has capital letters in it
2016-05-12 19:19:39 +01:00
aa10e084a4 [Scheduler] Bump to version 0.3 2016-05-12 11:41:00 +01:00
b2be4aba53 [#2796] [Console] Add time_added to info sort keys 2016-05-10 14:17:37 +01:00
a1e66a4dc1 [#2815] [Console] Fix 'add' cmd path inconsistency on windows
- When adding a torrent with a download location from command prompt
on Windows the slashes were not being normalised resulting in path errors.
2016-05-10 13:00:02 +01:00
6240243251 [#2795] [GTKUI] Reduce height of Add Torrent Dialog
- Reduced height from 575px to 480px
 - Low resolution screen users (600px high) will be unable to click
the add button with a dialog height of >550px. Keeping the height
to less than 500px leaves more room for large size themes.
2016-05-10 12:45:25 +01:00
ad58fca1f9 [#2790] Ensure base32 magnet hash is uppercase 2016-05-09 23:24:59 +01:00
f221ae53eb [#2832] [UI] Skip blank lines in auth file 2016-05-09 16:40:02 +01:00
5590c31ace [Daemon] Fix unable to use uppercase log level 2016-04-27 08:20:58 +01:00
4e5754b285 [Core] Fix UnboundLocalError in torrentmanager 2016-04-07 11:00:16 +01:00
90a22af5e5 Add command-line option for the daemon to restrict some config keys to being read-only.
This only affects the core.set_config() RPC method which will drop items if the key
is listed as read-only.
2016-02-02 19:02:28 -08:00
77f8449c0c [#2767] [Packaging] Don't include .py files in OSX App 2015-12-11 18:50:49 +00:00
be7ad16a3f [#2783] [GTKUI] Case insensitive sort for name column 2015-12-11 18:02:10 +00:00
e28954f63e Update Changelog 2015-12-11 14:27:11 +00:00
52e60ac5b0 [#2782] [WebUI] Fix HTTPS negotiating incorrect cipher 2015-12-11 11:53:52 +00:00
6ffe5cd2a4 [Core] Improve logging in update_state 2015-12-11 11:52:59 +00:00
9038357d78 [OSX] Fix starting deluged from connection manager 2015-12-10 21:31:37 +00:00
d56f6cb4f1 [Core] Increase RSA key size 2015-12-10 09:47:41 +00:00
5d301a4b33 [Core] Fix move_storage exception handling 2015-12-09 19:02:18 +00:00
e65a7ff2ea [GTKUI] Only save_state when mainwindow is visible
* A similar fix (550ddc01) was applied to develop so backporting to guard
   against similar problems with columns not saving properly.
2015-11-30 23:41:51 +00:00
1bdc99ded7 [GTKUI] Fix installing plugin from non-ascii path 2015-11-27 13:41:06 +00:00
dd34492e16 [Core] Update tracker_host when setting new tracker status
* Fixes the tracker_host not updating when a tracker announce
   is received from a different tracker and sets the tracker status.
2015-11-27 12:03:55 +00:00
9f3b2f3167 [#2093] Backport win32_unicode_argv from develop
* Also includes fix for drag'n'drop non-ascii filepaths by decoding after urlparse.
2015-11-26 13:46:04 +00:00
0260e34189 [#2485] [WebUI] Fix unconnected Options in context menu 2015-11-23 23:20:45 +00:00
5464cf674a [#2777] Update MSVC SP1 check to latest release CLID 2015-11-15 18:43:04 +00:00
a58ce30e7b [#2738] [Core] Fix illegal argument with torrent_handle.set_max_connections 2015-11-15 14:17:00 +00:00
83cecc0c09 [Core] Put back translation markup for tracker error 2015-11-05 22:59:17 +00:00
00757af149 [Core] Empty error message fix with certain trackers
By design alert.msg will be empty if the error code is '-1' so use
a.e.message() to get the message as fallback. It was not used at
replacement because when error code is not '-1' then a.e.message()
will also include the error code, which we do not want.
2015-11-05 22:23:35 +00:00
639eefcf1d [Core] Supress warnings with fresh config
* Test TMState has torrents before attempting old state update.
 * Only warn about missing fastresume if torrents in session.
2015-10-28 15:35:36 +00:00
69a1f5f210 [GTKUI] Don't display percentage for Error'd torrents 2015-10-28 15:35:36 +00:00
0a74812eeb [Console] Fix adding non-ascii torrent in non-interactive mode 2015-10-28 15:35:35 +00:00
cf437b6a33 [Core] Add handle.clear_error to resume 2015-10-28 15:35:35 +00:00
0ab7ebd017 [#1032] [Core] Force a torrent error if resume data is rejected
* Add two new methods, force_error_state and clear_forced_error_state.
 * Force error state upon rejected resume data.
 * Keep original resume data in forced_error state.
2015-10-28 15:35:35 +00:00
34e92b9f12 [Core] Add fastresume rejected alert handler 2015-10-20 15:32:15 +01:00
86b1b75fb8 [#2772] [GTKUI] Fix GtkWarning with unknown pango markup 2015-10-18 18:47:32 +01:00
4b9dcf377c [Core] Fix Twisted AlreadyCalled error on shutdown 2015-10-07 00:18:40 +01:00
560318a5a7 [#2703] [Core] Stop moving files if target files exist 2015-09-29 23:18:04 +01:00
244ae878c9 [Core] Fix placement of self.state in torrent.py
* Need to be created earlier as set_options calls update_state
2015-09-29 23:17:46 +01:00
f9b7892976 [Core] Reset trackers in force_recheck only if paused 2015-09-29 19:05:50 +01:00
5f5b6fad0b Fix indention error in move_storage 2015-09-29 18:51:52 +01:00
5c545c5e0b [Core] Fix torrent displaying wrong state 2015-09-29 18:44:52 +01:00
20088a5c70 [Core] Workaround unwanted tracker announce when force rechecking paused torrent
* This workaround updates the stored torrent.trackers, sets empty handle.trackers then
   resets trackers after pausing.
2015-09-29 18:43:11 +01:00
099a4eb8c6 [#2753] [GTKUI] Fix 'Added' column showing wrong date
* Unsure why added_time would be zero but only set the date if it is a postive value.
2015-09-28 13:17:13 +01:00
ad7e519fb2 [Core] Minor correction to session resume 2015-09-28 12:37:15 +01:00
df57c7f924 [#2729] [Blocklist] Fix plugin lockup with empty url 2015-09-28 11:56:32 +01:00
7315255831 [#1330] [Core] Fix pausing and resuming session
* The paused state of torrents is now correctly stored on shutdown if the session is paused.
 * core.pause_all_torrents now uses libtorrent session.pause and resume_all_torrents also refreshes
   all torrents' state. This fixes only torrents that changed state being updated so queued torrents
   would be incorrectly displayed as paused.
 * Scheduler and Blocklist now use updated core methods rather than calling libtorrent directly.
2015-09-28 11:53:27 +01:00
eab7850ed6 [Core] Return all plugin status keys with empty list 2015-09-28 11:30:33 +01:00
542e028977 [#2236] [Core] Fix filter keyerror removing plugin 2015-09-26 12:58:52 +01:00
f131194b75 [GTKUI] [OSX] Fix empty scrolling status (systray) menu
* Same issue as seen on Windows in #302
2015-09-25 23:58:32 +01:00
d7e6afb01e [#2435] [GTKUI] Prevent user changing selection when editing tracker 2015-09-25 17:45:59 +01:00
e1dcf378c3 [#2705] [WebUI] Fix hostlist not being created 2015-09-25 13:56:39 +01:00
697c22a46c [#2765] Add support for TLS SNI in httpdownloader 2015-09-25 13:56:39 +01:00
7ca704be72 [GTKUI] Fix connected issue in connection manager
* If host was not an ip address then it would not show as connected
2015-09-25 13:56:00 +01:00
72d381a3b6 Fix data_files check in setup.py 2015-09-20 18:41:24 +01:00
59c2520e0d [Packaging] Revert unintended changes to osx scripts 2015-09-20 15:48:03 +01:00
58d385241f [#2762] [GTKUI] Use correct column types for data 2015-09-20 15:39:04 +01:00
58059300bd [#2763] [GTKUI] Fix unhandled error with invalid magnet uri 2015-09-20 15:19:57 +01:00
e4f2a450d6 [#2764] [Scheduler] Fix corrupt plugin prefs page on osx 2015-09-20 14:59:33 +01:00
64bba77807 [Packaging] Minor osx updates 2015-09-20 01:50:05 +01:00
a13b4270b5 [Packaging] Updates to the NSIS Installer script
* New message box popup if VC 2008 Redist package not detected.
 * Add Start Menu page to choose where/if to install items.
 * Add desktop shortcut install option to finish page.
 * Clean up spacing and use consistent 4 spaces to indent.
 * Exclude as many unneeded pygame libraries as possible.
2015-09-18 22:47:06 +01:00
52c8fde461 [Packaging] Updates to osx scripts
* bundle_contents now appends 'Contents' without adding it twice.
 * Remove reference to non-existent gdk-pixbuf.loaders
 * Separate libtorrent in new module.
 * Update lib versions for bundle file.
2015-09-18 22:47:05 +01:00
0a01aa28b0 [#2402] [Notification] Fix popup to show actual count of files finished 2015-09-18 22:44:58 +01:00
bfb202086d [#2754] [GTKUI] Fix Deluge isn't sorting torrents properly 2015-09-17 22:26:24 +01:00
6032c25813 [#2696] [GTKUI] Fix incorrect destination folder shown in GTK UI 2015-09-17 11:28:56 +02:00
6cbb2fa5e1 [GTKUI] Remove deprecated 'has_separator' from glade files
* Deprecated since GTK 2.22 and defaults to False.
2015-09-16 15:31:46 +01:00
cdf301601f [Scheduler] Revert erroneous fix backported from develop branch
* The issue this was intended to fix only occurs on develop branch
2015-09-16 15:20:03 +01:00
1b974d1061 [Win32] Fix icon path and output exes in bbfreeze 2015-09-13 22:47:31 +01:00
602a913fa3 Bump version to 1.3.12 2015-09-13 21:32:11 +01:00
6a8f24e973 Fix icon paths in setup 2015-09-13 21:32:10 +01:00
fde46885e9 Update Translation files 2015-09-12 11:56:27 +01:00
7223a51ba5 [WebUI] Lint and minify 2015-09-12 11:35:50 +01:00
8ac65d77e0 Update ChangeLog 2015-09-10 15:01:52 +01:00
65ebcf5384 [#2325] [Packaging] Fix uninstaller deleting non-deluge files 2015-09-10 14:43:32 +01:00
53caeb4565 [Packaging] bbfreeze updates
* No need for data_files to be installed on windows
2015-09-10 14:39:25 +01:00
3b1cb0f58e [Scheduler] Show current speed limit in statusbar
* Intercepts the updates of the statusbar and displays plugin values when in Yellow zone.
 * Core fix for resetting speed limits to core.conf values.
2015-09-07 11:32:09 +01:00
41ac46c7fe [Core] Backport atomic fastresume and state file saving fixes
* On Windows using shutil.move is not atomic and could account for corruption on power loss.
 * Using file saving code from develop branch including latest changes:
	7414737cbf
2015-09-07 11:25:31 +01:00
8e3d737adc [#2731] [GTKUI] Fix potential AttributeError in is_on_active_workspace
* Without being able to replicate adding the forced updated is the likely fix for 'win'
being None but also add test in case it's not...
2015-09-01 16:27:57 +01:00
7ef9e3dbe0 Check for private flag on duplicate added torrent 2015-08-31 00:47:19 +01:00
78fcf1781a [#2333] [Console] Fix 'set and then get' in config command
* The get method was returning old config information so use correct
 core get callback.
 * Remove redundant deferred in set method
2015-08-28 17:19:40 +01:00
2b08ed06af [Core] Enable lt extension bindings again for versions >=0.16.7
* This will also no longer enable the lt_trackers extensions that seems
to be an issue for private trackers mixing with public ones #2721.
2015-08-28 15:34:56 +01:00
0cdab04a64 [Packaging] bbfreeze tweaks and comments
* Reduce output from bbfreeze and add debug option to enable again.
2015-08-26 17:30:00 +01:00
84aca3c009 [Packaging] Fix typo in bbfreeze 2015-08-26 17:27:28 +01:00
9662ccf486 Use just Taiwan in countries list 2015-08-25 16:30:25 +01:00
83719e8404 [Win32] Updated bbreeze script from develop branch 2015-08-24 15:56:51 +01:00
04d90903a6 [#2758] [win32] Include _cffi_backend module in bbfreeze 2015-08-24 15:42:44 +01:00
f599b883cf [win32] Update packaging scripts
* Update directory paths.
2015-08-24 15:40:55 +01:00
bef71e60b3 [#2734] Add 256x256 to deluge.ico 2015-08-24 15:37:16 +01:00
acf4fc4193 [#2233] [lp:#1487704] Fix AttributeError in set_trackers with lt 1.0 2015-08-22 15:31:26 +01:00
123dd8f011 [WebUI] Fix i18n issue in Connection Manager
The status strings were incorrectly marked for translation which when combined with
some translations using 'connected' and 'online' as the same word resulted in
users being unabe to connect to running daemon.

 * Removed translation markup from json_api but left as original capitalised word in
case other third-party scripts do comparison on these status strings.
 * Added translation markup prior to displaying ConnectionManager using template.
 * Reworded password prompt and added translation markup.
 * Update gettext.js
2015-08-20 13:48:34 +01:00
0516e3df45 Update author name as per request 2015-08-17 23:05:34 +01:00
0c750084dc [#2295] [WebUI] Increased lifespan of display settings
Display settings for the WebUI are persisted using cookies created by
Ex.state.CookieProvider. When no expiration date is provided, a default
value of (now + 7 days) is used. This causes display settings to be
lost frequently.

This fix adds an 'expires' parameter with a value of (now + 10 years).
This change does not affect the lifespan of the session cookie, which
is created by a separate system.
2015-08-14 16:51:38 +01:00
907109b8bc Update man pages 2015-08-14 13:22:23 +01:00
630aa730d5 [#2730] Fix Deluge dev versions not starting
Change to use the VersionSplit class and fix code there.
2015-08-14 00:20:02 +01:00
16faa26124 [GTKUI] Improve About dialog copyright format for translators 2015-08-13 23:03:26 +01:00
ebabd20c98 Remove stray tab in label plugin text 2015-08-09 12:17:47 +01:00
d40dfcd53c Fix for Twisted 15.0 URI class rename 2015-02-23 12:39:40 +00:00
6ab951caee Bump version to 1.3.11
* Update changelog
 * Merge translations
 * Build js files
2014-11-30 21:53:46 +00:00
52e0993fa3 [#2676] Add pilow and appindicator to DEPENDS 2014-11-25 18:59:04 +00:00
d7bb5dfa8b [WebUI] Add missing column entries to Torrent Record 2014-11-20 21:46:16 +00:00
7c3d44c42e [#2588] [WebUI] Fix Size column to show total_wanted
* It is more useful to show total_wanted and now matches GTKUI column.
2014-11-20 21:43:33 +00:00
dd6e7ec490 [#2698] [GTKUI] Fix corrupted column indexes when using multiple col_types
* Ensures that removing multiple items from liststore_columns list does not affect the index.
2014-11-20 18:48:30 +00:00
2c1a863ffb [WebUI] Modify SSL Context to allow >=TLSv1 protocol
* The TLSv1_METHOD is a fixed protocol version so this change will allow higher versions to be used where possible.
2014-11-20 15:11:48 +00:00
40382002f6 [#2555] [Core] Disable use of SSLv3 for DelugeRPC 2014-11-20 15:06:59 +00:00
05b4cb5546 [GTKUI] Fix ImportError with ReactorAlreadyInstalledError
Older systems such as Ubuntu Lucid encountered this import error as Twisted versions < 10 don't
have the exception type ReactorAlreadyInstalledError.
2014-11-18 12:03:46 +00:00
75dca80ac4 [Core] Modify #1869 fix to only apply to lt <= 0.15
A fix was implemented in 0.16: https://code.google.com/p/libtorrent/issues/detail?id=406#c39
2014-11-18 11:17:45 +00:00
cc56764ee9 Bump version to 1.3.10 and update changelog 2014-10-15 22:10:39 +01:00
53f485d87e [#2256] [GTKUI] Indexes are not updated correctly when removing columns 2014-10-15 19:02:00 +01:00
f95cfb42c3 [GTKUI] Fix bug in the torrentview introduced by 5dba83
The speedup optimizations removed code that recreates the
model filter when a new column is added. This missing line
is only a problem when there plugins that add columns to the
GTKUI after initially loading the torrentlist.
2014-10-15 19:01:44 +01:00
26f5be1760 [WebUI] Security update for POODLE vulnerability
WebUI with HTTPS enabled is vulnerable to POODLE (CVE­-2014­-3566), so switch from
SSLv3 to TLSv1.
2014-10-15 18:44:11 +01:00
d3f47097c1 Update changelog and bump version to 1.3.9 2014-10-04 23:33:07 +01:00
7a2092d3c4 [#2514] [GTKUI] Every torrent is displayed twice in classic mode 2014-10-04 23:15:04 +01:00
3e632600c6 Bump version to 1.3.8 2014-10-04 11:15:52 +01:00
4df58b51ff Update copyright year in About dialog and po files 2014-10-04 10:53:29 +01:00
4fc8032c88 Update Changelog and translation files 2014-10-03 22:04:28 +01:00
5e1874eb8d Revert "[#1032] Keep track of torrent errors over restarts"
This reverts commit 2c54c696a1.

This is not working as I intended, will hopefully commit a revised version to 1.3-stable.
2014-10-03 15:26:50 +01:00
810391316c Fix previous commit's except statement for py2.5 2014-10-02 17:36:58 +01:00
47daef1e47 [#2335] [GTKUI] Fix startup failing with 'cannot acquire lock'
This issue was caused by an unclean shutdown of Deluge, usually on system shutdown, and upon rebooting
the PID stored in the lockfile is in used by another process thus the lockfile is never removed. It
affects users with Deluge set in startup applications as the PIDs are more likely to be reused.

 * Lockfile is removed if Deluge is restarted in IPC.
 * Renamed the old_tempfile variable to make it clearer as to it's role.
2014-10-02 17:15:02 +01:00
294ad9fae1 [Extractor] Add Finding Win 7z Path via Registry 2014-09-24 22:44:18 +01:00
f1fe593fd6 [#2497] [GTKUI] Fix the queue 'Clear' button not properly clearing. 2014-09-01 21:27:38 +01:00
c982e8de67 Revert "Fix #2221 : Addtorrentdialog KeyError accessing download_location"
This reverts commit 686fb31844.
2014-08-31 14:56:38 +01:00
33339b1dc6 [#2496] [GTKUI] Fix updating core_config before setting default options
* Remove duplicate entry in init.
 * Call update if empty config and prevent potential loop in update method.
 * Ensure that the queue Add button is sensitive, even when automatically adding.
2014-08-31 14:35:47 +01:00
ecf5af1e16 [GTKUI] Fix listview error with new config 2014-08-31 12:17:05 +01:00
4e77c46694 [#2493] [GTKUI] Fix TypeError if active workspace is None 2014-08-25 16:33:47 +01:00
3f8526160d [Notifications] Small layout fixes for web page and version bump 2014-08-19 16:30:02 +01:00
82fb3408ee [#1310] [Notifications] Add webui prefs page 2014-08-19 16:27:01 +01:00
223c9319c7 Fix firing of Finished event when moving 2014-08-16 22:50:02 +01:00
c61c2d8c3a Fix for Indicator icon label issue 2014-08-09 16:51:28 +01:00
8bdf1e9044 [LP:#1168858] Nautilus window opens behind current window 2014-08-09 00:47:09 +01:00
98dcc3f26e [GTKUI] Fix showing the open_folder menuitem 2014-08-09 00:17:43 +01:00
e2b0ceae1d [GTKUI] Suppress unimportant gnome warnings 2014-08-09 00:16:48 +01:00
5dba838533 [GTKUI] Optimized the updating of the torrent view
Instead of disabling sort, sort is not enabled until the list is
loaded for the first time.
2014-08-04 22:17:12 +01:00
54eb28a097 Backport decode_string from develop 2014-08-04 22:05:30 +01:00
4bd4c78969 [WebUI] Update from config upon showing plugin page 2014-08-04 21:59:47 +01:00
1990bdcb52 Bump version for updated plugins 2014-08-04 21:57:55 +01:00
70bf274974 [#2478] [Blocklist] Add WebUI plugin page 2014-08-04 21:57:55 +01:00
a4fb8e769b [#2470] [Console] Fix console parsing args
This negates the need for quoting a single command with an arg e.g.
    deluge-console del --remove_data torrrent_file

Multiple commands separated by semi-colon still require quoting.
2014-08-04 21:57:54 +01:00
56bbc90c5b [#1290] [Execute] Add TorrentRemoved event 2014-08-04 21:57:54 +01:00
2c54c696a1 [#1032] Keep track of torrent errors over restarts 2014-08-04 19:09:38 +01:00
ddde10ec99 [Extractor] Add webui page 2014-08-04 19:09:37 +01:00
fed5221503 [#1126] [#2322] Emit FinishedEvent after moving storage complete
Also changed the Execute and Extractor plugins to process the updated
FinishedEvent functionality.
2014-07-19 23:04:31 +01:00
c0650f88d1 Fix to mitigate fastresume corruption
The code in develop is more robust but by writing to a temp file first
then moving it should stop the worst of fastresume corruption issues,
e.g. hard resets.
2014-07-19 20:16:51 +01:00
5d5edd2639 [#2238] [Scheduler] Fix undefined this.scheduleCells 2014-07-13 23:08:07 +01:00
f77440efcb Bump version to 1.3.7 2014-07-09 20:08:22 +01:00
74aa924625 [WebUI] Update compressed js 2014-07-09 19:37:08 +01:00
0338fc6f2d Update ChangeLog 2014-07-09 19:35:31 +01:00
12118c5454 Update POT file 2014-07-09 19:22:49 +01:00
1bdb072ac8 Update translation po files from launchpad 2014-07-09 19:13:44 +01:00
ade26794ec [GTKUI] Fix text typo and mark for translation 2014-07-09 19:09:46 +01:00
8c4a08bb87 [#2418] Fix WebUI error when adding non-ascii torrent
json.dumps attempts to decode (utf8) the 'path' entry which had a
different encoding. The solution is to ensure the 'path' entry is
utf8 encoded and remove the unneeded 'path.utf-8' entry.

As self.__m_metadata["info"]["files"] is updated the later code
checking and decoding the 'path' entry can be removed.
2014-07-08 15:31:49 +01:00
34650f4b3c Prevent private flagged torrents auto-merging trackers
When adding a torrent already in session any new trackers are merged
to the exiting torrent but this is an unwanted feature for private
flagged torrents.
2014-07-07 23:27:50 +01:00
59fa974b3b [#2315] [GTKUI] Potential fix for lost window on Win32 2014-07-07 22:07:56 +01:00
98e8418087 [GTKUI] Typo causing password dialog to show 2014-07-07 19:58:56 +01:00
176064b520 [GTKUI] Fix quitting bypassing password lock 2014-07-07 18:56:53 +01:00
c5ad5589df [#2369] [GTKUI] Fix bypassing tray password dialog
Created a generic password dialog and moved the unlock code out of
systemtray so any call to window.present will now show the dialog.

Also fixed the appindicator not showing the correct visible status
2014-07-07 18:19:55 +01:00
9987d335a0 [GTKUI] Hide the associate magnet button on OSX 2014-07-04 20:51:26 +01:00
d6b44afb99 [#1490] Increase the Alertmanager interval to 0.3s
The original 0.05 interval is causing excessive idle cpu usage
2014-07-04 19:17:16 +01:00
7597ba9343 [#2372] [GTKUI] 'Ratio' column will not retain position
This is a backport of restore_columns_order_from_state applied to develop code.
2014-02-20 18:51:59 +00:00
41f1ad9f5f [#2373] [OSX] Fix laucher scripts for single leading slash path
On Mavericks the application path passed to scripts only has single leading slash
compared to previous double slash.
Renamed and changed shebang to bash to prevent any issues.
Updated README to rst format for display in trac wiki.
2014-02-19 19:00:23 +00:00
29d3e72f49 [#2082] Validate ip address for listen_interface entry
This ensures that only ip addresses are accepted for
listen_interface as libtorrent cannot accept interface
names (eth0) and will cause unexpected results for user.
2014-02-18 19:34:31 +00:00
d04af1e392 [#2343] Fix error if listen interface is whitespace
Whitespace in the interface dialog is not obvious to the user so
strip in core to prevent error from bad config
2014-02-18 19:22:12 +00:00
c620ddcba0 [#2310] [WebUI] Fix unicode password support 2014-02-17 23:59:24 +00:00
e8aee7327b [2374][WebUI] Fix right-click selection issue 2014-02-17 23:02:45 +00:00
018330c92c forgot break in for loop 2014-02-09 19:45:28 +00:00
58c048f1b0 GTKUI: Ensure None value from problem config is empty string for set_text 2014-02-09 19:14:19 +00:00
9f75d4597e Change get_default_download_dir to use expanduser as fallback 2014-02-09 19:12:59 +00:00
ffc48d3810 Fix common.free_space to handle path is None 2014-02-09 18:38:18 +00:00
c38b00dd07 Fix #2381 : Allow silent uninstall for Windows package 2013-11-19 22:43:24 +00:00
479c96745c Fix #2371 : Add StartupWMClass to desktop file 2013-11-19 22:43:24 +00:00
63807899a0 Fix #2367 : Private Flag not showing as ticked/checked in DelugeStart theme 2013-11-19 22:43:24 +00:00
a3806b6d7a Fix #2365 : Hiding Progress column generates TypeError 2013-11-19 22:43:24 +00:00
7bd87d1a82 Fix #2335 : IPC lockfile issue preventing start of deluge-gtk 2013-11-19 22:43:01 +00:00
8bf18d6694 Fix #2355 previous fix wasn't entirely correct - thanks Thomas Hipp 2013-11-12 14:01:08 -08:00
06ee112344 Fix twisted 13.1 compat -- the _parse() function was replaced by the _URI class 2013-08-06 18:52:59 -07:00
3cc43f63a0 Fix #2338 : Spelling mistake with occurred 2013-06-09 02:35:10 +01:00
27bfa5a649 Fix #2302 : deluge-gtk crashed with IndexError in get_plugin_info
This fix handles the plugin info not being available
2013-05-22 23:26:30 +01:00
5057e2caab Fix #2303 : Torrent state not updated until after emitting TorrentFinishedEvent 2013-05-22 23:18:01 +01:00
686fb31844 Fix #2221 : Addtorrentdialog KeyError accessing download_location
Sets a default value of None for any missing config keys
2013-05-09 19:02:34 +01:00
03d5654a16 Fix #2324 : Encryption level set by deluge does not match libtorrent values
The clients are using range (0-2) whereas actual bit values are (1-3)
2013-05-09 19:00:33 +01:00
83f0d72601 Fix Python 2.5 compatibility 2013-04-23 00:21:49 +01:00
19093e03ae Update DEPENDS 2013-03-27 00:34:38 +00:00
d28de71995 Update Extractor plugin description, version and modify log levels 2013-03-26 19:39:47 +00:00
f107485871 Fix #2290 : Extractor: Dotted filenames being rejected 2013-03-26 18:35:37 +00:00
984691f74c Fix scalable icon install dir 2013-03-24 23:31:45 +00:00
8ba8e24fab Add pango env vars to osx package script 2013-03-17 19:26:21 +00:00
7c9433fd8b Update osx build and packaging scripts 2013-03-17 18:10:51 +00:00
821f395d8b Fix issue with Plugins that add Tab to torrentdetails 2013-02-27 17:44:52 +00:00
e9ba3972ad Bump version for release
Also update deluge.pot and .gitattributes
2013-02-25 17:01:07 +00:00
7fbe163c24 Extractor: Refactor and fix tar.* issue on windows 2013-02-23 02:07:09 +00:00
e4118048eb Add a new DelugeStart theme to win32 gtk
This theme is based upon ANewStart theme and uses murrine theme engine.
2013-02-22 19:04:10 +00:00
bb67721002 Disable unused torrentview reordering property which fixes Win32 mouse scroll bug 2013-02-22 01:03:52 +00:00
9856f97323 Fix #2283 : Potential for sessionproxy keyerror with newly added torrents 2013-02-21 22:47:30 +00:00
e2e37a83de Update Extractor with Win32 and extra archives support
Also disabled extracting on move_completed enabled torrents and fixed
some other small issues.
2013-02-21 21:58:23 +00:00
61c125420b GTKUI: Autofill save path when creating torrent from remote path 2013-02-21 16:23:59 +00:00
36a78d8f21 Optimized torrentview.cell_data_trackericon
cell_data_trackericon would load the tracker icon with
gtk.gdk.pixbuf_new_from_file_at_size each time it's requested.
These regular requests acumulating to thousands calls to
pixbuf_new_from_file_at_size with a big torrent list.

Now, read the tracker icon from disk once, and cache it.
2013-02-17 18:38:35 +00:00
3f4cfd5c88 Replace Exception with GError in filtertreeview 2013-02-17 18:37:01 +00:00
cc85f00588 Update Changelog 2013-02-17 15:17:46 +00:00
72b58d19c1 Build webui js and gettext 2013-02-17 15:00:27 +00:00
bbf17772ac Add tracker host details to debug logging 2013-02-17 14:59:34 +00:00
2cbcb35c9e Add OSX packaging and GTK support 2013-02-14 00:29:55 +00:00
7ef7cc41b6 GTK: Fix showing exception error to user with no libtorrent installed 2013-02-13 01:30:48 +00:00
7c6d1f30ff Fix GTK ConnMgr update after stopping daemon and reduce wait time 2013-02-13 01:30:47 +00:00
8911600155 Fix prioritize first/last pieces for magnet links 2013-02-11 22:09:46 -05:00
c58221c866 Fix renaming folders on libtorrent 0.16 compiled with unicode support (Windows) 2013-02-11 21:36:46 -05:00
92eb9feae4 Fix setting 1GB/s speeds in gtkui 2013-02-11 18:35:26 +00:00
b9311d4b57 Add exception details to EventManager error log 2013-02-05 19:29:25 +00:00
b0d78da13b Fix #2258 : Potential runtimeError when emiting event 2013-02-05 18:56:18 +00:00
12365241a5 Fix #2260 : Add dialog pulling main window to active workspace 2013-02-05 18:06:51 +00:00
8ba5e78610 Fix #2242 : Notifications: Missing word in torrent finished message 2013-02-04 13:26:07 +00:00
1bfaf74ff9 Fix #2261 : WebUI: Proxy settings not being saved 2013-02-04 13:18:34 +00:00
e362b36a59 WebUI: Add failed login log message with IP address for fail2ban 2013-02-04 13:15:44 +00:00
a0ae3ebfce Optimizations to torrentview.update_view
A few changes that reduces the CPU usage of the GTK UI
significantly. This small patch is made simple to be
100% certain not to introduce new bugs.
2013-01-21 01:45:23 -05:00
08d7b9fba3 Fix issue with downloaded torrent temp files on windows which had illegal characters. 2013-01-20 16:26:55 -05:00
95ce85ec78 Make sure sessionproxy events are registered after stopping and starting a daemon from gtkui. 2013-01-17 22:10:48 -05:00
93dee4c764 Don't deliver empty resume_data parameter to session.add_torrent
Fixes a libtorrent crash on python 2.7 on Windows
2013-01-17 22:08:56 -05:00
dcd85e64c0 Add move complete location to webui add torrent dialog. 2013-01-04 18:43:06 -05:00
58e8a0e562 Fix mapped_files error in AddTorrentDialog 2013-01-03 17:30:45 +00:00
bfa3564ba3 Fix Gtk addtorrentdialog parent None error for single file torrents 2013-01-02 22:38:55 +00:00
669d10e6be Fix #2240 : Win32 freespace issue with large capacity drives 2013-01-01 17:44:11 +00:00
3d1b47bca6 Fix error when loading torrent through IPC
Fix bug from commit 0045ec0cf1: missing args attribute error when
loading torrent through IPC on non-windows.
2013-01-01 17:37:42 +00:00
2fde78f236 Update Changelog, webui gettext, gitignore & compress js 2012-12-22 02:24:25 +00:00
444740709a Update translation files from launchpad 2012-12-22 01:40:55 +00:00
d7d91aec0b Fix WebUI submenus closing upon mouse click 2012-12-21 19:34:18 +00:00
e865180e83 Fix issues with js eventmanager. refs #2046
Fix plugin methods not being available when enabled until refresh. refs #2125
2012-12-21 12:51:40 -05:00
782b39c90d Fix #2125
Clean up some json api code.
2012-12-21 12:51:36 -05:00
7e71995e55 WebUI: Catch potential undefined error when attempting to disable a plugin 2012-12-18 21:50:19 +00:00
1dd078f4f1 Fix #1963 : Unhandled OSError if permission issue creating default config dir
The fix now logs the error and exits. To log the error also required moving
the logger setup code to before any default_config_dir call.
2012-12-18 01:03:06 +00:00
0045ec0cf1 Fix #1946 : GtkUI: ReactorNotRestartable error when set as startup application 2012-12-17 19:57:32 +00:00
5ecc580463 Fix #2175 : systemtray free variable self referenced before assignment
This is only the likely fix for the issue as I have been unable to reproduce it.
2012-12-15 21:26:36 +00:00
70047c367a fix error in #2085 commit 3ca886ac7a: value may be a tuple 2012-12-11 00:57:48 +00:00
b65918d616 Catch exception when enabling/disabling indicator in classic mode 2012-12-10 19:33:13 +00:00
3ca886ac7a Fix #2085 : WebUI: Does not show torrents in sidebar for categories other than 'All'
unicode value in filter_dict would not be converted into a list
2012-12-10 15:48:38 +00:00
74208c27f8 Fix #2227 : Torrent file contains sha1 and ed2k digest that needs encoding to hex 2012-12-09 23:22:30 +00:00
7cc8243849 Use try-except instead of if statement to gain a little performance 2012-12-09 22:57:00 +00:00
c741e127b9 First change outside of deluge/ui/console - fixed a problem when removing torrents 2012-12-09 22:51:40 +00:00
b5ea33e506 On some "race" conditions, the torrent is removed before it's status could be retrieved. Return an empty status. 2012-12-09 22:31:22 +00:00
ffe0c168bb Fix #2232 : WebUI: Flag Icon path in Peers Tab missing deluge.config.base 2012-12-09 19:06:40 +00:00
b8c345ff26 Fix #2231 : WebUI: Fix unneeded scrollbars in webui add dialog
Also fix spinner display issue
2012-12-08 19:14:33 +00:00
9286d43ba8 Increase libtorrent alert queue size. fix #2204 2012-12-07 23:10:09 -05:00
23b0f58eb4 fix snafu in last commit 2012-12-05 18:35:44 +00:00
ccd2e5e41d Fix #2130 : Same name can be given to different files in Add Torrent dialog 2012-12-05 18:12:08 +00:00
62a1602d5a Fix #2129 : Empty filename can be set in AddTorrent dialog 2012-12-05 18:10:53 +00:00
b50c848054 Fix #2228 : Apply-To-All in AddTorrent Dialog is copying file renames to other torrents 2012-12-05 14:06:25 +00:00
e4d94ea528 Fix #2220 : MacOSX homebrew build not finding boost libs 2012-12-05 13:49:48 +00:00
fc4ca861da Fix libtorrent version check in torrent.py. fix #2223 2012-12-03 01:14:17 -05:00
74d59eb6ec Fix the version check in _libtorrent to work as intended. 2012-12-03 01:08:31 -05:00
ce4b4ef48e Handle torrent add failures in web UI
Show an error dialog and remove the torrent from the list
when a torrent file fails to upload or a URL fails to download.
2012-12-02 17:34:21 +11:00
2e0b0d9474 Make web build script sh compatible 2012-12-02 15:08:58 +11:00
0e4101a9a3 Add windows support to is_ip 2012-12-01 02:21:01 +00:00
ba4ca111c6 Fix Win32 connection manager hanging when starting new windowsless daemon 2012-11-30 14:44:05 +00:00
827b53792b Update Changelog and deluge.pot 2012-11-29 22:39:37 +00:00
6e75a194c3 Fix typo in json_api docstring 2012-11-28 23:35:56 +00:00
a3a9cae9f7 Fix #1474 : on_show_prefs hook is not executed immediatly after enabling a plugin 2012-11-27 22:47:03 +00:00
f447bd5cea Fix #2110 : Accept magnet uris with xt param anywhere within them 2012-11-27 21:17:26 +00:00
f79785abf2 Fix #2147 : Missing translations for plugin preferences page 2012-11-27 21:14:02 +00:00
a2423ba536 Fix #2146 : Missing translations in View|Tabs submenu
Also fixed small bug when hiding Status tab
2012-11-27 02:02:35 +00:00
4307699bbf Fix torrent names on libtorrent 0.16 on windows. 2012-11-26 19:42:36 -05:00
e7a2a8dcee Fix #2109 : Proxy settings not being cleared by setting None 2012-11-26 22:03:54 +00:00
67450f43b3 Fix print statements for Python2.5 2012-11-26 17:31:01 +00:00
10ccd9aaaf Update Changelog, translation files and compress js 2012-11-26 16:54:36 +00:00
16568404e7 Fix Windows tray submenu items requiring right-click instead of left-click 2012-11-26 13:31:41 +00:00
901f5a84bf Fix #2208 : Win32 Open Folder not working with non-ascii paths 2012-11-26 03:19:20 +00:00
8ffa80c2a2 Fix #2086 : Enable submenus for appindicator 2012-11-26 02:03:20 +00:00
0f16faabcb Fix use of translated text for widget name in build_menu_radio_list 2012-11-26 02:03:20 +00:00
508b5aed8f Fix #2201 : auth fails if auth file has extra newlines 2012-11-25 23:30:13 +00:00
f2b2f98fac Fix #2069 : WebUI: Login window layout problem when using larger than default font size 2012-11-24 17:11:25 +00:00
42e33d452e Fix #1890 : WebUI: Column in files and peers view could use some spacing
Also fixed the SpinnerGroup to no longer show horizontal scrollbar and added
vertical scrolling to detailstab.
2012-11-24 16:10:15 +00:00
ea75cfb6d7 Fix config not defined in ipcinterface 2012-11-24 15:49:57 +00:00
9155191b0a Fix #2103 : WebUI: Sorting by name is case-sensitive 2012-11-24 12:41:54 +00:00
0571799a07 Fix #2120 : WebUI: Manually entered values not being saved in Spinners 2012-11-24 12:41:54 +00:00
aaf4aa5226 Fix #2212 : WebUI: Unable to scroll in proxy preferences page 2012-11-24 12:41:44 +00:00
3e98ef5f89 Add quit dialog when changing classic mode.
Don't change visibility of connection manager when changing classic mode.
2012-11-23 20:47:26 -05:00
c398ef57a5 Fix unhandled error with empty clipboard on Win32 2012-11-23 01:04:01 +00:00
68b413af5f Updates to web gen_gettext script and add .build_data to gitignore 2012-11-23 00:53:49 +00:00
3f79d36489 Removing unneeded webui files 2012-11-23 00:36:37 +00:00
582c6735d0 Fix #2100 : Add option not to bring main window to front when adding torrents through ipcinterface 2012-11-22 23:38:27 +00:00
5d43c2ac94 Update bbfreeze and nsis scripts for win32 packaging
bbfreeze script:
  * Creates a VERSION.tmp file for use by nsis script
  * Includes all theme, icon and locale files. Closes #2096 & #2145
  * Add email.mime.multipart and email.mime.text. Closes #2074
  * deluged.exe and deluge-web.exe will no longer show a cmd window and created
    deluged-debug.exe and deluge-web-debug.exe as replacements if still needed
  * Overridden bbfreeze gtk recipe thus no longer requiring file editing.
  * Remove unnecessary python module includes

nsis script:
  * Deluge version now based upon bbfreeze output
  * Installer will warn if deluge already running. Closes #1217
  * Removed deluged and deluge-web shortcuts from start menu
  * Increased compression level for lzma
2012-11-22 23:19:05 +00:00
845b95d88f updated gitattributes to ignore deluge-web debug files 2012-11-22 23:19:05 +00:00
66437531e8 Update changelog. 2012-11-21 02:16:46 -05:00
666bb09513 Make sure queue order is preserved when restarting daemon. 2012-11-21 02:14:12 -05:00
7d88cb1850 Fix file renaming and moving with unicode characters on libtorrent 0.16
Fix torrent creation with unicode characters

Update changelog
2012-11-21 01:25:18 -05:00
d825be4901 Make path separators in Torrent.get_files consistent across platforms. 2012-11-12 21:12:54 -05:00
135c98634a Eliminate the need to manually call the on_toggle handler for move completed in add torrent dialog. 2012-11-12 21:06:16 -05:00
ecb457c043 Make sure sensitivity of move completed path is always set correctly in add torrent dialog. 2012-11-10 22:25:27 -05:00
cd8ab2805c Fix daemon starting with config dir containing spaces on Windows. 2012-11-09 18:44:36 -05:00
b7ca968fae Fix jitter in gtk torrent view. 2012-11-07 00:35:58 -05:00
8f71b8d5c6 Revert stable sort and speedup commits. 2012-11-07 00:16:24 -05:00
8a72187998 Replaced WMI process enumeration with the EnumProcesses API call. (Shorter, faster, does not depend on pythoncom.) 2012-11-06 22:30:19 +00:00
d9f1210fe7 Fix 2107 : create_plugin.py call correct version of python 2012-11-06 22:21:00 +00:00
0a9fe242e7 Move sensitivity check to a more appropriate place for move completed on add torrent dialog. 2012-11-02 19:25:24 -04:00
e53413902c Update changelog. 2012-11-02 19:17:42 -04:00
bd500c30de Merge remote-tracking branch 'github/1.3-gtk-movecompleted' into 1.3-stable
Conflicts:
	ChangeLog
2012-11-02 18:09:11 -04:00
b8b27bdaf2 Make move completed field sensitive only when check box is enabled on add torrent dialog. 2012-11-02 18:04:38 -04:00
ad8b757387 Fix changelog entry for move completed patch. 2012-11-02 02:09:21 -04:00
fd8dc457fa Add move completed option to add torrent dialog. 2012-11-02 02:06:33 -04:00
69509f446e Update changelog. 2012-11-01 23:41:28 -04:00
db502253c9 Generalize stable sorting to use unique column set for the ListView.
Add a default sorting to the ListView.
Switch gtk speedup patch for new sorting.
2012-11-01 00:25:00 -04:00
8d25a5e691 Merge remote-tracking branch 'bro/1.3-stable-torrentview' into 1.3-stable 2012-10-31 22:05:15 -04:00
3c85cc4b03 Make the gtkui torrent view stable sort. 2012-10-31 00:12:36 -04:00
03abe32054 Fix #2185: register call should be deregister in deregister_event_handler 2012-10-14 00:31:28 +01:00
7695c4e566 Add #1397 : Console UI - Support -s STATE in info
Cherrypick nick's commit from git master with code tidyup and workaround
for tuple issue in filtermanager so backward compatible.
2012-10-13 02:23:48 +01:00
a64fe05890 Ensure torrent_ids is a list
If torrent_ids is created from filter_dict it is a tuple. This results
in an error when attempting to remove a torrent_id from torrent_ids
later on in 'leftover filter args' and 'filter_state_active()'.
2012-10-12 23:48:40 +01:00
762ad783e2 Speed optimizations for the torrentview 2012-10-10 15:53:21 +02:00
aa969fd830 Fix #2169 : Add Torrent Dialog 'Download Location' not set correctly when folder typed into Other->Location field
Using get_current_folder() in the file chooser will use the default folder when a folder path has been typed into the Location field rather than selected with mouse. The solution is to replace it with get_filename().
2012-10-06 22:54:37 +01:00
e5f56e2fdd Fix #2171 : Add Peer dialog stops responding if empty or invalid values entered 2012-09-30 18:23:51 +01:00
610cd7dd33 Fix #2104 : Deluge has no indicator title 2012-09-29 19:15:49 +01:00
bb7b529c29 Fix #2112 : World readable tmp directory in json_api 2012-09-29 17:02:16 +01:00
43390b850a Fix 2163 : Cannot add torrent file with empty (0:) encoding tag 2012-09-27 18:36:50 +01:00
8c2189f161 Fix exception handling in rencode 2012-09-27 18:00:47 +01:00
37ea2854a2 Fix 2160 : Disable use of python bindings for libtorrent extensions and replace with session flag
The fixes a GIL issue causing libtorrent segfault. https://code.google.com/p/libtorrent/issues/detail?id=369

Note: The ut_pex plugin (Peer Exchange) will now always be enabled.
2012-09-27 17:56:13 +01:00
7b9bca0957 Fix copy pasta fail :( 2012-09-19 22:23:48 +10:00
ec3d698a14 Merge branch '1.3-stable' of deluge-torrent.org:deluge into 1.3-stable 2012-09-18 18:00:02 -07:00
3309f59333 Fix previous commit 2012-09-18 17:59:54 -07:00
68990b4a3f Fix execute plugin not working with unicode torrent names 2012-09-16 18:40:53 +10:00
17cac01673 Fix deluge-gtk not working with twisted 12 (fixes #2148) 2012-09-16 18:36:58 +10:00
18eb885983 Don't use deprecated twisted imports (fixes #2164)
Aliases have been removed in twisted 12.2.0.
2012-09-16 17:12:16 +10:00
cb661f2595 Update google.ico so tracker_icons tests pass again 2012-09-16 17:09:23 +10:00
fc14b00868 Only convert the move path to unicode if on windows 2012-09-14 15:56:13 -07:00
725d06f439 Add compile arg needed by libtorrent 0.16.x 2012-08-27 08:25:38 +10:00
3569e18712 Don't clobber filename when adding torrents with mapped_files 2012-08-21 18:31:59 -07:00
42118932f2 Fix exception handling 2012-08-06 15:54:28 -07:00
c480132fa2 Fix autoconnecting to the default host 2012-07-17 17:24:25 -07:00
313a04f9a6 Fix LP#1004793 : Console: Enable use of connect in non-interactive mode 2012-06-28 00:07:06 +01:00
d1f2776463 Update Win32 Installer readme
Also remove unneeded StartX.exe
2012-06-27 01:05:44 +01:00
dac524ccf3 Fix common.open_file for osx 2012-05-30 00:54:56 +01:00
bafd0209af Console: Fix test for empty color string 2012-05-30 00:54:56 +01:00
0a6c2ee147 Also handle alias for quit (exit) 2012-05-30 09:27:37 +10:00
85cdbec10d Only add quit to deluge-console args if it isn't already present
This prevents an error from being raised due to trying to stop
a reactor which is no longer running
2012-05-30 09:15:09 +10:00
f083a3b67b Ensure console commands are executed in order 2012-05-28 00:35:14 +10:00
d08ea7da81 Fix #2062 : Console discards text before first colour string 2012-04-20 12:32:20 +01:00
483c439e38 Fix #2065 : Console crash with missing closing quote 2012-04-19 15:52:59 +01:00
914413c88f Catch & log KeyError when removing a torrent from the queued torrents set
This seems to happen due to libtorrent firing the torrent finished event
twice.
2012-04-12 23:52:50 +10:00
438dff177c Fix formatting in ChangeLog 2012-04-11 23:09:14 +10:00
196458399e Update version number 2012-04-09 18:53:16 -07:00
1d243d5967 Remove some additional DLLs 2012-04-09 18:51:55 -07:00
418037dd43 Update version 2012-04-09 18:42:25 -07:00
900907a545 Update Changelog 2012-04-09 17:28:31 +01:00
b3a721b539 Update Translations from Launchpad 2012-04-09 17:17:12 +01:00
d783b8ead7 WebUI: Increase focus delay for password field cursor 2012-04-09 17:14:11 +01:00
5572f61022 Fix #2071 : KeyError in gtkui when file priority set to value '3'
Bug results from setting file priority value in core which does not
exist in the FILE_PRIORITY dict used by UIs.
2012-04-08 23:35:34 +01:00
fe6e9ec467 Gtkui: move height request to child widget in create dialog 2012-04-08 17:50:55 +01:00
675a64e213 Fix missing semi-colon in deluge.desktop 2012-04-08 12:04:59 +02:00
931b8aec71 Console: Fix prefixed space for tab completing commands
The join command adds space if 'p' is empty string.
2012-03-26 19:08:28 +01:00
f19caf69e0 Console: Fix missing trailing space for command options with tab complete 2012-03-26 19:04:55 +01:00
56a24f16f2 Only assign prioritize_first_last_pieces to torrent options if actually changed 2012-03-26 17:06:51 +01:00
275c939b95 Remove unnecessary translation from connection manager 2012-03-24 00:24:10 +00:00
8238c63156 Use (documented) formatdate over format_date_time 2012-03-23 19:23:01 +11:00
c19718b66a Grey out file priorities for 'is_seed:True' seeding torrents 2012-03-22 01:22:31 +00:00
eac52dec73 Bring MainWindow to front when opening another instance of gtkui 2012-03-22 01:14:41 +00:00
124daaf8b2 Update translations po files 2012-03-21 21:32:58 +00:00
5d6fa23011 Hide unused Infohash button in WebUI 2012-03-14 00:22:48 +00:00
0da64f7db4 Update ChangeLog 2012-03-13 00:05:44 +11:00
b9030dfb8b Preserve order when moving multiple torrents in the queue 2012-03-12 23:46:19 +11:00
3528549430 Add get_queue_position & use it for sorting ids 2012-03-12 23:46:19 +11:00
39a04aae20 Fix not properly detecting when torrent is at end of queue 2012-03-12 23:45:51 +11:00
72a2ace0a1 Update Changelog, deluge.pot and js compress 2012-03-11 19:33:06 +00:00
4240345daf Label Plugin: Mark 'Label Options' for translation 2012-03-11 18:40:04 +00:00
cb9867a26f Label Plugin: Defer translate No Label text in submenu 2012-03-11 18:26:53 +00:00
07e166b94a Label Plugin: Disable menu items for 'All' in sidebar 2012-03-11 18:26:53 +00:00
3c7f492451 Fix Label Plugin text 'All' for translation in sidebar 2012-03-11 18:26:18 +00:00
aeca5dd1e7 Mark torrent menu Pause text for translation 2012-03-11 17:17:29 +00:00
c194f6bbe4 Fix #2052 : Progress bar state text marked for deferred translation 2012-03-11 17:13:25 +00:00
4d77241603 Modified fix for #1957 non-acsii columns 2012-03-10 22:31:43 +00:00
a2a45f1a0b Fix gtk sidebar text for translation 2012-03-10 22:31:17 +00:00
217087a2fe Fix for Up Speed column not sorting in Webui 2012-03-10 13:17:24 +00:00
bb89a355e5 Merge branch '1.3-stable' of deluge-torrent.org:deluge into 1.3-stable 2012-03-04 16:41:43 -08:00
954c0e2d4d Change some of the win32 build/installer scripts to support bundling GTK
in with the installer
2012-03-04 16:41:13 -08:00
9ce738e39a Fix adding magnet error in webui when started from classic mode 2012-03-03 23:41:24 +00:00
911d583ff0 Bump version to 1.3.4 2012-03-03 11:55:13 -08:00
07bc1322dd update depends 2012-03-03 02:32:50 +00:00
1058435700 Set process name to match application using setproctitle
Using the setproctitle module the process name displayed in top
and other places will correctly reflect the binary name. This is an
optional dependency
2012-03-03 02:29:42 +00:00
0676aaf918 Properly wait for the component.shutdown deferred on shutdown. This should prevent the daemon from exiting before all the state has been saved. 2012-03-02 09:15:35 -08:00
5d0dace131 Fix #2045 : UnicodeDecodeError when using non-ascii chars in info
Input arg string needed decoding otherwise comparing with unicode
torrent name fails.
2012-03-02 15:42:15 +00:00
be75d5021b Execute: log stdout/stderr when command fails 2012-03-02 13:03:01 +11:00
b0029517eb Execute: make running commands asynchronous
This prevents deluge from hanging while it waits
for a command to finish.
This also prevents a deadlock from occuring
(c.f. warning at
 http://docs.python.org/library/subprocess.html#subprocess.Popen.wait)
2012-03-02 12:57:47 +11:00
2ae936df44 Remove setting torrent.is_finished in the resume alert
Set torrent.is_finished to false when torrent is in a Checking or Downloading state
2012-02-29 15:20:59 -08:00
1f5cfd16e0 Updates to previous fixes for setting is_finished 2012-02-29 02:56:14 +00:00
b5b0db6c60 Update Changelog and deluge.pot 2012-02-29 01:35:37 +00:00
1f660653ff Set is_finished to match is_seed after checking
Fixes issue where re-downloading data would not change is_finished
2012-02-29 01:35:33 +00:00
7020e5ca90 Blocklist: remove default url as it is outdated 2012-02-29 12:21:18 +11:00
00ebaae67a Blocklist: check for updates iff interval > 0 2012-02-29 12:18:24 +11:00
eb773bba2c Fix preferences dialog not opening with main window on Windows 2012-02-28 22:44:52 +00:00
e10cfb8f8c Fix #1976 : Text entry with trailing newline characters causes issues for Move Storage
Changed most GtkEntry truncate-mutliline properties to True for all single line
entries to prevent similar issues.
2012-02-28 19:29:36 +00:00
fcf26bad45 Add optparse custom version to prevent unnecessary loading of libtorrent 2012-02-28 19:29:35 +00:00
ec373c0ec9 Update translations 2012-02-28 19:29:34 +00:00
933f80c01c Alternative fix for re-enabling plugin issue 2012-02-28 19:29:34 +00:00
89634137b9 Update Changelog 2012-02-27 15:39:08 +00:00
e7dada6afc Fix #2021 : Share ratio limit not obeyed for torrents downloaded outside deluge
Share ratio limit is based upon torrent.is_finished and a seeded torrent added
to the session was not set after checking.
2012-02-27 15:31:53 +00:00
8db789ffe2 Fix #2038 : Chrome 17 disconnecting from webui 2012-02-27 15:31:53 +00:00
dd3aab1cef Catch glade object issue when re-enabling Autoadd
Found an additional glade object from the previous instance of Autoadd
calling cb_get_config resulting in an exceptions.AttributeError.
This workaround simply checks that get_widget is not None.
2012-02-27 15:29:50 +00:00
54769fe190 Fix #2044 : Unable to re-enable execute plugin 2012-02-27 15:22:04 +00:00
fa7edd0bad Fix plugins not showing enabled in webui 2012-02-26 23:00:06 +00:00
2b865273f6 Fix potential keyerror for on_torrent_removed in sessionproxy 2012-02-24 00:34:53 +00:00
403ad26111 Update Changelog 2012-02-23 00:51:29 +00:00
6bc3968ba4 Multiple Magnet links support in autoadd plugin 2012-02-22 18:38:16 +00:00
bbeb11b1e7 Magnet link support in autoadd plugin
Check the watch folders for .magnet files which contain valid magnet links
and add them.
2012-02-22 18:38:05 +00:00
e4840d6b37 tabs to spaces 2012-02-22 15:53:29 +00:00
88db73e244 More fixes for labels plugin webui
Disabled options and remove for filters No Label and All
Removed All from torrent menu
Fixed No Label not working in torrent menu
Bumped version to 0.2
2012-02-22 15:49:49 +00:00
a359374547 Fix #2035: If auto_add_trackers is empty, it is an array 2012-02-22 13:55:06 +00:00
c5e328c3bd Fix #2036: new labels are not sorted on torrent right click 2012-02-22 13:35:14 +00:00
bc425b392a Convert tabs to spaces in label.js 2012-02-22 13:34:57 +00:00
4feb816380 Fix missing desktop file preventing install 2012-02-20 16:56:20 +00:00
ff95d9720a Fix setting daemon listen interface from command line 2012-02-20 14:06:29 +00:00
7847362dbb Catch and log ReactorNotRunning when stopping reactor in gtk 2012-02-19 16:44:12 +00:00
7b1e8862b4 correction for glib.gerror commit 2012-02-19 13:32:45 +00:00
ed883125fd catch and log 'glib.GError: Unrecognized image file format' error 2012-02-19 00:54:33 +00:00
9799c64505 Fix #2037: webui 'Add Torrents' dialog torrents list not scrolling 2012-02-18 20:36:32 +00:00
d1f788ebe3 Further fix for progress bar display in webui
When first loading webui is browser this.style is undefined and p.style
contains the width of the progress column however after this point
p.style contains the width of the previous column so need to use
this.style which now represents the progress column width.
2012-02-18 18:59:13 +00:00
3744bdad69 Build compressed javascript for deluge-all 2012-02-18 18:26:04 +00:00
ea75828f25 Fix progress bar display 2012-02-18 18:23:57 +00:00
966fc6f64f Update extensions to Ext JS 3.4.0 2012-02-18 18:23:52 +00:00
5ff0d61b52 Add Webui keymaps for torrents - Ctrl-A (select all) and Delete 2012-02-18 03:42:00 +00:00
f5956f01e7 Ignore unmaximise event when window isn't visible
This fixes the bug where a maximised main window
will become unmaximised (on restart) after
quitting deluge from the system tray.
2012-02-18 12:34:05 +11:00
717db367e8 Add magnet uri support to Add Url in Webui 2012-02-18 00:39:24 +00:00
e0efe3885a Update Changelog 2012-02-16 16:58:32 +00:00
836da50f78 Remove orientation property from glade files to fix compatibility warnings 2012-02-16 16:44:15 +00:00
85b1753a28 Fix compatibility for Python2.5 and Debian Lenny
Recent commit to handle warnings were >=Py2.6 and glib binding is
unavailable on Debian Lenny.
2012-02-16 16:44:14 +00:00
eb6959fb98 Cleaner log entry if deluged missing 2012-02-16 16:44:14 +00:00
30c142ac4d Fix #1954 : 'invalid literal for float' console error when setting listen interface 2012-02-16 16:44:14 +00:00
08a75bd9f9 Wait for client to shutdown/disconnect before stopping reactor (fixes #2032) 2012-02-16 14:12:03 +11:00
754a5a7f8a Add scheduler plugin page to webui 2012-01-25 01:00:15 +00:00
863fd7d2b7 Webui applies changes when OK clicked in Preferences 2012-01-25 01:00:05 +00:00
56f2283e3e Fix collapsed treeview in Create Torrent dialog 2012-01-24 14:25:09 +00:00
272d2005e0 Add missing columns to WebUI
Added Download,Uploaded,Down Limit, Up Limit & Seeder/Peeds. Also selected
columns start out hidden to match gtkui and the name column has a minimum
width of 150.
2012-01-24 01:55:56 +00:00
375ee2dd1c correction for the comparision in previous commit 2012-01-19 01:28:39 +00:00
98dcc8e3b1 Fix stored file priorities settings
File priorities stored in torrent options were based upon the supplied
funtion values rather than the current values stored in libtorrent. So
if the priorities failed to be set by libtorrent the settings would be
out of sync.
2012-01-19 00:51:54 +00:00
e91458662f ui: fix error in last commit
The last commit assumed that loglevel would always be a string,
take into account that it can sometimes be None
2012-01-17 17:07:09 +00:00
2600785cbb Merge branch '1.3-stable' of deluge-torrent.org:deluge into 1.3-stable 2012-01-17 16:58:29 +00:00
e5576dff1e ui: fix setting capital log level
Whilst providing the log level as a lowercase string has worked
for a long time trying to use DEBUG doesn't work, so lowercase
the string first.
2012-01-17 16:58:18 +00:00
4c648bc09f Update Changelog 2012-01-10 02:08:17 +00:00
17d9739abb create the toolbar with the rest of the UI 2012-01-10 00:53:02 +00:00
c1bf52e8d9 update changelog 2012-01-09 22:38:18 +00:00
d60b436fcb web: rebuild the compressed javascript
There were a few changes when upgrading to ext 3.4 so rebuild and
compress the javascript files
2012-01-09 22:37:29 +00:00
2e0e0fb6b5 Merge branch '1.3-stable' of deluge-torrent.org:deluge into 1.3-stable 2012-01-09 22:34:59 +00:00
fe4f732c12 web: update to extjs 3.4.0
There are numerous fixes to the framework between 3.1.1 and 3.4.0 and
since there are no obvious bugs introduced it's only sensible to pull
the update in to the stable branch
2012-01-09 22:34:47 +00:00
25d930b307 Fix #1929 : Update setup.py to clean deluge*.egg_info dir from root dir 2012-01-09 22:19:24 +00:00
083c7fbb32 Fix #1936 : Referenced before assignment error in json_api 2012-01-09 22:19:24 +00:00
81fc47d080 web: fix gen_gettext script
The script for generating the gettext.js file was outdated and needed
a fix to work with the newer layout of the javascript source code, it
was still looking for Deluge.Something files which no longer exist.
2012-01-09 21:58:20 +00:00
e1745443bf Fix #1895 : Files Tab showing wrong files due to torrent_info race condition 2012-01-09 18:33:10 +00:00
649f933316 Update AUTHORS 2012-01-09 18:32:49 +00:00
8b46ed8bdb Remove unneeded license from blocklist 2012-01-08 14:03:22 +00:00
62aa339fd8 Fix #2010 : Move speed text in titlebar to the beginning 2012-01-08 03:53:30 +00:00
96d8f10080 Strip trailing space and tabs in aboutdialog 2012-01-07 19:53:24 +00:00
3d8e3f4add Webui: Smaller minSize for Sidebar and remove 1px border from mainpanel 2012-01-07 19:22:09 +00:00
08eb6002f8 Remove dotted line on buttons in Firefox 2012-01-06 20:52:04 +00:00
0015c9af86 Add Deluge and icon to start of toolbar in webui 2012-01-06 20:34:29 +00:00
4365e1ff39 Fix clipped Browse button in WebUI 2012-01-06 15:44:38 +00:00
0b6af77d57 Fix plugin uploads from behind a reverse proxy 2012-01-06 15:44:38 +00:00
6b2320d4b6 Fix password box focus issue in Firefox 9 for WebUI 2012-01-06 15:44:38 +00:00
a5742f892d Fix #1915 : Unable to stop the status bar from autohiding 2012-01-06 15:44:38 +00:00
01adb882ea Remove uneeded Title to save space in WebUI 2012-01-06 15:44:38 +00:00
9fd6d3d418 Hide unused Create button in WebUI 2012-01-06 15:44:38 +00:00
d4834bc6c7 web: fix font in loaded html
When dynamically loading the content panels in the details panel they
would sometimes look quite bad since the only font they have been
told to use is verdana. Fix this why using the same as extjs.
2012-01-06 15:06:21 +00:00
e4eda24e8f Update Changelog 2012-01-04 19:00:21 +00:00
39f648684e Fix #1961 : Missing 'All' filter option for Label plugin 2012-01-04 18:40:29 +00:00
56f8e213e3 Update POT and PO files 2012-01-03 00:38:02 +00:00
cb86828fa6 Update About dialog for translation 2012-01-02 19:12:48 +00:00
5cffc8f7e0 Add clean desktop file to setup.py 2012-01-02 16:53:28 +00:00
97912a28e4 Update Win32 README 2011-12-15 17:00:41 +00:00
9d2b0101d6 Fix issue in saving libtorrent session state 2011-12-15 16:10:21 +00:00
e49b7d5c23 Update README file 2011-12-15 15:41:00 +00:00
78a0ffd437 New AUTHORS file 2011-12-15 15:40:38 +00:00
dee8c30968 Add unneeded files for release to export-ignore 2011-12-15 15:33:47 +00:00
a34f224201 Build deluge-all.js 2011-12-07 01:20:21 +00:00
7a3c4440dc Update webui build file to run on Ubuntu 2011-12-07 01:07:19 +00:00
ce0c6d99f2 Revert "Fix #1976 : Trailing newlines in move_storage"
This reverts commit d96fae520d.
2011-12-05 18:14:56 +00:00
d96fae520d Fix #1976 : Trailing newlines in move_storage 2011-12-01 23:49:46 +00:00
d3c3d64cd4 Fix #1938 : AttributeError when attempting to shutdown daemon from client 2011-12-01 23:46:47 +00:00
b530658e20 Fix #1969 : Menu item 'quit & shutdown' available when not connected to daemon 2011-12-01 23:32:19 +00:00
eb70a7a6dc Fix #1984 : KeyError in preferences.py if key not in stored config 2011-12-01 19:30:57 +00:00
370035ffc5 Fix #1934 : Unicode error in AddTorrent Dialog 2011-12-01 19:24:33 +00:00
0941377fac Fix #1957 : Columns don't add resulting in keyerror for non-latin languages 2011-12-01 19:21:13 +00:00
1a8aa4b920 Fix #1898 : Email notifications do not include date/time they were sent 2011-11-30 00:05:13 +00:00
1c8327034d Revert "Fix #1338 Seeds and Peers totals not updating"
Did not fix the issue.
This reverts commit 1a9ae62669.
2011-11-29 17:52:13 +00:00
9ed155c456 Update to the DnD windows fix
Found that the original fix worked fine with GTK v2.24 but with v2.16 on Windows get_uris is empty
2011-11-27 01:44:30 +00:00
3d813ea1f8 Fix #1905 : No email sent to second email address in Notifications plugin 2011-11-26 14:51:49 +00:00
0f962aeda5 Fix #1953 : Console flickering on every update 2011-11-26 14:51:44 +00:00
3a0b6f8a6d Fix #1945 : Mutable default arguments in deluge.ui.client 2011-11-25 14:18:45 +00:00
cade8ee784 Change Windows default download path from '~' to '~\Downloads' 2011-11-25 13:46:34 +00:00
0d27032c06 AddTorrent file dialog now can browse network shares 2011-11-25 09:50:40 +00:00
3b8bbb2e77 Update Changelog 2011-11-22 23:16:27 +00:00
9c9064b246 Fix #1918 : Drag'n'Drop not working in Windows
Moved uri handling from mainwindow into ipcinterface process_args() and fix url to path conversion
2011-11-22 22:48:21 +00:00
d1a3cbebbe Remove code duplication in queuedtorrents.py, use ipcinterface process_args() instead 2011-11-22 22:48:21 +00:00
79f8af688a Modify log message from Error to Warning level 2011-11-22 22:37:51 +00:00
bbba60f34c Fix Webui files-tab menu setting wrong priority 2011-11-21 21:50:54 +00:00
a2d313383c Fix #1921 : GTKUI reports free disk space incorrectly 2011-11-20 18:00:19 +00:00
e336cd64b4 Fix #1967 : IndexError when trying to open a non-json conf file 2011-11-20 18:00:19 +00:00
eff3577505 Fix LP#821577 : UnpicklingError when external selection dragged onto Files Tab 2011-11-20 18:00:19 +00:00
2504b2520a Fix #1964 : Unhandled UnpicklingError with corrupt state file 2011-11-20 18:00:18 +00:00
d8560f5c25 Fix #1944 : Use errno constants for portability 2011-11-20 18:00:18 +00:00
51802f7c54 Fix #1912 : Exit nicely from get_libtorrent.sh if svn not installed 2011-11-20 18:00:18 +00:00
a3538c8937 Fix #1941 : Increase UIs max cache value to 999999 (15GiB) 2011-11-20 18:00:18 +00:00
714b7f3c55 Fix #1960 : Web UI statusbar shows total_payload_download for upload 2011-11-20 18:00:18 +00:00
f0c4a4c766 Fix #1928 : Crash when dragging column header
The fix specifically applied to on_alert_save_resume_data by moving function call str(alert.handle.info_hash()) into the try statement. For completeness any calls to str(alert.handle.info_hash()) also moved into try statements.
2011-11-20 18:00:12 +00:00
683e4be529 Fix #1940 : File & folder renaming issue when using Add Torrent dialog in Windows
The file rename in torrentmanager was calling lt.rename_file directly
so skipping the sanitize function normally applied when renaming.
2011-11-20 17:58:29 +00:00
93a860f2a1 Fix typo in Windows shutdown handler 2011-08-08 10:42:06 -07:00
9c4cd86492 Iterate over values not keys (fixes autoadd error) 2011-08-07 15:16:44 +10:00
fc6f9ebc3b Fix formatting of Changelog and add next version 2011-07-29 00:10:35 +01:00
603ca1b855 Fix i18n sub-dir issue in gitignore
Also fixes trailing whitespace in setup.py
2011-07-28 22:34:20 +01:00
3b89595d38 Update translation 'po' files 2011-07-26 00:49:48 +01:00
448478485a Add my name to author list 2011-07-22 19:28:31 +01:00
4234583fc7 Fix .desktop file creation on Windows by just ignoring it 2011-07-22 11:12:47 -07:00
bdd9bd11b5 Update version 2011-07-22 10:58:01 -07:00
8dbdb02967 Update windows setting 2011-07-19 16:50:32 -07:00
0555fbeb9d Fix python2.5 compatibility with except statements in remove_empty_folders 2011-07-16 14:11:52 +01:00
3126407d74 Update Changelog and ez_setup 2011-07-14 13:42:17 +01:00
2d09035dc4 Fix httpdownloader Tests 2011-07-14 01:00:26 +01:00
ed229d2ace Add intltool to dependencies 2011-07-13 23:29:39 +01:00
9e0d173115 Fix torrent file and folder renaming issues
Adds `sanitize_filepath` for use before passing to libtorrent rename_file
2011-07-13 22:39:23 +01:00
81d4b00ade Localize the Desktop file 2011-07-13 21:28:59 +01:00
1a9be0e9a4 Update Changelog, deluge.pot & gitignore 2011-07-10 17:45:37 +01:00
28fc325db9 Fix UnicodeDecodeError from 'deluge-console --help' with other languages 2011-07-10 16:30:00 +01:00
eb309813ea Fix #1505: Add libtorrent info to --version output 2011-07-09 23:09:17 +01:00
2e7bd90bda Fix #1801: ConsoleUI failed connect results in unhandled defered error and missing error message 2011-07-09 21:57:36 +01:00
f59eca4405 Fixes keyerror with existing file priorities set to High 2011-07-08 23:24:54 +01:00
fa209dfd5f Add handler for drag_data_received to supress warning 2011-07-08 23:15:15 +01:00
8e8717c867 Fix httpdownloader error with existing filename 2011-07-06 22:53:41 +01:00
8644bc219a LP Bug #496265: Peers in PeersTab show non-zero download rate when seeding 2011-07-06 21:33:02 +01:00
7c276f3133 Fix #1263: GTK UI not remembering column width
Removing a column from the treeview on shutdown causes all the
column widths to be zero which are saved to the state file.

The workaround is to not save the state file if all columns are zero.
2011-07-06 19:11:05 +01:00
ce1aca54b5 Fix #948: New Release Dialog does not show server version 2011-07-05 18:30:11 +01:00
54642720e4 Update ubuntu favicon in test_tracker_icons.py 2011-07-05 17:53:11 +10:00
18ebf5b912 Only deregister component if the registry still exists 2011-07-05 17:53:11 +10:00
ff087d133c Fix #1239: Translated Tracker Error text not counted in sidebar Error status 2011-07-04 21:20:59 +01:00
5d4c8241ea Fix translation of KiB/s 2011-07-04 21:13:44 +01:00
fbc664fa14 Fix #1258: Add Magnet and Url support to add command in console 2011-07-02 19:32:43 +01:00
cc130c0085 Fix up/down speed labels in status tab 2011-07-02 19:10:55 +01:00
87802aa965 Update Changelog 2011-07-02 18:57:57 +01:00
678be3ce15 Fix #1715: AddTorrentsDialog does not display filename changes when switching between torrents 2011-07-02 15:30:57 +01:00
52f89270e6 Fix #1582: Wrong path separator returned when moving storage in Windows 2011-07-02 15:30:57 +01:00
1a9ae62669 Fix #1338 Seeds and Peers totals not updating 2011-07-01 02:37:40 +01:00
e7b5be6a60 Fix #1477: Execute Plugin should ignore Added events from state file on startup 2011-06-30 22:38:34 +01:00
7e51c82705 Improved fix for losing Labels upon restart 2011-06-30 22:38:07 +01:00
d6e619c413 Add session_started to determine if TorrentAddedEvent is from state file 2011-06-30 22:33:48 +01:00
ba1cc6ef1f Fix #1232: Improve display of Peers Tab IPv6 addresses 2011-06-30 17:56:43 +01:00
b5a0f32826 Fix append trackers error occuring with magnet uris 2011-06-30 17:19:41 +01:00
2cceb3a349 Update append trackers commit to ignore state file adds 2011-06-28 01:42:26 +01:00
6ad3a770af Add #890: If added torrent already exists, append extra trackers to it 2011-06-28 00:53:02 +01:00
f7c21fd87b Fix #1246: Losing Labels upon restart 2011-06-27 23:09:08 +01:00
01465f583f Adjust file priorities to make Highest actually the highest allowed by libtorrent and High has been changed to what Highest was 2011-06-21 10:51:49 -07:00
d3b0df5788 Update Changelog 2011-06-20 00:18:13 +01:00
4f3c753fc1 Save and restore Preferences dialog size from config 2011-06-19 23:47:39 +01:00
6a873c524e Update potfiles and deluge.pot 2011-06-19 23:12:18 +01:00
010b6dd4af Fix preferencesmanager from failing to stop when trying to stop
loopingcall that wasn't started
2011-06-18 20:14:37 -07:00
00900fef1c Fix uri handling when dragged to gtk window 2011-06-17 22:27:39 +01:00
d2e1d66f43 Fix unhandled 'Connection was refused' error in gtkui 2011-06-17 18:00:40 +01:00
c95ca18b37 Add a file exists check to torrents passed as arg 2011-06-16 21:14:41 +01:00
34f81634e5 Fix path error with torrent files prefixed with 'file://' from Firefox 2011-06-16 21:14:41 +01:00
2cb77d17ce Increase max piece size to 16 MiB in create torrent dialog
Increasing it beyond this will require changes to
createtorrentdialog.py
2011-06-10 13:28:18 +10:00
4c32aa14d0 modify pluginbasemanager to search for egg_info dirs 2011-06-08 22:46:23 +01:00
5d9120b667 Add 2 more commands to setup.py
Two more commands were added to setup.py:
 * develop_plugins - Installs each of the plugins in development mode
 * egg_info_plugins - Create the '.egg-info' distribution directories for each plugin. This will make the plugin discoverable by deluge

Both these commands are intended to be used while developing deluge.
2011-06-08 22:26:28 +01:00
8a3bad9fc2 Fix #1456 - No ETA showing with multiple files 2011-06-05 13:10:02 +01:00
2005691312 Fix #1560 - FilesTab Progress value sorting by int instead of float 2011-06-05 13:10:02 +01:00
47c9cccd74 Merge branch 'translate_updates' into 1.3-stable 2011-06-05 00:28:20 +01:00
2186fdb870 Catch snd_path is None error in Notification Plugin 2011-06-04 23:35:03 +01:00
5b1e43735b Fix systemtray from stopping properly when appindicator is enabled 2011-06-03 14:54:36 -07:00
e54f6c84d6 Fix translations texts in glade and python files 2011-06-03 20:16:54 +01:00
30d91f17dc Remove page x from translatable in pref_diaog glade 2011-06-03 20:16:54 +01:00
af058bbdc7 Change translatable to No for gtk stock labels 2011-06-03 20:16:54 +01:00
7232dc4b01 Add gtk-* items to gettextize 2011-06-03 20:16:54 +01:00
263b10ffd2 Update gettextize to ignore .git folder 2011-06-03 20:16:54 +01:00
36d5ff5040 Fix translate string in notifications plugin 2011-06-03 20:16:54 +01:00
85d4602949 Fix translated string in addtorrentdialog 2011-06-03 20:16:54 +01:00
a75fa41c42 update create_potfiles_in to ignore plugins build dir 2011-06-03 20:16:46 +01:00
e75ae7c81e Merge branch '1.3-stable' of deluge-torrent.org:deluge into 1.3-stable 2011-06-03 09:01:48 -07:00
fad24e93f3 Update setuptools version in ez_setup 2011-06-02 21:49:27 +01:00
94d53ac368 Show errors when trying failing to properly stop a component 2011-06-02 12:04:56 -07:00
52bf08dfd1 Fix #1869: Set the disk io read/write to bypass OS cache in Windows as suggested in http://code.google.com/p/libtorrent/issues/detail?id=166 2011-05-31 09:57:59 -07:00
532973c3d1 Fix #1504 - Win32 run deluged as not logged in user via runas or service 2011-05-30 12:48:23 +01:00
254efa88e5 Add check to key_press_event for keyname returning None 2011-05-29 12:08:55 +01:00
583248f558 Allow a smtp port higher than 100
Add a shadow to scrolled window
2011-05-28 18:25:58 -07:00
69956ad1db Implemented search as you type capabilities to the treeview, ie, when the
treeview has focus and user starts typing, select the first matching
torrent name.
2011-05-28 22:12:32 +01:00
1e274cfb48 Update Changelog 2011-05-27 23:58:52 +01:00
b0e38d7bde Merge branch 'Add-F2' into 1.3-stable 2011-05-27 23:47:43 +01:00
4d643f2cba Fix #1861 - AutoAdd Warning (column number is a boolean) 2011-05-27 23:46:02 +01:00
09a56ae03c Catch an IndexError occurring in Files Tab when scrolling through long list of torrents 2011-05-27 23:46:02 +01:00
c2b5d29c6a Fix #1860 - Files Tab TypeError (could not parse subscript as a tree path) 2011-05-27 23:46:02 +01:00
a3d2b41b54 Fix #1195 - Right-click selecting issue when switching between files and folders 2011-05-27 23:46:02 +01:00
da679371b7 Add F2 key shortcut to rename files in Files Tab 2011-05-27 23:46:02 +01:00
83283cdcf3 Add XDG_DOWNLOAD_DIR for default download folder #1788 2011-05-27 23:45:54 +01:00
e180e2af88 Fix subheading in ChangeLog 2011-05-26 10:10:08 +10:00
14c3655ba1 Properly show the 'Checking Resume Data' state instead of just 7
Show the checking icon for torrents in the 'Checking Resume Data' state
2011-05-25 13:27:16 -07:00
f330469bc9 Set the WM_CLASS name to Deluge 2011-05-25 13:17:41 -07:00
c81fbf788d Update version numbers 2011-05-24 15:16:56 -07:00
a35b2497f3 Update javascript release files 2011-05-24 15:13:50 -07:00
8fe299dc21 Update translations 2011-05-24 11:49:35 -07:00
e66f0cb503 Small text updates 2011-05-24 01:58:40 +01:00
5e129b3c64 Fix up displaying versions in the about dialog 2011-05-24 01:42:35 +01:00
2d40d2b224 PEP-8 2011-05-24 01:41:15 +01:00
ce0234f0ef Change Connection Manager Key Shortcut to Ctrl-M 2011-05-23 22:20:10 +01:00
c225eae189 1862: Fix typo in move storage 2011-05-23 13:41:37 -07:00
afa941df2e Update Changelog 2011-05-23 01:22:18 +01:00
49cbcf1f9c Update certain torrentview columns to default to not visible 2011-05-23 01:00:23 +01:00
3c3b68e2cc Add ability to set columns as not visible by default by setting the kwarg default to False when adding the column 2011-05-22 15:18:17 -07:00
b93477c41e Feature #1308: Add Seeds/Peers ratio to torrent list view 2011-05-22 21:04:59 +01:00
766c48e3ca Feature #1646: Add columns for per torrent upload and download speed limits 2011-05-22 21:04:59 +01:00
1f73476dc3 Fix Up/Down buttons in Edit Trackers Dialog
This fix properly reflects the movement of the tracker in the dialog table rather than by the tracker index.
2011-05-22 21:04:41 +01:00
5bfb98f9a9 Change default value of close_to_tray to False
Prevents default install of Deluge disappearing if tray icon is missing.
2011-05-22 21:04:41 +01:00
d07b53f665 Add key shortcuts for menu items 2011-05-21 18:53:22 +01:00
449be00e33 Supress gobject warning in filtertreeview and torrentview
In console the warning "g_object_set_qdata: assertion `G_IS_OBJECT (object)' failed" will appear. Quick investigation could find no solution with suggestions a python issue.
2011-05-21 18:53:03 +01:00
655af15695 Modify setup scripts to be executable 2011-05-21 18:46:10 +01:00
a549eac063 Add --sort option to deluge-console's "info" command. 2011-05-21 18:46:10 +01:00
6fa2728ddc Add seeding_time, active_time and tracker_status to deluge-console's "info" command. 2011-05-20 19:51:33 +01:00
9060de9b70 Fix spelling error in deluge-console output. 2011-05-20 19:49:22 +01:00
57ac902d50 Updates to desktop file
Add magnet mimetype and tryexec key
Fix exec key to handle files and urls to conform with new desktop-entry spec
Update name, comment and category keys
2011-05-16 22:14:43 +01:00
05578e0c75 Fix LP Bug #779074 - TypeError in on_key_press_event(): cannot concatenate 'str' and 'NoneType' 2011-05-12 18:14:10 +01:00
a0d4141afd fix unrequired requests 2011-05-07 13:19:41 +01:00
493d0ac690 fix a bug when the host_id doesn't exist 2011-05-07 11:51:47 +01:00
fe9fe7977c update changelog 2011-05-07 00:03:27 +01:00
e579a78d26 apply patch from #1742 2011-05-07 00:02:20 +01:00
bf96475840 update changelog 2011-05-07 00:00:18 +01:00
93c49495b2 apply patch from #1548 2011-05-06 23:59:31 +01:00
54ae8a4482 update changelog 2011-05-06 23:44:19 +01:00
d658c8fe47 fix #1537 editing trackers list, trackers have to be reselected 2011-05-06 23:43:40 +01:00
58134925a2 update changelog 2011-05-06 23:25:05 +01:00
244583ef97 Fix #1333 Peer list doesn't update automatically 2011-05-06 23:24:00 +01:00
0b821640bb fix #1481 file uploads from behind a reverse proxy 2011-05-06 22:38:55 +01:00
612ed4123f fix #1323 filter panels not scrollable 2011-05-06 22:32:46 +01:00
91b9eac075 update changelog 2011-05-06 22:23:12 +01:00
5be93cd5d8 Fix #1268, Torrent errors not displayed in webui 2011-05-06 22:22:29 +01:00
816f3ff6d2 update changelog 2011-05-06 22:09:05 +01:00
2e62140d2c fix issue #1567, js from plugins not working with different base setting 2011-05-06 22:08:59 +01:00
2381b1ae28 update changelog 2011-05-06 22:03:18 +01:00
6a131f021e fix issue #1799 2011-05-06 22:00:47 +01:00
871d9ac4b0 apply patch from #1562 2011-05-06 19:14:26 +01:00
0d665d772d fix the widths on the input boxes, whitespace changes too 2011-05-06 19:02:54 +01:00
aef2a83f25 fix the path given by the set-cookie header 2011-05-03 19:05:04 +01:00
e6cd4d17ee Fix #1278 by keeping references.
Conflicts:

	deluge/ui/gtkui/menubar.py
2011-04-28 10:44:18 +01:00
b9c49f27fa Include gif pixmaps in the package data 2011-04-09 22:34:23 +10:00
e2118b6bb2 Merge branch '1.3-stable' of git.deluge-torrent.org:deluge into 1.3-stable 2011-03-28 16:51:34 +01:00
d7ba74f01d split the auto_add_trackers textfield otherwise it breaks the label plugin 2011-03-28 16:50:47 +01:00
bc9abc8bc9 Fix libtorrent not compiling with boost libs 1.46 2011-03-26 17:34:56 +11:00
00ad550a52 Improve autoadd filename matching (fixes #1614) 2011-03-26 17:34:44 +11:00
884bfd777e Apply patch from #1581 to add an option to enable the app indicator
interface
2011-03-22 17:16:03 -07:00
e7db1b285f Fix indentation on Changelog 2011-03-09 00:56:04 +11:00
ee3a17bf37 Update ChangeLog for previous commits 2011-03-09 00:51:33 +11:00
292ffb35ac Handle redirection when adding a torrent by url 2011-03-09 00:37:35 +11:00
fd458fbe64 Handle partial downloads due to incorrect headers (fixes #1517) 2011-03-09 00:05:07 +11:00
b9fdb5a65f Update translation template files 2011-02-19 11:25:00 -08:00
36f92231a6 Updated Changelog 2011-02-15 17:37:50 +00:00
6cb584d53d update changelog 2011-02-15 12:57:09 +00:00
2eb1a51f6b make the edit trackers window resizable 2011-02-15 12:54:25 +00:00
84804d37cc fix scrolling on the edit trackers window 2011-02-15 12:50:38 +00:00
1da7a518b5 Fixes for gtk-ui translations 2011-02-14 23:39:16 +00:00
808d9bfba8 Fix translate issue for Trackers tree in sidebar 2011-02-14 23:39:02 +00:00
53b4a06fd1 Fix: os.join created root path in Remove_Empty_Folder if variable 'folder' had a leading slash 2011-02-14 23:37:33 +00:00
4490cd371a Sidebar: Enabled strings for translation and added icons to Trackers filter 2011-02-11 21:48:49 +00:00
7d36a4fa51 Fix #1527 - Converting unicode to unicode error in move_storage 2011-02-11 21:48:41 +00:00
6f844a86d2 Fix Create Torrent Dialog Box - Some buttons raise Type Error if no row selected 2011-02-11 21:48:35 +00:00
03689a805b Fix #1510 - Cannot create a torrent with only non-zero tier trackers 2011-02-11 21:48:28 +00:00
1d0857964e Fix #1513: Unhandled Twisted Error in test_listen_port 2011-02-11 21:48:20 +00:00
fd3a33af03 #1514 - Indicator Applet Patch 2011-02-09 19:14:33 +00:00
2354eeca7b Fix #690 - Renaming folders does not remove old empty folders 2011-02-08 19:34:16 +00:00
ca0003a7af Catch a possible DivByZero error when moving folders around in fileview tab 2011-02-08 17:38:03 +00:00
2c615e468b Fix #1336 - Uneeded Horizontal Scrollbar shows in Files&Peers Tab 2011-02-08 17:37:53 +00:00
3794773e95 Fix #1248 - Deluge-console unicode support on redirected stdout 2011-02-08 17:01:37 +00:00
1731fd641b Fix #1506 - max speed not restored on a yellow->green transition 2011-02-08 05:00:25 +00:00
c379b6c3b2 Fix #755 - Can't set listen_ports through console UI 2011-02-05 01:08:37 +00:00
e1896d2ace Fix #1450 Trailing white space in paths 2011-02-05 01:08:36 +00:00
5f168f3a25 Fix #1500 - Console crashes on command longer than terminal width. This error is raised if the cursor is off screen and is supressed with try-except 2011-02-05 01:08:33 +00:00
8346b4bb77 Fix #1282 - Text for AutoManaged changed to 'On/Off' and localized 2011-02-05 01:08:31 +00:00
39bbe76436 Updated help text for deluge-console on Windows 2011-02-05 01:08:27 +00:00
3bd28208d1 Fix for deluge-console adding torrent files in Windows 2011-02-05 01:08:26 +00:00
ffebfb9cdf Fix #1508 - TypeError in cell_data_queue() could not convert argument to correct param type 2011-02-05 01:08:24 +00:00
93091fbe23 Fix #1373, #1386 - Creating and moving non-ascii folder names in MS Windows 2011-02-05 01:08:11 +00:00
efd2762255 Fix #1507 - Temporary file race condition in core/core.py:add_torrent_url 2011-02-05 01:08:04 +00:00
4870d34a52 #1494 - Add Downloaded and Uploaded columns to torrent view 2011-02-05 01:06:26 +00:00
26410ca9c1 Apply patch from #1194 2011-02-04 19:49:54 +00:00
c1477e45cb Fix typo 2011-01-27 11:18:40 -08:00
25e58bc8a2 Fix #1498: Use os.path.normpath on new_folder to remove any double slashes or other problems that could be in the string 2011-01-27 11:11:28 -08:00
4d2a0b1856 Fix #1484: trying to access the screen object when not using interactive mode 2011-01-16 15:58:50 -08:00
82fbbad385 fix bug #1355 2010-12-12 00:02:41 +00:00
29a306e378 Merge branch '1.3-stable' of deluge-torrent.org:deluge into 1.3-stable 2010-12-01 10:21:56 +00:00
5cfe3b5601 fix a bug that can occur when upgrading 1.1 config files 2010-12-01 10:21:26 +00:00
3f458e46dd Fix #1283 Consistent icons and add localization to file priorities
Signed-off-by: John Garland <johnnybg+deluge@gmail.com>
2010-11-11 14:02:21 +11:00
1067eb7f98 rebuild the compressed javascript 2010-11-01 09:15:19 +00:00
dca27a4cf9 update the build file to include the spinnerfieldfix file 2010-11-01 09:15:14 +00:00
b0ceae8d28 Fix copying scripts 2010-10-31 10:50:51 -07:00
dc0bf3bc88 Update versions and changelog 2010-10-31 10:15:02 -07:00
3b9d7ff9c3 remove the convert conf script that won't actually work anymore 2010-10-31 14:35:12 +00:00
a165d5d746 fix a silly bug 2010-10-31 10:13:22 +00:00
cc02ebea6a Merge branch '1.3-stable' of deluge-torrent.org:deluge into 1.3-stable 2010-10-31 09:18:36 +00:00
41ffee5d8a change entry_points to a dictionary and split it up into console and gui scripts 2010-10-31 09:16:18 +00:00
14a89b3f8a don't depend on being executed from a specific directory 2010-10-29 10:09:15 +01:00
6f0c2af58a Fix up Changelog (entry was in wrong section) 2010-10-25 09:59:06 +11:00
84cccabf19 update changelog 2010-10-24 23:44:40 +01:00
7fb483adde fix a bug in the MultiOptionsManager that didn't fire the right arguments in the initial event fire 2010-10-24 23:42:29 +01:00
28ce7a70a0 apply patch from #1377 2010-10-24 13:30:39 +01:00
14565977fa include a file that fixes the SpinnerField onBlur method (no idea why it is set to emptyFn) 2010-10-23 22:22:00 +01:00
e4420ef354 fix the path to the loading gif (not that its actually used) 2010-10-23 21:24:05 +01:00
02ad0b93ab Fix hang on quit 2010-10-23 01:14:48 +11:00
6d2a001635 Fix #1373 use of cyrllic paths 2010-10-16 12:56:29 -07:00
2a3eb0578c Fix #1349 force a theme style with expander-size = 15 to show entries in the sidebar properly. 2010-10-15 19:31:36 -07:00
60fac28217 Keep a torrent paused after a forced recheck if it was paused to start. 2010-10-10 12:34:13 -07:00
59e01e7ecf add a check to ensure that the events loop doesn't continue indefinitely 2010-10-10 19:51:50 +01:00
4c52ee4229 Update ChangeLog for previous commit 2010-10-07 22:46:49 +11:00
8428524793 wrap client.disconnect() call with a check to see if its classic mode 2010-10-07 00:14:55 +01:00
21c8d02d9a Update ChangeLog for previous commit 2010-10-03 19:52:33 +11:00
0c687c7684 Make sure config value strings are utf8 encoded (fixes #1369) 2010-10-03 19:24:29 +11:00
78f9efefd9 Move decode_string/utf8_encoded to common 2010-10-03 19:24:27 +11:00
6b228ce31f Fix sidebar not updating (#1365) 2010-10-03 00:01:29 +10:00
40ce4ec731 Use better attribute / method names in blocklist 2010-09-26 11:39:47 +10:00
c029c312e4 Fix attribute error in blocklist plugin 2010-09-26 11:37:29 +10:00
16c38cd027 Set locale to the user's default settings in the gtkui 2010-09-20 02:44:18 +10:00
e23a6b852a Organise latest changes into appropriate sections 2010-09-19 20:59:27 +10:00
90e4de54e9 Do not include unnecessary dlls in windows build 2010-09-18 16:03:21 -07:00
c1505bea3a Update versions 2010-09-18 11:31:31 -07:00
6235e832fe include missing theme images 2010-09-18 00:48:22 +10:00
a71f14c47e include the .order files 2010-09-16 09:23:35 -07:00
ed3b23b0fc add all the other scripts to package_data 2010-09-16 09:23:19 -07:00
6402634ec1 Update win32 build files 2010-09-14 11:48:05 -07:00
3e68733cfd More clean-up of setup.py 2010-09-14 11:40:41 -07:00
f847a7dc4e Remove the custom 'install' class and include_package_data 2010-09-14 11:40:34 -07:00
c7954c20eb Fix preference page index when removing a preference page 2010-09-13 18:22:08 -07:00
dc7ed11601 Update ChangeLog 2010-09-13 16:11:57 -07:00
d898def9ec Fix bugs with unicode torrents in AutoAdd plugin. 2010-09-13 02:22:18 -04:00
3e2f6c4060 Fix bug in AutoAdd plugin where watchdirs would not display in gtkui when first enabled. 2010-09-13 02:22:17 -04:00
321a22a6f0 Increase max piece size to 8 MiB in create torrent dialog (closes #1358) 2010-09-13 08:53:19 +10:00
b4774af2f3 Fix VersionSplit behavior when comparing to a dev version. 2010-09-11 05:39:40 -04:00
d0fd709c74 AutoAdd plugin can now recover when one of the watchfolders has an unhandled exception. 2010-09-03 22:30:24 -04:00
e24212b3f8 Fix "adjustment with non-zero page size" deprication warning in autoadd plugin. 2010-09-03 22:28:41 -04:00
f8f72af6dc Add TorrentFileCompleted event. 2010-09-03 17:11:57 -07:00
b9caa4eeeb Fix issue when adding torrents without a 'session'. This can happen
when a plugin adds a torrent, like how the AutoAdd plugin works.  The
user that adds this torrent will be an empty string.
2010-09-03 14:29:36 -07:00
6c3b216b40 Use a temp filename with add_torrent_url 2010-08-31 00:11:58 +10:00
eaad867885 Update get_free_space test 2010-08-31 00:11:54 +10:00
f6b9f67df8 Fix error in last commit. 2010-08-26 02:33:24 -04:00
24fe3f7fd5 Ensure preferencesmanager only changes intended libtorrent session settings. 2010-08-26 02:23:40 -04:00
da2fb41a3a Fix scheduler so that it keeps current state, even after global settings change. 2010-08-26 01:39:40 -04:00
f8d7f22167 Ignore global stop ratio related settings in logic, so per torrent ones are used. 2010-08-24 22:47:24 -04:00
b75abc70e5 Add max active downloading and seeding options to scheduler. 2010-08-24 00:58:28 -04:00
2d821bd79a Merge branch '1.3-stable' of deluge-torrent.org:deluge into 1.3-stable 2010-08-23 17:35:31 -07:00
12d9a7a5bd Fix key error after enabling a plugin that introduces a new status key 2010-08-23 17:35:19 -07:00
c118fa36a9 Moved xdg import so it is not called on Windows, where it is unused. fixes #1343 2010-08-22 15:38:22 -04:00
82c91cdc51 AutoAdd plugin changes
adds queue to top option
adds ability to append extension instead of deleting torrent once added
2010-08-22 00:01:58 -04:00
5501094214 Fix unhandled exception when adding a torrent to the session 2010-08-21 12:54:19 -07:00
b41aa808be Fix issue where the save_timer is cancelled when it's not active 2010-08-21 12:54:13 -07:00
b9336889f5 Update version 2010-08-20 14:20:51 -07:00
995f5387eb Update windows files 2010-08-20 14:19:42 -07:00
38958d3c4f Update ChangeLog 2010-08-20 14:15:21 -07:00
b45e019f08 Fix man deluged not showing '-u' on its own line 2010-08-20 01:16:09 +10:00
d93fcf6eea Fix #1341 issue where Config would try to cancel the save_timer when it is None. 2010-08-18 12:32:11 -07:00
a2d75a5274 Add cache expiry check by key update times to fix issue where some status updates would not return
correctly if they were done < cache_time from the previous status request
2010-08-18 12:17:31 -07:00
8797c3ce1b Add additional test for get_torrents_status and fix the other one to properly invalidate the cache
time from startup before proceeding
2010-08-18 12:17:23 -07:00
79749cca03 Add test to demonstrate flaw in SessionProxy design. Need to keep track of update times for each
status key individually to fix this.
2010-08-18 11:05:21 -07:00
5fd8628761 fix the script resource on windows 2010-08-14 17:38:31 +01:00
0e80b3ea0a add the apple iOS bookmark icons from #1339 2010-08-14 16:15:18 +01:00
aa61d33ee2 Merge branch '1.3-stable' of deluge-torrent.org:deluge into 1.3-stable 2010-08-14 16:06:00 +01:00
13f29a77dd fix the system.listMethods json call when running in classic mode 2010-08-14 16:05:41 +01:00
97453d1411 Add test suite for SessionProxy 2010-08-10 09:58:28 -07:00
62d02091b3 Fix getting a torrent's status with an empty key list to return all the
torrent's status keys instead of an empty dict
2010-08-06 17:26:23 -07:00
161ad0ff0d use the get_libtorrent.sh script to get libtorrent if it is missing 2010-07-22 21:13:27 +01:00
7f323ec0fc add libtorrent fetch script 2010-07-22 18:17:51 +01:00
05aebbb575 remove the libtorrent submodule 2010-07-22 18:04:49 +01:00
de85e1dcdc a couple of fixes to stop the webui crashing when running within the gtkui 2010-07-18 23:11:02 +01:00
1ce480ff23 Only use an icon if it passes some sanity checks 2010-07-17 17:13:15 +10:00
007a9912d2 Use a blank icon when the tracker icon downloaded isn't a proper image 2010-07-15 19:17:48 -07:00
d793b9e6b8 Attempt to create a move_storage destination path if it doesn't exist 2010-07-15 10:50:15 -07:00
72ec926c1a Do not attempt to move a torrents storage if the destination path does
not exist
2010-07-12 14:45:51 -07:00
0d431ae7db Try to import system rencode before deluge.rencode to allow the use of the new rencode library at: http://code.google.com/p/rencode/ 2010-07-08 16:39:53 -07:00
f1e0e3be15 Add logging the user when a torrent is added or removed 2010-07-05 21:10:16 -07:00
e8bf5eb592 Fix ChangeLog 2010-07-04 02:13:31 +10:00
d9a2c4db72 Fix uncaught exception when closing deluge in classic mode 2010-07-02 02:43:07 +10:00
8fb7277a82 Fix typo 2010-07-02 02:41:30 +10:00
35128cf18f more improvements to the shift select 2010-07-01 14:21:37 +01:00
6ff1da2391 fix select 'upwards' 2010-07-01 14:08:20 +01:00
4614188c62 update changelog 2010-07-01 13:46:27 +01:00
80297b8e45 allow for shift selecting in tree grids 2010-07-01 13:45:22 +01:00
9173a9cfdd Update Changelog 2010-06-22 18:26:43 -07:00
571d1079f6 Fix #1302 an uncaught exception in an state_changed event handler in SessionProxy was preventing the
TorrentManager's stop method from properly saving all the resume data.
2010-06-22 18:25:50 -07:00
0497c407e1 Always look for -mt boost libraries first 2010-06-18 09:51:50 -07:00
8b58c960f3 fix typo 2010-06-12 22:48:00 +01:00
b615ebe1b8 change bits to bytes, thanks to charles 2010-06-11 15:59:33 +01:00
3ed8279219 Fix typo in label plugin - thanks konti 2010-06-11 00:51:46 +10:00
f2944bdeef Handle os.remove failing on windows 2010-06-08 03:20:48 +10:00
0fcd90ee2c Python independent version of previous commit 2010-06-08 01:57:13 +10:00
26460808e7 Fix console ui not liking paths with backslashes on windows (#1293) 2010-06-08 01:30:10 +10:00
7aba1af0b2 Print a more informative error message if the torrent file doesn't exist 2010-06-08 01:26:49 +10:00
4d2b7df49d Fix execute plugin only executing last event (#1306) 2010-06-08 00:20:07 +10:00
bd775d0d40 Only encode if necessary 2010-06-07 20:18:37 +10:00
7fb3c3c04c Fix unicode support in console ui (#1307) 2010-06-07 20:18:35 +10:00
19c27ee8c5 Add some debug logging statements 2010-06-04 18:05:27 +01:00
d69b8e1099 Fix an error in the key 2010-06-04 17:37:45 +01:00
88daf82cb0 Fix saving the correct event name 2010-06-04 16:37:50 +01:00
99c1a61383 Save the execute config after adding/removing/saving commands 2010-06-04 16:30:51 +01:00
2e55769c18 Fix typo in execute plugin 2010-05-20 00:06:18 +10:00
259d2633e7 Fix man deluged not showing '-d' on its own line 2010-05-16 22:32:59 +10:00
8e5aab660c Fix remote save path dialog not disappearing after creating a torrent 2010-05-16 18:13:34 +10:00
fc96e9d02c Fix only being able to click "remote path" once when creating a torrent 2010-05-16 18:13:31 +10:00
821d403a6c Fix deluged crashing on windows when logfile's directory doesn't exist 2010-05-16 13:12:51 +10:00
5e0d988ef0 Revert "Fix trac wiki turning CamelCase words into broken links"
This reverts commit 925ac42f7c.
2010-05-11 23:46:48 +10:00
925ac42f7c Fix trac wiki turning CamelCase words into broken links 2010-05-11 23:29:02 +10:00
1ac72b81b6 Update email address and copyright 2010-05-11 03:52:17 +10:00
3417caf1d2 Fix label plugin not remembering newly created labels 2010-05-09 17:52:29 +10:00
1bcfc91c35 Remove unused code from label plugin 2010-05-09 17:52:25 +10:00
6ee0e5b6be Update docstrings to use names from previous commit 2010-05-09 17:07:11 +10:00
58a74202e1 Use better names for TrackerIcons' args 2010-05-09 17:01:47 +10:00
a4c6f4e8c9 Return the noIcon for empty strings as well 2010-05-09 16:44:12 +10:00
60f3d32de7 Raise IconsError instead of IndexError (fixes infinite looping) 2010-05-09 16:36:54 +10:00
b3eed8a1f0 Add test for tracker_icons for when requesting an icon for host that is "". This test results in an infinite loop. 2010-05-08 20:10:12 -07:00
37137d9b54 Return 0 in get_free_space if the download_location is invalid 2010-05-08 20:09:57 -07:00
4fb14b581d Use previously defined host variable instead of getting the tracker host from the TreeModel 2010-05-08 20:09:49 -07:00
98da4d0291 Do not request a tracker icon if the host is "" 2010-05-08 20:09:37 -07:00
f0c06f4bc5 Update Changelog 2010-05-08 11:50:19 -07:00
63d701305c rebuild deluge-all and ext-extensions 2010-05-08 16:19:40 +01:00
99396afa0c update the build files for deluge-all and ext-extensions 2010-05-08 16:19:40 +01:00
6231dbd1ca fix the null comparison 2010-05-08 16:19:40 +01:00
8f021c7f06 set the baseCls for the add label form panel to x-plain 2010-05-08 16:19:40 +01:00
6bb4559d18 Make host_to_url support redirection and add another test 2010-05-08 16:26:08 +10:00
7c9eea0361 Try favicon.ico if there's a HTMLParseError 2010-05-08 15:50:57 +10:00
15247507d4 Fix relative redirecting in blocklist plugin 2010-05-06 23:31:25 +10:00
10de8d5475 Remove plugins that aren't release ready 2010-05-05 17:48:04 -07:00
e304c1f719 update the ChangeLog 2010-05-05 23:03:19 +01:00
48d3e89d84 Update windows build files 2010-05-05 15:01:52 -07:00
44f9e17a09 Update version
Update ChangeLog
2010-05-05 14:52:18 -07:00
497 changed files with 292214 additions and 177152 deletions

27
.gitattributes vendored
View File

@ -1,9 +1,24 @@
/libtorrent export-ignore
/win32 export-ignore
docs/build export-ignore
docs/source export-ignore
/tests export-ignore
deluge/scripts export-ignore
/libtorrent/ export-ignore
/win32/ export-ignore
/osx/ export-ignore
docs/build/ export-ignore
docs/source/ export-ignore
/tests/ export-ignore
deluge/scripts/ export-ignore
setup.cfg export-ignore
check_glade.sh export-ignore
createicons.sh export-ignore
create_potfiles_in.py export-ignore
gettextize.sh export-ignore
deluge/i18n/deluge.pot export-ignore
deluge/ui/web/css/*-debug.css export-ignore
deluge/ui/web/js/*-debug.js export-ignore
deluge/ui/web/js/deluge-all/ export-ignore
deluge/ui/web/js/ext-extensions/ export-ignore
deluge/ui/web/gen_gettext.py export-ignore
deluge/ui/web/build export-ignore
deluge/ui/web/docs/ export-ignore
.gitattributes export-ignore
.gitmodules export-ignore
.gitignore export-ignore

4
.gitignore vendored
View File

@ -7,3 +7,7 @@ dist
*.pyc
*.tar.*
_trial_temp
deluge/i18n/*/
*.desktop
.build_data*
osx/app

3
.gitmodules vendored
View File

@ -1,3 +0,0 @@
[submodule "libtorrent"]
path = libtorrent
url = git://deluge-torrent.org/libtorrent

797
AUTHORS Normal file
View File

@ -0,0 +1,797 @@
Authors:
* Andrew Resch ('andar') <andrewresch@gmail.com>
* Damien Churchill ('damoxc') <damoxc@gmail.com>
Main Developers:
* Andrew Resch
* Damien Churchill
* John Garland ('johnnyg') <johnnybg+deluge@gmail.com>
* Calum Lind ('cas') <calumlind+deluge@gmail.com>
libtorrent (http://www.libtorrent.org):
* Arvid Norberg
Contributors (and Past Developers):
* Zach Tibbitts <zach@collegegeek.org>
* Alon Zakai ('Kripken') <kripkensteiner@gmail.com>
* Marcos Mobley ('markybob') <markybob@gmail.com>
* Alex Dedul
* Sadrul Habib Chowdhury
* Ido Abramovich <ido.deluge@gmail.com>
* Martijn Voncken <mvoncken@gmail.com>
* Mark Stahler ('kramed') <markstahler@gmail.com>
* Pedro Algarvio ('s0undt3ch') <ufs@ufsoft.org>
* Cristian Greco ('cgreco') <cristian@regolo.cc>
* Chase Sterling ('gazpachoKing') <chase.sterling@gmail.com>
Plugin Developers:
* Autoadd : Chase Sterling
* Blocklist : John Garland
* Execute : Damien Churchill
* Extractor : Andrew Resch
* Label : Martijn Voncken
* Notifications : Pedro Algarvio
* Scheduler : Andrew Resch
* Webui : Damien Churchill
Images Authors:
* files: deluge/data/pixmaps/*.svg, *.png
deluge/ui/web/icons/active.png, alert.png, all.png, checking.png, dht.png,
downloading.png, inactive.png, queued.png, seeding.png, traffic.png
exceptions: deluge/data/pixmaps/deluge.svg and derivatives
copyright: Andrew Resch
license: GPLv3
* files: deluge/data/pixmaps/deluge.svg and derivatives
deluge/ui/web/icons/apple-pre-*.png, deluge*.png
deluge/ui/web/images/deluge*.png
copyright: Andrew Wedderburn
license: GPLv3
* files: deluge/plugins/blocklist/blocklist/data/*.png
deluge/data/pixmaps/tracker_warning16.png, tracker_all16.png, lock48.png
copyright: Gnome Icon Theme
license: GPLv2
url: http://ftp.acc.umu.se/pub/GNOME/sources/gnome-icon-theme
* files: deluge/data/pixmaps/magnet.png
copyright: Woothemes
license: Freeware
icon pack: WP Woothemes Ultimate
url: http://www.woothemes.com/
* files: deluge/data/pixmaps/flags/*.png
copyright: Mark James <mjames@gmail.com>
license: Public Domain
url: http://famfamfam.com/lab/icons/flags/
* files: deluge/ui/web/icons/*.png
exceptions: apple-pre-*.png, active.png, alert.png, all.png, deluge.png, dht.png,
downloading.png, inactive.png, queued.png, seeding.png, traffic.png
copyright: Yusuke Kamiyamane <p@yusukekamiyamane.com>
license: Creative Commons Attribution 3.0 License
url: http://p.yusukekamiyamane.com/
* files: deluge/ui/web/images/spinner.gif, spinner-split.gif
copyright: Steven Chim
license: BSD license
url: http://members.upc.nl/j.chim/ext/spinner2/ext-spinner.html
Translation Contributors:
* files: deluge/i18n/*.po
Aaron Wang Shi
abbigss
ABCdatos
Abcx
Actam
Adam
adaminikisi
adi_oporanu
Adrian Goll
afby
Ahmades
Ahmad Farghal
Ahmad Gharbeia أحمد غربية
akira
Aki Sivula
Alan Pepelko
Alberto
Alberto Ferrer
alcatr4z
AlckO
Aleksej Korgenkov
Alessio Treglia
Alexander Ilyashov
Alexander Matveev
Alexander Saltykov
Alexander Taubenkorb
Alexander Telenga
Alexander Yurtsev
Alexandre Martani
Alexandre Rosenfeld
Alexandre Sapata Carbonell
Alexey Osipov
Alin Claudiu Radut
allah
AlSim
Alvaro Carrillanca P.
A.Matveev
Andras Hipsag
András Kárász
Andrea Ratto
Andreas Johansson
Andreas Str
André F. Oliveira
AndreiF
andrewh
Angel Guzman Maeso
Aníbal Deboni Neto
animarval
Antonio Cono
antoniojreyes
Anton Shestakov
Anton Yakutovich
antou
Arkadiusz Kalinowski
Artin
artir
Astur
Athanasios Lefteris
Athmane MOKRAOUI (ButterflyOfFire)
Augusta Carla Klug
Avoledo Marco
axaard
AxelRafn
Axezium
Ayont
b3rx
Bae Taegil
Bajusz Tamás
Balaam's Miracle
Ballestein
Bent Ole Fosse
berto89
bigx
Bjorn Inge Berg
blackbird
Blackeyed
blackmx
BlueSky
Blutheo
bmhm
bob00work
boenki
Bogdan Bădic-Spătariu
bonpu
Boone
boss01
Branislav Jovanović
bronze
brownie
Brus46
bumper
butely
BXCracer
c0nfidencal
Can Kaya
Carlos Alexandro Becker
cassianoleal
Cédric.h
César Rubén
chaoswizard
Chen Tao
chicha
Chien Cheng Wei
Christian Kopac
Christian Widell
Christoffer Brodd-Reijer
christooss
CityAceE
Clopy
Clusty
cnu
Commandant
Constantinos Koniaris
Coolmax
cosmix
Costin Chirvasuta
CoVaLiDiTy
cow_2001
Crispin Kirchner
crom
Cruster
Cybolic
Dan Bishop
Danek
Dani
Daniel Demarco
Daniel Ferreira
Daniel Frank
Daniel Holm
Daniel Høyer Iversen
Daniel Marynicz
Daniel Nylander
Daniel Patriche
Daniel Schildt
Daniil Sorokin
Dante Díaz
Daria Michalska
DarkenCZ
Darren
Daspah
David Eurenius
davidhjelm
David Machakhelidze
Dawid Dziurdzia
Daya Adianto
dcruz
Deady
Dereck Wonnacott
Devgru
Devid Antonio FiloniDevilDogTG
di0rz`
Dialecti Valsamou
Diego Medeiros
Dkzoffy
Dmitrij D. Czarkoff
Dmitriy Geels
Dmitry Olyenyov
Dominik Kozaczko
Dominik Lübben
doomster
Dorota Król
Doyen Philippe
Dread Knight
DreamSonic
duan
Duong Thanh An
DvoglavaZver
dwori
dylansmrjones
Ebuntor
Edgar Alejandro Jarquin Flores
Eetu
ekerazha
Elias Julkunen
elparia
Emberke
Emiliano Goday Caneda
EndelWar
eng.essam
enubuntu
ercangun
Erdal Ronahi
ergin üresin
Eric
Éric Lassauge
Erlend Finvåg
Errdil
ethan shalev
Evgeni Spasov
ezekielnin
Fabian Ordelmans
Fabio Mazanatti
Fábio Nogueira
FaCuZ
Felipe Lerena
Fernando Pereira
fjetland
Florian Schäfer
FoBoS
Folke
Force
fosk
fragarray
freddeg
Frédéric Perrin
Fredrik Kilegran
FreeAtMind
Fulvio Ciucci
Gabor Kelemen
Galatsanos Panagiotis
Gaussian
gdevitis
Georg Brzyk
George Dumitrescu
Georgi Arabadjiev
Georg Sieber
Gerd Radecke
Germán Heusdens
Gianni Vialetto
Gigih Aji Ibrahim
Giorgio Wicklein
Giovanni Rapagnani
Giuseppe
gl
glen
granjerox
Green Fish
greentea
Greyhound
G. U.
Guillaume BENOIT
Guillaume Pelletier
Gustavo Henrique Klug
gutocarvalho
Guybrush88
Hans Rødtang
HardDisk
Hargas Gábor
Heitor Thury Barreiros Barbosa
helios91940
helix84
Helton Rodrigues
Hendrik Luup
Henrique Ferreiro
Henry Goury-Laffont
Hezy Amiel
hidro
hoball
hokten
Holmsss
hristo.num
Hubert Życiński
Hyo
Iarwain
ibe
ibear
Id2ndR
Igor Zubarev
IKON (Ion)
imen
Ionuț Jula
Isabelle STEVANT
István Nyitrai
Ivan Petrovic
Ivan Prignano
IvaSerge
jackmc
Jacks0nxD
Jack Shen
Jacky Yeung
Jacques Stadler
Janek Thomaschewski
Jan Kaláb
Jan Niklas Hasse
Jasper Groenewegen
Javi Rodríguez
Jayasimha (ಜಯಸಿಂಹ)
jeannich
Jeff Bailes
Jesse Zilstorff
Joan Duran
João Santos
Joar Bagge
Joe Anderson
Joel Calado
Johan Linde
John Garland
Jojan
jollyr0ger
Jonas Bo Grimsgaard
Jonas Granqvist
Jonas Slivka
Jonathan Zeppettini
Jørgen
Jørgen Tellnes
josé
José Geraldo Gouvêa
José Iván León Islas
José Lou C.
Jose Sun
Jr.
Jukka Kauppinen
Julián Alarcón
julietgolf
Jusic
Justzupi
Kaarel
Kai Thomsen
Kalman Tarnay
Kamil Páral
Kane_F
kaotiks@gmail.com
Kateikyoushii
kaxhinaz
Kazuhiro NISHIYAMA
Kerberos
Keresztes Ákos
kevintyk
kiersie
Kimbo^
Kim Lübbe
kitzOgen
Kjetil Rydland
kluon
kmikz
Knedlyk
koleoptero
Kőrösi Krisztián
Kouta
Krakatos
Krešo Kunjas
kripken
Kristaps
Kristian Øllegaard
Kristoffer Egil Bonarjee
Krzysztof Janowski
Krzysztof Zawada
Larry Wei Liu
laughterwym
Laur Mõtus
lazka
leandrud
lê bình
Le Coz Florent
Leo
liorda
LKRaider
LoLo_SaG
Long Tran
Lorenz
Low Kian Seong
Luca Andrea Rossi
Luca Ferretti
Lucky LIX
Luis Gomes
Luis Reis
Łukasz Wyszyński
luojie-dune
maaark
Maciej Chojnacki
Maciej Meller
Mads Peter Rommedahl
Major Kong
Malaki
malde
Malte Lenz
Mantas Kriaučiūnas
Mara Sorella
Marcin
Marcin Falkiewicz
marcobra
Marco da Silva
Marco de Moulin
Marco Rodrigues
Marcos
Marcos Escalier
Marcos Mobley
Marcus Ekstrom
Marek Dębowski
Mário Buči
Mario Munda
Marius Andersen
Marius Hudea
Marius Mihai
Mariusz Cielecki
Mark Krapivner
marko-markovic
Markus Brummer
Markus Sutter
Martin
Martin Dybdal
Martin Iglesias
Martin Lettner
Martin Pihl
Masoud Kalali
mat02
Matej Urbančič
Mathias-K
Mathieu Arès
Mathieu D. (MatToufoutu)
Mathijs
Matrik
Matteo Renzulli
Matteo Settenvini
Matthew Gadd
Matthias Benkard
Matthias Mailänder
Mattias Ohlsson
Mauro de Carvalho
Max Molchanov
Me
MercuryCC
Mert Bozkurt
Mert Dirik
MFX
mhietar
mibtha
Michael Budde
Michael Kaliszka
Michalis Makaronides
Michał Tokarczyk
Miguel Pires da Rosa
Mihai Capotă
Miika Metsälä
Mikael Fernblad
Mike Sierra
mikhalek
Milan Prvulović
Milo Casagrande
Mindaugas
Miroslav Matejaš
misel
mithras
Mitja Pagon
M.Kitchen
Mohamed Magdy
moonkey
MrBlonde
muczy
Münir Ekinci
Mustafa Temizel
mvoncken
Mytonn
NagyMarton
neaion
Neil Lin
Nemo
Nerijus Arlauskas
Nicklas Larsson
Nicolaj Wyke
Nicola Piovesan
Nicolas Sabatier
Nicolas Velin
Nightfall
NiKoB
Nikolai M. Riabov
Niko_Thien
niska
Nithir
noisemonkey
nomemohes
nosense
null
Nuno Estêvão
Nuno Santos
nxxs
nyo
obo
Ojan
Olav Andreas Lindekleiv
oldbeggar
Olivier FAURAX
orphe
osantana
Osman Tosun
OssiR
otypoks
ounn
Oz123
Özgür BASKIN
Pablo Carmona A.
Pablo Ledesma
Pablo Navarro Castillo
Paco Molinero
Pål-Eivind Johnsen
pano
Paolo Naldini
Paracelsus
Patryk13_03
Patryk Skorupa
PattogoTehen
Paul Lange
Pavcio
Paweł Wysocki
Pedro Brites Moita
Pedro Clemente Pereira Neto
Pekka "PEXI" Niemistö
Penegal
Penzo
perdido
Peter Kotrcka
Peter Skov
Peter Van den Bosch
Petter Eklund
Petter Viklund
phatsphere
Phenomen
Philipi
Philippides Homer
phoenix
pidi
Pierre Quillery
Pierre Rudloff
Pierre Slamich
Pietrao
Piotr Strębski
Piotr Wicijowski
Pittmann Tamás
Playmolas
Prescott
Prescott_SK
pronull
Przemysław Kulczycki
Pumy
pushpika
PY
qubicllj
r21vo
Rafał Barański
rainofchaos
Rajbir
ras0ir
Rat
rd1381
Renato
Rene Hennig
Rene Pärts
Ricardo Duarte
Richard
Robert Hrovat
Roberth Sjonøy
Robert Lundmark
Robin Jakobsson
Robin Kåveland
Rodrigo Donado
Roel Groeneveld
rohmaru
Rolf Christensen
Rolf Leggewie
Roni Kantis
Ronmi
Rostislav Raykov
royto
RuiAmaro
Rui Araújo
Rui Moura
Rune Svendsen
Rusna
Rytis
Sabirov Mikhail
salseeg
Sami Koskinen
Samir van de Sand
Samuel Arroyo Acuña
Samuel R. C. Vale
Sanel
Santi
Santi Martínez Cantelli
Sardan
Sargate Kanogan
Sarmad Jari
Saša Bodiroža
sat0shi
Saulius Pranckevičius
Savvas Radevic
Sebastian Krauß
Sebastián Porta
Sedir
Sefa Denizoğlu
sekolands
Selim Suerkan
semsomi
Sergii Golovatiuk
setarcos
Sheki
Shironeko
Shlomil
silfiriel
Simone Tolotti
Simone Vendemia
sirkubador
Sławomir Więch
slip
slyon
smoke
Sonja
spectral
spin_555
spitf1r3
Spiziuz
Spyros Theodoritsis
SqUe
Squigly
srtck
Stefan Horning
Stefano Maggiolo
Stefano Roberto Soleti
steinberger
Stéphane Travostino
Stephan Klein
Steven De Winter
Stevie
Stian24
stylius
Sukarn Maini
Sunjae Park
Susana Pereira
szymon siglowy
takercena
TAS
Taygeto
temy4
texxxxxx
thamood
Thanos Chatziathanassiou
Tharawut Paripaiboon
Theodoor
Théophane Anestis
Thor Marius K. Høgås
Tiago Silva
Tiago Sousa
Tikkel
tim__b
Tim Bordemann
Tim Fuchs
Tim Kornhammar
Timo
Timo Jyrinki
Timothy Babych
TitkosRejtozo
Tom
Tomas Gustavsson
Tomas Valentukevičius
Tomasz Dominikowski
Tomislav Plavčić
Tom Mannerhagen
Tommy Mikkelsen
Tom Verdaat
Tony Manco
Tor Erling H. Opsahl
Toudi
tqm_z
Trapanator
Tribaal
Triton
TuniX12
Tuomo Sipola
turbojugend_gr
Turtle.net
twilight
tymmej
Ulrik
Umarzuki Mochlis
unikob
Vadim Gusev
Vagi
Valentin Bora
Valmantas Palikša
VASKITTU
Vassilis Skoullis
vetal17
vicedo
viki
villads hamann
Vincent Garibal
Vincent Ortalda
vinchi007
Vinícius de Figueiredo Silva
Vinzenz Vietzke
virtoo
virtual_spirit
Vitor Caike
Vitor Lamas Gatti
Vladimir Lazic
Vladimir Sharshov
Wanderlust
Wander Nauta
Ward De Ridder
WebCrusader
webdr
Wentao Tang
wilana
Wilfredo Ernesto Guerrero Campos
Wim Champagne
World Sucks
Xabi Ezpeleta
Xavi de Moner
XavierToo
XChesser
Xiaodong Xu
xyb
Yaron
Yasen Pramatarov
YesPoX
Yuren Ju
Yves MATHIEU
zekopeko
zhuqin
Zissan
Γιάννης Κατσαμπίρης
Артём Попов
Миша
Шаймарданов Максим
蔡查理

581
ChangeLog
View File

@ -1,4 +1,563 @@
=== Deluge 1.3.0 (In Development) ===
=== Deluge 1.3.14 (6 March 2017) ===
==== Core ====
* #2889: Fixed 'Too many files open' errors.
* #2861: Added support for python-geoip for use with libtorrent 1.1.
* #2149: Fixed a single proxy entry being overwritten resulting in no proxy set.
==== UI ====
* Added tracker_status translation to UIs.
==== GtkUI ====
* #2901: Strip whitespace from infohash before checks.
* Add missed feature autofill infohash entry from clipboard.
==== WebUI ====
* #1908: Backport bind interface option for server.
* Security: Fixed WebUI CSRF Vulnerability.
==== ConsoleUI ====
* [#2948] [Console] Fix decode error comparing non-ascii (str) torrent name.
==== AutoAdd Plugin ====
* Fixes for splitting magnets from file.
* Remove duplicate magnet extension when splitting.
=== Deluge 1.3.13 (20 July 2016) ===
==== Core ====
* Increase RSA key size from 1024 to 2048 and use SHA256 digest.
* Fixed empty error message from certain trackers.
* Fixed torrent ending up displaying the wrong state.
* #1032: Force a torrent into Error state if the resume data is rejected.
* Workaround unwanted tracker announce when force rechecking paused torrent.
* #2703: Stop moving torrent files if target files exist to prevent unintended clobbering of data.
* #1330: Fixed the pausing and resuming of the Deluge session so torrents return to previous state.
* #2765: Add support for TLS SNI in httpdownloader.
* #2790: Ensure base32 magnet hash is uppercase to fix lowercase magnets uris.
==== Daemon ====
* New command-line option to restict selected config key to read-only.
* Allow use of uppercase log level to match UIs.
==== UI ====
* #2832: Fixed error with blank lines in auth file.
==== GtkUI ====
* Fixed installing plugin from a non-ascii directory.
* Error'd torrents no longer display a progress percentage.
* #2753: Fixed the 'Added' column showing the wrong date.
* #2435: Prevent the user from changing tracker selection when editing trackers.
* Fixed showing the wrong connected status with hostname in the Connection Manager.
* #2754: Fixed the progress column to sort by progress and state correctly.
* #2696: Fixed incorrect Move Completed folder shown in Options tab.
* #2783: Sorting for name column is now case insensitive.
* #2795: Reduce height of Add Torrent Dialog to help with smaller screeen resoltuions.
* OSX: Fixed empty scrolling status (systray) menu.
* OSX: Fixed starting deluged from connection manager.
* #2093: Windows OS: Fixed opening non-ascii torrent files.
* #2855: Fixed adding UDP trackers to trackers dialog.
==== WebUI ====
* #2782: Fixed HTTPS negotiating incorrect cipher.
* #2485: Fixed the broken Options context menu.
* #2705: Fixed the hostlist config file not being created.
* #2293: Fixed plugin's js code not loading when using the WebUI plugin.
==== Console ====
* Fixed adding non-ascii torrent in non-interactive mode.
* #2796: Add time_added to info sort keys.
* #2815: Fixed 'add' cmd path inconsistency on Windows.
==== OSX Packaging ====
* Source .py files no longer included in Deluge.app.
==== Windows OS Packaging ====
* #2777: Updated MSVC SP1 check to latest release CLID.
==== Blocklist Plugin ====
* #2729: Fixed plugin lockup with empty url.
==== Scheduler Plugin ====
* Fixed corrupt plugin prefences page on OSX.
* Fixed error accidentally introduced in 1.3.12.
==== Notification Plugin ====
* #2402: Fixed the popup to show the actual count of files finished.
* #2857: Fixed issue with SMTP port entry not updating in GTKUI.
==== AutoAdd Plugin ====
* Fixed watch dir not accepting uppercase file extension.
==== Extractor Plugin ====
* Ignore the remaining rar part files to prevent spawning useless processes.
* #2785: Fixed only an empty folder when extracting rar files.
==== Execute Plugin ====
* #2784: Windows OS: Escape ampersand in torrent args.
=== Deluge 1.3.12 (13 September 2015) ===
==== GtkUI ====
* #2731: Fix potential AttributeError in is_on_active_workspace
==== Core ====
* Include fix for Twisted 15.0 URI class rename
* #2233: Fix AttributeError in set_trackers with lt 1.0
* Enable lt extension bindings again for versions >=0.16.7 (this disables Tracker Exchange by default)
* Backport atomic fastresume and state file saving fixes as another attempt to prevent data loss on unclean exits
==== WebUI ====
* Fixed i18n issue in Connection Manager which left users unable to connect
* #2295: Increase cookie lifespan for display settings
==== Console ====
* #2333: Fixed 'set and then get' in config command
==== Scheduler Plugin ====
* Show current speed limit in statusbar
==== Win32 Packaging ====
* #2736: Added version info to the properties of Deluge exes
* #2734: Added a 256x256 to deluge.ico
* #2325: Fixed the uninstaller deleting non-deluge files
* Include pillow module to enable resizing of tracker icons
=== Deluge 1.3.11 (30 November 2014) ===
==== GtkUI ====
* Fixed ImportError for users with Twisted < 10
* #2698: Fixed column issue when disabling a plugin
==== Core ====
* Fixed cache issue with libtorrent 0.16 on Windows
* #2555: Disabled use of SSLv3 protocol for DelugeRPC
==== WebUI ====
* Modify SSL Context to allow >= TLSv1 protocol
* #2588: Fixed Size column to show total_wanted instead of total_size
=== Deluge 1.3.10 (15 October 2014) ===
==== GtkUI ====
* #2256: Indexes are not updated correctly when removing column
* Fix bug in the torrentview when Plugins added a column
==== WebUI ====
* Security update for POODLE vulnerability
=== Deluge 1.3.9 (4 October 2014) ===
==== GtkUI ====
* #2514: Fix every torrent is displayed twice in classic mode
=== Deluge 1.3.8 (4 October 2014) ===
==== Core ====
* #1126 & #2322: Emit FinishedEvent after moving storage complete
* Fixes to mitigate fastresume corruption
==== GtkUI ====
* #2335: Fix application startup failing with 'cannot acquire lock' error
* #2497: Fix the Queued Torrents 'Clear' button not properly clearing the list of torrent
* #2496: Fix updating core_config before setting default options
* #2493: Fix TypeError if active workspace is None
* LP:#1168858: Nautilus window opens behind current window
* Fix showing the open_folder menuitem
* Suppress unimportant gnome warnings
* Optimized the updating of the torrent view
* Fixed Indicator icon label issue
* Fix listview error with new config
==== WebUI ====
* Ensure values are updated from config upon showing a plugin page
==== Extractor ====
* Add WebUI plugin page
* Find 7-zip application path on Windows via registry
==== Execute ====
* #1290: Add a TorrentRemoved event option
==== Scheduler ====
* #2238: Fix an 'undefined this.scheduleCells' error in javascript console
==== Notifications ====
* #1310: Add WebUI plugin page
==== Blocklist ====
* #2478: Add WebUI plugin page
==== Console ====
* #2470: Fix console parsing args
=== Deluge 1.3.7 (9 July 2014) ===
==== Core ====
* #2324: Encryption level set by Deluge did not match libtorrent values
* #2303: Torrent state was not updated until after emitting TorrentFinishedEvent
* Fix twisted 13.1 compatability
* #2343: Fix error if listen interface is whitespace
* #2082: Validate ip address for listen_interface entry
* #1490: Increase the Alertmanager interval to 0.3s
* Prevent private flagged torrents auto-merging trackers
==== GtkUI ====
* Fix issue with Plugins that add Tab to torrentdetails
* Fix the scalable icon install directory
* #2335: Fix IPC lockfile issue preventing start of deluge-gtk
* #2365: Fix hiding Progress column generating TypeError
* #2371: Add StartupWMClass to desktop file
* #2372: Fix the Ratio column not retaining position
* #2369: Fix bypassing the password dialog when showing/quitting
==== WebUI ====
* #2374: Fix right-click selection issue
* #2310: Fix unicode password support
* #2418: Fix WebUI error when adding non-ascii torrent
==== Windows OS ====
* Allow silent uninstall for Windows package
* #2367: Fix DelugeStart theme not showing Private Flag as ticked/checked
* #2315: Potential fix for lost window issue
==== Extractor ====
* #2290: Fix dotted filenames being rejected
=== Deluge 1.3.6 (25 Feburary 2013) ===
==== Core ====
* Catch & log KeyError when removing a torrent from the queued torrents set
* Fix moving/renaming torrents issues when using libtorrent 0.16
* Make sure queue order is preserved when restarting
* #2160: Disable use of python bindings for libtorrent extensions and replace with session flag
* #2163: Fix unable add torrent file with empty (0:) encoding tag
* #2201: Fix error in authmanager if auth file has extra newlines
* #2109: Fix the Proxy settings not being cleared by setting None
* #2110: Fix accepting magnet uris with xt param anywhere within them
* #2204: Fix daemon shutdown hang with large numbers of torrents
* Fix prioritize first/last pieces option for magnet links
==== Client ====
* Fix keyerrors after removing torrents from UIs
==== GtkUI ====
* Add move completed option to add torrent dialog
* Prevent jitter in torrent view
* Fix torrent creation with non-ascii characters
* Fix #2100 : Add option not to bring main window to front when adding torrents through ipcinterface
* Add Quit Dialog when toggling classic mode in preferences and only show connection manager when not in classic mode.
* #2169: Fix 'Download Location' in the Add Torrent Dialog not set correctly when folder typed into Other->Location field
* #2171: Fix the Add Peer dialog not responding if empty or invalid values entered
* #2104: Fix no title set for the appindicator
* #2086: Fix submenus and icons for appindicator
* #2146: Fix missing translations in View|Tabs submenu
* Fix torrent names on libtorrent 0.16 on windows
* #2147: Fix missing translations for plugin preferences page
* #1474: Fix the on_show_prefs hook not being executed immediatly after enabling a plugin
* #1946: Fix ReactorNotRestartable error when set as startup application
* #2130: Fix same name can be given to different files in Add Torrent dialog
* #2129: Fix empty filename able to be set in AddTorrent dialog
* #2228: Fix Apply-To-All in AddTorrent Dialog copying file renames to other torrents
* #2260: Fix the Add Torrent dialog also bringing the main window to active workspace
* Fix showing exception error to user in Classic Mode with no libtorrent installed
==== Console ====
* LP#1004793: Enable use of connect command in non-interactive mode
* Ensure console commands are executed in order
* #2065: Fix crash with missing closing quote
* #1397: Add support for -s STATE in info command
==== WebUI ====
* Add move completed option to add torrent dialog
* #2112: Fix world readable tmp directory in json_api
* #2069: Fix login window layout problem when using larger than default font size
* #1890: Fix columns in files and peers view could use some spacing
* #2103: Fix sorting by name is case-sensitive [sedulous]
* #2120: Fix manually entered values not being saved in spinners
* #2212: Fix unable to scroll in proxy preferences page
* Fix autoconnecting to the default host
* #2046: Fix plugins not enabling properly until after refreshing page
* #2125: Fix plugin methods not being available when enabled until restart
* #2085: Fix not showing torrents in sidebar for categories other than 'All' in classic mode
* #2232: Fix flag icon path in Peers Tab missing deluge.config.base
* Fix submenus closing upon mouse click
* Add failed login log message, including IP address, to enable use with fail2ban
* #2261: Fix Proxy settings not being saved in preferences
==== Windows OS ====
* Hide the cmd windows when running deluged.exe or deluge-web.exe
* Add deluged-debug.exe and deluge-web-debug.exe that still show the cmd window
* Add gtk locale files to fix untranslated text
* Fix the Open Folder option not working with non-ascii paths
* Fix the daemon starting with config dir containing spaces
* Fix Windows tray submenu items requiring right-click instead of left-click
* Fix issue with adding some torrents with illegal characters via url in gtk client
* #2240: Fix freespace issue with large capacity drives
==== OS X ====
* Fix Open File/Folder option
* Add OS X Menu for GTK Quartz
==== Execute ====
* Fix execute plugin not working with unicode torrent names
==== Extractor ====
* Add Windows support, using 7-zip
* Added support for more extensions
* Disabled extracting 'Move Completed' torrents due to race condition
=== Deluge 1.3.5 (09 April 2012) ===
==== Core ====
* Fix not properly detecting when torrent is at end of queue
* #2049: Preserve order when moving multiple torrents in the queue
==== GtkUI ====
* Modified fix for #1957, keyerror with non-acsii columns
* Fix translation of items in Sidebar and Torrent Menu
* #2052: Fix translation of Progress bar text
* #2071: Fix KeyError in gtkui when file priority set to value '3'
* #2064: Fix files treeview height in Create Dialog
* Fix missing semi-colon in deluge.desktop
* Disable setting file priorities for seeding torrents
* Bring MainWindow to front when opening another instance
==== WebUI ====
* #2050: Fix 'Up Speed' column not sorting
* Hide unused Infohash button in WebUI
==== Label ====
* Disable unusable items for 'All' in sidebar menu
* Fix items for translation
==== Console ====
* Fix prefixed space for tab completing commands
* Fix missing trailing space for command options with tab complete
==== Blocklist ====
* Use (documented) formatdate over format_date_time
=== Deluge 1.3.4 (03 March 2012) ===
==== Core ====
* #1921: Free disk space reporting incorrectly in FreeBSD
* #1964: Fix unhandled UnpicklingErrors
* #1967: Fix unhandled IndexError when trying to open a non-json conf file
* Fix setting daemon listen interface from command line
* #2021: Fix share ratio limit not obeyed for seeded torrents added to session
* Add optparse custom version to prevent unnecessary loading of libtorrent
* #1554: Fix seeding on share ratio failing for partially selected torrents
* Add proper process title naming in ps, top etc. (Depends: setproctitle)
==== GtkUI ====
* #1918: Fix Drag'n'Drop not working in Windows
* #1941: Increase maximum Cache Size to 999999 (15GiB)
* #1940: File & folder renaming issue when using Add Torrent dialog in Windows
* LP#821577: Fix UnpicklingError when external selection dragged onto Files Tab
* #1934: Fix Unicode error in AddTorrent Dialog
* #1957: Fix keyerror when adding columns for non-latin languages
* #1969: Fix menu item 'Quit & Shutdown' still available when not connected to daemon
* #1895: Fix Files Tab showing wrong files due to torrent_info race condition
* #2010: Move speed text in titlebar to the beginning
* #2032: Wait for client to shutdown/disconnect before stopping reactor
* Fix compatibility with Python 2.5
* Fix collapsed treeview in Create Torrent dialog
* Ignore unmaximise event when window isn't visible
* #1976: Fixed text entry with trailing newline characters causing issues for Move Storage
==== WebUI ====
* Fix Webui files-tab menu setting wrong priority
* Update to ExtJS 3.4.0
* #1960: Fix statustab showing total_payload_download for upload as well
* Remove uneeded Titlebar to save space
* Fix clipped Browse button in WebUI
* #1915: Fix being unable to stop the status bar from autohiding
* Fix password box focus issue in Firefox
* Fix plugin uploads from behind a reverse proxy
* #2010: Move speed text in titlebar to the beginning
* #1936: Fix Referenced before assignment error in json_api
* Changes are now applied when clicking OK in Preferences
* Added Download,Uploaded,Down Limit, Up Limit & Seeder/Peeds columns
* Add magnet uri support to Add Url
* Add keymaps for torrents - Ctrl-A (select all) and Delete
* #2037: Fix 'Add Torrents' torrents list not scrolling
* #2038: Fix Chrome 17 disconnecting from webui
==== Console ====
* #1953: Fix flickering on every update
* #1954: Fix 'invalid literal for float' when setting listen interface
* #1945: Fix UnicodeDecodeError when using non-ascii chars in info
==== Label ====
* #1961: Add missing 'All' filter option
* #2035: Fix label options dialog in webui
* #2036: Fix newly added labels not being sorted in torrent right click menu
==== Notification ====
* #1905: Fix no email sent to second email address
* #1898: Fix email notifications not including date/time they were sent
==== Scheduler ====
* Add plugin page for WebUi
==== Execute ====
* Commands now run scripts asynchronous to prevent Deluge from hanging
==== AutoAdd ====
* Added watch folder support for '.magnet' text file containing single or multiple magnet uris
* Fix glade object issue when re-enabling plugin in same session
* Fix plugin not showing as enabled in webui
=== Deluge 1.3.3 (22 July 2011) ===
==== Core ====
* Properly show the 'Checking Resume Data' state instead of just 7
* #1788: Added ability to use XDG_DOWNLOAD_DIR as default download folder
* Fix path error with torrent files prefixed with 'file://' from Firefox
* #1869: Fix setting the disk io read/write to bypass OS cache in Windows
* #1504: Fix win32 running deluged as not logged in user via runas or service
* #890: If added torrent already exists, append extra trackers to it
* #1338: Fix Seeds and Peers totals not updating
* #1239: Fix translated Tracker Error text not counted in sidebar Error status
* Fix httpdownloader error with existing filename
* #1505: Add libtorrent info to version output
* #1637 Fix UnicodeDecodeError from 'deluge-* --help' with non-english languages
* #1714 Fix handling of backslashes when renaming files/folders
==== GtkUI ====
* Show the checking icon for torrents in the 'Checking Resume Data' state
* #1195: Fix right-click selecting issue when switching between folders and files
* Add F2 key shortcut for renaming filenames in the Files Tab
* Increase max piece size to 16 MiB in create torrent dialog
* #1475: Fix save and restore Preferences dialog size from config
* Add search as you type to the torrent view
* #1456: Fix no ETA showing with multiple files
* #1560: Fix FilesTab Progress value sorting by int instead of float
* #1263: Fix not remembering column widths
* #948: New Release Dialog now shows the server version
* Fix peers in PeersTab showing non-zero download rate when seeding
==== AutoAdd ====
* #1861: Fix AutoAdd Warning (column number is a boolean)
==== Label ====
* #1246: Fix losing Labels upon restart
==== Execute ====
* #1477: Fix ignore Added events from state file on startup
==== ConsoleUI ====
* #1258: Add support for urls and magnet uris in add command
* #1801: Fix unhandled defered error and missing error message upon failed connect
=== Deluge 1.3.2 (24 May 2011) ===
==== Core ====
* #1527: Fix Converting unicode to unicode error in move_storage
* #1373: Fix creating and moving non-ascii folder names in MS Windows
* #1507: Fix temporary file race condition in core/core.py:add_torrent_url
* Fix a bug that can occur when upgrading 1.1 config files
* #1517: Fix isohunt urls not loading
* Handle redirection when adding a torrent by url
* #1614: Fix autoadd matching a directory called "torrent"
* #1742: Fix failure in Event handler prevents further emissions
==== GtkUI ====
* #1514: Added Indicator Applet
* #1494: Add torrent columns Downloaded and Uploaded
* #1308: Add torrent column Seeds/Peers ratio
* #1646: Add torrent columns for per torrent upload and download speed limits
* Add missing icons for Trackers filter
* Fix inconsistancies in the text for translation
* #1510: Fix cannot create a torrent with only non-zero tier trackers
* #1513: Fix unhandled Twisted Error in test_listen_port
* #690: Fix renaming folders does not remove old empty folders
* #1336: Fix uneeded horizontal scrollbar showing in Files & Peers Tab
* #1508: Fix TypeError in cell_data_queue() could not convert argument to correct param type
* #1498: Fix double slashes appearing when renaming
* #1283: Fix consistent icons for Files tab
* #1282: Text for AutoManaged changed to 'On/Off' and localized
* Fix Up/Down buttons in Edit Trackers Dialog
* Add Key Shortcuts for main menu functions
==== WebUI ====
* #1194: Fix infinite login prompt in web ui through reverse proxy
* #1355: Fix slow changing states in webUI
* #1536: Fix Edit Trackers window not scrolling and not being resizable
* #1799: Fix Missing textbox for "Move completed" in torrent options
* #1562: Fix Javascript error in Web UI when re-opening preferences
* #1567: Fix js from plugins does not work with different 'base' setting
* #1268: Fix torrent errors not displayed in webui
* #1323: Fix filter panels not scrollable
* Fix file uploads from behind a reverse proxy.
* #1333: Fix peer list doesn't update automatically
* #1537: Fix editing trackers list, trackers have to be reselected
==== ConsoleUI ====
* #755: Fix can't set listen_ports through console UI
* #1500: Fix Console crashes on command longer than terminal width
* #1248: Fix deluge-console unicode support on redirected stdout
* Fix for deluge-console not adding torrent files on MS Windows
* #1450: Fix trailing white space in paths
* Misc: Updated help text for deluge-console on MS Windows
* #1484: Fix trying to access the screen object when not using interactive mode
* #1548: Fix cli argument processing
* #1856: Add --sort option to info command
* #1857: Add seeding_time, active_time and tracker_status to info command
==== Scheduler ====
* #1506: Fix max speed not restored on a yellow->green transition
=== Deluge 1.3.1 (31 October 2010) ===
==== Core ====
* #1369: Fix non-ascii config folders not working in windows
==== GtkUI ====
* #1365: Fix sidebar not updating show/hide trackers
* #1247: Fix hang on quit
==== WebUI ====
* #1364: Fix preferences not saving when the web ui plugin is enabled in classic mode
* #1377: Fix bug when enabling plugins
* #1370: Fix issues with preferences
* #1312: Fix deluge-web using 100% CPU
=== Deluge 1.3.0 (18 September 2010) ===
==== Core ====
* Fix issue where the save_timer is cancelled when it's not active
* Fix unhandled exception when adding a torrent to the session
* Moved xdg import so it is not called on Windows, where it is unused. fixes #1343
* Fix key error after enabling a plugin that introduces a new status key
* Ignore global stop ratio related settings in logic, so per torrent ones are used.
* Ensure preferencesmanager only changes intended libtorrent session settings.
* Fix issue when adding torrents without a 'session'. This can happen when a plugin adds a torrent, like how the AutoAdd plugin works. The user that adds this torrent will be an empty string.
* Add TorrentFileCompleted event
==== GtkUI ====
* Increase max piece size to 8 MiB in create torrent dialog (closes #1358)
==== Scheduler ====
* Add max active downloading and seeding options to scheduler.
* Fix scheduler so that it keeps current state, even after global settings change.
==== AutoAdd ====
* AutoAdd plugin can now recover when one of the watchfolders has an unhandled exception.
* Fix bug in AutoAdd plugin where watchdirs would not display in gtkui when first enabled.
* Fix bugs with unicode torrents in AutoAdd plugin.
=== Deluge 1.3.0-rc2 (20 August 2010) ===
==== Core ====
* Fix tracker_icons failing on windows
* Fix #1302 an uncaught exception in an state_changed event handler in SessionProxy was preventing the TorrentManager's stop method from properly saving all the resume data
* Fix issue with SessionProxy not updating the torrent status correctly when get_torrent_status calls take place within the cache_expiry time
==== ConsoleUI ====
* #1307: Fix not being able to add torrents
* #1293: Fix not being able to add paths that contain backslashes
==== GtkUI ====
* Fix uncaught exception when closing deluge in classic mode
==== Execute ====
* #1306: Fix always executing last event
==== Label ====
* Fix being able to remove labels in web ui
==== WebUI ====
* #1319: Fix shift selecting in file trees
=== Deluge 1.3.0-rc1 (08 May 2010) ===
==== Core ====
* Implement #1063 option to delete torrent file copy on torrent removal - patch from Ghent
* Implement #457 progress bars for folders
@ -7,15 +566,33 @@
* #1112: Fix renaming files in add torrent dialog
* #1247: Fix deluge-gtk from hanging on shutdown
* #995: Rewrote tracker_icons
* Add AutoAdd plugin
* Add Notifications plugin
==== GtkUI ====
* Use new SessionProxy class for caching torrent status client-side
* Use torrent status diffs to reduce RPC traffic
==== Blocklist ====
* Implement local blocklist support
* #861: Pause transfers until blocklist is imported
* Fix redirection not working with relative paths
==== Execute ====
* Fix running commands with the TorrentAdded event
* Fix the web interface
==== Label ====
* Fix the web interface (#733)
==== Web ====
* Migrate to ExtJS 3.1
* Add gzip compression of HTTP data to the server
* Improve the efficiency of the TorrentGrid
* Improve the efficiency of the TorrentGrid with lots of torrents (#1026)
* Add a base parameter to allow reverse proxying (#1076)
* Fix showing all the peers in the details tab (#1054)
* Fix uploading torrent files in Opera or IE (#1087)
* Complete IE support
=== Deluge 1.2.0 - "Bursting like an infected kidney" (10 January 2010) ===
==== Core ====

17
DEPENDS
View File

@ -6,25 +6,28 @@
* simplejson (if python < 2.6)
* setuptools
* gettext
* intltool
* pyxdg
* chardet
* geoip-database (optional)
* setproctitle (optional)
* pillow (optional)
* python-geoip (optional)
* libtorrent >= 0.14, or build the included version
* libtorrent (rasterbar) >= 0.14
* If building included libtorrent::
* If building libtorrent:
* boost >= 1.34.1
* openssl
* zlib
=== UIs ===
* chardet
=== Gtk ===
* python-notify (libnotify python wrapper)
* pygame
* pygtk >= 2.12
* librsvg
* xdg-utils
* python-notify (optional)
* pygame (optional)
* python-appindicator (optional)
=== Web ===
* mako

71
README
View File

@ -1,4 +1,3 @@
==========================
Deluge BitTorrent Client
==========================
@ -9,86 +8,50 @@ Authors:
Andrew Resch
Damien Churchill
For past developers and contributers see: http://dev.deluge-torrent.org/wiki/About
==========================
License
==========================
Deluge is under the GNU GPLv3 license.
Icon data/pixmaps/deluge.svg and derivatives in data/icons are copyright
Andrew Wedderburn and are under the GNU GPLv3.
All other icons in data/pixmaps are copyright Andrew Resch and are under
the GNU GPLv3.
==========================
Contact/Support:
==========================
We have two options available for support:
Our Forum, at: http://forum.deluge-torrent.org
or
Our IRC Channel, at #deluge on Freenode: http://freenode.net
For contributors and past developers see:
AUTHORS
==========================
Installation Instructions:
==========================
For more detailed instructions see: http://dev.deluge-torrent.org/wiki/Installing/Source
For detailed instructions see: http://dev.deluge-torrent.org/wiki/Installing/Source
See: DEPENDS for a full list of dependencies.
Ensure build dependencies are installed, see DEPENDS for a full listing.
First, make sure you have the proper build dependencies installed. On a normal
Debian or Ubuntu system:
Build and install by running:
sudo apt-get install g++ make python-all-dev python-all python-dbus \
python-gtk2 python-notify librsvg2-common python-xdg python-support \
subversion libboost-dev libboost-python-dev \
libboost-thread-dev libboost-date-time-dev libboost-filesystem-dev \
libssl-dev zlib1g-dev python-setuptools \
python-mako python-twisted-web python-chardet python-simplejson
$ python setup.py build
$ sudo python setup.py install
The names of the packages may vary depending on your OS / distro.
==========================
Contact/Support:
==========================
Once you have the needed libraries installed, build and install by running:
$ python setup.py build
$ sudo python setup.py install
Forum: http://forum.deluge-torrent.org
IRC Channel: #deluge on irc.freenode.net
==========================
FAQ
==========================
For the full FAQ see: http://dev.deluge-torrent.org/wiki/Faq
How to start the various user-interfaces
Gtk:
deluge-gtk
deluge or deluge-gtk
Console:
deluge-console
Web:
deluge-web
Go to http://localhost:8112/ default-password = "deluge"
Why is deluge still listed in my system tray even after I close it ?
You closed the gtk user-interface but you did not close the daemon. Choose "Quit & Shutdown Daemon" to close both Daemon and gtk-ui.
How do I start the daemon?
deluged
How do I start the daemon with logging to console?
deluged -d -L <log level>
I can't connect to the daemon from another machine
* Configure the daemon to allow remote connections
* Add a user to the auth file located in the config folder: ~/.config/deluge/auth
* Restart the daemon.
See: http://dev.deluge-torrent.org/wiki/UserGuide/ThinClient
I upgraded from 0.5 and plugin x is missing
1.0 is a rewrite, all old 0.5 plugins have to be rewritten.
For the full FAQ see: http://dev.deluge-torrent.org/wiki/Faq

21
check_glade.sh Executable file
View File

@ -0,0 +1,21 @@
#!/bin/sh
# Fixes glade files which may have set gtk stock labels set to translatable
for x in `find . -name '*.glade' |grep -v '.git\|build'` ; do \
for y in gtk-add gtk-apply gtk-bold gtk-cancel gtk-cdrom gtk-clear \
gtk-close gtk-color-picker gtk-connect gtk-convert gtk-copy gtk-cut \
gtk-delete gtk-dialog-error gtk-dialog-info gtk-dialog-question \
gtk-dialog-warning gtk-dnd gtk-dnd-multiple gtk-edit gtk-execute gtk-find \
gtk-find-and-replace gtk-floppy gtk-goto-bottom gtk-goto-first \
gtk-goto-last gtk-goto-top gtk-go-back gtk-go-down gtk-go-forward \
gtk-go-up gtk-help gtk-home gtk-index gtk-italic gtk-jump-to \
gtk-justify-center gtk-justify-fill gtk-justify-left gtk-missing-image \
gtk-new gtk-no gtk-ok gtk-open gtk-paste gtk-preferences gtk-print \
gtk-print-preview gtk-properties gtk-quit gtk-redo gtk-refresh \
gtk-remove gtk-revert-to-saved gtk-save gtk-save-as gtk-select-color \
gtk-select-font gtk-sort-descending gtk-spell-check gtk-stop \
gtk-strikethrough gtk-undelete gtk-underline gtk-undo gtk-yes \
gtk-zoom-100 gtk-zoom-fit gtk-zoom-in gtk-zoom-out; do \
sed -i "s/<property\ name\=\"label\"\ translatable\=\"yes\">$y<\/property>/<property\ name\=\"label\"\ translatable\=\"no\">$y<\/property>/g" $x; \
done;\
done

17
create_potfiles_in.py Normal file → Executable file
View File

@ -1,17 +1,26 @@
#!/usr/bin/env python
import os
import re
import sys
# Paths to exclude
EXCLUSIONS = [
"deluge/scripts"
"deluge/scripts",
"deluge/i18n",
]
POTFILE_IN = "deluge/i18n/POTFILES.in"
print "Creating " + POTFILE_IN + " .."
pattern = "deluge\/plugins\/.*\/build"
compiled = re.compile(pattern)
sys.stdout.write("Creating " + POTFILE_IN + " ... ")
sys.stdout.flush()
to_translate = []
for (dirpath, dirnames, filenames) in os.walk("deluge"):
for filename in filenames:
if os.path.splitext(filename)[1] in (".py", ".glade") and dirpath not in EXCLUSIONS:
if os.path.splitext(filename)[1] in (".py", ".glade", ".in") \
and dirpath not in EXCLUSIONS \
and not compiled.match(dirpath):
to_translate.append(os.path.join(dirpath, filename))
f = open(POTFILE_IN, "wb")

View File

@ -47,7 +47,7 @@ supports.
REQUIRED_VERSION = "0.14.9.0"
def check_version(LT):
def check_version(lt):
from deluge.common import VersionSplit
if VersionSplit(lt.version) < VersionSplit(REQUIRED_VERSION):
raise ImportError("This version of Deluge requires libtorrent >=%s!" % REQUIRED_VERSION)

View File

@ -17,9 +17,9 @@
#
# You should have received a copy of the GNU General Public License
# along with deluge. If not, write to:
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
#
# In addition, as a special exception, the copyright holders give
# permission to link the code of portions of this program with the OpenSSL
@ -36,17 +36,26 @@
"""Common functions for various parts of Deluge to use."""
from __future__ import with_statement
import os
import time
import subprocess
import platform
import sys
import chardet
import pkg_resources
import gettext
import locale
try:
import json
except ImportError:
import simplejson as json
from deluge.error import *
from deluge.log import LOG as log
# Do a little hack here just in case the user has json-py installed since it
# has a different api
if not hasattr(json, "dumps"):
@ -62,29 +71,19 @@ if not hasattr(json, "dumps"):
json.dump = dump
json.load = load
import pkg_resources
import xdg, xdg.BaseDirectory
import gettext
import locale
# Initialize gettext
try:
if hasattr(locale, "bindtextdomain"):
locale.bindtextdomain("deluge", pkg_resources.resource_filename("deluge", "i18n"))
if hasattr(locale, "textdomain"):
locale.textdomain("deluge")
gettext.bindtextdomain("deluge", pkg_resources.resource_filename("deluge", "i18n"))
gettext.textdomain("deluge")
gettext.install("deluge", pkg_resources.resource_filename("deluge", "i18n"))
gettext.install("deluge", pkg_resources.resource_filename("deluge", "i18n"), unicode=True)
except Exception, e:
from deluge.log import LOG as log
log.error("Unable to initialize gettext/locale!")
log.exception(e)
import __builtin__
__builtin__.__dict__["_"] = lambda x: x
from deluge.error import *
LT_TORRENT_STATE = {
"Queued": 0,
"Checking": 1,
@ -104,7 +103,6 @@ LT_TORRENT_STATE = {
7: "Checking Resume Data"
}
TORRENT_STATE = [
"Allocating",
"Checking",
@ -119,11 +117,15 @@ FILE_PRIORITY = {
0: "Do Not Download",
1: "Normal Priority",
2: "High Priority",
5: "Highest Priority",
3: "High Priority",
4: "High Priority",
5: "High Priority",
6: "High Priority",
7: "Highest Priority",
"Do Not Download": 0,
"Normal Priority": 1,
"High Priority": 2,
"Highest Priority": 5
"High Priority": 5,
"Highest Priority": 7
}
def get_version():
@ -145,15 +147,27 @@ def get_default_config_dir(filename=None):
"""
if windows_check():
appDataPath = os.environ.get("APPDATA")
if not appDataPath:
import _winreg
hkey = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders")
appDataReg = _winreg.QueryValueEx(hkey, "AppData")
appDataPath = appDataReg[0]
_winreg.CloseKey(hkey)
if filename:
return os.path.join(os.environ.get("APPDATA"), "deluge", filename)
return os.path.join(appDataPath, "deluge", filename)
else:
return os.path.join(os.environ.get("APPDATA"), "deluge")
return os.path.join(appDataPath, "deluge")
else:
if filename:
return os.path.join(xdg.BaseDirectory.save_config_path("deluge"), filename)
else:
return xdg.BaseDirectory.save_config_path("deluge")
from xdg.BaseDirectory import save_config_path
try:
if filename:
return os.path.join(save_config_path("deluge"), filename)
else:
return save_config_path("deluge")
except OSError, e:
log.error("Unable to use default config directory, exiting... (%s)", e)
sys.exit(1)
def get_default_download_dir():
"""
@ -161,10 +175,21 @@ def get_default_download_dir():
:rtype: string
"""
if windows_check():
return os.path.expanduser("~")
else:
return os.environ.get("HOME")
download_dir = ""
if not windows_check():
from xdg.BaseDirectory import xdg_config_home
try:
with open(os.path.join(xdg_config_home, 'user-dirs.dirs'), 'r') as _file:
for line in _file:
if not line.startswith('#') and line.startswith('XDG_DOWNLOAD_DIR'):
download_dir = os.path.expandvars(line.partition("=")[2].rstrip().strip('"'))
break
except IOError:
pass
if not download_dir:
download_dir = os.path.join(os.path.expanduser("~"), 'Downloads')
return download_dir
def windows_check():
"""
@ -209,18 +234,27 @@ def get_pixmap(fname):
return pkg_resources.resource_filename("deluge", os.path.join("data", \
"pixmaps", fname))
def open_file(path):
def open_file(path, timestamp=None):
"""
Opens a file or folder using the system configured program
:param path: the path to the file or folder to open
:type path: string
:param timestamp: the timestamp of the event that requested to open
:type timestamp: int
"""
if windows_check():
os.startfile("%s" % path)
os.startfile(path.decode("utf8"))
elif osx_check():
subprocess.Popen(["open", "%s" % path])
else:
subprocess.Popen(["xdg-open", "%s" % path])
if timestamp is None:
timestamp = int(time.time())
env = os.environ.copy()
env["DESKTOP_STARTUP_ID"] = "%s-%u-%s-xdg_open_TIME%d" % \
(os.path.basename(sys.argv[0]), os.getpid(), os.uname()[1], timestamp)
subprocess.Popen(["xdg-open", "%s" % path], env=env)
def open_url_in_browser(url):
"""
@ -259,6 +293,30 @@ def fsize(fsize_b):
fsize_gb = fsize_mb / 1024.0
return "%.1f %s" % (fsize_gb, _("GiB"))
def fsize_short(fsize_b):
"""
Formats the bytes value into a string with K, M or G units
:param fsize_b: the filesize in bytes
:type fsize_b: int
:returns: formatted string in K, M or G units
:rtype: string
**Usage**
>>> fsize(112245)
'109.6 K'
"""
fsize_kb = fsize_b / 1024.0
if fsize_kb < 1024:
return "%.1f %s" % (fsize_kb, _("K"))
fsize_mb = fsize_kb / 1024.0
if fsize_mb < 1024:
return "%.1f %s" % (fsize_mb, _("M"))
fsize_gb = fsize_mb / 1024.0
return "%.1f %s" % (fsize_gb, _("G"))
def fpcnt(dec):
"""
Formats a string to display a percentage with two decimal places
@ -291,7 +349,14 @@ def fspeed(bps):
'42.1 KiB/s'
"""
return '%s/s' % (fsize(bps))
fspeed_kb = bps / 1024.0
if fspeed_kb < 1024:
return "%.1f %s" % (fspeed_kb, _("KiB/s"))
fspeed_mb = fspeed_kb / 1024.0
if fspeed_mb < 1024:
return "%.1f %s" % (fspeed_mb, _("MiB/s"))
fspeed_gb = fspeed_mb / 1024.0
return "%.1f %s" % (fspeed_gb, _("GiB/s"))
def fpeer(num_peers, total_peers):
"""
@ -402,7 +467,9 @@ def is_magnet(uri):
True
"""
if uri[:20] == "magnet:?xt=urn:btih:":
magnet_scheme = 'magnet:?'
xt_param = 'xt=urn:btih:'
if uri.startswith(magnet_scheme) and xt_param in uri:
return True
return False
@ -466,16 +533,15 @@ def free_space(path):
:raises InvalidPathError: if the path is not valid
"""
if not os.path.exists(path):
if not path or not os.path.exists(path):
raise InvalidPathError("%s is not a valid path" % path)
if windows_check():
import win32file
sectors, bytes, free, total = map(long, win32file.GetDiskFreeSpace(path))
return (free * sectors * bytes)
from win32file import GetDiskFreeSpaceEx
return GetDiskFreeSpaceEx(path)[0]
else:
disk_data = os.statvfs(path)
block_size = disk_data.f_bsize
disk_data = os.statvfs(path.encode("utf8"))
block_size = disk_data.f_frsize
return disk_data.f_bavail * block_size
def is_ip(ip):
@ -496,15 +562,23 @@ def is_ip(ip):
import socket
#first we test ipv4
try:
if socket.inet_pton(socket.AF_INET, "%s" % (ip)):
return True
if windows_check():
if socket.inet_aton("%s" % (ip)):
return True
else:
if socket.inet_pton(socket.AF_INET, "%s" % (ip)):
return True
except socket.error:
if not socket.has_ipv6:
return False
#now test ipv6
try:
if socket.inet_pton(socket.AF_INET6, "%s" % (ip)):
if windows_check():
log.warning("ipv6 check unavailable on windows")
return True
else:
if socket.inet_pton(socket.AF_INET6, "%s" % (ip)):
return True
except socket.error:
return False
@ -526,7 +600,7 @@ def path_join(*parts):
path += '/' + part
return path
XML_ESCAPES = (
XML_ESCAPES = (
('&', '&amp;'),
('<', '&lt;'),
('>', '&gt;'),
@ -535,9 +609,9 @@ XML_ESCAPES = (
)
def xml_decode(string):
"""
"""
Unescape a string that was previously encoded for use within xml.
:param string: The string to escape
:type string: string
:returns: The unescaped version of the string.
@ -548,9 +622,9 @@ def xml_decode(string):
return string
def xml_encode(string):
"""
"""
Escape a string for use within an xml element or attribute.
:param string: The string to escape
:type string: string
:returns: An escaped version of the string.
@ -560,6 +634,59 @@ def xml_encode(string):
string = string.replace(char, escape)
return string
def decode_string(s, encoding="utf8"):
"""
Decodes a string and return unicode. If it cannot decode using
`:param:encoding` then it will try latin1, and if that fails,
try to detect the string encoding. If that fails, decode with
ignore.
:param s: string to decode
:type s: string
:keyword encoding: the encoding to use in the decoding
:type encoding: string
:returns: s converted to unicode
:rtype: unicode
"""
if not s:
return u''
elif isinstance(s, unicode):
return s
encodings = [lambda: ("utf8", 'strict'),
lambda: ("iso-8859-1", 'strict'),
lambda: (chardet.detect(s)["encoding"], 'strict'),
lambda: (encoding, 'ignore')]
if not encoding is "utf8":
encodings.insert(0, lambda: (encoding, 'strict'))
for l in encodings:
try:
return s.decode(*l())
except UnicodeDecodeError:
pass
return u''
def utf8_encoded(s, encoding="utf8"):
"""
Returns a utf8 encoded string of s
:param s: (unicode) string to (re-)encode
:type s: basestring
:keyword encoding: the encoding to use in the decoding
:type encoding: string
:returns: a utf8 encoded string of s
:rtype: str
"""
if isinstance(s, str):
s = decode_string(s, encoding).encode("utf8")
elif isinstance(s, unicode):
s = s.encode("utf8")
return s
class VersionSplit(object):
"""
Used for comparing version numbers.
@ -570,13 +697,15 @@ class VersionSplit(object):
"""
def __init__(self, ver):
ver = ver.lower()
vs = ver.split("_") if "_" in ver else ver.split("-")
self.version = [int(x) for x in vs[0].split(".")]
vs = ver.replace("_", "-").split("-")
self.version = [int(x) for x in vs[0].split(".") if x.isdigit()]
self.suffix = None
self.dev = False
if len(vs) > 1:
for s in ("rc", "alpha", "beta", "dev"):
if s in vs[1][:len(s)]:
self.suffix = vs[1]
if vs[1].startswith(("rc", "alpha", "beta")):
self.suffix = vs[1]
if vs[-1] == 'dev':
self.dev = True
def __cmp__(self, ver):
"""
@ -587,19 +716,32 @@ class VersionSplit(object):
"""
if self.version > ver.version or (self.suffix and self.suffix[:3] == "dev"):
return 1
if self.version < ver.version:
return -1
# If there is no suffix we use z because we want final
# to appear after alpha, beta, and rc alphabetically.
v1 = [self.version, self.suffix or 'z', self.dev]
v2 = [ver.version, ver.suffix or 'z', ver.dev]
return cmp(v1, v2)
if self.version == ver.version:
if self.suffix == ver.suffix:
return 0
if self.suffix is None:
return 1
if ver.suffix is None:
return -1
if self.suffix < ver.suffix:
return -1
if self.suffix > ver.suffix:
return 1
def win32_unicode_argv():
""" Gets sys.argv as list of unicode objects on any platform."""
if windows_check():
# Versions 2.x of Python don't support Unicode in sys.argv on Windows, with the
# underlying Windows API instead replacing multi-byte characters with '?'.
from ctypes import POINTER, byref, cdll, c_int, windll
from ctypes.wintypes import LPCWSTR, LPWSTR
get_cmd_linew = cdll.kernel32.GetCommandLineW
get_cmd_linew.argtypes = []
get_cmd_linew.restype = LPCWSTR
cmdline_to_argvw = windll.shell32.CommandLineToArgvW
cmdline_to_argvw.argtypes = [LPCWSTR, POINTER(c_int)]
cmdline_to_argvw.restype = POINTER(LPWSTR)
cmd = get_cmd_linew()
argc = c_int(0)
argv = cmdline_to_argvw(cmd, byref(argc))
if argc.value > 0:
# Remove Python executable and commands if present
start = argc.value - len(sys.argv)
return [argv[i] for i in xrange(start, argc.value)]

View File

@ -96,6 +96,10 @@ class Component(object):
self._component_stopping_deferred = None
_ComponentRegistry.register(self)
def __del__(self):
if _ComponentRegistry:
_ComponentRegistry.deregister(self._component_name)
def _component_start_timer(self):
if hasattr(self, "update"):
self._component_timer = LoopingCall(self.update)
@ -139,11 +143,18 @@ class Component(object):
self._component_timer.stop()
return True
def on_stop_fail(result):
self._component_state = "Started"
self._component_stopping_deferred = None
log.error(result)
return result
if self._component_state != "Stopped" and self._component_state != "Stopping":
if hasattr(self, "stop"):
self._component_state = "Stopping"
d = maybeDeferred(self.stop)
d.addCallback(on_stop)
d.addErrback(on_stop_fail)
self._component_stopping_deferred = d
else:
d = maybeDeferred(on_stop, None)
@ -192,6 +203,18 @@ class Component(object):
d.addCallback(on_stop)
return d
def start(self):
pass
def stop(self):
pass
def update(self):
pass
def shutdown(self):
pass
class ComponentRegistry(object):
"""
The ComponentRegistry holds a list of currently registered

View File

@ -45,9 +45,9 @@ The format of the config file is two json encoded dicts:
<version dict>
<content dict>
The version dict contains two keys: file and format. The format version is
controlled by the Config class. It should only be changed when anything below
it is changed directly by the Config class. An example of this would be if we
The version dict contains two keys: file and format. The format version is
controlled by the Config class. It should only be changed when anything below
it is changed directly by the Config class. An example of this would be if we
changed the serializer for the content to something different.
The config file version is changed by the 'owner' of the config file. This is
@ -67,6 +67,8 @@ version as this will be done internally.
"""
from __future__ import with_statement
import cPickle as pickle
import shutil
import os
@ -93,13 +95,13 @@ def prop(func):
def find_json_objects(s):
"""
Find json objects in a string.
:param s: the string to find json objects in
:type s: string
:returns: a list of tuples containing start and end locations of json objects in the string `s`
:rtype: [(start, end), ...]
"""
objects = []
opens = 0
@ -119,8 +121,8 @@ def find_json_objects(s):
start = index + offset + 1
return objects
class Config(object):
"""
This class is used to access/create/modify config files
@ -146,7 +148,8 @@ class Config(object):
self._save_timer = None
if defaults:
self.__config = dict(defaults)
for key, value in defaults.iteritems():
self.set_item(key, value)
# Load the config from file in the config_dir
if config_dir:
@ -187,6 +190,10 @@ what is currently in the config and it could not convert the value
5
"""
if isinstance(value, basestring):
value = deluge.common.utf8_encoded(value)
if not self.__config.has_key(key):
self.__config[key] = value
log.debug("Setting '%s' to %s of %s", key, value, type(value))
@ -200,7 +207,10 @@ what is currently in the config and it could not convert the value
if value is not None and oldtype != type(None) and oldtype != newtype:
try:
value = oldtype(value)
if oldtype == unicode:
value = oldtype(value, "utf8")
else:
value = oldtype(value)
except ValueError:
log.warning("Type '%s' invalid for '%s'", newtype, key)
raise
@ -250,7 +260,13 @@ what is currently in the config and it could not convert the value
5
"""
return self.__config[key]
if isinstance(self.__config[key], str):
try:
return self.__config[key].decode("utf8")
except UnicodeDecodeError:
return self.__config[key]
else:
return self.__config[key]
def register_change_callback(self, callback):
"""
@ -342,27 +358,28 @@ what is currently in the config and it could not convert the value
filename = self.__config_file
try:
data = open(filename, "rb").read()
with open(filename, "rb") as _file:
data = _file.read()
except IOError, e:
log.warning("Unable to open config file %s: %s", filename, e)
return
objects = find_json_objects(data)
if not len(objects):
# No json objects found, try depickling it
try:
self.__config.update(pickle.loads(data))
except Exception, e:
log.exception(e)
log.warning("Unable to load config file: %s", filename)
log.warning("Unable to load config file: %s", filename)
elif len(objects) == 1:
start, end = objects[0]
try:
self.__config.update(json.loads(data[start:end]))
except Exception, e:
log.exception(e)
log.warning("Unable to load config file: %s", filename)
log.warning("Unable to load config file: %s", filename)
elif len(objects) == 2:
try:
start, end = objects[0]
@ -371,8 +388,8 @@ what is currently in the config and it could not convert the value
self.__config.update(json.loads(data[start:end]))
except Exception, e:
log.exception(e)
log.warning("Unable to load config file: %s", filename)
log.warning("Unable to load config file: %s", filename)
log.debug("Config %s version: %s.%s loaded: %s", filename,
self.__version["format"], self.__version["file"], self.__config)
@ -390,32 +407,31 @@ what is currently in the config and it could not convert the value
# Check to see if the current config differs from the one on disk
# We will only write a new config file if there is a difference
try:
data = open(filename, "rb").read()
with open(filename, "rb") as _file:
data = _file.read()
objects = find_json_objects(data)
start, end = objects[0]
version = json.loads(data[start:end])
start, end = objects[1]
loaded_data = json.loads(data[start:end])
if self.__config == loaded_data and self.__version == version:
# The config has not changed so lets just return
self._save_timer.cancel()
return
except Exception, e:
log.warning("Unable to open config file: %s", filename)
if self._save_timer and self._save_timer.active():
self._save_timer.cancel()
return True
except (IOError, IndexError), e:
log.warning("Unable to open config file: %s because: %s", filename, e)
# Save the new config and make sure it's written to disk
try:
log.debug("Saving new config file %s", filename + ".new")
f = open(filename + ".new", "wb")
json.dump(self.__version, f, indent=2)
json.dump(self.__version, f, indent=2)
json.dump(self.__config, f, indent=2)
f.flush()
os.fsync(f.fileno())
f.close()
except Exception, e:
except IOError, e:
log.error("Error writing new config file: %s", e)
return False
@ -424,7 +440,7 @@ what is currently in the config and it could not convert the value
log.debug("Backing up old config file to %s~", filename)
shutil.move(filename, filename + "~")
except Exception, e:
log.error("Error backing up old config..")
log.warning("Unable to backup old config...")
# The new config file has been written successfully, so let's move it over
# the existing one.

View File

@ -51,7 +51,7 @@ from deluge.log import LOG as log
class AlertManager(component.Component):
def __init__(self):
log.debug("AlertManager initialized..")
component.Component.__init__(self, "AlertManager", interval=0.05)
component.Component.__init__(self, "AlertManager", interval=0.3)
self.session = component.get("Core").session
self.session.set_alert_mask(
@ -74,7 +74,8 @@ class AlertManager(component.Component):
def stop(self):
for dc in self.delayed_calls:
dc.cancel()
if dc.active():
dc.cancel()
self.delayed_calls = []
def register_handler(self, alert_type, handler):

View File

@ -33,6 +33,8 @@
#
#
from __future__ import with_statement
import os
import random
import stat
@ -118,13 +120,14 @@ class AuthManager(component.Component):
f = [localclient]
else:
# Load the auth file into a dictionary: {username: password, ...}
f = open(auth_file, "r").readlines()
with open(auth_file, "r") as _file:
f = _file.readlines()
for line in f:
if line.startswith("#"):
# This is a comment line
continue
line = line.strip()
if line.startswith("#") or not line:
# This line is a comment or empty
continue
try:
lsplit = line.split(":")
except Exception, e:
@ -143,4 +146,5 @@ class AuthManager(component.Component):
self.__auth[username.strip()] = (password.strip(), level)
if "localclient" not in self.__auth:
open(auth_file, "a").write(self.__create_localclient_account())
with open(auth_file, "a") as _file:
_file.write(self.__create_localclient_account())

View File

@ -74,12 +74,12 @@ class AutoAdd(component.Component):
return
for filename in os.listdir(self.config["autoadd_location"]):
if filename.split(".")[-1] == "torrent":
try:
filepath = os.path.join(self.config["autoadd_location"], filename)
except UnicodeDecodeError, e:
log.error("Unable to auto add torrent due to inproper filename encoding: %s", e)
continue
try:
filepath = os.path.join(self.config["autoadd_location"], filename)
except UnicodeDecodeError, e:
log.error("Unable to auto add torrent due to improper filename encoding: %s", e)
continue
if os.path.isfile(filepath) and filename.endswith(".torrent"):
try:
filedump = self.load_torrent(filepath)
except (RuntimeError, Exception), e:

View File

@ -33,6 +33,8 @@
#
#
from __future__ import with_statement
from deluge._libtorrent import lt
import os
@ -42,11 +44,14 @@ import shutil
import threading
import pkg_resources
import warnings
import tempfile
from urlparse import urljoin
from twisted.internet import reactor, defer
from twisted.internet.task import LoopingCall
import twisted.web.client
import twisted.web.error
from deluge.httpdownloader import download_file
from deluge.log import LOG as log
@ -69,19 +74,30 @@ from deluge.core.eventmanager import EventManager
from deluge.core.rpcserver import export
class Core(component.Component):
def __init__(self, listen_interface=None):
def __init__(self, listen_interface=None, read_only_config_keys=None):
log.debug("Core init..")
component.Component.__init__(self, "Core")
# These keys will be dropped from the set_config() RPC and are
# configurable from the command-line.
self.read_only_config_keys = read_only_config_keys
log.debug("read_only_config_keys: %s", read_only_config_keys)
# Start the libtorrent session
log.info("Starting libtorrent %s session..", lt.version)
# Create the client fingerprint
version = [int(value.split("-")[0]) for value in deluge.common.get_version().split(".")]
version = deluge.common.VersionSplit(deluge.common.get_version()).version
while len(version) < 4:
version.append(0)
self.session = lt.session(lt.fingerprint("DE", *version), flags=0)
# In libtorrent versions below 0.16.7.0 disable extension bindings due to GIL issue.
# https://code.google.com/p/libtorrent/issues/detail?id=369
if deluge.common.VersionSplit(lt.version) >= deluge.common.VersionSplit("0.16.7.0"):
self.session = lt.session(lt.fingerprint("DE", *version), flags=0)
else:
# Setting session flags to 1 enables all libtorrent default plugins
self.session = lt.session(lt.fingerprint("DE", *version), flags=1)
# Load the session state if available
self.__load_session_state()
@ -89,15 +105,25 @@ class Core(component.Component):
# Set the user agent
self.settings = lt.session_settings()
self.settings.user_agent = "Deluge %s" % deluge.common.get_version()
# Increase the alert queue size so that alerts don't get lost
self.settings.alert_queue_size = 10000
# Set session settings
self.settings.send_redundant_have = True
if deluge.common.windows_check() and lt.version_major == 0 and lt.version_minor <= 15:
self.settings.disk_io_write_mode = \
lt.io_buffer_mode_t.disable_os_cache
self.settings.disk_io_read_mode = \
lt.io_buffer_mode_t.disable_os_cache
self.session.set_settings(self.settings)
# Load metadata extension
self.session.add_extension(lt.create_metadata_plugin)
self.session.add_extension(lt.create_ut_metadata_plugin)
self.session.add_extension(lt.create_smart_ban_plugin)
# In libtorrent versions below 0.16.7.0 disable extension bindings due to GIL issue.
# https://code.google.com/p/libtorrent/issues/detail?id=369
if deluge.common.VersionSplit(lt.version) >= deluge.common.VersionSplit("0.16.7.0"):
self.session.add_extension("metadata_transfer")
self.session.add_extension("ut_metadata")
self.session.add_extension("smart_ban")
# Create the components
self.eventmanager = EventManager()
@ -112,6 +138,9 @@ class Core(component.Component):
# New release check information
self.new_release = None
# GeoIP instance with db loaded
self.geoip_instance = None
# Get the core config
self.config = deluge.configmanager.ConfigManager("core.conf")
@ -119,8 +148,11 @@ class Core(component.Component):
# store the one in the config so we can restore it on shutdown
self.__old_interface = None
if listen_interface:
self.__old_interface = self.config["listen_interface"]
self.config["listen_interface"] = listen_interface
if deluge.common.is_ip(listen_interface):
self.__old_interface = self.config["listen_interface"]
self.config["listen_interface"] = listen_interface
else:
log.error("Invalid listen interface (must be IP Address): %s", listen_interface)
def start(self):
"""Starts the core"""
@ -128,9 +160,12 @@ class Core(component.Component):
self.__new_release = None
def stop(self):
log.debug("Core stopping...")
# Save the DHT state if necessary
if self.config["dht"]:
self.save_dht_state()
# Save the libtorrent session state
self.__save_session_state()
@ -147,16 +182,17 @@ class Core(component.Component):
def __save_session_state(self):
"""Saves the libtorrent session state"""
try:
open(deluge.configmanager.get_config_dir("session.state"), "wb").write(
lt.bencode(self.session.state()))
lt_data = open(deluge.configmanager.get_config_dir("session.state"), "wb")
lt_data.write(lt.bencode(self.session.save_state()))
lt_data.close()
except Exception, e:
log.warning("Failed to save lt state: %s", e)
def __load_session_state(self):
"""Loads the libtorrent session state"""
try:
self.session.load_state(lt.bdecode(
open(deluge.configmanager.get_config_dir("session.state"), "rb").read()))
with open(deluge.configmanager.get_config_dir("session.state"), "rb") as _file:
self.session.load_state(lt.bdecode(_file.read()))
except Exception, e:
log.warning("Failed to load lt state: %s", e)
@ -236,20 +272,35 @@ class Core(component.Component):
:returns: a Deferred which returns the torrent_id as a str or None
"""
log.info("Attempting to add url %s", url)
def on_get_file(filename):
def on_download_success(filename):
# We got the file, so add it to the session
data = open(filename, "rb").read()
f = open(filename, "rb")
data = f.read()
f.close()
try:
os.remove(filename)
except Exception, e:
log.warning("Couldn't remove temp file: %s", e)
return self.add_torrent_file(filename, base64.encodestring(data), options)
def on_get_file_error(failure):
# Log the error and pass the failure onto the client
log.error("Error occured downloading torrent from %s", url)
log.error("Reason: %s", failure.getErrorMessage())
return failure
def on_download_fail(failure):
if failure.check(twisted.web.error.PageRedirect):
new_url = urljoin(url, failure.getErrorMessage().split(" to ")[1])
result = download_file(new_url, tempfile.mkstemp()[1], headers=headers, force_filename=True)
result.addCallbacks(on_download_success, on_download_fail)
elif failure.check(twisted.web.client.PartialDownloadError):
result = download_file(url, tempfile.mkstemp()[1], headers=headers, force_filename=True,
allow_compression=False)
result.addCallbacks(on_download_success, on_download_fail)
else:
# Log the error and pass the failure onto the client
log.error("Error occurred downloading torrent from %s", url)
log.error("Reason: %s", failure.getErrorMessage())
result = failure
return result
d = download_file(url, url.split("/")[-1], headers=headers)
d.addCallback(on_get_file)
d.addErrback(on_get_file_error)
d = download_file(url, tempfile.mkstemp()[1], headers=headers, force_filename=True)
d.addCallbacks(on_download_success, on_download_fail)
return d
@export
@ -368,15 +419,18 @@ class Core(component.Component):
@export
def pause_all_torrents(self):
"""Pause all torrents in the session"""
for torrent in self.torrentmanager.torrents.values():
torrent.pause()
if not self.session.is_paused():
self.session.pause()
component.get("EventManager").emit(SessionPausedEvent())
@export
def resume_all_torrents(self):
"""Resume all torrents in the session"""
for torrent in self.torrentmanager.torrents.values():
torrent.resume()
component.get("EventManager").emit(SessionResumedEvent())
if self.session.is_paused():
self.session.resume()
for torrent_id in self.torrentmanager.torrents:
self.torrentmanager[torrent_id].update_state()
component.get("EventManager").emit(SessionResumedEvent())
@export
def resume_torrent(self, torrent_ids):
@ -387,11 +441,15 @@ class Core(component.Component):
@export
def get_torrent_status(self, torrent_id, keys, diff=False):
# Build the status dictionary
status = self.torrentmanager[torrent_id].get_status(keys, diff)
try:
status = self.torrentmanager[torrent_id].get_status(keys, diff)
except KeyError:
# Torrent was probaly removed meanwhile
return {}
# Get the leftover fields and ask the plugin manager to fill them
# Get any remaining keys from plugin manager or 'all' if no keys specified.
leftover_fields = list(set(keys) - set(status.keys()))
if len(leftover_fields) > 0:
if len(leftover_fields) > 0 or len(keys) == 0:
status.update(self.pluginmanager.get_status(torrent_id, leftover_fields))
return status
@ -454,6 +512,8 @@ class Core(component.Component):
"""Set the config with values from dictionary"""
# Load all the values into the configuration
for key in config.keys():
if self.read_only_config_keys and key in self.read_only_config_keys:
continue
if isinstance(config[key], unicode) or isinstance(config[key], str):
config[key] = config[key].encode("utf8")
self.config[key] = config[key]
@ -606,7 +666,9 @@ class Core(component.Component):
if add_to_session:
options = {}
options["download_location"] = os.path.split(path)[0]
self.add_torrent_file(os.path.split(target)[1], open(target, "rb").read(), options)
with open(target, "rb") as _file:
filedump = base64.encodestring(_file.read())
self.add_torrent_file(os.path.split(target)[1], filedump, options)
@export
def upload_plugin(self, filename, filedump):
@ -679,7 +741,8 @@ class Core(component.Component):
@export
def queue_top(self, torrent_ids):
log.debug("Attempting to queue %s to top", torrent_ids)
for torrent_id in torrent_ids:
# torrent_ids must be sorted in reverse before moving to preserve order
for torrent_id in sorted(torrent_ids, key=self.torrentmanager.get_queue_position, reverse=True):
try:
# If the queue method returns True, then we should emit a signal
if self.torrentmanager.queue_top(torrent_id):
@ -690,35 +753,48 @@ class Core(component.Component):
@export
def queue_up(self, torrent_ids):
log.debug("Attempting to queue %s to up", torrent_ids)
torrents = ((self.torrentmanager.get_queue_position(torrent_id), torrent_id) for torrent_id in torrent_ids)
torrent_moved = True
prev_queue_position = None
#torrent_ids must be sorted before moving.
torrent_ids = list(torrent_ids)
torrent_ids.sort(key = lambda id: self.torrentmanager.torrents[id].get_queue_position())
for torrent_id in torrent_ids:
try:
# If the queue method returns True, then we should emit a signal
if self.torrentmanager.queue_up(torrent_id):
component.get("EventManager").emit(TorrentQueueChangedEvent())
except KeyError:
log.warning("torrent_id: %s does not exist in the queue", torrent_id)
for queue_position, torrent_id in sorted(torrents):
# Move the torrent if and only if there is space (by not moving it we preserve the order)
if torrent_moved or queue_position - prev_queue_position > 1:
try:
torrent_moved = self.torrentmanager.queue_up(torrent_id)
except KeyError:
log.warning("torrent_id: %s does not exist in the queue", torrent_id)
# If the torrent moved, then we should emit a signal
if torrent_moved:
component.get("EventManager").emit(TorrentQueueChangedEvent())
else:
prev_queue_position = queue_position
@export
def queue_down(self, torrent_ids):
log.debug("Attempting to queue %s to down", torrent_ids)
torrents = ((self.torrentmanager.get_queue_position(torrent_id), torrent_id) for torrent_id in torrent_ids)
torrent_moved = True
prev_queue_position = None
#torrent_ids must be sorted before moving.
torrent_ids = list(torrent_ids)
torrent_ids.sort(key = lambda id: -self.torrentmanager.torrents[id].get_queue_position())
for torrent_id in torrent_ids:
try:
# If the queue method returns True, then we should emit a signal
if self.torrentmanager.queue_down(torrent_id):
component.get("EventManager").emit(TorrentQueueChangedEvent())
except KeyError:
log.warning("torrent_id: %s does not exist in the queue", torrent_id)
for queue_position, torrent_id in sorted(torrents, reverse=True):
# Move the torrent if and only if there is space (by not moving it we preserve the order)
if torrent_moved or prev_queue_position - queue_position > 1:
try:
torrent_moved = self.torrentmanager.queue_down(torrent_id)
except KeyError:
log.warning("torrent_id: %s does not exist in the queue", torrent_id)
# If the torrent moved, then we should emit a signal
if torrent_moved:
component.get("EventManager").emit(TorrentQueueChangedEvent())
else:
prev_queue_position = queue_position
@export
def queue_bottom(self, torrent_ids):
log.debug("Attempting to queue %s to bottom", torrent_ids)
for torrent_id in torrent_ids:
# torrent_ids must be sorted before moving to preserve order
for torrent_id in sorted(torrent_ids, key=self.torrentmanager.get_queue_position):
try:
# If the queue method returns True, then we should emit a signal
if self.torrentmanager.queue_bottom(torrent_id):
@ -747,7 +823,11 @@ class Core(component.Component):
def on_get_page(result):
return bool(int(result))
def logError(failure):
log.warning("Error testing listen port: %s", failure)
d.addCallback(on_get_page)
d.addErrback(logError)
return d
@ -768,7 +848,10 @@ class Core(component.Component):
"""
if not path:
path = self.config["download_location"]
return deluge.common.free_space(path)
try:
return deluge.common.free_space(path)
except InvalidPathError:
return 0
@export
def get_libtorrent_version(self):

View File

@ -32,6 +32,8 @@
# statement from all source files in the program, then also delete it here.
#
from __future__ import with_statement
import os
import gettext
import locale
@ -52,7 +54,8 @@ class Daemon(object):
if os.path.isfile(deluge.configmanager.get_config_dir("deluged.pid")):
# Get the PID and the port of the supposedly running daemon
try:
(pid, port) = open(deluge.configmanager.get_config_dir("deluged.pid")).read().strip().split(";")
with open(deluge.configmanager.get_config_dir("deluged.pid")) as _file:
(pid, port) = _file.read().strip().split(";")
pid = int(pid)
port = int(port)
except ValueError:
@ -62,13 +65,8 @@ class Daemon(object):
def process_running(pid):
if deluge.common.windows_check():
# Do some fancy WMI junk to see if the PID exists in Windows
from win32com.client import GetObject
def get_proclist():
WMI = GetObject('winmgmts:')
processes = WMI.InstancesOf('Win32_Process')
return [process.Properties_('ProcessID').Value for process in processes]
return pid in get_proclist()
import win32process
return pid in win32process.EnumProcesses()
else:
# We can just use os.kill on UNIX to test if the process is running
try:
@ -110,7 +108,7 @@ class Daemon(object):
# Twisted catches signals to terminate, so just have it call the shutdown
# method.
reactor.addSystemEventTrigger("after", "shutdown", self.shutdown)
reactor.addSystemEventTrigger("before", "shutdown", self._shutdown)
# Catch some Windows specific signals
if deluge.common.windows_check():
@ -120,7 +118,7 @@ class Daemon(object):
def win_handler(ctrl_type):
log.debug("ctrl_type: %s", ctrl_type)
if ctrl_type == CTRL_CLOSE_EVENT or ctrl_type == CTRL_SHUTDOWN_EVENT:
self.__shutdown()
self._shutdown()
return 1
SetConsoleCtrlHandler(win_handler)
@ -133,9 +131,20 @@ class Daemon(object):
if options and options.config:
deluge.configmanager.set_config_dir(options.config)
if options and options.listen_interface:
listen_interface = options.listen_interface
else:
listen_interface = ""
if options and options.read_only_config_keys:
read_only_config_keys = options.read_only_config_keys.split(",")
else:
read_only_config_keys = []
from deluge.core.core import Core
# Start the core as a thread and join it until it's done
self.core = Core()
self.core = Core(listen_interface=listen_interface,
read_only_config_keys=read_only_config_keys)
port = self.core.config["daemon_port"]
if options and options.port:
@ -163,8 +172,8 @@ class Daemon(object):
if not classic:
# Write out a pid file all the time, we use this to see if a deluged is running
# We also include the running port number to do an additional test
open(deluge.configmanager.get_config_dir("deluged.pid"), "wb").write(
"%s;%s\n" % (os.getpid(), port))
with open(deluge.configmanager.get_config_dir("deluged.pid"), "wb") as _file:
_file.write("%s;%s\n" % (os.getpid(), port))
component.start()
try:
@ -177,17 +186,16 @@ class Daemon(object):
reactor.callLater(0, reactor.stop)
def _shutdown(self, *args, **kwargs):
try:
os.remove(deluge.configmanager.get_config_dir("deluged.pid"))
except Exception, e:
log.exception(e)
log.error("Error removing deluged.pid!")
if os.path.exists(deluge.configmanager.get_config_dir("deluged.pid")):
try:
os.remove(deluge.configmanager.get_config_dir("deluged.pid"))
except Exception, e:
log.exception(e)
log.error("Error removing deluged.pid!")
component.shutdown()
try:
reactor.stop()
except twisted.internet.error.ReactorNotRunning:
log.debug("Tried to stop the reactor but it is not running..")
log.info("Waiting for components to shutdown..")
d = component.shutdown()
return d
@export()
def info(self):

View File

@ -53,7 +53,10 @@ class EventManager(component.Component):
if event.name in self.handlers:
for handler in self.handlers[event.name]:
#log.debug("Running handler %s for event %s with args: %s", event.name, handler, event.args)
handler(*event.args)
try:
handler(*event.args)
except Exception, e:
log.error("Event handler %s failed in %s with exception %s", event.name, handler, e)
def register_event_handler(self, event, handler):
"""

View File

@ -126,12 +126,11 @@ class FilterManager(component.Component):
#sanitize input: filter-value must be a list of strings
for key, value in filter_dict.items():
if isinstance(value, str):
filter_dict[key] = [value]
if isinstance(value, basestring):
filter_dict[key] = [value]
if "id"in filter_dict: #optimized filter for id:
torrent_ids = filter_dict["id"]
if "id" in filter_dict: #optimized filter for id:
torrent_ids = list(filter_dict["id"])
del filter_dict["id"]
else:
torrent_ids = self.torrents.get_torrent_list()
@ -170,7 +169,9 @@ class FilterManager(component.Component):
for torrent_id in list(torrent_ids):
status = status_func(torrent_id, filter_dict.keys()) #status={key:value}
for field, values in filter_dict.iteritems():
if (not status[field] in values) and torrent_id in torrent_ids:
if field in status and status[field] in values:
continue
elif torrent_id in torrent_ids:
torrent_ids.remove(torrent_id)
return torrent_ids
@ -196,9 +197,8 @@ class FilterManager(component.Component):
value = status[field]
items[field][value] = items[field].get(value, 0) + 1
items["tracker_host"]["All"] = len(torrent_ids)
if "tracker_host" in items:
items["tracker_host"]["All"] = len(torrent_ids)
items["tracker_host"]["Error"] = len(tracker_error_filter(torrent_ids, ("Error",)))
if "state" in tree_keys and not show_zero_hits:

View File

@ -92,6 +92,8 @@ class PluginManager(deluge.pluginmanagerbase.PluginManagerBase,
def get_status(self, torrent_id, fields):
"""Return the value of status fields for the selected torrent_id."""
status = {}
if len(fields) == 0:
fields = self.status_fields.keys()
for field in fields:
try:
status[field] = self.status_fields[field](torrent_id)

View File

@ -33,6 +33,7 @@
#
#
from __future__ import with_statement
import os.path
import threading
@ -48,6 +49,12 @@ import deluge.common
import deluge.component as component
from deluge.log import LOG as log
try:
import GeoIP
except ImportError:
GeoIP = None
DEFAULT_PREFS = {
"send_info": False,
"info_sent": 0.0,
@ -152,7 +159,6 @@ class PreferencesManager(component.Component):
def start(self):
self.core = component.get("Core")
self.session = component.get("Core").session
self.settings = component.get("Core").settings
# Register set functions in the Config
self.config.register_set_function("torrentfiles_location",
@ -229,10 +235,15 @@ class PreferencesManager(component.Component):
self.config.register_change_callback(self._on_config_value_change)
def stop(self):
if self.new_release_timer:
if self.new_release_timer and self.new_release_timer.running:
self.new_release_timer.stop()
# Config set functions
def session_set_setting(self, key, value):
settings = self.session.settings()
setattr(settings, key, value)
self.session.set_settings(settings)
def _on_config_value_change(self, key, value):
component.get("EventManager").emit(ConfigValueChangedEvent(key, value))
@ -247,7 +258,7 @@ class PreferencesManager(component.Component):
# Only set the listen ports if random_port is not true
if self.config["random_port"] is not True:
log.debug("listen port range set to %s-%s", value[0], value[1])
self.session.listen_on(value[0], value[1], str(self.config["listen_interface"]))
self.session.listen_on(value[0], value[1], str(self.config["listen_interface"]).strip())
def _on_set_listen_interface(self, key, value):
# Call the random_port callback since it'll do what we need
@ -269,13 +280,12 @@ class PreferencesManager(component.Component):
# Set the listen ports
log.debug("listen port range set to %s-%s", listen_ports[0],
listen_ports[1])
self.session.listen_on(listen_ports[0], listen_ports[1], str(self.config["listen_interface"]))
self.session.listen_on(listen_ports[0], listen_ports[1], str(self.config["listen_interface"]).strip())
def _on_set_outgoing_ports(self, key, value):
if not self.config["random_outgoing_ports"]:
log.debug("outgoing port range set to %s-%s", value[0], value[1])
self.settings.outgoing_ports = value[0], value[1]
self.session.set_settings(self.settings)
self.session_set_setting("outgoing_ports", (value[0], value[1]))
def _on_set_random_outgoing_ports(self, key, value):
if value:
@ -284,20 +294,19 @@ class PreferencesManager(component.Component):
def _on_set_peer_tos(self, key, value):
log.debug("setting peer_tos to: %s", value)
try:
self.settings.peer_tos = chr(int(value, 16))
self.session_set_setting("peer_tos", chr(int(value, 16)))
except ValueError, e:
log.debug("Invalid tos byte: %s", e)
return
self.session.set_settings(self.settings)
def _on_set_dht(self, key, value):
log.debug("dht value set to %s", value)
state_file = deluge.configmanager.get_config_dir("dht.state")
if value:
state = None
try:
state = lt.bdecode(open(state_file, "rb").read())
with open(state_file, "rb") as _file:
state = lt.bdecode(_file.read())
except Exception, e:
log.warning("Unable to read DHT state file: %s", e)
@ -336,16 +345,19 @@ class PreferencesManager(component.Component):
def _on_set_utpex(self, key, value):
log.debug("utpex value set to %s", value)
if value:
self.session.add_extension(lt.create_ut_pex_plugin)
# In libtorrent versions below 0.16.7.0 disable extension bindings due to GIL issue.
# https://code.google.com/p/libtorrent/issues/detail?id=369
if value and deluge.common.VersionSplit(lt.version) >= deluge.common.VersionSplit("0.16.7.0"):
self.session.add_extension("ut_pex")
def _on_set_encryption(self, key, value):
log.debug("encryption value %s set to %s..", key, value)
pe_enc_level = {0: lt.enc_level.plaintext, 1: lt.enc_level.rc4, 2: lt.enc_level.both}
pe_settings = lt.pe_settings()
pe_settings.out_enc_policy = \
lt.enc_policy(self.config["enc_out_policy"])
pe_settings.in_enc_policy = lt.enc_policy(self.config["enc_in_policy"])
pe_settings.allowed_enc_level = lt.enc_level(self.config["enc_level"])
pe_settings.allowed_enc_level = lt.enc_level(pe_enc_level[self.config["enc_level"]])
pe_settings.prefer_rc4 = self.config["enc_prefer_rc4"]
self.session.set_pe_settings(pe_settings)
set = self.session.get_pe_settings()
@ -387,51 +399,39 @@ class PreferencesManager(component.Component):
self.session.set_max_half_open_connections(value)
def _on_set_max_connections_per_second(self, key, value):
self.settings.connection_speed = value
self.session.set_settings(self.settings)
self.session_set_setting("connection_speed", value)
def _on_ignore_limits_on_local_network(self, key, value):
self.settings.ignore_limits_on_local_network = value
self.session.set_settings(self.settings)
self.session_set_setting("ignore_limits_on_local_network", value)
def _on_set_share_ratio_limit(self, key, value):
log.debug("%s set to %s..", key, value)
self.settings.share_ratio_limit = value
self.session.set_settings(self.settings)
self.session_set_setting("share_ratio_limit", value)
def _on_set_seed_time_ratio_limit(self, key, value):
log.debug("%s set to %s..", key, value)
self.settings.seed_time_ratio_limit = value
self.session.set_settings(self.settings)
self.session_set_setting("seed_time_ratio_limit", value)
def _on_set_seed_time_limit(self, key, value):
log.debug("%s set to %s..", key, value)
# This value is stored in minutes in deluge, but libtorrent wants seconds
self.settings.seed_time_limit = int(value * 60)
self.session.set_settings(self.settings)
self.session_set_setting("seed_time_limit", int(value * 60))
def _on_set_max_active_downloading(self, key, value):
log.debug("%s set to %s..", key, value)
log.debug("active_downloads: %s", self.settings.active_downloads)
self.settings.active_downloads = value
self.session.set_settings(self.settings)
self.session_set_setting("active_downloads", value)
def _on_set_max_active_seeding(self, key, value):
log.debug("%s set to %s..", key, value)
log.debug("active_seeds: %s", self.settings.active_seeds)
self.settings.active_seeds = value
self.session.set_settings(self.settings)
self.session_set_setting("active_seeds", value)
def _on_set_max_active_limit(self, key, value):
log.debug("%s set to %s..", key, value)
log.debug("active_limit: %s", self.settings.active_limit)
self.settings.active_limit = value
self.session.set_settings(self.settings)
self.session_set_setting("active_limit", value)
def _on_set_dont_count_slow_torrents(self, key, value):
log.debug("%s set to %s..", key, value)
self.settings.dont_count_slow_torrents = value
self.session.set_settings(self.settings)
self.session_set_setting("dont_count_slow_torrents", value)
def _on_send_info(self, key, value):
log.debug("Sending anonymous stats..")
@ -467,57 +467,59 @@ class PreferencesManager(component.Component):
if value:
log.debug("Checking for new release..")
threading.Thread(target=self.core.get_new_release).start()
if self.new_release_timer:
if self.new_release_timer and self.new_release_timer.running:
self.new_release_timer.stop()
# Set a timer to check for a new release every 3 days
self.new_release_timer = LoopingCall(
self._on_new_release_check, "new_release_check", True)
self.new_release_timer.start(72 * 60 * 60, False)
else:
if self.new_release_timer:
if self.new_release_timer and self.new_release_timer.running:
self.new_release_timer.stop()
def _on_set_proxies(self, key, value):
lt_single_proxy = deluge.common.VersionSplit(lt.version) >= deluge.common.VersionSplit("0.16.0.0")
for k, v in value.items():
if v["type"]:
proxy_settings = lt.proxy_settings()
proxy_settings.type = lt.proxy_type(v["type"])
proxy_settings.username = str(v["username"])
proxy_settings.password = str(v["password"])
proxy_settings.hostname = str(v["hostname"])
proxy_settings.port = v["port"]
log.debug("setting %s proxy settings", k)
getattr(self.session, "set_%s_proxy" % k)(proxy_settings)
if k != "peer" and lt_single_proxy:
# Only set peer proxy to stop overwriting proxy setting in libtorrent >= 0.16.
if v["hostname"]:
log.warning("Using libtorrent >= 0.16 ignores proxy settings for %s", k)
self.config["proxies"][k] = DEFAULT_PREFS["proxies"][k]
continue
proxy_settings = lt.proxy_settings()
proxy_settings.type = lt.proxy_type(v["type"])
proxy_settings.username = str(v["username"])
proxy_settings.password = str(v["password"])
proxy_settings.hostname = str(v["hostname"])
proxy_settings.port = v["port"]
log.debug("Setting %s proxy settings: %s", k, v)
getattr(self.session, "set_%s_proxy" % k)(proxy_settings)
def _on_rate_limit_ip_overhead(self, key, value):
log.debug("%s: %s", key, value)
self.settings.rate_limit_ip_overhead = value
self.session.set_settings(self.settings)
self.session_set_setting("rate_limit_ip_overhead", value)
def _on_geoip_db_location(self, key, value):
log.debug("%s: %s", key, value)
# Load the GeoIP DB for country look-ups if available
geoip_db = ""
if os.path.exists(value):
geoip_db = value
elif os.path.exists(pkg_resources.resource_filename("deluge", os.path.join("data", "GeoIP.dat"))):
geoip_db = pkg_resources.resource_filename("deluge", os.path.join("data", "GeoIP.dat"))
try:
self.core.geoip_instance = GeoIP.open(value, GeoIP.GEOIP_STANDARD)
except AttributeError:
try:
self.session.load_country_db(value)
except RuntimeError, ex:
log.error("Unable to load geoip database: %s", ex)
except AttributeError:
log.warning("GeoIP Unavailable")
else:
log.warning("Unable to find GeoIP database file!")
if geoip_db:
try:
self.session.load_country_db(str(geoip_db))
except Exception, e:
log.error("Unable to load geoip database!")
log.exception(e)
def _on_cache_size(self, key, value):
log.debug("%s: %s", key, value)
self.settings.cache_size = value
self.session.set_settings(self.settings)
self.session_set_setting("cache_size", value)
def _on_cache_expiry(self, key, value):
log.debug("%s: %s", key, value)
self.settings.cache_expiry = value
self.session.set_settings(self.settings)
self.session_set_setting("cache_expiry", value)

View File

@ -35,6 +35,8 @@
"""RPCServer Module"""
from __future__ import with_statement
import sys
import zlib
import os
@ -47,7 +49,11 @@ from twisted.internet import ssl, reactor, defer
from OpenSSL import crypto, SSL
from types import FunctionType
import deluge.rencode as rencode
try:
import rencode
except ImportError:
import deluge.rencode as rencode
from deluge.log import LOG as log
import deluge.component as component
@ -90,13 +96,13 @@ def export(auth_level=AUTH_LEVEL_DEFAULT):
def format_request(call):
"""
Format the RPCRequest message for debug printing
:param call: the request
:type call: a RPCRequest
:returns: a formatted string for printing
:rtype: str
"""
try:
s = call[1] + "("
@ -111,7 +117,7 @@ def format_request(call):
return "UnicodeEncodeError, call: %s" % call
else:
return s
class DelugeError(Exception):
pass
@ -127,7 +133,8 @@ class ServerContextFactory(object):
SSL transport.
"""
ssl_dir = deluge.configmanager.get_config_dir("ssl")
ctx = SSL.Context(SSL.SSLv3_METHOD)
ctx = SSL.Context(SSL.SSLv23_METHOD)
ctx.set_options(SSL.OP_NO_SSLv2 | SSL.OP_NO_SSLv3)
ctx.use_certificate_file(os.path.join(ssl_dir, "daemon.cert"))
ctx.use_privatekey_file(os.path.join(ssl_dir, "daemon.pkey"))
return ctx
@ -139,7 +146,7 @@ class DelugeRPCProtocol(Protocol):
"""
This method is called whenever data is received from a client. The
only message that a client sends to the server is a RPC Request message.
If the RPC Request message is valid, then the method is called in
If the RPC Request message is valid, then the method is called in
:meth:`dispatch`.
:param data: the data from the client. It should be a zlib compressed
@ -187,7 +194,7 @@ class DelugeRPCProtocol(Protocol):
:param data: the object that is to be sent to the client. This should
be one of the RPC message types.
:type data: object
"""
self.transport.write(zlib.compress(rencode.dumps(data)))
@ -197,8 +204,8 @@ class DelugeRPCProtocol(Protocol):
"""
peer = self.transport.getPeer()
log.info("Deluge Client connection made from: %s:%s", peer.host, peer.port)
# Set the initial auth level of this session to AUTH_LEVEL_NONE
self.factory.authorized_sessions[self.transport.sessionno] = AUTH_LEVEL_NONE
# Set the initial auth level of this session to AUTH_LEVEL_NONE and empty username.
self.factory.authorized_sessions[self.transport.sessionno] = (AUTH_LEVEL_NONE, "")
def connectionLost(self, reason):
"""
@ -254,7 +261,7 @@ class DelugeRPCProtocol(Protocol):
try:
ret = component.get("AuthManager").authorize(*args, **kwargs)
if ret:
self.factory.authorized_sessions[self.transport.sessionno] = ret
self.factory.authorized_sessions[self.transport.sessionno] = (ret, args[0])
self.factory.session_protocols[self.transport.sessionno] = self
except Exception, e:
sendError()
@ -283,7 +290,7 @@ class DelugeRPCProtocol(Protocol):
if method in self.factory.methods and self.transport.sessionno in self.factory.authorized_sessions:
try:
method_auth_requirement = self.factory.methods[method]._rpcserver_auth_level
auth_level = self.factory.authorized_sessions[self.transport.sessionno]
auth_level = self.factory.authorized_sessions[self.transport.sessionno][0]
if auth_level < method_auth_requirement:
# This session is not allowed to call this method
log.debug("Session %s is trying to call a method it is not authorized to call!", self.transport.sessionno)
@ -338,7 +345,7 @@ class RPCServer(component.Component):
self.factory = Factory()
self.factory.protocol = DelugeRPCProtocol
self.factory.session_id = -1
# Holds the registered methods
self.factory.methods = {}
# Holds the session_ids and auth levels
@ -417,26 +424,41 @@ class RPCServer(component.Component):
def get_session_id(self):
"""
Returns the session id of the current RPC.
:returns: the session id, this will be -1 if no connections have been made
:rtype: int
"""
return self.factory.session_id
def get_session_user(self):
"""
Returns the username calling the current RPC.
:returns: the username of the user calling the current RPC
:rtype: string
"""
session_id = self.get_session_id()
if session_id > -1 and session_id in self.factory.authorized_sessions:
return self.factory.authorized_sessions[session_id][1]
else:
# No connections made yet
return ""
def is_session_valid(self, session_id):
"""
Checks if the session is still valid, eg, if the client is still connected.
:param session_id: the session id
:type session_id: int
:returns: True if the session is valid
:rtype: bool
"""
return session_id in self.factory.authorized_sessions
def emit_event(self, event):
"""
Emits the event to interested clients.
@ -446,7 +468,7 @@ class RPCServer(component.Component):
"""
log.debug("intevents: %s", self.factory.interested_events)
# Find sessions interested in this event
for session_id, interest in self.factory.interested_events.iteritems():
for session_id, interest in self.factory.interested_events.items():
if event.name in interest:
log.debug("Emit Event: %s %s", event.name, event.args)
# This session is interested so send a RPC_EVENT
@ -473,10 +495,10 @@ def generate_ssl_keys():
"""
This method generates a new SSL key/cert.
"""
digest = "md5"
digest = "sha256"
# Generate key pair
pkey = crypto.PKey()
pkey.generate_key(crypto.TYPE_RSA, 1024)
pkey.generate_key(crypto.TYPE_RSA, 2048)
# Generate cert request
req = crypto.X509Req()
@ -489,7 +511,7 @@ def generate_ssl_keys():
cert = crypto.X509()
cert.set_serial_number(0)
cert.gmtime_adj_notBefore(0)
cert.gmtime_adj_notAfter(60*60*24*365*5) # Five Years
cert.gmtime_adj_notAfter(60 * 60 * 24 * 365 * 3) # Three Years
cert.set_issuer(req.get_subject())
cert.set_subject(req.get_subject())
cert.set_pubkey(req.get_pubkey())
@ -497,8 +519,10 @@ def generate_ssl_keys():
# Write out files
ssl_dir = deluge.configmanager.get_config_dir("ssl")
open(os.path.join(ssl_dir, "daemon.pkey"), "w").write(crypto.dump_privatekey(crypto.FILETYPE_PEM, pkey))
open(os.path.join(ssl_dir, "daemon.cert"), "w").write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert))
with open(os.path.join(ssl_dir, "daemon.pkey"), "w") as _file:
_file.write(crypto.dump_privatekey(crypto.FILETYPE_PEM, pkey))
with open(os.path.join(ssl_dir, "daemon.cert"), "w") as _file:
_file.write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert))
# Make the files only readable by this user
for f in ("daemon.pkey", "daemon.cert"):
os.chmod(os.path.join(ssl_dir, f), stat.S_IREAD | stat.S_IWRITE)

View File

@ -34,6 +34,8 @@
"""Internal Torrent class"""
from __future__ import with_statement
import os
import time
from urllib import unquote
@ -49,6 +51,31 @@ from deluge.event import *
TORRENT_STATE = deluge.common.TORRENT_STATE
def sanitize_filepath(filepath, folder=False):
"""
Returns a sanitized filepath to pass to libotorrent rename_file().
The filepath will have backslashes substituted along with whitespace
padding and duplicate slashes stripped. If `folder` is True a trailing
slash is appended to the returned filepath.
"""
def clean_filename(filename):
filename = filename.strip()
if filename.replace('.', '') == '':
return ''
return filename
if '\\' in filepath or '/' in filepath:
folderpath = filepath.replace('\\', '/').split('/')
folderpath = [clean_filename(x) for x in folderpath]
newfilepath = '/'.join(filter(None, folderpath))
else:
newfilepath = clean_filename(filepath)
if folder is True:
return newfilepath + '/'
else:
return newfilepath
class TorrentOptions(dict):
def __init__(self):
config = ConfigManager("core.conf").config
@ -73,6 +100,14 @@ class TorrentOptions(dict):
self["file_priorities"] = []
self["mapped_files"] = {}
class TorrentError(object):
def __init__(self, error_message, was_paused=False, restart_to_resume=False):
self.error_message = error_message
self.was_paused = was_paused
self.restart_to_resume = restart_to_resume
class Torrent(object):
"""Torrent holds information about torrents added to the libtorrent session.
"""
@ -82,7 +117,7 @@ class Torrent(object):
self.config = ConfigManager("core.conf")
self.rpcserver = component.get("RPCServer")
# This dict holds previous status dicts returned for this torrent
# We use this to return dicts that only contain changes from the previous
# {session_id: status_dict, ...}
@ -90,7 +125,7 @@ class Torrent(object):
from twisted.internet.task import LoopingCall
self.prev_status_cleanup_loop = LoopingCall(self.cleanup_prev_status)
self.prev_status_cleanup_loop.start(10)
# Set the libtorrent handle
self.handle = handle
# Set the torrent_id for this torrent
@ -116,6 +151,9 @@ class Torrent(object):
# Store the magnet uri used to add this torrent if available
self.magnet = magnet
# Torrent state e.g. Paused, Downloading, etc.
self.state = None
# Holds status info so that we don't need to keep getting it from lt
self.status = self.handle.status()
@ -149,7 +187,7 @@ class Torrent(object):
self.trackers = []
# Create a list of trackers
for value in self.handle.trackers():
if lt.version_minor < 15:
if lt.version_major == 0 and lt.version_minor < 15:
tracker = {}
tracker["url"] = value.url
tracker["tier"] = value.tier
@ -160,11 +198,14 @@ class Torrent(object):
# Various torrent options
self.handle.resolve_countries(True)
self.set_options(self.options)
# Details of torrent forced into error state (i.e. not by libtorrent).
self.forced_error = None
# Status message holds error info about the torrent
self.statusmsg = "OK"
self.set_options(self.options)
# The torrents state
self.update_state()
@ -179,7 +220,10 @@ class Torrent(object):
else:
self.time_added = time.time()
log.debug("Torrent object created.")
# Keep track if we're forcing a recheck of the torrent so that we can
# repause it after its done if necessary
self.forcing_recheck = False
self.forcing_recheck_paused = False
## Options methods ##
def set_options(self, options):
@ -205,6 +249,10 @@ class Torrent(object):
def set_max_connections(self, max_connections):
if max_connections == 0:
max_connections = -1
elif max_connections == 1:
max_connections = 2
self.options["max_connections"] = int(max_connections)
self.handle.set_max_connections(max_connections)
@ -230,11 +278,11 @@ class Torrent(object):
self.handle.set_download_limit(v)
def set_prioritize_first_last(self, prioritize):
self.options["prioritize_first_last_pieces"] = prioritize
if prioritize:
if self.handle.has_metadata():
if self.handle.get_torrent_info().num_files() == 1:
# We only do this if one file is in the torrent
self.options["prioritize_first_last_pieces"] = prioritize
priorities = [1] * self.handle.get_torrent_info().num_pieces()
priorities[0] = 7
priorities[-1] = 7
@ -262,19 +310,19 @@ class Torrent(object):
self.options["move_completed_path"] = move_completed_path
def set_file_priorities(self, file_priorities):
if len(file_priorities) != len(self.get_files()):
log.debug("file_priorities len != num_files")
self.options["file_priorities"] = self.handle.file_priorities()
return
if self.options["compact_allocation"]:
log.debug("setting file priority with compact allocation does not work!")
self.options["file_priorities"] = self.handle.file_priorities()
return
handle_file_priorities = self.handle.file_priorities()
# Workaround for libtorrent 1.1 changing default priorities from 1 to 4.
if 4 in handle_file_priorities:
handle_file_priorities = [1 if x == 4 else x for x in handle_file_priorities]
log.debug("setting %s's file priorities: %s", self.torrent_id, file_priorities)
self.handle.prioritize_files(file_priorities)
if (self.handle.has_metadata() and not self.options["compact_allocation"] and
file_priorities and len(file_priorities) == len(self.get_files())):
self.handle.prioritize_files(file_priorities)
else:
log.debug("Unable to set new file priorities.")
file_priorities = handle_file_priorities
if 0 in self.options["file_priorities"]:
# We have previously marked a file 'Do Not Download'
@ -286,19 +334,24 @@ class Torrent(object):
self.update_state()
break
self.options["file_priorities"] = file_priorities
self.options["file_priorities"] = handle_file_priorities
if self.options["file_priorities"] != list(file_priorities):
log.warning("File priorities were not set for this torrent")
# Set the first/last priorities if needed
self.set_prioritize_first_last(self.options["prioritize_first_last_pieces"])
def set_trackers(self, trackers):
def set_trackers(self, trackers, reannounce=True):
"""Sets trackers"""
if trackers == None:
trackers = []
for value in self.handle.trackers():
tracker = {}
tracker["url"] = value.url
tracker["tier"] = value.tier
if lt.version_major == 0 and lt.version_minor < 15:
tracker = {}
tracker["url"] = value.url
tracker["tier"] = value.tier
else:
tracker = value
trackers.append(tracker)
self.trackers = trackers
self.tracker_host = None
@ -318,7 +371,7 @@ class Torrent(object):
# log.debug("tier: %s tracker: %s", t["tier"], t["url"])
# Set the tracker list in the torrent object
self.trackers = trackers
if len(trackers) > 0:
if len(trackers) > 0 and reannounce:
# Force a reannounce if there is at least 1 tracker
self.force_reannounce()
@ -331,48 +384,56 @@ class Torrent(object):
def set_tracker_status(self, status):
"""Sets the tracker status"""
self.tracker_host = None
self.tracker_status = self.get_tracker_host() + ": " + status
def update_state(self):
"""Updates the state based on what libtorrent's state for the torrent is"""
# Set the initial state based on the lt state
LTSTATE = deluge.common.LT_TORRENT_STATE
ltstate = int(self.handle.status().state)
status = self.handle.status()
ltstate = status.state
# Set self.state to the ltstate right away just incase we don't hit some
# of the logic below
self.state = str(ltstate)
# Set self.state to the ltstate right away just incase we don't hit some of the logic below
old_state = self.state
self.state = LTSTATE.get(int(ltstate), str(ltstate))
log.debug("set_state_based_on_ltstate: %s", deluge.common.LT_TORRENT_STATE[ltstate])
log.debug("session.is_paused: %s", component.get("Core").session.is_paused())
is_paused = self.handle.is_paused()
is_auto_managed = self.handle.is_auto_managed()
session_paused = component.get("Core").session.is_paused()
# First we check for an error from libtorrent, and set the state to that
# if any occurred.
if len(self.handle.status().error) > 0:
if self.forced_error:
self.state = "Error"
self.set_status_message("Error: " + self.forced_error.error_message)
elif status.error:
# This is an error'd torrent
self.state = "Error"
self.set_status_message(self.handle.status().error)
if self.handle.is_paused():
self.set_status_message(status.error)
if is_paused:
self.handle.auto_managed(False)
return
if ltstate == LTSTATE["Queued"] or ltstate == LTSTATE["Checking"]:
if self.handle.is_paused():
else:
if is_paused and is_auto_managed and not session_paused:
self.state = "Queued"
elif is_paused or session_paused:
self.state = "Paused"
else:
elif ltstate == LTSTATE["Queued"] or ltstate == LTSTATE["Checking"] or \
ltstate == LTSTATE["Checking Resume Data"]:
self.state = "Checking"
return
elif ltstate == LTSTATE["Downloading"] or ltstate == LTSTATE["Downloading Metadata"]:
self.state = "Downloading"
elif ltstate == LTSTATE["Finished"] or ltstate == LTSTATE["Seeding"]:
self.state = "Seeding"
elif ltstate == LTSTATE["Allocating"]:
self.state = "Allocating"
elif ltstate == LTSTATE["Downloading"] or ltstate == LTSTATE["Downloading Metadata"]:
self.state = "Downloading"
elif ltstate == LTSTATE["Finished"] or ltstate == LTSTATE["Seeding"]:
self.state = "Seeding"
elif ltstate == LTSTATE["Allocating"]:
self.state = "Allocating"
if self.handle.is_paused() and self.handle.is_auto_managed() and not component.get("Core").session.is_paused():
self.state = "Queued"
elif component.get("Core").session.is_paused() or (self.handle.is_paused() and not self.handle.is_auto_managed()):
self.state = "Paused"
if self.state != old_state:
log.debug("Using torrent state from lt: %s, auto_managed: %s, paused: %s, session_paused: %s",
ltstate, is_auto_managed, is_paused, session_paused)
log.debug("Torrent %s set from %s to %s: '%s'",
self.torrent_id, old_state, self.state, self.statusmsg)
component.get("EventManager").emit(TorrentStateChangedEvent(self.torrent_id, self.state))
def set_state(self, state):
"""Accepts state strings, ie, "Paused", "Seeding", etc."""
@ -386,6 +447,37 @@ class Torrent(object):
def set_status_message(self, message):
self.statusmsg = message
def force_error_state(self, message, restart_to_resume=True):
"""Forces the torrent into an error state.
For setting an error state not covered by libtorrent.
Args:
message (str): The error status message.
restart_to_resume (bool, optional): Prevent resuming clearing the error, only restarting
session can resume.
"""
status = self.handle.status()
self.handle.auto_managed(False)
self.forced_error = TorrentError(message, status.paused, restart_to_resume)
if not status.paused:
self.handle.pause()
self.update_state()
def clear_forced_error_state(self, update_state=True):
if not self.forced_error:
return
if self.forced_error.restart_to_resume:
log.error("Restart deluge to clear this torrent error")
if not self.forced_error.was_paused and self.options["auto_managed"]:
self.handle.auto_managed(True)
self.forced_error = None
self.set_status_message("OK")
if update_state:
self.update_state()
def get_eta(self):
"""Returns the ETA in seconds for this torrent"""
if self.status == None:
@ -393,15 +485,14 @@ class Torrent(object):
else:
status = self.status
if self.is_finished and (self.options["stop_at_ratio"] or self.config["stop_seed_at_ratio"]):
if self.is_finished and self.options["stop_at_ratio"]:
# We're a seed, so calculate the time to the 'stop_share_ratio'
if not status.upload_payload_rate:
return 0
stop_ratio = self.config["stop_seed_ratio"] if self.config["stop_seed_at_ratio"] else self.options["stop_ratio"]
stop_ratio = self.options["stop_ratio"]
return ((status.all_time_download * stop_ratio) - status.all_time_upload) / status.upload_payload_rate
left = status.total_wanted - status.total_done
left = status.total_wanted - status.total_wanted_done
if left <= 0 or status.download_payload_rate == 0:
return 0
@ -444,7 +535,8 @@ class Torrent(object):
for index, file in enumerate(files):
ret.append({
'index': index,
'path': file.path.decode("utf8", "ignore"),
# Make path separators consistent across platforms
'path': file.path.decode("utf8").replace('\\', '/'),
'size': file.size,
'offset': file.offset
})
@ -464,22 +556,24 @@ class Torrent(object):
except UnicodeDecodeError:
client = str(peer.client).decode("latin-1")
# Make country a proper string
country = str()
for c in peer.country:
if not c.isalpha():
country += " "
else:
country += c
try:
country = component.get("Core").geoip_instance.country_code_by_addr(peer.ip[0])
except AttributeError:
country = peer.country
try:
country = "".join([char if char.isalpha() else " " for char in country])
except TypeError:
country = ""
ret.append({
"client": client,
"country": country,
"down_speed": peer.down_speed,
"down_speed": peer.payload_down_speed,
"ip": "%s:%s" % (peer.ip[0], peer.ip[1]),
"progress": peer.progress,
"seed": peer.flags & peer.seed,
"up_speed": peer.up_speed,
"up_speed": peer.payload_up_speed,
})
return ret
@ -488,10 +582,21 @@ class Torrent(object):
"""Returns the torrents queue position"""
return self.handle.queue_position()
def get_file_priorities(self):
"""Return the file priorities"""
if not self.handle.has_metadata():
return []
if not self.options["file_priorities"]:
# Ensure file_priorities option is populated.
self.set_file_priorities([])
return self.options["file_priorities"]
def get_file_progress(self):
"""Returns the file progress as a list of floats.. 0.0 -> 1.0"""
if not self.handle.has_metadata():
return 0.0
return []
file_progress = self.handle.file_progress()
ret = []
@ -500,6 +605,8 @@ class Torrent(object):
ret.append(float(file_progress[i]) / float(f["size"]))
except ZeroDivisionError:
ret.append(0.0)
except IndexError:
return []
return ret
@ -543,18 +650,18 @@ class Torrent(object):
def get_status(self, keys, diff=False):
"""
Returns the status of the torrent based on the keys provided
:param keys: the keys to get the status on
:type keys: list of str
:param diff: if True, will return a diff of the changes since the last
call to get_status based on the session_id
:type diff: bool
:returns: a dictionary of the status keys and their values
:rtype: dict
"""
# Create the full dictionary
self.status = self.handle.status()
if self.handle.has_metadata():
@ -568,6 +675,13 @@ class Torrent(object):
if distributed_copies < 0:
distributed_copies = 0.0
# Calculate the seeds:peers ratio
if self.status.num_incomplete == 0:
# Use -1.0 to signify infinity
seeds_peers_ratio = -1.0
else:
seeds_peers_ratio = self.status.num_complete / float(self.status.num_incomplete)
#if you add a key here->add it to core.py STATUS_KEYS too.
full_status = {
"active_time": self.status.active_time,
@ -575,7 +689,6 @@ class Torrent(object):
"compact": self.options["compact_allocation"],
"distributed_copies": distributed_copies,
"download_payload_rate": self.status.download_payload_rate,
"file_priorities": self.options["file_priorities"],
"hash": self.torrent_id,
"is_auto_managed": self.options["auto_managed"],
"is_finished": self.is_finished,
@ -586,6 +699,8 @@ class Torrent(object):
"message": self.statusmsg,
"move_on_completed_path": self.options["move_completed_path"],
"move_on_completed": self.options["move_completed"],
"move_completed_path": self.options["move_completed_path"],
"move_completed": self.options["move_completed"],
"next_announce": self.status.next_announce.seconds,
"num_peers": self.status.num_peers - self.status.num_seeds,
"num_seeds": self.status.num_seeds,
@ -595,6 +710,7 @@ class Torrent(object):
"remove_at_ratio": self.options["remove_at_ratio"],
"save_path": self.options["download_location"],
"seeding_time": self.status.seeding_time,
"seeds_peers_ratio": seeds_peers_ratio,
"seed_rank": self.status.seed_rank,
"state": self.state,
"stop_at_ratio": self.options["stop_at_ratio"],
@ -623,7 +739,7 @@ class Torrent(object):
def ti_name():
if self.handle.has_metadata():
name = self.torrent_info.file_at(0).path.split("/", 1)[0]
name = self.torrent_info.file_at(0).path.replace("\\", "/", 1).split("/", 1)[0]
if not name:
name = self.torrent_info.name()
try:
@ -671,6 +787,7 @@ class Torrent(object):
fns = {
"comment": ti_comment,
"eta": self.get_eta,
"file_priorities": self.get_file_priorities,
"file_progress": self.get_file_progress,
"files": self.get_files,
"is_seed": self.handle.is_seed,
@ -699,7 +816,7 @@ class Torrent(object):
status_dict[key] = full_status[key]
elif key in fns:
status_dict[key] = fns[key]()
session_id = self.rpcserver.get_session_id()
if diff:
if session_id in self.prev_status:
@ -711,7 +828,7 @@ class Torrent(object):
status_diff[key] = value
else:
status_diff[key] = value
self.prev_status[session_id] = status_dict
return status_diff
@ -731,6 +848,8 @@ class Torrent(object):
def pause(self):
"""Pause this torrent"""
if self.state == "Error":
return False
# Turn off auto-management so the torrent will not be unpaused by lt queueing
self.handle.auto_managed(False)
if self.handle.is_paused():
@ -754,20 +873,16 @@ class Torrent(object):
if self.handle.is_paused() and self.handle.is_auto_managed():
log.debug("Torrent is being auto-managed, cannot resume!")
return
elif self.forced_error and self.forced_error.was_paused:
log.debug("Skip resuming Error state torrent that was originally paused.")
else:
# Reset the status message just in case of resuming an Error'd torrent
self.set_status_message("OK")
if self.handle.is_finished():
# If the torrent has already reached it's 'stop_seed_ratio' then do not do anything
if self.config["stop_seed_at_ratio"] or self.options["stop_at_ratio"]:
if self.options["stop_at_ratio"]:
ratio = self.options["stop_ratio"]
else:
ratio = self.config["stop_seed_ratio"]
if self.get_ratio() >= ratio:
if self.options["stop_at_ratio"]:
if self.get_ratio() >= self.options["stop_ratio"]:
#XXX: This should just be returned in the RPC Response, no event
#self.signals.emit_event("torrent_resume_at_stop_ratio")
return
@ -783,6 +898,11 @@ class Torrent(object):
return True
if self.forced_error and not self.forced_error.restart_to_resume:
self.clear_forced_error_state()
elif self.state == "Error" and not self.forced_error:
self.handle.clear_error()
def connect_peer(self, ip, port):
"""adds manual peer"""
try:
@ -795,8 +915,33 @@ class Torrent(object):
def move_storage(self, dest):
"""Move a torrent's storage location"""
try:
self.handle.move_storage(dest.encode("utf8"))
except:
dest = unicode(dest, "utf-8")
except TypeError:
# String is already unicode
pass
if not os.path.exists(dest):
try:
# Try to make the destination path if it doesn't exist
os.makedirs(dest)
except OSError, ex:
log.error("Could not move storage for torrent %s since %s does "
"not exist and could not create the directory: %s",
self.torrent_id, dest, ex)
return False
kwargs = {}
if deluge.common.VersionSplit(lt.version) >= deluge.common.VersionSplit("1.0.0.0"):
kwargs['flags'] = 2 # dont_replace
dest_bytes = dest.encode('utf-8')
try:
# libtorrent needs unicode object if wstrings are enabled, utf8 bytestring otherwise
try:
self.handle.move_storage(dest, **kwargs)
except TypeError:
self.handle.move_storage(dest_bytes, **kwargs)
except Exception, e:
log.error("Error calling libtorrent move_storage: %s" % e)
return False
return True
@ -804,8 +949,17 @@ class Torrent(object):
def save_resume_data(self):
"""Signals libtorrent to build resume data for this torrent, it gets
returned in a libtorrent alert"""
self.handle.save_resume_data()
self.waiting_on_resume_data = True
# Don't generate fastresume data if torrent is in a Deluge Error state.
if self.forced_error:
log.debug("Skipped creating resume_data while in Error state")
else:
self.handle.save_resume_data()
self.waiting_on_resume_data = True
def on_metadata_received(self):
if self.options["prioritize_first_last_pieces"]:
self.set_prioritize_first_last(True)
self.write_torrentfile()
def write_torrentfile(self):
"""Writes the torrent file"""
@ -820,7 +974,8 @@ class Torrent(object):
md = lt.bdecode(self.torrent_info.metadata())
torrent_file = {}
torrent_file["info"] = md
open(path, "wb").write(lt.bencode(torrent_file))
with open(path, "wb") as _file:
_file.write(lt.bencode(torrent_file))
except Exception, e:
log.warning("Unable to save torrent file: %s", e)
@ -857,19 +1012,43 @@ class Torrent(object):
def force_recheck(self):
"""Forces a recheck of the torrents pieces"""
self.forcing_recheck = True
if self.forced_error:
self.forcing_recheck_paused = self.forced_error.was_paused
self.clear_forced_error_state(update_state=False)
else:
self.forcing_recheck_paused = self.handle.is_paused()
# Store trackers for paused torrents to prevent unwanted announce before pausing again.
if self.forcing_recheck_paused:
self.set_trackers(None, reannounce=False)
self.handle.replace_trackers([])
try:
self.handle.force_recheck()
self.handle.resume()
except Exception, e:
log.debug("Unable to force recheck: %s", e)
return False
return True
self.forcing_recheck = False
if self.forcing_recheck_paused:
self.set_trackers(torrent.trackers, reannounce=False)
return self.forcing_recheck
def rename_files(self, filenames):
"""Renames files in the torrent. 'filenames' should be a list of
(index, filename) pairs."""
for index, filename in filenames:
self.handle.rename_file(index, filename.encode("utf-8"))
# Make sure filename is a unicode object
try:
filename = unicode(filename, "utf-8")
except TypeError:
pass
filename = sanitize_filepath(filename)
# libtorrent needs unicode object if wstrings are enabled, utf8 bytestring otherwise
try:
self.handle.rename_file(index, filename)
except TypeError:
self.handle.rename_file(index, filename.encode("utf-8"))
def rename_folder(self, folder, new_folder):
"""Renames a folder within a torrent. This basically does a file rename
@ -879,24 +1058,26 @@ class Torrent(object):
log.error("Attempting to rename a folder with an invalid folder name: %s", new_folder)
return
if new_folder[-1:] != "/":
new_folder += "/"
new_folder = sanitize_filepath(new_folder, folder=True)
wait_on_folder = (folder, new_folder, [])
for f in self.get_files():
if f["path"].startswith(folder):
# Keep a list of filerenames we're waiting on
wait_on_folder[2].append(f["index"])
self.handle.rename_file(f["index"], f["path"].replace(folder, new_folder, 1).encode("utf-8"))
new_path = f["path"].replace(folder, new_folder, 1)
try:
self.handle.rename_file(f["index"], new_path)
except TypeError:
self.handle.rename_file(f["index"], new_path.encode("utf-8"))
self.waiting_on_folder_rename.append(wait_on_folder)
def cleanup_prev_status(self):
"""
This method gets called to check the validity of the keys in the prev_status
dict. If the key is no longer valid, the dict will be deleted.
"""
for key in self.prev_status.keys():
if not self.rpcserver.is_session_valid(key):
del self.prev_status[key]

View File

@ -17,9 +17,9 @@
#
# You should have received a copy of the GNU General Public License
# along with deluge. If not, write to:
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
#
# In addition, as a special exception, the copyright holders give
# permission to link the code of portions of this program with the OpenSSL
@ -41,22 +41,21 @@ import os
import time
import shutil
import operator
import re
from twisted.internet import reactor
from twisted.internet.task import LoopingCall
from deluge._libtorrent import lt
from deluge.event import *
from deluge.error import *
import deluge.common
import deluge.component as component
from deluge.configmanager import ConfigManager, get_config_dir
from deluge.core.torrent import Torrent
from deluge.core.torrent import TorrentOptions
import deluge.core.oldstateupgrader
from deluge.ui.common import utf8_encoded
from deluge.common import utf8_encoded, decode_string
from deluge.log import LOG as log
@ -139,6 +138,7 @@ class TorrentManager(component.Component):
# Create the torrents dict { torrent_id: Torrent }
self.torrents = {}
self.queued_torrents = set()
# This is a list of torrent_id when we shutdown the torrentmanager.
# We use this list to determine if all active torrents have been paused
@ -148,9 +148,15 @@ class TorrentManager(component.Component):
# self.num_resume_data used to save resume_data in bulk
self.num_resume_data = 0
# Keep track of torrents finished but moving storage
self.waiting_on_finish_moving = []
# Keeps track of resume data that needs to be saved to disk
self.resume_data = {}
# Workaround to determine if TorrentAddedEvent is from state file
self.session_started = False
# Register set functions
self.config.register_set_function("max_connections_per_torrent",
self.on_set_max_connections_per_torrent)
@ -178,6 +184,8 @@ class TorrentManager(component.Component):
self.on_alert_tracker_error)
self.alerts.register_handler("storage_moved_alert",
self.on_alert_storage_moved)
self.alerts.register_handler("storage_moved_failed_alert",
self.on_alert_storage_moved_failed)
self.alerts.register_handler("torrent_resumed_alert",
self.on_alert_torrent_resumed)
self.alerts.register_handler("state_changed_alert",
@ -192,6 +200,14 @@ class TorrentManager(component.Component):
self.on_alert_metadata_received)
self.alerts.register_handler("file_error_alert",
self.on_alert_file_error)
self.alerts.register_handler("file_completed_alert",
self.on_alert_file_completed)
self.alerts.register_handler("fastresume_rejected_alert",
self.on_alert_fastresume_rejected)
# Define timers
self.save_state_timer = LoopingCall(self.save_state)
self.save_resume_data_timer = LoopingCall(self.save_resume_data)
def start(self):
# Get the pluginmanager reference
@ -200,14 +216,12 @@ class TorrentManager(component.Component):
# Run the old state upgrader before loading state
deluge.core.oldstateupgrader.OldStateUpgrader()
# Try to load the state from file
# Try to load the state from file.
self.load_state()
# Save the state every 5 minutes
self.save_state_timer = LoopingCall(self.save_state)
# Save the state and resume data every ~3 minutes.
self.save_state_timer.start(200, False)
self.save_resume_data_timer = LoopingCall(self.save_resume_data)
self.save_resume_data_timer.start(190)
self.save_resume_data_timer.start(190, False)
def stop(self):
# Stop timers
@ -256,16 +270,13 @@ class TorrentManager(component.Component):
def update(self):
for torrent_id, torrent in self.torrents.items():
if self.config["stop_seed_at_ratio"] or torrent.options["stop_at_ratio"] and torrent.state not in ("Checking", "Allocating", "Paused", "Queued"):
if torrent.options["stop_at_ratio"] and torrent.state not in ("Checking", "Allocating", "Paused", "Queued"):
# If the global setting is set, but the per-torrent isn't.. Just skip to the next torrent
# This is so that a user can turn-off the stop at ratio option on a per-torrent basis
if self.config["stop_seed_at_ratio"] and not torrent.options["stop_at_ratio"]:
if not torrent.options["stop_at_ratio"]:
continue
stop_ratio = self.config["stop_seed_ratio"]
if torrent.options["stop_at_ratio"]:
stop_ratio = torrent.options["stop_ratio"]
if torrent.get_ratio() >= stop_ratio and torrent.is_finished:
if self.config["remove_seed_at_ratio"] or torrent.options["remove_at_ratio"]:
if torrent.get_ratio() >= torrent.options["stop_ratio"] and torrent.is_finished:
if torrent.options["remove_at_ratio"]:
self.remove(torrent_id)
break
if not torrent.handle.is_paused():
@ -374,9 +385,44 @@ class TorrentManager(component.Component):
resume_data = self.legacy_get_resume_data_from_file(state.torrent_id)
self.legacy_delete_resume_data(state.torrent_id)
add_torrent_params["resume_data"] = resume_data
if resume_data:
add_torrent_params["resume_data"] = resume_data
else:
# We have a torrent_info object so we're not loading from state.
# We have a torrent_info object or magnet uri so we're not loading from state.
if torrent_info:
add_torrent_id = str(torrent_info.info_hash())
# If this torrent id is already in the session, merge any additional trackers.
if add_torrent_id in self.get_torrent_list():
log.info("Merging trackers for torrent (%s) already in session...", add_torrent_id)
# Don't merge trackers if either torrent has private flag set
if torrent_info.priv() or self[add_torrent_id].get_status(["private"])["private"]:
log.info("Merging trackers abandoned: Torrent has private flag set.")
return
add_torrent_trackers = []
for value in torrent_info.trackers():
tracker = {}
tracker["url"] = value.url
tracker["tier"] = value.tier
add_torrent_trackers.append(tracker)
torrent_trackers = {}
tracker_list = []
for tracker in self[add_torrent_id].get_status(["trackers"])["trackers"]:
torrent_trackers[(tracker["url"])] = tracker
tracker_list.append(tracker)
added_tracker = 0
for tracker in add_torrent_trackers:
if tracker['url'] not in torrent_trackers:
tracker_list.append(tracker)
added_tracker += 1
if added_tracker:
log.info("%s tracker(s) merged into torrent.", added_tracker)
self[add_torrent_id].set_trackers(tracker_list)
return
# Check if options is None and load defaults
if options == None:
options = TorrentOptions()
@ -388,12 +434,19 @@ class TorrentManager(component.Component):
# Check for renamed files and if so, rename them in the torrent_info
# before adding to the session.
if options["mapped_files"]:
for index, name in options["mapped_files"].items():
log.debug("renaming file index %s to %s", index, name)
torrent_info.rename_file(index, utf8_encoded(name))
for index, fname in options["mapped_files"].items():
try:
fname = unicode(fname, "utf-8")
except TypeError:
pass
fname = deluge.core.torrent.sanitize_filepath(fname)
log.debug("renaming file index %s to %s", index, fname)
try:
torrent_info.rename_file(index, fname)
except TypeError:
torrent_info.rename_file(index, fname.encode("utf-8"))
add_torrent_params["ti"] = torrent_info
add_torrent_params["resume_data"] = ""
#log.info("Adding torrent: %s", filename)
log.debug("options: %s", options)
@ -418,7 +471,8 @@ class TorrentManager(component.Component):
handle = None
try:
if magnet:
handle = lt.add_magnet_uri(self.session, magnet, add_torrent_params)
magnet_uri = utf8_encoded(magnet.strip())
handle = lt.add_magnet_uri(self.session, magnet_uri, add_torrent_params)
else:
handle = self.session.add_torrent(add_torrent_params)
except RuntimeError, e:
@ -442,10 +496,17 @@ class TorrentManager(component.Component):
component.resume("AlertManager")
# Store the orignal resume_data, in case of errors.
if resume_data:
self.resume_data[torrent.torrent_id] = resume_data
# Resume the torrent if needed
if not options["add_paused"]:
torrent.resume()
# Add to queued torrents set
self.queued_torrents.add(torrent.torrent_id)
# Write the .torrent file to the state directory
if filedump:
try:
@ -476,6 +537,7 @@ class TorrentManager(component.Component):
# Emit the torrent_added signal
component.get("EventManager").emit(TorrentAddedEvent(torrent.torrent_id))
log.info("Torrent %s added by user: %s", torrent.get_status(["name"])["name"], component.get("RPCServer").get_session_user())
return torrent.torrent_id
def load_torrent(self, torrent_id):
@ -511,8 +573,9 @@ class TorrentManager(component.Component):
:raises InvalidTorrentError: if the torrent_id is not in the session
"""
if torrent_id not in self.torrents:
try:
torrent_name = self.torrents[torrent_id].get_status(["name"])["name"]
except KeyError:
raise InvalidTorrentError("torrent_id not in session")
# Emit the signal to the clients
@ -551,10 +614,17 @@ class TorrentManager(component.Component):
# Stop the looping call
self.torrents[torrent_id].prev_status_cleanup_loop.stop()
# Remove from set if it wasn't finished
if not self.torrents[torrent_id].is_finished:
try:
self.queued_torrents.remove(torrent_id)
except KeyError:
log.debug("%s isn't in queued torrents set?", torrent_id)
# Remove the torrent from deluge's session
try:
del self.torrents[torrent_id]
except KeyError, ValueError:
except (KeyError, ValueError):
return False
# Save the session state
@ -562,26 +632,29 @@ class TorrentManager(component.Component):
# Emit the signal to the clients
component.get("EventManager").emit(TorrentRemovedEvent(torrent_id))
log.info("Torrent %s removed by user: %s", torrent_name, component.get("RPCServer").get_session_user())
return True
def load_state(self):
"""Load the state of the TorrentManager from the torrents.state file"""
state = TorrentManagerState()
try:
log.debug("Opening torrent state file for load.")
state_file = open(
os.path.join(get_config_dir(), "state", "torrents.state"), "rb")
state = cPickle.load(state_file)
state_file.close()
except (EOFError, IOError, Exception), e:
log.warning("Unable to load state file: %s", e)
filepath = os.path.join(get_config_dir(), "state", "torrents.state")
log.debug("Opening torrent state file for load.")
for _filepath in (filepath, filepath + ".bak"):
try:
state_file = open(_filepath, "rb")
state = cPickle.load(state_file)
state_file.close()
except (EOFError, IOError, Exception, cPickle.UnpicklingError), e:
log.warning("Unable to load state file: %s", e)
state = TorrentManagerState()
else:
log.info("Successfully loaded state file: %s", _filepath)
break
# Try to use an old state
try:
state_tmp = TorrentState()
if dir(state.torrents[0]) != dir(state_tmp):
if state.torrents and dir(state.torrents[0]) != dir(state_tmp):
for attr in (set(dir(state_tmp)) - set(dir(state.torrents[0]))):
for s in state.torrents:
setattr(s, attr, getattr(state_tmp, attr, None))
@ -590,7 +663,7 @@ class TorrentManager(component.Component):
# Reorder the state.torrents list to add torrents in the correct queue
# order.
state.torrents.sort(key=operator.attrgetter("queue"))
state.torrents.sort(key=operator.attrgetter("queue"), reverse=self.config["queue_new_to_top"])
resume_data = self.load_resume_data_file()
@ -602,6 +675,7 @@ class TorrentManager(component.Component):
log.error("Torrent state file is either corrupt or incompatible! %s", e)
break
self.session_started = True
component.get("EventManager").emit(SessionStartedEvent())
def save_state(self):
@ -609,9 +683,14 @@ class TorrentManager(component.Component):
state = TorrentManagerState()
# Create the state for each Torrent and append to the list
for torrent in self.torrents.values():
paused = False
if torrent.state == "Paused":
if self.session.is_paused():
paused = torrent.handle.is_paused()
elif torrent.forced_error:
paused = torrent.forced_error.was_paused
elif torrent.state == "Paused":
paused = True
else:
paused = False
torrent_state = TorrentState(
torrent.torrent_id,
@ -641,26 +720,32 @@ class TorrentManager(component.Component):
state.torrents.append(torrent_state)
# Pickle the TorrentManagerState object
filepath = os.path.join(get_config_dir(), "state", "torrents.state")
filepath_tmp = filepath + ".tmp"
filepath_bak = filepath + ".bak"
try:
log.debug("Saving torrent state file.")
state_file = open(os.path.join(get_config_dir(),
"state", "torrents.state.new"), "wb")
os.remove(filepath_bak)
except OSError:
pass
try:
log.debug("Creating backup of state at: %s", filepath_bak)
os.rename(filepath, filepath_bak)
except OSError, ex:
log.error("Unable to backup %s to %s: %s", filepath, filepath_bak, ex)
try:
log.info("Saving the state at: %s", filepath)
state_file = open(filepath_tmp, "wb", 0)
cPickle.dump(state, state_file)
state_file.flush()
os.fsync(state_file.fileno())
state_file.close()
except IOError:
log.warning("Unable to save state file.")
return True
# We have to move the 'torrents.state.new' file to 'torrents.state'
try:
shutil.move(
os.path.join(get_config_dir(), "state", "torrents.state.new"),
os.path.join(get_config_dir(), "state", "torrents.state"))
except IOError:
log.warning("Unable to save state file.")
return True
os.rename(filepath_tmp, filepath)
except IOError, ex:
log.error("Unable to save %s: %s", filepath, ex)
if os.path.isfile(filepath_bak):
log.info("Restoring backup of state from: %s", filepath_bak)
os.rename(filepath_bak, filepath)
# We return True so that the timer thread will continue
return True
@ -680,15 +765,20 @@ class TorrentManager(component.Component):
self.num_resume_data = len(torrent_ids)
def load_resume_data_file(self):
resume_data = {}
try:
log.debug("Opening torrents fastresume file for load.")
fastresume_file = open(os.path.join(get_config_dir(), "state",
"torrents.fastresume"), "rb")
resume_data = lt.bdecode(fastresume_file.read())
fastresume_file.close()
except (EOFError, IOError, Exception), e:
log.warning("Unable to load fastresume file: %s", e)
filepath = os.path.join(get_config_dir(), "state", "torrents.fastresume")
log.debug("Opening torrents fastresume file for load.")
for _filepath in (filepath, filepath + ".bak"):
try:
fastresume_file = open(_filepath, "rb")
resume_data = lt.bdecode(fastresume_file.read())
fastresume_file.close()
except (EOFError, IOError, Exception), e:
if self.torrents:
log.warning("Unable to load fastresume file: %s", e)
resume_data = None
else:
log.info("Successfully loaded fastresume file: %s", _filepath)
break
# If the libtorrent bdecode doesn't happen properly, it will return None
# so we need to make sure we return a {}
@ -712,7 +802,9 @@ class TorrentManager(component.Component):
if self.num_resume_data or not self.resume_data:
return
path = os.path.join(get_config_dir(), "state", "torrents.fastresume")
filepath = os.path.join(get_config_dir(), "state", "torrents.fastresume")
filepath_tmp = filepath + ".tmp"
filepath_bak = filepath + ".bak"
# First step is to load the existing file and update the dictionary
if resume_data is None:
@ -722,14 +814,64 @@ class TorrentManager(component.Component):
self.resume_data = {}
try:
log.debug("Saving fastresume file: %s", path)
fastresume_file = open(path, "wb")
os.remove(filepath_bak)
except OSError:
pass
try:
log.debug("Creating backup of fastresume at: %s", filepath_bak)
os.rename(filepath, filepath_bak)
except OSError, ex:
log.error("Unable to backup %s to %s: %s", filepath, filepath_bak, ex)
try:
log.info("Saving the fastresume at: %s", filepath)
fastresume_file = open(filepath_tmp, "wb", 0)
fastresume_file.write(lt.bencode(resume_data))
fastresume_file.flush()
os.fsync(fastresume_file.fileno())
fastresume_file.close()
except IOError:
log.warning("Error trying to save fastresume file")
os.rename(filepath_tmp, filepath)
except IOError, ex:
log.error("Unable to save %s: %s", filepath, ex)
if os.path.isfile(filepath_bak):
log.info("Restoring backup of fastresume from: %s", filepath_bak)
os.rename(filepath_bak, filepath)
def remove_empty_folders(self, torrent_id, folder):
"""
Recursively removes folders but only if they are empty.
Cleans up after libtorrent folder renames.
"""
try:
info = self.torrents[torrent_id].get_status(['save_path'])
except KeyError:
raise InvalidTorrentError("torrent_id not in session")
# Regex removes leading slashes that causes join function to ignore save_path
folder_full_path = os.path.join(info['save_path'], re.sub("^/*", "", folder))
folder_full_path = os.path.normpath(folder_full_path)
try:
if not os.listdir(folder_full_path):
os.removedirs(folder_full_path)
log.debug("Removed Empty Folder %s", folder_full_path)
else:
for root, dirs, files in os.walk(folder_full_path, topdown=False):
for name in dirs:
try:
os.removedirs(os.path.join(root, name))
log.debug("Removed Empty Folder %s", os.path.join(root, name))
except OSError, (errno, strerror):
from errno import ENOTEMPTY
if errno == ENOTEMPTY:
# Error raised if folder is not empty
log.debug("%s", strerror)
except OSError, (errno, strerror):
log.debug("Cannot Remove Folder: %s (ErrNo %s)", strerror, errno)
def get_queue_position(self, torrent_id):
"""Get queue position of torrent"""
return self.torrents[torrent_id].get_queue_position()
def queue_top(self, torrent_id):
"""Queue torrent to top"""
@ -749,7 +891,7 @@ class TorrentManager(component.Component):
def queue_down(self, torrent_id):
"""Queue torrent down one position"""
if self.torrents[torrent_id].get_queue_position() == (len(self.torrents) - 1):
if self.torrents[torrent_id].get_queue_position() == (len(self.queued_torrents) - 1):
return False
self.torrents[torrent_id].handle.queue_position_down()
@ -757,7 +899,7 @@ class TorrentManager(component.Component):
def queue_bottom(self, torrent_id):
"""Queue torrent to bottom"""
if self.torrents[torrent_id].get_queue_position() == (len(self.torrents) - 1):
if self.torrents[torrent_id].get_queue_position() == (len(self.queued_torrents) - 1):
return False
self.torrents[torrent_id].handle.queue_position_bottom()
@ -790,28 +932,34 @@ class TorrentManager(component.Component):
log.debug("on_alert_torrent_finished")
try:
torrent = self.torrents[str(alert.handle.info_hash())]
torrent_id = str(alert.handle.info_hash())
except:
return
torrent_id = str(alert.handle.info_hash())
log.debug("%s is finished..", torrent_id)
# Get the total_download and if it's 0, do not move.. It's likely
# that the torrent wasn't downloaded, but just added.
total_download = torrent.get_status(["total_payload_download"])["total_payload_download"]
# Move completed download to completed folder if needed
if not torrent.is_finished and total_download:
move_path = None
if torrent.options["move_completed"]:
move_path = torrent.options["move_completed_path"]
if torrent.options["download_location"] != move_path:
torrent.move_storage(move_path)
torrent.is_finished = True
component.get("EventManager").emit(TorrentFinishedEvent(torrent_id))
torrent.update_state()
if not torrent.is_finished and total_download:
# Move completed download to completed folder if needed
if torrent.options["move_completed"] and \
torrent.options["download_location"] != torrent.options["move_completed_path"]:
self.waiting_on_finish_moving.append(torrent_id)
torrent.move_storage(torrent.options["move_completed_path"])
else:
torrent.is_finished = True
component.get("EventManager").emit(TorrentFinishedEvent(torrent_id))
else:
torrent.is_finished = True
# Torrent is no longer part of the queue
try:
self.queued_torrents.remove(torrent_id)
except KeyError:
# Sometimes libtorrent fires a TorrentFinishedEvent twice
log.debug("%s isn't in queued torrents set?", torrent_id)
# Only save resume data if it was actually downloaded something. Helps
# on startup with big queues with lots of seeding torrents. Libtorrent
@ -825,14 +973,11 @@ class TorrentManager(component.Component):
log.debug("on_alert_torrent_paused")
try:
torrent = self.torrents[str(alert.handle.info_hash())]
torrent_id = str(alert.handle.info_hash())
except:
return
torrent_id = str(alert.handle.info_hash())
# Set the torrent state
old_state = torrent.state
torrent.update_state()
if torrent.state != old_state:
component.get("EventManager").emit(TorrentStateChangedEvent(torrent_id, torrent.state))
# Don't save resume data for each torrent after self.stop() was called.
# We save resume data in bulk in self.stop() in this case.
@ -850,11 +995,19 @@ class TorrentManager(component.Component):
except:
return
# Check to see if we're forcing a recheck and set it back to paused
# if necessary
if torrent.forcing_recheck:
torrent.forcing_recheck = False
if torrent.forcing_recheck_paused:
torrent.handle.pause()
torrent.set_trackers(torrent.trackers, reannounce=False)
# Set the torrent state
torrent.update_state()
def on_alert_tracker_reply(self, alert):
log.debug("on_alert_tracker_reply: %s", alert.message().decode("utf8"))
log.debug("on_alert_tracker_reply: %s", decode_string(alert.message()))
try:
torrent = self.torrents[str(alert.handle.info_hash())]
except:
@ -862,7 +1015,7 @@ class TorrentManager(component.Component):
# Set the tracker status for the torrent
if alert.message() != "Got peers from DHT":
torrent.set_tracker_status(_("Announce OK"))
torrent.set_tracker_status("Announce OK")
# Check to see if we got any peer information from the tracker
if alert.handle.status().num_complete == -1 or \
@ -878,7 +1031,7 @@ class TorrentManager(component.Component):
return
# Set the tracker status for the torrent
torrent.set_tracker_status(_("Announce Sent"))
torrent.set_tracker_status("Announce Sent")
def on_alert_tracker_warning(self, alert):
log.debug("on_alert_tracker_warning")
@ -886,41 +1039,63 @@ class TorrentManager(component.Component):
torrent = self.torrents[str(alert.handle.info_hash())]
except:
return
tracker_status = '%s: %s' % (_("Warning"), str(alert.message()))
tracker_status = '%s: %s' % ("Warning", decode_string(alert.message()))
# Set the tracker status for the torrent
torrent.set_tracker_status(tracker_status)
def on_alert_tracker_error(self, alert):
log.debug("on_alert_tracker_error")
"""Alert handler for libtorrent tracker_error_alert"""
error_message = decode_string(alert.msg)
# If alert.msg is empty then it's a '-1' code so fallback to a.e.message. Note that alert.msg
# cannot be replaced by a.e.message because the code is included in the string (for non-'-1').
if not error_message:
error_message = decode_string(alert.error.message())
log.debug("Tracker Error Alert: %s [%s]", decode_string(alert.message()), error_message)
try:
torrent = self.torrents[str(alert.handle.info_hash())]
except:
except (RuntimeError, KeyError):
return
tracker_status = "%s: %s" % (_("Error"), alert.msg)
torrent.set_tracker_status(tracker_status)
torrent.set_tracker_status("Error: %s" % error_message)
def on_alert_storage_moved(self, alert):
log.debug("on_alert_storage_moved")
try:
torrent = self.torrents[str(alert.handle.info_hash())]
except:
torrent_id = str(alert.handle.info_hash())
torrent = self.torrents[torrent_id]
except (RuntimeError, KeyError):
return
torrent.set_save_path(alert.handle.save_path())
torrent.set_save_path(os.path.normpath(alert.handle.save_path()))
torrent.set_move_completed(False)
if torrent_id in self.waiting_on_finish_moving:
self.waiting_on_finish_moving.remove(torrent_id)
torrent.is_finished = True
component.get("EventManager").emit(TorrentFinishedEvent(torrent_id))
def on_alert_storage_moved_failed(self, alert):
"""Alert handler for libtorrent storage_moved_failed_alert"""
log.debug("on_alert_storage_moved_failed: %s", decode_string(alert.message()))
try:
torrent_id = str(alert.handle.info_hash())
torrent = self.torrents[torrent_id]
except (RuntimeError, KeyError):
return
log.error("Torrent %s, %s", torrent_id, decode_string(alert.message()))
if torrent_id in self.waiting_on_finish_moving:
self.waiting_on_finish_moving.remove(torrent_id)
torrent.is_finished = True
component.get("EventManager").emit(TorrentFinishedEvent(torrent_id))
def on_alert_torrent_resumed(self, alert):
log.debug("on_alert_torrent_resumed")
try:
torrent = self.torrents[str(alert.handle.info_hash())]
torrent_id = str(alert.handle.info_hash())
except:
return
torrent_id = str(alert.handle.info_hash())
torrent.is_finished = torrent.handle.is_seed()
old_state = torrent.state
torrent.update_state()
if torrent.state != old_state:
# We need to emit a TorrentStateChangedEvent too
component.get("EventManager").emit(TorrentStateChangedEvent(torrent_id, torrent.state))
component.get("EventManager").emit(TorrentResumedEvent(torrent_id))
def on_alert_state_changed(self, alert):
@ -931,18 +1106,17 @@ class TorrentManager(component.Component):
except:
return
old_state = torrent.state
torrent.update_state()
# Only emit a state changed event if the state has actually changed
if torrent.state != old_state:
component.get("EventManager").emit(TorrentStateChangedEvent(torrent_id, torrent.state))
# Torrent may need to download data after checking.
if torrent.state in ('Checking', 'Checking Resume Data', 'Downloading'):
torrent.is_finished = False
self.queued_torrents.add(torrent_id)
def on_alert_save_resume_data(self, alert):
log.debug("on_alert_save_resume_data")
torrent_id = str(alert.handle.info_hash())
try:
torrent_id = str(alert.handle.info_hash())
torrent = self.torrents[torrent_id]
except:
return
@ -956,7 +1130,7 @@ class TorrentManager(component.Component):
self.save_resume_data_file()
def on_alert_save_resume_data_failed(self, alert):
log.debug("on_alert_save_resume_data_failed: %s", alert.message())
log.debug("on_alert_save_resume_data_failed: %s", decode_string(alert.message()))
try:
torrent = self.torrents[str(alert.handle.info_hash())]
except:
@ -967,15 +1141,34 @@ class TorrentManager(component.Component):
self.save_resume_data_file()
def on_alert_fastresume_rejected(self, alert):
"""Alert handler for libtorrent fastresume_rejected_alert"""
alert_msg = decode_string(alert.message())
log.error("on_alert_fastresume_rejected: %s", alert_msg)
try:
torrent_id = str(alert.handle.info_hash())
torrent = self.torrents[torrent_id]
except (RuntimeError, KeyError):
return
if alert.error.value() == 134:
if not os.path.isdir(torrent.options["download_location"]):
error_msg = "Unable to locate Download Folder!"
else:
error_msg = "Missing or invalid torrent data!"
else:
error_msg = "Problem with resume data: %s" % alert_msg.split(":", 1)[1].strip()
torrent.force_error_state(error_msg, restart_to_resume=True)
def on_alert_file_renamed(self, alert):
log.debug("on_alert_file_renamed")
log.debug("index: %s name: %s", alert.index, alert.name.decode("utf8"))
log.debug("index: %s name: %s", alert.index, decode_string(alert.name))
try:
torrent = self.torrents[str(alert.handle.info_hash())]
torrent_id = str(alert.handle.info_hash())
except:
return
torrent_id = str(alert.handle.info_hash())
# We need to see if this file index is in a waiting_on_folder list
folder_rename = False
@ -985,6 +1178,8 @@ class TorrentManager(component.Component):
if len(wait_on_folder[2]) == 1:
# This is the last alert we were waiting for, time to send signal
component.get("EventManager").emit(TorrentFolderRenamedEvent(torrent_id, wait_on_folder[0], wait_on_folder[1]))
# Empty folders are removed after libtorrent folder renames
self.remove_empty_folders(torrent_id, wait_on_folder[0])
del torrent.waiting_on_folder_rename[i]
self.save_resume_data((torrent_id,))
break
@ -1003,12 +1198,21 @@ class TorrentManager(component.Component):
torrent = self.torrents[str(alert.handle.info_hash())]
except:
return
torrent.write_torrentfile()
torrent.on_metadata_received()
def on_alert_file_error(self, alert):
log.debug("on_alert_file_error: %s", alert.message())
log.debug("on_alert_file_error: %s", decode_string(alert.message()))
try:
torrent = self.torrents[str(alert.handle.info_hash())]
except:
return
torrent.update_state()
def on_alert_file_completed(self, alert):
log.debug("file_completed_alert: %s", decode_string(alert.message()))
try:
torrent_id = str(alert.handle.info_hash())
except:
return
component.get("EventManager").emit(
TorrentFileCompletedEvent(torrent_id, alert.index))

View File

@ -1,2 +0,0 @@
From: http://famfamfam.com/lab/icons/flags/
"These flag icons are available for free use for any purpose with no requirement for attribution."

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 683 B

View File

@ -1,12 +0,0 @@
[Desktop Entry]
Version=1.0
Name=Deluge BitTorrent Client
GenericName=Bittorrent Client
Comment=Transfer files using the Bittorrent protocol
Exec=deluge-gtk
Icon=deluge
Terminal=false
Type=Application
Categories=Network;
StartupNotify=true
MimeType=application/x-bittorrent;

View File

@ -0,0 +1,15 @@
[Desktop Entry]
Version=1.0
_Name=Deluge
_GenericName=BitTorrent Client
_X-GNOME-FullName=Deluge BitTorrent Client
_Comment=Download and share files over BitTorrent
TryExec=deluge-gtk
Exec=deluge-gtk %U
Icon=deluge
Terminal=false
Type=Application
Categories=Network;FileTransfer;P2P;GTK;
StartupWMClass=Deluge
StartupNotify=true
MimeType=application/x-bittorrent;x-scheme-handler/magnet;

View File

@ -164,6 +164,22 @@ class TorrentResumedEvent(DelugeEvent):
"""
self._args = [torrent_id]
class TorrentFileCompletedEvent(DelugeEvent):
"""
Emitted when a file completes.
This will only work with libtorrent 0.15 or greater.
"""
def __init__(self, torrent_id, index):
"""
:param torrent_id: the torrent_id
:type torrent_id: string
:param index: the file index
:type index: int
"""
self._args = [torrent_id, index]
class NewVersionAvailableEvent(DelugeEvent):
"""
Emitted when a more recent version of Deluge is available.

View File

@ -51,6 +51,8 @@ class HTTPDownloader(client.HTTPDownloader):
:type url: string
:param filename: the filename to save the file as
:type filename: string
:param force_filename: forces use of the supplied filename, regardless of header content
:type force_filename: bool
:param part_callback: a function to be called when a part of data
is received, it's signature should be: func(data, current_length, total_length)
:type part_callback: function
@ -84,15 +86,20 @@ class HTTPDownloader(client.HTTPDownloader):
self.decoder = zlib.decompressobj(zlib.MAX_WBITS + 32)
if "content-disposition" in headers and not self.force_filename:
try:
new_file_name = str(headers["content-disposition"][0]).split(";")[1].split("=")[1]
new_file_name = sanitise_filename(new_file_name)
new_file_name = os.path.join(os.path.split(self.fileName)[0], new_file_name)
except Exception, e:
log.exception(e)
else:
self.fileName = new_file_name
self.value = new_file_name
new_file_name = str(headers["content-disposition"][0]).split(";")[1].split("=")[1]
new_file_name = sanitise_filename(new_file_name)
new_file_name = os.path.join(os.path.split(self.fileName)[0], new_file_name)
count = 1
fileroot = os.path.splitext(new_file_name)[0]
fileext = os.path.splitext(new_file_name)[1]
while os.path.isfile(new_file_name):
# Increment filename if already exists
new_file_name = "%s-%s%s" % (fileroot, count, fileext)
count += 1
self.fileName = new_file_name
self.value = new_file_name
elif self.code in (http.MOVED_PERMANENTLY, http.FOUND, http.SEE_OTHER, http.TEMPORARY_REDIRECT):
location = headers["location"][0]
@ -129,8 +136,6 @@ def sanitise_filename(filename):
:type filename: string
:returns: the sanitised filename
:rtype: string
:raises IOError: when the filename exists
"""
# Remove any quotes
@ -141,15 +146,12 @@ def sanitise_filename(filename):
log.warning("Potentially malicious server: trying to write to file '%s'" % filename)
# Only use the basename
filename = os.path.basename(filename)
filename = filename.strip()
if filename.startswith(".") or ";" in filename or "|" in filename:
# Dodgy server, log it
log.warning("Potentially malicious server: trying to write to file '%s'" % filename)
if os.path.exists(filename):
raise IOError, "File '%s' already exists!" % filename
return filename
def download_file(url, filename, callback=None, headers=None, force_filename=False, allow_compression=True):
@ -190,11 +192,42 @@ def download_file(url, filename, callback=None, headers=None, force_filename=Fal
headers = {}
headers["accept-encoding"] = "deflate, gzip, x-gzip"
scheme, host, port, path = client._parse(url)
# In Twisted 13.1.0 _parse() function replaced by _URI class.
# In Twisted 15.0.0 _URI class renamed to URI.
if hasattr(client, "_parse"):
scheme, host, port, path = client._parse(url)
else:
try:
from twisted.web.client import _URI as URI
except ImportError:
from twisted.web.client import URI
uri = URI.fromBytes(url)
scheme = uri.scheme
host = uri.host
port = uri.port
path = uri.path
factory = HTTPDownloader(url, filename, callback, headers, force_filename, allow_compression)
if scheme == "https":
from twisted.internet import ssl
reactor.connectSSL(host, port, factory, ssl.ClientContextFactory())
# ClientTLSOptions in Twisted >= 14, see ticket #2765 for details on this addition.
try:
from twisted.internet._sslverify import ClientTLSOptions
except ImportError:
ctx_factory = ssl.ClientContextFactory()
else:
class TLSSNIContextFactory(ssl.ClientContextFactory):
"""
A custom context factory to add a server name for TLS connections.
"""
def getContext(self, hostname=None, port=None):
ctx = ssl.ClientContextFactory.getContext(self)
ClientTLSOptions(host, ctx)
return ctx
ctx_factory = TLSSNIContextFactory()
reactor.connectSSL(host, port, factory, ctx_factory)
else:
reactor.connectTCP(host, port, factory)

View File

@ -1,290 +0,0 @@
deluge/configmanager.py
deluge/httpdownloader.py
deluge/error.py
deluge/component.py
deluge/log.py
deluge/metafile.py
deluge/config.py
deluge/main.py
deluge/__init__.py
deluge/common.py
deluge/bencode.py
deluge/pluginmanagerbase.py
deluge/event.py
deluge/rencode.py
deluge/decorators.py
deluge/_libtorrent.py
deluge/__rpcapi.py
deluge/maketorrent.py
deluge/plugins/__init__.py
deluge/plugins/pluginbase.py
deluge/plugins/init.py
deluge/plugins/feeder/setup.py
deluge/plugins/feeder/feeder/__init__.py
deluge/plugins/feeder/feeder/core.py
deluge/plugins/feeder/feeder/webui.py
deluge/plugins/feeder/build/lib/feeder/__init__.py
deluge/plugins/feeder/build/lib/feeder/core.py
deluge/plugins/feeder/build/lib/feeder/webui.py
deluge/plugins/label/setup.py
deluge/plugins/label/label/test.py
deluge/plugins/label/label/__init__.py
deluge/plugins/label/label/core.py
deluge/plugins/label/label/webui.py
deluge/plugins/label/label/gtkui/__init__.py
deluge/plugins/label/label/gtkui/label_config.py
deluge/plugins/label/label/gtkui/submenu.py
deluge/plugins/label/label/gtkui/sidebar_menu.py
deluge/plugins/label/label/data/label_pref.glade
deluge/plugins/label/label/data/label_options.glade
deluge/plugins/label/build/lib/label/test.py
deluge/plugins/label/build/lib/label/__init__.py
deluge/plugins/label/build/lib/label/core.py
deluge/plugins/label/build/lib/label/webui.py
deluge/plugins/label/build/lib/label/gtkui/__init__.py
deluge/plugins/label/build/lib/label/gtkui/label_config.py
deluge/plugins/label/build/lib/label/gtkui/submenu.py
deluge/plugins/label/build/lib/label/gtkui/sidebar_menu.py
deluge/plugins/label/build/lib/label/data/label_pref.glade
deluge/plugins/label/build/lib/label/data/label_options.glade
deluge/plugins/autoadd/setup.py
deluge/plugins/autoadd/autoadd/__init__.py
deluge/plugins/autoadd/autoadd/common.py
deluge/plugins/autoadd/autoadd/core.py
deluge/plugins/autoadd/autoadd/webui.py
deluge/plugins/autoadd/autoadd/gtkui.py
deluge/plugins/autoadd/autoadd/data/config.glade
deluge/plugins/autoadd/autoadd/data/autoadd_options.glade
deluge/plugins/autoadd/build/lib/autoadd/__init__.py
deluge/plugins/autoadd/build/lib/autoadd/common.py
deluge/plugins/autoadd/build/lib/autoadd/core.py
deluge/plugins/autoadd/build/lib/autoadd/webui.py
deluge/plugins/autoadd/build/lib/autoadd/gtkui.py
deluge/plugins/autoadd/build/lib/autoadd/data/config.glade
deluge/plugins/autoadd/build/lib/autoadd/data/autoadd_options.glade
deluge/plugins/scheduler/setup.py
deluge/plugins/scheduler/scheduler/__init__.py
deluge/plugins/scheduler/scheduler/common.py
deluge/plugins/scheduler/scheduler/core.py
deluge/plugins/scheduler/scheduler/webui.py
deluge/plugins/scheduler/scheduler/gtkui.py
deluge/plugins/scheduler/build/lib/scheduler/__init__.py
deluge/plugins/scheduler/build/lib/scheduler/common.py
deluge/plugins/scheduler/build/lib/scheduler/core.py
deluge/plugins/scheduler/build/lib/scheduler/webui.py
deluge/plugins/scheduler/build/lib/scheduler/gtkui.py
deluge/plugins/notifications/setup.py
deluge/plugins/notifications/notifications/test.py
deluge/plugins/notifications/notifications/__init__.py
deluge/plugins/notifications/notifications/common.py
deluge/plugins/notifications/notifications/core.py
deluge/plugins/notifications/notifications/webui.py
deluge/plugins/notifications/notifications/gtkui.py
deluge/plugins/notifications/notifications/data/config.glade
deluge/plugins/notifications/build/lib/notifications/test.py
deluge/plugins/notifications/build/lib/notifications/__init__.py
deluge/plugins/notifications/build/lib/notifications/common.py
deluge/plugins/notifications/build/lib/notifications/core.py
deluge/plugins/notifications/build/lib/notifications/webui.py
deluge/plugins/notifications/build/lib/notifications/gtkui.py
deluge/plugins/notifications/build/lib/notifications/data/config.glade
deluge/plugins/stats/setup.py
deluge/plugins/stats/stats/test_total.py
deluge/plugins/stats/stats/test.py
deluge/plugins/stats/stats/__init__.py
deluge/plugins/stats/stats/graph.py
deluge/plugins/stats/stats/common.py
deluge/plugins/stats/stats/core.py
deluge/plugins/stats/stats/webui.py
deluge/plugins/stats/stats/gtkui.py
deluge/plugins/stats/stats/data/tabs.glade
deluge/plugins/stats/stats/data/config.glade
deluge/plugins/stats/build/lib/stats/test_total.py
deluge/plugins/stats/build/lib/stats/test.py
deluge/plugins/stats/build/lib/stats/__init__.py
deluge/plugins/stats/build/lib/stats/graph.py
deluge/plugins/stats/build/lib/stats/common.py
deluge/plugins/stats/build/lib/stats/core.py
deluge/plugins/stats/build/lib/stats/webui.py
deluge/plugins/stats/build/lib/stats/gtkui.py
deluge/plugins/stats/build/lib/stats/data/tabs.glade
deluge/plugins/stats/build/lib/stats/data/config.glade
deluge/plugins/webui/setup.py
deluge/plugins/webui/webui/__init__.py
deluge/plugins/webui/webui/common.py
deluge/plugins/webui/webui/core.py
deluge/plugins/webui/webui/gtkui.py
deluge/plugins/webui/webui/data/config.glade
deluge/plugins/webui/build/lib/webui/__init__.py
deluge/plugins/webui/build/lib/webui/common.py
deluge/plugins/webui/build/lib/webui/core.py
deluge/plugins/webui/build/lib/webui/gtkui.py
deluge/plugins/webui/build/lib/webui/data/config.glade
deluge/plugins/extractor/setup.py
deluge/plugins/extractor/build/lib/extractor/__init__.py
deluge/plugins/extractor/build/lib/extractor/common.py
deluge/plugins/extractor/build/lib/extractor/core.py
deluge/plugins/extractor/build/lib/extractor/webui.py
deluge/plugins/extractor/build/lib/extractor/gtkui.py
deluge/plugins/extractor/build/lib/extractor/data/extractor_prefs.glade
deluge/plugins/extractor/extractor/__init__.py
deluge/plugins/extractor/extractor/common.py
deluge/plugins/extractor/extractor/core.py
deluge/plugins/extractor/extractor/webui.py
deluge/plugins/extractor/extractor/gtkui.py
deluge/plugins/extractor/extractor/data/extractor_prefs.glade
deluge/plugins/execute/setup.py
deluge/plugins/execute/build/lib/execute/__init__.py
deluge/plugins/execute/build/lib/execute/common.py
deluge/plugins/execute/build/lib/execute/core.py
deluge/plugins/execute/build/lib/execute/webui.py
deluge/plugins/execute/build/lib/execute/gtkui.py
deluge/plugins/execute/build/lib/execute/data/execute_prefs.glade
deluge/plugins/execute/execute/__init__.py
deluge/plugins/execute/execute/common.py
deluge/plugins/execute/execute/core.py
deluge/plugins/execute/execute/webui.py
deluge/plugins/execute/execute/gtkui.py
deluge/plugins/execute/execute/data/execute_prefs.glade
deluge/plugins/example/setup.py
deluge/plugins/example/build/lib/example/__init__.py
deluge/plugins/example/build/lib/example/common.py
deluge/plugins/example/build/lib/example/core.py
deluge/plugins/example/build/lib/example/webui.py
deluge/plugins/example/build/lib/example/gtkui.py
deluge/plugins/example/example/__init__.py
deluge/plugins/example/example/common.py
deluge/plugins/example/example/core.py
deluge/plugins/example/example/webui.py
deluge/plugins/example/example/gtkui.py
deluge/plugins/freespace/setup.py
deluge/plugins/freespace/build/lib/freespace/__init__.py
deluge/plugins/freespace/build/lib/freespace/common.py
deluge/plugins/freespace/build/lib/freespace/core.py
deluge/plugins/freespace/build/lib/freespace/webui.py
deluge/plugins/freespace/build/lib/freespace/gtkui.py
deluge/plugins/freespace/build/lib/freespace/data/config.glade
deluge/plugins/freespace/freespace/__init__.py
deluge/plugins/freespace/freespace/common.py
deluge/plugins/freespace/freespace/core.py
deluge/plugins/freespace/freespace/webui.py
deluge/plugins/freespace/freespace/gtkui.py
deluge/plugins/freespace/freespace/data/config.glade
deluge/plugins/blocklist/setup.py
deluge/plugins/blocklist/build/lib/blocklist/peerguardian.py
deluge/plugins/blocklist/build/lib/blocklist/decompressers.py
deluge/plugins/blocklist/build/lib/blocklist/detect.py
deluge/plugins/blocklist/build/lib/blocklist/readers.py
deluge/plugins/blocklist/build/lib/blocklist/__init__.py
deluge/plugins/blocklist/build/lib/blocklist/common.py
deluge/plugins/blocklist/build/lib/blocklist/core.py
deluge/plugins/blocklist/build/lib/blocklist/webui.py
deluge/plugins/blocklist/build/lib/blocklist/gtkui.py
deluge/plugins/blocklist/build/lib/blocklist/data/blocklist_pref.glade
deluge/plugins/blocklist/blocklist/peerguardian.py
deluge/plugins/blocklist/blocklist/decompressers.py
deluge/plugins/blocklist/blocklist/detect.py
deluge/plugins/blocklist/blocklist/readers.py
deluge/plugins/blocklist/blocklist/__init__.py
deluge/plugins/blocklist/blocklist/common.py
deluge/plugins/blocklist/blocklist/core.py
deluge/plugins/blocklist/blocklist/webui.py
deluge/plugins/blocklist/blocklist/gtkui.py
deluge/plugins/blocklist/blocklist/data/blocklist_pref.glade
deluge/core/eventmanager.py
deluge/core/autoadd.py
deluge/core/authmanager.py
deluge/core/rpcserver.py
deluge/core/torrentmanager.py
deluge/core/oldstateupgrader.py
deluge/core/__init__.py
deluge/core/torrent.py
deluge/core/pluginmanager.py
deluge/core/core.py
deluge/core/daemon.py
deluge/core/alertmanager.py
deluge/core/preferencesmanager.py
deluge/core/filtermanager.py
deluge/ui/sessionproxy.py
deluge/ui/ui.py
deluge/ui/session.py
deluge/ui/tracker_icons.py
deluge/ui/__init__.py
deluge/ui/common.py
deluge/ui/Win32IconImagePlugin.py
deluge/ui/client.py
deluge/ui/countries.py
deluge/ui/coreconfig.py
deluge/ui/web/server.py
deluge/ui/web/web.py
deluge/ui/web/__init__.py
deluge/ui/web/common.py
deluge/ui/web/pluginmanager.py
deluge/ui/web/gen_gettext.py
deluge/ui/web/auth.py
deluge/ui/web/json_api.py
deluge/ui/gtkui/connectionmanager.py
deluge/ui/gtkui/torrentdetails.py
deluge/ui/gtkui/queuedtorrents.py
deluge/ui/gtkui/addtorrentdialog.py
deluge/ui/gtkui/__init__.py
deluge/ui/gtkui/status_tab.py
deluge/ui/gtkui/preferences.py
deluge/ui/gtkui/mainwindow.py
deluge/ui/gtkui/notification.py
deluge/ui/gtkui/ipcinterface.py
deluge/ui/gtkui/createtorrentdialog.py
deluge/ui/gtkui/torrentview.py
deluge/ui/gtkui/listview.py
deluge/ui/gtkui/systemtray.py
deluge/ui/gtkui/common.py
deluge/ui/gtkui/pluginmanager.py
deluge/ui/gtkui/menubar.py
deluge/ui/gtkui/sidebar.py
deluge/ui/gtkui/statusbar.py
deluge/ui/gtkui/filtertreeview.py
deluge/ui/gtkui/new_release_dialog.py
deluge/ui/gtkui/options_tab.py
deluge/ui/gtkui/peers_tab.py
deluge/ui/gtkui/details_tab.py
deluge/ui/gtkui/files_tab.py
deluge/ui/gtkui/gtkui.py
deluge/ui/gtkui/edittrackersdialog.py
deluge/ui/gtkui/removetorrentdialog.py
deluge/ui/gtkui/toolbar.py
deluge/ui/gtkui/dialogs.py
deluge/ui/gtkui/aboutdialog.py
deluge/ui/gtkui/glade/filtertree_menu.glade
deluge/ui/gtkui/glade/main_window.glade
deluge/ui/gtkui/glade/remove_torrent_dialog.glade
deluge/ui/gtkui/glade/create_torrent_dialog.glade
deluge/ui/gtkui/glade/connection_manager.glade
deluge/ui/gtkui/glade/preferences_dialog.glade
deluge/ui/gtkui/glade/torrent_menu.glade
deluge/ui/gtkui/glade/queuedtorrents.glade
deluge/ui/gtkui/glade/move_storage_dialog.glade
deluge/ui/gtkui/glade/add_torrent_dialog.glade
deluge/ui/gtkui/glade/dgtkpopups.glade
deluge/ui/gtkui/glade/tray_menu.glade
deluge/ui/gtkui/glade/edit_trackers.glade
deluge/ui/console/colors.py
deluge/ui/console/eventlog.py
deluge/ui/console/main.py
deluge/ui/console/__init__.py
deluge/ui/console/statusbars.py
deluge/ui/console/screen.py
deluge/ui/console/commands/plugin.py
deluge/ui/console/commands/info.py
deluge/ui/console/commands/recheck.py
deluge/ui/console/commands/quit.py
deluge/ui/console/commands/connect.py
deluge/ui/console/commands/help.py
deluge/ui/console/commands/add.py
deluge/ui/console/commands/config.py
deluge/ui/console/commands/__init__.py
deluge/ui/console/commands/cache.py
deluge/ui/console/commands/debug.py
deluge/ui/console/commands/pause.py
deluge/ui/console/commands/rm.py
deluge/ui/console/commands/halt.py
deluge/ui/console/commands/resume.py

4011
deluge/i18n/af.po Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

3993
deluge/i18n/fo.po Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

3993
deluge/i18n/ga.po Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

4001
deluge/i18n/km.po Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

3993
deluge/i18n/ky.po Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

3993
deluge/i18n/lb.po Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

3743
deluge/i18n/ml.po Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

4001
deluge/i18n/nap.po Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

4024
deluge/i18n/nn.po Normal file

File diff suppressed because it is too large Load Diff

4018
deluge/i18n/oc.po Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More