Compare commits

...

188 Commits

Author SHA1 Message Date
28da88006d Tag 1.2.0_rc5 release 2009-12-18 00:55:26 +00:00
00c4b53b67 Remove MANIFEST.in file 2009-12-18 00:46:26 +00:00
9a9ae71564 Update translations 2009-12-18 00:01:36 +00:00
c9c57e0e32 Update pot file 2009-12-17 23:58:21 +00:00
c70a9875c5 Prep for release 2009-12-17 23:49:25 +00:00
c932de8470 Remove redundant variable. 2009-12-17 23:08:55 +00:00
0663da4424 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.
2009-12-17 21:40:21 +00:00
8c265bb308 Fix #1095 incorrect piece size used when using some non-English languages 2009-12-17 21:27:04 +00:00
fe6c89a2e1 Upgrade older confs instead of just dying.
Fix major logic error when checking if an update is needed.
2009-12-16 13:46:39 +00:00
3c5d5aa16e Fix import on startup which got broken in previous commit. 2009-12-16 12:46:57 +00:00
389e9cdbb0 Fix blocklist not working for all locales (#1059). 2009-12-16 11:55:34 +00:00
193f1b85ca Apply #1100 sort plugins list by name 2009-12-15 17:37:05 +00:00
4daa2a098b Fix #1099 use triple quotes on docstrings 2009-12-15 06:36:02 +00:00
52817498cf Fix showing the remove torrent dialog twice if using the delete key and pressing cancel in the dialog 2009-12-14 23:25:03 +00:00
cc3f3495b6 Fix #768 save tracker list for create torrent dialog 2009-12-14 18:46:08 +00:00
4bd00aa331 Fix #1086 deprecated gtk.Tooltips usage 2009-12-14 18:20:51 +00:00
e27c38ca67 Fix #594 tray password dialog freeze in Windows
Made the password dialog prettier
2009-12-14 02:15:08 +00:00
eeac8efcf2 Fix issue where stoping a daemon that you aren't connected to causes the gtkui to shutdown the
currently connected daemon.
2009-12-14 00:48:18 +00:00
f59901c1be Fix #823 setting config values to -1.0 2009-12-13 22:47:15 +00:00
ee76075fa4 Add #891 remove torrents by pressing the Delete key 2009-12-13 22:16:05 +00:00
3f69b05ded disconnect the client if getting information fails 2009-12-13 21:50:16 +00:00
ecca68772e use metavar to change the output of --help by optparse 2009-12-13 21:49:10 +00:00
9878fced37 Fix issue where hosts will show up erroneously as Offline 2009-12-13 21:46:55 +00:00
c312cf4b91 Disconnect from daemon if getting the info fails 2009-12-13 21:34:26 +00:00
de262bf7db Fix autoconnecting to a host other than the first one in the list 2009-12-13 21:29:46 +00:00
8edd91a3d5 Add an error dialog when trying to add a duplicate host
Center the add host dialog over the connection manager
2009-12-13 21:25:22 +00:00
f6fdae727d Fix #1036 autoconnecting to localhost daemon on start-up 2009-12-13 20:49:23 +00:00
139d6538a2 Fix #782 do not ask for tray password when window is not minimized to tray 2009-12-12 22:38:26 +00:00
b88319b4be Fix #692 no longer require tray password when quitting from the tray icon while the window is
visible.
2009-12-12 21:22:51 +00:00
dd129f8544 reset the add torrent window on hide 2009-12-12 15:56:49 +00:00
af18bdb72a Fix typo 2009-12-11 23:29:21 +00:00
85b3546c47 Fix printing 'rm' command usage when called with no arguments 2009-12-11 21:19:48 +00:00
07cd4ba83d fix #1075 (changing priority on a whole folder) 2009-12-11 20:45:59 +00:00
361f2b2390 Fix possible exception when upgrading from a 0.5 state file 2009-12-10 21:28:51 +00:00
97a69b8c0c update some of the icons in the webui 2009-12-10 18:24:31 +00:00
29f2ed84dd disable the files and options tabs until a torrent has been selected 2009-12-10 17:45:40 +00:00
9e9fbd6242 fix uploading plugins when the daemon is not localhost 2009-12-10 17:35:35 +00:00
2840d43ccb fix the onResize method for the togglefield so it resizes the textfield to the correct size 2009-12-10 17:26:45 +00:00
14454791c4 implement installing plugins via the webui 2009-12-10 15:40:37 +00:00
fcbaa1f4f2 fix the upload_plugin method as it wasn't upgraded to deluge-rpc spec 2009-12-10 15:31:27 +00:00
c716f55dda fix incorrect class name 2009-12-10 14:39:14 +00:00
a1e950d6e5 remove the margin and padding from the bottom of the options fieldset 2009-12-10 14:35:10 +00:00
e646a5ef87 fix enabling plugins on the fly 2009-12-10 14:32:55 +00:00
3c703d2ef7 Fix using the console in Windows, but only in command-line mode 2009-12-10 01:26:26 +00:00
429f7064fa tweak the download prefs page so no scrollbars appear 2009-12-10 00:38:48 +00:00
47b5274f34 improve the ToggleField widget, having the checkbox to the left of the
field rather than above it
2009-12-10 00:32:24 +00:00
a6c6d5b2b4 add tooltips to the statusbar items
add disk free space to the statusbar
2009-12-10 00:06:34 +00:00
3d3edccdac Apply cookie date fix from adios 2009-12-09 13:13:04 +00:00
36b2a82561 fix a bug in the execute plugin when move_completed is used the incorrect path was passed in 2009-12-08 11:24:56 +00:00
f5096c6e7c tweak the sizes of some form elements to improve the layout 2009-12-08 02:09:03 +00:00
76bc32d72a begin the makings of the togglefield widget that allows enabling of move completed/copy torrent files/auto add torrent files fields 2009-12-08 01:56:15 +00:00
581517c8e9 Change the compressed js script to deluge-all.js to avoid naming conflicts on case sensitive filesystems 2009-12-01 17:11:07 +00:00
b41a025217 Add button to Other preferences to associate magnet links with Deluge 2009-11-30 03:50:28 +00:00
7a91b96183 Fix #1085 only use ints for specific options to prevent unhandled exception 2009-11-29 21:32:56 +00:00
a317fdec48 Fix crash in Windows when creating a torrent 2009-11-29 07:38:29 +00:00
20b6791670 Properly show 100.00% and reduce number of progress bar updates during a torrent creation 2009-11-29 07:37:29 +00:00
411ee123f1 Register just 'deluge' not '/usr/bin/deluge' in the magnet uri handler 2009-11-29 01:45:46 +00:00
2bc13a3fb7 Attempt to register as the default magnet uri handler in GNOME on startup 2009-11-29 01:40:30 +00:00
dda893e2b7 Add some checks for OSX since it doesn't support SVG icons 2009-11-29 00:52:00 +00:00
00de8311fd swap the order of the buttons in the remove window 2009-11-26 14:59:04 +00:00
6d7572c444 update the build script and rebuild deluge.js and ext-extensions.js 2009-11-25 18:52:00 +00:00
3e1a6a1fb8 exclude some more things from the sdist 2009-11-25 18:37:40 +00:00
dbbc1124f4 prevent undefineds ending up as a key in the option manager 2009-11-25 18:37:06 +00:00
13d949381a Set batch_write to False in __init__ 2009-11-25 18:24:29 +00:00
bfea47c8bd add the updated manifest to 1.2 2009-11-25 18:00:15 +00:00
f858e271ad Add magnet link association to the installer 2009-11-25 03:09:42 +00:00
708f052153 Prep for release 2009-11-25 02:41:15 +00:00
8d6bc283d0 Fix loading the saved metadata when loading state with magnet uris 2009-11-25 01:55:51 +00:00
313c73c40c Fix files list when using magnet uris 2009-11-25 01:41:50 +00:00
012dd1919c Update translations 2009-11-23 18:16:51 +00:00
d7e83d922c Re-commit. This change got lost on the mess of merging HG and SVN branches. 2009-11-22 06:17:55 +00:00
860ceccd52 Fix adding torrents with different metadata by storing the bencoded dict too. If we bencode the stored metadata dict, there is a chance the order of the dict will be different and change the info-hash. 2009-11-20 19:13:12 +00:00
907f618607 add the beginnings of a MANIFEST.in file for specifying which files to include in the sdist command
tweak setup.py
2009-11-19 21:20:17 +00:00
abcb76e959 rename deluge-yc.js to deluge.js 2009-11-19 20:27:36 +00:00
825edb1fd8 Update changelog 2009-11-19 04:51:28 +00:00
4cdf919076 Fix issues adding magnet uris 2009-11-19 04:51:19 +00:00
90a143a4ef Fix issue where some torrents with special characters could not be added 2009-11-19 02:39:07 +00:00
04f8f80b9b Fix exception on startup when the system tray icon is not enabled 2009-11-19 02:29:37 +00:00
266693a6f9 Remove maketorrent.py in 1.2 since we're not using it 2009-11-18 19:02:05 +00:00
2b9e1e5ff4 Change the event_list to be a dictionary of known_events and their docstrings 2009-11-16 00:39:15 +00:00
68fe9512df Add way to get a list of DelugeEvent classes 2009-11-14 23:42:04 +00:00
b10ea808fd Fix endless loop when trying to autoconnect to an offline daemon 2009-11-13 05:26:54 +00:00
234863b664 Fix autoconnecting to the next host in the list if the selected one isn't available 2009-11-13 05:22:38 +00:00
940bc4a3dc Add bug number to changelog 2009-11-13 01:08:41 +00:00
aa5f69b203 Fix #1071 issue where Deluge will fail to start if there is a stale ipc lockfile 2009-11-13 01:07:36 +00:00
5f4b39aeb8 Comment out a debug log 2009-11-10 18:28:27 +00:00
0e07cdf8b1 Reduce height of Add Torrent Dialog by ~80 pixels 2009-11-10 02:45:36 +00:00
64eb296c9d remove alpha from the title 2009-11-09 23:48:32 +00:00
fa40f38c1b Allow for colons in PeerGuardian/SafePeer lists' descriptions.
Check that the start & end range resembles an ip when checking a list's validity.
2009-11-09 08:54:13 +00:00
1b46d99620 Force blocklist to re-detect the format when a download is forced.
Move remove_zeros to common.py and simplify / speed up.
Change debug logging lines to be more uniform.
2009-11-09 01:52:58 +00:00
441c20491c Fix printing info, help, etc.. on the command line 2009-11-08 17:22:57 +00:00
8c7bbbf398 Fix disabling/enabling plugins after switching daemons 2009-11-08 04:04:40 +00:00
267905295c Fix #1067 import os 2009-11-06 19:22:13 +00:00
fb4495fc33 Only try to stop LoopingCalls if they are running 2009-11-05 04:35:17 +00:00
447da3b1b4 Fix deleting old .fastresume files with fresh configs 2009-11-05 03:44:46 +00:00
9af41fd457 allow commands that are .pyc files to be used 2009-11-04 23:49:07 +00:00
7e19a11521 run the path from the add command through os.path.expanduser 2009-11-04 23:36:27 +00:00
4da33c72cc add a basic move storage window that fixes #1057 2009-11-04 20:45:21 +00:00
d411f90a67 remove the connected call upon an update to reduce the number of ajax calls 2009-11-04 19:54:59 +00:00
3179ff2060 Allow the 'help' command to be called when not connected to a daemon 2009-11-03 22:08:18 +00:00
b6dc72218d remove accidentally left in debug line 2009-11-03 14:48:24 +00:00
e884d2cbfa make the delete key work in the console ui 2009-11-03 12:47:23 +00:00
fc3ae8229f Fix adding torrents from the Queued Torrents dialog 2009-11-03 03:25:57 +00:00
48e3df5ff3 Fix showing the 'Other' speed dialogs in Windows 2009-11-03 03:19:30 +00:00
464e11abe6 Remove debian/ folder 2009-11-02 17:50:32 +00:00
0fbaecbc00 escape the hyphens in the console and web manpages 2009-11-02 17:33:06 +00:00
4c86ed7535 forward port the setup.py fix to trunk and update the 1.2 branch ChangeLog 2009-11-02 15:35:56 +00:00
6f333cefc9 include the deluge-web manpage 2009-11-02 15:28:08 +00:00
750f8fb794 Update translations 2009-11-02 01:35:13 +00:00
be529c1518 Prep rc3 release 2009-11-02 01:23:15 +00:00
e32bd8f4d8 Add the clear() back 2009-11-01 17:49:32 +00:00
87723a3354 Use batch writing mode in the help command 2009-10-31 22:05:35 +00:00
0cb52cca23 Do not include an 'announce-list' key in torrents when there is only one tracker 2009-10-31 19:49:14 +00:00
09ae4fbb72 Improve 'info' command draw speed 2009-10-31 18:52:52 +00:00
6e063e7c85 Don't bother clearing the screen during a refresh 2009-10-31 18:44:27 +00:00
41db357084 Fix crash when string length makes line longer than terminal width 2009-10-31 18:43:48 +00:00
3611584b0b Fix crash when removing multiple torrents 2009-10-31 05:50:01 +00:00
6e695d8410 Fix adding torrents when not showing the add torrent dialog in Windows 2009-10-31 00:08:53 +00:00
60fdcb3bd8 Fix #1052 crash when issuing commands while not connected to a daemon 2009-10-30 20:06:07 +00:00
d110b23a9f Fix improper dos line endings 2009-10-30 19:08:23 +00:00
2457fd0aea Fix displaying non-ascii strings in the console ui -- patch from Ian Martin 2009-10-30 18:00:13 +00:00
92afb8ab80 Fix torrent name being blank when root folder is renamed to /
Update changelog (for previous commit as well)
2009-10-30 00:15:22 +00:00
eba82457bd Make sure renamed files are utf-8 encoded. 2009-10-30 00:02:25 +00:00
099415776d Consider 0 unlimited when displaying limits in the statusbar 2009-10-28 17:43:29 +00:00
145f402aa2 fix #990, showing 0 as a limit when it means unlimited in the statusbar 2009-10-28 17:38:35 +00:00
d44efe8a66 use tag_build in setup.cfg and change version to rc3 in setup.py 2009-10-28 15:55:19 +00:00
1a9f715353 need to actually continue from the loop otherwise another error still occurs 2009-10-28 13:33:27 +00:00
2308961a04 create a method to escape all possible forms of newlines in a translation as well as the quotes 2009-10-28 13:24:37 +00:00
0cdd779396 remove new lines from any translations and replace them with \n characters so javascript can interupt it 2009-10-27 22:32:31 +00:00
db54dada9d fix displaying the protocol speed in the webui
also update the update_ui method in json_api so it gets the status more like how the gtkui does
2009-10-27 11:39:53 +00:00
7c5582a21e fix the eta sort order in the webui 2009-10-27 11:16:55 +00:00
7055a96930 update the ChangeLog so andar doesn't beat me up
fix displaying tracker urls with & in the url in the gtkui
2009-10-27 11:07:30 +00:00
e7a45f6dd1 add < and > escaping to the html escape method 2009-10-27 10:57:47 +00:00
ea4dcfbb5e fix actually escaping (foolish me had left it commented out) and also only update if there has been a change 2009-10-27 10:34:07 +00:00
5c506121a4 create a simple html escape method and escape the fields in the details tab 2009-10-27 10:26:59 +00:00
cc7aaa1ae0 fix a couple of bugs in the M.O.M and fix the options tab and file priorities in the torrent add window (success!) 2009-10-27 10:25:16 +00:00
cca2a4ab60 fixes #1046, changing the option name in the ui rather than the core which would break the other uis 2009-10-27 09:12:22 +00:00
197027510e Fix #1047 move completed does not work if saving to non default path 2009-10-27 03:08:47 +00:00
b12b5a8403 Fix typo in changelog. 2009-10-26 03:10:29 +00:00
0b5a0ac9a0 Update translations 2009-10-26 01:54:19 +00:00
65e50d1992 Prep 1.2_rc2 release 2009-10-25 23:32:13 +00:00
ecd75ba424 modify the M.O.M so the API is practically the same as the O.M, so the only method that accepts an id is changeId 2009-10-25 17:48:28 +00:00
694051e876 Fix typo, update plugin info. 2009-10-25 13:42:11 +00:00
350c523e7d Fix exception when using the 'halt' command 2009-10-24 19:49:20 +00:00
dbece6a6f6 Fix create_plugin.py script 2009-10-24 05:51:26 +00:00
5c26a4b1cf Fix #215 ETA sort order 2009-10-24 04:56:10 +00:00
475a880dd9 Fix previous commit [5864] 2009-10-24 03:47:35 +00:00
b0702e6a6d Fix #799 translate connection status 2009-10-24 02:04:19 +00:00
e506147289 Fix starting plugins when the pluginmanager is started 2009-10-23 23:23:38 +00:00
3c4144e01a Remove '-dev' tag 2009-10-23 22:08:14 +00:00
d4f2c2eda8 Fix possible exception when trying to load pre-1.2 plugins 2009-10-23 01:15:30 +00:00
4a996a1b41 Fix 'autostart localhost if needed' option 2009-10-23 01:07:46 +00:00
e39d1ab679 fix removing torrents that fail to download when added via url 2009-10-21 20:30:07 +00:00
c49ab0c6b1 fix switching the options when a different torrent is selected
fix showing the private flag
2009-10-21 20:15:16 +00:00
9c412e8aff fixes to the M.O.M and the options details tab, still not 100% though 2009-10-21 19:48:44 +00:00
83f42f5bf8 show the infinity symbol if ratio is less than 0 2009-10-20 22:45:32 +00:00
039a41def3 just a slight tweak adding some trac wiki formatting 2009-10-20 22:35:02 +00:00
b94060c60d fix setting bandwidth limits via the statusbar 2009-10-20 22:33:18 +00:00
33301b3433 fix setting the add options in the mom 2009-10-20 21:53:54 +00:00
b9ae412d06 add support for returning all options for an id in the get() method 2009-10-20 21:32:32 +00:00
f55bc6c9d8 Add option to create torrent name sub-folders in extract folder
Fix issue where the plugin would not stop extracting files after being disabled
2009-10-19 02:10:43 +00:00
511bfd5d84 use os._exit() rather than exit() when forking 2009-10-14 15:53:31 +00:00
89f88f3beb big bunch of fixes to the M.O.M along with a couple to the O.M 2009-10-13 16:21:28 +00:00
b1b09fbe89 move the parameter type converting into a seperate method 2009-10-13 15:22:24 +00:00
07b50730a2 improve the forking code 2009-10-13 15:20:45 +00:00
5607e0f6fa change all the 2 space gaps to tabs so vim hightlighting doesn't look irritating 2009-10-13 12:01:20 +00:00
9ab638377b add the option to fork the webui 2009-10-13 11:32:40 +00:00
4b79ae8280 fix a bug in the connection manager where the host list wasn't refreshed after a host was added 2009-10-13 09:56:49 +00:00
f1a1fdb630 update the changelog 2009-10-12 16:46:14 +00:00
d1f52a7051 allow setting of the value without firing an event 2009-10-12 16:45:28 +00:00
000297dc95 give names to both the radio buttons so they end up in a group (duh) 2009-10-12 16:44:30 +00:00
81eeb6edf7 fix a bug in converting non-boolean values back to boolean in the options manager 2009-10-12 09:53:13 +00:00
7d67da4371 Fix saving torrent state on fresh configs
Do not try to call doIteration() on the reactor if it has already stopped
2009-10-11 18:46:35 +00:00
ef5739a6a8 change the value of torrent.queue from -1 to 99999 so the grid sorting works the same as the gtk ui 2009-10-10 14:06:08 +00:00
4f968b9887 add a man page for deluge-web 2009-10-10 13:45:31 +00:00
22447993fa Add man pages for deluge-console and deluge-gtk
Update the other man pages
2009-10-09 16:26:10 +00:00
58be1f08fc Fix localclient authentication by stripping the lines read from the auth file 2009-10-09 00:39:57 +00:00
41d26bbbce Fix path errors when adding torrents externally in Windows 2009-10-09 00:19:07 +00:00
f1383f9655 Update ChangeLog 2009-10-08 02:59:24 +00:00
644f0ecb38 Modify setup.py to allow building without libtorrent/ 2009-10-08 02:51:49 +00:00
42a57b1f41 Fix quitting in Windows 2009-10-08 02:42:22 +00:00
8f50687034 Make sure libtorrent.pyd is included in bbfreeze 2009-10-08 02:42:00 +00:00
9f661caee8 Update win32 folder 2009-10-08 02:18:48 +00:00
044306cb3d Update gettextize.sh script to use proper encoding
Regenerate deluge.pot
2009-10-05 00:00:37 +00:00
ebd0290e44 Add script to regenerate the POTFILES.in file
Update the POTFILES.in file
2009-10-04 23:48:18 +00:00
4f1713734f Remove feeder, example and stats plugin from 1.2 2009-10-04 23:24:45 +00:00
f86e319d49 Update setup.py 2009-10-04 23:19:34 +00:00
95bb8fb4c3 Branch 1.2 2009-10-04 23:13:40 +00:00
217 changed files with 136313 additions and 129343 deletions

430
ChangeLog
View File

@ -1,98 +1,376 @@
=== Deluge 1.2.0 (In Development) ===
==== 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
=== 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 ====
* 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
* 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
==== ConsoleUI ====
* Changed to use curses for a more interactive client
==== Console ====
* Fix using the console in Windows, but only in command-line mode
* Fix #823 setting config values to -1.0
==== WebUI ====
* Move over to using Twisted-Web for the webserver.
* Move to only AJAX interface built upon Ext-JS.
==== Label ====
* Fix #1085 only use ints for specific options to prevent unhandled exception
==== Plugins ====
* Add Scheduler plugin
* Add Extractor plugin
==== 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 &amp; 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".

View File

@ -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.5
=== UIs ===
* chardet

23
create_potfiles_in.py Normal file
View 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
View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
View File

@ -1 +0,0 @@
5

21
debian/control vendored
View File

@ -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/

View File

@ -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/

View File

@ -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
View File

@ -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
View File

@ -1,2 +0,0 @@
docs/man/deluge.1
docs/man/deluged.1

3
debian/menu vendored
View File

@ -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"

View File

1
debian/pyversions vendored
View File

@ -1 +0,0 @@
2.5

View File

@ -1 +0,0 @@
2.5

View File

@ -1 +0,0 @@
2.5

75
debian/rules vendored
View File

@ -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

View File

@ -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:

View File

@ -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:

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -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
@ -491,7 +488,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 +556,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 +604,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:
return self.torrent_info.name()
try:
return name.decode("utf8", "ignore")
except UnicodeDecodeError:
@ -639,6 +637,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,
@ -762,9 +761,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 +816,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 +834,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)

