Compare commits
291 Commits
deluge-2.1
...
archive/1.
Author | SHA1 | Date | |
---|---|---|---|
8c36830456 | |||
568321a8ed | |||
2c10218efd | |||
ee73936c26 | |||
d299ecedb2 | |||
0b609bf4ad | |||
131af5a50a | |||
65b4f8c543 | |||
e79461c7d2 | |||
c1f137505a | |||
f598d048d1 | |||
4f134731df | |||
de25c17af1 | |||
41314e595a | |||
e5e43532d3 | |||
9e4a92444b | |||
72fd3bd061 | |||
cc086917c1 | |||
3e0a35c802 | |||
4a2316411d | |||
1b54d5b93b | |||
64d927b499 | |||
3e639c3445 | |||
ec39a8d501 | |||
90103358f3 | |||
32a00d7919 | |||
3932e632c1 | |||
3f37b3bb01 | |||
03b9b940af | |||
eeda4a5ecd | |||
fd5460b403 | |||
35b72ba8d7 | |||
fc109479bf | |||
f0226decff | |||
5bd22ee6d5 | |||
c0b3d4745a | |||
f9414105df | |||
a227617bac | |||
58ef466d9c | |||
9250bbfb89 | |||
dfdcf117b4 | |||
52b5e9d4e3 | |||
479d84857f | |||
b9abe8ea10 | |||
9e51e39629 | |||
e999d34e5c | |||
abc66b5b5e | |||
5b23993960 | |||
eadfa323ca | |||
f666c28e14 | |||
1da79ceb75 | |||
8e5f8bb249 | |||
3791fe2d2f | |||
27c0f339ce | |||
c605616cb9 | |||
443d4d7a3a | |||
34fb2def75 | |||
95b26efbb4 | |||
dc35732896 | |||
292428280d | |||
5438a39af2 | |||
ec15c3aadb | |||
41ef49a27e | |||
e3fcaf0c1a | |||
10262cea81 | |||
545e64e3c3 | |||
85493750fb | |||
124ec3e9c7 | |||
b3975bd4c2 | |||
445096378c | |||
3686130ea5 | |||
4af387f774 | |||
a62fdac0a6 | |||
1941c5976c | |||
4f28ab9a39 | |||
79c78fa7ef | |||
89c9228cec | |||
0df79b03c5 | |||
c54a50af34 | |||
e81d2ea0bd | |||
5e19f91613 | |||
5a35d60178 | |||
34b2ada0db | |||
547cfa6339 | |||
3870c25c9d | |||
4cde35a067 | |||
d5a11d0e95 | |||
1f8919b47f | |||
59f05a890f | |||
afbeaa6b7d | |||
f5409e0d0c | |||
ac857eaef7 | |||
886f2d8682 | |||
fa79c37aa2 | |||
6a8e023ffd | |||
6b396f1f77 | |||
b2990e89cb | |||
7ebe07db15 | |||
14eb3b8b33 | |||
cffc25aac8 | |||
ed2568c8b0 | |||
700fe2ec17 | |||
571b8a84af | |||
3d821fb80b | |||
00c4b53b67 | |||
9a9ae71564 | |||
c9c57e0e32 | |||
c70a9875c5 | |||
c932de8470 | |||
0663da4424 | |||
8c265bb308 | |||
fe6c89a2e1 | |||
3c5d5aa16e | |||
389e9cdbb0 | |||
193f1b85ca | |||
4daa2a098b | |||
52817498cf | |||
cc3f3495b6 | |||
4bd00aa331 | |||
e27c38ca67 | |||
eeac8efcf2 | |||
f59901c1be | |||
ee76075fa4 | |||
3f69b05ded | |||
ecca68772e | |||
9878fced37 | |||
c312cf4b91 | |||
de262bf7db | |||
8edd91a3d5 | |||
f6fdae727d | |||
139d6538a2 | |||
b88319b4be | |||
dd129f8544 | |||
af18bdb72a | |||
85b3546c47 | |||
07cd4ba83d | |||
361f2b2390 | |||
97a69b8c0c | |||
29f2ed84dd | |||
9e9fbd6242 | |||
2840d43ccb | |||
14454791c4 | |||
fcbaa1f4f2 | |||
c716f55dda | |||
a1e950d6e5 | |||
e646a5ef87 | |||
3c703d2ef7 | |||
429f7064fa | |||
47b5274f34 | |||
a6c6d5b2b4 | |||
3d3edccdac | |||
36b2a82561 | |||
f5096c6e7c | |||
76bc32d72a | |||
581517c8e9 | |||
b41a025217 | |||
7a91b96183 | |||
a317fdec48 | |||
20b6791670 | |||
411ee123f1 | |||
2bc13a3fb7 | |||
dda893e2b7 | |||
00de8311fd | |||
6d7572c444 | |||
3e1a6a1fb8 | |||
dbbc1124f4 | |||
13d949381a | |||
bfea47c8bd | |||
f858e271ad | |||
708f052153 | |||
8d6bc283d0 | |||
313c73c40c | |||
012dd1919c | |||
d7e83d922c | |||
860ceccd52 | |||
907f618607 | |||
abcb76e959 | |||
825edb1fd8 | |||
4cdf919076 | |||
90a143a4ef | |||
04f8f80b9b | |||
266693a6f9 | |||
2b9e1e5ff4 | |||
68fe9512df | |||
b10ea808fd | |||
234863b664 | |||
940bc4a3dc | |||
aa5f69b203 | |||
5f4b39aeb8 | |||
0e07cdf8b1 | |||
64eb296c9d | |||
fa40f38c1b | |||
1b46d99620 | |||
441c20491c | |||
8c7bbbf398 | |||
267905295c | |||
fb4495fc33 | |||
447da3b1b4 | |||
9af41fd457 | |||
7e19a11521 | |||
4da33c72cc | |||
d411f90a67 | |||
3179ff2060 | |||
b6dc72218d | |||
e884d2cbfa | |||
fc3ae8229f | |||
48e3df5ff3 | |||
464e11abe6 | |||
0fbaecbc00 | |||
4c86ed7535 | |||
6f333cefc9 | |||
750f8fb794 | |||
be529c1518 | |||
e32bd8f4d8 | |||
87723a3354 | |||
0cb52cca23 | |||
09ae4fbb72 | |||
6e063e7c85 | |||
41db357084 | |||
3611584b0b | |||
6e695d8410 | |||
60fdcb3bd8 | |||
d110b23a9f | |||
2457fd0aea | |||
92afb8ab80 | |||
eba82457bd | |||
099415776d | |||
145f402aa2 | |||
d44efe8a66 | |||
1a9f715353 | |||
2308961a04 | |||
0cdd779396 | |||
db54dada9d | |||
7c5582a21e | |||
7055a96930 | |||
e7a45f6dd1 | |||
ea4dcfbb5e | |||
5c506121a4 | |||
cc7aaa1ae0 | |||
cca2a4ab60 | |||
197027510e | |||
b12b5a8403 | |||
0b5a0ac9a0 | |||
65e50d1992 | |||
ecd75ba424 | |||
694051e876 | |||
350c523e7d | |||
dbece6a6f6 | |||
5c26a4b1cf | |||
475a880dd9 | |||
b0702e6a6d | |||
e506147289 | |||
3c4144e01a | |||
d4f2c2eda8 | |||
4a996a1b41 | |||
e39d1ab679 | |||
c49ab0c6b1 | |||
9c412e8aff | |||
83f42f5bf8 | |||
039a41def3 | |||
b94060c60d | |||
33301b3433 | |||
b9ae412d06 | |||
f55bc6c9d8 | |||
511bfd5d84 | |||
89f88f3beb | |||
b1b09fbe89 | |||
07b50730a2 | |||
5607e0f6fa | |||
9ab638377b | |||
4b79ae8280 | |||
f1a1fdb630 | |||
d1f52a7051 | |||
000297dc95 | |||
81eeb6edf7 | |||
7d67da4371 | |||
ef5739a6a8 | |||
4f968b9887 | |||
22447993fa | |||
58be1f08fc | |||
41d26bbbce | |||
f1383f9655 | |||
644f0ecb38 | |||
42a57b1f41 | |||
8f50687034 | |||
9f661caee8 | |||
044306cb3d | |||
ebd0290e44 | |||
4f1713734f | |||
f86e319d49 | |||
95bb8fb4c3 |
9
.gitattributes
vendored
Normal file
9
.gitattributes
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
/libtorrent export-ignore
|
||||
/win32 export-ignore
|
||||
docs/build export-ignore
|
||||
docs/source export-ignore
|
||||
/tests export-ignore
|
||||
deluge/scripts export-ignore
|
||||
.gitattributes export-ignore
|
||||
.gitmodules export-ignore
|
||||
.gitignore export-ignore
|
8
.gitignore
vendored
Normal file
8
.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
*~
|
||||
build
|
||||
dist
|
||||
*egg-info
|
||||
*.egg
|
||||
*.log
|
||||
*.pyc
|
||||
*.tar.*
|
503
ChangeLog
503
ChangeLog
@ -1,98 +1,451 @@
|
||||
=== Deluge 1.2.0 (In Development) ===
|
||||
=== Deluge 1.2.3 (27 March 2010) ===
|
||||
==== Core ====
|
||||
* Implement new RPC protocol DelugeRPC replacing XMLRPC
|
||||
* Move to a twisted framework
|
||||
* Add an 'Error' filter for Trackers to show trackers that currently have a tracker error
|
||||
* Use system GeoIP database if available, this is now an optional dependency
|
||||
* Fix libtorrent version compare to use a proper numerical compare instead
|
||||
of string. This fixes a problem where using lt 0.14.10 wouldn't allow
|
||||
Deluge to start.
|
||||
* Fix libtorrent 0.15 compatibility
|
||||
* Fix hang on quit
|
||||
|
||||
=== Deluge 1.2.2 (19 March 2010) ===
|
||||
==== Core ====
|
||||
* Fix #1109 auto add halting when a torrent with invalid filename encoding
|
||||
is in the directory
|
||||
|
||||
==== GtkUI ====
|
||||
* Remove SignalReceiver
|
||||
* Implemented a cross-platform IPC method thus removing the DBUS dependency
|
||||
* Implement a "True" Classic Mode where there is no longer a separate daemon process
|
||||
* Add preferences option "Add torrent in paused state"
|
||||
* Add tracker icons to the Tracker column
|
||||
* Implement #259 show tooltip with country name in the peers tab
|
||||
* Add an error category to the tracker sidebar list
|
||||
* Add Find More Plugins button to Plugins preference page
|
||||
* Fix #518 remove header in add torrent dialog to save vertical space
|
||||
* Add a Cache preferences page to adjust cache settings and examine cache status
|
||||
* Add ability to rename files prior to adding them
|
||||
* Fix shutdown handler with GNOME session manager
|
||||
* Allow 4 MiB piece sizes when creating a torrent
|
||||
* Fix #1162 problem with the queued torrents dialog from not properly adding
|
||||
to the add torrent dialog if set to auto add
|
||||
* Fix #1172 notify startup complete when adding torrents externally
|
||||
* Fix issue where the gtkui sometimes won't start if there is a stale lock
|
||||
file or socket in the ipc/ directory.
|
||||
|
||||
==== ConsoleUI ====
|
||||
* Changed to use curses for a more interactive client
|
||||
==== Console ====
|
||||
* Fix #1143 deluge-console crashes when tab-completing not-existent directory
|
||||
|
||||
==== WebUI ====
|
||||
* Move over to using Twisted-Web for the webserver.
|
||||
* Move to only AJAX interface built upon Ext-JS.
|
||||
=== Deluge 1.2.1 (20 February 2010) ===
|
||||
==== Core ====
|
||||
* Make Deluge dependent upon libtorrent 0.14.9 or greater. This is due to
|
||||
an over-downloading bug in previous versions of libtorrent.
|
||||
|
||||
==== Plugins ====
|
||||
* Add Scheduler plugin
|
||||
* Add Extractor plugin
|
||||
==== GtkUI ====
|
||||
* Fix #1128 Show an error dialog when unable to start a 'deluged' process
|
||||
* Increased max enterable download / upload limit to 60000 KiB/s
|
||||
|
||||
==== Console ====
|
||||
* Fix hanging when using commands from the command-line
|
||||
|
||||
==== Web ====
|
||||
* Fix #1147: Cannot upload a torrent in a multi-user system via the web interface
|
||||
* Fix #1148: Unable to save execute command in execute plugin
|
||||
|
||||
=== Deluge 1.2.0 - "Bursting like an infected kidney" (10 January 2010) ===
|
||||
==== Core ====
|
||||
* Fix file renaming
|
||||
* Fix tracker host filtering (Closes #1106)
|
||||
* Fix exceptions when gettext/locale cannot be initialized properly
|
||||
* Change share ratio calculation to use the total done instead of the all time
|
||||
downloaded value. This change will make the share ratio calculation not
|
||||
use data downloaded in failed hash checks.
|
||||
* Fix torrent info name not being utf-8 decoded when root file/folder name
|
||||
is blank
|
||||
|
||||
==== GtkUI ====
|
||||
* Fix #1104, #735 use path.utf-8 if available
|
||||
* Fix #1114 test active port not working in classic mode
|
||||
|
||||
==== Console ====
|
||||
* Fix #1115 not showing usage for the 'debug' command
|
||||
* Fix #1116 not being able to use command aliases when not connected to a daemon
|
||||
* Fix #1117 can't use the '3' key
|
||||
|
||||
==== Windows ====
|
||||
* Fix displaying folders in the add torrent dialog
|
||||
* Fix displaying the new release dialog
|
||||
|
||||
==== Blocklist ====
|
||||
* Fix blocklist status icon not opening the blocklist preference
|
||||
page in certain locales
|
||||
* Fix blocklist not recognising comments that begin with whitespace
|
||||
* Minor speedup in parsing blocklists
|
||||
* Blocklist now attempts to download the URL multiple times before giving
|
||||
up
|
||||
* Fix blocklist not being able to open zipped blocklists with python 2.5
|
||||
|
||||
==== Web ====
|
||||
* Put the default password in the manpage.
|
||||
|
||||
=== Deluge 1.2.0_rc5 (17 December 2009) ===
|
||||
==== Web ====
|
||||
* Swap order of buttons in Remove window (Closes #1083)
|
||||
* Change the compressed js script to deluge-all.js to avoid naming
|
||||
conflicts on case-sensitive filesystems.
|
||||
* Apply patch from adios fixing the cookie date
|
||||
* Add tooltips to the statusbar items
|
||||
* Add disk usage to the statusbar
|
||||
* Add a ToggleField widget and use this on the Downloads preferences
|
||||
page allowing the movecom/copytorrent/autoadd boxes to be enabled.
|
||||
* Fix enabling plugins.
|
||||
* Implement installing plugins.
|
||||
* Update some icons
|
||||
* Fixed #1075 (changing priority on a whole folder doesn't work)
|
||||
|
||||
==== GtkUI ====
|
||||
* Attempt to register as the default magnet uri handler in GNOME on startup
|
||||
* Properly show 100.00% and reduce number of progress bar updates during a
|
||||
torrent creation
|
||||
* Fix crash in Windows when creating a torrent
|
||||
* Add button to Other preferences to associate magnet links with Deluge
|
||||
* Fix uploading plugins when the daemon is not localhost
|
||||
* Fix #692 no longer require tray password when quitting from the tray icon
|
||||
while the window is visible.
|
||||
* Fix #782 do not ask for tray password when window is not minimized to tray
|
||||
* Fix #1036 autoconnecting to localhost daemon on start-up
|
||||
* Fix issue where hosts will show up erroneously as Offline
|
||||
* Add #891 remove torrents by pressing the Delete key
|
||||
* Fix issue where stoping a daemon that you aren't connected to causes the
|
||||
gtkui to shutdown the currently connected daemon.
|
||||
* Fix #594 tray password dialog freeze in Windows
|
||||
* Made the password dialog prettier
|
||||
* Fix #1086 deprecated gtk.Tooltips usage
|
||||
* Fix #768 save tracker list for create torrent dialog
|
||||
* Fix #1095 incorrect piece size used when using some non-English languages
|
||||
|
||||
==== Console ====
|
||||
* Fix using the console in Windows, but only in command-line mode
|
||||
* Fix #823 setting config values to -1.0
|
||||
|
||||
==== Label ====
|
||||
* Fix #1085 only use ints for specific options to prevent unhandled exception
|
||||
|
||||
==== Execute ====
|
||||
* Use the move_completed path if it is different to the save path
|
||||
in the completed event.
|
||||
|
||||
==== Core ====
|
||||
* Fix the upload_plugin rpc method (was still using XML-RPC stuff)
|
||||
* Fix possible exception when upgrading from a 0.5 state file
|
||||
* Use metavar to modify the help output by optparse.
|
||||
* Partial fix for #1103 if the per-torrent option for stopping at a ratio has
|
||||
been unchecked, then do not stop it at the global setting.
|
||||
|
||||
==== Blocklist ====
|
||||
* Fix blocklist not working for all locales
|
||||
* Fix blocklist checking for updates when it shouldn't
|
||||
|
||||
=== Deluge 1.2.0_rc4 (24 November 2009) ===
|
||||
==== Core ====
|
||||
* Fix deleting old .fastresume files with fresh configs
|
||||
* Fix files list when using magnet uris
|
||||
* Fix loading the saved metadata when loading state with magnet uris
|
||||
|
||||
==== GtkUI ====
|
||||
* Fix showing the 'Other' speed dialogs in Windows
|
||||
* Fix adding torrents from the Queued Torrents dialog
|
||||
* Fix disabling/enabling plugins after switching daemons
|
||||
* Reduce height of Add Torrent Dialog by ~80 pixels
|
||||
* Fix #1071 issue where Deluge will fail to start if there is a stale ipc lockfile
|
||||
* Fix autoconnecting to the next host in the list if the selected one isn't available
|
||||
* Fix endless loop when trying to autoconnect to an offline daemon
|
||||
* Fix exception on startup when the system tray icon is not enabled
|
||||
* Fix issue where some torrents with special characters could not be added
|
||||
* Fix issues adding magnet uris
|
||||
|
||||
==== Web ====
|
||||
* Fix installing the deluge-web manpage
|
||||
* Escape hyphens in the manpage
|
||||
|
||||
==== Console ====
|
||||
* Escape hyphens in the manpage
|
||||
* Make the delete key work
|
||||
* Allow ~ to be used in the path in the add command
|
||||
* Allow commands that are .pyc files to be used
|
||||
* Fix printing info, help, etc.. on the command line
|
||||
|
||||
==== Blocklist ====
|
||||
* Force blocklist to auto-detect format when a download / import is forced
|
||||
* Fix blocklist failing on certain PeerGuardian/SafePeer lists
|
||||
|
||||
=== Deluge 1.2.0_rc3 (01 November 2009) ===
|
||||
==== Core ====
|
||||
* Fix #1047 move completed does not work if saving to non default path
|
||||
* Fix renamed files not being utf-8 encoded
|
||||
* Fix torrent name being blank when renaming root folder to /
|
||||
* Do not include an 'announce-list' key in torrents when there is only one tracker
|
||||
|
||||
==== GtkUI ====
|
||||
* Replace & with & in the details tab to ensure there are no markup errors
|
||||
* Consider 0 unlimited when displaying limits in the statusbar
|
||||
* Fix adding torrents when not showing the add torrent dialog in Windows
|
||||
* Fix crash when removing multiple torrents
|
||||
|
||||
==== Web ====
|
||||
* Fix #1046 changing auto managed via the details tab
|
||||
* Fix setting torrent options when adding
|
||||
* Fix setting file priorities when adding
|
||||
* HTML escape the field values on the details tab
|
||||
* Fix #215, make infinite eta values display in the correct order
|
||||
* Fix displaying the protocol upload speed
|
||||
* Fix #990, showing 0 as a limit when it means unlimited in the statusbar
|
||||
|
||||
==== Console ====
|
||||
* Fix displaying non-ascii strings
|
||||
* Fix #1052 crash when issuing commands while not connected to a daemon
|
||||
* Fix crash when string length makes line longer than terminal width
|
||||
* Improve 'info' command draw speed
|
||||
|
||||
=== Deluge 1.2.0_rc2 (25 October 2009) ===
|
||||
==== GtkUI ====
|
||||
* Fix path errors when adding torrents externally in Windows
|
||||
* Fix localclient authentication by stripping the lines read from the auth file
|
||||
* Do not try to call doIteration() on the reactor if it has already stopped
|
||||
* Fix 'autostart localhost if needed' option
|
||||
* Fix starting plugins when the pluginmanager is started
|
||||
* Fix #799 translate connection status
|
||||
* Fix #215 ETA sort order
|
||||
|
||||
==== Core ====
|
||||
* Fix saving torrent state on fresh configs
|
||||
|
||||
==== Web ====
|
||||
* Fix changing of the allocation in the preferences.
|
||||
* Fix updating the Connection Manager when a host is added.
|
||||
* Add a `--fork` option to allow forking the webui to the background
|
||||
* Fix the statusbar menu limits
|
||||
* Fix setting the torrent options via the options tab
|
||||
* Fix the private flag in the options tab
|
||||
|
||||
==== Console ====
|
||||
* Fix exception when using the 'halt' command
|
||||
|
||||
==== Misc ====
|
||||
* PyGTK dependency bumped to => 2.12 to use new tooltip system
|
||||
* Add new scripts for invoking UIs: deluge-gtk, deluge-web, deluge-console
|
||||
* Remove GeoIP database from the source tree
|
||||
* Add man pages for deluge-console, deluge-gtk and deluge-web
|
||||
|
||||
==== Extractor ====
|
||||
* Fix issue where the plugin would not stop extracting files after being disabled
|
||||
* Add option to create torrent name sub-folders in extract folder
|
||||
|
||||
=== Deluge 1.2.0_rc1 (07 October 2009) ===
|
||||
==== Core ====
|
||||
* Implement new RPC protocol DelugeRPC replacing XMLRPC
|
||||
* Move to a twisted framework
|
||||
* Add an 'Error' filter for Trackers to show trackers that currently have a tracker error
|
||||
* Use system GeoIP database if available, this is now an optional dependency
|
||||
|
||||
==== GtkUI ====
|
||||
* Remove SignalReceiver
|
||||
* Implemented a cross-platform IPC method thus removing the DBUS dependency
|
||||
* Implement a "True" Classic Mode where there is no longer a separate daemon process
|
||||
* Add preferences option "Add torrent in paused state"
|
||||
* Add tracker icons to the Tracker column
|
||||
* Implement #259 show tooltip with country name in the peers tab
|
||||
* Add an error category to the tracker sidebar list
|
||||
* Add Find More Plugins button to Plugins preference page
|
||||
* Fix #518 remove header in add torrent dialog to save vertical space
|
||||
* Add a Cache preferences page to adjust cache settings and examine cache status
|
||||
* Add ability to rename files prior to adding them
|
||||
* Fix shutdown handler with GNOME session manager
|
||||
* Allow 4 MiB piece sizes when creating a torrent
|
||||
|
||||
==== ConsoleUI ====
|
||||
* Changed to use curses for a more interactive client
|
||||
|
||||
==== WebUI ====
|
||||
* Move over to using Twisted-Web for the webserver.
|
||||
* Move to only AJAX interface built upon Ext-JS.
|
||||
|
||||
==== Plugins ====
|
||||
* Add Scheduler plugin
|
||||
* Add Extractor plugin
|
||||
|
||||
==== Misc ====
|
||||
* PyGTK dependency bumped to => 2.12 to use new tooltip system
|
||||
* Add new scripts for invoking UIs: deluge-gtk, deluge-web, deluge-console
|
||||
* Remove GeoIP database from the source tree
|
||||
|
||||
=== Deluge 1.1.9 - (15 June 2009) ===
|
||||
==== Core ====
|
||||
* Only move a torrent due to 'move on complete' when some data has been downloaded
|
||||
* Update libtorrent for CVE-2009-1760
|
||||
|
||||
==== GtkUI ====
|
||||
* Fix #950 renaming a parent folder into multiple folders
|
||||
|
||||
==== WebUI ====
|
||||
* Fix remote torrent add
|
||||
|
||||
=== Deluge 1.1.8 - (21 May 2009) ===
|
||||
==== Core ====
|
||||
* Fix pause all/resume all
|
||||
* Torrent name is now changed when the root folder or file is renamed
|
||||
|
||||
==== GtkUI ====
|
||||
* Fix high cpu usage when displaying speeds in titlebar
|
||||
* Fix showing non-utf8 encoded torrents in add torrent dialog -- this adds
|
||||
an additional dependency on chardet.
|
||||
* Fix exception when timing out trying to send notification email
|
||||
* Set some sane defaults for peers/file tabs column widths
|
||||
|
||||
==== WebUI ====
|
||||
* Fix starting when -l option is used
|
||||
|
||||
=== Deluge 1.1.7 - (25 April 2009) ===
|
||||
==== Core ====
|
||||
* Fix issue where cannot resume torrent after doing a 'Pause All'
|
||||
* Add workaround for 'address_v4 from unsigned long' bug experienced by users
|
||||
with 64-bit machines. This bug is fixed in libtorrent 0.14.3.
|
||||
|
||||
==== GtkUI ====
|
||||
* Fix #883 segfault if locale is not using UTF-8 encoding
|
||||
* Fix for adding torrents with invalid filename encodings
|
||||
* Fix displaying IPv6 peers in the Peers tab
|
||||
* Fix starting the daemon in OS X
|
||||
* Fix loading improperly created torrents with mismatched encodings
|
||||
* Fix displaying improper progress when creating torrent
|
||||
|
||||
==== Windows ====
|
||||
* Fix freezing in create torrent dialog
|
||||
* Fix creating torrents in Windows
|
||||
* Fix free space check
|
||||
|
||||
=== Deluge 1.1.6 - (06 April 2009) ===
|
||||
==== Core ====
|
||||
* Fix udp trackers being classified as DHT source
|
||||
* Fix #855 force a resume on a torrent if a 'Force Recheck' is initiated
|
||||
* Fix #862 deluged crash when access http://localhost:58846
|
||||
|
||||
==== GtkUI ====
|
||||
* Fix displaying torrents with non-utf8 encodings in add torrent dialog
|
||||
|
||||
==== WebUI ====
|
||||
* Fix #870 use proper config location for loading ssl cert
|
||||
|
||||
==== Misc ====
|
||||
* Add OpenSSL exception to license
|
||||
|
||||
=== Deluge 1.1.5 - (16 March 2009) ===
|
||||
==== Core ====
|
||||
* Fix config file saving when no current config file exists
|
||||
|
||||
==== GtkUI ====
|
||||
* Add 'Comments' field to the Details tab
|
||||
* Fix #841 maximum upload slots tooltip
|
||||
|
||||
=== Deluge 1.1.4 - (08 March 2009) ===
|
||||
==== Core ====
|
||||
* Fix displaying file errors when the torrent isn't paused
|
||||
* Fix issue where torrents being check would get removed due to "stop at ratio" rules
|
||||
* Fix #790 tracker hosts not correct for some .uk trackers
|
||||
* Make sure config files, resume data and state are fsync'd when saved. This should help prevent data losses on crashes/improper shutdowns.
|
||||
|
||||
==== GtkUI ====
|
||||
* Fix hiding bottom pane when no tabs are enabled upon restart
|
||||
* Fix saving file priorities when switching torrents in the addtorrentdialog
|
||||
* Fix the allocate mode not being preserved when selecting different torrents in addtorrentdialog
|
||||
* Fix #655 issue where default torrent options wouldn't be set for new torrents added to the addtorrentdialog
|
||||
* Fix #817 email notifications fail to substitute format strings
|
||||
|
||||
==== Plugins ====
|
||||
* Label: Fix setting 'Move on completed' folder when connected to a remote daemon
|
||||
|
||||
=== Deluge 1.1.3 - (15 February 2009) ===
|
||||
==== Core ====
|
||||
* Fix issue where checking queue would stop
|
||||
* Fix announcing to SSL trackers
|
||||
|
||||
==== Misc ====
|
||||
* Fix issue when initializing gettext that would prevent deluge from starting
|
||||
* Fix logging exceptions when starting the daemon
|
||||
* Fix displaying errors when a torrent is Checking
|
||||
* Fix #790 tracker hosts not correct for some 3rd-level domain names
|
||||
|
||||
=== Deluge 1.1.2 - (31 January 2009) ===
|
||||
==== Core ====
|
||||
* Fix issue where torrents get stuck Checking
|
||||
|
||||
==== GtkUI ====
|
||||
* Fix #761 use proper theme colours in sidebar
|
||||
* Fix saving files/peers tab state when no column is sorted
|
||||
|
||||
=== Deluge 1.1.1 - (24 January 2009) ===
|
||||
==== Core ====
|
||||
* Fix oldstateupgrader for those upgrading from 0.5.x
|
||||
* Fix setting Peer TOS byte
|
||||
* Fix setting outgoing ports
|
||||
|
||||
==== GtkUI ====
|
||||
* Fix opening links from Help menu and others
|
||||
* Fix remembering sorted column in the torrent list
|
||||
* Fix saving Files tab and Peers tab state
|
||||
* Disable popup notification in preferences on Windows
|
||||
* Fix crashing in Add Torrent Dialog when removing torrents from the list
|
||||
* Do not allow duplicate torrents in the Add Torrent Dialog
|
||||
* Fix translating speed units in status tab when a per-torrent limit is set
|
||||
* Fix torrents not displaying properly after disconnecting and reconnecting to the daemon
|
||||
* Fix when sorting # column, downloads should be on top
|
||||
|
||||
==== Misc ====
|
||||
* Fix bdecoding some torrent files
|
||||
* Fix the -l, --logfile option
|
||||
* Fix #729 tracker icons not being saved in the correct location
|
||||
* Add support for more tracker icons
|
||||
* Fix being able to connect to a local daemon from another user account
|
||||
|
||||
=== Deluge 1.1.0 - "Time gas!" (10 January 2009) ===
|
||||
==== Core ====
|
||||
* Implement #79 ability to change outgoing port range
|
||||
* Implement #296 ability to change peer TOS byte
|
||||
* Add per-torrent move on completed settings
|
||||
* Implement #414 use async save_resume_data method
|
||||
* Filter Manager with torrent filtering in get_torrents_status , for sidebar and plugins.
|
||||
* Implement #368 add torrents by infohash/magnet uri (trackerless torrents)
|
||||
* Remove remaining gtk functions in common
|
||||
* Tracker icons.
|
||||
* Add ETA for torrents with stop at seed ratio set
|
||||
* Fix #47 the state and config files are no longer invalidated when there is no diskspace
|
||||
* Fix #619 return "" instead of "Infinity" if seconds == 0 in ftime
|
||||
* Add -P, --pidfile option to deluged
|
||||
* Implement #79 ability to change outgoing port range
|
||||
* Implement #296 ability to change peer TOS byte
|
||||
* Add per-torrent move on completed settings
|
||||
* Implement #414 use async save_resume_data method
|
||||
* Filter Manager with torrent filtering in get_torrents_status , for sidebar and plugins.
|
||||
* Implement #368 add torrents by infohash/magnet uri (trackerless torrents)
|
||||
* Remove remaining gtk functions in common
|
||||
* Tracker icons.
|
||||
* Add ETA for torrents with stop at seed ratio set
|
||||
* Fix #47 the state and config files are no longer invalidated when there is no diskspace
|
||||
* Fix #619 return "" instead of "Infinity" if seconds == 0 in ftime
|
||||
* Add -P, --pidfile option to deluged
|
||||
|
||||
==== GtkUI ====
|
||||
* Add peer progress to the peers tab
|
||||
* Add ability to manually add peers
|
||||
* Sorting # column will place downloaders above seeds
|
||||
* Remove dependency on libtorrent for add torrent dialog
|
||||
* Allow adding multiple trackers at once in the edit tracker dialog
|
||||
* Implement #28 Create Torrent Dialog
|
||||
* Redesiged sidebar with filters for Active and Tracker (see Filter Manager)
|
||||
* Implement #428 the ability to rename files and directories
|
||||
* Implement #229 add date added column
|
||||
* Implement #596 show speeds in title
|
||||
* Fix #636 not setting the daemon's config directory when using --config= with the UI in classic mode.
|
||||
* Fix #624 do not allow changing file priorities when using compact allocation
|
||||
* Fix #602 re-did files/peers tab state saving/loading
|
||||
* Fix gtk warnings
|
||||
* Add protocol traffic statusbar item
|
||||
* Rework the Remove Torrent Dialog to only have 2 options, remove data and remove from session.
|
||||
* Add "Install Plugin" and "Rescan Plugins" buttons to the Plugins preferences
|
||||
* Make active port test use internal graphic instead of launching browser
|
||||
* Add peer progress to the peers tab
|
||||
* Add ability to manually add peers
|
||||
* Sorting # column will place downloaders above seeds
|
||||
* Remove dependency on libtorrent for add torrent dialog
|
||||
* Allow adding multiple trackers at once in the edit tracker dialog
|
||||
* Implement #28 Create Torrent Dialog
|
||||
* Redesiged sidebar with filters for Active and Tracker (see Filter Manager)
|
||||
* Implement #428 the ability to rename files and directories
|
||||
* Implement #229 add date added column
|
||||
* Implement #596 show speeds in title
|
||||
* Fix #636 not setting the daemon's config directory when using --config= with the UI in classic mode.
|
||||
* Fix #624 do not allow changing file priorities when using compact allocation
|
||||
* Fix #602 re-did files/peers tab state saving/loading
|
||||
* Fix gtk warnings
|
||||
* Add protocol traffic statusbar item
|
||||
* Rework the Remove Torrent Dialog to only have 2 options, remove data and remove from session.
|
||||
* Add "Install Plugin" and "Rescan Plugins" buttons to the Plugins preferences
|
||||
* Make active port test use internal graphic instead of launching browser
|
||||
|
||||
==== WebUI ====
|
||||
* Lots of smaller tweaks.
|
||||
* All details tabs have the same features as in gtk-ui 1.0.x
|
||||
* Persistent sessions #486
|
||||
* Plugin improvements for easy use of templates and images in eggs. #497
|
||||
* Classic template takes over some style elements from white template.
|
||||
* https (for users that know how to create certificates)
|
||||
* Easier apache mod_proxy use.
|
||||
* Redesigned sidebar
|
||||
* Lots of smaller tweaks.
|
||||
* All details tabs have the same features as in gtk-ui 1.0.x
|
||||
* Persistent sessions #486
|
||||
* Plugin improvements for easy use of templates and images in eggs. #497
|
||||
* Classic template takes over some style elements from white template.
|
||||
* https (for users that know how to create certificates)
|
||||
* Easier apache mod_proxy use.
|
||||
* Redesigned sidebar
|
||||
|
||||
==== AjaxUI ====
|
||||
* Hosted in a webui template.
|
||||
* Hosted in a webui template.
|
||||
|
||||
==== ConsoleUI ====
|
||||
* New ConsoleUI written by Idoa01
|
||||
* Callable from command-line for scripts.
|
||||
* New ConsoleUI written by Idoa01
|
||||
* Callable from command-line for scripts.
|
||||
|
||||
==== Plugins ====
|
||||
* Stats plugin for graphs.
|
||||
* Label plugin for grouping torrents and per torrent settings.
|
||||
* Stats plugin for graphs.
|
||||
* Label plugin for grouping torrents and per torrent settings.
|
||||
|
||||
==== Misc ====
|
||||
* Implement #478 display UI options in usage help
|
||||
* Fix #547 add description to name field per HIG entry 2.1.1.1
|
||||
* Fix #531 set default log level to ERROR and add 2 command-line options, "-L, --loglevel" and "-q, --quiet".
|
||||
* Implement #478 display UI options in usage help
|
||||
* Fix #547 add description to name field per HIG entry 2.1.1.1
|
||||
* Fix #531 set default log level to ERROR and add 2 command-line options, "-L, --loglevel" and "-q, --quiet".
|
||||
|
8
DEPENDS
8
DEPENDS
@ -8,13 +8,7 @@
|
||||
* gettext
|
||||
* pyxdg
|
||||
* geoip-database (optional)
|
||||
|
||||
* libtorrent >= 0.14, or build the included version
|
||||
|
||||
* If building included libtorrent::
|
||||
* boost >= 1.34.1
|
||||
* openssl
|
||||
* zlib
|
||||
* libtorrent >= 0.14.9
|
||||
|
||||
=== UIs ===
|
||||
* chardet
|
||||
|
23
create_potfiles_in.py
Normal file
23
create_potfiles_in.py
Normal file
@ -0,0 +1,23 @@
|
||||
import os
|
||||
|
||||
# Paths to exclude
|
||||
EXCLUSIONS = [
|
||||
"deluge/scripts"
|
||||
]
|
||||
|
||||
POTFILE_IN = "deluge/i18n/POTFILES.in"
|
||||
|
||||
print "Creating " + POTFILE_IN + " .."
|
||||
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:
|
||||
to_translate.append(os.path.join(dirpath, filename))
|
||||
|
||||
f = open(POTFILE_IN, "wb")
|
||||
for line in to_translate:
|
||||
f.write(line + "\n")
|
||||
|
||||
f.close()
|
||||
|
||||
print "Done"
|
5
debian/changelog
vendored
5
debian/changelog
vendored
@ -1,5 +0,0 @@
|
||||
deluge-torrent (0.9.08-1) unstable; urgency=low
|
||||
|
||||
* R8 release
|
||||
|
||||
-- Andrew Resch (andar) <andrewresch@gmail.com> Tue, 26 Aug 2008 16:31:14 -0800
|
5
debian/changelog.debian-lenny
vendored
5
debian/changelog.debian-lenny
vendored
@ -1,5 +0,0 @@
|
||||
deluge-torrent (0.6.0-svn3235-1) lenny; urgency=low
|
||||
|
||||
* Daily Build
|
||||
|
||||
-- Andrew Resch (andar) <andrewresch@gmail.com> Tue, 17 Jun 2008 16:31:14 -0800
|
5
debian/changelog.debian-sid
vendored
5
debian/changelog.debian-sid
vendored
@ -1,5 +0,0 @@
|
||||
deluge-torrent (0.6.0-svn3235-1) unstable; urgency=low
|
||||
|
||||
* Daily Build
|
||||
|
||||
-- Andrew Resch (andar) <andrewresch@gmail.com> Tue, 17 Jun 2008 16:31:14 -0800
|
5
debian/changelog.ubuntu-gutsy
vendored
5
debian/changelog.ubuntu-gutsy
vendored
@ -1,5 +0,0 @@
|
||||
deluge-torrent (0.6.0-svn3235-1) gutsy; urgency=low
|
||||
|
||||
* Daily Build
|
||||
|
||||
-- Andrew Resch (andar) <andrewresch@gmail.com> Tue, 17 Jun 2008 16:31:14 -0800
|
5
debian/changelog.ubuntu-hardy
vendored
5
debian/changelog.ubuntu-hardy
vendored
@ -1,5 +0,0 @@
|
||||
deluge-torrent (0.6.0-svn3235-1) hardy; urgency=low
|
||||
|
||||
* Daily Build
|
||||
|
||||
-- Andrew Resch (andar) <andrewresch@gmail.com> Tue, 17 Jun 2008 16:31:14 -0800
|
1
debian/compat
vendored
1
debian/compat
vendored
@ -1 +0,0 @@
|
||||
5
|
21
debian/control
vendored
21
debian/control
vendored
@ -1,21 +0,0 @@
|
||||
Source: deluge-torrent
|
||||
Section: net
|
||||
Priority: optional
|
||||
Maintainer: Andrew Resch (andar) <andrewresch@gmail.com>
|
||||
Build-Depends: debhelper (>= 5.0.37.2), python-all-dev (>= 2.3.5-11), python-all, python-support (>= 0.5.3), libboost-dev (>= 1.34.1), libboost-thread-dev (>= 1.34.1), libboost-date-time-dev (>= 1.34.1), libboost-filesystem-dev (>= 1.34.1), libboost-python-dev (>= 1.34.1), libboost-iostreams-dev (>= 1.34.1), zlib1g-dev, libssl-dev, dpatch, python-setuptools
|
||||
Standards-Version: 3.7.2
|
||||
|
||||
Package: deluge-torrent
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}, ${python:Depends}, python-gtk2, python-glade2, python-xdg, python-notify, notification-daemon | notification-daemon-xfce, python-dbus, librsvg2-common, python-pyopenssl, python-setuptools, python-pkg-resources
|
||||
Conflicts: deluge-torrent-common
|
||||
Replaces: deluge-torrent-common
|
||||
Description: A Bittorrent client written in Python/PyGTK
|
||||
Deluge is a Bittorrent client, created using Python and GTK+.
|
||||
.
|
||||
Deluge is intended to bring a native, full-featured client to Linux GTK
|
||||
desktop environments such as Gnome and XFCE.
|
||||
.
|
||||
It uses Rasterbar's version of libtorrent.
|
||||
.
|
||||
Homepage: http://www.deluge-torrent.org/
|
19
debian/control.debian-lenny
vendored
19
debian/control.debian-lenny
vendored
@ -1,19 +0,0 @@
|
||||
Source: deluge-torrent
|
||||
Section: net
|
||||
Priority: optional
|
||||
Maintainer: Andrew Resch (andar) <andrewresch@gmail.com>
|
||||
Build-Depends: debhelper (>= 5.0.37.2), python-all-dev (>= 2.3.5-11), python-all, python-support (>= 0.5.3), libboost-dev (>= 1.33.1), libboost-thread-dev (>= 1.33.1), libboost-date-time-dev (>= 1.33.1), libboost-filesystem-dev (>= 1.33.1), libboost-serialization-dev (>= 1.33.1), libboost-program-options-dev (>= 1.33.1), libboost-regex-dev (>= 1.33.1), libboost-python-dev (>= 1.33.1), zlib1g-dev, libssl-dev, dpatch, python-setuptools
|
||||
Standards-Version: 3.7.2
|
||||
|
||||
Package: deluge-torrent
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}, ${python:Depends}, python-gtk2, python-glade2, python-xdg, python-notify, notification-daemon | notification-daemon-xfce, python-dbus, librsvg2-common, python-pyopenssl, python-setuptools
|
||||
Description: A Bittorrent client written in Python/PyGTK
|
||||
Deluge is a Bittorrent client, created using Python and GTK+.
|
||||
.
|
||||
Deluge is intended to bring a native, full-featured client to Linux GTK
|
||||
desktop environments such as Gnome and XFCE.
|
||||
.
|
||||
It uses Rasterbar's version of libtorrent.
|
||||
.
|
||||
Homepage: http://www.deluge-torrent.org/
|
19
debian/control.debian-sid
vendored
19
debian/control.debian-sid
vendored
@ -1,19 +0,0 @@
|
||||
Source: deluge-torrent
|
||||
Section: net
|
||||
Priority: optional
|
||||
Maintainer: Andrew Resch (andar) <andrewresch@gmail.com>
|
||||
Build-Depends: debhelper (>= 5.0.37.2), python-all-dev (>= 2.3.5-11), python-all, python-support (>= 0.5.3), libboost1.36-dev (>= 1.36), libboost-thread1.36-dev (>= 1.36), libboost-date-time1.36-dev (>= 1.36), libboost-filesystem1.36-dev (>= 1.36), libboost-serialization1.36-dev (>= 1.36), libboost-program-options1.36-dev (>= 1.36), libboost-regex1.36-dev (>= 1.36), libboost-python1.36-dev (>= 1.36), zlib1g-dev, libssl-dev, dpatch, python-setuptools
|
||||
Standards-Version: 3.7.2
|
||||
|
||||
Package: deluge-torrent
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}, ${python:Depends}, python-gtk2, python-glade2, python-xdg, python-notify, notification-daemon | notification-daemon-xfce, python-dbus, librsvg2-common, python-pyopenssl, python-setuptools
|
||||
Description: A Bittorrent client written in Python/PyGTK
|
||||
Deluge is a Bittorrent client, created using Python and GTK+.
|
||||
.
|
||||
Deluge is intended to bring a native, full-featured client to Linux GTK
|
||||
desktop environments such as Gnome and XFCE.
|
||||
.
|
||||
It uses Rasterbar's version of libtorrent.
|
||||
.
|
||||
Homepage: http://www.deluge-torrent.org/
|
99
debian/copyright
vendored
99
debian/copyright
vendored
@ -1,99 +0,0 @@
|
||||
This package was debianized by Marcos Pinto (markybob) <markybob@gmail.com> on
|
||||
Fri, 31 Jul 2008 22:03:13 +0100.
|
||||
|
||||
It was downloaded from http://www.deluge-torrent.org/
|
||||
|
||||
Upstream Authors & Copyright:
|
||||
Andrew Resch
|
||||
Marcos Pinto
|
||||
Sadrul Habib Chowdhury
|
||||
Martijn Voncken
|
||||
|
||||
License:
|
||||
|
||||
This package is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This package is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this package; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, 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
|
||||
library.
|
||||
You must obey the GNU General Public License in all respects for all of
|
||||
the code used other than OpenSSL. If you modify file(s) with this
|
||||
exception, you may extend this exception to your version of the file(s),
|
||||
but you are not obligated to do so. If you do not wish to do so, delete
|
||||
this exception statement from your version. If you delete this exception
|
||||
statement from all source files in the program, then also delete it here.
|
||||
|
||||
On Debian systems, the complete text of the GNU General
|
||||
Public License can be found in `/usr/share/common-licenses/GPL'.
|
||||
|
||||
libtorrent is (C) 2003-2008 Arvid Norberg arvid@cs.umu.se and its
|
||||
python bindings were initially written by Daniel Wallin in 2006.
|
||||
It is distributed unders terms of the BSD License below:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the author nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
"libtorrent/include/libtorrent/asio*" are (C) 2003-2008 Christopher
|
||||
M. Kohlhoff <chris@kohlhoff.com> and distributed under terms of the Boost
|
||||
Software License, Version 1.0 :
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
"deluge/i18n/*" are (C) 2006 Rosetta Contributors and Canonical Ltd 2006 and distributed
|
||||
under the same license as the deluge software.
|
||||
|
||||
The Debian packaging is (C) 2006-2008, Marcos Pinto (markybob)
|
||||
<markybob@gmail.com> and is licensed under GPL3, see above.
|
2
debian/manpages
vendored
2
debian/manpages
vendored
@ -1,2 +0,0 @@
|
||||
docs/man/deluge.1
|
||||
docs/man/deluged.1
|
3
debian/menu
vendored
3
debian/menu
vendored
@ -1,3 +0,0 @@
|
||||
?package(deluge-torrent): needs="X11" section="Applications/Network/File Transfer" \
|
||||
title="Deluge BitTorrent Client" longtitle="Bittorrent client written in Python/PyGTK" \
|
||||
command="/usr/bin/deluge" icon="/usr/share/pixmaps/deluge.png"
|
0
debian/patches/00list
vendored
0
debian/patches/00list
vendored
1
debian/pyversions
vendored
1
debian/pyversions
vendored
@ -1 +0,0 @@
|
||||
2.5
|
1
debian/pyversions.ubuntu-gutsy
vendored
1
debian/pyversions.ubuntu-gutsy
vendored
@ -1 +0,0 @@
|
||||
2.5
|
1
debian/pyversions.ubuntu-hardy
vendored
1
debian/pyversions.ubuntu-hardy
vendored
@ -1 +0,0 @@
|
||||
2.5
|
75
debian/rules
vendored
75
debian/rules
vendored
@ -1,75 +0,0 @@
|
||||
#!/usr/bin/make -f
|
||||
|
||||
# Uncomment this to turn on verbose mode.
|
||||
#export DH_VERBOSE=1
|
||||
|
||||
# Dpatch targets
|
||||
include /usr/share/dpatch/dpatch.make
|
||||
|
||||
# Available python (using debian/pyversions) and destdir
|
||||
PYVERS = 2.5
|
||||
DESTDIR = $(CURDIR)/debian/deluge-torrent
|
||||
|
||||
# We need to known the target arch to enable/disable amd64 hack
|
||||
ARCH = $(shell dpkg-architecture -qDEB_BUILD_ARCH_CPU)
|
||||
ARCH64 = ia64 amd64 alpha kfreebsd-amd64 ppc64
|
||||
|
||||
CFLAGS = -Wall -g
|
||||
ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
|
||||
CFLAGS += -O0
|
||||
else
|
||||
CFLAGS += -O2
|
||||
endif
|
||||
# python-libtorrent need to define AMD64 to work fine on a 64 bits system
|
||||
ifneq (,$(findstring $(ARCH),$(ARCH64)))
|
||||
CFLAGS += -DAMD64
|
||||
endif
|
||||
|
||||
build: patch-stamp $(PYVERS:%=build-stamp%)
|
||||
build-stamp%: patch-stamp
|
||||
dh_testdir
|
||||
CFLAGS="$(CFLAGS)" python$* setup.py build
|
||||
touch $@
|
||||
|
||||
clean: unpatch
|
||||
dh_testdir
|
||||
dh_testroot
|
||||
rm -rf build/
|
||||
find . -name \*.pyc | xargs rm -f
|
||||
rm -rf build-stamp*
|
||||
dh_clean
|
||||
|
||||
install: build install-prereq $(PYVERS:%=install-%) install-finish
|
||||
install-prereq:
|
||||
dh_testdir
|
||||
dh_testroot
|
||||
dh_clean -k
|
||||
dh_installdirs
|
||||
install-%:
|
||||
python$* setup.py install --root=$(DESTDIR) --prefix=/usr --no-compile
|
||||
install-finish:
|
||||
# Desktop menu
|
||||
rm -rf $(DESTDIR)/usr/share/applications
|
||||
install -D -m644 $(CURDIR)/deluge/data/share/applications/deluge.desktop $(DESTDIR)/usr/share/applications/deluge.desktop
|
||||
|
||||
|
||||
binary-indep: build install
|
||||
binary-arch: build install
|
||||
dh_testdir
|
||||
dh_testroot
|
||||
dh_installchangelogs
|
||||
dh_installdocs
|
||||
dh_installmenu
|
||||
dh_strip
|
||||
dh_compress
|
||||
dh_fixperms
|
||||
dh_pysupport
|
||||
dh_desktop
|
||||
dh_installdeb
|
||||
dh_shlibdeps
|
||||
dh_gencontrol
|
||||
dh_md5sums
|
||||
dh_builddeb
|
||||
|
||||
binary: binary-indep binary-arch
|
||||
.PHONY: build clean binary-indep binary-arch binary install
|
@ -45,7 +45,7 @@ supports.
|
||||
|
||||
"""
|
||||
|
||||
REQUIRED_VERSION = "0.14.5.0"
|
||||
REQUIRED_VERSION = "0.14.9.0"
|
||||
|
||||
def check_version(LT):
|
||||
from deluge.common import VersionSplit
|
||||
@ -57,4 +57,4 @@ try:
|
||||
check_version(lt)
|
||||
except ImportError:
|
||||
import libtorrent as lt
|
||||
check_version(lt)
|
||||
check_version(lt)
|
||||
|
@ -210,7 +210,7 @@ def open_url_in_browser(url):
|
||||
|
||||
:param url: the url to open
|
||||
:type url: string
|
||||
|
||||
|
||||
"""
|
||||
import webbrowser
|
||||
webbrowser.open(url)
|
||||
@ -469,13 +469,13 @@ def free_space(path):
|
||||
:type path: string
|
||||
:returns: the free space at path in bytes
|
||||
:rtype: int
|
||||
|
||||
|
||||
:raises InvalidPathError: if the path is not valid
|
||||
|
||||
"""
|
||||
if 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))
|
||||
@ -514,19 +514,19 @@ def is_ip(ip):
|
||||
return True
|
||||
except socket.error:
|
||||
return False
|
||||
|
||||
|
||||
class VersionSplit(object):
|
||||
"""
|
||||
Used for comparing version numbers.
|
||||
|
||||
|
||||
:param ver: the version
|
||||
:type ver: string
|
||||
|
||||
|
||||
"""
|
||||
def __init__(self, ver):
|
||||
ver = ver.lower()
|
||||
vs = ver.split("_") if "_" in ver else ver.split("-")
|
||||
self.version = vs[0]
|
||||
self.version = [int(x) for x in vs[0].split(".")]
|
||||
self.suffix = None
|
||||
if len(vs) > 1:
|
||||
for s in ("rc", "alpha", "beta", "dev"):
|
||||
@ -536,12 +536,12 @@ class VersionSplit(object):
|
||||
def __cmp__(self, ver):
|
||||
"""
|
||||
The comparison method.
|
||||
|
||||
|
||||
:param ver: the version to compare with
|
||||
:type ver: VersionSplit
|
||||
|
||||
|
||||
"""
|
||||
|
||||
|
||||
if self.version > ver.version or (self.suffix and self.suffix[:3] == "dev"):
|
||||
return 1
|
||||
if self.version < ver.version:
|
||||
|
@ -101,6 +101,13 @@ class ComponentRegistry:
|
||||
if depend != None:
|
||||
self.depend[name] = depend
|
||||
|
||||
def deregister(self, name):
|
||||
"""Deregisters a component"""
|
||||
if name in self.components:
|
||||
log.debug("Deregistering Component: %s", name)
|
||||
self.stop_component(name)
|
||||
del self.components[name]
|
||||
|
||||
def get(self, name):
|
||||
"""Returns a reference to the component 'name'"""
|
||||
return self.components[name]
|
||||
@ -126,8 +133,14 @@ class ComponentRegistry:
|
||||
|
||||
def stop(self):
|
||||
"""Stops all components"""
|
||||
for component in self.components.keys():
|
||||
self.stop_component(component)
|
||||
# We create a separate list of the keys and do an additional check to
|
||||
# make sure the key still exists in the components dict.
|
||||
# This is because components could be deregistered during a stop and
|
||||
# the dictionary would get modified while iterating through it.
|
||||
components = self.components.keys()
|
||||
for component in components:
|
||||
if component in self.components:
|
||||
self.stop_component(component)
|
||||
|
||||
def stop_component(self, component):
|
||||
if self.components[component].get_state() != \
|
||||
@ -187,6 +200,10 @@ def register(name, obj, depend=None):
|
||||
"""Registers a component with the registry"""
|
||||
_ComponentRegistry.register(name, obj, depend)
|
||||
|
||||
def deregister(name):
|
||||
"""Deregisters a component"""
|
||||
_ComponentRegistry.deregister(name)
|
||||
|
||||
def start(component=None):
|
||||
"""Starts all components"""
|
||||
if component == None:
|
||||
|
@ -156,6 +156,9 @@ class Config(object):
|
||||
|
||||
self.load()
|
||||
|
||||
def __contains__(self, item):
|
||||
return item in self.__config
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
"""
|
||||
See
|
||||
|
@ -124,6 +124,7 @@ class AuthManager(component.Component):
|
||||
if line.startswith("#"):
|
||||
# This is a comment line
|
||||
continue
|
||||
line = line.strip()
|
||||
try:
|
||||
lsplit = line.split(":")
|
||||
except Exception, e:
|
||||
|
@ -75,7 +75,11 @@ class AutoAdd(component.Component):
|
||||
|
||||
for filename in os.listdir(self.config["autoadd_location"]):
|
||||
if filename.split(".")[-1] == "torrent":
|
||||
filepath = os.path.join(self.config["autoadd_location"], filename)
|
||||
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:
|
||||
filedump = self.load_torrent(filepath)
|
||||
except (RuntimeError, Exception), e:
|
||||
|
@ -655,14 +655,21 @@ class Core(component.Component):
|
||||
self.add_torrent_file(os.path.split(target)[1], open(target, "rb").read(), options)
|
||||
|
||||
@export
|
||||
def upload_plugin(self, filename, plugin_data):
|
||||
def upload_plugin(self, filename, filedump):
|
||||
"""This method is used to upload new plugins to the daemon. It is used
|
||||
when connecting to the daemon remotely and installing a new plugin on
|
||||
the client side. 'plugin_data' is a xmlrpc.Binary object of the file data,
|
||||
ie, plugin_file.read()"""
|
||||
|
||||
try:
|
||||
filedump = base64.decodestring(filedump)
|
||||
except Exception, e:
|
||||
log.error("There was an error decoding the filedump string!")
|
||||
log.exception(e)
|
||||
return
|
||||
|
||||
f = open(os.path.join(deluge.configmanager.get_config_dir(), "plugins", filename), "wb")
|
||||
f.write(plugin_data.data)
|
||||
f.write(filedump)
|
||||
f.close()
|
||||
component.get("CorePluginManager").scan_for_plugins()
|
||||
|
||||
|
@ -105,6 +105,8 @@ class Daemon(object):
|
||||
gettext.install("deluge", pkg_resources.resource_filename("deluge", "i18n"))
|
||||
except Exception, e:
|
||||
log.error("Unable to initialize gettext/locale: %s", e)
|
||||
import __builtin__
|
||||
__builtin__.__dict__["_"] = lambda x: x
|
||||
|
||||
# Twisted catches signals to terminate, so just have it call the shutdown
|
||||
# method.
|
||||
|
@ -84,7 +84,7 @@ def tracker_error_filter(torrent_ids, values):
|
||||
# If this is a tracker_host, then we need to filter on it
|
||||
if values[0] != "Error":
|
||||
for torrent_id in torrent_ids:
|
||||
if values[0] in tm[torrent_id].get_status(["tracker_host"])["tracker_host"]:
|
||||
if values[0] == tm[torrent_id].get_status(["tracker_host"])["tracker_host"]:
|
||||
filtered_torrent_ids.append(torrent_id)
|
||||
return filtered_torrent_ids
|
||||
|
||||
|
@ -97,7 +97,7 @@ class OldStateUpgrader:
|
||||
torrent_info = lt.torrent_info(lt.bdecode(_file.read()))
|
||||
_file.close()
|
||||
except (IOError, RuntimeError), e:
|
||||
log.warning("Unable to open %s: %s", filepath, e)
|
||||
log.warning("Unable to open %s: %s", torrent_path, e)
|
||||
|
||||
# Copy the torrent file to the new location
|
||||
import shutil
|
||||
|
@ -131,7 +131,7 @@ class DelugeRPCProtocol(Protocol):
|
||||
try:
|
||||
request = rencode.loads(dobj.decompress(data))
|
||||
except Exception, e:
|
||||
log.debug("Received possible invalid message (%r): %s", data, e)
|
||||
#log.debug("Received possible invalid message (%r): %s", data, e)
|
||||
# This could be cut-off data, so we'll save this in the buffer
|
||||
# and try to prepend it on the next dataReceived()
|
||||
self.__buffer = data
|
||||
|
@ -113,9 +113,6 @@ class Torrent:
|
||||
except RuntimeError:
|
||||
self.torrent_info = None
|
||||
|
||||
# Files dictionary
|
||||
self.files = self.get_files()
|
||||
|
||||
# Default total_uploaded to 0, this may be changed by the state
|
||||
self.total_uploaded = 0
|
||||
|
||||
@ -254,7 +251,7 @@ class Torrent:
|
||||
self.options["move_completed_path"] = move_completed_path
|
||||
|
||||
def set_file_priorities(self, file_priorities):
|
||||
if len(file_priorities) != len(self.files):
|
||||
if len(file_priorities) != len(self.get_files()):
|
||||
log.debug("file_priorities len != num_files")
|
||||
self.options["file_priorities"] = self.handle.file_priorities()
|
||||
return
|
||||
@ -302,14 +299,11 @@ class Torrent:
|
||||
log.debug("Setting trackers for %s: %s", self.torrent_id, trackers)
|
||||
tracker_list = []
|
||||
|
||||
if lt.version_minor < 15:
|
||||
for tracker in trackers:
|
||||
new_entry = lt.announce_entry(tracker["url"])
|
||||
new_entry.tier = tracker["tier"]
|
||||
tracker_list.append(new_entry)
|
||||
self.handle.replace_trackers(tracker_list)
|
||||
else:
|
||||
self.handle.replace_trackers(trackers)
|
||||
for tracker in trackers:
|
||||
new_entry = lt.announce_entry(tracker["url"])
|
||||
new_entry.tier = tracker["tier"]
|
||||
tracker_list.append(new_entry)
|
||||
self.handle.replace_trackers(tracker_list)
|
||||
|
||||
# Print out the trackers
|
||||
#for t in self.handle.trackers():
|
||||
@ -337,6 +331,10 @@ class Torrent:
|
||||
LTSTATE = deluge.common.LT_TORRENT_STATE
|
||||
ltstate = int(self.handle.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)
|
||||
|
||||
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())
|
||||
|
||||
@ -414,9 +412,7 @@ class Torrent:
|
||||
else:
|
||||
status = self.status
|
||||
|
||||
if status.all_time_download > 0:
|
||||
downloaded = status.all_time_download
|
||||
elif status.total_done > 0:
|
||||
if status.total_done > 0:
|
||||
# We use 'total_done' if the downloaded value is 0
|
||||
downloaded = status.total_done
|
||||
else:
|
||||
@ -491,7 +487,7 @@ class Torrent:
|
||||
|
||||
file_progress = self.handle.file_progress()
|
||||
ret = []
|
||||
for i,f in enumerate(self.files):
|
||||
for i,f in enumerate(self.get_files()):
|
||||
try:
|
||||
ret.append(float(file_progress[i]) / float(f["size"]))
|
||||
except ZeroDivisionError:
|
||||
@ -559,7 +555,6 @@ class Torrent:
|
||||
"distributed_copies": distributed_copies,
|
||||
"download_payload_rate": self.status.download_payload_rate,
|
||||
"file_priorities": self.options["file_priorities"],
|
||||
"files": self.files,
|
||||
"hash": self.torrent_id,
|
||||
"is_auto_managed": self.options["auto_managed"],
|
||||
"is_finished": self.is_finished,
|
||||
@ -608,6 +603,8 @@ class Torrent:
|
||||
def ti_name():
|
||||
if self.handle.has_metadata():
|
||||
name = self.torrent_info.file_at(0).path.split("/", 1)[0]
|
||||
if not name:
|
||||
name = self.torrent_info.name()
|
||||
try:
|
||||
return name.decode("utf8", "ignore")
|
||||
except UnicodeDecodeError:
|
||||
@ -639,6 +636,7 @@ class Torrent:
|
||||
"comment": ti_comment,
|
||||
"eta": self.get_eta,
|
||||
"file_progress": self.get_file_progress,
|
||||
"files": self.get_files,
|
||||
"is_seed": self.handle.is_seed,
|
||||
"name": ti_name,
|
||||
"num_files": ti_num_files,
|
||||
@ -742,6 +740,9 @@ class Torrent:
|
||||
|
||||
def move_storage(self, dest):
|
||||
"""Move a torrent's storage location"""
|
||||
if not os.path.exists(dest):
|
||||
log.error("Could not move storage for torrent %s since %s does not exist!", self.torrent_id, dest)
|
||||
return False
|
||||
try:
|
||||
self.handle.move_storage(dest.encode("utf8"))
|
||||
except:
|
||||
@ -762,9 +763,10 @@ class Torrent:
|
||||
self.torrent_id)
|
||||
log.debug("Writing torrent file: %s", path)
|
||||
try:
|
||||
ti = self.handle.get_torrent_info()
|
||||
md = lt.bdecode(ti.metadata())
|
||||
log.debug("md: %s", md)
|
||||
self.torrent_info = self.handle.get_torrent_info()
|
||||
# Regenerate the file priorities
|
||||
self.set_file_priorities([])
|
||||
md = lt.bdecode(self.torrent_info.metadata())
|
||||
torrent_file = {}
|
||||
torrent_file["info"] = md
|
||||
open(path, "wb").write(lt.bencode(torrent_file))
|
||||
@ -816,7 +818,7 @@ class Torrent:
|
||||
"""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)
|
||||
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
|
||||
@ -834,5 +836,5 @@ class Torrent:
|
||||
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))
|
||||
self.handle.rename_file(f["index"], f["path"].replace(folder, new_folder, 1).encode("utf-8"))
|
||||
self.waiting_on_folder_rename.append(wait_on_folder)
|
||||
|
@ -132,6 +132,10 @@ class TorrentManager(component.Component):
|
||||
# Get the core config
|
||||
self.config = ConfigManager("core.conf")
|
||||
|
||||
# Make sure the state folder has been created
|
||||
if not os.path.exists(os.path.join(get_config_dir(), "state")):
|
||||
os.makedirs(os.path.join(get_config_dir(), "state"))
|
||||
|
||||
# Create the torrents dict { torrent_id: Torrent }
|
||||
self.torrents = {}
|
||||
|
||||
@ -142,7 +146,7 @@ class TorrentManager(component.Component):
|
||||
|
||||
# self.num_resume_data used to save resume_data in bulk
|
||||
self.num_resume_data = 0
|
||||
|
||||
|
||||
# Keeps track of resume data that needs to be saved to disk
|
||||
self.resume_data = {}
|
||||
|
||||
@ -200,20 +204,23 @@ class TorrentManager(component.Component):
|
||||
|
||||
# Save the state every 5 minutes
|
||||
self.save_state_timer = LoopingCall(self.save_state)
|
||||
self.save_state_timer.start(200)
|
||||
self.save_state_timer.start(200, False)
|
||||
self.save_resume_data_timer = LoopingCall(self.save_resume_data)
|
||||
self.save_resume_data_timer.start(190)
|
||||
|
||||
def stop(self):
|
||||
# Stop timers
|
||||
self.save_state_timer.stop()
|
||||
self.save_resume_data_timer.stop()
|
||||
if self.save_state_timer.running:
|
||||
self.save_state_timer.stop()
|
||||
|
||||
if self.save_resume_data_timer.running:
|
||||
self.save_resume_data_timer.stop()
|
||||
|
||||
# Save state on shutdown
|
||||
self.save_state()
|
||||
|
||||
# Make another list just to make sure all paused torrents will be
|
||||
# passed to self.save_resume_data(). With
|
||||
# Make another list just to make sure all paused torrents will be
|
||||
# passed to self.save_resume_data(). With
|
||||
# self.shutdown_torrent_pause_list it is possible to have a case when
|
||||
# torrent_id is removed from it in self.on_alert_torrent_paused()
|
||||
# before we call self.save_resume_data() here.
|
||||
@ -225,9 +232,9 @@ class TorrentManager(component.Component):
|
||||
self.torrents[key].handle.pause()
|
||||
self.shutdown_torrent_pause_list.append(key)
|
||||
save_resume_data_list.append(key)
|
||||
|
||||
|
||||
self.save_resume_data(save_resume_data_list)
|
||||
|
||||
|
||||
# We have to wait for all torrents to pause and write their resume data
|
||||
wait = True
|
||||
while wait:
|
||||
@ -246,7 +253,11 @@ 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"):
|
||||
if self.config["stop_seed_at_ratio"] or 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"]:
|
||||
continue
|
||||
stop_ratio = self.config["stop_seed_ratio"]
|
||||
if torrent.options["stop_at_ratio"]:
|
||||
stop_ratio = torrent.options["stop_ratio"]
|
||||
@ -294,7 +305,7 @@ class TorrentManager(component.Component):
|
||||
|
||||
def legacy_delete_resume_data(self, torrent_id):
|
||||
"""Deletes the .fastresume file"""
|
||||
path = os.path.join(self.config["state_location"],
|
||||
path = os.path.join(get_config_dir(), "state",
|
||||
torrent_id + ".fastresume")
|
||||
log.debug("Deleting fastresume file: %s", path)
|
||||
try:
|
||||
@ -343,24 +354,23 @@ class TorrentManager(component.Component):
|
||||
options["move_completed_path"] = state.move_completed_path
|
||||
options["add_paused"] = state.paused
|
||||
|
||||
if not state.magnet:
|
||||
add_torrent_params["ti"] =\
|
||||
self.get_torrent_info_from_file(
|
||||
os.path.join(get_config_dir(),
|
||||
"state", state.torrent_id + ".torrent"))
|
||||
|
||||
if not add_torrent_params["ti"]:
|
||||
log.error("Unable to add torrent!")
|
||||
return
|
||||
else:
|
||||
ti = self.get_torrent_info_from_file(
|
||||
os.path.join(get_config_dir(),
|
||||
"state", state.torrent_id + ".torrent"))
|
||||
if ti:
|
||||
add_torrent_params["ti"] = ti
|
||||
elif state.magnet:
|
||||
magnet = state.magnet
|
||||
else:
|
||||
log.error("Unable to add torrent!")
|
||||
return
|
||||
|
||||
# Handle legacy case with storing resume data in individual files
|
||||
# for each torrent
|
||||
if resume_data is None:
|
||||
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
|
||||
else:
|
||||
# We have a torrent_info object so we're not loading from state.
|
||||
@ -377,7 +387,7 @@ class TorrentManager(component.Component):
|
||||
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, name)
|
||||
torrent_info.rename_file(index, name.encode("utf-8"))
|
||||
|
||||
add_torrent_params["ti"] = torrent_info
|
||||
add_torrent_params["resume_data"] = ""
|
||||
@ -517,7 +527,7 @@ class TorrentManager(component.Component):
|
||||
except (RuntimeError, KeyError), e:
|
||||
log.warning("Error removing torrent: %s", e)
|
||||
return False
|
||||
|
||||
|
||||
# Remove fastresume data if it is exists
|
||||
resume_data = self.load_resume_data_file()
|
||||
resume_data.pop(torrent_id, None)
|
||||
@ -618,7 +628,7 @@ class TorrentManager(component.Component):
|
||||
# Pickle the TorrentManagerState object
|
||||
try:
|
||||
log.debug("Saving torrent state file.")
|
||||
state_file = open(os.path.join(get_config_dir(),
|
||||
state_file = open(os.path.join(get_config_dir(),
|
||||
"state", "torrents.state.new"), "wb")
|
||||
cPickle.dump(state, state_file)
|
||||
state_file.flush()
|
||||
@ -645,13 +655,13 @@ class TorrentManager(component.Component):
|
||||
Saves resume data for list of torrent_ids or for all torrents if
|
||||
torrent_ids is None
|
||||
"""
|
||||
|
||||
|
||||
if torrent_ids is None:
|
||||
torrent_ids = self.torrents.keys()
|
||||
|
||||
|
||||
for torrent_id in torrent_ids:
|
||||
self.torrents[torrent_id].save_resume_data()
|
||||
|
||||
|
||||
self.num_resume_data = len(torrent_ids)
|
||||
|
||||
def load_resume_data_file(self):
|
||||
@ -664,35 +674,35 @@ class TorrentManager(component.Component):
|
||||
fastresume_file.close()
|
||||
except (EOFError, IOError, Exception), e:
|
||||
log.warning("Unable to load fastresume file: %s", e)
|
||||
|
||||
|
||||
# If the libtorrent bdecode doesn't happen properly, it will return None
|
||||
# so we need to make sure we return a {}
|
||||
if resume_data is None:
|
||||
return {}
|
||||
|
||||
|
||||
return resume_data
|
||||
|
||||
|
||||
def save_resume_data_file(self, resume_data=None):
|
||||
"""
|
||||
Saves the resume data file with the contents of self.resume_data. If
|
||||
`resume_data` is None, then we grab the resume_data from the file on
|
||||
disk, else, we update `resume_data` with self.resume_data and save
|
||||
that to disk.
|
||||
|
||||
|
||||
:param resume_data: the current resume_data, this will be loaded from disk if not provided
|
||||
:type resume_data: dict
|
||||
|
||||
|
||||
"""
|
||||
# Check to see if we're waiting on more resume data
|
||||
if self.num_resume_data or not self.resume_data:
|
||||
return
|
||||
|
||||
|
||||
path = os.path.join(get_config_dir(), "state", "torrents.fastresume")
|
||||
|
||||
|
||||
# First step is to load the existing file and update the dictionary
|
||||
if resume_data is None:
|
||||
resume_data = self.load_resume_data_file()
|
||||
|
||||
|
||||
resume_data.update(self.resume_data)
|
||||
self.resume_data = {}
|
||||
|
||||
@ -775,20 +785,19 @@ class TorrentManager(component.Component):
|
||||
total_download = torrent.get_status(["total_payload_download"])["total_payload_download"]
|
||||
|
||||
# Move completed download to completed folder if needed
|
||||
if not torrent.is_finished:
|
||||
if not torrent.is_finished and total_download:
|
||||
move_path = None
|
||||
|
||||
if torrent.options["move_completed"] and total_download:
|
||||
if torrent.options["move_completed"]:
|
||||
move_path = torrent.options["move_completed_path"]
|
||||
if torrent.options["download_location"] != move_path and \
|
||||
torrent.options["download_location"] == self.config["download_location"]:
|
||||
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()
|
||||
|
||||
|
||||
# Only save resume data if it was actually downloaded something. Helps
|
||||
# on startup with big queues with lots of seeding torrents. Libtorrent
|
||||
# emits alert_torrent_finished for them, but there seems like nothing
|
||||
@ -914,9 +923,9 @@ class TorrentManager(component.Component):
|
||||
|
||||
def on_alert_save_resume_data(self, alert):
|
||||
log.debug("on_alert_save_resume_data")
|
||||
|
||||
|
||||
torrent_id = str(alert.handle.info_hash())
|
||||
|
||||
|
||||
try:
|
||||
torrent = self.torrents[torrent_id]
|
||||
except:
|
||||
@ -925,9 +934,9 @@ class TorrentManager(component.Component):
|
||||
# Libtorrent in add_torrent() expects resume_data to be bencoded
|
||||
self.resume_data[torrent_id] = lt.bencode(alert.resume_data)
|
||||
self.num_resume_data -= 1
|
||||
|
||||
|
||||
torrent.waiting_on_resume_data = False
|
||||
|
||||
|
||||
self.save_resume_data_file()
|
||||
|
||||
def on_alert_save_resume_data_failed(self, alert):
|
||||
@ -936,12 +945,12 @@ class TorrentManager(component.Component):
|
||||
torrent = self.torrents[str(alert.handle.info_hash())]
|
||||
except:
|
||||
return
|
||||
|
||||
|
||||
self.num_resume_data -= 1
|
||||
torrent.waiting_on_resume_data = False
|
||||
|
||||
|
||||
self.save_resume_data_file()
|
||||
|
||||
|
||||
|
||||
def on_alert_file_renamed(self, alert):
|
||||
log.debug("on_alert_file_renamed")
|
||||
@ -951,7 +960,6 @@ class TorrentManager(component.Component):
|
||||
except:
|
||||
return
|
||||
torrent_id = str(alert.handle.info_hash())
|
||||
torrent.files[alert.index]["path"] = alert.name
|
||||
|
||||
# We need to see if this file index is in a waiting_on_folder list
|
||||
folder_rename = False
|
||||
|
BIN
deluge/data/pixmaps/lock48.png
Normal file
BIN
deluge/data/pixmaps/lock48.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.9 KiB |
BIN
deluge/data/pixmaps/magnet.png
Normal file
BIN
deluge/data/pixmaps/magnet.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 906 B |
@ -3,7 +3,7 @@ Version=1.0
|
||||
Name=Deluge BitTorrent Client
|
||||
GenericName=Bittorrent Client
|
||||
Comment=Transfer files using the Bittorrent protocol
|
||||
Exec=deluge
|
||||
Exec=deluge-gtk
|
||||
Icon=deluge
|
||||
Terminal=false
|
||||
Type=Application
|
||||
|
@ -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,6 +41,17 @@ and subsequently emitted to the clients.
|
||||
|
||||
"""
|
||||
|
||||
known_events = {}
|
||||
|
||||
class DelugeEventMetaClass(type):
|
||||
"""
|
||||
This metaclass simply keeps a list of all events classes created.
|
||||
"""
|
||||
def __init__(cls, name, bases, dct):
|
||||
super(DelugeEventMetaClass, cls).__init__(name, bases, dct)
|
||||
if name != "DelugeEvent":
|
||||
known_events[name] = cls
|
||||
|
||||
class DelugeEvent(object):
|
||||
"""
|
||||
The base class for all events.
|
||||
@ -49,6 +60,8 @@ class DelugeEvent(object):
|
||||
:prop args: a list of the attribute values
|
||||
|
||||
"""
|
||||
__metaclass__ = DelugeEventMetaClass
|
||||
|
||||
def _get_name(self):
|
||||
return self.__class__.__name__
|
||||
|
||||
|
@ -1,139 +1,161 @@
|
||||
deluge/plugins/label/label/data/label_pref.glade
|
||||
deluge/plugins/label/label/data/label_options.glade
|
||||
deluge/plugins/blocklist/blocklist/data/blocklist_pref.glade
|
||||
deluge/plugins/stats/stats/data/config.glade
|
||||
deluge/plugins/stats/stats/data/tabs.glade
|
||||
deluge/ui/gtkui/glade/add_torrent_dialog.glade
|
||||
deluge/ui/gtkui/glade/filtertree_menu.glade
|
||||
deluge/ui/gtkui/glade/torrent_menu.glade
|
||||
deluge/ui/gtkui/glade/remove_torrent_dialog.glade
|
||||
deluge/ui/gtkui/glade/preferences_dialog.glade
|
||||
deluge/ui/gtkui/glade/edit_trackers.glade
|
||||
deluge/ui/gtkui/glade/queuedtorrents.glade
|
||||
deluge/ui/gtkui/glade/move_storage_dialog.glade
|
||||
deluge/ui/gtkui/glade/connection_manager.glade
|
||||
deluge/ui/gtkui/glade/create_torrent_dialog.glade
|
||||
deluge/ui/gtkui/glade/dgtkpopups.glade
|
||||
deluge/ui/gtkui/glade/tray_menu.glade
|
||||
deluge/ui/gtkui/glade/main_window.glade
|
||||
deluge/error.py
|
||||
deluge/common.py
|
||||
deluge/rencode.py
|
||||
deluge/httpdownloader.py
|
||||
deluge/main.py
|
||||
deluge/configmanager.py
|
||||
deluge/bencode.py
|
||||
docs/source/conf.py
|
||||
deluge/core/autoadd.py
|
||||
deluge/core/preferencesmanager.py
|
||||
deluge/core/filtermanager.py
|
||||
deluge/core/torrentmanager.py
|
||||
deluge/core/daemon.py
|
||||
deluge/core/torrent.py
|
||||
deluge/core/pluginmanager.py
|
||||
deluge/core/oldstateupgrader.py
|
||||
deluge/core/__init__.py
|
||||
deluge/core/core.py
|
||||
deluge/core/alertmanager.py
|
||||
deluge/core/rpcserver.py
|
||||
deluge/config.py
|
||||
deluge/countries.py
|
||||
deluge/metafile.py
|
||||
deluge/__rpcapi.py
|
||||
deluge/pluginmanagerbase.py
|
||||
deluge/plugins/label/label/webui.py
|
||||
deluge/plugins/label/label/test.py
|
||||
deluge/plugins/label/label/gtkui/label_config.py
|
||||
deluge/plugins/label/label/gtkui/sidebar_menu.py
|
||||
deluge/plugins/label/label/gtkui/submenu.py
|
||||
deluge/plugins/label/label/gtkui/__init__.py
|
||||
deluge/plugins/label/label/__init__.py
|
||||
deluge/plugins/label/label/core.py
|
||||
deluge/plugins/label/setup.py
|
||||
deluge/metafile.py
|
||||
deluge/event.py
|
||||
deluge/__init__.py
|
||||
deluge/_libtorrent.py
|
||||
deluge/log.py
|
||||
deluge/component.py
|
||||
deluge/config.py
|
||||
deluge/plugins/pluginbase.py
|
||||
deluge/plugins/init.py
|
||||
deluge/plugins/blocklist/setup.py
|
||||
deluge/plugins/blocklist/blocklist/webui.py
|
||||
deluge/plugins/blocklist/blocklist/gtkui.py
|
||||
deluge/plugins/blocklist/blocklist/text.py
|
||||
deluge/plugins/blocklist/blocklist/peerguardian.py
|
||||
deluge/plugins/blocklist/blocklist/__init__.py
|
||||
deluge/plugins/blocklist/blocklist/core.py
|
||||
deluge/plugins/__init__.py
|
||||
deluge/plugins/webuipluginbase.py
|
||||
deluge/plugins/stats/setup.py
|
||||
deluge/plugins/stats/stats/webui.py
|
||||
deluge/plugins/stats/stats/gtkui.py
|
||||
deluge/plugins/stats/stats/test.py
|
||||
deluge/plugins/stats/stats/graph.py
|
||||
deluge/plugins/stats/stats/test_total.py
|
||||
deluge/plugins/stats/stats/__init__.py
|
||||
deluge/plugins/stats/stats/core.py
|
||||
deluge/configmanager.py
|
||||
deluge/plugins/execute/setup.py
|
||||
deluge/plugins/execute/execute/common.py
|
||||
deluge/plugins/execute/execute/core.py
|
||||
deluge/plugins/execute/execute/gtkui.py
|
||||
deluge/plugins/execute/execute/__init__.py
|
||||
deluge/plugins/execute/execute/webui.py
|
||||
deluge/plugins/execute/execute/data/execute_prefs.glade
|
||||
deluge/plugins/extractor/setup.py
|
||||
deluge/plugins/extractor/extractor/common.py
|
||||
deluge/plugins/extractor/extractor/core.py
|
||||
deluge/plugins/extractor/extractor/gtkui.py
|
||||
deluge/plugins/extractor/extractor/__init__.py
|
||||
deluge/plugins/extractor/extractor/webui.py
|
||||
deluge/plugins/extractor/extractor/data/extractor_prefs.glade
|
||||
deluge/plugins/webui/setup.py
|
||||
deluge/plugins/webui/webui/common.py
|
||||
deluge/plugins/webui/webui/core.py
|
||||
deluge/plugins/webui/webui/gtkui.py
|
||||
deluge/plugins/webui/webui/__init__.py
|
||||
deluge/plugins/webui/webui/data/config.glade
|
||||
deluge/plugins/scheduler/setup.py
|
||||
deluge/plugins/scheduler/scheduler/common.py
|
||||
deluge/plugins/scheduler/scheduler/core.py
|
||||
deluge/plugins/scheduler/scheduler/gtkui.py
|
||||
deluge/plugins/scheduler/scheduler/__init__.py
|
||||
deluge/plugins/scheduler/scheduler/webui.py
|
||||
deluge/plugins/label/setup.py
|
||||
deluge/plugins/label/label/core.py
|
||||
deluge/plugins/label/label/test.py
|
||||
deluge/plugins/label/label/__init__.py
|
||||
deluge/plugins/label/label/webui.py
|
||||
deluge/plugins/label/label/data/label_pref.glade
|
||||
deluge/plugins/label/label/data/label_options.glade
|
||||
deluge/plugins/label/label/gtkui/submenu.py
|
||||
deluge/plugins/label/label/gtkui/sidebar_menu.py
|
||||
deluge/plugins/label/label/gtkui/__init__.py
|
||||
deluge/plugins/label/label/gtkui/label_config.py
|
||||
deluge/plugins/blocklist/setup.py
|
||||
deluge/plugins/blocklist/blocklist/readers.py
|
||||
deluge/plugins/blocklist/blocklist/peerguardian.py
|
||||
deluge/plugins/blocklist/blocklist/common.py
|
||||
deluge/plugins/blocklist/blocklist/detect.py
|
||||
deluge/plugins/blocklist/blocklist/core.py
|
||||
deluge/plugins/blocklist/blocklist/decompressers.py
|
||||
deluge/plugins/blocklist/blocklist/gtkui.py
|
||||
deluge/plugins/blocklist/blocklist/__init__.py
|
||||
deluge/plugins/blocklist/blocklist/webui.py
|
||||
deluge/plugins/blocklist/blocklist/data/blocklist_pref.glade
|
||||
deluge/ui/ui.py
|
||||
deluge/ui/common.py
|
||||
deluge/ui/coreconfig.py
|
||||
deluge/ui/countries.py
|
||||
deluge/ui/tracker_icons.py
|
||||
deluge/ui/client.py
|
||||
deluge/ui/ui.py
|
||||
deluge/ui/coreconfig.py
|
||||
deluge/ui/console/colors.py
|
||||
deluge/ui/console/commands/resume.py
|
||||
deluge/ui/console/commands/config.py
|
||||
deluge/ui/console/commands/halt.py
|
||||
deluge/ui/console/commands/debug.py
|
||||
deluge/ui/console/commands/__init__.py
|
||||
deluge/ui/console/commands/quit.py
|
||||
deluge/ui/console/commands/connect.py
|
||||
deluge/ui/console/commands/pause.py
|
||||
deluge/ui/console/commands/add.py
|
||||
deluge/ui/console/commands/rm.py
|
||||
deluge/ui/console/commands/info.py
|
||||
deluge/ui/console/commands/help.py
|
||||
deluge/ui/console/main.py
|
||||
deluge/ui/console/__init__.py
|
||||
deluge/ui/gtkui/listview.py
|
||||
deluge/ui/gtkui/options_tab.py
|
||||
deluge/ui/gtkui/statusbar.py
|
||||
deluge/ui/gtkui/status_tab.py
|
||||
deluge/ui/gtkui/addtorrentdialog.py
|
||||
deluge/ui/gtkui/sidebar.py
|
||||
deluge/ui/gtkui/gtkui.py
|
||||
deluge/ui/gtkui/aboutdialog.py
|
||||
deluge/ui/gtkui/systemtray.py
|
||||
deluge/ui/gtkui/files_tab.py
|
||||
deluge/ui/gtkui/menubar.py
|
||||
deluge/ui/gtkui/peers_tab.py
|
||||
deluge/ui/gtkui/notification.py
|
||||
deluge/ui/gtkui/toolbar.py
|
||||
deluge/ui/gtkui/ipcinterface.py
|
||||
deluge/ui/gtkui/filtertreeview.py
|
||||
deluge/ui/gtkui/queuedtorrents.py
|
||||
deluge/ui/gtkui/pluginmanager.py
|
||||
deluge/ui/gtkui/mainwindow.py
|
||||
deluge/ui/gtkui/removetorrentdialog.py
|
||||
deluge/ui/gtkui/common.py
|
||||
deluge/ui/gtkui/torrentdetails.py
|
||||
deluge/ui/gtkui/__init__.py
|
||||
deluge/ui/gtkui/edittrackersdialog.py
|
||||
deluge/ui/gtkui/preferences.py
|
||||
deluge/ui/gtkui/torrentview.py
|
||||
deluge/ui/gtkui/new_release_dialog.py
|
||||
deluge/ui/gtkui/connectionmanager.py
|
||||
deluge/ui/gtkui/createtorrentdialog.py
|
||||
deluge/ui/gtkui/details_tab.py
|
||||
deluge/ui/common.py
|
||||
deluge/ui/__init__.py
|
||||
deluge/ui/web/auth.py
|
||||
deluge/ui/web/common.py
|
||||
deluge/ui/gtkui/toolbar.py
|
||||
deluge/ui/gtkui/addtorrentdialog.py
|
||||
deluge/ui/gtkui/removetorrentdialog.py
|
||||
deluge/ui/gtkui/status_tab.py
|
||||
deluge/ui/gtkui/common.py
|
||||
deluge/ui/gtkui/peers_tab.py
|
||||
deluge/ui/gtkui/connectionmanager.py
|
||||
deluge/ui/gtkui/systemtray.py
|
||||
deluge/ui/gtkui/notification.py
|
||||
deluge/ui/gtkui/new_release_dialog.py
|
||||
deluge/ui/gtkui/details_tab.py
|
||||
deluge/ui/gtkui/options_tab.py
|
||||
deluge/ui/gtkui/torrentdetails.py
|
||||
deluge/ui/gtkui/sidebar.py
|
||||
deluge/ui/gtkui/edittrackersdialog.py
|
||||
deluge/ui/gtkui/mainwindow.py
|
||||
deluge/ui/gtkui/dialogs.py
|
||||
deluge/ui/gtkui/aboutdialog.py
|
||||
deluge/ui/gtkui/listview.py
|
||||
deluge/ui/gtkui/createtorrentdialog.py
|
||||
deluge/ui/gtkui/statusbar.py
|
||||
deluge/ui/gtkui/ipcinterface.py
|
||||
deluge/ui/gtkui/gtkui.py
|
||||
deluge/ui/gtkui/torrentview.py
|
||||
deluge/ui/gtkui/queuedtorrents.py
|
||||
deluge/ui/gtkui/filtertreeview.py
|
||||
deluge/ui/gtkui/__init__.py
|
||||
deluge/ui/gtkui/menubar.py
|
||||
deluge/ui/gtkui/files_tab.py
|
||||
deluge/ui/gtkui/preferences.py
|
||||
deluge/ui/gtkui/pluginmanager.py
|
||||
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/torrent_menu.glade
|
||||
deluge/ui/gtkui/glade/edit_trackers.glade
|
||||
deluge/ui/gtkui/glade/filtertree_menu.glade
|
||||
deluge/ui/gtkui/glade/tray_menu.glade
|
||||
deluge/ui/gtkui/glade/dgtkpopups.glade
|
||||
deluge/ui/gtkui/glade/move_storage_dialog.glade
|
||||
deluge/ui/gtkui/glade/connection_manager.glade
|
||||
deluge/ui/gtkui/glade/queuedtorrents.glade
|
||||
deluge/ui/gtkui/glade/add_torrent_dialog.glade
|
||||
deluge/ui/gtkui/glade/preferences_dialog.glade
|
||||
deluge/ui/web/gen_gettext.py
|
||||
deluge/ui/web/web.py
|
||||
deluge/ui/web/common.py
|
||||
deluge/ui/web/auth.py
|
||||
deluge/ui/web/server.py
|
||||
deluge/ui/web/__init__.py
|
||||
deluge/ui/web/json_api.py
|
||||
deluge/ui/web/pluginmanager.py
|
||||
deluge/ui/web/server.py
|
||||
deluge/ui/web/web.py
|
||||
deluge/common.py
|
||||
deluge/component.py
|
||||
deluge/main.py
|
||||
deluge/error.py
|
||||
deluge/__init__.py
|
||||
deluge/tests/test_signalreceiver.py
|
||||
deluge/tests/test_filters.py
|
||||
deluge/tests/test_plugin_metadata.py
|
||||
deluge/tests/test_tracker_icons.py
|
||||
deluge/tests/test_stats.py
|
||||
deluge/tests/test_client.py
|
||||
deluge/log.py
|
||||
deluge/scripts/deluge_remote.py
|
||||
deluge/scripts/wiki_docgen.py
|
||||
deluge/scripts/create_plugin.py
|
||||
deluge/ui/console/eventlog.py
|
||||
deluge/ui/console/main.py
|
||||
deluge/ui/console/statusbars.py
|
||||
deluge/ui/console/colors.py
|
||||
deluge/ui/console/__init__.py
|
||||
deluge/ui/console/screen.py
|
||||
deluge/ui/console/commands/quit.py
|
||||
deluge/ui/console/commands/help.py
|
||||
deluge/ui/console/commands/add.py
|
||||
deluge/ui/console/commands/pause.py
|
||||
deluge/ui/console/commands/resume.py
|
||||
deluge/ui/console/commands/halt.py
|
||||
deluge/ui/console/commands/recheck.py
|
||||
deluge/ui/console/commands/cache.py
|
||||
deluge/ui/console/commands/connect.py
|
||||
deluge/ui/console/commands/plugin.py
|
||||
deluge/ui/console/commands/info.py
|
||||
deluge/ui/console/commands/__init__.py
|
||||
deluge/ui/console/commands/rm.py
|
||||
deluge/ui/console/commands/config.py
|
||||
deluge/ui/console/commands/debug.py
|
||||
deluge/core/torrent.py
|
||||
deluge/core/alertmanager.py
|
||||
deluge/core/filtermanager.py
|
||||
deluge/core/authmanager.py
|
||||
deluge/core/core.py
|
||||
deluge/core/preferencesmanager.py
|
||||
deluge/core/torrentmanager.py
|
||||
deluge/core/oldstateupgrader.py
|
||||
deluge/core/__init__.py
|
||||
deluge/core/rpcserver.py
|
||||
deluge/core/daemon.py
|
||||
deluge/core/eventmanager.py
|
||||
deluge/core/pluginmanager.py
|
||||
deluge/core/autoadd.py
|
||||
|
6048
deluge/i18n/ar.po
6048
deluge/i18n/ar.po
File diff suppressed because it is too large
Load Diff
5934
deluge/i18n/bg.po
5934
deluge/i18n/bg.po
File diff suppressed because it is too large
Load Diff
5858
deluge/i18n/ca.po
5858
deluge/i18n/ca.po
File diff suppressed because it is too large
Load Diff
5511
deluge/i18n/cs.po
5511
deluge/i18n/cs.po
File diff suppressed because it is too large
Load Diff
6030
deluge/i18n/da.po
6030
deluge/i18n/da.po
File diff suppressed because it is too large
Load Diff
5700
deluge/i18n/de.po
5700
deluge/i18n/de.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
5912
deluge/i18n/el.po
5912
deluge/i18n/el.po
File diff suppressed because it is too large
Load Diff
5632
deluge/i18n/en_AU.po
5632
deluge/i18n/en_AU.po
File diff suppressed because it is too large
Load Diff
5906
deluge/i18n/en_CA.po
5906
deluge/i18n/en_CA.po
File diff suppressed because it is too large
Load Diff
5904
deluge/i18n/en_GB.po
5904
deluge/i18n/en_GB.po
File diff suppressed because it is too large
Load Diff
6029
deluge/i18n/es.po
6029
deluge/i18n/es.po
File diff suppressed because it is too large
Load Diff
5903
deluge/i18n/et.po
5903
deluge/i18n/et.po
File diff suppressed because it is too large
Load Diff
5312
deluge/i18n/eu.po
5312
deluge/i18n/eu.po
File diff suppressed because it is too large
Load Diff
5687
deluge/i18n/fi.po
5687
deluge/i18n/fi.po
File diff suppressed because it is too large
Load Diff
5938
deluge/i18n/fr.po
5938
deluge/i18n/fr.po
File diff suppressed because it is too large
Load Diff
5609
deluge/i18n/gl.po
5609
deluge/i18n/gl.po
File diff suppressed because it is too large
Load Diff
5928
deluge/i18n/he.po
5928
deluge/i18n/he.po
File diff suppressed because it is too large
Load Diff
5326
deluge/i18n/hi.po
5326
deluge/i18n/hi.po
File diff suppressed because it is too large
Load Diff
5765
deluge/i18n/hu.po
5765
deluge/i18n/hu.po
File diff suppressed because it is too large
Load Diff
5357
deluge/i18n/id.po
5357
deluge/i18n/id.po
File diff suppressed because it is too large
Load Diff
5814
deluge/i18n/is.po
5814
deluge/i18n/is.po
File diff suppressed because it is too large
Load Diff
5754
deluge/i18n/it.po
5754
deluge/i18n/it.po
File diff suppressed because it is too large
Load Diff
5853
deluge/i18n/ja.po
5853
deluge/i18n/ja.po
File diff suppressed because it is too large
Load Diff
5022
deluge/i18n/kk.po
5022
deluge/i18n/kk.po
File diff suppressed because it is too large
Load Diff
6679
deluge/i18n/ko.po
6679
deluge/i18n/ko.po
File diff suppressed because it is too large
Load Diff
5648
deluge/i18n/lt.po
5648
deluge/i18n/lt.po
File diff suppressed because it is too large
Load Diff
5836
deluge/i18n/lv.po
5836
deluge/i18n/lv.po
File diff suppressed because it is too large
Load Diff
5883
deluge/i18n/ms.po
5883
deluge/i18n/ms.po
File diff suppressed because it is too large
Load Diff
5780
deluge/i18n/nb.po
5780
deluge/i18n/nb.po
File diff suppressed because it is too large
Load Diff
5712
deluge/i18n/nl.po
5712
deluge/i18n/nl.po
File diff suppressed because it is too large
Load Diff
3381
deluge/i18n/nn.po
Normal file
3381
deluge/i18n/nn.po
Normal file
File diff suppressed because it is too large
Load Diff
3389
deluge/i18n/oc.po
Normal file
3389
deluge/i18n/oc.po
Normal file
File diff suppressed because it is too large
Load Diff
5616
deluge/i18n/pl.po
5616
deluge/i18n/pl.po
File diff suppressed because it is too large
Load Diff
5974
deluge/i18n/pt.po
5974
deluge/i18n/pt.po
File diff suppressed because it is too large
Load Diff
5692
deluge/i18n/pt_BR.po
5692
deluge/i18n/pt_BR.po
File diff suppressed because it is too large
Load Diff
5863
deluge/i18n/ro.po
5863
deluge/i18n/ro.po
File diff suppressed because it is too large
Load Diff
5773
deluge/i18n/ru.po
5773
deluge/i18n/ru.po
File diff suppressed because it is too large
Load Diff
6025
deluge/i18n/sk.po
6025
deluge/i18n/sk.po
File diff suppressed because it is too large
Load Diff
5454
deluge/i18n/sl.po
5454
deluge/i18n/sl.po
File diff suppressed because it is too large
Load Diff
5778
deluge/i18n/sr.po
5778
deluge/i18n/sr.po
File diff suppressed because it is too large
Load Diff
5718
deluge/i18n/sv.po
5718
deluge/i18n/sv.po
File diff suppressed because it is too large
Load Diff
5296
deluge/i18n/th.po
5296
deluge/i18n/th.po
File diff suppressed because it is too large
Load Diff
5644
deluge/i18n/tr.po
5644
deluge/i18n/tr.po
File diff suppressed because it is too large
Load Diff
5667
deluge/i18n/uk.po
5667
deluge/i18n/uk.po
File diff suppressed because it is too large
Load Diff
6931
deluge/i18n/zh_CN.po
6931
deluge/i18n/zh_CN.po
File diff suppressed because it is too large
Load Diff
6207
deluge/i18n/zh_TW.po
6207
deluge/i18n/zh_TW.po
File diff suppressed because it is too large
Load Diff
@ -135,11 +135,11 @@ def start_daemon():
|
||||
help="Port daemon will listen on", action="store", type="int")
|
||||
parser.add_option("-i", "--interface", dest="interface",
|
||||
help="Interface daemon will listen for bittorrent connections on, \
|
||||
this should be an IP address",
|
||||
this should be an IP address", metavar="IFACE",
|
||||
action="store", type="str")
|
||||
parser.add_option("-u", "--ui-interface", dest="ui_interface",
|
||||
help="Interface daemon will listen for UI connections on, this should be\
|
||||
an IP address", action="store", type="str")
|
||||
an IP address", metavar="IFACE", action="store", type="str")
|
||||
parser.add_option("-d", "--do-not-daemonize", dest="donot",
|
||||
help="Do not daemonize", action="store_true", default=False)
|
||||
parser.add_option("-c", "--config", dest="config",
|
||||
@ -197,6 +197,11 @@ this should be an IP address",
|
||||
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
|
||||
|
||||
|
@ -1,356 +0,0 @@
|
||||
#
|
||||
# maketorrent.py
|
||||
#
|
||||
# Copyright (C) 2009 Andrew Resch <andrewresch@gmail.com>
|
||||
#
|
||||
# Deluge is free software.
|
||||
#
|
||||
# You may redistribute it and/or modify it under the terms of the
|
||||
# GNU General Public License, as published by the Free Software
|
||||
# Foundation; either version 3 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# deluge is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See the GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with deluge. If not, write to:
|
||||
# The Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor
|
||||
# Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# In addition, as a special exception, the copyright holders give
|
||||
# permission to link the code of portions of this program with the OpenSSL
|
||||
# library.
|
||||
# You must obey the GNU General Public License in all respects for all of
|
||||
# the code used other than OpenSSL. If you modify file(s) with this
|
||||
# exception, you may extend this exception to your version of the file(s),
|
||||
# but you are not obligated to do so. If you do not wish to do so, delete
|
||||
# this exception statement from your version. If you delete this exception
|
||||
# statement from all source files in the program, then also delete it here.
|
||||
#
|
||||
#
|
||||
|
||||
import sys
|
||||
import os
|
||||
from hashlib import sha1 as sha
|
||||
|
||||
from deluge.common import get_path_size
|
||||
from deluge.bencode import bencode, bdecode
|
||||
|
||||
class InvalidPath(Exception):
|
||||
"""
|
||||
Raised when an invalid path is supplied
|
||||
"""
|
||||
pass
|
||||
|
||||
class InvalidPieceSize(Exception):
|
||||
"""
|
||||
Raised when an invalid piece size is set. Piece sizes must be multiples of
|
||||
16KiB.
|
||||
"""
|
||||
pass
|
||||
|
||||
class TorrentMetadata(object):
|
||||
"""
|
||||
This class is used to create .torrent files.
|
||||
|
||||
** Usage **
|
||||
|
||||
>>> t = TorrentMetadata()
|
||||
>>> t.data_path = "/tmp/torrent"
|
||||
>>> t.comment = "My Test Torrent"
|
||||
>>> t.trackers = [["http://tracker.openbittorent.com"]]
|
||||
>>> t.save("/tmp/test.torrent")
|
||||
|
||||
"""
|
||||
def __init__(self):
|
||||
self.__data_path = None
|
||||
self.__piece_size = 0
|
||||
self.__comment = ""
|
||||
self.__private = False
|
||||
self.__trackers = []
|
||||
self.__webseeds = []
|
||||
self.__pad_files = False
|
||||
|
||||
def save(self, torrent_path, progress=None):
|
||||
"""
|
||||
Creates and saves the torrent file to `path`.
|
||||
|
||||
:param torrent_path: where to save the torrent file
|
||||
:type torrent_path: string
|
||||
|
||||
:param progress: a function to be called when a piece is hashed
|
||||
:type progress: function(num_completed, num_pieces)
|
||||
|
||||
:raises InvalidPath: if the data_path has not been set
|
||||
|
||||
"""
|
||||
if not self.data_path:
|
||||
raise InvalidPath("Need to set a data_path!")
|
||||
|
||||
torrent = {
|
||||
"info": {}
|
||||
}
|
||||
|
||||
if self.comment:
|
||||
torrent["comment"] = self.comment.encode("UTF-8")
|
||||
|
||||
if self.private:
|
||||
torrent["info"]["private"] = True
|
||||
|
||||
if self.trackers:
|
||||
torrent["announce"] = self.trackers[0][0]
|
||||
torrent["announce-list"] = self.trackers
|
||||
else:
|
||||
torrent["announce"] = ""
|
||||
|
||||
if self.webseeds:
|
||||
httpseeds = []
|
||||
webseeds = []
|
||||
for w in self.webseeds:
|
||||
if w.endswith(".php"):
|
||||
httpseeds.append(w)
|
||||
else:
|
||||
webseeds.append(w)
|
||||
|
||||
if httpseeds:
|
||||
torrent["httpseeds"] = httpseeds
|
||||
if webseeds:
|
||||
torrent["url-list"] = webseeds
|
||||
|
||||
datasize = get_path_size(self.data_path)
|
||||
|
||||
if self.piece_size:
|
||||
piece_size = piece_size * 1024
|
||||
else:
|
||||
# We need to calculate a piece size
|
||||
piece_size = 16384
|
||||
while (datasize / piece_size) > 1024 and piece_size < (8192 * 1024):
|
||||
piece_size *= 2
|
||||
|
||||
# Calculate the number of pieces we will require for the data
|
||||
num_pieces = datasize / piece_size
|
||||
if datasize % piece_size:
|
||||
num_pieces += 1
|
||||
|
||||
torrent["info"]["piece length"] = piece_size
|
||||
|
||||
# Create the info
|
||||
if os.path.isdir(self.data_path):
|
||||
torrent["info"]["name"] = os.path.split(self.data_path)[1]
|
||||
files = []
|
||||
padding_count = 0
|
||||
# Collect a list of file paths and add padding files if necessary
|
||||
for (dirpath, dirnames, filenames) in os.walk(self.data_path):
|
||||
for index, filename in enumerate(filenames):
|
||||
size = get_path_size(os.path.join(self.data_path, dirpath, filename))
|
||||
p = dirpath[len(self.data_path):]
|
||||
p = p.lstrip("/")
|
||||
p = p.split("/")
|
||||
if p[0]:
|
||||
p += [filename]
|
||||
else:
|
||||
p = [filename]
|
||||
files.append((size, p))
|
||||
# Add a padding file if necessary
|
||||
if self.pad_files and (index + 1) < len(filenames):
|
||||
left = size % piece_size
|
||||
if left:
|
||||
p = list(p)
|
||||
p[-1] = "_____padding_file_" + str(padding_count)
|
||||
files.append((piece_size - left, p))
|
||||
padding_count += 1
|
||||
|
||||
# Run the progress function with 0 completed pieces
|
||||
if progress:
|
||||
progress(0, num_pieces)
|
||||
|
||||
fs = []
|
||||
pieces = []
|
||||
# Create the piece hashes
|
||||
buf = ""
|
||||
for size, path in files:
|
||||
path = [s.decode(sys.getfilesystemencoding()).encode("UTF-8") for s in path]
|
||||
fs.append({"length": size, "path": path})
|
||||
if path[-1].startswith("_____padding_file_"):
|
||||
buf += "\0" * size
|
||||
pieces.append(sha(buf).digest())
|
||||
buf = ""
|
||||
fs[-1]["attr"] = "p"
|
||||
else:
|
||||
fd = open(os.path.join(self.data_path, *path), "rb")
|
||||
r = fd.read(piece_size - len(buf))
|
||||
while r:
|
||||
buf += r
|
||||
if len(buf) == piece_size:
|
||||
pieces.append(sha(buf).digest())
|
||||
# Run the progress function if necessary
|
||||
if progress:
|
||||
progress(len(pieces), num_pieces)
|
||||
buf = ""
|
||||
else:
|
||||
break
|
||||
r = fd.read(piece_size - len(buf))
|
||||
fd.close()
|
||||
|
||||
if buf:
|
||||
pieces.append(sha(buf).digest())
|
||||
if progress:
|
||||
progress(len(pieces), num_pieces)
|
||||
buf = ""
|
||||
|
||||
torrent["info"]["pieces"] = "".join(pieces)
|
||||
torrent["info"]["files"] = fs
|
||||
|
||||
elif os.path.isfile(self.data_path):
|
||||
torrent["info"]["name"] = os.path.split(self.data_path)[1]
|
||||
torrent["info"]["length"] = get_path_size(self.data_path)
|
||||
pieces = []
|
||||
|
||||
fd = open(self.data_path, "rb")
|
||||
r = fd.read(piece_size)
|
||||
while r:
|
||||
pieces.append(sha(r).digest())
|
||||
if progress:
|
||||
progress(len(pieces), num_pieces)
|
||||
|
||||
r = fd.read(piece_size)
|
||||
|
||||
torrent["info"]["pieces"] = "".join(pieces)
|
||||
|
||||
# Write out the torrent file
|
||||
open(torrent_path, "wb").write(bencode(torrent))
|
||||
|
||||
def get_data_path(self):
|
||||
"""
|
||||
The path to the files that the torrent will contain. It can be either
|
||||
a file or a folder. This property needs to be set before the torrent
|
||||
file can be created and saved.
|
||||
"""
|
||||
return self.__data_path
|
||||
|
||||
def set_data_path(self, path):
|
||||
"""
|
||||
:param path: the path to the data
|
||||
:type path: string
|
||||
|
||||
:raises InvalidPath: if the path is not found
|
||||
|
||||
"""
|
||||
if os.path.exists(path) and (os.path.isdir(path) or os.path.isfile(path)):
|
||||
self.__data_path = os.path.abspath(path)
|
||||
else:
|
||||
raise InvalidPath("No such file or directory: %s" % path)
|
||||
|
||||
def get_piece_size(self):
|
||||
"""
|
||||
The size of pieces in bytes. The size must be a multiple of 16KiB.
|
||||
If you don't set a piece size, one will be automatically selected to
|
||||
produce a torrent with less than 1024 pieces or the smallest possible
|
||||
with a 8192KiB piece size.
|
||||
|
||||
"""
|
||||
return self.__piece_size
|
||||
|
||||
def set_piece_size(self, size):
|
||||
"""
|
||||
:param size: the desired piece size in KiBs
|
||||
:type size: int
|
||||
|
||||
:raises InvalidPieceSize: if the piece size is not a multiple of 16 KiB
|
||||
|
||||
"""
|
||||
if size % 16 and size:
|
||||
raise InvalidPieceSize("Piece size must be a multiple of 16 KiB")
|
||||
self.__piece_size = size
|
||||
|
||||
def get_comment(self):
|
||||
"""
|
||||
Comment is some extra info to be stored in the torrent. This is
|
||||
typically an informational string.
|
||||
"""
|
||||
return self.__comment
|
||||
|
||||
def set_comment(self, comment):
|
||||
"""
|
||||
:param comment: an informational string
|
||||
:type comment: string
|
||||
"""
|
||||
self.__comment = comment
|
||||
|
||||
def get_private(self):
|
||||
"""
|
||||
Private torrents only announce to the tracker and will not use DHT or
|
||||
Peer Exchange.
|
||||
|
||||
See: http://bittorrent.org/beps/bep_0027.html
|
||||
|
||||
"""
|
||||
return self.__private
|
||||
|
||||
def set_private(self, private):
|
||||
"""
|
||||
:param private: True if the torrent is to be private
|
||||
:type private: bool
|
||||
"""
|
||||
self.__private = private
|
||||
|
||||
def get_trackers(self):
|
||||
"""
|
||||
The announce trackers is a list of lists.
|
||||
|
||||
See: http://bittorrent.org/beps/bep_0012.html
|
||||
|
||||
"""
|
||||
return self.__trackers
|
||||
|
||||
def set_trackers(self, trackers):
|
||||
"""
|
||||
:param trackers: a list of lists of trackers, each list is a tier
|
||||
:type trackers: list of list of strings
|
||||
"""
|
||||
self.__trackers = trackers
|
||||
|
||||
def get_webseeds(self):
|
||||
"""
|
||||
The web seeds can either be:
|
||||
Hoffman-style: http://bittorrent.org/beps/bep_0017.html
|
||||
or,
|
||||
GetRight-style: http://bittorrent.org/beps/bep_0019.html
|
||||
|
||||
If the url ends in '.php' then it will be considered Hoffman-style, if
|
||||
not it will be considered GetRight-style.
|
||||
"""
|
||||
return self.__webseeds
|
||||
|
||||
def set_webseeds(self, webseeds):
|
||||
"""
|
||||
:param webseeds: the webseeds which can be either Hoffman or GetRight style
|
||||
:type webseeds: list of urls
|
||||
"""
|
||||
self.__webseeds = webseeds
|
||||
|
||||
def get_pad_files(self):
|
||||
"""
|
||||
If this is True, padding files will be added to align files on piece
|
||||
boundaries.
|
||||
"""
|
||||
return self.__pad_files
|
||||
|
||||
def set_pad_files(self, pad):
|
||||
"""
|
||||
:param pad: set True to align files on piece boundaries
|
||||
:type pad: bool
|
||||
"""
|
||||
self.__pad_files = pad
|
||||
|
||||
data_path = property(get_data_path, set_data_path)
|
||||
piece_size = property(get_piece_size, set_piece_size)
|
||||
comment = property(get_comment, set_comment)
|
||||
private = property(get_private, set_private)
|
||||
trackers = property(get_trackers, set_trackers)
|
||||
webseeds = property(get_webseeds, set_webseeds)
|
||||
pad_files = property(get_pad_files, set_pad_files)
|
@ -100,7 +100,7 @@ def make_meta_file(path, url, piece_length, progress=dummy,
|
||||
if created_by:
|
||||
data['created by'] = created_by.encode("utf8")
|
||||
|
||||
if trackers:
|
||||
if trackers and (len(trackers[0]) > 1 or len(trackers) > 1):
|
||||
data['announce-list'] = trackers
|
||||
|
||||
data["encoding"] = "UTF-8"
|
||||
@ -175,11 +175,12 @@ def makeinfo(path, piece_length, progress, name = None,
|
||||
piece_count += 1
|
||||
done = 0
|
||||
sh = sha()
|
||||
progress(piece_count, num_pieces)
|
||||
progress(piece_count, num_pieces)
|
||||
h.close()
|
||||
if done > 0:
|
||||
pieces.append(sh.digest())
|
||||
|
||||
progress(piece_count, num_pieces)
|
||||
|
||||
if name is not None:
|
||||
assert isinstance(name, unicode)
|
||||
name = to_utf8(name)
|
||||
|
@ -87,7 +87,7 @@ class PluginManagerBase:
|
||||
def disable_plugins(self):
|
||||
# Disable all plugins that are enabled
|
||||
for key in self.plugins.keys():
|
||||
self.plugins[key].disable()
|
||||
self.disable_plugin(key)
|
||||
|
||||
def __getitem__(self, key):
|
||||
return self.plugins[key]
|
||||
@ -131,12 +131,13 @@ class PluginManagerBase:
|
||||
egg.activate()
|
||||
for name in egg.get_entry_map(self.entry_name):
|
||||
entry_point = egg.get_entry_info(self.entry_name, name)
|
||||
cls = entry_point.load()
|
||||
try:
|
||||
cls = entry_point.load()
|
||||
instance = cls(plugin_name.replace("-", "_"))
|
||||
except Exception, e:
|
||||
log.error("Unable to instantiate plugin!")
|
||||
log.exception(e)
|
||||
continue
|
||||
instance.enable()
|
||||
if self.get_state() == component.COMPONENT_STATE.index("Started"):
|
||||
component.start(instance.plugin.get_component_name())
|
||||
@ -152,6 +153,7 @@ class PluginManagerBase:
|
||||
"""Disables a plugin"""
|
||||
try:
|
||||
self.plugins[name].disable()
|
||||
component.deregister(self.plugins[name].plugin.get_component_name())
|
||||
del self.plugins[name]
|
||||
self.config["enabled_plugins"].remove(name)
|
||||
except KeyError:
|
||||
|
@ -49,3 +49,18 @@ def raiseError(error):
|
||||
raise error
|
||||
return new
|
||||
return safer
|
||||
|
||||
def remove_zeros(ip):
|
||||
"""
|
||||
Removes unneeded zeros from ip addresses.
|
||||
|
||||
Example: 000.000.000.003 -> 0.0.0.3
|
||||
|
||||
:param ip: the ip address
|
||||
:type ip: string
|
||||
|
||||
:returns: the ip address without the unneeded zeros
|
||||
:rtype: string
|
||||
|
||||
"""
|
||||
return ".".join([part.lstrip("0").zfill(1) for part in ip.split(".")])
|
||||
|
@ -35,7 +35,9 @@
|
||||
#
|
||||
|
||||
import os
|
||||
import datetime
|
||||
import time
|
||||
from datetime import datetime, timedelta
|
||||
from wsgiref.handlers import format_date_time
|
||||
import shutil
|
||||
|
||||
from twisted.internet.task import LoopingCall
|
||||
@ -60,7 +62,7 @@ DEFAULT_PREFS = {
|
||||
"check_after_days": 4,
|
||||
"list_compression": "",
|
||||
"list_type": "",
|
||||
"last_update": "",
|
||||
"last_update": 0.0,
|
||||
"list_size": 0,
|
||||
"timeout": 180,
|
||||
"try_times": 3,
|
||||
@ -85,14 +87,15 @@ class Core(CorePluginBase):
|
||||
|
||||
self.reader = create_reader(self.config["list_type"], self.config["list_compression"])
|
||||
|
||||
if type(self.config["last_update"]) is not float:
|
||||
self.config.config["last_update"] = 0.0
|
||||
|
||||
update_now = False
|
||||
if self.config["load_on_start"]:
|
||||
if self.config["last_update"]:
|
||||
now = datetime.datetime.now()
|
||||
last_update = datetime.datetime.strptime(self.config["last_update"],
|
||||
"%a, %d %b %Y %H:%M:%S GMT")
|
||||
check_period = datetime.timedelta(days=self.config["check_after_days"])
|
||||
if not self.config["last_update"] or last_update + check_period >= now:
|
||||
last_update = datetime.fromtimestamp(self.config["last_update"])
|
||||
check_period = timedelta(days=self.config["check_after_days"])
|
||||
if not self.config["last_update"] or last_update + check_period < datetime.now():
|
||||
update_now = True
|
||||
else:
|
||||
self.use_cache = True
|
||||
@ -128,6 +131,8 @@ class Core(CorePluginBase):
|
||||
self.use_cache = False
|
||||
self.failed_attempts = 0
|
||||
self.auto_detected = False
|
||||
if force:
|
||||
self.reader = None
|
||||
|
||||
# Start callback chain
|
||||
d = self.download_list()
|
||||
@ -186,7 +191,7 @@ class Core(CorePluginBase):
|
||||
:type blocklist: string
|
||||
"""
|
||||
log.debug("Updating blocklist info: %s", blocklist)
|
||||
self.config["last_update"] = datetime.datetime.utcnow().strftime("%a, %d %b %Y %H:%M:%S GMT")
|
||||
self.config["last_update"] = time.time()
|
||||
self.config["list_size"] = os.path.getsize(blocklist)
|
||||
|
||||
def download_list(self, url=None):
|
||||
@ -216,10 +221,10 @@ class Core(CorePluginBase):
|
||||
|
||||
headers = {}
|
||||
if self.config["last_update"] and not self.force_download:
|
||||
headers['If-Modified-Since'] = self.config["last_update"]
|
||||
headers['If-Modified-Since'] = format_date_time(self.config["last_update"])
|
||||
|
||||
log.debug("Attempting to download blocklist %s" % url)
|
||||
log.debug("Sending headers: %s" % headers)
|
||||
log.debug("Attempting to download blocklist %s", url)
|
||||
log.debug("Sending headers: %s", headers)
|
||||
self.up_to_date = False
|
||||
self.is_downloading = True
|
||||
return download_file(url, deluge.configmanager.get_config_dir("blocklist.download"), on_retrieve_data, headers)
|
||||
@ -239,9 +244,8 @@ class Core(CorePluginBase):
|
||||
# Handle redirect errors
|
||||
location = error_msg.split(" to ")[1]
|
||||
if "Moved Permanently" in error_msg:
|
||||
log.debug("Setting blocklist url to %s" % location)
|
||||
log.debug("Setting blocklist url to %s", location)
|
||||
self.config["url"] = location
|
||||
f.trap(f.type)
|
||||
d = self.download_list(url=location)
|
||||
d.addCallbacks(self.on_download_complete, self.on_download_error)
|
||||
else:
|
||||
@ -253,13 +257,13 @@ class Core(CorePluginBase):
|
||||
bl_filename = "blocklist.cache" if self.use_cache else "blocklist.download"
|
||||
d = threads.deferToThread(self.update_info,
|
||||
deluge.configmanager.get_config_dir(bl_filename))
|
||||
f.trap(f.type)
|
||||
elif self.failed_attempts < self.config["try_times"]:
|
||||
log.warning("Blocklist download failed!")
|
||||
self.failed_attempts += 1
|
||||
f.trap(f.type)
|
||||
else:
|
||||
log.error(error_msg)
|
||||
log.warning("Blocklist download failed: %s", error_msg)
|
||||
if self.failed_attempts < self.config["try_times"]:
|
||||
log.debug("Let's try again!")
|
||||
self.failed_attempts += 1
|
||||
d = self.download_list()
|
||||
d.addCallbacks(self.on_download_complete, self.on_download_error)
|
||||
return d
|
||||
|
||||
def import_list(self, force=False):
|
||||
@ -291,7 +295,7 @@ class Core(CorePluginBase):
|
||||
self.auto_detect(blocklist)
|
||||
self.auto_detected = True
|
||||
|
||||
log.debug("Importing using reader: %s",self.reader)
|
||||
log.debug("Importing using reader: %s", self.reader)
|
||||
log.debug("Reader type: %s compression: %s", self.config["list_type"], self.config["list_compression"])
|
||||
d = threads.deferToThread(self.reader(blocklist).read, on_read_ip_range)
|
||||
d.addCallback(on_finish_read)
|
||||
@ -325,9 +329,8 @@ class Core(CorePluginBase):
|
||||
self.reader = None
|
||||
try_again = True
|
||||
elif os.path.exists(blocklist) and not self.use_cache:
|
||||
# If we have a backup and we haven't already used it
|
||||
e = f.trap(Exception)
|
||||
log.warning("Error reading blocklist: ", e)
|
||||
# If we have a backup and we haven't already used it
|
||||
log.warning("Error reading blocklist: %s", f.getErrorMessage())
|
||||
self.use_cache = True
|
||||
try_again = True
|
||||
|
||||
@ -347,7 +350,7 @@ class Core(CorePluginBase):
|
||||
"""
|
||||
self.config["list_compression"] = detect_compression(blocklist)
|
||||
self.config["list_type"] = detect_format(blocklist, self.config["list_compression"])
|
||||
log.debug("Auto-detected type: %s compression: %s", self.config["list_type"], self.config["list_compression"])
|
||||
log.debug("Auto-detected type: %s compression: %s", self.config["list_type"], self.config["list_compression"])
|
||||
if not self.config["list_type"]:
|
||||
self.config["list_compression"] = ""
|
||||
raise UnknownFormatError
|
||||
|
@ -6,6 +6,7 @@
|
||||
<child>
|
||||
<widget class="GtkVBox" id="blocklist_prefs_box">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<widget class="GtkFrame" id="frame1">
|
||||
@ -58,6 +59,7 @@
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
@ -74,6 +76,7 @@
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox1">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<widget class="GtkTable" id="table1">
|
||||
@ -156,6 +159,7 @@
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
@ -177,6 +181,7 @@
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox3">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<widget class="GtkButton" id="button_check_download">
|
||||
<property name="visible">True</property>
|
||||
@ -294,6 +299,7 @@
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
@ -311,6 +317,7 @@
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox4">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<widget class="GtkProgressBar" id="progressbar">
|
||||
<property name="visible">True</property>
|
||||
@ -440,6 +447,7 @@
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
|
@ -39,7 +39,13 @@ def Zipped(reader):
|
||||
"""Blocklist reader for zipped blocklists"""
|
||||
def open(self):
|
||||
z = zipfile.ZipFile(self.file)
|
||||
return z.open(z.namelist()[0])
|
||||
if hasattr(z, 'open'):
|
||||
f = z.open(z.namelist()[0])
|
||||
else:
|
||||
# Handle python 2.5
|
||||
import cStringIO
|
||||
f = cStringIO.StringIO(z.read(z.namelist()[0]))
|
||||
return f
|
||||
reader.open = open
|
||||
return reader
|
||||
|
||||
|
@ -39,7 +39,7 @@ from readers import EmuleReader, SafePeerReader, PeerGuardianReader
|
||||
COMPRESSION_TYPES = {
|
||||
"PK" : "Zip",
|
||||
"\x1f\x8b" : "GZip",
|
||||
"BZ" : "BZ ip2"
|
||||
"BZ" : "BZip2"
|
||||
}
|
||||
|
||||
DECOMPRESSERS = {
|
||||
@ -77,5 +77,4 @@ def create_reader(format, compression=""):
|
||||
decompressor = DECOMPRESSERS.get(compression)
|
||||
if decompressor:
|
||||
reader = decompressor(reader)
|
||||
|
||||
return reader
|
||||
|
@ -33,6 +33,7 @@
|
||||
#
|
||||
#
|
||||
|
||||
from datetime import datetime
|
||||
import gtk
|
||||
|
||||
from deluge.log import LOG as log
|
||||
@ -115,7 +116,7 @@ class GtkUI(GtkPluginBase):
|
||||
self.glade.get_widget("label_filesize").set_text(
|
||||
deluge.common.fsize(status["file_size"]))
|
||||
self.glade.get_widget("label_modified").set_text(
|
||||
str(status["file_date"]))
|
||||
datetime.fromtimestamp(status["file_date"]).strftime("%c"))
|
||||
self.glade.get_widget("label_type").set_text(status["file_type"])
|
||||
self.glade.get_widget("label_url").set_text(
|
||||
status["file_url"])
|
||||
@ -151,7 +152,7 @@ class GtkUI(GtkPluginBase):
|
||||
client.blocklist.check_import(force=True)
|
||||
|
||||
def _on_status_item_clicked(self, widget, event):
|
||||
component.get("Preferences").show("Blocklist")
|
||||
component.get("Preferences").show(_("Blocklist"))
|
||||
|
||||
def load_preferences_page(self):
|
||||
"""Initializes the preferences page and adds it to the preferences dialog"""
|
||||
|
@ -33,29 +33,9 @@
|
||||
#
|
||||
#
|
||||
|
||||
from deluge.log import LOG as log
|
||||
from common import raiseError
|
||||
from common import raiseError, remove_zeros
|
||||
import re
|
||||
|
||||
def remove_zeros(ip):
|
||||
"""
|
||||
Removes unneeded zeros from ip addresses.
|
||||
|
||||
Example: 000.000.000.003 -> 0.0.0.3
|
||||
|
||||
:param ip: the ip address
|
||||
:type ip: string
|
||||
|
||||
:returns: the ip address without the unneeded zeros
|
||||
:rtype: string
|
||||
|
||||
"""
|
||||
new_ip = []
|
||||
for part in ip.split("."):
|
||||
while part[0] == "0" and len(part) > 1:
|
||||
part = part[1:]
|
||||
new_ip.append(part)
|
||||
return ".".join(new_ip)
|
||||
|
||||
class ReaderParseError(Exception):
|
||||
pass
|
||||
|
||||
@ -80,7 +60,8 @@ class BaseReader(object):
|
||||
|
||||
def is_ignored(self, line):
|
||||
"""Ignore commented lines and blank lines"""
|
||||
return line.startswith('#') or not line.strip()
|
||||
line = line.strip()
|
||||
return line.startswith('#') or not line
|
||||
|
||||
def is_valid(self):
|
||||
"""Determines whether file is valid for this reader"""
|
||||
@ -90,6 +71,9 @@ class BaseReader(object):
|
||||
if not self.is_ignored(line):
|
||||
try:
|
||||
(start, end) = self.parse(line)
|
||||
if not re.match("^(\d{1,3}\.){4}$", start + ".") or \
|
||||
not re.match("^(\d{1,3}\.){4}$", end + "."):
|
||||
valid = False
|
||||
except:
|
||||
valid = False
|
||||
finally:
|
||||
@ -97,6 +81,7 @@ class BaseReader(object):
|
||||
blocklist.close()
|
||||
return valid
|
||||
|
||||
@raiseError(ReaderParseError)
|
||||
def readranges(self):
|
||||
"""Yields each ip range from the file"""
|
||||
blocklist = self.open()
|
||||
@ -107,15 +92,13 @@ class BaseReader(object):
|
||||
|
||||
class EmuleReader(BaseReader):
|
||||
"""Blocklist reader for emule style blocklists"""
|
||||
@raiseError(ReaderParseError)
|
||||
def parse(self, line):
|
||||
return line.strip().split(" , ")[0].split(" - ")
|
||||
|
||||
class SafePeerReader(BaseReader):
|
||||
"""Blocklist reader for SafePeer style blocklists"""
|
||||
@raiseError(ReaderParseError)
|
||||
def parse(self, line):
|
||||
return line.strip().split(":")[1].split("-")
|
||||
return line.strip().split(":")[-1].split("-")
|
||||
|
||||
class PeerGuardianReader(SafePeerReader):
|
||||
"""Blocklist reader for PeerGuardian style blocklists"""
|
||||
|
@ -34,9 +34,9 @@
|
||||
from setuptools import setup
|
||||
|
||||
__plugin_name__ = "Blocklist"
|
||||
__author__ = "Andrew Resch"
|
||||
__author_email__ = "andrew.resch@gmail.com"
|
||||
__version__ = "1.0"
|
||||
__author__ = "John Garland"
|
||||
__author_email__ = "johnnybg@gmail.com"
|
||||
__version__ = "1.2"
|
||||
__url__ = "http://deluge-torrent.org"
|
||||
__license__ = "GPLv3"
|
||||
__description__ = "Download and import IP blocklists"
|
||||
|
@ -1,54 +0,0 @@
|
||||
#
|
||||
# __init__.py
|
||||
#
|
||||
# Copyright (C) 2009 Andrew Resch <andrewresch@gmail.com>
|
||||
#
|
||||
# Deluge is free software.
|
||||
#
|
||||
# You may redistribute it and/or modify it under the terms of the
|
||||
# GNU General Public License, as published by the Free Software
|
||||
# Foundation; either version 3 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# deluge is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See the GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with deluge. If not, write to:
|
||||
# The Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor
|
||||
# Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# In addition, as a special exception, the copyright holders give
|
||||
# permission to link the code of portions of this program with the OpenSSL
|
||||
# library.
|
||||
# You must obey the GNU General Public License in all respects for all of
|
||||
# the code used other than OpenSSL. If you modify file(s) with this
|
||||
# exception, you may extend this exception to your version of the file(s),
|
||||
# but you are not obligated to do so. If you do not wish to do so, delete
|
||||
# this exception statement from your version. If you delete this exception
|
||||
# statement from all source files in the program, then also delete it here.
|
||||
#
|
||||
#
|
||||
|
||||
from deluge.plugins.init import PluginInitBase
|
||||
|
||||
class CorePlugin(PluginInitBase):
|
||||
def __init__(self, plugin_name):
|
||||
from core import Core as _plugin_cls
|
||||
self._plugin_cls = _plugin_cls
|
||||
super(CorePlugin, self).__init__(plugin_name)
|
||||
|
||||
class GtkUIPlugin(PluginInitBase):
|
||||
def __init__(self, plugin_name):
|
||||
from gtkui import GtkUI as _plugin_cls
|
||||
self._plugin_cls = _plugin_cls
|
||||
super(GtkUIPlugin, self).__init__(plugin_name)
|
||||
|
||||
class WebUIPlugin(PluginInitBase):
|
||||
def __init__(self, plugin_name):
|
||||
from webui import WebUI as _plugin_cls
|
||||
self._plugin_cls = _plugin_cls
|
||||
super(WebUIPlugin, self).__init__(plugin_name)
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user