Compare commits

...

259 Commits

Author SHA1 Message Date
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
533 changed files with 91230 additions and 53689 deletions

22
.gitattributes vendored
View File

@ -1,14 +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

2
.gitignore vendored
View File

@ -9,3 +9,5 @@ dist
_trial_temp
deluge/i18n/*/
*.desktop
.build_data*
osx/app

195
ChangeLog
View File

@ -1,3 +1,198 @@
=== 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

View File

@ -12,19 +12,19 @@
* geoip-database (optional)
* setproctitle (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
=== Gtk ===
* python-notify (libnotify python wrapper)
* pygame
* pygtk >= 2.12
* librsvg
* xdg-utils
* python-notify (optional)
* pygame (optional)
=== Web ===
* mako

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

@ -42,12 +42,18 @@ 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"):
@ -63,10 +69,6 @@ if not hasattr(json, "dumps"):
json.dump = dump
json.load = load
import pkg_resources
import gettext
import locale
# Initialize gettext
try:
if hasattr(locale, "bindtextdomain"):
@ -75,14 +77,11 @@ try:
locale.textdomain("deluge")
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,
@ -102,7 +101,6 @@ LT_TORRENT_STATE = {
7: "Checking Resume Data"
}
TORRENT_STATE = [
"Allocating",
"Checking",
@ -117,7 +115,10 @@ FILE_PRIORITY = {
0: "Do Not Download",
1: "Normal Priority",
2: "High Priority",
3: "High Priority",
4: "High Priority",
5: "High Priority",
6: "High Priority",
7: "Highest Priority",
"Do Not Download": 0,
"Normal Priority": 1,
@ -156,11 +157,15 @@ def get_default_config_dir(filename=None):
else:
return os.path.join(appDataPath, "deluge")
else:
import xdg.BaseDirectory
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():
"""
@ -168,22 +173,20 @@ def get_default_download_dir():
:rtype: string
"""
if windows_check():
return os.path.join(os.path.expanduser("~"), 'Downloads')
else:
download_dir = ""
if not windows_check():
from xdg.BaseDirectory import xdg_config_home
userdir_file = os.path.join(xdg_config_home, 'user-dirs.dirs')
try:
for line in open(userdir_file, 'r'):
if not line.startswith('#') and 'XDG_DOWNLOAD_DIR' in line:
download_dir = os.path.expandvars(\
line.partition("=")[2].rstrip().strip('"'))
if os.path.isdir(download_dir):
return download_dir
for line in open(os.path.join(xdg_config_home, 'user-dirs.dirs'), 'r'):
if not line.startswith('#') and line.startswith('XDG_DOWNLOAD_DIR'):
download_dir = os.path.expandvars(line.partition("=")[2].rstrip().strip('"'))
break
except IOError:
pass
return os.environ.get("HOME")
if not download_dir:
download_dir = os.path.join(os.path.expanduser("~"), 'Downloads')
return download_dir
def windows_check():
"""
@ -228,18 +231,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):
"""
@ -452,7 +464,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
@ -516,13 +530,12 @@ 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.encode("utf8"))
block_size = disk_data.f_frsize
@ -546,15 +559,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
@ -612,37 +633,55 @@ def xml_encode(string):
def decode_string(s, encoding="utf8"):
"""
Decodes a string and re-encodes it in utf8. If it cannot decode using
`:param:encoding` then it will try to detect the string encoding and
decode it.
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
try:
s = s.decode(encoding).encode("utf8", "ignore")
except UnicodeDecodeError:
s = s.decode(chardet.detect(s)["encoding"], "ignore").encode("utf8", "ignore")
return s
encodings = [lambda: ("utf8", 'strict'),
lambda: ("iso-8859-1", 'strict'),
lambda: (chardet.detect(s)["encoding"], 'strict'),
lambda: (encoding, 'ignore')]
def utf8_encoded(s):
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)
s = decode_string(s, encoding).encode("utf8")
elif isinstance(s, unicode):
s = s.encode("utf8", "ignore")
s = s.encode("utf8")
return s
class VersionSplit(object):

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(

View File

@ -121,10 +121,10 @@ class AuthManager(component.Component):
f = open(auth_file, "r").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:

View File

@ -84,7 +84,10 @@ class Core(component.Component):
while len(version) < 4:
version.append(0)
self.session = lt.session(lt.fingerprint("DE", *version), flags=0)
# Note: All libtorrent python bindings to set plugins/extensions need to be disabled
# due to GIL issue. https://code.google.com/p/libtorrent/issues/detail?id=369
# 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()
@ -92,6 +95,8 @@ 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
@ -103,9 +108,11 @@ class Core(component.Component):
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)
# Note: All libtorrent python bindings to set plugins/extensions need to be disabled
# due to GIL issue. https://code.google.com/p/libtorrent/issues/detail?id=369
# 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)
# Create the components
self.eventmanager = EventManager()
@ -127,8 +134,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"""
@ -270,7 +280,7 @@ class Core(component.Component):
result.addCallbacks(on_download_success, on_download_fail)
else:
# Log the error and pass the failure onto the client
log.error("Error occured downloading torrent from %s", url)
log.error("Error occurred downloading torrent from %s", url)
log.error("Reason: %s", failure.getErrorMessage())
result = failure
return result
@ -414,7 +424,11 @@ 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
leftover_fields = list(set(keys) - set(status.keys()))
@ -706,7 +720,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):
@ -717,35 +732,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):

View File

@ -62,13 +62,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:

View File

@ -55,8 +55,8 @@ class EventManager(component.Component):
#log.debug("Running handler %s for event %s with args: %s", event.name, handler, event.args)
try:
handler(*event.args)
except:
log.error("Event handler %s failed in %s", event.name, handler)
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()

View File

@ -251,7 +251,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
@ -273,7 +273,7 @@ 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"]:
@ -338,15 +338,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)
# Note: All libtorrent python bindings to set plugins/extensions need to be disabled
# due to GIL issue. https://code.google.com/p/libtorrent/issues/detail?id=369
#self.session.add_extension(lt.create_ut_pex_plugin)
pass
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()
@ -468,15 +472,14 @@ class PreferencesManager(component.Component):
def _on_set_proxies(self, key, value):
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)
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)
def _on_rate_limit_ip_overhead(self, key, value):
log.debug("%s: %s", key, value)

View File

@ -465,7 +465,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

View File

@ -174,7 +174,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
@ -260,11 +260,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
@ -478,7 +478,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
})
@ -667,7 +668,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:
@ -833,26 +834,30 @@ class Torrent(object):
def move_storage(self, dest):
"""Move a torrent's storage location"""
# Attempt to convert utf8 path to unicode
# Note: Inconsistent encoding for 'dest', needs future investigation
try:
dest_u = unicode(dest, "utf-8")
dest = unicode(dest, "utf-8")
except TypeError:
# String is already unicode
dest_u = dest
pass
if not os.path.exists(dest_u):
if not os.path.exists(dest):
try:
# Try to make the destination path if it doesn't exist
os.makedirs(dest_u)
os.makedirs(dest)
except IOError, e:
log.exception(e)
log.error("Could not move storage for torrent %s since %s does not exist and could not create the directory.", self.torrent_id, dest_u)
return False
dest_bytes = dest.encode('utf-8')
try:
self.handle.move_storage(dest_u)
except:
# libtorrent needs unicode object if wstrings are enabled, utf8 bytestring otherwise
try:
self.handle.move_storage(dest)
except TypeError:
self.handle.move_storage(dest_bytes)
except Exception, e:
log.error("Error calling libtorrent move_storage: %s" % e)
return False
return True
@ -863,6 +868,11 @@ class Torrent(object):
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"""
path = "%s/%s.torrent" % (
@ -928,8 +938,17 @@ class Torrent(object):
"""Renames files in the torrent. 'filenames' should be a list of
(index, filename) pairs."""
for index, filename in filenames:
# Make sure filename is a unicode object
try:
filename = unicode(filename, "utf-8")
except TypeError:
pass
filename = sanitize_filepath(filename)
self.handle.rename_file(index, filename.encode("utf-8"))
# 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
@ -946,7 +965,11 @@ class Torrent(object):
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):

View File

@ -55,7 +55,7 @@ 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.common import utf8_encoded
from deluge.common import utf8_encoded, decode_string
from deluge.log import LOG as log
@ -138,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
@ -147,6 +148,9 @@ 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 = {}
@ -180,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",
@ -375,14 +381,20 @@ 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 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():
# Torrent already exists just append any extra trackers.
log.debug("Torrent (%s) exists, checking for trackers to add...", add_torrent_id)
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 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 = {}
@ -392,17 +404,18 @@ class TorrentManager(component.Component):
torrent_trackers = {}
tracker_list = []
for tracker in self[add_torrent_id].get_status(["trackers"])["trackers"]:
for tracker in self[add_torrent_id].get_status(["trackers"])["trackers"]:
torrent_trackers[(tracker["url"])] = tracker
tracker_list.append(tracker)
added_tracker = False
added_tracker = 0
for tracker in add_torrent_trackers:
if tracker['url'] not in torrent_trackers:
tracker_list.append(tracker)
added_tracker = True
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
@ -417,13 +430,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, filename in options["mapped_files"].items():
filename = deluge.core.torrent.sanitize_filepath(filename)
log.debug("renaming file index %s to %s", index, filename)
torrent_info.rename_file(index, utf8_encoded(filename))
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)
@ -476,6 +495,9 @@ class TorrentManager(component.Component):
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:
@ -542,12 +564,11 @@ 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")
torrent_name = self.torrents[torrent_id].get_status(["name"])["name"]
# Emit the signal to the clients
component.get("EventManager").emit(PreTorrentRemovedEvent(torrent_id))
@ -584,10 +605,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
@ -623,7 +651,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()
@ -747,6 +775,7 @@ class TorrentManager(component.Component):
return
path = os.path.join(get_config_dir(), "state", "torrents.fastresume")
path_tmp = path + ".tmp"
# First step is to load the existing file and update the dictionary
if resume_data is None:
@ -757,11 +786,12 @@ class TorrentManager(component.Component):
try:
log.debug("Saving fastresume file: %s", path)
fastresume_file = open(path, "wb")
fastresume_file = open(path_tmp, "wb")
fastresume_file.write(lt.bencode(resume_data))
fastresume_file.flush()
os.fsync(fastresume_file.fileno())
fastresume_file.close()
shutil.move(path_tmp, path)
except IOError:
log.warning("Error trying to save fastresume file")
@ -771,10 +801,10 @@ class TorrentManager(component.Component):
Cleans up after libtorrent folder renames.
"""
if torrent_id not in self.torrents:
raise InvalidTorrentError("torrent_id is not in session")
info = self.torrents[torrent_id].get_status(['save_path'])
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)
@ -798,6 +828,10 @@ class TorrentManager(component.Component):
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"""
if self.torrents[torrent_id].get_queue_position() == 0:
@ -816,7 +850,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()
@ -824,7 +858,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()
@ -866,19 +900,25 @@ class TorrentManager(component.Component):
# 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)
component.get("EventManager").emit(TorrentFinishedEvent(torrent_id))
torrent.is_finished = True
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
@ -928,7 +968,7 @@ class TorrentManager(component.Component):
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:
@ -960,7 +1000,7 @@ 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)
@ -976,12 +1016,32 @@ class TorrentManager(component.Component):
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(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
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:
@ -1010,6 +1070,7 @@ class TorrentManager(component.Component):
# 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)
# Only emit a state changed event if the state has actually changed
if torrent.state != old_state:
@ -1032,7 +1093,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:
@ -1046,7 +1107,7 @@ class TorrentManager(component.Component):
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())
@ -1081,10 +1142,10 @@ 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:
@ -1092,7 +1153,7 @@ class TorrentManager(component.Component):
torrent.update_state()
def on_alert_file_completed(self, alert):
log.debug("file_completed_alert: %s", alert.message())
log.debug("file_completed_alert: %s", decode_string(alert.message()))
try:
torrent_id = str(alert.handle.info_hash())
except:

View File

@ -9,6 +9,7 @@ Exec=deluge-gtk %U
Icon=deluge
Terminal=false
Type=Application
Categories=Network;FileTransfer;P2P;GTK
Categories=Network;FileTransfer;P2P;GTK;
StartupWMClass=Deluge
StartupNotify=true
MimeType=application/x-bittorrent;x-scheme-handler/magnet;

View File

@ -192,7 +192,17 @@ 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 the _parse() function was replaced by the _URI class
if hasattr(client, '_parse'):
scheme, host, port, path = client._parse(url)
else:
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

3977
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

View File

@ -2224,7 +2224,7 @@ msgid "Up:"
msgstr "Unvíu:"
#: deluge/ui/gtkui/aboutdialog.py:59
msgid "Copyright 2007-2011 Deluge Team"
msgid "Copyright 2007-2014 Deluge Team"
msgstr ""
#: deluge/ui/gtkui/aboutdialog.py:61

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

View File

@ -2221,7 +2221,7 @@ msgid "Up:"
msgstr ""
#: deluge/ui/gtkui/aboutdialog.py:59
msgid "Copyright 2007-2011 Deluge Team"
msgid "Copyright 2007-2014 Deluge Team"
msgstr ""
#: deluge/ui/gtkui/aboutdialog.py:61

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

View File

@ -2221,7 +2221,7 @@ msgid "Up:"
msgstr ""
#: deluge/ui/gtkui/aboutdialog.py:59
msgid "Copyright 2007-2011 Deluge Team"
msgid "Copyright 2007-2014 Deluge Team"
msgstr ""
#: deluge/ui/gtkui/aboutdialog.py:61

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

View File

@ -2223,7 +2223,7 @@ msgid "Up:"
msgstr "Omheech:"
#: deluge/ui/gtkui/aboutdialog.py:59
msgid "Copyright 2007-2011 Deluge Team"
msgid "Copyright 2007-2014 Deluge Team"
msgstr ""
#: deluge/ui/gtkui/aboutdialog.py:61

3962
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

View File

@ -2221,7 +2221,7 @@ msgid "Up:"
msgstr ""
#: deluge/ui/gtkui/aboutdialog.py:59
msgid "Copyright 2007-2011 Deluge Team"
msgid "Copyright 2007-2014 Deluge Team"
msgstr ""
#: deluge/ui/gtkui/aboutdialog.py:61

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

3970
deluge/i18n/km.po Normal file

File diff suppressed because it is too large Load Diff

View File

@ -2221,7 +2221,7 @@ msgid "Up:"
msgstr ""
#: deluge/ui/gtkui/aboutdialog.py:59
msgid "Copyright 2007-2011 Deluge Team"
msgid "Copyright 2007-2014 Deluge Team"
msgstr ""
#: deluge/ui/gtkui/aboutdialog.py:61

File diff suppressed because it is too large Load Diff

View File

@ -2221,7 +2221,7 @@ msgid "Up:"
msgstr ""
#: deluge/ui/gtkui/aboutdialog.py:59
msgid "Copyright 2007-2011 Deluge Team"
msgid "Copyright 2007-2014 Deluge Team"
msgstr ""
#: deluge/ui/gtkui/aboutdialog.py:61

3962
deluge/i18n/ky.po Normal file

File diff suppressed because it is too large Load Diff

View File

@ -2221,7 +2221,7 @@ msgid "Up:"
msgstr ""
#: deluge/ui/gtkui/aboutdialog.py:59
msgid "Copyright 2007-2011 Deluge Team"
msgid "Copyright 2007-2014 Deluge Team"
msgstr ""
#: deluge/ui/gtkui/aboutdialog.py:61

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

View File

@ -2221,7 +2221,7 @@ msgid "Up:"
msgstr ""
#: deluge/ui/gtkui/aboutdialog.py:59
msgid "Copyright 2007-2011 Deluge Team"
msgid "Copyright 2007-2014 Deluge Team"
msgstr ""
#: deluge/ui/gtkui/aboutdialog.py:61

File diff suppressed because it is too large Load Diff

3970
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

View File

@ -2221,7 +2221,7 @@ msgid "Up:"
msgstr ""
#: deluge/ui/gtkui/aboutdialog.py:59
msgid "Copyright 2007-2011 Deluge Team"
msgid "Copyright 2007-2014 Deluge Team"
msgstr ""
#: deluge/ui/gtkui/aboutdialog.py:61

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

View File

@ -2221,7 +2221,7 @@ msgid "Up:"
msgstr ""
#: deluge/ui/gtkui/aboutdialog.py:59
msgid "Copyright 2007-2011 Deluge Team"
msgid "Copyright 2007-2014 Deluge Team"
msgstr ""
#: deluge/ui/gtkui/aboutdialog.py:61

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

View File

@ -2221,7 +2221,7 @@ msgid "Up:"
msgstr ""
#: deluge/ui/gtkui/aboutdialog.py:59
msgid "Copyright 2007-2011 Deluge Team"
msgid "Copyright 2007-2014 Deluge Team"
msgstr ""
#: deluge/ui/gtkui/aboutdialog.py:61

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -2221,7 +2221,7 @@ msgid "Up:"
msgstr ""
#: deluge/ui/gtkui/aboutdialog.py:59
msgid "Copyright 2007-2011 Deluge Team"
msgid "Copyright 2007-2014 Deluge Team"
msgstr ""
#: deluge/ui/gtkui/aboutdialog.py:61

View File

@ -2221,7 +2221,7 @@ msgid "Up:"
msgstr ""
#: deluge/ui/gtkui/aboutdialog.py:59
msgid "Copyright 2007-2011 Deluge Team"
msgid "Copyright 2007-2014 Deluge Team"
msgstr ""
#: deluge/ui/gtkui/aboutdialog.py:61

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

View File

@ -2221,7 +2221,7 @@ msgid "Up:"
msgstr ""
#: deluge/ui/gtkui/aboutdialog.py:59
msgid "Copyright 2007-2011 Deluge Team"
msgid "Copyright 2007-2014 Deluge Team"
msgstr ""
#: deluge/ui/gtkui/aboutdialog.py:61

File diff suppressed because it is too large Load Diff

View File

@ -42,6 +42,8 @@
import os
import sys
from optparse import OptionParser
from logging import FileHandler
from errno import EEXIST
import deluge.log
import deluge.common
@ -86,6 +88,14 @@ def start_ui():
# Get the options and args from the OptionParser
(options, args) = parser.parse_args()
# Setup the logger
if options.quiet:
options.loglevel = "none"
if options.loglevel:
options.loglevel = options.loglevel.lower()
deluge.log.setupLogger(level=options.loglevel, filename=options.logfile)
from deluge.log import LOG as log
if options.config:
if not os.path.exists(options.config):
# Try to create the config folder if it doesn't exist
@ -94,7 +104,7 @@ def start_ui():
except Exception, e:
pass
elif not os.path.isdir(options.config):
print "Config option needs to be a directory!"
log.error("Config option needs to be a directory!")
sys.exit(1)
else:
if not os.path.exists(deluge.common.get_default_config_dir()):
@ -110,18 +120,8 @@ def start_ui():
print "The default UI has been changed to", options.default_ui
sys.exit(0)
if options.quiet:
options.loglevel = "none"
if options.loglevel:
options.loglevel = options.loglevel.lower()
# Setup the logger
deluge.log.setupLogger(level=options.loglevel, filename=options.logfile)
version = deluge.common.get_version()
from deluge.log import LOG as log
log.info("Deluge ui %s", version)
log.debug("options: %s", options)
log.debug("args: %s", args)
@ -170,18 +170,31 @@ this should be an IP address", metavar="IFACE",
# Get the options and args from the OptionParser
(options, args) = parser.parse_args()
# Setup the logger
if options.quiet:
options.loglevel = "none"
if options.logfile:
# Try to create the logfile's directory if it doesn't exist
try:
os.makedirs(os.path.abspath(os.path.dirname(options.logfile)))
except OSError, e:
if e.errno != EEXIST:
print "There was an error creating the log directory, exiting... (%s)" % e
sys.exit(1)
deluge.log.setupLogger(level=options.loglevel, filename=options.logfile)
from deluge.log import LOG as log
if options.config:
if not deluge.configmanager.set_config_dir(options.config):
print("There was an error setting the config dir! Exiting..")
log.error("There was an error setting the config directory! Exiting...")
sys.exit(1)
# Sets the options.logfile to point to the default location
def open_logfile():
if not options.logfile:
options.logfile = deluge.configmanager.get_config_dir("deluged.log")
file_handler = FileHandler(options.logfile)
log.addHandler(file_handler)
# Writes out a pidfile if necessary
def write_pidfile():
@ -208,15 +221,6 @@ this should be an IP address", metavar="IFACE",
# Do not daemonize
write_pidfile()
# Setup the logger
try:
# Try to make the logfile's directory if it doesn't exist
os.makedirs(os.path.abspath(os.path.dirname(options.logfile)))
except:
pass
deluge.log.setupLogger(level=options.loglevel, filename=options.logfile)
from deluge.log import LOG as log
if options.profile:
import hotshot
hsp = hotshot.Profile(deluge.configmanager.get_config_dir("deluged.profile"))

View File

@ -174,6 +174,12 @@ class PluginManagerBase:
info = {}.fromkeys(METADATA_KEYS)
last_header = ""
cont_lines = []
# Missing plugin info
if not self.pkg_env[name]:
log.warn("Failed to retrive info for plugin '%s'" % name)
for k in info:
info[k] = _("Not available")
return info
for line in self.pkg_env[name][0].get_metadata("PKG-INFO").splitlines():
if not line:
continue
@ -187,5 +193,4 @@ class PluginManagerBase:
if line.split(":", 1)[0] in info.keys():
last_header = line.split(":", 1)[0]
info[last_header] = line.split(":", 1)[1].strip()
return info

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