View File

@ -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 = {}
@ -206,14 +210,17 @@ class TorrentManager(component.Component):
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:
@ -247,6 +254,10 @@ 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 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 = {}
@ -780,15 +790,14 @@ class TorrentManager(component.Component):
if torrent.options["move_completed"] and total_download:
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")

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 906 B

View File

@ -17,9 +17,9 @@
#
# You should have received a copy of the GNU General Public License
# along with deluge. If not, write to:
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
#
# In addition, as a special exception, the copyright holders give
# permission to link the code of portions of this program with the OpenSSL
@ -41,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__

View File

@ -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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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",

View File

@ -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)

View File

@ -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)

View File

@ -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:

View File

@ -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(".")])

View File

@ -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()
@ -169,7 +174,7 @@ class Core(CorePluginBase):
status["file_progress"] = self.file_progress
status["file_url"] = self.config["url"]
status["file_size"] = self.config["list_size"]
status["file_date"] = self.config["last_update"]
status["file_date"] = datetime.fromtimestamp(self.config["last_update"]).strftime("%a, %d %b %Y %H:%M:%S") if self.config["last_update"] else ""
status["file_type"] = self.config["list_type"]
if self.config["list_compression"]:
status["file_type"] += " (%s)" % self.config["list_compression"]
@ -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,7 +244,7 @@ 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)
@ -291,7 +296,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)
@ -327,7 +332,7 @@ class Core(CorePluginBase):
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)
log.warning("Error reading blocklist: %s", e)
self.use_cache = True
try_again = True
@ -347,7 +352,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

View File

@ -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

View File

@ -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
@ -90,6 +70,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:
@ -115,7 +98,7 @@ 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"""

View File

@ -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"

View File

@ -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)

View File

@ -1,40 +0,0 @@
#
# common.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 pkg_resources
import os.path
def get_resource(filename):
return pkg_resources.resource_filename("example", os.path.join("data", filename))

View File

@ -1,55 +0,0 @@
#
# core.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.log import LOG as log
from deluge.plugins.pluginbase import CorePluginBase
import deluge.component as component
import deluge.configmanager
from deluge.core.rpcserver import export
class Core(CorePluginBase):
def enable(self):
log.debug("Example core plugin enabled!")
def disable(self):
log.debug("Example core plugin disabled!")
def update(self):
pass
### Exported RPC methods ###
@export()
def example_method(self):
pass

View File

@ -1,51 +0,0 @@
/*
Script: example.js
The client-side javascript code for the Example plugin.
Copyright:
(C) Damien Churchill 2009 <damoxc@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, write to:
The Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor
Boston, MA 02110-1301, USA.
In addition, as a special exception, the copyright holders give
permission to link 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.
*/
ExamplePlugin = Ext.extend(Deluge.Plugin, {
constructor: function(config) {
config = Ext.apply({
name: "Example"
}, config);
ExamplePlugin.superclass.constructor.call(this, config);
},
onDisable: function() {
Deluge.Preferences.removePage(this.prefsPage);
},
onEnable: function() {
this.prefsPage = new ExamplePreferencesPanel();
this.prefsPage = Deluge.Preferences.addPage(this.prefsPage);
}
});
new ExamplePlugin();

View File

@ -1,48 +0,0 @@
#
# gtkui.py
#
# Copyright (C) 2008 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 gtk
from deluge.log import LOG as log
from deluge.ui.client import client
from deluge.plugins.pluginbase import GtkPluginBase
import deluge.component as component
import deluge.common
class GtkUI(GtkPluginBase):
def enable(self):
pass
def disable(self):
pass

View File

@ -1,54 +0,0 @@
#
# webui.py
#
# Copyright (C) 2009 Martijn Voncken <mvoncken@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.log import LOG as log
from deluge.ui.client import client
from deluge import component
from deluge.plugins.pluginbase import WebPluginBase
from common import get_resource
class WebUI(WebPluginBase):
scripts = [get_resource("example.js")]
# The enable and disable methods are not scrictly required on the WebUI
# plugins. They are only here if you need to register images/stylesheets
# with the webserver.
def enable(self):
log.debug("Example Web plugin enabled!")
def disable(self):
log.debug("Example Web plugin disabled!")

View File

@ -1,67 +0,0 @@
#
# setup.py
#
# Copyright (C) 2008 Andrew Resch <andrewresch@gmail.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, write to:
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
#
# In addition, as a special exception, the copyright holders give
# permission to link 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 setuptools import setup
__plugin_name__ = "Example"
__author__ = "Andrew Resch"
__author_email__ = "andrewresch@gmail.com"
__version__ = "1.2"
__url__ = "http://deluge-torrent.org"
__license__ = "GPLv3"
__description__ = "Example plugin"
__long_description__ = __description__
__pkg_data__ = {__plugin_name__.lower(): []}
setup(
name=__plugin_name__,
version=__version__,
description=__description__,
author=__author__,
author_email=__author_email__,
url=__url__,
license=__license__,
long_description=__long_description__,
packages=[__plugin_name__.lower()],
package_data = __pkg_data__,
entry_points="""
[deluge.plugin.core]
%s = %s:CorePlugin
[deluge.plugin.gtkui]
%s = %s:GtkUIPlugin
[deluge.plugin.webui]
%s = %s:WebUIPlugin
""" % ((__plugin_name__, __plugin_name__.lower())*3)
)

View File

@ -78,9 +78,14 @@ class Core(CorePluginBase):
def execute_commands(self, torrent_id, event):
torrent = component.get("TorrentManager").torrents[torrent_id]
info = torrent.get_status(["name", "save_path"])
info = torrent.get_status(["name", "save_path",
"move_on_completed_path"])
torrent_name = info["name"]
path = info["save_path"]
path = info["save_path"] if \
info["move_on_completed_path"] == info["save_path"] else \
info["move_on_completed_path"]
for command in self.config["commands"]:
if command[EXECUTE_EVENT] == event:
command = os.path.expandvars(command[EXECUTE_COMMAND])

View File

@ -80,7 +80,7 @@
<property name="layout_style">end</property>
<child>
<widget class="GtkButton" id="button_add">
<property name="label" translatable="yes">gtk-add</property>
<property name="label" translatable="no">gtk-add</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>

View File

@ -48,7 +48,8 @@ import deluge.configmanager
from deluge.core.rpcserver import export
DEFAULT_PREFS = {
"extract_path": ""
"extract_path": "",
"use_name_folder": True
}
# The first format is the source file, the second is the dest path
@ -69,7 +70,7 @@ class Core(CorePluginBase):
component.get("EventManager").register_event_handler("TorrentFinishedEvent", self._on_torrent_finished)
def disable(self):
pass
component.get("EventManager").deregister_event_handler("TorrentFinishedEvent", self._on_torrent_finished)
def update(self):
pass
@ -97,11 +98,22 @@ class Core(CorePluginBase):
# Now that we have the cmd, lets run it to extract the files
fp = os.path.join(save_path, f["path"])
if os.path.exists(self.config["extract_path"]):
dest = self.config["extract_path"]
else:
dest = None
# Get the destination path
dest = self.config["extract_path"]
if self.config["use_name_folder"]:
name = component.get("TorrentManager")[torrent_id].get_status(["name"])["name"]
dest = os.path.join(dest, name)
# Create the destination folder if it doesn't exist
if not os.path.exists(dest):
try:
os.makedirs(dest)
except Exception, e:
log.error("Error creating destination folder: %s", e)
return
log.debug("Extracting to %s", dest)
def on_extract_success(result, torrent_id):
# XXX: Emit an event
log.debug("Extract was successful for %s", torrent_id)
@ -115,14 +127,14 @@ class Core(CorePluginBase):
d.addCallback(on_extract_success, torrent_id)
d.addErrback(on_extract_failed, torrent_id)
@export()
@export
def set_config(self, config):
"sets the config dictionary"
for key in config.keys():
self.config[key] = config[key]
self.config.save()
@export()
@export
def get_config(self):
"returns the config dictionary"
return self.config.config

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
<!--Generated with glade3 3.4.5 on Wed May 6 12:45:11 2009 -->
<?xml version="1.0"?>
<glade-interface>
<!-- interface-requires gtk+ 2.6 -->
<!-- interface-naming-policy toplevel-contextual -->
<widget class="GtkWindow" id="window1">
<child>
<widget class="GtkVBox" id="extractor_prefs_box">
@ -11,7 +11,7 @@
<widget class="GtkFrame" id="frame1">
<property name="visible">True</property>
<property name="label_xalign">0</property>
<property name="shadow_type">GTK_SHADOW_NONE</property>
<property name="shadow_type">none</property>
<child>
<widget class="GtkVBox" id="vbox1">
<property name="visible">True</property>
@ -29,6 +29,7 @@
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
@ -36,9 +37,12 @@
<property name="visible">True</property>
<child>
<widget class="GtkFileChooserButton" id="folderchooser_path">
<property name="action">GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER</property>
<property name="action">select-folder</property>
<property name="title" translatable="yes">Select A Folder</property>
</widget>
<packing>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkEntry" id="entry_path">
@ -57,6 +61,22 @@
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkCheckButton" id="chk_use_name">
<property name="label" translatable="yes">Create torrent name sub-folder</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="tooltip" translatable="yes">This option will create a sub-folder using the torrent's name within the selected extract folder and put the extracted files there.</property>
<property name="draw_indicator">True</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</widget>
@ -72,6 +92,9 @@
</packing>
</child>
</widget>
<packing>
<property name="position">0</property>
</packing>
</child>
</widget>
</child>

View File

@ -70,7 +70,8 @@ class GtkUI(GtkPluginBase):
path = self.glade.get_widget("entry_path").get_text()
config = {
"extract_path": path
"extract_path": path,
"use_name_folder": self.glade.get_widget("chk_use_name").get_active()
}
client.extractor.set_config(config)
@ -88,5 +89,7 @@ class GtkUI(GtkPluginBase):
self.glade.get_widget("folderchooser_path").set_current_folder(config["extract_path"])
else:
self.glade.get_widget("entry_path").set_text(config["extract_path"])
self.glade.get_widget("chk_use_name").set_active(config["use_name_folder"])
client.extractor.get_config().addCallback(on_get_config)

View File

@ -1,55 +0,0 @@
#
# feeder/__init__.py
#
# Copyright (C) 2007-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)

View File

@ -1,432 +0,0 @@
#
# core.py
#
# Copyright (C) 2008-2009 Fredrik Eriksson <feeder@winterbird.org>
# Copyright (C) 2009 David Mohr <david@mcbf.net>
#
# Basic plugin template created by:
# Copyright (C) 2008 Martijn Voncken <mvoncken@gmail.com>
# Copyright (C) 2007-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 feedparser # for parsing rss feeds
import threading # for threaded updates
import re # for regular expressions
from twisted.internet.task import LoopingCall
from deluge.log import LOG as log
from deluge.plugins.pluginbase import CorePluginBase
import deluge.component as component
import deluge.configmanager
from deluge.core.rpcserver import export
DEFAULT_PREFS = {
"feeds": {},
"filters": {},
"updatetime": 15,
"history": []
}
# Helper classes
class Feed:
"""
Class for the Feed object (containging feed configurations)
"""
def __init__(self):
self.url = ""
self.cookies = {}
self.updatetime = 15
def get_config(self):
try:
tmp = self.cookies
except Exception, e:
log.debug("Old feed without cookies... updating")
self.cookies = {}
return {'url': self.url, 'updatetime': self.updatetime, 'cookies': self.cookies}
def set_config(self, config):
self.url = config['url']
self.updatetime = config['updatetime']
self.cookies = config['cookies']
class Filter:
"""
Class for the Filter object (containing filter configurations)
"""
def __init__(self):
self.regex = ""
self.feeds = [] #TODO activate filter per feed
self.all_feeds = True
self.active = True
# by default, set the configuration to match
# the per-torrent settings in deluge
def_conf = component.get("Core").get_config()
self.max_download_speed = def_conf['max_download_speed_per_torrent']
self.max_upload_speed = def_conf['max_upload_speed_per_torrent']
self.max_connections = def_conf['max_connections_per_torrent']
self.max_upload_slots = def_conf['max_upload_slots_per_torrent']
self.prioritize_first_last_pieces = def_conf['prioritize_first_last_pieces']
self.auto_managed = def_conf['auto_managed']
self.download_location = def_conf['download_location']
self.stop_at_ratio = def_conf['stop_seed_at_ratio']
self.stop_ratio = def_conf['stop_seed_ratio']
self.remove_at_ratio = def_conf['remove_seed_at_ratio']
def get_config(self):
def_conf = component.get("Core").get_config()
try:
tmp = self.active
except Exception, e:
log.debug("Old filter detected (pre 0.3), updating...")
self.active = True
try:
tmp = self.stop_at_ratio
tmp = self.stop_ratio
tmp = self.remove_at_ratio
except:
log.debug("Old filter detected (pre 0.4), updating...")
self.stop_at_ratio = def_conf['stop_seed_at_ratio']
self.stop_ratio = def_conf['stop_seed_ratio']
self.remove_at_ratio = def_conf['remove_seed_at_ratio']
conf = {
'regex': self.regex,
'feeds': self.feeds,
'all_feeds': self.all_feeds,
'active' : self.active,
'max_download_speed': self.max_download_speed,
'max_upload_speed': self.max_upload_speed,
'max_connections': self.max_connections,
'max_upload_slots': self.max_upload_slots,
'prioritize_first_last_pieces': self.prioritize_first_last_pieces,
'auto_managed': self.auto_managed,
'download_location':self.download_location,
'remove_at_ratio':self.remove_at_ratio,
'stop_ratio': self.stop_ratio,
'stop_at_ratio': self.stop_at_ratio }
return conf
def set_config(self, conf):
self.regex = conf['regex']
self.feeds = conf['feeds']
self.all_feeds = conf['all_feeds']
self.active = conf['active']
self.max_download_speed = int(conf['max_download_speed'])
self.max_upload_speed = int(conf['max_upload_speed'])
self.max_connections = int(conf['max_connections'])
self.max_upload_slots = int(conf['max_upload_slots'])
self.prioritize_first_last_pieces = conf['prioritize_first_last_pieces']
self.auto_managed = conf['auto_managed']
self.download_location = conf['download_location']
self.remove_at_ratio = conf['remove_at_ratio']
self.stop_ratio = float(conf['stop_ratio'])
self.stop_at_ratio = conf['stop_at_ratio']
class Core(CorePluginBase):
def enable(self):
self.config = deluge.configmanager.ConfigManager("feeder.conf", DEFAULT_PREFS)
self.feeds = {}
self.timers = {}
self.history = self.config['history']
self.time = 0
# Setting default timer to configured update time
for feed in self.config['feeds']:
self.timers[feed] = LoopingCall(self.update_feed, feed)
self.timers[feed].start( self.config['feeds'][feed].updatetime * 60)
def disable(self):
self.config['history'] = self.history
self.config.save()
def update(self):
pass
#=================Exported functions==================
@export
def set_config(self, config):
"""sets the config dictionary"""
for key in config.keys():
self.config[key] = config[key]
self.config.save()
####################Configuration Getters##################
@export
def get_config(self):
"""returns the config dictionary"""
return self.config.config
@export
def get_feed_config(self, feedname):
"""Returns configuration for a feed"""
return self.config['feeds'][feedname].get_config()
@export
def get_filter_config(self, filtername):
"""Returns a configuration for a filter"""
return self.config['filters'][filtername].get_config()
####################Information Getters####################
@export
def get_feeds(self):
"""Returns a list of the configured feeds"""
feeds = []
for feedname in self.config['feeds']:
feeds.append(feedname)
feeds.sort(key=string.lower)
return feeds
@export
def get_filters(self):
"""Returns a list of all available filters"""
filters = []
for filter in self.config['filters']:
filters.append(filter)
filters.sort(key=string.lower)
return filters
@export
def get_items(self, feedname):
"""Returns a dictionary with feedname:link"""
try:
items = {}
feed = self.feeds[feedname]
for entry in feed['entries']:
items[entry.title] = entry.link
except Exception, e:
items = {}
log.warning("Feed '%s' not loaded", feedname)
return items
@export
def test_filter(self, regex):
filters = { "to_test":Filter() }
conf = filters["to_test"].get_config()
conf["regex"] = regex
filters["to_test"].set_config(conf)
hits = {}
for feed in self.feeds:
hits.update(self.run_filters(feed, filters, test=True))
return hits
@export
def add_feed(self, config):
"""adds/updates a feed and, for whatever reason, sets the default timeout"""
# save the feedname and remove it from the config
feedname = config['name']
del config['name']
# check if the feed already exists and save config
try:
conf = self.config['feeds'][feedname].get_config()
del self.config['feeds'][feedname]
except Exception, e:
conf = {}
# update configuration
for var in config:
conf[var] = config[var]
# save as default update time
try:
self.config['updatetime'] = config['updatetime']
except Exception, e:
log.warning("updatetime not set when adding feed %s", feedname)
# Create the new feed
newfeed = Feed()
newfeed.set_config(conf)
# Add a timer (with default timer for now, since we can't get ttl just yet)...
self.timers[feedname] = LoopingCall(self.update_feed, feedname)
# Save the new feed
self.config['feeds'].update({feedname: newfeed })
self.config.save()
# Start the timeout, which will also update the new feed
self.timers[feedname].start(newfeed.updatetime * 60)
@export
def remove_feed(self, feedname):
"""Remove a feed"""
if self.feeds.has_key(feedname): # Check if we have the feed saved and remove it
del self.feeds[feedname]
if self.timers.has_key(feedname): # Check if we have a timer for this feed and remove it
self.timers[feedname].stop()
del self.timers[feedname]
if self.config['feeds'].has_key(feedname): # Check if we have the feed in the configuration and remove it
del self.config['feeds'][feedname]
self.config.save()
@export
def add_filter(self, name):
"""Adds a new filter to the configuration"""
if not self.config['filters'].has_key(name): # we don't want to add a filter that already exists
self.config['filters'][name] = Filter()
self.config.save()
@export
def set_filter_config(self, filtername, conf):
"""Changes the options for a filter"""
oldconf = self.config['filters'][filtername].get_config()
for item in conf:
oldconf[item] = conf[item]
self.config['filters'][filtername].set_config(oldconf)
self.config.save()
for feed in self.config['feeds']: # we would like to check if the filter now matches something new
self.run_filters(feed)
@export
def remove_filter(self, name):
"""Removes a filter"""
if self.config['filters'].has_key(name): # Can't remove a filter that doesn't exists
del self.config['filters'][name]
self.config.save()
#=================Internal functions================
def update_feed(self, feedname):
"""Start a thread to update a single feed"""
threading.Thread(
target=self.update_feed_thread,
args=(self.on_feed_updated, feedname)).start()
# Need to return true to not destoy timer...
return True
def update_feed_thread(self, callback, feedname):
"""updates a feed"""
feed = self.config['feeds'][feedname]
try:
self.feeds[feedname] = feedparser.parse(feed.url)
except Exception, e:
log.warning("Error parsing feed %s: %s", feedname, e)
else:
callback(feedname)
def on_feed_updated(self, feedname):
"""Run stuff when a feed has been updated"""
# Not all feeds contain a ttl value, but if it does
# we would like to obey it
try:
if not self.feeds[feedname].ttl == self.config['feeds'][feedname].updatetime:
log.debug("feed '%s' request a ttl of %s, updating timer", feedname, self.feeds[feedname].ttl)
self.config['feeds'][feedname].updatetime = self.feeds[feedname].ttl
self.timers[feedname].stop()
self.timers[feedname].start(self.config['feeds'][feedname].updatetime * 60)
except Exception, e:
log.debug("feed '%s' has no ttl set, will use default timer", feedname)
# Run filters on the feed
self.run_filters(feedname)
def run_filters(self, feedname, filters={}, test=False):
"""Test all available filters on the given feed"""
if not filters:
filters = self.config['filters']
log.debug("will test filters %s", filters)
hits = {}
# Test every entry...
for entry in self.feeds[feedname]['entries']:
# ...and every filter
for filter in filters:
# We need to be able to run feeds saved before implementation of actiave/deactivate filter (pre 0.3) TODO
try:
if not filters[filter].active:
continue
except:
log.debug("old filter, will assume filter is activated")
if filters[filter].regex == "": # we don't want a empty regex...
log.warning("Filter '%s' has not been configured, ignoring!", filter)
continue
# if the filter isn't supposed to be run on this feed we don't want to run it...
# if filter.all_feeds or self.config['filters'][filter].feeds.has_element(feedname) : # ...apparently has_element doesn't work on arrays... TODO
if self.test_filter(entry, filters[filter].regex):
if test:
hits[entry.title] = entry.link
else:
opts = filters[filter].get_config()
#remove filter options that should not be passed on to the torrent.
del opts['regex']
del opts['feeds']
del opts['all_feeds']
# history patch from Darrell Enns, slightly modified :)
# check history to prevent multiple adds of the same torrent
log.debug("testing %s", entry.link)
if not entry.link in self.history:
self.add_torrent(entry.link, opts, self.feeds[feedname].cookies)
self.history.append(entry.link)
#limit history to 50 entries
if len(self.history)>50:
self.history=self.history[-50:]
log.debug("wrapping history")
else:
log.debug("'%s' is in history, will not download", entry.link)
return hits
def test_filter(self, entry, filter):
"""Tests a filter to a given rss entry"""
f = re.compile(filter, re.IGNORECASE)
if f.search(entry.title) or f.search(entry.link):
log.debug("RSS item '%s' matches filter '%s'", entry.title, filter)
return True
else:
return False
def add_torrent(self, url, torrent_options, headers):
log.debug("Attempting to add torrent %s", url)
component.get("Core").add_torrent_url(url, torrent_options, headers)

View File

@ -1,13 +0,0 @@
$def with (entries, feedname)
$:render.header("things", '')
<div class="panel" >
<div>
<h3>Feed items for feed $feedname</h3>
<ul>
$entries
</ul>
</div>
<a href="/config/feeder">back to config</a>
</div>
$:render.footer()

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